animation function is not applied to each elements - javascript

here is a problem i am facing in my progressbar. i have data-percent attribute in my "pro-bar" class . each data-percent is different but when in browser i'am getting first pro-bar's data-percent value applied to all
Here is my code:
$('.pro-bar').each(function( i, elem ){
var percent = $('.pro-bar').attr('data-percent'),
barparcent = Math.round(percent*5.56),
$elem = $(this);
console.log(percent);
$elem.animate({'width':barparcent}, 2000, 'easeInOutExpo');
});

Your problem is how you are referring to your pro-bar inside the each. Use "this" to refer to the current element, not a general class selector.
$('.pro-bar').each(function( i, elem ){
var percent = $(this).attr('data-percent'),//change here
barparcent = Math.round(percent*5.56),
$elem = $(this);
console.log(percent);
$elem.animate({'width':barparcent}, 2000, 'easeInOutExpo');
});
Further explanation:
$(".pro-bar").attr("data-percent") gets all of the .pro-bar, then .attr("data-percent") gets the value of the first element (as does most other similar jquery methods). Then as you loop through each element, this same effect is called multiple times.

Related

Trying to get width of element inside .each()

I am trying to get the width of an element whilst inside a .each() function however I am running into issues with it simply not working.
jQuery(document).ready(function($) {
$('.tooltip').each(function() {
var self = $(this);
var width = self.find("#testing").offsetWidth;
alert(width); //Returns undefined
$(this).find(".tooltip-icon").hover(function(){
self.find(".tooltip-text").show();
}, function () {
self.find(".tooltip-text").hide();
});
});
});
you are using jquery and javascript in the same line
do this
var width = self.find("#testing").width(); // jquery. you should change the name of the `self` variable to another one

...scrollTop($(this)...)

I have a few divs with the .class class whose scroll position is defined by another child of its parent, so I need to assign a scrollTop() with $(this), something like
$(".class").scrollTop($(this).parent().find('.child').scrollTop());
But that code doesn't work...
$(".class").scrollTop(
function(){
$(this).parent().find('.child').scrollTop()
}
);
Doesn't work either. Any clue?
This is assuming that I am reading your question right. You have mulitple "class" elements that have their own "child" elements. You would need to use each to set every element separately.
$(".class").each(
function(){
var elem = $(this);
var childsScrollPosition = elem.parent().find('.child').scrollTop();
elem.scrollTop(childsScrollPosition);
}
);
ScrollTop wants an integer for the position so passing the DOM node wont help.
Try caching your selector and pass it with the position method:
var scrollTo = $(this).parent().find('.child');
$(".class").scrollTop( scrollTo.position().top );
Or you use offset depending on your use case:
var scrollTo = $(this).parent().find('.child');
$(".class").scrollTop( scrollTo.offset().top );
I am doing this blind here but this should work too:
var scrollTo = $(this).parent().find('.child');
$(".class").scrollTop(
function() {
return scrollTo.offset().top;
}
);
Does this help?

Display order of Elements in a Loop

