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.
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 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.
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()...
So I have looked through most of the facebook questions here and it has absolutely confirmed my thoughts. Facebook development may be among some of the worst I've ever used. I'll avoid my rant for now, but as a note to where I'm coming from: tried php sdk, worked decently out of the box, found out I need to put the functionality on a pages tab, can't iframe on pages tab, have to use FBML (which they are retiring in two months, yet I can't start testing the iframe approach yet)
Anyway, I run into FBJS at this point. It works "good enough" for most things, but for some reason I can't get an event registered to an object (a select box in particular interest) by adding a listener (as per FBJS documentation). I am able to add it directly to the html object and have it work, but this is not desirable and I would really like to know what I consider the proper way to do it, which involves seperation of logic and display.
What I want to happen: click on the select box, make a selection, display the text of the selection in an empty div (later on adding Ajax but one step at a time here)
Code:
<script>
var obj = document.getElementById('select-id');
obj.addEventListener('onchange',my_func);
function my_func(evt){
var inner = document.getElementById('div-id');
inner.setTextValue('hey'); // for testing purposes
}
</script>
The above code doesn't do anything when I make a change to the select box. However, this behaves as planned:
<select name="find_state" id="find_state" onchange="my_func();">
I will be grudgingly using this method as I develop, but would really love to know what I might be doing wrong or if anyone else has this issue? And if anyone has any opinions on the matter I would love to know of some form of facebook development recommendations as applications, pages, and tabs all appear to behave totally different from eachother, yet it seems that they all should be doing the same thing to me? Is there any unified way to develop across all three of these things, or am I missing something?
Thanks in advance, as well as for the past help!
I think it should be:
obj.addEventListener('change',my_func);
(instead of onchange)
Straight from Facebook documentation:
The third parameter [to addEventListener], boolean useCapture is required (it does not have a default value)
That means that you should have:
obj.addEventListener('change', my_func, false);
Use the following html and your events attached with .addEventListener() start to work. This seems to be undocumented "feature".
<select name="find_state" id="find_state" onmousedown="return true;">
This also enables the event to fire first time the user changes the value of select. Otherwise it would fire only on second onchange event.
Safari has a feature to prompt you if you're sure you want to close/refresh the page on which there are some forms which you typed into. This is useful in most cases, but in this case it's bugging me.
I'm hijacking the "submit" event on some forms and sending them to the server via XMLHttpRequest. However, Safari doesn't know that, so when I want to close the tab it displays that damn warning that form values have changed.
I know how to turn it off in OS X and I don't want that. I want to turn it off on this specific web page I'm building, and for all users with Safari. Surely there must be some JavaScript way—I don't care if it's proprietary to webkit.
Update: I tried this, but to no effect. Safari first warns about unsaved data, then triggers the "beforeunload" event.
if (Prototype.Browser.WebKit)
window.addEventListener('beforeunload', function(e) {
forms.invoke('reset')
})
I don't know Safari that deeply, but if you just submit the values and don't need them afterwards, why not simply reset the form? I would expect no change = no warning.
If you don't want to reset it straight away, you could even try hooking the reset command to the unbeforeunloadevent to do it when you close the page. Whether that works depends on when Safari checks for the changed form, though - before or after calling unload.
That's application behavior, so there mustn't really be any JavaScript way of modifying it. Every WebKit specific feature is documented pretty well, and I've never seen anything of the sort. Just clear your form fields if you're really that worried about it.
https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/Introduction/Introduction.html#//apple_ref/doc/uid/TP40002079-SW1
https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariHTMLRef/Introduction.html#//apple_ref/doc/uid/30001261
The only way I see left around this is having a form consisiting of hidden inputs only, and a bunch of input elements that are not associated with the form. On submit, you fetch the values from the the elements, make your request and reset the internal form. You could even do the moving of the input elements out of the form via DOM so it would even degrade gracefully.
A lot of work and a bit hacky, but as far as I can see the only option if you can't change the workflow.
Try removing the action and method attributes from your form tag with Javascript after you bind submit. This way, Safari should no longer see the inputs as being part of a real form.