I am using the values input by the user to perform this action.
Here is the full code: https://jsfiddle.net/7196dfyz/
This is part of the code where the elements are traversed, where I'm having trouble:
var lists = $ul.getElementsByTagName("li");
for (var i = 0; i < lists.length; ++i) {
if (lists[i] == value) {
$("ul").css("background-color","black");
}
}
The first input should take the value in some li
and the second input should take the respective parent ul class name.
I think this is what you're looking for. (Here is an updated jsfiddle):
function func() {
var key = $("#key").val();
var value = $("#entry").val();
var $ul = $("." + key);
var lists = $ul.find("li");
for (var i = 0; i < lists.length; ++i) {
console.log($(lists[i]).text(), value);
if ($(lists[i]).text() === value) {
$(lists[i]).css("background-color","black");
}
}
}
You have several issues:
$ul.getElementsByTagName is not a valid function. Because $ul at this point is a jQuery array-like object, it wont work. You'd need to do $ul[0].getElementsByTagName, or simply use jQuery's find() like my example above.
You're trying to compare lists[i] to value, which happens to be an HTML element. When comparing to a string, it will return <li>Say</li> which will never match anything you type in. Using $(lists[i]).text() should get you what you need.
$("ul").css("background-color","black");: You were setting every ul to black if a match was found. I assume you only want to match the one that was matched. $(lists[i]).css("background-color","black"); fixes this.
You can even simplify this entire function down to this:
function func() {
var key = $("#key").val();
var value = $("#entry").val();
$("." + key).find("li").filter(function() {
return $(this).text() === value;
}).css("background-color","black");
}
Broken down:
$("." + key): Find the ul that has the class of key.
.find("li") Find all list items within each unordered list found.
.filter(...) For each element in this list, and return to me only the items that match my criteria: $(this).text() === value.
And finally .css("background-color","black"): Set all the background colors to black of the list items that were returned from the filter() function.
Related
How can I pass values from an array from one event click to another with jQuery?
Here is an example of I want to do: the first click event adds or remove values from the array if the input checkbox is selected or not. In the second click I want to loop trough all the elements of this array.
var array=[];
$( "input" ).on( "click", function() {
var $input=$(this)
if($input.is(":checked")){
array.push($(this).val()); //append check box value to array if is selected
}
else{
array.pop($(this).val()); // remove check box value to array if is not selected
}
})
$('#cmd').click(function() {
for (i of array) {
console.log(array[i]); // loop trough all elements in array
...
});
Your code looks ok except two things. First for for (i of array). Using of will return actual value as i, but you are using value as index in array[i].
If you want use index then use for (let i = 0; i < array.length; i++) instead.
You can also use Array.prototype.forEach() but you can't break out of it's loop https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
Second thing is that .pop() doesn't support parameter. Use code below instead of .pop()
var index = array.indexOf($input.val());
if (index > -1) {
array.splice(index, 1);
}
If your event handlers are in different scope and #cmd handler can't see the array. You might use this little bit bad solution for sharing the array between scopes :)
$("input").on( "click", function() {
var array = $("#cmd").data("arr") || [];
var $input= $(this);
var value = $input.val();
if($input.is(":checked")){
array.push(value); /
} else {
var index = array.indexOf(value);
if (index > -1) {
array.splice(index, 1);
}
}
$("#cmd").data("arr", array);
});
$('#cmd').click(function() {
var array = $(this).data("arr") || [];
for (let value of array) {
console.log(value); // loop trough all elements in array
}
});
I set up a search function for a content system.
The user is able to publish and unpublish his elements.
Every element has two keywords + the condition state = 3 keywords for the search in sum.
Every element has an attribute namend "data-meta" in which the three keywords are stored.
eg.
data-meta="banana blue public"
How can i edit the last value "public", if the user wants to unpublish his element and set it to private?
Without actually altering how you store these values, such as creating custom attributes like
data-keyone="banana" data-keytwo="blue" data-state="public"
you can pull the value of the attribute, split it, modify the third element, join it, then set the attribute value to the new string.
Starting with this:
<myelement id="example" data-meta="banana blue public">
Pull the value:
var oElem = document.getElementById("example");
var strTemp = oElem.getAttribute("data-meta"); //javascript
var strTemp = $('myelement#example').attr('data-meta'); // jquery
Split it:
var astrVals = strTemp.split(" ");
Modify the third value:
astrVals[2] = "private";
Rejoin it:
strTemp = astrVals.join(" ");
Then set the value again:
$('myelement#example').attr('data-meta', strTemp); //jquery
oElem.setAttribute("data-meta", strTemp); // javascript
Edit with jQuery not with javascript:
First:
$('#anyID').removeAttr("meta-data")
After:
$('#anyID').attr("data-meta", "banana blue private")
I've made a few small functions that can make toggle like functionality.
The first one takes the string from attribute and splits it by spaces to make an array, the next one looks at the array to see if it contains what you want to toggle. Third and forth add and remove from the array and then join the array back together as a string with spaces.
I haven't added any error handling so if you try and remove an attribute that isn't there it will have issues but other than that is should get you started.
// take contents of attribute and return an array
function arrFromAttr(selector, attribute) {
return selector.getAttribute(attribute).split(" ");
}
// check the array and toggle the value
function toggleAttr(selector, attribute, value) {
let attrs = arrFromAttr(selector, attribute);
if (attrs.includes(value)) {
removeAttr(selector, attribute, value)
} else {
addAttr(selector, attribute, value)
}
}
// add to the array and set the attribute
function addAttr(selector, attribute, value) {
let attrs = arrFromAttr(selector, attribute);
attrs.push(value);
selector.setAttribute(attribute, attrs.join(' '));
}
// remove from the array and set the attribute
function removeAttr(selector, attribute, value) {
let attrs = arrFromAttr(selector, attribute);
attrs.splice(attrs.indexOf(value), 1);
selector.setAttribute(attribute, attrs.join(' '));
}
// toggle the attribute on button click
document.querySelector('button').addEventListener('click', () => {
toggleAttr(document.querySelector('[data-meta]'), "data-meta", "public");
})
div[data-meta]:after {
content: attr(data-meta)
}
<div data-meta="banana blue public"></div>
<button>Toggle public</button>
I hope you find this helpful 🙂
If you're feeling fancy you can have your own polyfill you make a toggle function, though I wouldn't recommend doing something like this until you're confident in JS
if (!(Element.prototype.toggleAttribute || Element.prototype.deleteAttribute || Element.prototype.addAttribute)) {
Element.prototype.toggleAttribute = function(name, value) {
let attrs = this.getAttribute(name).split(" ");
if (attrs.includes(value)) {
this.deleteAttribute(name, value)
} else {
this.addAttribute(name, value);
}
}
Element.prototype.addAttribute = function(name, value) {
let attrs = this.getAttribute(name).split(" ");
attrs.push(value);
this.setAttribute(name, attrs.join(' '));
}
Element.prototype.deleteAttribute = function(name, value) {
let attrs = this.getAttribute(name).split(" ");
attrs.splice(attrs.indexOf(value), 1);
this.setAttribute(name, attrs.join(' '));
}
}
document.querySelector('button').addEventListener('click', () => {
document.querySelector('div').toggleAttribute('data-meta', 'public');
})
div[data-meta]:after {
content: attr(data-meta)
}
<div data-meta="banana blue public"></div>
<button>Toggle public</button>
This code adds the functions to the native code so you can call the functions on a element rather than having to pass the element as an arguement.
I'm writing a javascript code, where the user should be able to search through dimension elements, which is displayed within a "pop-up" window with a table.
The code that displays the elements in the array looks like this:
$element.find("#myInput").on("qv-activate", function (){
let elemList = [];
self.backendApi.getData(requestList).then(function (dataPages) {
let elem = dataPages[0].qMatrix;
for(let i = 0; i < elem.length; i++){
elemList.push(elem[i][0].qText);
}
$(document).ready(function () {
$("#myInput").on("keyup", function () {
var value = $(this).val().toLowerCase();
for (var i=0; i<elemList.length; i++) {
if (elemList[i].toLowerCase().indexOf(value) >= 0){
$element.find('#searchTable').prepend('<tr><td id="searchElem">' + elemList[i] + '</td></tr>');
}
}
});
});
})
})
The only problem is, when I use the searchbar, it presents the element multiple times. Is there a way I can make sure, that the .prepend() only prepends if it is not the same value as before?
Some kind of; if element value is identical with the before prepended value, then don't prepend?
Hope it makes sense, and you have a solution to my problem.
Thanks!
Instead of calling prepend in the second for loop, make a new array and append elemList[i] to that.
Then use a solution from "Get all unique values in an array (remove duplicates)" to remove the duplicates from the array. For example, if values is your new array:
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
values = values.filter(onlyUnique);
Finally, loop through your new array and call prepend on each.
Original code:
item_boxes = $(".item-box")
$.each(item_boxes, function() {
var id = $(this).data("id")
$(this).find(".price").text(price_list[id])
})
JS code:
item_boxes = $(".item-box")
for(var i=0; i<item_boxes.length; i++) {
var id = item_boxes[i].getAttribute("data-id")
item_boxes[i].find... .text
// above line doesn't work, because it's jQuery
// item_boxes[i].querySelector(".price"), finds the child element, but then I can't figure out how to add the price info
// item_boxes[i].querySelector(".price").innerHTML(price_list[id]) throws a nomethod error on innerHTML
}
ooops sorry tanks for the responses, but I guess the quesiton wasn't clear, I'm moving TO the latter code (JS). I'd like the latter code to duplicate the same functionailty as former, but currently it does not. item_boxes[i].find throws a no method error on .find, so then I did querySelector, which finds the object, but there's no .text method to change the text.
Basically what the code is doing is looking at all the item_boxes, and on each of them, changing the text of the child price element.
Use the eq(id) method to fetch a jQuery object.
Proceed with data() as well.
var item_boxes = $(".item-box"),
i = 0,
el, id;
for(; i < item_boxes.length; i++) {
el = item_boxes.eq(i);
id = el.data("id");
el.find(".price").text(price_list[id]);
}
Notice with the for loop, all variables are extracted to it's function scope, which is more imaginary in this example. Use $.each(items, function(i, item){/*vars*/}) if you want to keep variables together.
Without jQuery:
var item_boxes = document.querySelectorAll(".item-box"),
i = 0,
el, id;
for(; i < item_boxes.length; i++) {
el = item_boxes[i];
id = el.dataset.id;
//el.querySelectorAll
el.querySelector(".price").innerHTML = price_list[id];
}
Following JQuery docs sample :
$.each([ 52, 97 ], function( index, value ) {
alert( index + ": " + value );
});
You can do much better without jQuery by using modern features, and a transpiler if needed.
for (const box of document.querySelectorAll(".item-box")) {
box.querySelector(".price").textContent = price_list[box.dataset.id];
}
The longest part is the function names, so you can shorten them.
function query(root, sel) {
return root.querySelector(sel);
}
function queryAll(root, sel) {
return root.querySelectorAll(sel)
}
So now it looks like this:
for (const box of queryAll(document, ".item-box")) {
query(box, ".price").textContent = price_list[box.dataset.id];
}
Make the function names as short as you like.
$.each takes two arguments. The first one is what it calls the index, the second one is what it calls the element.
As for "acting" on the data, it depends on whether you're talking about manipulating what you're iterating over or whether you're just manipulating the values that the function is returning.
To change what you're iterating over, use the index to select each respective item in what you're iterating over:
var list = [27, 43, 19];
$.each(list, function(i, element) {
list[i] += 7
});
To change the values being returned, just do whatever. They're variables.
var list = [27, 43, 19];
$.each(list, function(i, element) {
i += 3
element += 91
});
You could use ES6 Map method
It'd be something like
item_boxes.map( (item_box,index) => {
var id = item_box.getAttribute("data-id")
item_box.find... .text //if you actually need to do something with the index
})
I have 2 arrays, one with cities, and another array with ID's...
I would like to loop both, and then output some HTML
Right now im only looping cities, and then appending some HTML to a as following:
if ($jq(".area").length > 0) {
var region = $jq(".hiddenFieldRegion").val();
var cityIDs = $jq(".hiddenFieldChosenAreas").val();
var strcities = $jq(".hiddenFieldChosenCities").val();
//var cities = strcities.split('|');
//Set region to be marked
if (region) {
$jq(".mapdk").attr("class", region);
}
//Appending to searchform
if (strcities) {
$jq.each(strcities.toString().split("|"), function (k, v) {
var v = v.split("|");
$jq("<option selected />").text(v[0]).appendTo("select.chosen-cities");
});
}
}
I would like the place where im appending to the searchform, add an attribute value, with an ID from the cityIDs array...
So i get some HTML like:
<option value="XXX">CityName</option>
Is that possible?
Assuming your cities IDs and your cities names are orderred in the same way, you can access each name/id by this index in the arrays :
var cityIDs = $jq(".hiddenFieldChosenAreas").val();
var strcities = $jq(".hiddenFieldChosenCities").val();
var cityIDs_array = cityIds.split("|");
var strcities_array = strcities.split("|");
....
if (strcities) {
$jq.each(strcities_array, function (k, v) {
//var v = v.split("|"); Unnecessary if strcities is like "city1|city2|city3"
$jq("<option value='"+cityIDs_array[k]+"' />").text(v).appendTo("select.chosen-cities");
});
}
In this, way, you can access each city ID in your loop.
But I think you should store city name and city id in the same string. For example "city1:1|city2:2|city3:3". Then, with some use of split function, you'll get id and name.
Assuming the order is the same in both arrays you can use the index parameter (k) of the each function:
if (strcities) {
var aCityIDs = cityIDs.split("|");
$jq.each(strcities.toString().split("|"), function (k, v) {
var v = v.split("|");
var id = aCityIDs[k];
$jq("<option selected value='"+id+"' />").text(v[0]).appendTo("select.chosen-cities");
});
}
This is easy enough if your two arrays are in parity with one another with regards to indexing - loop over one, then look up a value in the other array at the same index.
//simulate environment
var strcities = 'one|two|three',
cityIDs = '1|2|3';
//main code
var ids = cityIDs.split('|');
$.each(strcities.toString().split("|"), function (index, val) {
var opt = $("<option />", {value: ids[index], text: val}).appendTo("select.chosen-cities");
/* if (index == 2) opt.prop('selected', 'selected'); /*
});
A few points of note:
you were splitting on | once in the $.each and again inside it. Since this would be illogical (any | would have disappeared after the first split) I removed it.
you were adding selected to each option. If you simply want the first option to be selected, you don't need to add anything in. If you want a specific option to be selected, see the line I commented out, which selects the 3rd element.
http://jsfiddle.net/DhH3U/
Another example:
var strict = ('aaa|eeee|dddd').split('|');
var id = ('1|2|3').split('|');
$.each(strict, function (k) {
$("<option selected />").text(strict[k]).appendTo("select.chosen-cities").attr('value',id[k]);
});