Jquery each inside each affects only the last element - javascript

I have problem with nested loops. Please take a look on the fiddle below:
http://jsfiddle.net/7znfmp9o/
I want each section to get parallax effect however something strange is going on here. .each() code is applied only for last element within the loop.
Changing this line:
$bgElm = $(this).find('.swiper-slide-bg, .mk-section-video')
into this:
$bgElm = $('.parallax-true').eq(0).find('.swiper-slide-bg, .mk-section-video')
runs the snippet on desired section, however iteration on .eq(i) doesn't work either, even within closure:
(function(i){ ... })(i);
What am I missing here? Thx for your help

The problem is due to this line:
$bgElm = $(this).find('.swiper-slide-bg'),
You are setting the contents of this internal variable every time the first forEach occurs. When the event is raised the value of this is the last element in the forEach loop. You should move these variables outside of the forEach loop and append elements into it. Then once the event is raised for loop on the elements within this variable.
I put together a VERY crude implementation of what I am proposing. While it works, you should reorganize the data structures and give proper naming to help describe your intentions. For instance, $bgElm is a poor variable choice for a variable describing the set of parallax-ed elements.
http://jsfiddle.net/myqswjnt/

Related

Javascript setAttribute confusion

I was using the setAttribute method and noticed that if I use it consecutively, only the first time I use it the DOM elements changes, whereas the second time it doesn't work. And i don't understand why.
example, if i write this:
grid.setAttribute("style", `grid-template-rows:repeat(auto-fill,${width/size}px);`);
grid.setAttribute("style", `grid-template-columns:repeat(auto-fill,${width/size}px);`);
only the grid-template-rows changes.
But if i put it all in one line like this:
grid.setAttribute("style", `grid-template-columns:repeat(auto-fill,${width/size}px); grid-template-rows:repeat(auto-fill,${width/size}px);`);
then both values change, which gives the desired outcome.
Can anyone explain me why the first instance doesn't work?

Detect array mutation

I have made a simple proof-of-concept Polymer 1.0 app that demonstrates my problem: JSBin.
In my problem, I am using array mutation methods to alter the array, which contains the list of shopping items.
However, this doesn't seem to work as intended. I do get a change in dom-repeat and when printing the length of the array. But I do not get the change event when I am printing the array itself nor when I wrap it in a function.
In short, why does this work?
<p>Number of items: [[list.length]]</p>
And why does this not work?
<p>Items inline: [[list]]</p>
<p>Observe function : [[_observe(list)]]</p>
Also, when I uncomment the following line (in the JSBin), things seem to work as indened. But I don't like it since it's a bit hackish.
app.notifyPath('list', app.list.slice());
I have stumbled upon the slice() fix by reading this issue: https://github.com/Polymer/polymer/issues/2068
EDIT
So, after reviewing the comments, the answer to the question "Is this by design" is YES. The array itself doesn't change (since it's only a reference), but it's property do change. That's why the slice() forces the reload since it creates a shallow copy.
However, one could argue whether this is OK. Yes, the variable list does not change per se. But putting [[list]] in the HTML code actually triggers toString(). And result of that function has changed.
I guess I'm stuck with piggybacking the length property for now...
As alluded to in the comments the notifyPath and slice calls are creating a shallow copy of the array and assigning a different reference back to the list variable - triggering an update of the binding. Without maintaining a separate (watchable) variable or messing around with object references, the only other workaround I can think of would be to piggy back on the list.length property instead of the list itself and pass that through some kind of "formatting" function. e.g.
<p>Items inline: [[format(list.length)]]</p>
app.format = function(){
return app.list.toString();
};
» Fiddle
As pointed out by #zb you could expand on this and make the function reusable with any array by passing the relevant variable as an argument too:
<p>Items inline: [[format(list, list.length)]]</p>
app.format = function(list){
return list.toString();
};
» Fiddle

Strange knockout js select option binding issue

Does anybody have a minute to take a look at a puzzling problem I'm having with Knockout JS and binding select lists?
The person's favourite color should be selected in the list by calling value: favColorId in the select list, rather than with the function-based call of value: favColorId(), something very strange is going on here, I've never used () in the past, it's also causing some other weird issues where it won't recall the value into the span (so changing the selected item does nothing).. I have tried recreating a simple sample as best I can demonstrating the issue.
http://jsfiddle.net/goneale/ph8Jw/
I have included my mapDictToArray() function but it simply converts a
javascript object into a key-value JS array. I wouldn't think that is
contributing to the problem.
Actually, that was part of the problem. The function returns a JavaScript array, not an observable array and therefor can't be used properly by Knockout. I've made the following changes to your code:
// The "mapDictToArray" makes a normal JS array, not a ko.observableArray();
// You can't simply "merge" a JS array with an observableArray(); you'll need
// some extra functionality for that: ko.utils.arrayPushAll()
// viewModel.colors(mapDictToArray(dict));
ko.utils.arrayPushAll(viewModel.colors(), mapDictToArray(dict));
// Apply the bindings *after* you've added the contents to the "colors" observable, in order to
// get the correct selected value
ko.applyBindings(viewModel);
That should do the trick (with the correct HTML without the () )!
JSFiddle.
UPDATE
I thought about my solution, but something wasn't correct. The only thing that was correct, was the part that you need to apply the bindings after you've added the contents of the colors observable. This is your fiddle, with that part moved down.
This works in your case, but you'll need to use the arrayPushAll method when there is already data inside the observableArray. This method merges, while you overwrite it when not using it (example with data inside the observable).

