Synchronizing identical html forms - javascript

I'd like to have two (or even more) identical html forms on my website.
For example, one - at the top, and another - at the bottom of the page.
What i want is for them to have exactly the same content at any given time. If user changes a value in one of them, all the rest are updated.
Is there a better way to synchronize then javascript onchange/onkeyup events?
onchange fires only after element loses focus.
onkeyup is not perfect too. It wastes a lot of cpu on long text copying and won't fire if element lost focus between onkeydown and onkeyup events.

Update: I just learned that HTML5 has a more appropriate event for this, oninput, but of course it doesn't work in older browsers. oninput will detect any kind of text change, including Paste, Cut, and Delete from the right-click menu. So the best option may be to check if the browser supports oninput (e.g. by using the function recommended here), falling back to the below method if not. On older versions of IE, onpropertychange can be used to simulate oninput.
I decided to change my answer, based on how KnockoutJS accomplishes this. From this page in the Knockout docs:
"afterkeydown" - updates your view model as soon as the user begins typing a
character. This works by catching the browser’s keydown event and handling the event
asynchronously.
Of these options, "afterkeydown" is the best choice if you want to keep your view model
updated in real-time.
It accomplishes the asynchronous behavior by using setTimeout with a time value of zero. Other than that, it appears to be just like a regular keydown event handler.
Here's a simple example, using jQuery, which I believe behaves equivalently to Knockout's "afterkeydown" event:
$('#email').keydown(function() {
setTimeout( $.proxy(handler, this), 0);
});
function handler() {
console.log( this.value );
}
Note:
This will not catch right-click paste events and drag-and-drop events. If you want to update the text on those events too, simply listen for them in the same manner as keydown, e.g.:
$('#email').on('keydown paste drop', function() {
setTimeout( $.proxy(handler, this), 0);
});
Like keydown, paste and drop also need the setTimeout in order to update with the latest value of the text.
Original answer:
onkeyup is probably the way to go, but you raise a good point about it not firing if the element loses focus between keydown and keyup. Based on this answer, I'm pretty sure the solution would be to listen for the keyup event on a container element (or on the body, although in this case it would probably make the most sense to bind it to the <form> element).
As to CPU usage on paste, you could try canceling the event unless a certain amount of time has passed (say 50 ms)...hopefully that will be sufficient. If not, you could look at how some of the popular 2-way data-binding frameworks handle this...most of the ones I've seen use onkeyup.

Related

Listening on every input field in forms using jQuery

I'm working on a SPA that uses jQuery and one of the requirements is that I should trigger actions for particular values of input fields (checkboxes, dropdowns, text). I want to know from a performance perspective which of the following is faster or less cumbersome
$('input, select').on('click focus change', function(e){
//do something
});
or
$('form').on('click focus change', 'input, select', function(e){
//do something
});
Also, given that there will be asynchronous operations on the page, the second option is what I'm leaning towards but I wanted to check with you experts :)
The second snippet attaches the event to the entire form. If a user clicks/focuses/changes anything anywhere (especially the click) then the event fires. As soon as it fires it then checks to see if it was done on an input or select and if not it aborts. As a result, the second version has slightly higher overhead because it will sometimes fire for non input/select events.
The major benefit to the second format is for dynamically created elements. Lets say that something the user does causes an additional field to be created on the form. If that field was not on the page when the page initially loaded then the first version of your event will not fire when that field is changed/clicked. But, the second version would fire.
My recommendation: Unless you are specifically doing something with dynamic fields as I described, then I would use the first. Honestly though, there is such a tiny difference that either would be fine.
In terms of performance there isn't much to write home about. The difference (if any) is negligible. For asynchronous operations, i'd suggest you go for the 2nd snippet.

How to add an extra Javascript Event Handler for all Input Fields to Log Clicks+Edits?

The problem that I am trying to solve is that I have a page with many input fields (some of which are generated dynamically), and I want to be able to do some logging for whenever the user is clicking on various input controls and has modified the data, then left the control. I figure that this can be done by capturing events for onFocus and onBlur, for all types of input fields (buttons, dropdowns, text boxes, etc.). I expect to log the fact that they entered the element and also the value when they left it. However, I have two restrictions:
Some of the inputs have their own event handlers. I do not want to clobber these, but want to trigger events independently of them. Since the goal is sending off log messages, there is really no need for my additional event handlers to ever interact with the existing event handlers.
I need to have a selector that will allow me to capture all the input controls that currently exist when the user triggers the event (however many that may be). This could be done at the same time that the event fires, or it could be triggered to update whenever the DOM is modified to create/remove elements.
I imagine this is a (somewhat) common case, which seems to have some handling in major frameworks (Backbone and Prototype seem to both give some better event handling patterns), but I am trying to avoid adding another framework to the web application. The project already has a jQuery dependency though, which I think should make this possible to do with selectors.
Does anyone know of a good pattern that would gracefully support this kind of behavior?
Could you bind to the blur event via jQuery, like:
$(document.body).on('blur', 'input', function (event) {
$.ajax({ url: "/log/", data: {value: event.currentTarget.value} })
})