I have got 3 elements (#hotlink1Div, #topBarContentid, #hotlink2Div) which will be in a loop.
I have managed to find the code to get the loop online.
Currently the order in which they are appearing is: #topBarContentid, #hotlink1Div, #hotlink2Div
I would like to see the following order: #topBarContentid, #hotlink1Div, #topBarContentid, #hotlink2Div, #topBarContentid.
slideHotlinks: function () {
console.log(this.px + "Hotlinks started");
var $elements = $('#hotlink1Div, #topBarContentid, #hotlink2Div'); //List of elements used
function hotlinks_loop(index) { //Function to index elements as their are shown
console.log(this.px + "Hotlinks loop created");
$elements.eq(index).slideDown(1000, function() {
var $self = $(this);
setTimeout(function() {
console.log(this.px + "Hotlinks timeout set");
$self.fadeOut(1000);
hotlinks_loop((index + 1) % $elements.length);
},5000);
});
}
hotlinks_loop(0); // start with the first element
How about:
var elements = ['#pointsbarDiv', '#hotlink1Div','#pointsbarDiv', '#hotlink2Div'];
function anim_loop(index) {
$(elements[index]).slideDown(1000, function() {
var $self = $(this);
setTimeout(function() {
$self.fadeOut(1000);
anim_loop((index + 1) % elements.length);
}, 5000);
});
}
anim_loop(0); // start with the first element
Taken from an edit of the original jsbin: http://jsbin.com/uwonun/46
This uses a javascript array rather than a jquery selector. Each entry in the array is converted into a jquery object in the first line of the anim_loop function.
A jquery selector is not quite the same thing as a collection, instead it walks the dom of the page and returns elements that match it's expression, in the order they appear on the page. Therefore it is not possible to get a selector to return the same element twice. In addition id's within a page should be unique, so a selector should only return one element for each id.

jQuery: Removing Browser Generated Title Attribute

I'm attempting to remove the browser generated title box that appears with anchors that have a title attribute. The reason I want to do this is so it doesn't interfere with my tooltip jQuery.
As of right now I am removing the title attr on hover, but it won't reassign it after removing yourself from the hover state. How come?
http://jsfiddle.net/fj4xz/5/
Thats because the
var title
is in the HandlerIn function and not defined in the handler out.
Simplest solution is to put de var title outside of your hover function and assign it inside the hover handlers.
Edit: Removing the vars as stated by Photon is also a solution. I highly recommend you use vars though. Your code soon gets messy and unmaintainable if variables that are global are not defined. But thats just my opinion.
http://jsfiddle.net/RubenJonker/fj4xz/6/
That's because your title variable is within the mouseenter function, but you're using it inside mouseleave. You should move your title variable outside the hover method.
var title;
$('a.tooltip').hover(function() {
title = $(this).attr('title');
var offset = $(this).offset();
var width = $(this).outerWidth();
var height = $(this).outerHeight();
$content = $('<div class="tooltip">' + title + '</div>').fadeIn('fast');
$(this).append($content);
$(this).attr('title', '');
$content.offset({
top: offset.top + height,
left: offset.left + (width - $content.outerWidth()) / 2
});
}, function() {
$(this).find('div').fadeOut('fast');
$(this).attr('title', title);
});​
The reason why it won't re-assign the title value is because you're declaring the title variable in the first function, which is out of the scope of the second. If you want to preserve the original title value, you need to do so in such a way the second function has access to it.
Instead, try adding it to a data value:
$(this).data("originalTitle", $(this).attr("title"));
And then re-assign it within your second function:
$(this).attr("title", $(this).data("originalTitle"));
I would avoid having a generic title variable floating around that you're setting and getting for n links on the page. Storing the values as data on the element itself seems like a far better approach to me.
You're declaring var title = $(this).attr('title'); in your first function there, but your second function has no knowledge of title.
just remove all var declarations before variable name
it will become global variable See this
$('a.tooltip').hover(function() {
title = $(this).attr('title');
offset = $(this).offset();
width = $(this).outerWidth();
height = $(this).outerHeight();
$content = $('<div class="tooltip">' + title + '</div>').fadeIn('fast');
$(this).append($content);
$(this).attr('title', '');
$content.offset({ top: offset.top+height, left: offset.left+(width-$content.outerWidth())/2 });
}, function() {
$(this).find('div').fadeOut('fast');
$(this).attr('title', title);
});​

Getting initial selector inside jquery plugin

I got some help earlier regarding selectors, but I'm stuck with the following.
Lets say you have a plugin like this
$('#box').customplugin();
how can I get the #box as a string in the plugin?
Not sure if that's the correct way of doing it, and any other solution would be great as well.
Considering #box is a select dropdown,
The problem I'm having is if I do the regular javascript
$('#box').val(x);
The correct option value gets selected,
but if i try the same inside a plugin
.....
this.each(function() {
var $this = $(this);
$this.val(x);
the last code doesn't really do anything.
I notice I'm having trouble targeting #box inside the plugin because it's a object and not a string...
Any help would be appreciated.
Thanks!
Edit:: Putting in the code I'm working in for better understanding
(function($){
$.fn.customSelect = function(options) {
var defaults = {
myClass : 'mySelect'
};
var settings = $.extend({}, defaults, options);
this.each(function() {
// Var
var $this = $(this);
var thisOpts = $('option',$this);
var thisSelected = $this[0].selectedIndex;
var options_clone = '';
$this.hide();
options_clone += '<li rel=""><span>'+thisOpts[thisSelected].text+'</span><ul>'
for (var index in thisOpts) {
//Check to see if option has any text, and that the value is not undefined
if(thisOpts[index].text && thisOpts[index].value != undefined) {
options_clone += '<li rel="' + thisOpts[index].value + '"><span>' + thisOpts[index].text + '</span></li>'
}
}
options_clone += '</ul></li>';
var mySelect = $('<ul class="' + settings.myClass + '">').html(options_clone); //Insert Clone Options into Container UL
$this.after(mySelect); //Insert Clone after Original
var selectWidth = $this.next('ul').find('ul').outerWidth(); //Get width of dropdown before hiding
$this.next('ul').find('ul').hide(); //Hide dropdown portion
$this.next('ul').css('width',selectWidth);
//on click, show dropdown
$this.next('ul').find('span').first().click(function(){
$this.next('ul').find('ul').toggle();
});
//on click, change top value, select hidden form, close dropdown
$this.next('ul').find('ul span').click(function(){
$(this).closest('ul').children().removeClass('selected');
$(this).parent().addClass("selected");
selection = $(this).parent().attr('rel');
selectedText = $(this).text();
$(this).closest('ul').prev().html(selectedText);
$this.val(selection); //This is what i can't get to work
$(this).closest('ul').hide();
});
});
// returns the jQuery object to allow for chainability.
return this;
}
Just a heads-up: .selector() is deprecated in jQuery 1.7 and removed in jQuery 1.9: api.jquery.com/selector.
– Simon Steinberger
Use the .selector property on a jQuery collection.
Note: This API has been removed in jQuery 3.0. The property was never a reliable indicator of the selector that could be used to obtain the set of elements currently contained in the jQuery set where it was a property, since subsequent traversal methods may have changed the set. Plugins that need to use a selector string within their plugin can require it as a parameter of the method. For example, a "foo" plugin could be written as $.fn.foo = function( selector, options ) { /* plugin code goes here */ };, and the person using the plugin would write $( "div.bar" ).foo( "div.bar", {dog: "bark"} ); with the "div.bar" selector repeated as the first argument of .foo().
var x = $( "#box" );
alert( x.selector ); // #box
In your plugin:
$.fn.somePlugin = function() {
alert( this.selector ); // alerts current selector (#box )
var $this = $( this );
// will be undefined since it's a new jQuery collection
// that has not been queried from the DOM.
// In other words, the new jQuery object does not copy .selector
alert( $this.selector );
}
However this following probably solves your real question?
$.fn.customPlugin = function() {
// .val() already performs an .each internally, most jQuery methods do.
// replace x with real value.
this.val(x);
}
$("#box").customPlugin();
This page talks about getting the selector:
http://api.jquery.com/selector/
That's how I get selector strings inside my plugins in 2017:
(function($, window, document, undefined) {
$.fn._init = $.fn.init
$.fn.init = function( selector, context, root ) {
return (typeof selector === 'string') ? new $.fn._init(selector, context, root).data('selector', selector) : new $.fn._init( selector, context, root );
};
$.fn.getSelector = function() {
return $(this).data('selector');
};
$.fn.coolPlugin = function() {
var selector = $(this).getSelector();
if(selector) console.log(selector); // outputs p #boldText
}
})(jQuery, window, document);
// calling plugin
$(document).ready(function() {
$("p #boldText").coolPlugin();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>some <b id="boldText">bold text</b></p>
The idea is to conditionally wrap jQuery's init() function based on whether a selector string is provided or not. If it is provided, use jQuery's data() method to associate the selector string with the original init() which is called in the end. Small getSelector() plugin just takes previously stored value. It can be called later inside your plugin. It should work well with all jQuery versions.
Because of the deprecation and removal of jQuery's .selector, I have experimented with javascript's DOM Nodes and came up with a 2017 and beyond solution until a better way comes along...
//** Get selector **//
// Set empty variables to work with
var attributes = {}, // Empty object
$selector = ""; // Empty selector
// If exists...
if(this.length) {
// Get each node attribute of the selector (class or id)
$.each(this[0].attributes, function(index, attr) {
// Set the attributes in the empty object
// In the form of name:value
attributes[attr.name] = attr.value;
});
}
// If both class and id exists in object
if (attributes.class && attributes.id){
// Set the selector to the id value to avoid issues with multiple classes
$selector = "#" + attributes.id
}
// If class exists in object
else if (attributes.class){
// Set the selector to the class value
$selector = "." + attributes.class
}
// If id exists in object
else if (attributes.id){
// Set the selector to the id value
$selector = "#" + attributes.id
}
// Output
// console.log($selector);
// e.g: .example #example
So now we can use this for any purpose. You can use it as a jQuery selector... eg. $($selector)
EDIT: My original answer would only get the attribute that appears first on the element. So if we wanted to get the id that was placed after the class on the element, it wouldn't work.
My new solution uses an object to store the attribute information, therefore we can check if both or just one exists and set the required selector accordingly. With thanks to ManRo's solution for the inspiration.

Categories