Declaring a var instead of using .find multiple times?

I have been reading on best practices and I have come across this one:
Dont do this:
$("#element .child").hide()
Do this:
$("#element").find('.child').hide()
Now my question is what if i want to hide/show the .child element multiple times, should I declare it like this:
var spinner = $("#element").find('.child');
spinner.hide();
or do I just keep calling $("#element").find('.child').hide()
Should I declare it like this:
var spinner = $("#element").find('.child');
spinner.hide();
Yes. You should do exactly that since it will obviate the need for multiple dom queries.
One common best practice though, so you can easily keep track of which variables are jQuery objects and which are not, is to prefix your variable with $
var $spinner = $("#element").find('.child');
$spinner.hide();
Yes, create the spinner variable. That way the jQuery constructor/function won't be executed each time, you can reuse the once created objects. The memory overhead is negligible.
That's entirely depending of your problem, if you need to use the same element for multiples purposes in different function, the best options will be to save it into a variable, never the less if you only need once work with chaining of events
Yes, you should always try to keep your selections low, which means that you should save every element selection in a variable that you need more then once.
Try to avoid single DOM operations, also. Let me provide an example:
jQuery('#test').addClass('hide');
jQuery('#check').addClass('hide');
This will add the class "hide" to elements with the id "#test" or "#check". You can apply many jQuery functions like .addClass on element collections also, which will reduce overhead (instead for example iterating over an array / collection with jQuery.each()).
// Select both ids within one query
jQuery('#test, #check').addClass('hide');
This can lead to a huge performance boost if you are really working with the DOM, like adding options to a select box. I've put up a little benchmark on jsfiddle: http://jsfiddle.net/rrgNZ/2/

Most efficient way to re-use jQuery-selected elements

I can imagine the correct answer to this based on theory, but I'm just looking for some confirmation. I'm wondering what the most efficient way to re-use a jQuery-selected element is. For example:
$('#my_div').css('background','red');
//some other code
$('#my_div').attr('name','Red Div');
vs.
myDiv = $('#my_div');
myDiv.css('background','red');
//some other code
myDiv.attr('name','Red Div');
I assume the second example is more efficient because the element #my_div doesn't have to get found more than once. Is that correct?
Similarly, is it more efficient to first save $(this) in a varaible, such as 'obj', and then reuse 'obj' rather than using $(this) over and over? In this case, jQuery isn't being forced to find an element over and over again, but it IS being forced to convert this to a jQuery object [$(this)]. So as a general rule of thumb, should a jQuery object ALWAYS be stored in a variable if it will be used more than once?
You should write your code such that you limit the number of DOM traversals.
When you write something like this:
$('#my_div').css('background','red');
//some other code
$('#my_div').attr('name','Red Div');
You are finding #my_div twice, which is inefficient.
You can improve this either by assigning the result of a selector (i.e. var x = $('.something')) and manipulate the variable x, or you can chain your method calls like this:
$('#my_div').css('background','red').attr('name','Red Div');
You'll see the above code used a lot, because you're finding the element once. The css() method will apply a CSS style and return the actual result of $('#my_div'), so you can invoke another method, in this case attr().
My preferred way of handling the re-use of selectors is to store them as a variable, and wrap my stuff in a closure.
if you're using jQuery selector (like $('#element')), then yes, you should always store your results.
if you're using object and wrapping it in jQuery (like $(this)), it's not necessary, because jQuery doesn't need to search for that element again.
One thing that I find is generally overlooked is just how powerful jQuery chains are. It may not be so noticeable, but since jQuery caches your wrapped elements within a chain, you can modify elements, go into a more specific subset, modify, then go back up into a a general superset without much overhead.
I expect something like (pardon the example)
$('#myDiv')
.addClass('processing')
.find('#myInput')
.hide('slow')
.end()
.removeClass('processing')
;
to be better performance-wise than even
var $myDiv = $('#myDiv').addClass('processing');
var $myInput = $('#myDiv #myInput').hide('slow');
$myDiv.removeClass('processing');
This also holds for applying the jQuery function to elements returned in an event handler. Try to avoid applying $(...) too many times, because this is slow. Instead create a variable that contains the result of $(...). Good practice is to start the variable with a $, which gives a hint about the jQuery object inside the variable.
$('a').click(function(){
var $this = $(this);
$this.addClass("clicked");
$this.attr("clicked", true);
});

Categories