Detecting a text-selection event in GWT? (equilivent of this javascript) - events

I am trying to detect when text is selected in a GWT app.
On Pc's this is easy, but on touch devices its providing hard.
I found this bit of javascript that at least works in newer webkits/blink.
document.addEventListener("selectionchange", function() {
var selectedText = window.getSelection().toString();
document.getElementById("demo").innerHTML = "selectedText"+selectedText;
}, false);"
Doesn't help with Firefox, but I can live with that for the moment.
How would I replicate this javascript in gwt?
I tried;
mainBody.addHandler(new SelectionHandler() {
#Override
public void onSelection(SelectionEvent event) {
Log.info("change detected");
String selected = mainBody.getSelectedText();
Log.info("selected="+selected);
if (selected.length()>10){
Window.alert("selection="+selected);
}
}
}, SelectionEvent.getType());
(where MainBody is a textarea widget)
But doesn't seem to work. Do I need to use a native javascript snippet? (not sure how to do that with a handler, however)
Thanks,

Related

Firefox crashes on element.remove()

When tinyMCE is used with Firefox and the user drags an image into the editor,image.remove (); window FF converts the image to a base64 string and embeds the image as text--not optimal DB strategy. This question addresses the issue. I've added a simple handler to the editor that handles it simply:
if (tinymce.isGecko) {
editor.getDoc().addEventListener('DOMNodeInserted', function(event) {
var image = event.target;
if ((image.nodeName === 'IMG') && (image.src.substring(0, 30).match(/.*?data.*?;base64/g))) {
image.remove ();
alert('Using drag-and-drop for images with Firefox has been disabled for technical reasons. Please use the "Add Media" button.')
}
},
false);
}
But image.remove (); crashes Firefox every time. Can anyone verify this, and is there a workaround?

GWT Image Drag and Drop on IE9 not working

