Cross-browser JavaScript input live change/paste detection - javascript

Is there a cross-browser way to detect live changes to an input field?
By live, I mean not when the field loses focus, and not on the next keypress, and so on. Immediately or something like it.
Using combinations of jQuery and .change(), .keyup(), .bind('paste') and so on I can get working live change detection in some browsers, but not all. Using different combinations will make it work somewhat in other browsers.
The trickiest thing to get working is mouse manipulation of the input field - selecting text and moving it (which is essentially cut and paste), right-clicking and pasting or cutting, etc. For some reason even .mousedown() and .mouseup() don't seem to cut it.
The only cross-browser solution I can think of right now is to check the input field value every 100-or-so milliseconds and compare the value against a stored value. But this seems like overkill when the event-based solution comes so close.
Is there a jQuery plug-in that does this already? Or is there some other way to achieve this?

To complete your change and key handlers, you can add handlers for cut/copy/paste. They work in Firefox >=3, IE, Safari and Chrome (but not in Opera/Konqueror).
Would that cover everything for your use case?

Depending on the Browsers you need to support you might use HTML5's oninput.
It fires immediately when the monitored input changes. In jQuery you would just do:
$('#my-input').bind('input', function(e) {
console.log("#my-input's value changed");
});

Related

DOM Changed Event Firefox Extension

So I have created a Firefox extension and it works great, however when I submitted it (although it was accepted) it came up with one security warning. It said setTimeout() was removed in an else clause.
So, is there a way to listen for any DOM change? (or even a specific element changing, I have an ID for both). However, divs do not have an onChange event so any ideas?
I don't mind if it's ANY change, doesn't have to be div-specific.
DOMSubtreeModified event sound like something you want to use. Keep in mind, that it is deprecated and after some time its support will probably be removed from browsers.
http://help.dottoro.com/ljrmcldi.php
It turns out adding an "onChange" event to a div works fine, although it might not be W3C valid it doesn't really matter as it's only a Firefox extension (plus it works!).

Partially select checkbox with javascript

