Buttons are slow on mobiles (at least 300ms delay in most browsers due to drag detection among other things). Google wrote some javascript to fix this:
http://code.google.com/mobile/articles/fast_buttons.html
The Mobile HTML5 Boilerplate people integrated this into their package:
https://github.com/h5bp/mobile-boilerplate/blob/master/js/mylibs/helper.js#L86
I want to figure out how I can easily use this with backbone. Something like:
events: {
"fastbutton button.save": "save"
}
Where fastbutton replaces click or mousedown with the fast button code. I expect that I will need to rewrite the MPB.fastbutton code a bit. Has anybody done this?
Instead of creating 'fastbuttons' everywhere, it's probably saner to use a library like FastClick that will transparently convert touches to click events on the touched element and get rid of that 300ms delay.
It's as easy as new FastClick(document.body) and you're ready to go.
The advantage of that approach is that if or when the behaviour of touch events changes on mobile devices so that there's no delay on elements with a click event registered, you can just change one line of code to drop the library instead of changing all your code to convert 'fastbuttons' to regular buttons. Maintainability is always good.
I'm pretty sure, this won't work the way you'd like it to. Instead of having an additional event, like say "fastclick", you have to define an element as beeing a fastButton. You actually have to create an instance of fastbutton on which you pass the element and the code like this:
new MBP.fastButton($("button.save"), function() { this.save(); }.bind(this));
In case of backbone, you can easily do this in the initialize() function instead of the events object.
// sorry, just read that you are not really looking for this :)
Related
TLDR Below
JS Fiddle To Demo
I've been really involved in recreating the tools that are foundations of premiere JS Libraries to better improve my skills. Currently I'm working on functional data-binding a la Angular.
The idea of data-binding is to take data and bind it to elements so that if manipulated all elements subscribed will change accordingly. I've gotten it to work but one thing I hadn't considered going into it was the issue with innerHTML vs value. Depending on the element you need to change one or the other( in the demo above you'll see that I needed to specifically single out the button element in a conditional statement because it has both, but that's kind of a fringe case )
The issue is that in order to capture a SPAN tag update I needed to trigger an event to happen, and the easiest one to manipulate for Text Boxes/Textareas was 'keyup'.
In my function then, if you pass in an element with no value property we assume you're going to be updating innerHTML, and we setup an observer to determine if the element ever mutates, and if it ever does, the observer will emit a 'keyup' event.
if (watchee.value == void(0)) {
var keyUpEvent = new Event('keyup');
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
watchee.dispatchEvent(keyUpEvent);
});
});
observer.observe(watchee, {
childList: true
});
}
Now it may just be my paranoia, but it seems like I might be tunneling into a can of worms by faking 'keyup' on an element that doesn't natively have that support.
TLDR:
I'm curious if there's an alternative way to make, a.e. a span tag reactive other than faking a 'keyup'/'keydown'/'change' event? For instance, is there a way that I can make my own pure event(by pure I mean not reliant on other events) that checks if innerHTML or value has changed and then performs a function? I know that this is probably possible with a timer, but I feel like that might hinder performance.
EDIT: just an aside. In the demo the function called hookFrom works by taking a DOM node and returning a function that will take the receiving dom node and continues to return a function that will take additional receiving dom nodes. :
hookFrom(sender)(receiver);
hookFrom(sender)(receiver)(receiver2);
hookFrom(sender)(receiver)(receiver2)(receiver3)(receiver4)...(receiver999)...etc
JS Fiddle To Demo (same as above)
There is nothing inherently wrong with creating a similar event on a DOM node that doesn't natively have that functionality. In fact this happens in a lot of cases when trying to polyfill functionality for separate browsers and platforms.
The only issue with doing this sort of DOM magic is that it can cause redundancy in other events. For instance the example given in this article: https://davidwalsh.name/dont-trigger-real-event-names shows how a newly minted event using the same event name can cause problems.
The advice is useful, but negligible in this specific case. The code adds the same functionality between text boxes, divs, spans, etc... and they are all intentionally handled the same way, and if the event would bubble up to another event, it would be intentional and planned.
In short: There is a can of worms that one can tunnel into while faking already explicitly defined event names, but in this case, the code is fine!
I was going through the history of dropdown.js in bootstrap and came across the following change History file on git, here:
$this.focus() // focus() being changed to trigger('focus');
$this.trigger('focus')
Now, the guy here has left a comment about the change saying:
Makes life for people with custom jQuery builds excluding event
aliases much easier.
I don't quite understand what's the difference here between using focus() or trigger('focus'), as for me both have the same effect; why has the author chosen such a change?
https://github.com/jquery/jquery#modules.
If you are making a custom jQuery build and exclude event/alias module - you won't have shortcuts to events (e.g. .click(), .focus(), .ready(), etc).
So you'll have to use .on('eventName', handler) for event binding and consequently .trigger('eventName') to trigger jQuery event.
People with custom jQuery builds could create or modify their own focus() functions intended to do whatever they want. Imagine if you create your own focus() which allows lot of parameters and chains multiple callback; it would be a mess when you combine its usage with the jQuery focus() basic function.
When you use a trigger it's qute obvious you're going to trigger an action; in this case, to focus an element.
Beside of that, using the trigger() functions makes the code a little easier to understand.
I have a script that does event.stop() and displays an alert on links.
Some of these links have other JS scripts linked to them, like tabs, accordions and so forth.
Of course my event.stop() doesn't always fire on them (the alert shows but the tabs etc. still work).
The project is quite big (many different plugins and JSes) and I'm wondering what's the best way of making my event.stop() always work before the other scripts do? Something like CSS !important.
Callbacks? For so many scripts?
You need to call event.preventDefault() or event.stopPropagation() like below:
$(selector).on('click',function(event){
event.stopPropagation();
});
Not: event.stop !
It's unclear from your question whether you're using PrototypeJS (which adds a stop method to events), or jQuery (which you've tagged, but which doesn't add a stop method on events).
But it doesn't really matter much to the answer: If the other handlers are attached to the element before yours is, there's no way for you to selectively prevent them being fired. You can remove them entirely (it may be hard or easy, but it's possible), but you can't stop them being fired.
If they're attached after your handler, then it's easy: Use Event#stopImmediatePropagation. jQuery adds it to event objects if the browser doesn't supply it; I don't recall whether PrototypeJS (which hasn't been updated in years) polyfills it for older IE or not. It does some of the others, but I don't know about that one.
I'm working on a heavy e-commerce app. In such apps tracking is a huge concern. It's crucial to know if users use feature x or click on button y etc.
For instance let's say you can bring up the search either by clicking on a search button on the header or by a app wide keyboard command CTRL + S.
Now if we want to track such things, how would be the best way to handle it. I ponder and dither between (using pseudo JavaScript here but the language doesn't really matter):
1. Just do the tracking directly where the action happens:
function searchButtonClicked{
//this event will be raised anyway to be catched somewhere else to bring up the search
raiseEvent('searchButtonClicked');
//now directly track the stuff here
trackingService.trackEvent('searchButtonClicked');
}
And...
2. Just raise events for the actions and then catch those in the trackingService
function searchButtonClicked{
//this event will be raised anyway to be catched somewhere else to bring up the search
raiseEvent('searchButtonClicked');
}
...and somewhere in trackingService
onEvent('searchButtonClicked', function(){
track('searchButtonClicked');
});
So on first glance 2. seems a bit nicer to me as none of the components need a dependency against the trackingService. They don't even know that tracking exist. In addition some of the existing events can probably be reused. However that only helds true for a small subset of events. Most events would be raised more or less exclusively for the sake of tracking. So I wonder if that layer of abstraction is really necessary?
Such tracking doesn't seem to be much different from logging and I think it's accepted practice to directly log at the places where the events happen, no?
As always, it depends on your specific case.
If, like you say, most trackable operations in your application don't raise an event, then an abstraction using events is not the best option.
you could just have your code call the tracking directly, which is not the most clean thing, but it's the simplest, and if each call is just one line, as above, is probably acceptable.
I can just suggest one more little thing- you could try AOP.
depending on the technology you use, you could, either-
1. Mark certain classes / methods for tracking (maybe using attributes, or whatever) OR
2. Create a class that would hold the list of all the classes / methods to track.
If you are doing this in JavaScript, using some library like JQuery can make your life easier. Otherwise you need to have a event registration and listener mechanism in your code.
check here of examples under bind() function
$( "#searchButton" ).bind( "click", function() {
track('searchButtonClicked');
})
I have a facebook connect button on this site here is the code
<fb:login-button onlogin="javascript:jfbc.login.login_button_click();"
perms="email,publish_stream,user_about_me,user_hometown,user_location,user_birthday,user_religion_politics,user_interests,user_activities,user_website"
size="medium" v="2"><a class="fb_button fb_button_medium">
<span class="fb_button_text"\>Login With Facebook</span></a></fb:login-button>
and i want to trigger this button with a javascript call and doing research i found this jquery that seems that it would do the trick (havent tested though) and i was wondering if there is an equivelent javascript or mootool because jquery is not installed. I can install it if i cant find a solution. Or if anyone has another idea on how to trigger this facebook button
$("fb\:login-button").trigger("click");
There are two ways to "trigger" a listener:
call it directly (e.g. element.onclick())
dispatch an event into the DOM that the listener will respond to
The trouble with the first method is that it doesn't replicate a bubbling event so the listener may not work as intended (e.g. there is no associated event object or bubbling, the listener's this keyword may not be correctly set).
The trouble with the second is that some browsers will not allow programatically dispatched events to do certain things (click on links for example). Also, in some browsers you have to use the W3C dispatchEvent and in others the Microsoft fireEvent.
So unless the listener has been designed specifically to work with one method or the other and is called appropriately, your chances of triggering the listener successfully are quite low.
PS. Some libraries provide their own event system, with custom events and bubbling of otherwise non-bubbling events, but in that case you have to set and trigger the listener using that library, otherwise it will probably not respond to either of the above methods.
You should be able to just invoke the same code that is invoked inline:
jfbc.login.login_button_click();
I suppose it would be something like
document.getElementsByTagName("fb\:login-button")[0].click();
I'm sure that would work very well with a "normal" DOM element that handles the click event; however, I'm not entirely sure it will work in all browsers with the fb:login-button element shimmed into HTML. You'll have to let me know.
Looks like you should be able to do:
document.body.getElementsByTagName("fb\:login-button")[0].click();
It looks like you want a namespaced element selector, so you should use:
document.getElementsByTagNameNS('fb', 'login-button')[0].click();
The : is the namespace separator.
I ran into this tonight, absolutely positioned a new button image over the iframe, and was planning on using pointer-events:none to pass through and click the iframe, but I was looking for a cross-browser solution, here you go.
jQuery('.button_fb_connect').live('click', function(){ FB.login() })
Your simply running the js function FB.login() after clicking your new element, obviously you can use whatever event you want.
Thats in jQuery of course, but thats the function you want, not just a simple click event trigger.