I hate my life. I'm trying to complete a simple tutorial that takes an empty div and adds a bunch of cat images to it. The details of the cats are contained within arrays, which are applied to each instance of a cat while iterating through a simple numeric array.
At the bottom of the script, you'll see that I'm alerting the innerHTML of the main container div which all of these images and header tags are supposed to be appended to. While the alert dialogue shows the correct HTML, the divs that are being generated lack the img and h1 elements, despite my attempts to get them to append properly. All that seems to be getting passed through are the h1 text nodes.
Can anyone please explain why I'm not getting the results I'm looking for here:
var cats_array = [1,2,3,4,5];
var cats_names = ['Jim','Joe','Jon','Larry','Mike'];
var cats_urls = [
'https://www.royalcanin.com/~/media/Royal-Canin/Product-Categories/cat-senior-landing-hero.ashx',
'http://i2.mirror.co.uk/incoming/article6745691.ece/ALTERNATES/s615b/Black-cat.jpg',
'https://www.royalcanin.com/~/media/Royal-Canin/Product-Categories/cat-breed-landing-hero.ashx',
'https://www.royalcanin.com/~/media/Royal-Canin/Subpage-Hero-Images/150327_Hero_kit.ashx',
'https://s-media-cache-ak0.pinimg.com/736x/a7/92/d8/a792d8ec74bbcc819bb65c7bad1f8dee.jpg'
];
for (cat in cats_array) {
var catgame_div = document.getElementById('catgame');
var num_div = document.createElement('DIV');
var img_el = document.createElement('IMG');
var h1_el = document.createElement('H1');
var current_cats_name = cats_names[cat];
var h1_text_node = document.createTextNode(current_cats_name);
h1_el.appendChild(h1_text_node);
img_el.src = cats_urls[cat];
num_div.appendChild(img_el);
var img_parent = img_el.parentNode;
img_parent.insertBefore(h1_el, img_el);
alert(img_parent.innerHTML);
catgame_div.appendChild(num_div);
}
<div id="catgame"></div>
Thank you
Related
I have built a todo list using Vanilla Javascript and localstorage. The todo list has the following key, value:
key: todolist
value: [[\"id:0\",\"title:buy groceries\",\"done:false\"],
[\"id:1\",\"title:pick up dry cleaning\",\"done:false\"],
[\"id:2\",\"title:walk dog\",\"done:false\"]]
The values display just great on my website (only the title is displaying) but when I refresh the page, the whole object is displaying.
Before page refresh:
buy groceries
pick up dry cleaning
walk dog
After page refresh:
id:0,title:buy groceries,done:false
id:1,title:pick up dry cleaning,done:false
id:2,title:walk dog,done:false
Obviously, after a page refresh I only want the title to display on the list inside the li tag. It's a head scratcher because it only does this after a page refresh.
How do I get only the title to display after page refresh?
I'm somewhat of a newbie to Javascript and can't quite figure out how to make this happen. I've been Googling for almost two days and ready to tear my hair out!!
// set up some variables for elements on the page
const form = document.querySelector('form');
const ul = document.querySelector('ul');
const button = document.querySelector('button');
const input = document.getElementById('item');
// Fix empty array when script runs by making a conditional statement that
checks if localStorage already exists
//let itemsArray = localStorage.getItem('todolist') ?
JSON.parse(localStorage.getItem('todolist')) : [];
let todolist;
if (localStorage.getItem('todolist')) {
itemsArray = JSON.parse(localStorage.getItem('todolist'));
} else {
itemsArray = [];
}
localStorage.setItem('todolist', JSON.stringify(itemsArray));
const data = JSON.parse(localStorage.getItem('todolist'));
//alert(typeof(data));
// function that creates an li element, sets the text of the element to the
parameter, and appends the list item to the ul.
const liMaker = (text) => {
const li = document.createElement('li');
li.textContent = text;
ul.appendChild(li);
// Create a "close" button and append it to each list item
var span = document.createElement("SPAN");
var txt = document.createTextNode("🗑️");
span.className = "close";
span.appendChild(txt);
li.appendChild(span);
for (i = 0; i < close.length; i++) {
close[i].onclick = function() {
var div = this.parentElement;
div.style.display = "none";
}
}
}
// Event listener that submits the value of the input
form.addEventListener('submit', function (e) {
e.preventDefault();
var id = "id:" + itemsArray.length;
var title = "title:" + input.value;
var done = "done:" + "false";
itemsArray.push([id, title, done]);
//itemsArray.push(input.value);
localStorage.setItem('todolist', JSON.stringify(itemsArray));
liMaker(input.value);
input.value = "";
});
data.forEach(item => {
liMaker(item);
});
// clear items from todolist
button.addEventListener('click', function () {
localStorage.removeItem("todolist");
while (ul.firstChild) {
ul.removeChild(ul.firstChild);
}
itemsArray = [];
});
One thing I should note, the page refresh issue doesn't happen when I change the following:
itemsArray.push([id, title, done]);
to the following:
itemsArray.push(input.value);
The main reason you are having this problem is because your JSON is not formatted properly.
The reason you are only seeing the problem on page refresh is because at this point local storage contains the "todolist" key with your improperly formed JSON. This JSON value is then stored in your data variable and output to your list items in an undesired way (as you described).
Otherwise (without page refresh) the text of your list items is coming directly from the text in the input field.
If you make the following changes to your code it will work properly (I have tested it). Hope it helps.
JavaScript comments
Firstly i'm not sure if this just happened when you posted your code here but if your comments in JS extend across two lines or more then you need to put // on all lines.
For example in your code you have:
//function that creates an li element, sets the text of the element to the
parameter, and appends the list item to the ul.
and it should be:
//function that creates an li element, sets the text of the element to the
//parameter, and appends the list item to the ul.
The format of your JSON
Secondly I see a problem with the way the JSON is formatted.
It should look something like the following (before slashes are added).
[{"id":0,"title":"buy groceries","done":false},
{"id":1,"title":"pick up dry cleaning","done":false},
{"id":2,"title":"walk dog","done":false}]
Note each property name (i.e "id", "title" and "done") should have double quotes and each property value (e.g "buy groceries") should have double quotes (unless its an int or a boolean etc).
You can use a tool called JSLint to check your JSON is valid.
So in order to create your JSON in the right format (when the form is submitted)
change these lines of code:
var id = "id:" + itemsArray.length;
var title = "title:" + input.value;
var done = "done:" + "false";
itemsArray.push([id, title, done]);
to the following:
var idValue = itemsArray.length;
var titleValue = input.value;
var doneValue = false;
itemsArray.push({"id": idValue, "title": titleValue, "done" : doneValue});
Iterating through the array
Your data variable will contain the array of todolist objects (from local storage).
So therefore the item you have in the following code will contain the full object i.e {"id":0,"title":"buy groceries","done":false}.
So in order to get the title here you need to say item.title. (This will work now that the JSON will be properly formatted):
data.forEach(item => {
//log the item to check it.
console.log(item);
liMaker(item.title);
});
I'm trying to use Google Apps Script to get the hyperlink from a specific string found in this Google Doc.
The string is ||stock||
The hyperlink is https://www.cnbc.com/quotes/?symbol=aapl&qsearchterm=aapl
Any help is greatly appreciated.
The code I'm currently using
function docReport() {
var doc = DocumentApp.openByUrl('https://docs.google.com/document/d/1XNiqgJ_hM2SWjoR-OTsq1w-ZFKvTIERDIs_NOWJpckY/edit');
var body = doc.getBody();
Logger.log(body.getParagraphs().length);//get the number of paragraphs
//https://www.udemy.com/apps-script-course/learn/v4/t/lecture/10208226?start=0
for (var x=0;x<body.getParagraphs();X++) {
var el = body.getChild(x);
Logger.log(el.getText());
}
var bodyText = body.getText();
var words = bodyText.match(/\S+/g); // get word count for body - https://stackoverflow.com/questions/33338667/function-for-word-count-in-google-docs-apps-script
Logger.log(words.length); // retruns # of words
var paragraphAll = body.getParagraphs(); // gets all paragraph objects in a document
Logger.log(paragraphAll);
var paragraphText = paragraphAll[1].getText().match(/\S+/g);
Logger.log(paragraphText.length); // retruns # of words in a paragraph
}
You want to retrieve hyperlink of the text of ||stock||.
If my understanding is correct, for example, how about this sample script? In your situation, the text value which has a link has already been known. The sample script uses this situation.
By the way, from your question, I'm not sure whether there are several values of ||stock|| in the document. So this sample script supposes that there are several values of ||stock|| in the document.
I think that there are several answers for your situation. So please think of this as one of them.
Sample script:
var searchValue = "\\|\\|stock\\|\\|"; // Search value
var body = DocumentApp.openByUrl('https://docs.google.com/document/d/1XNiqgJ_hM2SWjoR-OTsq1w-ZFKvTIERDIs_NOWJpckY/edit').getBody();
var searchedText = body.findText(searchValue);
var urls = [];
while (searchedText) {
var url = searchedText.getElement().asText().getLinkUrl(searchedText.getStartOffset());
urls.push(url);
searchedText = body.findText(searchValue, searchedText);
}
Logger.log(urls) // Results
Note:
If there is only one search value in the document, you can also use the following script.
var searchValue = "\\|\\|stock\\|\\|";
var body = DocumentApp.openByUrl('https://docs.google.com/document/d/1XNiqgJ_hM2SWjoR-OTsq1w-ZFKvTIERDIs_NOWJpckY/edit').getBody();
var searchedText = body.findText(searchValue);
var url = searchedText.getElement().asText().getLinkUrl(searchedText.getStartOffset());
Logger.log(url)
References:
findText()
getLinkUrl()
If I misunderstand your question, please tell me. I would like to modify it.
This is an Apps Script that goes through a webpage and collects img urls that are inside some div of a special class.
function getIMGs(url){
var url = 'url'
var result = UrlFetchApp.fetch(url);
if (result.getResponseCode() == 200) {
var doc = Xml.parse(result, true);
var bodyHtml = doc.html.body.toXmlString();
var doc = XmlService.parse(bodyHtml);
var html = doc.getRootElement();
var thumbs = getElementsByClassName(html, 'thumb');
var sheet = SpreadsheetApp.getActiveSheet();
for (i in Thumbs) {
var output = '';
var linksInMenu = getElementsByTagName(thumbs[i], 'img');
for(i in linksInMenu) {
output += XmlService.getRawFormat().format(linksInMenu[i]);
}
var linkRegExp = /data-src="(.*?)"/;
var dataSrc = linkRegExp.exec(output);
sheet.appendRow([dataSrc[1]]);
}
}
So first the code gets the html, and uses an auxiliary function to get certain elements, which look like this:
<div class="thumb"><div class="loader"><span class="icon-uniE611"></span></div><img src="//xxx" data-src="https://xxx/8491a83b1cacc2401907997b5b93e433c03c91f.JPG" data-target="#image-slider" data-slide-to="0"></div>
Then the code gets the img elements, and finally extracts the data-src address via RegExp.
While this kinda works, I have a problem:
1) After 9 loops it crashes, on the appendRow line, as the last 4 Thumbs elements don't have data-src, hence what i'm trying to write into the spreadsheet is null.
Any solution for this? I have fixed it for the moment by just doing 9 iterations only of the For loop, but this is far from optimal, as it's not automated and required me to go through the page to count the elements with data-src.
Also, any suggestion of a more elegant solution will be appreciated! I will be really grateful for any helping hand!
Cheers
I have an element displaying an image on an HTML page. This element's source is one of many different images in a JavaScript array.
I already have a script for looping through the images, creating a slideshow effect, but now I want to manually flick through the images with buttons.
This is my code so far, but I get no response when clicking the button.
function nextup()
{
imgs = [];
imgs[0] = "/snakelane/assets/images/thumb/_1.jpg"; imgs[10] = "/snakelane/assets/images/thumb/_19.jpg";
imgs[1] = "/snakelane/assets/images/thumb/_2.jpg"; imgs[11] = "/snakelane/assets/images/thumb/_20.jpg";
imgs[2] = "/snakelane/assets/images/thumb/_3.jpg"; imgs[12] = "/snakelane/assets/images/thumb/_21.jpg";
imgs[3] = "/snakelane/assets/images/thumb/_4.jpg"; imgs[13] = "/snakelane/assets/images/thumb/_22.jpg";
imgs[4] = "/snakelane/assets/images/thumb/_5.jpg"; imgs[14] = "/snakelane/assets/images/thumb/_23.jpg";
imgs[5] = "/snakelane/assets/images/thumb/_6.jpg"; imgs[15] = "/snakelane/assets/images/thumb/_24.jpg";
imgs[6] = "/snakelane/assets/images/thumb/_7.jpg"; imgs[16] = "/snakelane/assets/images/thumb/_25.jpg";
imgs[7] = "/snakelane/assets/images/thumb/_8.jpg"; imgs[17] = "/snakelane/assets/images/thumb/_26.jpg";
imgs[8] = "/snakelane/assets/images/thumb/_9.jpg"; imgs[18] = "/snakelane/assets/images/thumb/_27.jpg";
imgs[9] = "/snakelane/assets/images/thumb/_32.jpg"; imgs[19] = "/snakelane/assets/images/thumb/_28.jpg";
var pic = document.getElementById("picbox");
for(i =0; i < imgs.length; i++) {
var current = indexOf(pic.src);
var next = Math.round(current + 1);
pic.src = imgs[next];
}
}
Can anyone tell me what's wrong with my code or suggest a better way?
Multiple problems in the approach you had used. Have a look at the modified function below. Let me know if you need explanation with anything.
The following code will use an array containing image URLs and later assign in a sequential manner to an img tag on click. Enjoy!
Here you can try to see the output.
function nextup(){
//Initialized img array with 10 images, you can do it any way you want to.
var imgs = [];
for(i=0;i<10;i++){
imgs[i] = "http://lorempixel.com/output/cats-q-c-100-100-"+(i+1)+".jpg";
}
//Fetch the pic DOM element by ID
var pic = document.getElementById("picbox");
//Know what is position of currently assigned image in array.
var current = imgs.indexOf(pic.src);
var next = 0;
//Handle case if no image is present, the initial case.
if(current!=-1){
next = (current + 1)%(imgs.length);
}
//Assign the next src
pic.src = imgs[next];
}
//Scoped outside to call the function first time on load.
nextup();
I found the following problems in your code:
You tried to use indexOf without specifying the array in which the search has to be performed. Imagine s school principal asking someone to go find if John is present in the classroom without specifying a specific classroom.
For iterating through array you used a next variable which could have been a good idea if you needed an endless loop. But here since we are limited to 10 or 20 images we need to make sure that if the currently selected image is the last one, we find that next goes to 21 (assuming a total of 20 images.) and this would try to access a variable out of bounds.
Hence I've used the mod operator %.
For reference in JavaScript, 5%10 would return 5 , 15%10 would return 5 and so on. Read more about the mod operator HERE.
okay i have come across a simple javascript code that will search all the hyperlinks in a page which works briliantly fast. the only problem is that the browser freezes when it tries to remake these links in a div, no error just as soon as i push the button the browser refuses to load. as you can see it gets the input from a form then searches every hyperlink for these terms then is supposed to populate a div with links but it doesn't. the code is as follows.
function search0(){
var lists = document.getElementsByTagName("a");
for (var i = 0; i < lists.length; i++) {
var output = lists[i];
var team1 = document.getElementById("search1").value;
var matchPos1 = output.innerHTML.search(team1);
if(matchPos1 != -1){
var team2 = document.getElementById("search2").value;
var matchPos2 = output.innerHTML.search(team2);
if(matchPos2 != -1){
var elem1 = document.createElement("a")
var styleattr=document.createAttribute("href");
styleattr.nodeValue=output;
elem1.setAttributeNode(styleattr);
var text1 = document.createTextNode(output.innerhtml);
elem1.appendChild(text1);
var parentdiv = document.getElementById("frame2");
parentdiv.appendChild(elem1);
}
}
}
}
You are creating an infinite loop.
The nodeList you create with document.getElementsByTagName("a") is live i.e. if you add a link to the page it will appear in this list automatically! Yes, that's right, even without requerying. Here's a reference doc.
You are adding links to the nodeList which are then matched and added to the end on the nodeList which are then matched and so on and so on
To do what you want to do you should create an initial array of links like this.
//creates a real js array from a nodelist
var list = Array.prototype.slice.call( document.getElementsByTagName("a"), 0 );
Here is an explanation of Array.prototype.slice.call
Also change case-sensitive mistake:
var text1 = document.createTextNode(output.innerhtml);
To
var text1 = document.createTextNode(output.innerHTML);