I'm authoring a jQuery plugin in which one of the methods that I'd like to write will not take a selector argument and does not need to pass an element. I'd like it to be available by a call like $.myMethod() like the built in $.ajax() method. Up to now I've tried something like
$.fn.myMethod(options) {
console.log("I've been called");
}
This works when I try $('.a_selector').myMethod() but not when I try $.myMethod().
Is this doable with a jQuery plugin or is it only available for interal functions.
The purpose of this method is to perform an action on some data that is stored in jQuery.data. I recognize that they jQuery.data is associated with an element, but in this case I've hard coded it to the body element to make things easier for the end user.
The functions that are members of $.fn apply to jQuery objects, not to the $ object itself. If you want to create such a method, you only have to write:
$.yourMethod = function() {
// Do something.
};
Now you can call it without a jQuery object:
$.yourMethod();
An elaborate way of declaring such a function can be
$.extend({myMethodA:function(){
//Do something
},
myMethodB:function(){
//Do something else
}
});
Related
I wonder if there's a way to combine a JS selector with jQuery functions methods like that:
document.getElementsByClassName("example").on("click", function() {
...
});
You can pass your node list to the jQuery constructor:
$(document.getElementsByClassName("example")).on("click", function() {
// ...
});
I don't know for sure how long jQuery has recognized when node lists are passed to the constructor, but it seems to work now.
I'm working on a WordPress theme with a lot of jQuery in it. By default, WordPress doesn't allow you to use the $ shortcut and you have to use the full jQuery instead - e.g. jQuery('.class') rather than $('.class').
This isn't too much of a hassle over a few lines of code, but I've got a lot now, so I remapped jQuery to $ using:
(function($){
...my functions here...
})(window.jQuery);
This works fine for functions triggered from within that file, but if I use any inline triggers in the PHP, they no longer work. For example:
<a onclick="loadFullPost('<?=get_permalink()?>?ajax=true','<?=$post->post_name?>',<?=$post->ID?>)">Read more</a>
worked fine before remapping but doesn't now. I can't bind the event as usual within the js file, because I won't be able to access the PHP and WordPress functions I need - unless I'm missing something. For example, this wouldn't work:
$( "#target" ).click(function() {
loadFullPost('<?=get_permalink()?>?ajax=true','<?=$post->post_name?>',<?=$post->ID?>)
});
Is there any way around this?
The issue is that your functions are no longer globals. This is a Good Thing™. (See below for why.)
Is there any way around this?
By far the best way would be to not hook up events like that. Instead, keep your code and markup separate, and hook up your functions using jQuery's on and similar. See below for more.
But if you feel you have to, you can make your functions globals by assigning them as properties on window:
(function($) {
window.loadFullPost = function() {
// ...
};
)(jQuery);
or
(function($) {
function loadFullPost() {
// ...
}
window.loadFullPost = loadFullPost;
)(jQuery);
So how would you do
<a onclick="loadFullPost('<?=get_permalink()?>?ajax=true','<?=$post->post_name?>',<?=$post->ID?>)">Read more</a>
...without using a global function? Like this:
<a class="load-full-post" data-permalink="<?=get_permalink()?>" data-ajax=true data-post-name="<?=$post->post_name?>" data-post-id="<?=$post->ID?>">Read more</a>
and then one handler for them
$(document).on("click", ".load-full-post", function() {
var link = $(this);
// Use the values from link.attr("data-permalink") and such
// to do the work
});
Or if you wanted to use your existing loadFullPost function:
$(document).on("click", ".load-full-post", function() {
var link = $(this);
return loadFullPost(
link.attr("data-permalink"),
link.attr("data-ajax") === "true",
link.attr("data-post-name"),
+link.attr("data-post-id") // (+ converts string to number)
);
});
I should mention that you'll get people telling you to access those data-* attributes via the data function. You can do that, but unless you're using the various additional features of data, it's unnecessary overhead (creating jQuery's cache for the data, etc.). data is not an accessor function for data-* attributes, it's much more (and less) than that.
You can also pass your information as JSON:
<a class="load-full-post" data-postinfo="<?=htmlspecialchars(json_encode(array("permalink" => get_permalink(), "ajax" => true, "name" => $post->post_name, "id" => $post->ID))0?>">Read more</a>
(or something like that, my PHP-fu is weak)
Then:
$(document).on("click", ".load-full-post", function() {
var postInfo = JSON.parse($(this).attr("data-postinfo"));
return loadFullPost(
postInfo.permalink,
postInfo.ajax,
postInfo.name,
postInfo.id
);
});
Why making your functions non-global is a Good Thing™: The global namespace is very crowded, particularly when you're dealing with multiple scripts and plugins and Wordpress itself. The more globals you create, the greater the odds of conflicting with one from another script. By having your functions nicely contained inside your scoping function, you avoid the possibility of stomping on someone else's function/element/whatever and vice-versa.
You can add function from your enclosure to window like that:
(function($){
function loadFullPost(...) {
...
}
window.loadFullPost = loadFullPost;
}).(window.jQuery);
Then your function will be visible for onlick attribute etc.
I'm loading part of my webpage using AJAX, in particular jQuery.load(). With this the usual jQuery pattern
$('.classname').click(...) // Handler
// or, working with bootstrap
$("a[rel=tooltip]").tooltip() // Function
or similar obviously don't work any more, because they are called only when the page is loaded. I realize there is jQuery.on for the first example, but how would I implement the second?
Is there a simple (builtin) way to also apply these to jQuery.loaded stuff, or do I have to work around it myself? Seems like a problem a lot of people should be having.
You have to work around it yourself; but you can easily to this by calling $("a[rel=tooltip]").tooltip() in the callback for load():
$('#blah').load('/somewhere.html', function () {
$('#blah').find('a[rel="tooltip"]').tooltip();
});
Be sure to restrict the tooltip() call to only newly loaded elements, or you'll end up initializing tooltip multiple times per element (which may result in weird behaviour).
To avoid duplicating code you just need to define a helper function;
function initTooltip(root) {
return $(root || document).find('a[rel="tooltip"]').tooltip();
}
Which allows you to init tooltip. The parameter is optional, and lets you restrict initialization to only descendants of the provided element, e.g.:
jQuery(document).ready(function ($) {
initTooltip(); // equivilant to initTooltip(document);
$('#blah').load('/somewhere.html', function () {
initTooltip('#blah');
});
});
I have searched but have not been able to find any information. I know this isn't typical of jQuery however I need to appease our structure that we have for PHP and make that into the jQuery plugin per my boss.
Is there any way to extend the $.fn to add another name? For example
$.MyTools.useTool('piece of wood','cut');
or
$('#wood').MyTools.useTool('cut');
I guess MyTools would be the class and useTool would be the function. However I have done this in a plugin. We are wanting to have our plugin called MyTools and whenever you use a function in it you need to call MyTools.
Would it be better to do away with the plugin and just create a class?
Yeah, when I want to make a namespace (sort of) like that I do this for all my plugins:
(function( $ ){
if(!$.fn.MyTools) {
$.fn.MyTools = {};
}
$.fn.MyTools.useTool = function() {
// do stuff
};
})( jQuery );
It appears that is no way to do this, so I had to take a different approach and take the official plugin way method by doing $.GLCFormattingCurrency('remove', data);
I am using jQuery to apply some UI effects like adding a class to a number of elements, in the JS file i use :
$('.dataGrid').each(function(){
$(this).find('tr:odd').css('background-color', '#F7F8FA');
});
but when i use ajax to load an element with the class .dataGrid the rules up there doesn't apply, my solution was to make a function joins all cases like this one and call it every time i make an ajax request ! .. this off course is not a pro one .. i found .live() , i used and it worked fine with events like :
$('dataGrid').live('moveover', function(){ ... }); .
the .live solution is very good with events ... is there any way to use the same concept with the effects like mentioned up there ? ... i mean a way to reapply the rules set before, every time a change takes place on these elements ( adding new one for example )
I wish i was clear enough, Thanks in advance :)
The Livequery-plugin supports triggering functions when new nodes are added to the DOM.
Something like this should work:
$('.dataGrid').livequery(function() {
$(this).find('tr:odd').css('background-color', '#F7F8FA');
}
Depending on how you are loading elements i.e. which AJAX technique you are using, you can achieve this in many ways. If you are using jQuery Ajax then you can use the jQuery.when method.
Basically with this method you can have deferred execution. You can say something like "when the ajax call completes then do this function". The syntax goes like
$.when( $.ajax("test.aspx") ).then(function(ajaxArgs){
alert(ajaxArgs[1]); /* ajaxArgs is [ "success", statusText, jqXHR ] */
});
Following link will give you more information
http://api.jquery.com/jQuery.when/
Since you are using ajax to append your .dataGrid elements you could register a handler for ajaxComplete() that will handle the application of your :odd class.
$(document).ajaxComplete(function() {
$('.dataGrid').each(function(){
$(this).find('tr:odd').css('background-color', '#F7F8FA');
});
});