Stop jQuery step animation with inline object as target - javascript

Consider the following jQuery:
$({x: startX}).animate({x: endX}, {
duration: 100,
step: function(now, fx) {
xVar = now;
}
});
Is it possible to stop this animation before calling it again? I've tried
$({x: startX}).stop().animate(...)
but that doesn't seem right, and doesn't seem like it's working either. Any thoughts?
Thanks!

From the jQuery documentation, you can't use .animate() on a jQuery object that you just passed an object to. A relevant quote from this page:
Working With Plain Objects
At present, the only operations supported on plain JavaScript objects wrapped
in jQuery are: .data(),.prop(),.on(), .off(), .trigger() and .triggerHandler().
The use of .data() (or any method requiring .data()) on a plain object will
result in a new property on the object called jQuery{randomNumber}
(eg. jQuery123456789).
So, my conclusion is that this construct isn't supported:
$({x: startX}).animate(...)

Related

Why can't you call outerHTML on $(this)?

When you want to get the HTML of an entire DOM element (wrapper included), you can do the following (as explained here):
$('#myElementId')[0].outerHTML
But what you can't do is call outerHTML on $(this) inside e.g. a click listener or selector function body scope:
$(this).outerHTML //Doesn't complete in IntelliSense, returns undefined in browser
or
$(this)[0].outerHTML //Correction, this DOES work, but it doesn't complete in IntelliSense
because IntelliSense won't show innerHTML or outerHTML in those circumstances, although with vanilla JavaScript you can do:
document.getElementById($(this).attr('id')).outerHTML
So... what's up with that?
outerHTML is a DOM property; jQuery doesn't expose all DOM properties.
If you have a jQuery object, you can only directly access those properties and methods that jQuery exposes, and vice versa for DOM objects.
In object-oriented terms, jQuery objects don't inherit from DOM objects, they contain them.
Saying $x[0] gets you the DOM object for the first element represented by a jQuery object.
You can use directly this to access outerHTML of the current object instead of indirectly going through $(this) as this represents the DOM object (which has outerHTML property) whereas $(this) represents jQuery object.
this.outerHTML
jQuery selector returns an array-like jQuery object which has no outerHTML property.
However, the jQuery resulting array contains DOM elements.
It means that you can actually access it this way.
$(".someClass")[0].outerHTML // it works for me
Update:
It works for me in every browser.
I can access array-like jQuery object in a click event handler as well.
$(".someClass").click(function()
{
alert($(this)[0].outerHTML); // it works me too
});
Here is my JSFiddle: http://jsfiddle.net/13btf60p/
Update 2:
OK, now I get your question. It should have worked.
Do you really need an IntelliSense to complete such a plain and simple construction?
I will add what I found to be the correct solution to what ended up being a simple flaw in the default Visual Studio settings for future reference.
Since I didn't want to let this go, I searched further and found out that, by default, jQuery IntelliSense is somewhat deplorable out of the box in Visual Studio 2013.
Under
Tools > Options > Text Editor > Javascript > IntelliSense > References
I set
Reference Group: "Implicit (Web)"
and added an existing jQuery file. This solved all issues of my question and IntelliSense now suggests all members and methods correctly, although this should have simply worked out of the box instead of costing everyone a bunch of time.
this.outerHTML is enough.
If you use getElementById maybe you can use:
var table = document.getElementById('blablabla');

What does $($(this)) mean?

