javascript/jQuery anonymous functions to populate an array - javascript

Hi I was just wondering if building an array in javascript was possible using a function like so. I have a variable that is getting the margins of a series of elements using $(ele).css('margin');. This returns a string of 0px 0px 0px 0px where I only want the left property to check whether it's been animated -= left.
I can do a similar function but I know there must be a better way. Here's my example:
var marginsLeft = new array();
$(ele).each(function(i){
var r = $(i).css('margin').split(" ");
marginsLeft[i]=r[3];
});
I'm not entirely sure how to simplify this, but I'm sure it's possible :) thanks in advance.

You can use $.map:
var marginsLeft = $(ele).map(function() {
return parseInt($(this).css('margin-left'), 10);
}).get();
Update: as pointed out by #undefined, if you want a regular array you should also call .get on the result. Otherwise, you'll have a jQuery wrapped array. It is array-like, so it can be used as an array in many contexts, but not in others (in particular, it may not have the native Array methods).
Also, to convert the result to a number you can use parseInt (which will ignore the letters and use only the digits), remembering to explicitate the base (10).

Have a look at the docs for .each(): The first parameter of the callback function is the index, the array element (DOM node) can be accessed either as the second parameter or the this value. So, use
var marginsLeft = []; // literal shortcut for "new Array()"
$(ele).each(function(i, el){
marginsLeft[i] = $(el).css('margin-left');
});
You also might have a look at the .map() method, but that returns a jQuery wrapper object instead of an array.

you could use css('margin-left') instead

Related

Slicing an object off of a jQuery collection [duplicate]

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();

referring the array with a dynamic string name

