JQuery Selector Re-Write - javascript

I do this kind of thing all over the place, and I am looking for the most efficient (both computationally + syntactically) way to execute:
ids =[]
$('tr.selectON td').each( function() {
var answer_query = $(this).attr('id');
if ( answer_query !== undefined ) {
ids.push( answer_query )
}
});
I have access to underscore.js, which I suspect will help.

ids = $("tr.selectON td[id]").map(function() { return this.id; }).get();
Documentations :
To get elements with id attribute http://api.jquery.com/attribute-contains-prefix-selector/
To filter id attribute http://api.jquery.com/map/
To convert result into array http://api.jquery.com/get/

You can make it simpler, cant speak to the JQuery performance though:
ids =[]
$('tr.selectON td[id^=""]').each( function() {
ids.push( this.id )
});
"this" in the function is already a dom object, so you have direct access to its id.

Related

Selecting by text with Protractor

I am mostly familiar with java selenium, and I am new to both JS and Protractor. Lets say I am trying to click an option from a list of options with a common identifier..
var options = $('.options');
How could I get all elements with that common identifier, and then select one by its text? I can not do driver.findElements like I could in java since there is no reference to driver..
This is what I have tried so far but its not working and I think its due to my inexperience with JS
this.selectCompanyCode = function(companyCode) {
dropDownMenus[0].click();
var companyCodeOptions = $('[ng-bind-html="companyCode"]');
companyCodeOptions.filter(function (elem) {
return elem.getText().then(function text() {
return text === companyCode;
});
}).first().click();
};
Select all elements with common identifier: $$('.options'); That selects all elements with a class of .options -- equivalent of element.all(by.css('.options')). This returns an ElementArrayFinder. Also see .get() for how to choose an element by index from the ElementArrayFinder.
Find by text, you could use cssContainingText(css, text). For example,
var loginBtn = element(by.cssContainingText('button.ng-scope', 'Login'));
But if for some reason those are not providing the expected results, you can use .filter() (docs here) on an ElementArrayFinder to go through the array of elements and find an element based on a condition you specify. For example,
var allOptions = $$('.options');
allOptions.filter(function (elem) {
return elem.getText().then(function (text) {
return text === 'What you want';
});
}).first().click();
And, although I've never used regular Java Selenium (so I don't know if this is the same), but there is indeed a browser reference (and therefore findElements function): http://www.protractortest.org/#/api?view=ProtractorBrowser.
Hope it helps!
Edit:
Using your code:
this.selectCompanyCode = function(companyCode) {
// where is dropDownMenus defined? This has function no reference to it.
dropDownMenus.get(0).click(); // should be this
var companyCodeOptions = $$('[ng-bind-html="' + companyCode + '"]');
return companyCodeOptions.filter(function (elem) {
return elem.getText().then(function text() {
return text === companyCode;
});
}).first().click();
};
second edit:
Assuming company code is unique, you probably don't need to use filter. Try this:
this.selectCompanyCode = function(companyCode) {
dropDownMenus.get(0).click();
var companyCodeOptions = $('[ng-bind-html="' + companyCode + '"]');
return companyCodeOptions.click();
};
Use cssContainingText
element(by.cssContainingText(".option", "text")).click();
http://www.protractortest.org/#/api?view=ProtractorBy.prototype.cssContainingText

Remove an object from an from an array by it's id (angular)

