Since I started using JQuery ive always wondering how does this operator work in JQuery
Example:
for(var i = 0;i<=4;i++)
{
document.getElementById("mydiv").innerText += i;//<- works as expected
}
//results will be 0,1,2,3,4
but if i use JQuery instead i dont know how to do it
for(var i = 0;i<=4;i++)
{
$("mydiv").text(+i)//<- NO!
$("mydiv").text+(i)//<- NO!
$("mydiv").+text(i)//<- JAJA COME ON!
$("mydiv").text(i)+//<- I guess that was stupid
}
This isn't possible like this. Unlike innerText, text() is a method, not a property.
Try:
$("mydiv").text($("mydiv").text() + i);
Or if you'd rather not make 2 references to $("mydiv") you can do:
$("mydiv").text(function(i,v){
return v + i;
});
You can't use such shorcuts for jQuery methods, it only works for native assignment operators. For jQuery .text(), use a callback:
$("#mydiv").text(function(index, oldtext) {
return oldtext + i;
});
This callback thing works for all jQuery property "assignments", be it .html, .val, .prop, .attr, .css, or .text.
You just need to work with jQuery here. Use the text method to extract the value, and then call it again to set the new value:
for(var i = 0;i<=4;i++)
{
var mydiv = $("mydiv"),
t = mydiv.text();
mydiv.text(t + i);
}
Like other answers point out, jQuery is just a framework and is subject to same syntactic rules as any JavaScript code.
While I see the advantage of passing in a function to .text(), I don't think it's a general purpose approach to solve your real problem : how to concatenate text when you use a function instead of a variable.
I'd favor the usage of Array.join() for efficient concatenation:
var textParts = [ $("mydiv").text() ];
for(var i = 0;i<=4;i++)
{
textParts[textParts.length] = i;
}
$("mydiv").text(textParts.join(',')) // result: '...,1,2,3,4'
If you prefer the function approach over a loop, you could also use Array.map().
AFAIK DOM functions are rather slow so it's more effective to do the concatenation first and then set the div node value.
jQuery is not a programming language but a library built upon javascript, so, the rules are exactly the same as those you have to follow using javascript, and javascript has not been designed to understand these kinds of structures.
Edit
Of course I mean o.m(+1) does not increment o.p while o.p++ and o.p+=1 does :
var o = {};
o.p = 1;
o.m = function () { return this.p; };
o.m(+1); // o.p equals 1
o.p++; // o.p equals 2
o.p+=1; // o.p equals 3
Related
In Javascript, arrays should have methods pop and shift.
However, JQuery objects seem to be missing these methods:
$('div').shift(); // Error, shift is undefined
$('div').pop(); // Error, pop is undefined
$('div').splice(); // Splice is OK actually
I wonder why these functions are missing - after all, the jquery object is just an array.
What's the easiest way of performing pop and shift functions on jquery objects?
They're missing because a jQuery object isn't an Array.
(function( $ ) {
$.fn.pop = function() {
var top = this.get(-1);
this.splice(this.length-1,1);
return top;
};
$.fn.shift = function() {
var bottom = this.get(0);
this.splice(0,1);
return bottom;
};
})( jQuery );
EDIT: .slice() doesn't modify the original object. Fixed to use .splice() instead.
Your safest bet would be to just use:
[].pop.call($('div'))
[].shift.call($('div'))
If you want to use the exact syntax in your example you can augment jQuery.fn:
jQuery.fn.pop = [].pop;
jQuery.fn.shift = [].shift;
The latter works well for the mutator methods. It'll work for the accessor and iteration methods too, but be advised that many of those returns a pure array that you'd have to rewrap. Be aware that jQuery has is own version of some of these (e.g. .map, .slice, .filter, etc.) that you probably don't want to overwrite.
This seemed to work for me:
var divArray = $('div').toArray();
var elem = $( divArray.shift() );
.toArray() return the DOM elements as a JavaScript Array, which can be used as intended. Then all you need to do is convert it back into a jQuery object.
I realize this answer has already been selected, but here's another alternative that isn't too hard to remember, in case you don't want to worry about having to install plugins all the time.
$('div > :first').detach(); // shift
$('div > :last').detach(); // pop
By the way, I realize there are performance issues with using :last selector as part of your primary selector so you may want to consider doing something like this for pop:
$('div').children(':last').detach();
var $firstDiv = $( $('div').splice(0, 1) );
Another way using jQuery 1.9.1+:
$('div').first().remove();
$('div').last().remove();
Is there a nice, clean way to concatenate a string and a variable into a variable name that Jade can understand?
Ideally, it would look something like this:
each #{shape + 'Text'} in #{shape + 'Texts'}
li #{shape + 'Text'}
I tried using window[shape + 'Text'] but that didn't seem to work. Maybe I was doing it wrong?
Here's why I want to do this:
I have an array called shapes that looks like this: ['square', 'triangle', 'circle']
I'm using Jade's each ... in ... function to iterate through this array. Within each iteration of my function, I need to do another each ... in ... of one of a few other arrays. Instead of using a straight-up variable to select which array to iterate over, like each shape in shapes, I want to concatenate shape with a string in order to get something like each squareText in squareTexts or each circleText in circleTexts.
Currently, I'm using conditionals to achieve my desired result, but it's verbose and not in the minimalist spirit of the language.
Thanks in advance for any advice.
So it looks like in my case, the trick is to use Javascript's eval() function to concatenate the variable name and the string into a new variable name. Here's my successful (and succinct) implementation.
- var items = eval(shape + 'Texts');
each item, i in items
li #{items[i]}
I'd suggest looking at an option to create/eval this out of Jade, keep the jade code (and any templare for this matter) as simple as possible.
You can wrap a variable and string in parentheses.
each item, i in items
li=(shape + 'Texts')
I am not exactly following what you are referring to since I don't know jade at all, but you would loop through an array like this.
var a = ['square', 'triangle', 'circle'];
var i, l, item;
l = a.length;
for (i = 0; i < l; i++) {
item = a[i];
// At this point, you can refer to window[item + 'Text']
// but I'm not sure what that is supposed to mean.
}
There is also an Array.prototype.every available, but I usually don't bother to monkeypatch it in to older browsers.
I want get my program parameters from rel attribute of element, first of all is it logical ?
and the rel attribute may contain this string rel="_p|b|w=300|h=200" or rel="_p|w=300"
, so I use split to split my string with | pattern :
var attr = $(this).attr('rel').split('|');
for _p and b there is no problem because I can check with indexOf but for w and h I should use regular expression because the w and h value will be change.
how can I use regular expression in indexOf ?
sorry for my bad English
EDIT:
if (attr.indexOf('b')) {
blank = true;
}
First of all, that isn't a very elegant way of retrieving data. Anyway, if you really want to do that in that way, then you can use regexes as follows:
var matches = $(this).attr('rel').match(/w=(\d+)/);
var w = (matches && matches[1]) || defaultValue;
Also, if there can be multiple elements that end in 'w', then you'd better change your regex to something like:
var matches = $(this).attr('rel').match(/(?:^|\|)w=(\d+)/);
I would have suggested the use of custom attributes as well, however these would not be w3-conform as you want them to.
A simple way would be to split the parameters and then loop through and check each index whether it is one of the attributes you are expecting:
var cust_params = $(this).attr('rel').split('|'); //or this.rel as GGG suggested in a comment?
for(var i=0;i<cust_params.length;i++) {
if('_p'==cust_params[i]) {
//...
}
//...
if(cust_params[i].match(/w=(\d+)/)) {
//you could even do this without a regular expression
}
}
I hope this doesn't violate some good practice that I'm unaware of because I always feel like there must be a more elegant way when I do this kind of thing :) As it is I get a kind of quick-and-dirty feel about this.
Sorry there is no way you can do it in one command with normal javascript, indexOf just doesn't support regular expression.
You can either loop through the array or use jquery supported command for array.
For example: once you have the array attr as you like, you can use jQuery.grep() http://api.jquery.com/jQuery.grep/
a_equal = jQuery.grep(attr, function(a, i){
return (a.match(/=/) and i > 0); // modify this as you like
});
to create an array a_equal with all the assignment argument.
disclaimer.. code not yet tested.
Like Paolo Bergantino I'd also suggest using data-attributes, or you could store the data in a JSON (again, in a data attribute) and parse that:
<a href="#" data-info='{"width": "300", "height": "200", "color": "#fff", "etc": "foo"}'>
var info = JSON.parse(a.getAttribute('data-info'));
Edit: replaced eval with Phrogz's suggestion.
(With eval: eval('(' + a.getAttribute('data-info') + ')'))
Is it possible to create your own custom, I believe the term is 'method'? For example, something like this:
var str = "test"
str.replaceSpecial();
where replaceSpecial() will automatically replace say, the letter e with something else.
The reason I'm interested in doing this is because what I want to do is grab strings and then run a large number of replace actions, so I'm hoping that when I call on replaceSpecial() it will run a function.
Thanks
You can add your methods to String.prototype which will become available to all strings. That is how trim() is implemented in most libraries for example.
String.prototype.replaceSpecial = function() {
return this.replace(/l/g, 'L');
};
"hello".replaceSpecial(); // heLLo
However, note that it is generally a bad practice to define very specific functionality on the native prototypes. The above is a good example of exactly the same problem. For such specific cases, consider using a custom function or wrapper to do the job.
function replaceSpecial(str) {
return str.replace(/l/g, 'L');
}
replaceSpecial("hello"); // heLLo
or under a custom namespace, for example.
var StringUtils = {
replaceSpecial: function(str) { .. },
..
};
StringUtils.replaceSpecial("hello"); // heLLo
I have a string which I need to split into an array and then perform mathematical functions on each element of the array.
Currently I am doing something like this. (Actually, I am doing nothing like this, but this is a very simple example to explain my question!
var stringBits = theString.split('/');
var result = parseInt(stringBits[0]) + parseInt(stringBits[3]) / parseInt(stringBits[1]);
What I would like to know is if there is a way I can convert every element of an array into a certain type that would stop me from having to explicitly parse it each time.
An easier method is to map to the Number object
result= stringBits.map(Number);
javascript 1.6. has map() ( https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/Map ), so you can do something like
intArray = someArray.map(function(e) { return parseInt(e) })
You can just loop through it:
for(var i = 0; i < stringBits.length; i++) {
stringBits[i] = parseInt(stringBits[i]);
}
["1","2"].map(Number)
result: [1,2]
If you add a plus (+) sign in front of your strings they should be converted to numeric.
For example, this will print 3:
var x = "1";
var y = "2";
alert((+x) + (+y));
But I am not sure if this is portable to all browsers.
Your code will become:
var stringBits = theString.split('/');
var result = (+stringBits[0]) + (+stringBits[3]) / (+stringBits[1]);
But this is just a hack, so use with care.
I think the parseInt states better what you are trying to do, but you should delegate this responsibility to another method that returns the final data that you need to process. Convert and then process, don’t convert while processing. Your code will be easier to read.