Is there a way using Javascript and HTML(5) to make a checkbox be partially selected, like the checkboxes in a program installation menu when you select only some of the sub options?
HTML5 defines the indeterminate boolean property.
I've tested it only in the latest Safari, Chrome, and Firefox. They all support the indeterminate state.
Example: http://jsfiddle.net/5tpXc/
Edit: Note that this wont work with older browsers and maybe not with current versions of IE. You'd need to rely on hacks as described in other answers here if you want to support all browsers.
HTML checkboxes (that is, input elements of type checkbox) don't have a third state (partially checked). So no, there is no direct way to do this.
What you'd probably have to do is make a custom checkbox-looking image and bind to its various events (click, for example) to store its current "state" in a hidden form field via JavaScript. You may run into a number of issues with this approach, though.
For example, keyboard navigation of the form may not be possible for this particular element. (Can one tab to an image and send it keyboard events? I'm not sure.)
Additionally, you could try manipulating custom attributes on a checkbox element via JavaScript to store a third state. But the rendering of the element itself has no visual indicator of something like that. You could probably manipulate its style (color, background color, border color, etc.) to try to mimic the visual behavior. But you may not be able to achieve the exact visual style that you're using for reference.
It's certainly an interesting prospect, and I'm intrigued enough that I may try to implement something like this in the near future. But with a native checkbox element, it's not possible. It has only two states.
Edit: Refer to #kassens' answer for doing this in HTML5. If you're limited to previous versions of HTML for any reason, then it's going to have to be a hack as described here. But if you can rely on users supporting HTML5, then it looks like native support is there.
Nope. You would have to make a custom checkbox graphic and fake it.
Edit: Refer to #Kassen's answer for a way to have partially checked boxes in HTML5-compliant browsers.

JavaScript event for contenteditable elements

Is there a way to capture JavaScript events for when a contenteditable element begins and ends editing?
I'm not sure exactly here, but aren't you after focus and blur? I'm not sure what else "begins and ends editing" could be translated to that has a different timing than those, unless you mean an event for every keystroke, etc.
As Nick said, focus and blur will work, and in all major browsers. IE also has a number of related events (although none of these are implemented in other browsers as far as I know): activate, deactivate, beforeactivate, beforedeactivate and beforeeditfocus

Javascript context menu click event/detection - filter paste content

Scenario: I'm trying to intercept paste events inside a textarea/input text, and filter the content being pasted.
Webkit/IE are handled rather well, as I can attach code to the onpaste event, and then read from the clipboard what is being pasted. Plenty of examples around.
Gecko is trickier, because as far as I know it isn't possible to read the clipboard content on Firefox (unless somebody knows a workaround for that?)
I just use the input swap trick for that.
Opera is being annoying tho. I can trap CTRL+V and SHIFT+INS, but there's no onpaste event.
Not to mention any sort of clipboard interaction, apparently.
So, my question is:
Can I detect if the user clicked on paste in the context menu on Opera? Is there any other way to detect the event?
EDIT:
Thanks everybody for the answers - they all add a good input, even if there's no definitive solution.
Having to choose, I'll pick the only one that tried to address the original question, and that would probably work if it wasn't too much of an hack to even try.
Notes for those that have my same problem (input filtering):
it is possible to capture content being dragged: mouseup + setTimeout does the trick everywhere almost perfectly.
without flash, there is probably no solution bar polling. Even with flash, it's not a completely solid solution either. Too much effort to support 100% of the cases.
I ran into this last year. In short, no.
I ended up using an onchange handler and filtering the content after it's already been pasted into the text box.
You can intercept the paste with jQuery using the bind('paste', function() {});, compare string before and after pasting and apply your formatting.
The following was tested in IE7/FF3.6/Chrome/Safari 5
$("#textarea").bind('paste', function(e){
// Do whatever you needed to do with the code here.
});
Live Example http://jsfiddle.net/VSrTg/2/
Edit An approach would be something like this:
$("#textarea").bind('paste', function(e){
var oldText = this.value;
setTimeout(function() {
// Compare oldText to $("#textarea").val() and format accordingly.
}, 1000);
});
​Edit 2 Given your revisions to your original post, if you're worried about the giant market share that is Opera, you're going to have to monitor the value of your textbox with a setInterval() and compare it against itself for changes.
Ultimately there will always be a way around your script, even the above example is susceptible to simply dragging text from another text box (or the address bar) into it without triggering the paste event defined above.
I would like to point out DOJO menu widget that is creating context menus perfectly in different browsers. http://www.dojotoolkit.org/reference-guide/dijit/Menu.html#dijit-menu
What you can do is that detect paste event in browsers that are supporting it and override context menu in browsers that are not supporting this event like opera.
Once you create your own context menu then you can add copy paste menu item or create context menu similar to the default using css.
Edited
Some browsers might not allow us to fetch clipboard content, in this case we can always revert back to flash for borrowing some of its features that are cross browser. See couple of links I posted in comments.
Its complete implementation might have more issues than anticipated but it is possible and we can always give it a try (I will for sure).
The answer to the question is a simple no. The main browsers that have no paste event are recent versions of Opera and Firefox 2. Given that there is no paste event, you need to find an alternative event or set of events to detect a paste from the context menu as it actually happens. You can add handlers for every event there is (I've done this) and you simply get nothing in the relevant browsers when a paste is triggered from the context menu by the user.
This only leaves polling the text input's value regularly, which is not the same thing. You could keep track of keypresses and observe in your polling code that the text input's value has changed by some means other than keyboard input and do a diff, but that's hacky and unreliable.
I use the setTimeout for paste events. But for context menu select nothing seems to work(as stated above). I bind a mousemove to the input's form which fires the update function. Then unbind/bind so they don't stack up.
This handles the context menu select and dragging value to input field.
If your form is small, say with only one input field and the mouse will not land on it after selecting from context menu, bind to the form's parent or document. Sure, it has to wait until the mouse moves but that is the general user action after selecting from context menu.
Works fine.

Testing jQuery change event using Watij

I have a select list where a change event has been bound to the element using jQuery. Something like this:
$("#someId").change(function() {..});
When someone chooses a new option in the select list, another part of the UI will change accordingly. Now this works fine when I use the mouse and click things, however, when using Watij to write my tests I need the jQuery change event to fire which it isn't doing.
The Watij test will correctly choose the select option required but the actual event does not get triggered. I have tried calling fireevent("change"); and fireevent("onchange"); to no avail. I have also tried ie.sendKeys("{ENTER}"); and ie.sendKeys("{TAB}"); which also does not seem to do the trick.
Any ideas?
The only solution I've found so far is to roll back the version of jQuery in use. I'm currently using version 1.4.1 (the offending version in regards to the testability of the change event on select boxes) and after going back to version 1.2.6 the problem goes away.
Use $('#someId').trigger('change'); to fire the event manually.
See the documentation for trigger().
When the combo/list value is changed with script the onchange is not supposed to fire. I don't know how Watij is doing that, but this is one case.
Second thing is that Watij is working with IE (as long as wikipedia is rght) and IE is putting a system control in place of Your list or combo and it might break something too. Try upgrading to IE8 which has a tiny bit better realisation of form components (eg. select finally supports "disabled" attribute in options after 10 years)
You might also be interested in a normal application GUI testing apps and use them on a browser with the webapp. Record a macro and check screenshots.

Categories