$("#element").on("change", function(){
calculateValue();
});
function calculateValue(){
$("#result").html($("#int1").val() + $("#int2").val());
}
calculateValue();
In the above (example) code, I am calculating the results of an element every time an element is changed.
However I also want to do this calculation before the user has changed any values. So in the above example I just call the function.
It seems messy that I am calling the function in two places. When I have a few of these, it starts looking very messy. Is there any better way to write this?
You can simply declare two events to the elements as below:
$("#element").ready(function(){calculateValue();})
.bind("change", function() {
calculateValue();
});
FROM THE API:
The .ready() method offers a way to run JavaScript code as soon as the page's Document Object Model (DOM) becomes safe to manipulate.
Related
If I have multiple instances of the following lines of code through out my js file:
document.querySelector('#IdName').play();
document.querySelector('#IdName').pause();
Is it a good idea to create a function and pass it the IdName(IdName will change in various parts of the code)? I know what it does but I'm really just curious if it's a good practice to call document.querySelector( )a bunch of times in the file or put it in a function where I only call it twice to perform the play and pause actions.
If you constantly need the same element, change the function to take a DOM node, and store the element in a variable instead
function doStuff(elem) {
elem.play();
}
function stopStuff(elem) {
elem.pause();
}
var element = document.querySelector('#IdName');
doStuff( element );
// later
stopStuff( element );
That way you only get the element once, and avoid unneccesary DOM lookups
The best approach is to cache that query in a variable so you don't need to search the DOM each time.
For an ID selector this time saving is likely minimal but for more complex collections can help
var $el = document.querySelector('#IdName');
$el.play();
$el.pause();
It is good practice to write code that is reusable, so in that case a function is better practice. If the function only contains 1 line of code and you call it many times, it is still preferable because then if you ever decide to update that line of code or add more code, it's centralized and you change in one place only.
As far as actual execution is concerned, these are the same:
document.querySelector('#IdName1').play();
document.querySelector('#IdName1').pause();
document.querySelector('#IdName2').play();
document.querySelector('#IdName2').pause();
document.querySelector('#IdName3').play();
document.querySelector('#IdName3').pause();
vs
playpause("#IdName1");
playpause("#IdName2");
playpause("#IdName3");
function playpause(idname){
document.querySelector(idname).play();
document.querySelector(idname).pause();
}
In addition to Steve's answer, also note that if you are using the same one twice in a row:
document.querySelector('#IdName').play();
document.querySelector('#IdName').pause();
then it is a better practice to do:
var thing_with_play_and_pause = document.querySelector('#IdName');
thing_with_play_and_pause.play();
thing_with_play_and_pause.pause();
This reduces the number of queries you have to make. Some IDEs (PyCharm for instance) will complain if you don't because it is less efficient.
I was just wondering which is the correct or most efficient way of navigating through the Dom using variables.
For example, can I concatenate selectors
var $container = '.my-container';
$($container).addClass('hidden');
$($container + ' .button').on('click', function(){
//something here
});
or should I use the jQuery traversal functions
var $container = $('.my-container');
$container.addClass('hidden');
$container.children('.button').on('click', function(){
//something here
});
Is there a different approach, is one best, or can you use them at different times?
The $ is usually used only when working with an actual jquery object. You generally shouldn't prefix anything with that unless it's really something from jquery.
Beyond that little bit though, performance-wise, your second bit of code is going to be faster. I made an example jsperf here: http://jsperf.com/test-jquery-select
The reason the second bit of code is faster is because (if I remember correctly) jquery caches the selection, and then any actions performed on that selection are scoped. When you use .find (which is really what you meant in your code, not .children), instead of trying to find elements through the entire document, it only tries to find them within the scope of whatever my-container is.
The time when you wouldn't want to use the second pattern is when you expect the dom to change frequently. Using a previous selection of items, while efficient, is potentially a problem if more buttons are added or removed. Granted, this isn't a problem if you're simply chaining up a few actions on an item, then discarding the selection anyway.
Besides all of that, who really wants to continuously type $(...). It's awkward.
I wanna select some item by jQuery which has been added after loading page,so I wanna use live() function.I used it before for clicking like following code:
$("selector").live('click')
but now when I wanna use it in another function.
but It will not work with out argument,like it live()
for e.g followin code will alert test (work)
var pos_eq=Math.abs($('.myList').css("left").replace("px","")/$('.myList').children('li').eq(0).css('width').replace("px","")) + 1;
alert("test");
but this will not.
var pos_eq=Math.abs($('.myList').live().css("left").replace("px","")/$('.myList').live().children('li').eq(0).css('width').replace("px","")) + 1;
alert("test");
how can I solve it?
You want a function, not a variable. It looks like you are trying to keep pos_eq up to date after elements have been added to the page. Having a variable auto-update when the DOM changes in the way you are trying to do is not possible with JavaScript. What you can do is use a function instead of a variable. This way whenever the value is accessed you are getting the latest value because it is computed on demand:
function pos_eq() {
var list = $('.myList');
var left = parseInt(list.css("left"));
var width = parseInt(list.children('li').eq(0).css('width'));
return Math.abs(left / width) + 1;
}
I broke your code up into multiple statements to make it more readable. You would use this function the same as you used the variable, but instead add parens to the end to invoke the function:
alert(pos_eq);
alert(pos_eq());
To get a set of objects at the time you need them, just do $("selector"). That will do a query at that time and get the set of objects. There is no need to use .live() in order to query objects on the page. It does not matter whether the objects were part of the original page or were added dynamically later. When you do $("selector"), it will search the contents of the current page and get you the objects that are currently in the page that match the selector.
There is no way to do a live selector query and save it and have it automatically update in jQuery or any other library I know of. The way you solve that issue with a dynamic page is that you just do a new query when you need current results.
The description of live() is: Attach a handler to the event for all elements which match the current selector, now and in the future. It does not give you a live node list despite its name. jQuery does not have any method that returns a live node list(such as those returned by getElementsByTagName etc.) as far as I know.
Say i have a selection of textboxes like this;
var arrayoftextboxes = $('.textbox1, .textbox2, .textbox3');
Is there a way I can call a function on each one in a simpler way than this?
It only needs to be called once.
arrayoftextboxes.each(function(i){foo(arrayoftextboxes[i]);});
I tried
arrayoftextboxes.load(function(){foo(this)});
and
arrayoftextboxes.bind(function(){foo(this)});
but the functions dont seem to be called.
You can do this:
$('.textbox1, .textbox2, .textbox3').each(function() { foo(this); });
The .each() call creates a closure, inside it this refers to the DOM element you're currently on, but it may be better to write what you have as a jQuery plugin. Or, if you just use this inside foo (instead of the DOM element as a parameter) you can shorten it down to:
$('.textbox1, .textbox2, .textbox3').each(foo);
Here's a demonstration of that method
Also, make sure you're running this on document.ready like this:
$(function() {
$('.textbox1, .textbox2, .textbox3').each(foo);
});
Otherwise the DOM elements may not be there to find, making that selector return an empty array (so nothing to run on).
I'm populating a list by cloning elements into it. Then I change attrs to make each item unique. They need to call a function on click, so I'm wondering if it's more efficient to use new_element.click(func); or new_element.attr('onlick','func();');
new_element.attr('onclick','func();');
Is:
inefficient (needlessly creating a new inline function from a string, that does nothing except call func and lose the this reference);
aggravating to put any complex code in, since it all has to be JS string escaped;
broken in IE, due to bugs in setAttribute.
Avoid. click()/bind('click') is there for a reason.
onclick has a number of limitations, including cluttering the DOM and only allowing one function at a time. So you should use click. See Quirks Mode for more information.
Directly referencing the function will be more efficient than having to interpret a string.
The lowest touch way of doing this, however, is this way:
$(links_selector).live('click', func);
links_selector will presumably be something like ul.listClass a.actionClass. This will not require anything to be done when new list elements get added.
Since you are using jQuery then make it this way
new_element.click(function(){
// your code
});
or you can bind the click event handler like
new_element.bind("click", function(){
// your code
});
Any difference in performance between the two is most likely going to be negligible. You should use the one that reads better, and that's element.click. (Plus, onclick has many disadvantages, as #Matthew Flaschen mentioned.)