Create a certain number of elements based on integer with jQuery - javascript

I have a json file with an items category that lists items that are currently listed via an array. This item list is updated every few hours.
ex:
{
"items": [
{
"name": "Blueberry",
"img": "website.com/blueberry.png"
},
{
"name": "Raspberry",
"img": "website.com/raspberry.png"
}
]
}
Each item in the array is given an image and description. What I want to do is for every item, create an <img src='(item image url)'> element for the image that is listed inside the item, and create a <p> element for every item for the description that is listed.

You can achieve this with JQuery with a for loop, and create the elements dynamically using the JQuery function $(...) (Tutorial here)
In the end, You'll probably end up with something like this:
// fetch the items from the url
$.getJSON("your url").then(function(response){
//cycle through all the items in the array
for(var i = 0; i < response.items.length; i++){
// create image
var image = $('<img>').attr("src", response.items[i].img);
// make sure to set the attribute using the "attr" function
// to avoid Cross Site Scripting (see the link below)
// create text element
var text = $('<p>').text(response.items[i].name);
// append the items to the container
$("container element").append(image).append(text);
}
});
About Cross Site Scripting

To dinamically create elements in Pure JavaScript you can use the document.createElement
var imagesContainer = document.createElement('div')
for(var i = 0; i < array.length; i++){
var img = document.createElement('img'),
p = document.createElement('p');
img.setAttribute("src", array[i].img);
p.appendChild(document.createTextNode(array[i].name));
imagesContainer.appendChild(img);
imagesContainer.appendChild(p);
}
i think is this you are looking for :)

Related

getElementsByTagName is not returning all the images why?