I'm using GWT 2.5 and I want to make some images in one Panel Draggable and Dropable in another Panel. This is working fine on Firefox, but on IE9 it just don't want to work.
I searched really almost all the day, and didn't find any solution for that. The best threads I found were these here:
Drag and Drop in GWT 2.4
GWT native drag & drop - DragStartEvent not firing on IE9
The difference is that I'm dragging Images, an not Labels. So this could be the problem.
So the code looks something like this:
// Draggable Image
final Image img = new Image(imageName);
img.addDragStartHandler(new DragStartHandler() {
#Override
public void onDragStart(final DragStartEvent event) {
event.setData("text", img.getUrl());
}
});
img.getElement().setDraggable(Element.DRAGGABLE_TRUE);
Then I put it in my "source" panel:
// Image in the source container
wunschContainer = new AbsolutePanel();
img.setPixelSize(size, size);
wunschContainer.add(img, left, top);
The Images are displayed correctly (Firefox and IE9)
The Target Panel looks like this (it's a subclass of AbsolutePanel and implements HasDragOverHandlers and HasDropHandlers)
// Event-handlers for the target container.
this.addDragOverHandler(new DragOverHandler() {
#Override
public void onDragOver(final DragOverEvent event) {
}
});
this.addDropHandler(new DropHandler() {
#Override
public void onDrop(final DropEvent event) {
event.preventDefault();
final String data = event.getData("text");
/* ... some more handling ..., creates an image to be displayed here */
add(image, left, top);
}
});
In Firefox, when I drag the image, the dragging image is displayed under the mouse pointer. On IE9 I can't see an image at all, just a symbol (circle with a slash on it, this "not allowed" symbol). And when I release the mouse button, then nothing happen. I checked also with "F12" that I was using the IE9-mode, and no compatibility mode.
I really don't know what the problem is. The code seems ok (works on FF). Is there a problem making DnD with GWT-Images? The interesting part is, that the "onDragStart()" methode is being fired. But the "drag" is not being done.
Oh, I'm using GWT devmode to test this. Can this be a problem?
I'd like to solve this using only GWT. Or should I go and use another library, like gwt-dnd? Does anybody got plain GWT DnD working on IE9? I can't believe I'm the first one trying that :-(.
So, I tried really a lot of things, and I came across with a solution.
The problem seems to be in the "onDragOver()" method. As I posted in my original question, I have an empty implementation of the method:
this.addDragOverHandler(new DragOverHandler() {
#Override
public void onDragOver(final DragOverEvent event) {
}
});
As this is how I found in many pages. The method must be present, or else the Drag n Drop wont work. But it seems that for IE I need even to prevent the default behaviour (or do something else. Just logging the method was not "something"). So I added a "event.preventDefault();" to the method, and now it works.
this.addDragOverHandler(new DragOverHandler() {
#Override
public void onDragOver(final DragOverEvent event) {
event.preventDefault();
}
});
Just strange, that I couldn't find this information anywhere. This is hopefully useful for somebody else 8-).
I have been having the same issue with IE9 using GWT 2.6 and I have found that setting the data in the onDragStart puts IE9 off. All other browsers work fine. So I ended up doing the following:
this.addDragStartHandler(new DragStartHandler(){
#Override
public void onDragStart(DragStartEvent event) {
if(!isIE9()){
event.setData(RangeSliderControl.KEY, key); // This causes IE9 to not work
}
}}
);
and off course I have added the isIE9() method to my code as follows:
/**
* Gets the name of the used browser.
*/
public static boolean isIE9() {
return (getBrowserName().indexOf("msie 9.0") != -1);
};
/**
* Gets the name of the used browser.
*/
public static native String getBrowserName() /*-{
return navigator.userAgent.toLowerCase();
}-*/;

Force context menu to appear for form inputs

I'm trying to develop a ff addon that allows a user to right-click on a form element and perform a task associated with it.
Unfortunately somebody decided that the context menu shouldn't appear for form inputs in ff and despite long discussions https://bugzilla.mozilla.org/show_bug.cgi?id=433168, they still don't appear for checkboxes, radios or selects.
I did find this: https://developer.mozilla.org/en-US/docs/Offering_a_context_menu_for_form_controls but I cannot think how to translate the code to work with the new add-on SDK.
I tried dumping the javascript shown into a content script and also via the observer-service but to no avail.
I also cannot find the source for the recommended extension https://addons.mozilla.org/en-US/firefox/addon/form-control-context-menu/ which considering it was 'created specifically to demonstrate how to do this' is pretty frustrating.
This seems like very basic addon functionality, any help or links to easier documentation would be greatly appreciated.
** UPDATE **
I have added the following code in a file, required from main, that seems to do the trick.
var {WindowTracker} = require("window-utils");
var tracker = WindowTracker({
onTrack: function(window){
if (window.location.href == "chrome://browser/content/browser.xul") {
// This is a browser window, replace
// window.nsContextMenu.prototype.setTarget function
window.setTargetOriginal = window.nsContextMenu.prototype.setTarget;
window.nsContextMenu.prototype.setTarget = function(aNode, aRangeParent, aRangeOffset) {
window.setTargetOriginal.apply(this, arguments);
this.shouldDisplay = true;
};
};
}
, onUntrack: function(window) {
if (window.location.href == "chrome://browser/content/browser.xul") {
// In case we were called because the extension is uninstalled - restore
// original window.nsContextMenu.prototype.setTarget function
window.nsContextMenu.prototype.setTarget = window.setTargetOriginal;
};
}
});
Unfortunately this still does not bring up a context menu for disabled inputs, but this is not a show-stopper for me.
Many Thanks
The important piece of code in this extension can be seen here. It is very simple - it replaces nsContextMenu.prototype.setTarget function in each browser window and makes sure that it sets shouldDisplay flag for form controls.
The only problem translating this to Add-on SDK is that the high-level modules don't give you direct access to browser windows. You have to use the deprecated window-utils module. Something like this should work:
var {WindowTracker} = require("sdk/deprecated/window-utils");
var tracker = WindowTracker({
onTrack: function(window)
{
if (window.location.href == "chrome://browser/content/browser.xul")
{
// This is a browser window, replace
// window.nsContextMenu.prototype.setTarget function
}
},
onUntrack: function(window)
{
if (window.location.href == "chrome://browser/content/browser.xul")
{
// In case we were called because the extension is uninstalled - restore
// original window.nsContextMenu.prototype.setTarget function
}
}
});
Note that WindowTracker is supposed to be replaced in some future SDK version. Also, for reference: nsContextMenu implementation

Track Youtube player's states in YUI.add

My embed code to play Youtube video is:
<object height="356" width="425" type="application/x-shockwave-flash" id="myytplayer" data="http://www.youtube.com/v/MTf6qXn5Prw?enablejsapi=1&playerapiid=ytplayer&version=3"><param name="allowScriptAccess" value="always"></object>
I want to track Youtube player's events (play/pause/stop etc)
The following piece of code works independently
window.onYouTubePlayerReady = function(playerId){
ytplayer = document.getElementById("myytplayer");
ytplayer.addEventListener("onStateChange", "onytplayerStateChange");
}
window.onytplayerStateChange = function (newState) {
alert("Player's new state: " + newState);
}
I am using YUI.
When I put the same in
YUI.add('module-name', function(Y) {
[some other code...]
window.onYouTubePlayerReady = function(playerId){
// console.log(playerId); console.log(ytplayer);
ytplayer = document.getElementById("myytplayer");
ytplayer.addEventListener("onStateChange", "onytplayerStateChange");
}
window.onytplayerStateChange = function (newState) {
alert("Player's new state: " + newState);
}
},'3.4.0', {requires:'module-a', 'module-b'})
Function onytplayerStateChange works in Firefox and Safari but not in other browsers.
Then I tried YUI functions to make that working in all browsers so I did some changes
window.onYouTubePlayerReady = function(playerId){
var shinyPlayer = Y.one("#myytplayer");
shinyPlayer.on('onStateChange', function (e) {
e.preventDefault();
alert('here');
});
}
but it didn't work for me.
I don't want to place window.onytplayerStateChange outside of YUI.add('module-name', function(Y) {})
Please suggest what should I do to track Youtube player's states in all browsers.
Thanks in advance.
I made a jsFiddle to test this:
http://jsfiddle.net/2Mj6b/4/
For me it feels like addEventListener is a custom implementation of Google.
Normally the second parameter is a callback/function-pointer and no string.
If you attach a variable to the window object it gets global and is from every scope visible. So it's no problem if you define it in the YUI module.
The second problem is that you cant use the player as YUI object you have to stay on dom objects to get this work.
Oh this is a old question. Damn. But i will post this anyway. ;)