I saw some code around the web that uses the following statement
if ($($(this)).hasClass("footer_default")) {
$('#abc')
.appendTo($(this))
.toolbar({position: "fixed"});
}
What is the use of $($(this)) and why is that necessary here?
Yes, $($(this)) is the same as $(this), the jQuery() or $() function is wonderfully idempotent. There is no reason for that particular construction (double wrapping of this), however, something I use as a shortcut for grabbing the first element only from a group, which involves similar double wrapping, is
$($('selector')[0])
Which amounts to, grab every element that matches selector, (which returns a jQuery object), then use [0] to grab the first one on the list (which returns a DOM object), then wrap it in $() again to turn it back into a jQuery object, which this time only contains a single element instead of a collection. It is roughly equivalent to
document.querySelectorAll('selector')[0];, which is pretty much
document.querySelector('selector');
You can wrap $ as many times as you want, it won't change anything.
If foo is a DOM element, $(foo) will return the corresponding jQuery object.
If foo is a jQuery object, $(foo) will return the same object.
That's why $($(this)) will return exactly the same as $(this).
There is no specific need for double-wrapping and $($(this)) is exactly the same as $(this).
That said, I once found this double-wrapping in one file in my project, committed by another developer. Tracking the changes through revision, turned out that it started as $($(this).find('selector').first()) - that is, the result of some selector was wrapped to create a new object. Then for whatever reasons, the selector was removed and only the double-wrapping of this remained. Needless to say, on the next commit it was changed to $(this).
As explained before me, $($(this)) and $(this) are absolutely identical. jQuery returns the same jQuery object if you try to wrap it more than once.
Additionally, for performance considerations it is a good practice to reuse jQuery objects - it is quite expensive to create jQuery objects, especially the ones with complex selectors. Example:
var $this = $(this);
if ($this.hasClass("footer_default")) {
$('#abc')
.appendTo($this)
.toolbar({position: "fixed"});
}
Just google for 'jQuery best practices' - it will take a 30 min for you to learn these basics and you will use jQuery way more effectively.
There is no meainig of doing that.
The following code return the same:
console.log($($(this)).hasClass("footer_default"))
console.log($(this).hasClass("footer_default"))
a boolean value depenging on if the selected element has or not the class footer_default:
.hasClass( className )Returns: Boolean
Demo: http://jsfiddle.net/IrvinDominin/aSzFn/
$(this) and $($(this)) both return jquery object.
There is no difference between these two.

Can JQuery and Javascript be mixed together?

I am wondering if I could use query and javascript together so I could select an element by class with the javascript and then use javascript to work on that element. Sorry if that didn't make sense. Here is an example:
$('.nav_flag').src = "images/flags/"+userCountryLower+".gif";
Would that work, if not how do I get an element by class using regular javascript. Thanks!
EDIT:I know JQUERY is JavaScript but I was wondering if I could mix jquery selectors and javascript 'controller'-for a loss of a better word
To answer your question as asked, there are several ways to take a jQuery object, i.e., what is returned by $('some selector'), and get a reference to the underlying DOM element(s).
You can access the individual DOM elements like array elements:
// update the src of the first matching element:
$(".nav_flag")[0].src = "images/flags/"+userCountryLower+".gif";
// if you're going to access more than one you should cache the jQuery object in
// a variable, not keep selecting the same thing via the $() function:
var navFlgEls = $(".nav_flag");
for (var i = 0; i < navFlgEls.length; i++) { ... }
But you wouldn't manually loop through the elements when you can use jQuery's .each() method, noting that within the callback function you provide this will be set to the current DOM element:
$(".nav_flag").each(function() {
this.src = "images/flags/"+userCountryLower+".gif";
});
However, jQuery provides a way to set attributes with one line of code:
$(".nav_flag").attr("src", "images/flags/"+userCountryLower+".gif");
To answer the second part of your question, doing the same thing without jQuery, you can use .getElementsByClassname() or .querySelectorAll() if you don't care about supporting older browsers.
jQuery IS Javascript. You can mix and match them together. But you better know what you're doing.
In this case, you probably want to use .attr function to set value of attribute.
Use .attr() in jQuery, rather than mix the two here.
$('.nav_flag').attr('src', "images/flags/"+userCountryLower+".gif");
In many instances, it is fine to mix jQuery with plain JavaScript, but if you have already included the jQuery library, you might as well make use of it. Unless, that is, you have an operation which in jQuery would be more computationally expensive than the same operation in plain JavaScript.
You can do it with jQuery too:
$('.nav_flag').attr("src", "images/flags/"+userCountryLower+".gif");
keep in mind that jQuery is simply a library built upon javascript.
for any jQuery object, selecting its elements by subscription will return the corresponding dom element.
e.g.
$('#foo')[0] // is equivalent to document.getElementById('foo');
You need to add an index to the jQuery object to get the native Javascript object. Change:
$('.nav_flag').src = "images/flags/"+userCountryLower+".gif";
To:
$('.nav_flag')[0].src = "images/flags/"+userCountryLower+".gif";
To get elements by class name in Javascript you can use:
document.getElementsByClassName( 'nav_flag' )[0].src = "images/flags/"+userCountryLower+".gif";
To answer your question, you could use .toArray() to convert the jQuery object into an array of standard DOM elements. Then either get the first element or loop through the array to set all the elements with the class.
However, you could do this easier with pure jquery with attr or prop depending on the version:
$('.nav_flag').attr("src", "images/flags/"+userCountryLower+".gif");
Or use pure javascript:
if (navFlagElements = document.getElementsByClassName("nav_flag") && navFlagElements.length > 0) {
navFlagElements[0].src = "images/flags/"+userCountryLower+".gif"
}

