Multiple positions of an array - javascript

How can I reference more then one position of an array?
Something like this
$("#reset").click(function() {
$("form")[0, 2].reset();
});

If you're just using jQuery, you can do this all in a selector.
$("#reset").click(function() {
$("form:eq(0), form:eq(2)").reset();
});
EDIT: Using filter to do this would be better (thanks #Gumbo):
$("#reset").click(function() {
$("form").filter(":eq(0),:eq(2)").reset();
});

A multi-dimensional JavaScript array would be referenced like myArray[i][j] (e.g. myArray[0][2]). Your code example doesn't seem to make sense though.

The simplest way is to just do this:
$("form")[0].reset();
$("form")[2].reset();
or, a little more efficiently:
var forms = $("form");
forms[0].reset();
forms[2].reset();
A nicer way would be to put a common class "myClass" on each of those two forms and do it like this:
$("form.myClass").each(function() {this.reset();});

How about saving your selector to a variable and then looping about indizes?
var form = $('form');
[1, 2].each(function(value, index) {
form[value].reset();
});

Related

How to convert object into array in angularjs Ionic

Let's say I have an object that looks like this: {first: "asdasd", second: "asdas", third: "dasdas", four: "sdasa"}
I need to convert this object into array.
if(values){
var first=values.first;
var second=values.second;
var third=values.third;
var four=values.four;
var five=values.five;
var six=values.six;
var seven=values.seven;
var eight=values.eight;
var nine=values.nine;
var ten=values.ten;
if(first){
userData.push(first);
}
if(second){
userData.push(second);
}
if(third){
userData.push(third);
}
if(four){
userData.push(four);
}
if(five){
userData.push(five);
}
if(six){
userData.push(six);
}
if(seven){
userData.push(seven);
}
if(eight){
userData.push(eight);
}
if(nine){
userData.push(nine);
}
if(ten){
userData.push(ten);
}
console.log(userData);
I am currently doing by this code but i think it is the wrong approach. So how could i change this to array that looks like ["asdasd", "asdas", "dasdas", "sdasa", "asdasd", "asdas", "dasdas", "sdasa"].
In ionic drag and drop directive doesnot work when i use object in ng-repeat.And works perfectly when i apply array to ng-repeat.
There are several ways you could do it.
One would be using Object.keys:
Object.keys(values).forEach(function(key) {
userData.push(values[key]);
});
You could also use for ... in like this:
for (var key in values) {
userData.push(value[key]);
}
If your object has any properties inherited from prototype then it would also show, so you do need to check if property really belongs to this instance:
for (var key in values) { //proper way to iterate keys using for..in
if(values.hasOwnProperty(key)) {
userData.push(value[key]);
}
}
Since you're using angular, you could also use angular.forEach:
angular.forEach(values, function(value){
userData.push(value);
});
and I think this is the cleanest solution for you.
I would suggest using javascript library underscorejs or lodash for this kind of array and objects manipulation and iteration ,as it seems to be most preferable way of doing it ,keeping your code clean.
Its a simple javascript file that you can include in your project and you don't have to do any complex thing to make it work.Just plug and play.
If you do include underscore/lodash ,all you have to do is :-
var mycoll = _.values(yourobjectvariable);
This will fetch all the values in that object and convert it into an array automatically for you.
http://underscorejs.org/#values
Or if you want to do it with plain javascript , i think the above Randall Flag's answer is suffice for it.
`
if(values)
{
Object.keys(values).forEach(function(key) {
userData.push(values[key]);
});
}
`
Sometimes instead of a simple solution we think too much and end up with complex time taking solution ,which we can achieve with small simple code

Select tags that starts with "x-" in jQuery

How can I select nodes that begin with a "x-" tag name, here is an hierarchy DOM tree example:
<div>
<x-tab>
<div></div>
<div>
<x-map></x-map>
</div>
</x-tab>
</div>
<x-footer></x-footer>
jQuery does not allow me to query $('x-*'), is there any way that I could achieve this?
The below is just working fine. Though I am not sure about performance as I am using regex.
$('body *').filter(function(){
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
Working fiddle
PS: In above sample, I am considering body tag as parent element.
UPDATE :
After checking Mohamed Meligy's post, It seems regex is faster than string manipulation in this condition. and It could become more faster (or same) if we use find. Something like this:
$('body').find('*').filter(function(){
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
jsperf test
UPDATE 2:
If you want to search in document then you can do the below which is fastest:
$(Array.prototype.slice.call(document.all)).filter(function () {
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
jsperf test
There is no native way to do this, it has worst performance, so, just do it yourself.
Example:
var results = $("div").find("*").filter(function(){
return /^x\-/i.test(this.nodeName);
});
Full example:
http://jsfiddle.net/6b8YY/3/
Notes: (Updated, see comments)
If you are wondering why I use this way for checking tag name, see:
JavaScript: case-insensitive search
and see comments as well.
Also, if you are wondering about the find method instead of adding to selector, since selectors are matched from right not from left, it may be better to separate the selector. I could also do this:
$("*", $("div")). Preferably though instead of just div add an ID or something to it so that parent match is quick.
In the comments you'll find a proof that it's not faster. This applies to very simple documents though I believe, where the cost of creating a jQuery object is higher than the cost of searching all DOM elements. In realistic page sizes though this will not be the case.
Update:
I also really like Teifi's answer. You can do it in one place and then reuse it everywhere. For example, let me mix my way with his:
// In some shared libraries location:
$.extend($.expr[':'], {
x : function(e) {
return /^x\-/i.test(this.nodeName);
}
});
// Then you can use it like:
$(function(){
// One way
var results = $("div").find(":x");
// But even nicer, you can mix with other selectors
// Say you want to get <a> tags directly inside x-* tags inside <section>
var anchors = $("section :x > a");
// Another example to show the power, say using a class name with it:
var highlightedResults = $(":x.highlight");
// Note I made the CSS class right most to be matched first for speed
});
It's the same performance hit, but more convenient API.
It might not be efficient, but consider it as a last option if you do not get any answer.
Try adding a custom attribute to these tags. What i mean is when you add a tag for eg. <x-tag>, add a custom attribute with it and assign it the same value as the tag, so the html looks like <x-tag CustAttr="x-tag">.
Now to get tags starting with x-, you can use the following jQuery code:
$("[CustAttr^=x-]")
and you will get all the tags that start with x-
custom jquery selector
jQuery(function($) {
$.extend($.expr[':'], {
X : function(e) {
return /^x-/i.test(e.tagName);
}
});
});
than, use $(":X") or $("*:X") to select your nodes.
Although this does not answer the question directly it could provide a solution, by "defining" the tags in the selector you can get all of that type?
$('x-tab, x-map, x-footer')
Workaround: if you want this thing more than once, it might be a lot more efficient to add a class based on the tag - which you only do once at the beginning, and then you filter for the tag the trivial way.
What I mean is,
function addTagMarks() {
// call when the document is ready, or when you have new tags
var prefix = "tag--"; // choose a prefix that avoids collision
var newbies = $("*").not("[class^='"+prefix+"']"); // skip what's done already
newbies.each(function() {
var tagName = $(this).prop("tagName").toLowerCase();
$(this).addClass(prefix + tagName);
});
}
After this, you can do a $("[class^='tag--x-']") or the same thing with querySelectorAll and it will be reasonably fast.
See if this works!
function getXNodes() {
var regex = /x-/, i = 0, totalnodes = [];
while (i !== document.all.length) {
if (regex.test(document.all[i].nodeName)) {
totalnodes.push(document.all[i]);
}
i++;
}
return totalnodes;
}
Demo Fiddle
var i=0;
for(i=0; i< document.all.length; i++){
if(document.all[i].nodeName.toLowerCase().indexOf('x-') !== -1){
$(document.all[i].nodeName.toLowerCase()).addClass('test');
}
}
Try this
var test = $('[x-]');
if(test)
alert('eureka!');
Basically jQuery selector works like CSS selector.
Read jQuery selector API here.

Call a function on regex match

Is there a way to call a function when an id matches a regex?
I have an app where I have about 20 or so divs calling the same function by onclick and I'm trying to get rid of the onclicks and just find those divs by id. The divs id's start the same way for instance: sameId_xxx
This is what I have working but I was wondering if I could put the condition in the function call so it's not being called for every div on the page.
$("div").click(function () {
var id = this.id;
if (id.match(/sameId_/)) {
}
}
$('div[id^="sameId_"]').click(...)
Demo: http://jsfiddle.net/kpcxu/
For more info, see Attribute Starts With selector.
Try the jQuery 'attribute contains selector':
$('div[id*="sameId_"]').click(function() {
// Do stuff
});
I think better filter all div with using necessary condition and next add handler.
For example:
$('div')
.filter(function() { return $(this).attr('id') % 2 })
.click(function(){alert($(this).attr('id'))});​
Live demo on JSFiddle
Or you can use var id = $(this).attr('id') in your code.
I think the other answers (with filtering on the id up front) are better, but for posterity, here is what you actually asked for:
$("div").click(function () {
var id = this.id;
if (id.match(/(sameId_)(.)+/)) {
console.log("matched");
}
}​);​
where "sameId_" is a case sensitive representation of what you want to match.

Hide cached objects in jQuery

I'm not sure if "cached" is a correct term for this one. Maybe I should use "instantiated" instead. However, say I want to "cache" several objects, to save some resources:
var $foo = $("#foo"),
$bar = $("#bar");
Now, if I want to hide them, can I use a one-liner instead of:
$foo.hide();
$bar.hide();
I reckon that this one is quite simple (read: "stupid"), but hey... I can't figure it out all by myself...
You can also use .add() to roll up a bunch of jQuery objects and selectors:
$foo.add( $bar ).add('.someclass').add( $other_objects_or_selectors ).hide();
you can use something like this:
$.each([$foo, $bar], function(i, v) {
v.hide();
});
You can have multiple selectors in jQuery separated with comma:
$("#foo, #bar").hide();
If you're doing this for many id's, maybe do something like:
items = ['foo', 'bar'];
cache = {};
$.each(items, function(i,key) {
cache[key] = $('#' + key);
cache[key].hide();
});
Then later on access the 'cache' like cache['foo'].
Define a class for all these elements and then hide by the class
$('#foo').addClass('toHide');
//Later
$('.toHide').filter(':visible').hide();

Attaching an event to multiple elements at one go

Say I have the following :
var a = $("#a");
var b = $("#b");
//I want to do something as such as the following :
$(a,b).click(function () {/* */}); // <= does not work
//instead of attaching the handler to each one separately
Obviously the above does not work because in the $ function, the second argument is the context, not another element.
So how can I attach the event to both the elements at one go ?
[Update]
peirix posted an interesting snippet in which he combines elements with the & sign; But something I noticed this :
$(a & b).click(function () { /* */ }); // <= works (event is attached to both)
$(a & b).attr("disabled", true); // <= doesn't work (nothing happens)
From what you can see above, apparently, the combination with the & sign works only when attaching events...?
The jQuery add method is what you want:
Adds more elements, matched by the given expression, to the set of matched elements
var a = $("#a");
var b = $("#b");
var combined = a.add(b)
Don't forget either that jQuery selectors support the CSS comma syntax. If you need to combine two arbitrary collections, everyone else's suggestions are on the mark, but if it's as simple as doing something to elements with IDs a and b, use $('#a,#b').
This question has already been answered, but I think a simpler more streamlined way to accomplish the same end would be to rely on the similarities between jQuery's and CSS's selector model and just do:
$("#a, #b").click(function () {/* */});
I use this frequently, and have never seen it not work (I can't speak for jQuery versions before 1.3.2 though as I have not tested this there). Hopefully this helps someone someday.
UPDATE: I just reread the thread, and missed the comment you made about having the nodes in question already saved off to variables, but this approach will still work, with one minor tweek. you will want to do:
var a = $("#a");
var b = $("#b");
$(a.selector+", "+b.selector).click(function () {/* */});
One of the cool things that jquery does is that it adds a few jquery specific properties to the node that it returns (selector, which is the original selector used to grab that node is one of them). You may run into some issues with this if the selector you used already contained commas. Its also probably arguable if this is any easier then just using add, but its a fun example of how cool jquery can be :).
You could just put them in an array:
$.each([a, b], function()
{
this.click(function () { });
});
Why don't you use an array? This works on my side:
$([item1, item2]).on('click', function() {
// your logic
});
I just tried messing around with this, and found something very cool:
$(a & b).click(function() { /* WORKS! */ });
supersweet!
Edit: Now I feel really embarrassed for not testing this properly. What this did, was actually to put the click event on everything... Not sure why it does that, though...
You can also make up a class name and give each element that you want to work with that class. Then you can bind the event to all elements sharing that class.
<p><a class="fakeClass" href="#">Click Me!</a></p>
<p><a class="fakeClass" href="#">No, Click Me!</a></p>
<div class="fakeClass">Please, Click Me!</div>
<script type="text/javascript">
$(function () {
$(".fakeClass").on("click", function () {
alert("Clicked!");
});
})
</script>
try this: sweet and simple.
var handler = function() {
alert('hi!');
}
$.each([a,b], function() {
this.click(handler);
}
BTW, this method is not worth the trouble.
If you already know there are just two of these methods, then I guess the best bet would be
a.click(handler);
b.click(handler);
Cheers!
Example:
$("[name=ONE_FIELD_NAME], [name=ANOTHER_FIELD_NAME]").keypress(function(e){alert(e.which);});

Categories