jQuery: How to create array with two values for each item - javascript

I am new to jQuery and hope someone can help me with this and also provide a short explanation so that I can apply it for similar cases in the future.
I have a large HTML page that is built dynamically.
The page contains several tables with certain divs that are editable (contenteditable=true). These divs all have the class "editable".
Now I would like to create an array for all these divs that contains their id and their content (text).
So far I have the following which should create unique ids for these divs with an incrementing number but I am not sure on how to create the array for this.
Also, just out of curiosity, is there a certain term how to call such arrays with two values per item ?
My jQuery:
$('#btnSave').on('click', function(){
var i = 0;
$(this).closest('form').find('div.editable').each(function(){
$(this).attr('id', 'ed' + i+1);
if( ($(this).text != '') && ($(this).text != ' ') ){
$(this).addClass('edited');
}
i++;
});
});
// my attempt for the array (perhaps the wrong approach):
var arrEdited = new Array();
$('div.edited').each(function(){
arrEdited.push($.trim($(this).text()));
});
Many thanks in advance,
Mike

I don't think you need another loop, instead you can put it inside your first loop, inside if( ($(this).text() != '') && ($(this).text() != ' ') ), then push an object to your array instead of a value.
var arrEdited = new Array();
$('#btnSave').on('click', function(){
$(this).closest('form').find('div.editable').each(function(index){
//you could use the index when you use .each function
$(this).attr('id', 'ed' + (index+1));
if( ($(this).text() != '') && ($(this).text() != ' ') ){
$(this).addClass('edited');
//instead of using another loop, you can put your code here
arrEdited.push({
id: $(this).attr('id'),
text: $.trim($(this).text())
});
//here you use an object, people call it array of objects
}
});
});

You should use array of objects to store the div id and text inside array.
Check this:
// my attempt for the array (perhaps the wrong approach):
var arrEdited = []; // [] is better than new Array()
$('div.edited').each(function () {
// Add this div id and content in array
arrEdited.push({
id: $(this).attr('id'),
text: $.trim($(this).text())
});
});

You can use .map() to create an array.
Pass each element in the current matched set through a function, producing a new jQuery object containing the return value.
As the return value is a jQuery object, which contains an array, it's very common to call .get() on the result to work with a basic array.
var arrEdited = $('div.edited').map(function(){
return {
id: this.id,
text: $.trim($(this).text())
}
}).get();

Related

What am I missing in the jQuery .each() function?