I'm trying to remove an object from an array by it's key/value of ID. I would normally just splice by index, however the index might be changing quite a bit because multiple users will be manipulating and updating the object so I want to hook onto something more concrete - aka the id. So I have a bit of logic to check if it still exists and if so remove it by it's ID. However I can't seem to get the syntax quite correct. I Am using underscore.js, I don't know if it's easier with/without it but it's worth mentioning.
Here's what I have -
$scope.toggleSelection = function(typeId,name,index){
//check if exists in array
check = $scope.multipleTypes.some( function( el ) {
return el.name === name;
});
//checked on/off actions
if($scope.items[index].checked == false || $scope.items[index].checked == undefined ){
//IS cecked
if(check){
//already exists, do nothing
}else{
$scope.multipleTypes.push({id:typeId, name:name, checked: true});
}
}else{
//IS not checked
if(check){
var list = _.filter($scope.multipleTypes, function(element){
return element.id != typeId;
}
$scope.multipleTypes = list;
}else{
//is not there, do nothing
}
}
};
So if it does exist and is checked off, it gets pushed. If it does exist and is unchecked, I want to remove it from $scope.multipleTypes by it's ID. I think I Am doing this wrong, all I want to do is remove that one object that has the matching ID from $scope.multipleTypes. Would appreciate any help. Thanks for reading!
If you can use UnderScore Js, You can do it very easily.
Here is an Example:
var someArray= [{Employee:'ved',id:20},
{Employee:"ved",age:25},
{Employee:"p",age:2}];
var a = _.findWhere(someArray,{id:25});//searching Element in Array
var b= _.indexOf(someArray,a);// getting index.
someArray.splice(b,1);// removing.
I normally find the object by id, then splice it out. Note that angularjs adds other properties to the object .
e.g
$scope.items = [......]
var findItemByID = function(id, items){
angular.forEach(items, function(item){
if(item.id === id){
return item;
}
})
return null;
}
var removeItemByID = function(id, items){
var item = findItemByID(id);
if(item){
items.splice(items.indexOf(item), 1);
}
}
//you can now do removeItemByID(id, $scope.items);
//I have not tested this code and it may have syntax errors. hope you get the idea.
Josh

Returning an array of values

I need to get a list of values from a set of element attributes and store them in an array.
Currently, I am doing this:
var ids = [];
$("my selector").each(function (idx, v) {
ids.push($(v).data("id"));
});
This seems a bit clunky. Is there a more efficient/streamlined way of doing this? Perhaps something more like this:
var ids = $("my selector").data("id");
Try using .map() along with .get() in this context,
var ids = $("my selector").map(function(){
return $(this).data("id");
}).get();
Less clunky:
$("my selector").each(function () {
ids.push($(this).data("id"));
});
By, removing idx and v, you can use $(this)

HTML DOM. anyway to get attributes dict?

node.attributes return a NamedNodeMap..
and it won't give out all the attributes names or values like in the xml.
is there a way get something like this?
node.attributes.keys
node.attributes.values
node.attributes.items
any kind ?
now I use this for my won use..But js won't give out the attributes names like class、id、href.it gives number instead..
listattr = function(node) {
var attrs = [[],[]];
for (var attr in node.attributes) {
if (node.attributes[attr].nodeValue) {
console.log(attr);
console.log(node.attributes[attr].nodeValue);
attrs[0].push(attr);
attrs[1].push(node.attributes[attr].nodeValue);
}
}
return attrs;
}
But js won't give out the attributes names like class
It is an array-like list of Attribute nodes, which do have values and names! You are logging the indices.
var attrs = node.attributes;
for (var i=0; i<attrs.length; i++)
console.log(attrs[i].name, attrs[i].value);
Bergi's answer basically says it all, but here's a complete function (using underscore) to convert an html element's attributes to a dict:
_.reduce(myElement.attributes, function(memo, element){
memo[element.name] = element.value;
return memo;
}, {});
This worked for me:
Array.from(node.attributes).reduce((acc, it) => ({ ...acc, [it.name]: it.value }), {})

putting source of all images into an array

What is the cleanest way to put the source attribute string of all images within a div into an array?
I was hoping this would work -
var imageSourceArray = $("#leDiv img").attr('src');
alert(imageSourceArray[3]); //not alerting the source, boo hoo.
Do I need to loop through $("#leDiv img") and add each src string to an array individually? Or is there a more elegant way to do this?
You can use jQuery's map function which is described as:
Pass each element in the current matched set through a function, producing a new jQuery object containing the return values.
For your example:
var mySources = $('#leDiv img').map(function() {
return $(this).attr('src');
}).get();
Edit: Far more elegant solution, there's obviously still some looping involved internally:
var img_sources = $('#leDiv img').map(function(){ return $(this).attr('src') });
You will in fact need to loop over the collection and add sources individually.
var img_sources = [];
$('#leDiv img').each(function(i,e){
img_sources.push($(e).attr('src'))
})
Some background: jQuery.fn.attr() maps to jQuery.access() internally, the key part of which looks like this:
function( elems, key, value, exec, fn, pass ) {
var length = elems.length;
// setter functions omitted here …
// Getting an attribute
return length ? fn( elems[0], key ) : undefined;
}
Note the elems[0] part – only the first item in the collection is fed to the subsequent callback function (jQuery.attr() in fact) responsible for extracting the information.
var imageSourceArray = [];
$('#leDiv img').each(function(){
var src = $(this).attr("src");
imageSourceArray.push(src);
});
alert(imageSourceArray[3]);
you already have the src in a collection when you fetch the the images. It may be more efficient to not store the src attributes in another array:
$('#leDiv img').each(function(i,e){
var dosomethingwith = $(e).attr('src');
})
or you could do:
var ImageCol = $('#leDiv img');
alert(ImageCol[3].attr('src'));

Categories