I'm trying use js onmousehover to hover over an image and in a seperate fixed location tell me the name of said image. I have successfully done this but I can only get it to work on the first element when I have about six that I need to do. here is a sample of my code:
function getElementsById(ids) {
var idList = ids.split(" ");
var results = [], item;
for (var i = 0; i < idList.length; i++) {
item = document.getElementById(idList[i]);
if (item) {
results.push(item);
}
}
return(results);
}
function hover(description) {
console.log(description);
document.getElementsById('content content1').innerHTML = description;
}
and to call it I've been using this:
<div class="product-description-box">
<p>
<div class="colorHeading">colors available: <span class="selectedColor" id="content"></span></div>
<div class="prodColors"></div>
</p>
</div>
I am using different ids for each section. Js is for sure not my strong suit so any help would be appreciated!
A faster way of doing it is to pull your elements collection and then convert it into an array:
Like so:
[].slice.call(document.getElementsByClassName("box"))
.forEach(function(element) {element.addEventListener("mouseover", checkBoxColor);});
This calls slice on the collection of HTML elements returned by getElementsByClassName in order to convert it into an Array. After that I run the forEach method to add the event listener to each HTML element.
Fiddle: https://jsfiddle.net/0saLvq2q/
In your case if you need to return multiple elements by many different ID's you can use querySelectorAll() to pull the elements instead of getElementsByClassName().
'ids' isn't automatically a list. What you want to use is the Arguments Object.
function getElementsById() {
var i, results = [], item;
for (i = 0; i < arguments.length; i++) {
item = document.getElementById(arguments[i]);
if (item) {
results.push(item);
}
}
return(results);
Related
I am in the process of developing an AB Test for an e-commerce cart page. We have a list of about 100 stylenames that we are not going to be accepting returns on.
We have messaging displayed on those particular styles' product display pages, but we would also like to have this message reinforced on the cart page if any product in the cart matches the list of stylenames that qualify.
I have started by creating an array variable of all qualified stylenames (shortened here for example). I then loop through each cart item heading tag & check the .text() of that element. IF the .text() matches one of the stylenames I am looking for, I would then want to go ahead and append the message below the cart item heading tag.
Here is the script I have written, however, I don't see the result expected when running this locally in my devtools snippet:
var styleList = ['Astawia Loafer','Another Style','So On','So Forth'];
var finalSaleMessage = '<span><strong>Final sale! </strong>No returns on our best deals.</span>'
function checkStyleName(value,arr){
var result = false;
for (var i = 0; i < arr.length; i++){
var name = arr[i];
if(name == value){
result = true;
break;
}
}
return result;
}
$('.crt-heading--item').each(function(){
if (checkStyleName($('.crt-heading--item').text(),styleList) == true) {
// append the message
}
})
Any input here from the community would be greatly appreciated. Please let me know if you would need further information.
Thanks!
Can be simplified a little.
No need to send array everytime.
Usage of includes.
Looks like the text is in the format of BRAND PRODUCT_NAME CATEGORY. You may want to split or do something to get the PRODUCT_NAME.
Usage of this as pointed out by devmiguelopz
var styleList = ['Astawia Loafer','Another Style','So On','So Forth'];
var finalSaleMessage = '<span><strong>Final sale! </strong>No returns on our best deals.</span>'
// OLD SUGGESTION
/*
$('.crt-heading--item').each(function(){
if (styleList.includes($(this).text()) {
// append the message
}
*/
// This will iterate on the elements
$('.crt-heading--item').each(function(){
// Iterate on the styleList
var styleListLength = styleList.length;
for(var i = 0, i < styleListLength; i++){
// Check if the name has entry from styleList
if($(this).text().includes(styleList[i])){
// DO STUFF
}
}
})
// We re running a loop inside a loop in this case.
// There may be better ways of doing this with .some/.filter/.map
Check here for what .includes can do for you : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes
The problem is that you go through all the elements of a certain class and don't refer to every single one of them.
var styleList = ['Astawia Loafer','Another Style','So On','So Forth'];
var finalSaleMessage = '<span><strong>Final sale! </strong>No returns on our best deals.</span>'
function checkStyleName(value,arr){
var result = false;
for (var i = 0; i < arr.length; i++){
var name = arr[i];
if(name == value){
result = true;
break;
}
}
return result;
}
$('.crt-heading--item').each(function(){
if (checkStyleName($(this).text(),styleList) == true) {
// append the message
//test
alert($(this).text())
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class= "crt-heading--item">Astawia Loafer</li>
<li class= "crt-heading--item">Astawia Loafer</li>
<li class= "crt-heading--item">3</li>
<li class= "crt-heading--item">So On</li>
<li class= "crt-heading--item">5</li>
</ul>
Lets say I have
ThisTextChanges
ThisTextChanges
ThisTextChanges
ThisTextChanges
I want to iterate through these and get the "ThisTextChanges" which are some numbers that changes, most accurately timers.
How can i achieve that? jquery is fine.
They are inside a div with id "main_container".
I need to put the text in a var so the href is importanto to know which var i use for each one.
Lets break the task down into several steps:
Get a handle to all of our links (document.querySelectorAll)
learn how to get the current text of an a tag (childNode[0].nodeValue)
put it all together (Array.from, Array.map)
Get a handle to all of our links:
we will use document.querySelectorAll to get list of all nodes that match our selector. here I'm just going to use the selector a, but you probably have a class that specifies these links vs other links on the page:
var links = document.querySelectorAll('a');
Get the text of a link
This one is a bit more complicated. There are several ways to do this, but one of the more efficient ways is to loop through the child nodes (which will mostly be text nodes), and append the node.nodeValue for each one. We could probably get away with just using the nodeValue of the first child, but instead we'll build a function to loop through and append each.
function getText(link){
var text = "";
for (var i = 0; i < link.childNodes.length; i++){
var n = link.childNodes[i];
if (n && n.nodeValue){
text += n.nodeValue;
}
}
return text;
}
Put it all together
To put it all together we will use Array.map to turn each link in our list into the text inside it. This will leave us with an array of strings. However in order to be able to pass it to Array.map we will have to have an array, and document.querySelectorAll returns a NodeList instead. So to convert it over we will use Array.from to turn our NodeList into an array.
function getText(link){
var text = "";
for (var i = 0; i < link.childNodes.length; i++){
var n = link.childNodes[i];
if (n && n.nodeValue){
text += n.nodeValue;
}
}
return text;
}
var linkTexts = Array.from(document.querySelectorAll('a'))
.map(getText);
console.log(linkTexts);
this is text
this is some more text
You can just add condition in the a selector as follows:
var array = [];
$('#main_container a[href="/example2"]').each(function(){
array.push($(this).html());
});
console.log(array);
You can iterate and store them in an Array
var arr = [];
$("a").each(function(){
arr.push($(this).text());
console.log( arr );
});
you can achieve that in may ways. this example using for loop.
var main_container = document.getElementById("main_container");
var items = main_container.getElementsByTagName("a");
for (var i = 0; i < items.length; ++i) {
// do something.....
}
var array = [];
$('#main_container a').each(function(){
array.push($(this).html());
});
console.log(array);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main_container">
ThisTextChanges 1
ThisTextChanges 2
ThisTextChanges 3
ThisTextChanges 4
</div>
Please try:
$('#main_container > a[href]').each(function() {
var tes = $(this).attr('href').substring(1);
window[tes] = $(this).text();
});
123 will produce var named example1 with value 123, and so on.
In my jsfiddle, I'm trying to sort the items from high to low price by calling the following function:
function myFunction() {
var elements = [].slice.call(document.getElementsByClassName("price"));
elements.sort(function(a, b) {
return parseFloat(b.innerHTML.substring(1)) - parseFloat(a.innerHTML.substring(1));
});
for (var i = 0; i < elements.length; i++)
elements[i].parentNode.appendChild(elements[i]);
console.log(elements);
}
I can see it working when I console.log, but I can't get the results to actually appear on the screen and change the order of my items.
I see in this fiddle with the below JavaScript, it works, why doesn't mine?
$(function() {
$(".offer_item").sort(function(a, b) {
var priceAText = $(a).find(".offer_price").text();
var priceBText = $(b).find(".offer_price").text();
var priceA = parseFloat(priceAText.substring(1, priceAText.length));
var priceB = parseFloat(priceBText.substring(1, priceBText.length));
return priceA > priceB;
}).each(function() {
$(this).appendTo(".offer_list");
});
});
The working example sorts items in the document.
Your code creates an array elements outside of the document with references to elements in de document. You then sort this array, which does not change your document at all.
When you execute elements[i].parentNode.appendChild(elements[i]);, element[i] is still the reference to an element in the document and .parentNode is in the document too, so there you do edit the document.
Can someone show me the javascript I need to use to dynamically create a two dimensional Javascript Array like below?
desired array contents:
[["test1","test2","test3","test4","test5"],["test6","test7","test8","test9","test10"]]
current invalid output from alert(outterArray):
"test6","test7","test8","test9","test10","test6","test7","test8","test9","test10"
JavaScript code:
var outterArray = new Array();
var innerArray = new Array();
var outterCount=0;
$something.each(function () {
var innerCount = 0;//should reset the inner array and overwrite previous values?
$something.somethingElse.each(function () {
innerArray[innerCount] = $(this).text();
innerCount++;
}
outterArray[outterCount] = innerArray;
outterCount++;
}
alert(outterArray);
This is pretty cut and dry, just set up a nested loop:
var count = 1;
var twoDimensionalArray =[];
for (var i=0;i<2;i++)
{
var data = [];
for (var j=0;j<5;j++)
{
data.push("Test" + count);
count++;
}
twoDimensionalArray.push(data);
}
It sounds like you want to map the array of text for each $something element into an outer jagged array. If so then try the following
var outterArray = [];
$something.each(function () {
var innerArray = [];
$(this).somethingElse.each(function () {
innerArray.push($(this).text());
});
outterArray.push(innerArray);
});
alert(outterArray);
A more flexible approach is to use raw objects, they are used in a similar way than dictionaries. Dynamically expendables and with more options to define the index (as string).
Here you have an example:
var myArray = {};
myArray[12]="banana";
myArray["superman"]=123;
myArray[13]={}; //here another dimension is created
myArray[13][55]="This is the second dimension";
You don't need to keep track of array lengths yourself; the runtime maintains the ".length" property for you. On top of that, there's the .push() method to add an element to the end of an array.
// ...
innerArray.push($(this).text());
// ...
outerArray.push(innerArray);
To make a new array, just use []:
innerArray = []; // new array for this row
Also "outer" has only one "t" :-)
[SEE IT IN ACTION ON JSFIDDLE] If that $something variable is a jQuery search, you can use .map() function like this:
var outterArray = [];
var outterArray = $('.something').map(function() {
// find .somethingElse inside current element
return [$(this).find('.somethingElse').map(function() {
return $(this).text();
}).get()]; // return an array of texts ['text1', 'text2','text3']
}).get(); // use .get() to get values only, as .map() normally returns jQuery wrapped array
// notice that this alert text1,text2,text3,text4,text5,text6
alert(outterArray);
// even when the array is two dimensional as you can do this:
alert(outterArray[0]);
alert(outterArray[1]);
HTML:
<div class="something">
<span class="somethingElse">test1</span>
<span class="somethingElse">test2</span>
<span class="somethingElse">test3</span>
</div>
<div class="something">
<span class="somethingElse">test4</span>
<span class="somethingElse">test5</span>
<span class="somethingElse">test6</span>
</div>
Here you can see it working in a jsFiddle with your expected result: http://jsfiddle.net/gPKKG/2/
I had a similar issue recently while working on a Google Spreadsheet and came up with an answer similar to BrianV's:
// 1st nest to handle number of columns I'm formatting, 2nd nest to build 2d array
for (var i = 1; i <= 2; i++) {
tmpRange = sheet.getRange(Row + 1, Col + i, numCells2Format); // pass/fail cells
var d2Arr = [];
for (var j = 0; j < numCells2Format; j++) {
// 1st column of cells I'm formatting
if ( 1 == i) {
d2Arr[j] = ["center"];
// 2nd column of cells I'm formatting
} else if ( 2 == i ) {
d2Arr[j] = ["left"];
}
}
tmpRange.setHorizontalAlignments( d2Arr );
}
So, basically, I had to make the assignment d2Arr[index]=["some string"] in order to build the multidimensional array I was looking for. Since the number of cells I wanted to format can change from sheet to sheet, I wanted it generalized. The case I was working out required a 15-dimension array. Assigning a 1-D array to elements in a 1-D array ended up making the 15-D array I needed.
you can use Array.apply
Array.apply(0, Array(ARRAY_SIZE)).map((row, rowIndex) => {
return Array.apply(0, Array(ARRAY_SIZE)).map((column, columnIndex) => {
return null;
});
});`
I have been trying forever but it is just not working, how can I check the array of urls I got (document.getElementsByTagName('a').href;) to see if any of the websites are in another array?
getElementByTagName gives you a nodelist (an array of nodes).
var a = document.getElementsByTagName('a');
for (var idx= 0; idx < a.length; ++idx){
console.log(a[idx].href);
}
I really suggest that you use a frame work for this, like jquery. It makes your life so much easier.
Example with jquery:
$("a").each(function(){
console.log(this.href);
});
var linkcheck = (function(){
if(!Array.indexOf){
Array.prototype.indexOf = function(obj){
for(var i=0; i<this.length; i++){
if(this[i]===obj){
return i;
}
}
return -1;
}
}
var url_pages = [], anchor_nodes = []; // this is where you put the resulting urls
var anchors = document.links; // your anchor collection
var i = anchors.length;
while (i--){
var a = anchors[i];
anchor_nodes.push(a); // push the node object in case that needs to change
url_pages.push(a.href); // push the href attribute to the array of hrefs
}
return {
urlsOnPage: url_pages,
anchorTags: anchor_nodes,
checkDuplicateUrls: function(url_list){
var duplicates = []; // instantiate a blank array
var j = url_list.length;
while(j--){
var x = url_list[j];
if (url_pages.indexOf(x) > -1){ // check the index of each item in the array.
duplicates.push(x); // add it to the list of duplicate urls
}
}
return duplicates; // return the list of duplicates.
},
getAnchorsForUrl: function(url){
return anchor_nodes[url_pages.indexOf(url)];
}
}
})()
// to use it:
var result = linkcheck.checkDuplicateUrls(your_array_of_urls);
This is a fairly straight forward implementation of a pure JavaScript method for achieving what I believe the spec calls for. This also uses closures to give you access to the result set at any time, in case your list of urls changes over time and the new list needs to be checked. I also added the resulting anchor tags as an array, since we are iterating them anyway, so you can change their properties on the fly. And since it might be useful to have there is a convenience method for getting the anchor tag by passing the url (first one in the result set). Per the comments below, included snippet to create indexOf for IE8 and switched document.getElementsByTagName to document.links to get dynamic list of objects.
Using Jquery u can do some thing like this-
$('a').each(function(){
if( urls.indexOf(this.href) !- -1 )
alert('match found - ' + this.href );
})
urls is the your existing array you need to compare with.