Issue with binding in jQuery for copied elements - javascript

This is actually a bigger question because I know there are several ways to solve this problem but I will try to sum it up.
What I try to do: I am using this jQuery plugin to upload files via Flash http://www.uploadify.com/. However, the element #fileInput that I supposed to bind this function to is a live element which is generated after the page loaded: $('#fileInput').uploadify(). The reason #fileInput is a live element is because I use FancyBox to popup a DIV and this FancyBox basically just "cloned" the inner html of the DIV.
What happened: When I clicked "BROWSE" to upload a file, there is no progress bar for upload. The reason is because the Uploadify could not bind to live elements.
Questions:
1. I tried to replace bind() with live() in uploadify code but that did not work because bind() allows to pass [data]. The LiveQuery plugin http://docs.jquery.com/Plugins/livequery does not have the same syntax as bind() either. Is there anything similar to bind but works for live elements?
If I don't try to replace bind() function and keep uploadify code the same. Does anyone know how to change code in FancyBox so that it WILL NOT make a clone to generate live elements? I know this is a hard question too.
Note: FancyBox site seems dead --> http://www.visual-blast.com/javascript/fancybox-jquery-image-zooming-plugin/
Thank you very much!

You might consider changing the FancyBox code to support calling a callback function after it clones the HTML. Then, put the uploadify() call in the callback function.

You could overload the live method, making it support data as the second parameter:
jQuery.fn.live = (function(_live){
return function( type, data, fn ) {
var _fn;
if ( jQuery.isFunction(fn) ) {
_fn = function(e) {
e.data = data;
return fn.call( this, e );
};
}
return _live.call( this, type, _fn || fn || data );
};
})(jQuery.fn.live);
Replacing all instances of bind(...) with live(...) should now work.
Note: you'll have to put the overloaded method above everything else.

From my experience , the only way I have found to do this is by using livequery
It has a similar syntax, and in your case to bind uploadify on a live element, you would use
$('#fileInput').livequery(function(){
$(this).uploadify();
})
Livequery accepts functions without events, and executes them everytime there is a change in the DOM

How is the element generated? If its fetched from the server using jQuery you can use a more hackish way of fixing it, simply put jQuery runs eval() on any script tags it runs into so you could just put:
<script type='text/javascript'>
$(function(){
$('#fileInput').uploadify();
});
</script>
In the fetched html and it'll bind it on load instead of trying to watch over it live. Bonus points, if you fetch the html again it'll be unbound.

Related

Compatibility between GWT and JQuery

I created a simple javascript that uses jquery.tools.min.js library.
My javascript looks like this:
function testFunction() {
$("img").click(function() {
alert("Handler for .click() called.");
});
console.log("what's up?");
}
$(testFunction);
So when I try it on a simple HTML page, I get my alert message when I click on an Image.
I added the exact same javascript in my GWT application.
When the application loads I see the console.log message, but nothing ever happens when I click on any image on my app.
Why is that so ? Is it because the testFunction() doesn't apply to the dynamically created images ? Or is it because the event was overriden by GWT ?
Thank you.
EDIT
I tried recalling my function after I create my content:
public native final void recallFunction() /*-{
$wnd.console.log('again1');
$wnd.testFunction();
$wnd.console.log('again2');
}-*/;
I can see my log messages but no click event is fired.
EDIT 2:
When I run :
$("img").click(function() {
alert("Handler for .click().");
});
or
testFunction();
directly in Firebug's console, the event is correctly attached to my images!!
I tried also calling testFunction() in the window's onload event but with no better luck.
I assume you include jQuery library itself and it is 1.7 or later.
If your images do not exist in the DOM when at the time testFunction is defined use "on()".
function testFunction() {
$("img").on('click',function() {
alert("Handler for .click() called.");
});
console.log("what's up?");
}
When using jQuery in JSNI code, you must use $wnd.jQuery or $wnd.$ instead of $. See also this question on Google Groups.
Instead of Writing JSNI over Jquery you can easily start of with gwtquery http://code.google.com/p/gwtquery/
You will benefit from actually from both Jquery approach and also GWT performance optimization .
GwtQuery benefits over Jquery -
http://manolocarrasco.blogspot.in/2011/01/gwtquery-css-selectors-performance.html
jQuery vs GQuery Benchmark
Also if it is only nice scroll you are trying to achieve you can take a look -
GWT CustomScrollPanel example
and
Custom Scrollbar in GWT
Are you adding any other event listeners (in gwt) to the image in question?
There can only be one on-click handler, and if you are setting them in both enviros, you will run into hurt.
Gwt-Query, as mentioned in another comment, is kind enough to delegate back to gwt internal events (since it knows the syntax for event handlers).
You may want to use firebug object inspection on your image.
Try console.log($("img")) and see what you get.
Look for __listener variable on your images; that's the gwt listener. Check out DOMImplStandard ~line 200 to see what happens when you sink an event in gwt.
I'm not sure how jquery attaches events, but I did see this in the mozilla spec:
"If multiple identical EventListeners are registered on the same EventTarget with the same parameters, the duplicate instances are discarded. They do not cause the EventListener to be called twice, "
https://developer.mozilla.org/en/docs/DOM/element.addEventListener