Detect if an Input has Changed dynamically

Other javascript is changing the value of an input and I was wondering if there was a way to detect the change.
This question has nothing to do with Keyup or Change. This is not being typed in by the user it is being changed by other javascript though various actions of the user.
When changing an event programatically, you can trigger a change event to make sure event handlers that are attached to the element are fired. jQuery has a trigger() method to do this:
$('#elementID').on('change', function() {
alert( this.value );
});
$('#elementID').val('some new value').trigger('change');
The quick run-down of what I am going to say is: there is no way other than to modify the third-party scripts to output stuff, or to use setInterval (costly).
The bottom line of this issue is a simple one, that does not appear to be so at first: How can you get your scrips to communicate with each other?
When a script modifies the value of an input through JS methods (i.e. not user input), they have to go through specific hoops to get the "change" event to fire (they can fire it manually by calling it, which most devs never do and is easily forgotten when writing code). In practice, people tend to rely on the observation events (user-defined ones) to track code changes. This is very similar to DOM events - you bind callbacks to your script, which allow you to tap callbacks in that will fire whenever your scripts do something interesting (like modifying inputs. This is just one example). You then teach your scripts and developers to fire events on useful stuff using the callbacks to notify other scripts.
A great library for this is Postal, which is originally a Node library. jQuery also has an event system you can tap into. However, if you want to roll your own, all you have to read into is the Observer design pattern. It is trivial: you bind a function to your object to pick up callbacks, and another to fire them. Whenever you change the thing, you fire the callback. Simples.
Failure to do so means setInterval. Sucks, but there you go :-(

Difference between typing and pasteing in a field

If I use xss, what's the difference between typing in ALERT('DSSA');, or just paste it to a search textfield? In a site, typing works, and makes the alert, but if I just paste it, than it doesn't. To prevent the question, I don't want to hack any site, I'm just interested in network security.
thanks for the answer
This will be because the programmer who built the website is lazy and hasn't listened for the onpaste event.
Typing fires the onkeydown, onkeypress and onkeyup events, and are the standard events to consider when watching for user input.
It would seem those are the only events the programmer has listened for (which makes this irrelevant of network security).
If this is not the case, then he'll be using two different event handlers for the events; one which escapes the input, and in the other he's forgotten.
I may not have understood the question properly.
Typing triggers keyUp, keyDown and keyPress events on the element. If the codes are programmed to capture them only, then only those events will be captured.
Pasting can be done using keyboards, mouse and browser options. So this depends on which events you are listening too. There is a separate event called onpaste which will ease everything.
What I mean is, lets say my code is written to capture the pasting my pressing "Ctrl" + "v" only, but if mouse and browser options are used to paste on the
element, then it is configured to capture mouse events also, it cannot
be captured.

which HTML element lost focus?

in javascript, when I receive a focus event, how can I work out which element has lost focus? I'm trying to avoid having to put an onblur event handler on all elements within my web page.
#pbrodka: the target/srcElement property would refer to the element with focus for onfocus events
offhand I can't see a way to get this short of onblur, or if the set of objects you care about all have focus methods you could store a reference to that object instead. It's also possible event bubbling could get you out of jail
this all feels like a bit of a code smell though - perhaps you need to describe the problem in more detail
Difficult this. You cannot use event delegation to find out which control last produced a blur as focus/blur do not bubble up. There have been some attempts to 'fix' this but they are buggy and not resiliant cross browser.
Could I ask you why do you need this information as maybe there is an alternative solution.
Unfortunately, the onblur event doesn't bubble, otherwise you could have handled it at the window level to always know when an element lost focus.
As things are, I do believe it will be hard to do without, as you say, adding an onblur event handler to all elements (a truly nasty solution ;-).
It is possible to delegate the focus and blur events, if you follow PPK's advice, here:
http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
The most simple solution is to write a function that walks all forms and then all elements within the form and installs an onblur handler for each (which will probably call some global function). This handler will get an event and this event will contain the info you seek.
This way, you just have to call this method once in body.onload and it will work no matter how complex your document is.
The only drawback is that you will need to call it if you dynamically add forms to your current document. In this case, you must make sure not to install the handler again (or you will get spurious duplicate events).

Categories