Webkit (Chrome or Safari) way doing AJAX safely on onunload / onbeforeunload

In my tests Chrome (and I guess as any other webkit browser probably) is UNABLE to perform an AJAX request BEFORE leaving a page.
Imagine for instance, that you need to clean up something on the server because the user clicked on some link or left the page.
First thing I noticed is that window.onunload DOES NOT work anyhow on Chrome (Webkit?)
Once you are using window.onbeforeunload MAKE SURE you DON'T put in the the body like this: Cause it is ignored. YOU HAVE TO do window.onbeforeunload=function() {...} to make sure the binding is done (or use jquery or protoype libs for this)
WITHIN your onbeforeunload code a ASYNCHRONOUS Ajax like this WON'T work either:
var req = new XMLHttpRequest();
req.open("GET", "dosomething.page");
req.send(null);
(although this will WORK in Firefox)
It will work if ONLY if the request is made SYNCHRONOUS like this:
var req = new XMLHttpRequest();
req.open("GET", "dosomething.page",false);
req.send(null);
Although keep in mind that synchronous can cause the browser to hang for 2minutes if the server does NOT reply.
Also Firefox DOES NOT seem to work with onunload.
So in the end YOU have to provide with a different code path for each browser or browser family.
I haven't been able to test IE properly on this.
Does anyone know?
Is IE more like Chrome or FF in this?
or is it different to both as well?
IE seems to work just like Firefox (Gecko) in this particular case:
With this code you can make it work for WebKit, Firefox and IE:
// Browser detection
var Browser={
IE: !!(window.attachEvent && !window.opera),
Opera: !!window.opera,
WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
};
// Ensures the Ajax Get is performed... Asynchronously if possible
// or Synchronously in WebKit Browsers (otherwise it'll most probably fail)
function ensureAJAXGet(url, args) {
var async=!Browser.WebKit;
var finalUrl=url;
var sep="";
for (var key in args) {
sep=(sep=="?")?"&":"?";
finalUrl=finalUrl+sep+encodeURIComponent(key)+"="+encodeURIComponent(args[key]);
}
var req = new XMLHttpRequest();
req.open("GET", finalUrl,async);
req.send();
return req;
}
// Sets up an unload function for all browsers to work (onunload or onbeforeunload)
function onUnload(func) {
if(Browser.WebKit) {
window.onbeforeunload=func;
} else {
window.onunload=func;
}
}
A test html could be this:
var browser="?"
if (Browser.IE) {
browser="IE";
} else if (Browser.Opera) {
browser="Opera";
} else if (Browser.WebKit) {
browser="WebKit";
} else if (Browser.Gecko) {
browser="Gecko";
} else if (Browser.MobileSafari) {
browser="MobileSafari";
}
function unload() {
ensureAJAXGet("testajax.jsp", {"browser": browser});
}
onUnload(function() { unload(); });
That is:
To do something onunload you call onUnload() instead of directly using either window.onload or window.onunload. This ensures that the proper event is used (onbeforeunload in WebKit and onunload on the rest)
To sent some GET Ajax on an unload function use ensureAjaxGet() that will be asynchronous AJAX when possible and synchronous when needed (WebKit)

Resources