jQuery duration method

Currently I am working on an plugin for jQuery. In some jQuery functions you can pass an duration (e.g. '500ms', '1s', 'fast') parameter in.
I suppose there is a function within jQuery which pares that value and returns a value in ms? (so 1s would return 1000 or something).
Which method would this be, and is it possible to use this in my own plugin? So I can fire an callback after '1s' or 'fast' like some other methods as animate currently does.
You can always have a look at the source code. There you can see that .animate() calls a method jQuery.speed which uses jQuery.fx.speeds:
speeds: {
slow: 600,
fast: 200,
// Default speed
_default: 400
},
jQuery.speed seems to be useful in this regard, though I don't see any code which converts '1s' into 1000. Are you sure jQuery is doing this?
let's take a look at jquery source :
speeds: {
slow: 600,
fast: 200,
// Default speed
_default: 400
},
So, how about slow fadeOut ? let's take a peek into the source again. It looks like 'fadeOut' is just a shortcut for custom animation. There is a nice generic block of logic that jQuery re-uses for that purpose. There's no point in pasting the whole source in here :) you can easily go to your project a see for your self.
You could implement this very easily on your own
function ms(s){
return parseInt(s) *1000;
}
alert(ms("20s")); #=> 20000
Aside from that, using 1000 compared to '1s' is hardly an inconvenience. The integer has additional benefits as it's easier to modify in a programmatic way using simple arithmetic.

mootools 1.12 to 1.25 update script difficulties

hi i have a mootools script that works in version 1.12 but i want to update to 1.25 and it throws an error.
here is the script:
window.addEvent('load', function() {
Array.extend({
equalize: function(){
maxHeight = [];
this.each(function(el){
maxHeight.push(el.getSize().size.y);
});
this.setStyle('height', Math['max'].apply(Math, maxHeight));
}
});
$$('#col1,#col2,#col3,#col4,#col5').equalize();
$$('.column,.general').equalize();
});
pretty simple but i dont know what i need to do to update it for the newer version of mootools. the error in ie9 is the following:
Error Message: Object doesn't support property or method 'equalize'
You want to use implement instead of extend. Extend only adds a static method whereas implement alters the prototype of the Class.
That being said, you would probably want to use Elements instead of Array as equalize makes no sense for an untyped array (Elements can be considered an array that is only filled with Element items)
tl;dr: your code should read Elements.implement instead of Array.extend
In MooTools 1.2+ there's no size object of the getSize() method, so: el.getSize().size.y becomes el.getSize().y.
Example: http://jsfiddle.net/wagEJ/

Categories

Resources