Possible? When a function in a javascript file is triggered, it lets a function in a jQuery file know?

Could I create a function or custom event in a javascript file called "justDidStuff" and then make .live() watch for that being triggered in another jQuery file?
I know this sounds really complicated, but I can't think of another way to do this.
I have new content coming in from the javascript file which is the only infinite scroller known to work for Tumblr.
I have a bunch of styling happening on the layout of the incoming posts (http://syndex.me) which i'm obviously going to make with jQuery. Hence i'm in a situation where I
A) have to use .live() (posts are dynamically loaded) and
B) can't trigger the changes in a straightforward manner
In a previous question related to this DOMNodeInserted was reluctantly suggested. This just listens for when something has been changed, but it slows down pages such as this and has been depreciated.
EDIT
http://marckremers.com/syndex/js/jquery.infinitescrollfortumblr.js
Is the javascript file (NB it's a monster)
http://marckremers.com/syndex/js/jquery.syndex.js
Is my Styling and Site behaviour jQuery file.
You can use bind and trigger.
var justDidStuff = function(){
//do some stuff
}
$('something').bind('justDidStuff',justDidStuff); // binds to all elements,
// now and in the future.
//call it:
$('something').trigger('justDidStuff');
I think you want to use trigger() and bind
Something like this:
jQuery("body").bind("myEvent", function( data ){ alert("triggered"); } );
and in your function you can notify the page
jQuery("body").trigger("myEvent", { "foo", "bar" });
OK I have solved the problem. It's so easy i can't believe it. You live and learn. All I had to do was place jquery code inline within the javascript file by doing this:
jQuery(function ($) {//doStuff in a javascript file as normal, OMG}

Mozilla Closure Example

JS BIN Attempt
Attempting to follow along with the example, but it doesn't seem to work. A little confused, as it is Mozilla.
Mozilla
As #Xaerxess mentions, you need to call the "setupButtons" function when the DOM is ready for manipulation; typically one does that by adding an event handler to the window "load" event, which happens when the page is entirely loaded (which is what the jQuery idiom $(document).ready(function(){...}); does.
Try adding this snippet to the end of your existing <script> element to accomplish that goal using plain JavaScript, no jQuery needed:
window.onload = function() { setupButtons(); };
Another typical way of doing this is to use the element.addEventListener function; the difference is that you can add multiple event callbacks this way and they won't overwrite each other:
window.addEventListener('load', function() {
setupButtons();
}, false);
You didn't call setupButtons function on page load, only defined it. If you include jQuery, add:
$(document).ready(setupButtons);
in you script tag and it'll work.

How do I find if an element has been loaded using JQuery

I am loading data into the flexigrid. I am trying to use JQuery selectors to make the rows clickable, but I am unable to do so. I want to know if the element has been fully loaded, how do I do that?
I want to do something like if(element.load == true){//do this}. I am not sure of how to check that out. Could anybody help me with this.
Ok, so I already have this div, and am binding a flexigrid to that div. I want to know if the flexigrid has been bound.
$("#GridLoad").flexigrid();
I want to know if the flexigrid has been bound, after that, I need to run a piece of code.
Using a live() on div Gridload would always be true as it is already there. :(
I want to know if the element has been fully loaded?
There appears to be an onSuccess callback.
$("#GridLoad").flexigrid({
'onSuccess': function() {
// Do this.
}
});
Otherwise, if the things you are binding are being lost when the table updates, attach the events via on() or simply capture them at the persistent ancestor element and examine event.target.
You can use $(element).live('click', function () { // do something });
so that if it later loads it'll have the appropriate event binding.
you could use the callback function of jquery's load method.
like so :
$('#result').load('ajax/test.html', function() {
alert('Load was performed.');
});
Even if you are not using 'load' method, almost any method in jquery supports callbacks which happen after the functionality has been completed.
For example, ajax() has success and failure callbacks, animations has callbacks, etc.

Setting an event with DOM javascript

I am trying to set an event in JavaScript but it is not really working. I am pretty sure I am doing it correctly too.
// in index.htm:
function foo() {
// Load gets code from a php file via ajax
document.getElementById('div').innerHTML = load('phppage.php');
document.getElementById('element').onClick = func;
}
// in lib.js:
function func() { alert('Working'); }
Unfortunately... it never alerts 'Working'. I have Google Chrome and I even inspected the element in the developer tools and found that the onClick property was infact func()... I don't understand why this wont work.
I do have extensive use of ajax. The element 'element' is actually loaded with ajax
Try changing it to "onclick"
HTML attributes are not, but javascript properties are case-sensitive. You need to use onclick to set the event handler.
I think the onclick property is lowercase.
However, you should use event attaching methods.
element.addEventListener('click',func);
(and attachEvent for Internet Explorer)
Of course, there are plenty of frameworks out there to handle the cross browser issues for doing this, such as:
ExtJS
JQuery

Categories