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 :-(
Related
I am new to jQuery and I have been trying to look up the Bootstrap transition.js (line 50) code and figure out how it works in there. I have stumbled across the following:
$.event.special.bsTransitionEnd = {
bindType: $.support.transition.end,
delegateType: $.support.transition.end,
handle: function (e) {
if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
}
I have read the documentation, but couldn't really understand much except the following:
bindType: // the event you want to bind with
delegateType: // the event you want to delegate with
After some research I have found the following:
Those are the special attributes for the transition end event that are made available for later use in transition.js.
I am trying to figure out things by reading this article, but all I want to know is: what is $.event.special, what is the use of this line? What is it's common usage?
P.S.: I read this question but it has more external links than the answer itself. Is there a clear canonical Q&A about the most basic use of $.event.special?
WHAT is the use of this line?
I'm assuming you meant the first line of code in your question. It basically defines bsTransitionEnd as an alias for the transition end event (the transition end event may vary from browser to browser - that is what the function transitionEnd() does : determine the proper transition end event for the browser. I've used webkitTransitionEnd here on, but it could be something else depending on the browser)
Why use an alias? It insulates any handlers that Bootstrap attaches using this alias (e.g. $('myBootstrapDialog').on('bsTransitionEnd', Bootstrap's handler) from any $('myBootstrapDialog').off('webkitTransitionEnd') that other code (say, your code or maybe another library) does - so the Bootstrap transition end animations would still work!
Why would you or another library do that? The webkitTransitionEnd is a standard event, so let's say you decide to add a transition end animation to a bootstrap dialog - you'd probably do $('myBootstrapDialog').on('webkitTransitionEnd', your handler) and later on you decide to remove the handler you should be going $('myBootstrapDialog').off('webkitTransitionEnd', your handler), but you miscode it as $('myBootstrapDialog').off('webkitTransitionEnd') - this removes all transition end events :-(.
But since Bootstrap attached it's handlers using 'bsTransitionEnd', the only way you could mess up bootstrap would be to do $('myBootstrapDialog').off('bsTransitionEnd') - not something you would do accidentally :-). So voila! Gone be the bugs where Bootstrap inexplicably stops working because of some small miscoding on your part.
The bindType and delegateType basically state that bsTransitionEnd is an alias for transition events attached directly, and ones that are delegated (bubbles). The handle is basically a filter function - all the triggered events basically go through this before the attached Bootstrap event handlers are called (if at all they are)
what is $.event.special?
I'm sure you'd know most of it already - it's a way to hook into jQuery's event handling mechanism allowing you do large scale magic like do X on every attached click event on the page (imagine doing that one by one, at each and every place you've attached an onclick event), define your own events (with all the bubbly goodness and all which comes with it), hook in and spoof events by modifying the event object, etc.
WHAT is its common usage?
I assume this was rhetorical :-) - you already have a couple of really good examples in the Ben Alman blog post you linked to
(paraphrasing) - let's say you do an AJAX submit and want to disable all clicks on the page (you probably don't want the user clicking on and navigating off to some other page via a menu, or changing a checkbox, etc.) and $.event.special.click should help you (of course it might be just easier / traditional to just overlay a transparent / partially transparent div with a Submitting... animation or something or not doing anything - after all, most users wait around to make sure a submit was successful, at least the normal ones :-))
Another use case is the one you saw in the bootstrap code, but like you mentioned, you usually don't have to go in and use this unless you're writing a library or something that you intend to distribute publicly.
$.event.special
The jQuery special events API is a fairly flexible system by which you can specify bind and unbind hooks as well as default actions for custom events. In using this API, you can create custom events that do more than just execute bound event handlers when triggered--these "special" events can modify the event object passed to event handlers, trigger other entirely different events, or execute complex setup and teardown code when event handlers are bound to or unbound from elements.
The jQuery special event hooks are a set of per-event-name functions and properties that allow code to control the behavior of event processing within jQuery. The mechanism is similar to fixHooks in that the special event information is stored injQuery.event.special.NAME, where NAME is the name of the special event. Event names are case sensitive.
As with fixHooks, the special event hooks design assumes it will be very rare that two unrelated pieces of code want to process the same event name. Special event authors who need to modify events with existing hooks will need to take precautions to avoid introducing unwanted side-effects by clobbering those hooks
bindType: // the event you want to bind with
delegateType: // the event you want to delegate with
When defined bindType: String, delegateType: String, these string properties specify that a special event should be handled like another event type until the event is delivered. The bindType is used if the event is attached directly, and the delegateType is used for delegated events. These types are generally DOM event types, and should not be a special event themselves.
I am looking to create events in Javascript using the same methodology as JQuery- Does anyone know how JQuery does it?
My reasoning is that using raw Javascript such this:
var myEvent = new CustomEvent("userLogin", eventProperties);
...does not actually work on Android native browser, as it does not support DOM Level 3 like Chrome and other browsers do.
However, JQuery does work on Android's stock browser, and simply uses:
$.event.trigger('MyEvent');
My question is, what is the code behind this? I tried to find it by going through JQuery's source code, but cannot get my head around it!
The fundamental thing here is this: When you hook an event handler up with jQuery, jQuery doesn't directly add that handler to the DOM element. Instead, jQuery hooks up a handler of its own on the DOM element (if it doesn't already have one on it). When the event occurs, jQuery looks at the list of jQuery-registered handlers for the event and fires them in order. (There are several reasons for this; initially it was primarily around IE memory leaks and the fact that IE fired handlers in one order, and everyone else in a different order; so jQuery took over and ensured the order.)
(You might be able to see where I'm going with this...)
So when you use trigger, jQuery sends the synthetic event to the DOM element, but it doesn't rely on that synthetic event to work; it calls the handlers you've registered through jQuery directly. In fact, it sets a flag so that it knows that it's done that, so if the browser does send the event to jQuery's handler for it, jQuery knows to ignore it (since it's already done its work).
You can see this in all its glory starting with line 4,464 of the current uncompressed jQuery file.
So basically jQuery's build its own pub/sub system, and only uses the browser event system as an input to it. So custom events don't usually have to talk to the browser at all.
I want a generic (cross browser) way to get the browser to execute the default action for an object for a specified event preferably without getting any attached listeners to fire.
This kind of question has been asked before but in the context of already being in an event, &/or strictly talking about synchronously holding off the default action before letting it happen later.
Basically, let's say you have an DOM element (you don't know which) variable, and you want to invoke a click, such that if it were an anchor, it'd follow its href, if it were an input[type="submit"] it would submit the form.
But without firing that element's listeners for the click event (which may be prone preventDefault()s in the listeners).
For those that need a reason to answer questions; you may want to do it if you're implementing something like dispatchEvent() for browsers that only have fireEvent().
Both functions return true if the default wasn't 'prevented', but only dispatchEvent() actually follows through and invokes the default.
As a side question, jQuery's trigger() is meant to do this (although after firing the listeners) and be cross-browser, maybe the solution is there? As nice as jQuery is I'd like to know the vanilla methods it is calling (if it [this particular feature] indeed works on things like IE8).
It appears that, at least for the click event, you can call .click() on the element in these browsers.
This will have the element enact the default (as well as calling all listeners and the .onclick value, if defined).
I don't know of any other defaults on DOM elements, would scroll need to be accounted for? Keypress? Maybe those exist as functions too, but I haven't tested.
When I did test .click(), I noticed it obeyed any of the listeners returning false and did not fire the default, and the event did bubble (a listener I had on document fired too!).
There may be no other alternative (I.e. calling the default directly, avoiding the listeners). And as for passing it an event object, the browser in question has the single global event thing going on, so maybe you can manipulate that and it wont have changed when executing .click().
Adding as I find more information in my travels :)
Furthermore, there is an doScroll() function, but I think it would be really hard to translate a given event into the string accepted by this method
I see other questions for how to create custom events, but I'm not clear on how to track specific custom conditions.
In my example, I need to "listen" for the eventuality that an array has gone from having x elements to y elements.
I'm not sure if it's a good idea to prototype on top of Array, though that's kind of ideally what I need.
However, the broader question is, what's the methodology for writing custom listeners that are effectively the analog of -pseudo-
onClockStruckTwo
or
onDomChanged
or
onRapture
Meaning, that rather than waiting for some other predefined onEvent (onclick, onkeydown, etc) to happen, I want to make my own.
And please no Framework answers. I'm trying to understand how this actually works in native javascript.
TIA
The question I ask you is "what are you listening from?" If you're listening to a change on the server you could setTimeout an AJAX call, but that'd be far from suggested. If you're strictly looking to have the length of an element change, then there must be something else that you can know will set off the event. I say if it's not server related, don't "listen" at all, just attach the desired Javascript code to the end of something that you know will trigger the event change.
EDIT
Here's a list of all the Javascript event types. I don't see any mentions of an DOM object being empty. You may SOL with the way your hoping to do it.
Arrays do not have any sort of event notification system for changes in javascript. So, if you wanted to know when an array was changed, you would have to create your own notification system.
Since you don't want to use any frameworks (many of which offer event notification and triggering things), you would have to build your own.
There are several different approaches for event systems (messages through a generic message callback, individual callbacks for each event, object oriented approaches of either of these, etc...
The most straightforward (thought not necessarily the most elegant) is to have the object that creates the event maintain a list of callbacks for the event. Then, when an interested party wants to register for the event, they call a method and pass it the event and a callback. This is similar to how addEventListener works in the browser DOM for DOM events. The recipient of that method call, then stores the callback in an array of callbacks. Some time later when the actual event occurs, each callback that is registered for that event is called in turn.
Since array modifications don't trigger events by themselves, you would have to implement a function that both makes the array change and signals the event.
I'm using jQuery in an app which registers user clicks to perform a given action through the .click() binding, and I want this functionality to be available only through a user mousedown. One of my friends pointed out today that it's possible to run $(element).click() from a javascript terminal in Firebug (or something similar), and achieve the same functionality as clicking on the element -- something I'd like to prevent. Any ideas on how to go about doing this? Thanks for your input.
Short answer: No, you can't really prevent it.
Long answer: Any event like a click event is bound to such called Event handlers. Those handlers are functions which are executed when a given event occurs. So if you click on an element, your browser checks if any event handlers are bound to it, if so it fires them. If not, the browser will try to bubble up the event to the parent elements, again checks if there are any event handlers bound for that kind of event .. and so forth.
jQuerys .trigger() method (which is what you actually call if calling .click() for instance) just does the same thing. It calls the event handlers which are bound to a specific element, for a specific event.
EDIT
There might some simple ways to somekind of soft detect a real click, for instance you might check for the toElement property within an event object. That property is not set when triggered. But then again, you can easily fake that aswell with .trigger(). Example:
$(document).ready(function() {
$('#invalid2').bind('click', function(e){
alert('click\nevent.target: ' + e.toElement.id);
console.log(e);
});
$('#invalid1').bind('click', function(){
$('#invalid2').trigger({
type: 'click',
toElement: {id: 'Fake'}
});
});
});
Working example: http://www.jsfiddle.net/v4wkv/1/
If you would just call $('#invalid2').trigger('click') the toElement property would not be there and therefore fail. But as you can see, you can add like anything into the event object.
What are you trying to prevent? Someone messing with your client side script? You can do things like obfuscate your code but not much other than that. But even doing this is just making it more hassle than it's worth in my opinion.
If you don't want people doing certain things move the functionality to the server.
Sorry to be bearer of bad news.
You cannot really do anything against it, it would also be possible to write the complete function and then fire it.
But why is this a problem? If somebody is changing something client side it only affects him. Or are you trying to check some data? This MUST always be done in the backend, because you can never be sure what is really sent to it.
You can check event object (which is passed as first argument to handler) originalEvent.
It will be undefined if event is simulated by .click()
But it's completely useless. You cannot use javascript for security - client has full control over it (and firebug console is just most obvious tool). Client-side security checks should be only hint for user and protection against errors, malicious input can be stopped on server-side only.