I have an array.
var ABCD=[{Key:"Milk",Value:"1" },{Key:"Bread",Value:"2" }];
now need to find using the key in this array (ABCD) using a dynamic string value (returned from a function myFunction("guest_user")). I am using something like this which is working in all the browsers apart from IE because of the eval() and would be great if someone can advise on this.
var entry = eval(myFunction("guest_user")).find(function(e) { return e.Key === "Milk"; });
the return value myFunction("guest_user") is ABCD which is the array name defined above.
myFunction is returning a request parameter .. .
function myFunction(key) {
var result = new RegExp(key + "=([^&]*)", "i").exec(window.location.search);
return result && unescape(result[1]) || "";
}
The issue in IE11 is not the eval() function. It's the find() method.
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find, and you'll see that find() is not supported in Internet Explorer.
You can, however, add the functionality to IE by using the Polyfill from the same link.
That said, it's best to avoid using eval() altogether. You can do so by placing your arrays in an object, such as:
var obj = {ABCD: [{Key ...}];
You can then reference the appropriate array by calling:
obj[myFunction("guest_user")].find(...
adding polyfill method (Adding a function to Array.prototype in IE results in it being pushed in to every array as an element ) and as Rick advised obj[myFunction("guest_user")].find( is working on IE.

Is there an equivalent of elem.innerHTML that gets the code in the tag body?

If I have the following:
<p class="demo" id="first_p">
This is the first paragraph in the page and it says stuff in it.
</p>
I could use
document.getElementById("first_p").innerHTML
to get
This is the first paragraph in the page and it says stuff in it.
But is there something simple you can run which would return as a string
class="demo" id="first_p"
I know I can iterate through all of the element's attributes to get each one individually but is there a function which returns tagHTML or something like that?
The following code is something of a mouthful: I wrote it as a one-liner, but I've broken it out into several lines here. But this will get you a plain object where the keys are attribute names and the values are the values of the corresponding attributes:
Array.prototype.reduce.call(
document.getElementById('first_p').attributes,
function (attributes, currentAttribute) {
attributes[currentAttribute.name] = currentAttribute.value;
return attributes;
},
{}
);
Going through this, document.getElementById('first_p').attributes gets you a NamedNodeMap of the element's attributes. A NamedNodeMap is not an Array, but Array.prototype.reduce.call(...) calls Array.prototype.reduce on the NamedNodeMap as if it were an Array. We can do this because NamedNodeMap is written so that it can be accessed like an array.
But we can't stop here. That NamedNodeMap that I mentioned is an array of Attr objects, rather than an object of name-value pairs. We need to convert it, which is where the other arguments to Array.prototype.reduce come into play.
When it's not being called in a strange way, Array.prototype.reduce takes two arguments. The second argument (which is third for us because of the way we called it) is an object that we want to build up. In our case, that's a brand-new bare object: the {} that you see at the end.
The first argument to Array.prototype.reduce (which, again, is second for us) is another function. That function will get called once for each item in the loop, but it takes two arguments. The second argument is the current loop item, which is easy to understand, but the first argument is a little wild. The first time we call that function, its first argument is the object we want to build up (i.e. the last argument to Array.prototype.reduce. Each time after that, the first argument is whatever that function returned the last time it was called. Array.prototype.reduce returns whatever the last call to its inner function returned.
So we start with an empty object. Then for every Attr in the element's attributes, we add something to the object, and return it. When the last call finishes, the object is finished, so we return that. And this is how we make the attribute list.
If you wanted the exact code in the tag, like a String, then I'm afraid there is no standard function to get that exactly. But we can get a close approximation of that code, with a similar setup:
Array.prototype.map.call(
document.getElementById('first_p').attributes,
function (currentAttribute) {
return currentAttribute.name + '=' + JSON.stringify(currentAttribute.value);
}
).join(' ');
The basic principle is the same: we take that NamedNodeMap and call an Array function on it, but this time we're using map instead of reduce. You can think of map as a special case of reduce: it always builds up an Array, with one element for every element that was in the original. Because of that, you don't even need to mention the object you're building up: the callback function only has one argument, and we just return the thing to put into the new Array. Once we're done, we have an Array of 'name="value"' strings, and then we just join that with ' '.
It isn't a built-in property, but you can use the array-like object attributes to obtain what you're looking for.
Array.prototype.map.call(element.attributes, function (el) {
return el.name + '="' + el.value + '"';
}).join(' ')
This is assuming a browser that supports the map function. The Array.prototype.map.call part is because attributes is not really an array and does not have a join method, but because it's an array-like JavaScript's dynamism allows us to call map on it anyway.
Example from the current page with the footer div:
var element = document.getElementById('footer')
Array.prototype.map.call(element.attributes, function (el) {
return el.name + '="' + el.value + '"';
}).join(' ');
// "id="footer" class="categories""
You can try the following:-
var attributes = '';
for(var i=0; i<document.getElementById("first_p").attributes.length; i++){
var attr = document.getElementById("first_p").attributes[i];
attributes += attr.nodeName+"='"+attr.nodeValue+"' "
}
console.log(attributes);
You can use document.getElementById("first_p").attributes to get an array of all the attributes on that DOM element
If you wanted them all in one string just do: document.getElementById("first_p").attributes.join(' ') to get the desired output
Well, while nothing currently exists to do this directly (though the approaches using the Node's attributes is a more reliable approach, one option is to create this method yourself:
HTMLElement.prototype.tagHTML = function(){
// we create a clone to avoid doing anything to the original:
var clone = this.cloneNode(),
// creating a regex, using new RegExp, in order to create it
// dynamically, and inserting the node's tagName:
re = new RegExp('<' + this.tagName + '\\s+','i'),
// 'empty' variables for later:
closure, str;
// removing all the child-nodes of the clone (we only want the
// contents of the Node's opening HTML tag, so remove everything else):
while (clone.firstChild){
clone.removeChild(clone.firstChild);
}
// we get the outerHTML of the Node as a string,
// remove the opening '<' and the tagName and a following space,
// using the above regular expression:
str = clone.outerHTML.replace(re,'');
// naively determining whether the element is void
// (ends with '/>') or not (ends with '>'):
closure = str.indexOf('/>') > -1 ? '/>' : '>';
// we get the string of HTML from the beginning until the closing
// string we assumed just now, and then trim any leading/trailing
// white-space using trim(). And, of course, we return that string:
return str.substring(0,str.indexOf(closure)).trim();
};
console.log(document.getElementById('test').tagHTML());
console.log(document.getElementById('demo').tagHTML());
JS Fiddle demo.

Mootools Selector issue

Right now I have a dynamic string that assigns it's values to a particular div class.
Output looks like this
<div class="12923"></div>
I want to find that 'randNumber' div, then check if it has another class 'x'
Currently what I have now doesn't work:
var randNumber = 12923
var lookingForYou = $$('.'+randNumber);
if (lookingForYou.hasClass('XCLASS')){alert('XCLASS FOUND!');}
$$ returns an Elements instance, Elements is an array-like Class
anyway since you are basically filtering, you can tell Slick that you need an element with both class:
var randNumber = 12923;
if($$('.' + randNumber +'.XCLASS').length>0){
alert('XCLASS FOUND');
}else{
//dostuff
}
or you could just use one of the Elements methods, I think .some will be your best choice here:
var randNumber = 12923
var lookingForYou = $$('.' + randNumber);
alert(lookingForYou.some(function(el){
return el.hasClass('XCLASS');
}))
EDIT:
adding some links:
A better way to use Elements on MooTools blog
in my second example I used the some method, which, by looking at the source is not overloaded, but is just the one in Array.prototype.some:
Element.js source reference
Array.some on MDN
$$ returns an array of all matching elems. Not sure if you can do a hasclass on an array. Might have to do a .each() then do it. Try $('body').getElement('.'+randNumber).hasClass('XCLASS') this way you grab 1 elem if you don't want to mess with the array.
Here:
if (lookingForYou.hasClass('XCLASS')){alert('XCLASS FOUND!');}
$$() returns an array, and hasClass() performs the check on each element of the array, returning an array of booleans. Unfortunately, when you check if (...), then the return array, even if all of the values are false, is evaluated as true because it's non-empty.

an array of strings as a jQuery selector? [duplicate]

This question already has answers here:
Easy way to turn JavaScript array into comma-separated list?
(22 answers)
Closed 6 months ago.
I have an array of strings that are valid jQuery selectors (i.e. IDs of elements on the page):
["#p1", "#p2", "#p3", "#p4", "#p5"]
I want to select elements with those IDs into a jQuery array. This is probably elementary, but I can't find anything online. I could have a for-loop which creates a string "#p1,#p2,#p3,#p4,#p5" which could then be passed to jQuery as a single selector, but isn't there another way? Isn't there a way to pass an array of strings as a selector?
EDIT: Actually, there is an answer out there already.
Well, there's 'join':
["#p1", "#p2", "#p3", "#p4", "#p5"].join(", ")
EDIT - Extra info:
It is possible to select an array of elements, problem is here you don't have the elements yet, just the selector strings. Any way you slice it you're gonna have to execute a search like .getElementById or use an actual jQuery select.
Try the Array.join method:
var a = ["#p1", "#p2", "#p3", "#p4", "#p5"];
var s = a.join(", ");
//s should now be "#p1, #p2, #p3, ..."
$(s).whateverYouWant();
What about $(foo.join(", "))?
Use the array.join method to join them together
$(theArray.join(','));
Going to officially answer your question: with a one-liner:
//If this is only one use variable you can use
$(['#p1','#p2','#p3','#p4','#p5'].join(',')).methodToUse();
//if you DO need it as a variable you can
var joined = ['#p1','#p2','#p3','#p4','#p5'].join(',');
$(joined).methodsToUse();
If you want them to do something individually there is also .each();
In the example below, each p ids clicks makes any one of them red:
var peas = ['#p1','#p2','#p3','#p4','#p5'];
$.each(peas, i => {
$(peas[i]).click(() => {
$(peas[i]).css({'color':'red'});
});
});
When you throw 'i' into a function parameter, it finds the values inside the arrays appropriately. When you do '.each()' the format looks like this:
$.each(array, function(i){
// any code you wish as long as you have an array selector
//$(array[i]).whatever function
});
An even bigger example. Say you want to make the P you click on red, but want the other ps return to default color. Just make a function that removes the selected ID from the array and voila!
var peas = ['#p1','#p2','#p3','#p4','#p5'],
poppy=(v,i)=>peas.toString().replace(`,${v[i]}`,'').replace(`${v[i]},`,'');
(// get each pea index
$.each(peas,i=>///funciton(i){ code inside}
(//set up each individual index's functions
$('.peastock').append(`<p id="p${[i+1]}">I am ${peas[i]}</p>`),
$(peas[i]).click(()=>(
$(peas[i]).css({"color":"red","background-color":"rgba(128,0,0,0.1)"}),
$(poppy(peas,i)).css({'color':'black','background-color':'rgba(255,255,255,0.2)'}))))),
$('.peastock').append(`
<div id="ree">ES6 isnt suitable for all of jQuery's usage!</div>
<div>Since some functions inside of jQuery's methods dont require 'this' or 'return'</div>
<div>You can learn this by going here</div>
`),
$("*").css({"margin":"0 auto","padding":"1%"}),
$("* .peastock, .peastock, .peastock *").css({"background-color":"rgba(128,0,0,0.1)"})
);
I know someone is bound to want to know about each value array as jquery selectors. Hope everything goes well!
Source:
jQuery .each()
The fiddle in action (with updates!)
I think you're looking for join.
var arr = ["#p1", "#p2", "#p3", "#p4", "#p5"];
$(arr.join(","))
Shorter:
$( ["#p1", "#p2", "#p3", "#p4", "#p5"].toString() );

Categories

Resources