admin管理员组文章数量:1301580
Imagine we have a text field that executes the code below on each keydown event:
if( $('#my_input').val() == '' )
$('#my_span').html('my input is blank');
else
$('#my_span').html('My input is not blank');
Obviously we are executing code that possibly sets the state of something (#my_span
element) to what it already is and this seems inefficient. But I am curious as to what the alternative is? Adding more checks like:
if ( $('#my_input').val() == '' ){
if ( $('#my_span').html() != 'my input is blank' )
$('#my_span').html('my input is blank');
}
else if ( $('#my_span').html() != 'My input is not blank' )
$('#myspan').html('My input is not blank');
Is the latter more efficient? It would seem to me more 'correct', but obviously it's more code and I'm not sure how much more efficient it is than the first example.
I know that the former always involves a DOM manipulation, which will factor in puting the relative efficiency, but I've encountered situations like this before in non-DOM related code, so wondering what is the best approach in all cases. Should you always do the extra check on the value of something before setting it to a new value?
EDIT:
My final version actually uses a bination of the answers here so thanks to all for the great replies. So to sum, I now:
- Cache the jquery objects in a closure
- Uses state to determine the assignment to a new state
Also as an aside, the setTimeout on the keydown is a very nice way to get a input fields value immediately. Thanks again.
Imagine we have a text field that executes the code below on each keydown event:
if( $('#my_input').val() == '' )
$('#my_span').html('my input is blank');
else
$('#my_span').html('My input is not blank');
Obviously we are executing code that possibly sets the state of something (#my_span
element) to what it already is and this seems inefficient. But I am curious as to what the alternative is? Adding more checks like:
if ( $('#my_input').val() == '' ){
if ( $('#my_span').html() != 'my input is blank' )
$('#my_span').html('my input is blank');
}
else if ( $('#my_span').html() != 'My input is not blank' )
$('#myspan').html('My input is not blank');
Is the latter more efficient? It would seem to me more 'correct', but obviously it's more code and I'm not sure how much more efficient it is than the first example.
I know that the former always involves a DOM manipulation, which will factor in puting the relative efficiency, but I've encountered situations like this before in non-DOM related code, so wondering what is the best approach in all cases. Should you always do the extra check on the value of something before setting it to a new value?
EDIT:
My final version actually uses a bination of the answers here so thanks to all for the great replies. So to sum, I now:
- Cache the jquery objects in a closure
- Uses state to determine the assignment to a new state
Also as an aside, the setTimeout on the keydown is a very nice way to get a input fields value immediately. Thanks again.
Share edited Jun 4, 2013 at 22:42 BIOS asked Jun 4, 2013 at 17:14 BIOSBIOS 1,6955 gold badges21 silver badges37 bronze badges 6-
You could 1) cache elements, 2) use a boolean to store the state and not call
html
when you don't have to. – Denys Séguret Commented Jun 4, 2013 at 17:15 -
SOMESTRING == ""
can be replaced by!SOMESTRING
– Ian Commented Jun 4, 2013 at 17:23 - Ha. Every answer has gone through 100 iterations based on ments and paring and they are all almost identical now. How funny. – Lee Meador Commented Jun 4, 2013 at 18:05
- Ha Indeed :) I always leave a gap between an accept as the answers progressively get better :P. I feel this question could still have a better title however. One that is more general? If anyone can think of a better one please edit. – BIOS Commented Jun 4, 2013 at 21:49
- I think you should be careful in trying to generalise this too much. As it stands, the question is leaning heavily on the DOM, which is expensive to query and manipulate, hence the scope for a more efficient method. If you are simply manipulating strings, for instance, then your code optimisation could be very different, as "caching" and storing "state" could just add plexity and make the method less efficient. – MrWhite Commented Jun 4, 2013 at 23:15
7 Answers
Reset to default 7I would cache the jQuery objects and use a boolean to store the state and not call html
when you don't have to :
(function(){
var i = $('#my_input'), s=$('#my_span'), blank, check = function() {
if (i.val()=='') {
if (blank!==true) s.html('my input is blank');
blank = true;
} else {
if (blank!==false) s.html('my input is not blank');
blank = false;
}
};
i.keyup(check);
check(); // so that the span is initially filled
})();
Note that what you need isn't keydown
but keyup
, so that the value of the input is changed before you get the event.
This method even works if you keep pressing the key ;)
Performance? Go Pure JS. Fiddle
//before event binding
var my_input = document.getElementById('my_input'),
my_span = document.getElementById('my_span');
$(my_input).on('keydown', function () {
//inside event handler
var value = my_input.value
, prevVal = my_input.prevVal
;
if (value && prevVal && prevVal !== value) {
return;
}
//timeout to return event handler execution early
//(ie: differ DOM manipulation from the event handler.
//So, UX will extra smooth ;) )
setTimeout(function () {
fieldStatusUpdater(my_input.value);
}, 1);
});
function fieldStatusUpdater(value) {
if (my_input.value === '') {
my_span.innerHTML = 'my input is blank';
} else {
my_span.innerHTML = 'My input is not blank';
}
my_input.prevVal = value;
}
This is the fastest and nicest I can e up with:
function keyUpEvent(){
var state = null,
input = $('#my_input'),
span = $('#my_span');
return function(){
var test = input.val() === '';
if( test === state) return;
if(test)
span.html('my input is blank');
else
span.html('My input is not blank');
state = test;
}
}
$('#my_input').keyup(keyUpEvent());
http://jsfiddle/TMb8T/
This uses closures to store the input and span elements after initialization. And you can use it (almost) as if its a normal function, so u can bind it do multiple events and it still works.
Note that you have to execute keyUpEvent
when you bind the event.
Addition: You can now also do something like this:
function keyUpEvent(input, span){
var state = null;
return function(){
var test = input.val() === '';
if( test === state) return;
if(test)
span.html('My input is blank');
else
span.html('My input is not blank');
state = test;
}
}
$('#my_input').keyup( keyUpEvent($('#my_input'), $('#my_span')) );
$('#my_input2').keyup( keyUpEvent($('#my_input2'), $('#my_span2')) );
http://jsfiddle/TMb8T/2/
Like this you can easily check every input of a whole form with one single event handler.
Addition 2: If you want to make version 2 work even when the key is kept down ;)
Replace this:
$('#my_input').keyup( keyUpEvent($('#my_input'), $('#my_span')) );
With this:
$('#my_input').keydown(function(){
setTimeout(keyUpEvent($('#my_input'), $('#my_span')),1);
});
http://jsfiddle/TMb8T/4/
It really depends on how often you are executing the code. If it executes only when the user presses a button or something like that it would be fine to use the first one, it it runs on a quick timer then it might not.
Do like this:
var text;
if ( $('#my_input').val() == '' )
text = 'my input is blank';
else
text = 'My input is not blank';
if ( $(#my_span).html() != text )
$('#my_span').html(text);
Init:
var isBlank = true;
$('#my_span').html('my input is blank');
keyup:
if(!isBlank){
if( $('#my_input').val().length == 0){
isBlank = true;
$('#my_span').html('my input is blank');
}
} else {
if($('#my_input').val().length){
isBlank = false;
$('#my_span').html('my input is not blank');
}
}
This way you are only manipulating the DOM if the state changes.
Also testing the length property may actually be faster than testing the string against "", because the interpreter won't have to create a String object from the string literal.
You can simplify it with a ternary
$('#my_span').html( $('#my_input').val() == '' ? 'my input is blank' : 'My input is not blank' );
More readable
var text = $('#my_input').val() == '' ? 'my input is blank' : 'My input is not blank';
$('#my_span').html(text);
And it you care about speed, it es up is a DOM redraw faster that reading content. That really will depend on the page strucutre/size,browser. JSPerf is your friend if you want to see how many milliseconds you will save with 1000's of iterations. You really should be looking for the fastest if you see a performance problem.
- No Check, Writing content
- You have the penalty of updating the DOM if data changed or did not change
- Check, Writing content
- You have the penalty of reading the HTML
- You have penalty of updating DOM
- Check, no write needed
- You have the penalty of reading the HTML
Now Is the HTML most likely going to be different, the same, etc?
The solution depends on what you want to do. Caching the jQuery element will speed up the lookup/write. It will be slower than just a write.
How about saving the current value to a variable and just testing the variable to see if you have to change it. No messing with the DOM until you need to change it. (You could also use a boolean named isBlank
to get good effect here):
var currValue;
if ( $('#my_input').val() == '' ) {
if ( currValue != 'my input is blank' ) {
currValue = 'my input is blank';
$('#my_span').html(currValue);
}
} else if ( currValue != 'My input is not blank' ) {
currValue = 'My input is not blank';
$('#my_span').html(currValue);
}
You also mentioned this is in the keydown event handler.
- Don't forget to run this code one time at the start so it sets the display field to show the input field is blank to start with.
- Don't forget that the user can select the text and right click to choose 'cut' and empty the field or choose 'paste' to add text to the field. Similarly, a drag and drop action can conceivably add or remove text.
Alternate Train of Thought
You might be better off with periodic, timed event that checks. Some people can type bursts of keys around 3 or 4 a second. If you timed it to look at the field every 1 second, you could cut down the short term slowdown due to this code running and replace it with a long term constant use of CPU cycles. But remember that there is no reason to not use CPU cycles if the puter isn't doing anything interesting.
本文标签:
版权声明:本文标题:javascript - What is the most efficient way of toggling a DOM elements value based on the state of another element? - Stack Over 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741666418a2391335.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论