I'm trying to get all the img element from some website.
I opened the chrome dev tools console and put the following code which is,
var imgs = document.getElementsByTagName("img");
var i;
for (i = 0; i < imgs.length; i++) {
console.log(imgs[i]);
}
Yes, code works and returns lists of images in console but not fully.
I noticed that some img elements are not returned.
the parts that is not returened is in the following image.(the links is here)
I really wonder why these guys are not returned. Why is that?
As I said in the comment, there are no <img> elements, those are <a> elements with a css background image.
If you want to get those image urls, simply select the <a> elements, access their background-image css property and extract the urls:
var aElems = document.querySelectorAll(".J_Prop_Color a");
var images = [];
for(var i = 0; i < aElems.length; i++) {
images.push(aElems[i].style.backgroundImage.replace("url(", "").replace(")", "").replace(/\"/gi, ""))
}
console.log(images);
The .replace("url(", "").replace(")", "").replace(/\"/gi, "") part is used to remove the surrounding url("...") as per this SO answer.
Note 1: The resulting urls appear to be protocol-relative urls, where they start with // rather than an explicit protocol like https://, you may want to prepend "https:" to them before using them.
Note 2: The resulting urls are of thumbnails rather than of the full-sized images, remove the _(number)x(number).jpg part of those urls by using this replace: replace(/_\d+x\d+\.[^.]+$/, "") to get the full-size image urls:
images.push("https:" + aElems[i]
.style.backgroundImage
.replace("url(", "").replace(")", "").replace(/\"/gi, "")
.replace(/_\d+x\d+\.[^.]+$/, "")
);
The problem if you open the console and inspect the elements is like someone mention in the comments that there are no image tags, if you check the console, you will see:
a div.
You want to do:
var imgs = document.getElementsByID(IDVALUES);
var i;
for (i = 0; i < imgs.length; i++) {
console.log(imgs[i]);
}
the id is stored in the div id something like 'ks-component-??'
Most likely the answer above will not give you want since you want multiple images you would want to create an array and push the corresponding elements to it.
var img1 = ....
var img2 = etc....
....
let arr = [];
arr.push(img1);
arr.push(img2);
....
for (i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
Where the ... means the list or all the variables you need

Is there any way to cyclically update only a <div> content in pure Javascript?

I'm using a div with a <li> element inside where I add some dynamically created elements (localStorage keys to be more specific). I want to update the div every "x" seconds but only the <div>, not the whole page. I know that it can be done with Ajax and JQuery ($( "#here" ).load(window.location.href + " #here" );).
But is there any way to do this whit pure js?
UPDATE
The specific case is that im picking all the localstorage keys and appending them to a list inside a div. When i use like this (window.onload) it works fine. But I want to update it cyclically. If i use a "setinterval" or a button to call the function the previous keys appends repeatedly. (like: file 1.... then: file 1, file 1 file 2 ... then: file 1 file 1 file 2 file 1 file 1 file 1 file 2 file 3)
window.onload = function cargararchivos() {
localstorage = []
var keys = Object.keys(localStorage);
for (let i = 0; i < keys.length; i++) {
var elemento_lista = document.createElement('li')
elemento_lista.innerHTML = keys[i]
var lista = document.getElementById('lista_archivos')
lista.appendChild(elemento_lista)
localstorage[ keys[i] ] = localStorage.getItem( keys[i] )
elemento_lista.onclick = function()
{alert(JSON.parse(localStorage[keys[i]]))}}
};
This can be done using the setInterval function. It executes a function of your choice after a pre-determined amount of time.
To do this your DIV must have an unique ID, so we can access it using Javascript's getElementById() method.
Here's a simple example, which updates a div with the current time every 1000 milliseconds:
function update() {
document.getElementById("myDiv").innerHTML = new Date();
}
var interval = setInterval(update, 1000);
<div id="myDiv">
</div>
The reason your method works the first time, but doesn't work after that is because the method adds DOM nodes. After the second call, you're seeing DOM nodes from both the first call and second call. After the third call, you'd see nodes from the first, second, and third calls... and so on.
If you want to repeatedly call a method like cargararchivos() that adds DOM nodes, you must first remove any DOM elements that have been previously added. I've updated your code, assuming lista_archivos starts empty (no child elements):
function cargararchivos() {
localstorage = []
var keys = Object.keys(localStorage);
var lista = document.getElementById('lista_archivos')
// Ensure any previously added DOM nodes are removed.
while (lista.firstChild) {
lista.removeChild(lista.firstChild);
}
for (let i = 0; i < keys.length; i++) {
var elemento_lista = document.createElement('li')
elemento_lista.innerHTML = keys[i]
lista.appendChild(elemento_lista)
localstorage[ keys[i] ] = localStorage.getItem( keys[i] )
elemento_lista.onclick = function()
{alert(JSON.parse(localStorage[keys[i]]))}
}
};

Javascript code doesn't load the page

I have a little problem with this javascript code, when I add more site on the list, the page doesn't load. I have to add more than 200 site.
I'm a noob with javascript. Can someone explain what is the problem, what
I'm doing wrong?
<script language="JavaScript" type="text/javascript">
var a = new Array(
'notiziepericolose.blogspot.it',
'ilcorrieredellanotte.it',
'ilmattoquotidiano.it',
'ilfattonequotidiano.com',
'rebubblica.altervista.org',
'coriere.net'
);
var aa = a.slice();
aa.sort();
document.write("<ol>");
document.write("<b>");
for (i = 0; i < a.length; i=i+1) {
document.write('<li id="demo'+i+'">'+a[i]+'</li>');
}
document.write("</b>");
document.write("</ol>");
</script>
I guess the first thing is that document.write is very rarely used now as there a better and more efficient ways of adding things (elements, text etc) to the DOM (more on that later). In addition, in your case, what you don't realise is that document.write is not like echo or println; each time it is used it clears the document, which is probably why you're not seeing anything appear. In other words, The results of multiple document.writes are not cumulative.
The second thing is that there are better ways of "labelling" elements than with ids, particularly if there are a lot of them on the page like you'll have. Again, there are now much better ways of targetting elements, or catching events than there were ten or fifteen years ago.
So, let's talk about your code.
You can quickly create a array using the [] brackets.
var arr = [
'notiziepericolose.blogspot.it',
'ilcorrieredellanotte.it',
'ilmattoquotidiano.it',
'ilfattonequotidiano.com',
'rebubblica.altervista.org',
'coriere.net'
];
You don't have to create a copy of the array in order to sort it - it can be done in place:
arr.sort();
I'm going to keep your loop but show you a different way of concatenating strings together. Some people prefer adding strings together, but I prefer this way, and that's to create an array of the little parts of your string and then join() them together**.
// Set l as the length, and create an output array called list
for (var i = 0, l = arr.length, list = []; i < l; i++) {
// I've changed things here. I've added a class called item
// but also changed the element id to a data-id instead
var li = ['<li class="item" data-id="', i, '">', arr[i], '</li>'];
// Push the joined li array of strings into list
list.push(li.join(''));
}
Assuming you have an element on your page called "main":
HTML
<div id="main"></div>
JS
You can add the list array as an HTML string to main by using [insertAdjacentHTML] method:
var main = document.getElementById('main');
// Note that I've given the ordered list an id called list
var HTML = ['<ol id="list"><b>', list.join(''), '</b></ol>'].join('');
main.insertAdjacentHTML('beforeend', html);
OK, so that's pretty easy. But I bet you're asking how you can target the individual items in the list so that if I click on one of them it alerts what it is (or something).
Instead of adding an event listener to each list item (which we could but it can work out performatively expensive the more items you have), we're going to attach one to the ol element we added that list id to and catch events from the items as they bubble up:
var ol = document.getElementById('list');
Then an event listener is added to the list that tells us what function (checkItem) is called when a click event is raised:
ol.addEventListener('click', checkItem);
Our function uses the event (e) to find out what the event's target was (what item was clicked), and alerts its text content.
function checkItem(e) {
alert(e.target.textContent);
}
You can see all this working in this demo. Hope some of this was of some help.
** Here's another way of sorting, and looping through the array using reduce:
var list = arr.sort().reduce(function (p, c, i) {
return p.concat(['<li class="item" data-id="', i, '">', c, '</li>']);
}, []).join('');
DEMO
if ES6 is possible for you, you can do it like this:
var a = new Array(
'notiziepericolose.blogspot.it',
'ilcorrieredellanotte.it',
'ilmattoquotidiano.it',
'ilfattonequotidiano.com',
'rebubblica.altervista.org',
'coriere.net');
var aa = a.slice();
var mL = document.getElementById('mylist');
aa.sort().map(el => {
var li = document.createElement("li");
var b = document.createElement("b");
var t = document.createTextNode(el);
b.appendChild(t);
li.appendChild(b);
mL.appendChild(li);
});
<ol id="mylist"></ol>
If you're using an Array, you can use a forEach instead of a loop.
var domUpdate = '';
var websites = ['notiziepericolose.blogspot.it','ilcorrieredellanotte.it','ilmattoquotidiano.it','ilfattonequotidiano.com','rebubblica.altervista.org','coriere.net'];
websites.forEach(function(website, index){
domUpdate += '<li id="website-' + ( index + 1 ) + '"><b>' + website + '</b></li>';
});
document.getElementById('hook').innerHTML = '<ol>' + domUpdate + '</ol>';
<div id="hook"></div>
I'm thinking document.write is the wrong choice here, as it seems to be clearing the document. https://developer.mozilla.org/en-US/docs/Web/API/Document/write Probably you want to bind the new content to existing html through document.getElementById or something like that

create div with content from array of objects?

So I have:
arrayofobj = [
{
property: "string", // "card" object with different data types
property2: integer
},
{
property: "string", // "card" object with different data types
property2: integer
},
{
//etc more cards
}
];
var playDeck = arrayofobj.slice(0);//creates copy of deck to "use" for game
shuffled(playDeck);//shuffles deck
playerHand = [];//empty array to save cards into
deal10(playDeck);//removes the 1st 10 out of playDeck and puts in playerHand
Now from the 10 that get drawn into playerHand, I'm trying to display them on screen. I have a field set up with:
<div id="playerHand"></div>
My attempt which hasn't been very successful:
for (var i = 0; i < playerHand.length; i++) {
content = playerHand[i];
x = document.getElementById('playerHand').appendChild(document.createElement('div'));
x.className = 'card' + [i];
document.getElementsByClassName('card' + [i]).textContent = content;
}
I haven't been able to achieve the desired effect. I'm a beginner as far as programming goes so I'm open to constructive criticism. So if you haven't gathered already what I'm trying to do is display each object or card on the screen as its own div (so that I can add click handlers to them and have the clicked one played on the screen... for example.)
I think the main problem is getElementsByClassName, which returns an array and not the actual reference to the element. See below:
var data, content, container, element;
container = document.getElementById('container');
data = [
{
name: "stringa"
},
{
name: "stringb"
}
];
for (var i = 0; i < data.length; i++) {
// Are you accessing an actual property in your code? It seems
// you are just referencing the whole object.
content = data[ i ].name;
// Just save the createElement reference ;)
element = document.createElement('div');
// Why are you appending [i] instead of i directly?
element.className = 'card' + i;
// By saving the element directly we don't have to query for
// the class in this step. The other problem was probably that
// `getElementsByClassName` returns an array, so you would have
// to call: vvv
// document.getElementsByClassName('card' + [i])[ 0 ]
element.textContent = content;
container.appendChild( element );
}
Obligatory JSFiddle: http://jsfiddle.net/tgtefsrm/1/

How to find a text frame in Indesign CS6 with javascript? (I can query by text-frames containing a particular paragraph style or what?)

I was looking about indesign scripts and I have not found anything about this topic, which I think is important. So here it is my question:
How to find a text frame in Indesign CS6 with javascript?
I can query by text-frames containing a particular paragraph style?
I can set some kind of name on my text-frame (which is in the master page) to get it in javascript?
Ok, after some research I've found that you can set a label to an object by opening the "Script label", selecting the object you want and the write the label-name into the "Script label" panel. You don't have to click ok or nothing, it will automatically save the label for that object.
After you do that, you can check the ".label" property on objects and when you will find the object with that label, you found it. Multiple objects can have the same label.
Below is an example with a helper function "selectWhere":
var document = app.documents.item(0); // active document
var allTextFrames = toArray(document.textFrames);
var textFrames = selectWhere("chapterLetter", "label", allTextFrames);
function selectWhere(value, key, array){
var i = array.length; var t; var filtered = [];
while(i--){
t = array[i];
if(t && t[key] == value){
filtered.push(t);
}
}
return filtered;
}
function toArray(objects){
var i = objects.length; var array = [];
while(i--){
array.push(objects[i]);
}
return array;
}
1)The answer to your first question is:-
solved in this thread
2)Now you get array of textframes.So you can query to get the paragraph style on the text frames
var paraStyle1 = app.activeDocument.paragraphStyles.itemByName("styleA");
var paraStyle2 = app.activeDocument.paragraphStyles.itemByName("styleB");
if (paraStyle1.isValid && paraStyle2.isValid)
3) Through paraStyle1.name you can get the name of the style.See parastyle1 is the paragraph style object so get the style object and find by this property.

Categories

Resources