I want to create a "confirm plugin" that will fire first and ask the user if "they are sure". Just to be clear, I will be using a custom made confirm box, not a the default Window confirm() Method.
If yes then it will fire all the other events that have been bound to it. If no then it will do nothing.
A use case would be a delete button that has a separate click event bound to it, which when pressed will delete an element.
If I attach my plugin to the button then it will bind another click event and by using the events info inside $._data I can send my even to the top of the list (making it fire first), I then stop propagation (this stops the other binding firing which deletes the element). If the user clicks ok on my confirm box, I trigger a click again this time just bypass the stop stuff and it will then fire the original events
I am using a slightly modified version of https://github.com/private-face/jquery.bind-first
The only way it can access this info on an element is by using:
$._data($(this)[0]).events
I want to know how "future proof" this is as I know this changed already since 1.7. Are there any plans to officially support a similar thing.
If all else fails, I know I can just make sure that the plugin and the bindings happen first in the code, but this is not really the most flexible solution.
Using $._data is a smelly solution, hence this post. Maybe there are some fancy custom event things I can do?
The short and simple answer is not at all. Using, or more importantly relying on undocumented features is never a good idea.
It sounds like you have an XY Problem here. There are likely many other ways to achieve what you're trying to do here, and using $._data is almost certainly not the best solution.
Related
I'm working on a software that got quite huge over many years and we've noticed there are many buttons (or clickable elements like <a> and <img>) that aren't safe from double clicks. Since the software is running on sometimes quite laggy hardware (with touch screens that might bug out and register double clicks for no apparent reason) I'd like to implement some kind of global solution for it.
My first thoughts were:
Global click listener that gets the click event, processes it and starts a cooldown on that specific element. If another click event is registered before the cooldown is over, it'll just block the event.
Changing the click() prototype method of a button or something. I'm not that good with plain JS but I've done something like that for plugins before so I know at least conceptually how that works.
Adding a directive that can be inserted into existing elements which need double click protection. This would probably be the "scalpel" method, even though people might just forget to add it. Sadly I have no idea whether my idea is actually possible with directives as I've never implemented one before.
Something like a class that can be inherited which handles all clicks. Might be possible to implement together with solutions (1) and/or (2).
Do you have a direction you can point me to to investigate further? Is some kind of global handling for this a good idea at all? Are any/all of the solutions possible at all?
I've encountered an annoying issue while working on YUI.
I have a main area and a navigation block. The elements in the main area can be activated with a direct click or by clicking an element in the navigation block that triggers the appropriate element in the main area.
As it turns out, triggering a click event programmatically in YUI isn't as simple as I thought it might be. Looking at the documentation I found pleanty of information on how to attach and delegate events but not how to call one.
I found this question, but it deals with creating a new custom event and not calling an existing one.
All other similar questions are answered with using .simulate(), but this is actually not the best option for compatability reasons and it's also not recommended by YAHOO itself for client-side use http://yuilibrary.com/yui/docs/event/simulate.html#faking. EDIT: After re-reading the section I realized the warning is irrelevant for the subject of this question.
I found a solution by calling the click() command in the node's DOM element, but this is really a last resort and I would like to know if there's a more "clean" way to do it through YUI.
Here is an example of what I'm doing now: http://jsfiddle.net/3fso2dg8/
In the example, the second button is triggering the click event of the first button by using the DOM element
Y.one('#clickme')._node.click();
CONCLUSIONS
After more fiddling with the code I came to realize simulate() is the preferred option in most cases, but not all.
The YUI vesrion I'm required to work with (3.14) has a known issue on simulating a click event in IE9 and above. Since - for other technical reasons - I cannot upgrade to whatever version this issue was fixed and I need to keep a multi-platform compatibility, my original solution is still the best option. Anyone else that uses YUI components that don't respond well on IE, maybe you stumbled upon the same issue so this is one way to solve it.
After looking for exactly the same functionality I just used simulate in user-facing code - where It would just mimic clicking with no return method etc. (simple submit button or choose fil trigger).
When I would needed "complex" functionality I would just add a class or new ID and add new delegate or "on" method in my code - following the: "If a function needs to respond to user action or be called programmatically, it should be written accordingly and called directly in the latter case." prinsipp.
So to summarize - I use simulate for very simple effects with no callbacks or other "advanced" stuff and (sadly) duplicate other delegate/on elements where simulating would be tricky...
Had also looked into your method (._node.click();) and I can't see no obvious difference comparing to simulate()...
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 :-(
I've been struggling to deal with a few forms that have users entering in a lot of repeat data. In these cases it helps users to have access to form history (ie. to select the name of a person they've sent multiple notices to, etc. The issue here is that in most browsers there is no event fired with a user selects a chunk of text from their form history. So with the help of a few other posts on stackoverflow I decided to use setInterval instead.
What I'm looking for now is feedback to spot anything that might be a bad idea and anything to make this better.
I have a demo of it here http://lab.atworkinthecloud.com/form-history-select/
I believe you shouldn't base your implementation on the behavior of the browser (remembering the history), which might or might not be available to the user.
If you want to design a useful interface, you should provide the access to the history yourself, or use features like autocomlete
since you trigger the handler so frequently , (and I noticed that you also bind the propterychange event), then why don't just bind the propertychange only, that will do it as well.
you don't need to bind all those events at all.
I met the same problem, but I still prefer to have a way that only trigger the hanlder after the user finished typing.
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).