I have this function that I am trying to figure out/fix and can't seem to pinpoint the issue / can't figure out a way to get it working.
Basically my CMS is spitting certain hrefs that I would like to:
Part 1) change the targeted href URL
Part 2) change the button's text
Right now I only have 2 instances of this type of button, so here's what is printing out in my console:
Part 1) for this part I get the correct urls without the characters i want to strip out.
Part 2) two instances of the button's text (See All) followed by the correct variable of btnParent for the first button and then the second button and finally one instance of "Products".
My issue is, I can't figure out how to:
Part 1) send back the stripped URL to its respective button's href as an each function.
Part 2) Have the each() function print out the new text as "See All + BLAH + Products" for each instance, and then append the new text to the respective button.
Here is the code:
function viewMoreBtn() {
var btnMain = $("li:contains('See All')");
var btnText = $("li:contains('See All')").text();
var btnParent = $("li:contains('See All')").parent('ul').prev('li').text();
// PART 1 - STRIP LINK URL OF -_-// CHARACTERS
$.each(btnMain, function(i, v) {
v = $(this).find('a').attr('href').replace('-_-//', '');
console.log(v);
});
// PART 2 - ADD LABEL TO HTML TEXT OF BTN
$.each(btnMain, function(index, value) {
value = (btnText + btnParent + 'Products');
$(btnMain).text(value);
console.log(value);
});
}
viewMoreBtn();
Thank you.
jQuery objects, as return by $(...) have a each method already on them. The element is passed as the this context. You could use that further with jQuery to act on the objects in an scoped context. Basically, you have the right code, just in the wrong scope.
Part 1
btnMain.each(function() {
var $li = $(this);
var $a = $li.find('a');
var desiredUrl = $a.attr('href').replace('-_-//', '');
$a.attr('href', desiredUrl);
});
Part 2
btnMain.each(function() {
var $li = $(this);
var btnText = $li.text();
varbtnParent = $li.parent('ul').prev('li').text();
value = (btnText + btnParent + 'Products');
console.log(value);
$li.find('a').text(value);
});
See #Zequ's answer for the iteration over the each() function in the returned btnMain.
This is how $.each( obj, function( key, value ) works: you iterate over btnMain, and for each iteration of $.each(), the function assigns the index of the iteration to i and the value of btnMain at that index to v.
$.each(btnMain, function(i, v) {
//v = $(this).find('a').attr('href').replace('-_-//', '');
console.log(i); // I am the index of $.each() iterator
console.log(v); // I am the node from the btnMain array
// I don't know if this is right without seeing your HTML, but it seems like what you want
v.find('a').attr('href').replace('-_-//', '');
});
The second $.each() follows the same pattern.
If I understood correctly, you're confusing your variables.
$.each is a function for each element of the array/object being passed. It gives you a index and the element, check the reference
In part 1, you're defining v as the string you want, you're not changing the element at all,you need something like this:
$.each(btnMain, function() {
// you're saying you got the correct URLs, so the only thing you need to do is to change the element afterwards
var element = $(this).find('a');
v = element.attr('href').replace('-_-//', '');
element.attr('href', v);
});`
Also you could use btnMain.each instead of $.each
In part 2, you are changing the value variable (it's actually the element you're iterating over), to the string you want, then you follow it by trying to change btnMain's text. This is wrong, from what I understood, btnMain is an array of two elements you can't change it's text. You should change the element's value (that you are calling value). It would be something like that
$.each(btnMain, function(index, element){
// I think this is the time you want to define the btnParent, relative to the element
var btnParent = element.parent('ul').prev('li').text();
var value = (btnText + btnParent + 'Products');
element.text(value);
}
I THINK this is what you need.
Also you could append both parts into one, since both are iterating over btnMain

Add text with a specific class to dropdown <select>

I want to
Get Text From Classes with class .pick and populate them into a dropdown #pingList
1) my Variable picker returns a long string, so I assume I need to create an array
2) var array I want the result to be ['x','y','z'] as I assume this is what I need in the next step.
3) I then want to add this to the dropdown with the text and val set.
I am pretty sure all I am missing is the array part. Looking for some help.
My Jquery Code and Live Demo http://jsfiddle.net/UUY5Z/1/
// Get text from Pick CLass
var picker = $('.pick').text();
// Make an Array from string result above
var array = //??
// Add this to the dropdown
$.each(array, function (val, text) {
$('#pingList').append($('<option></option>').val(val).html(text));
});
.text() method returns textContent of all of the selected elements as one string, you can use .map() method instead which returns an array:
var picker = $('.pick').map(function(i, elem) {
return "<option value='"+i+"'>" +
(elem.textContent || elem.innerText) + // == $(elem).text()
"</option>";
}).get(); // array of options (string)
$('#pingList').append(picker);
http://jsfiddle.net/JJsRd/
Here an other solution , using $.each() :
$.each($('.pick'),function(i, elem){
$('#pingList').append( "<option value='"+i+"'>"+ $(elem).text() +"</option>");
});
DEMO HERE
$('.pick').each(function(){
$('#pinglist').append(""+$(this).text()+"");
});
This should work for Above Case.
http://jsfiddle.net/sushilbharwani/uNpND/
I have updated in your demo page.. #http://jsfiddle.net/UUY5Z/7/
$(".pick").each(function(){
var val = $(this).text();
$('<option>').val(val).text(val).appendTo('#pingList');
});
You can achieve the same like this.
No need to make an array.
$.each($('.pick'), function (val, text) {
$('#pingList').append($('<option></option>').val($(this).text()).html($(this).text()));
});
JSFiddle For Same http://jsfiddle.net/sushilbharwani/uNpND/

how to loop though div and get each value

I am trying to figure out how to get each value within my div. I am using
var cart = $('.basic-cart-cart-node-title.cell').text();
It is giving the results of OI-01OP-01OS-10-5SOR-04OR-05
I need to view them one by one: OI-01, OP-01, OS-10-5S, OR-04 OR-05.
So that I can match them against another field.
If you care to help me further, I have another div on the page:
var ParNum = $('.assess-title').text();
I would like to compare the values returned from the var cart and see if that value is in the ParNum. If it is there, I would like to apply a class.
Any help would be greatly appreciated.
Thanks!
You can store the values in an array using .map() method:
var values = $('.basic-cart-cart-node-title.cell').map(function() {
return $.trim( $(this).text() );
}).get();
For checking existence of the ParNum value in the array:
var does_exist = values.indexOf(ParNum) > -1;
Try this to iterate over elements:
var text = '';
$('.basic-cart-cart-node-title.cell').each(function (i, div) {
text += ' ' + $(div).text();
});
or this to get an array of matching div elements:
var divs = $('.basic-cart-cart-node-title.cell').toArray();
for (var i = 0; i < divs.length; i++) {
// $(div).text();
}
Reason for this is that $('.basic-cart-cart-node-title.cell') returns all div's at once, and you need to loop through the result. More specifically, $(selector) returns a so-called "wrapped set". It can be used to access each matching element (as I've shown above) or it can be used to apply any other jQuery function to the whole set at once. More info here.
var text = "";
$('.basic-cart-cart-node-title.cell').each(function(){
text += $(this).text() + ", ";
});
// remove the last ", " from string
text = text.substr(0, text.length -2);
var cart = [];
$('.basic-cart-cart-node-title.cell').each(function {
cart.push($(this).text());
}
This performs the matching and class adding you mentioned in the question.
var ParNum = $('.assess-title').text();
$('basic-cart-cart-node-title.cell').each(function () {
if ($(this).text() == ParNum) {
$(this).addClass("someclass");
}
}
You should try using
var cart ='';
$('.basic-cart-cart-node-title'.find('.cell').each(function()
{
cart = cart + $(this).val();
});
Hope it works for you.
var cart = $('.basic-cart-cart-node-title.cell').text().match(/.{5}/g);
This will give you an array with items 5 chars long. Regexes arent very fast, but a loop might be slower
Or easier to read, and in a string with commas:
var cart = $('.basic-cart-cart-node-title.cell').text(); // get text
cart = cart.match(/.{1,5}/g); // split into 5 char long pieces
cart = cart.join(",",); join on comma

How do I remove every attribute from every tag?

I'm trying to strip MS Word formatting on a paste into a Telerik RadEditer. Unfortunately I can't seem to get the built in format stripper to work.
//performing paste
var editor = $find("radEditor1");
editor.setFocus();
var rng = editor.getSelection().getRange();
rng.execCommand("Paste", null, false);
//does nothing! (even when uncommented)
//editor.fire("FormatStripper", {value: "MSWordRemoveAll" });
So I figure I could leverge jQuery to string all the attributes out of the tags and that may just do exactly what I need.
//fixing content
var html = editor.get_html();
$("*", html).each(function(){
var attr = $.map(this.attributes, function(item){
return item.name;
});
var node = $(this);
$.each(attr, function(i, item){
//added a filter for crazy Error
if(item != "dataSrc" &&
item != "implementation" &&
item != "dataFld" &&
item != "dataFormatAs" &&
item != "nofocusrect" &&
item != "dateTime" &&
item != "cite")
node.removeAttr(item);
});
});
editor.set_html(html);
Now after this function completes my html variable does not have it's html updated...
This code seems to do the trick. It uses a safeAttrs array to make updating the list of attributes you want to keep easier. You can pass .removeAttr() a space delimited list of attributes to remove, so you don't need to loop through the attribute names one-by-one.
Finally, different browsers may handle attributes differently (Chrome, for example, stores all attributes in lowercase, so 'dataFld' is stored as 'datafld'), so it's best to normalize them all with .toLowerCase()
var safeAttrs = ["datasrc","implementation","datafld","dataformatas","nofocusrect","datetime","cite"];
$('html *').each(function() {
var attrs = $.map(this.attributes,function(attr) {
if($.inArray(attr.nodeName.toLowerCase(),safeAttrs) < 0) {
return attr.nodeName;
} else { return null; }
});
$(this).removeAttr(attrs.join(' '));
});
jsFiddle DEMO. Use Chrome or Firebug to inspect the resulting elements to check that attributes have been removed.
I think I have it.
var html = editor.get_html();
var parent = $('<div></div>').html(html);
$(parent).find('*').each(function(){
var attr = $.map(this.attributes, function(item){
return item.name;
});
var tag = $(this);
$.each(attr, function(i, item){
tag.removeAttr(item);
});
});
editor.set_html(parent.html());​
http://jsfiddle.net/duC6Z/8/
Unfortunately I'm still having issues with my RadEditor but that is normal.

jQuery Selecting Elements That Have Class A or B or C

I working on something where I need two functions.
1 - I need to look at a group of children under the same parent and based on a class name, "active", add that element's ID to an array.
['foo-a','foo-b','foo-d']
2 - I then iterate through all the children in another parent and for each element I want to find out if it has any class name that match the ids in the array.
Does this element have class foo-a, foo-b or foo-d?
For the first part, I'd use map and get:
var activeGroups = $('#parent .active').map(function() {
return this.id;
}).get();
This gives you an array of id values (say, ['foo-a', 'foo-d']). You can then make a selector like .foo-a, .foo-b, .foo-c (the multiple selector) using join:
var activeSelector = '.' + activeGroups.join(', .');
This makes a valid jQuery selector string, e.g. '.foo-a, .foo-d'. You can then use this selector to find the elements you want using find:
var activeEls = $('#secondParent').find(activeSelector);
You can then do whatever you need to with activeEls.
var active = $("#foo").find(".active").map(function() {
return this.id;
}).get();
$("#anotherParent *").each(function() {
var that = this;
var classes = $(this).attr("class");
if(classes.indexOf(" ") !== -1) {
classes = classes.split(" ");
} else {
classes = [ classes ];
}
$.each(classes, function(i, val) {
if($.inArray(val, active)) {
// this element has one of 'em, do something with it
$(that).hide();
}
});
});
There's always .is('.foo-a, .foo-b, .foo-d'). Or if you actually just wanted to select them, instead of iterating and deciding for each element, $('.foo-a, .foo-b, .foo-d', startingPoint).

Categories

Resources