I have an array that contains a bunch of Widget Ids[s1,s2,s3...etc]. This array can vary as in sometimes it can have 5 ids and other times it can have 2 ids etc.So basically as i am looping through this array I want to be able to create pages dynamically for every id in the array.
This is the basic format of the page that i want to be able to create dynamically for every id.
<!--id should eqqual id# like s1,s2,s3,etc -->
<div data-role="page" id="page5">
<div data-role="header" data-position="fixed">
<a data-iconpos="notext" href="#" data-role="button" data-icon="flat-menu"></a>
<h1>BasketBall Fanatico</h1>
<a data-iconpos="notext" href ="#page2" data-role="button" data-icon="home" title="Home">Home</a>
</div>
<div data-role="content">
<ul data-role="listview" data-inset="true">
<li data-role="list-divider" data-theme="b">Raptors Score</li>
<li><h2>0</h2></li>
</ul>
</div>
</div>
This is the loop where i am iterating through the ids in the array and trying to add pages dynamically.This is what i have attempted in order to achieve my result but have failed.
for(var i=0; i<widgetId.length; i++){
var makePage = $("<div data-role='page' id="+widgetId[i]+">
<div data-role='header' data-position='fixed'><a data-iconpos='notext' href='#' data-role='button' data-icon='flat-menu'></a>
<h1>BasketBall Fanatico</h1><a data-iconpos='notext' href='#page2' data-role='button' data-icon='home' title='Home'>Home</a></div>
<div data-role='content'><ul data-role='listview'data-insert='true'><li data-role='list-divider' data-theme='b'>Raptors Score</li>
<li><h2>0</h2></li></ul></div></div>");
makePage.appendTo($mobile.pageContainer);
}
I am using the chrome console window and its telling me: Uncaught SyntaxError: Unexpected token< . However upon looking at my code i don't see where the error could be. Also is my approach correct for creating pages dynamically? All answers are highly appreciated .
I am new to jquery and web dev in general so apologize in advance.
I had to dynamically add products to an auction page and I used the following code. The issue was that I didn't know exactly how many products I was going to display on the page.
/* takes element type and all options for element returns html string for the element
* Arg1 is the type of element to create
* Options is an array/list of key-value pairs. The even numbered objects in the array
* will represent the attribute name, the odd elements will be the value of the attribute*/
function addElement(ELEMENT, options)
{
var element = document.createElement(ELEMENT); //create the element
var i = 0;//iterate through the array and set each element
while(i < options.length)
element.setAttribute(options[i++], options[i++]);
return element;
}
Then in my index file I do this 'fullProductList' is a div that will hold all divs containing products:
//get the html for each item and write it to the page
for( var i = 0; i < productList.length; i++)
$("#fullProductList").append(getProductHTML(productList[i], i));
Here is getProductHTML:
/* creates a parent div for each product that will be displayed on the page
* a picture is displayed in the parent div then a child div is created
* in order to display product info and a bid button which happens in another function*/
function getProductHTML(prod, id)
{//create the parent div
var html = document.createElement('div');
html.className = 'singleProduct';
html.id = id;
//append the picture to the parent div
html.appendChild(addElement('img', ['SRC', prod.pic, 'ALT', prod.name, "height", "400px", 'class', 'pic']));
//create div for product title
var title = document.createElement('div');
title.className = 'prodTitle';
title.innerHTML = '<b>'+prod.name + "<b><BR>" ;
html.appendChild(title);
html.appendChild(writeProductInfo(prod));//this creates another child div for the product data
return html;
}
Instead of numbering the div's myself I used an ID from the DB which was provided with each product. I didn't include the code for writeProductInfo because I think with this you should be able to see how I made it work. I know that your situation will be different from the situation I encountered but I hope this helps.
I have figured out the error after several trial and error. It seems that the cause of the error was that i had the page structure on different lines . so for instance if everything is on the same line it works fine like this.
for(var i=0; i<widgetId.length; i++){
var makePage = $("<div data-role='page' id="+widgetId[i]+"><div data-role='header' data-position='fixed'><a data-iconpos='notext' href='#' data-role='button'data-icon='flat-menu'></a> <h1>BasketBall Fanatico</h1><a data-iconpos='notext' href='#page2' data-role='button' data-icon='home' title='Home'>Home</a></div> <div data-role='content'><ul data-role='listview'data-insert='true'><li data-role='list-divider' data-theme='b'>Raptors Score</li><li><h2>0</h2></li></ul></div></div>");
makePage.appendTo($.mobile.pageContainer);
}
I don't know what it is but when everything is in on line it seems to be working fine. I hope this can help someone in the future with a similar error or someone who is looking to create pages dynamically in general.
Related
I've looked over numerous Stack Overflow discussions on getElementsByClassName but can't seem to find anything that can help me resolve this particular issue. To explain . . .
I have the following javascript
field_to_update.innerHTML = '';
var elOptNew = document.createElement('option');
elOptNew.text = '---'
elOptNew.value = '';
field_to_update.add(elOptNew);
field_to_update.options[0].selected = true;
var track_names = document.getElementsByClassName('wpaudio');
for (i=0; i<track_names.length; i++) {
var track_name = track_names[i].innerHTML;
var elOptNew = document.createElement('option');
elOptNew.text = track_name.replace("&", "&");
elOptNew.value = track_name;
field_to_update.add(elOptNew); // standards compliant; doesn't work in IE
}
and I am looking to extract the names of a list of audio files using the line var track_names = document.getElementsByClassName('wpaudio') which refers to the following code included in the functions.php file of a wordpress child theme.
<ol id="audioFilesList" class="reactionFormAudio">
<?php
// loop through rows (parent repeater)
while( have_rows('song_upload') ): the_row(); ?>
<li><p class="wpaudio" name="audioFileName"><?php the_sub_field('track_name'); ?></p><br>
The above scenario works fine. BUT i have decided to not use the ordered list of audio files as listed above - but instead us the default audio playlist that can be created within a wordpress post, which produces the following code:
<div class="wp-playlist-tracks">
<div class="wp-playlist-item wp-playlist-playing">
<a class="wp-playlist-caption" href="https://www.futureproofpromotions.com/wp-content/uploads/2020/09/01_WhereToBegin-128.mp3">
1.
<span class="wp-playlist-item-title">
“Where To Begin” </span>
<span class="wp-playlist-item-artist"> — Alice Clayton</span>
</a>
<div class="wp-playlist-item-length">2:57</div>
</div>
<div class="wp-playlist-item">
<a class="wp-playlist-caption" href="https://www.futureproofpromotions.com/wp-content/uploads/2020/09/02_BeingAlone-128.mp3">
2.
<span class="wp-playlist-item-title">
“Being Alone” </span>
<span class="wp-playlist-item-artist"> — Brosnan</span>
</a>
<div class="wp-playlist-item-length">3:15</div>
</div>
</div>
</div>
However, when I swap the javascript line from document.getElementsByClassName('wpaudio'); to document.getElementsByClassName('wp-playlist-caption'); in order to reference the different class name in the the new html, it doesn't display any names!
I am very new indeed to javascript so this may be obvious to someone skilled in that language, but I do have a limited knowlege of php.
Would anybody be able to explain why when i change the class name/reference in the above scenario I get no names displayed?
FYI I have also tried changing document.getElementsByClassName() to document.querySelectorAll() which also works well, when referencing the original class ('.wpaudio') - but again produces no result when referencing ('.wp-playlist-caption') or any other class name nested within it (such as .wp-playlist-item-title or .wp-playlist-item-artist).
Any help with the above would be most appreciated
Since wp-playlist-caption has multiple nested elements, you can either query for each one of them and string them together or take the lazy route and use .innerText. That will extract the rendered plaintext inside the element and its children.
// Wait until the page has loaded
document.addEventListener('DOMContentLoaded', () => {
var field_to_update = document.getElementById('reactionForm_strongestTrack');
field_to_update.innerHTML = '';
var elOptNew = document.createElement('option');
elOptNew.text = '---'
elOptNew.value = '';
field_to_update.add(elOptNew);
field_to_update.options[0].selected = true;
// Search for all playlist-captions inside the playlist-tracks list.
// 'Currently playing' has a playlist-caption too,
// limiting to the tracklist excludes it
document.querySelectorAll('.wp-playlist-tracks .wp-playlist-caption')
.forEach( // The following arrow function will be called for each element
track => {
// There are nested elements but we just want the plaintext
let track_name = track.innerText;
// Create a new element and append to the select as before
let elOptNew = document.createElement('option');
elOptNew.text = track_name.replace("&", "&");
elOptNew.value = track_name;
field_to_update.add(elOptNew);
});
});
Additional reference for arrow functions.
I am currently working on a contact list program. I want to let people being able to delete the contacts on the list through a trash can button. Each of the contact info has its own button and people can delete which ever they want to remove. My code doesn't show any error through inspect (chrome) but the code is not working.
var demo = document.getElementById("demo");
function addName() {
var fname = document.getElementById("fname").value;
var entry = document.createElement("li");
var img = document.createElement("img");
img.src = "img/talkbox.png";
$(img).addClass("talkbox");
var deleteBtn = document.createElement("img");
deleteBtn.src = "img/delete.png";
$(deleteBtn).addClass("deleteBtn");
entry.appendChild(img);
entry.appendChild(document.createTextNode(fname));
entry.appendChild(deleteBtn);
demo.appendChild(entry);
document.getElementById('fname').value = "";
};
const trashCan = document.getElementById("trashcan");
trashCan.addEventListener('click', removeEvent);
function removeEvent(e) {
const list = document.getElementById("demo");
if (e.target.classList.contains('deleteBtn')) {
list.removeChild(e.target.parentElement);
list.removeChild(list);
};
};
<div>
<ul id="contactlist" class=ppl>
<li id="pplli">
<img id="wetalk" class="talkbox" src="img/talkbox.png">
<p class="contactname">Aiden<img id="trashcan" class="deleteBtn" src="img/delete.png"></p>
</li>
<ol id="demo">
</ol>
<br>
<img id="plus" src="img/plus.png">
</ul>
</div>
const trashCan = document.getElementById("trashcan");
If you have a list of items and you are using this code for it, this isn't going to work because IDs need to be unique in a document. If you create multiple elements and give them all the same ID, when you try to get the element by its ID, the browser won't know which one you are talking about.
On a separate note, you should use appropriate HTML elements to construct your document or you will cause accessibility issues. An image isn't a button. Consider using the <button> element instead.
I'm actually not sure how you are handling the delete work. But if you are planning to delete an item when clicking on the delete button in it. I mean the delete button is inside the item. Then you can just select the item using document.querySelect and use remove method in js. Here is the link
I have dynamic object (button and textbox) create by jquery where each time I press Add Transport. I took this code from this forum and modify little bit to suit my situtions (thanks to whom create this code).
Let me detail first regarding my dynamic items:
My set of group data are Trip[], Bus No[] and Amount[] .
This set can be multiple but consistent with 3 items only each group.
trip[] = button object
busno[] = text object
amount = text object
Below are my HTML script:
<div class="purchase-items-fieldset" style="clear:both;">
<div class="purchase-items-wrapper">
<div class="purchase-items">
<ul>
<li>
<input type="button" name="trip[]" value="PB" class="field btn-field">
</li>
<li>
<input type="text" name="busno[]" class="field txt-field">
</li>
<li>
<input type="text" name="amount[]" class="field txt-field">
</li>
</ul>
<input type="button" class="remove-line btn-remove" style="border:solid">
</div>
</div>
<button type="button" id="btnAddTrans" class="add-field" style="display: none">Add field</button>
</div>
Let says I have 2 set group data like below***(mydata="PB,WBX001,1000,P,WBK001,500")***
Then, my plan is:-
Group 1
trip[]=PB
busno[]=WBX001
amount[]=1000
Group 2
trip[]=P
busno[]=WBK001
amount[]=500
where I want Jquery/Javascript create 2 group dynamic object and assign value each object base on plan above :-
function assigndatatrip (mydata) {
//mydata="PB,WBX001,1000,P,WBK001,500"
//each 3 item are 1 set group data etc: PB,WBX001,500
//do split function and count how many set group
// create dynamic object
// assign data for dynamic object
//loop
//else no more data to assign then exit-return
}
I no idea where to start because I not so good on javascript/jquery function.
I hope anybody who face this problem can share and help me how to solve this problem. Thanks on advance who's reading and reply this question.
Thanks you.
If you will have that structure for your data : "each three items a group".
Then you can apply this logic:
$(document).ready(function() {
//Initialize vars
var start,
mydata = ["PB", "WBX001", "1000", "P", "WBK001", "500"]
//Loop to create items based on the array amount/3
for (start = 0; start < (mydata.length / 3); start++) {
//Target the elements of the array you need for each group
var trip = start * 3,
busno = trip + 1,
amount = trip + 2;
//Create the element to append
var item = "<div class='item'><ul><li>"
+ mydata[trip] + "</li><li>"
+ mydata[busno] + "</li><li>"
+ mydata[amount] + "</li></ul></div>";
//Append the group element
$('body').append(item);
}
})
.item {
color: white;
background: purple;
margin: 20px auto;
padding: 25px;
}
.item li {
list-style: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I must thanks to DaniP who have spirit and kindness, helping without asking. Thanks again.
I think and think many time regarding problem above, I can't use DaniP entire solution because I already have function AddTrans, SaveTrans and many more. My critical part only how to display back all a data I already save. Since object are dynamic my head getting sick to think and honestly I really bad on javascript/jquery coding.
Ok. If anybody using Dynamic Object inside Div and already run perfectly but do not know how to display back a data while create dynamic object then please consider my code below are one of solution on your reference.
function assigndatatrans(mydata) {
//var mydata = "PB,WBX001,500,P,WBK001,300"
var gdata = mydata.split(',').length / 3;
for (start = 0; start < gdata - 1; start++) {
$('#btnremove').click();
clickaddtrans();
}
var substr = mydata.split(',');
$.each($('.field'), function (index,value) {
$(this).val(substr[index]);
});
}
Let me explain my code for myself (I still on learning process JQuery function):-
First thing first is data string get from database
//var mydata = "PB,WBX001,500,P,WBK001,300"
then I need to count how many group data I have, each 3 item are 1 group then I need do small calculation
var gdata = mydata.split(',').length / 3;
After that, I know I already have function AddTrans and RemoveTrans then I need to clear first my dynamic object and show it again based how many group should be appear:-
for (start = 0; start < gdata - 1; start++) {
$('#btnremove').click();
clickaddtrans();
}
Finally, I learn some function $.each and Index and Value on JQuery recently and I try apply to make sure my data string can be perfectly insert into each field on my dynamic object. I think this part are really tricky for me and I try many time to make it working.
var substr = mydata.split(',');
$.each($('.field'), function (index,value) {
$(this).val(substr[index]);
});
That's all.... Now I can get my output run smoothly and workable. I can't say perfect! because I believe yours all who read this question can do better than this and far far more superior.
Anyway thanks so much and sleep well. :)
I am using both html and velocity and came up with this code. The names and images are stored in an array and this is the code I used to display each of the contents of this array to the page.
#foreach($starter in $starter)
<div class="product">
<div class="color"><img src= "$starter.img" width="100" height="100"></div>
<span class="product-name">$starter.name</span>
<div class="compare-wrap">
<input type="checkbox" id="">
<label id="view">Compare</label>
</div>
</div>
#end
I wanted the label to change from "Compare" to "View Compare" while at the same time storing its id in the array upon checking their correspondng check box. I eventually came up with this code:
var checkedArray = [];
$(":checkbox").change(function(){
if((this).checked){
checkedArray.push(this.id);
document.getElementById('view').innerHTML = "<a href='/compare'>View Compare</a>";
}
else{
checkedArray.splice(checkedArray.indexOf(this.id), 1);
document.getElementById('view').innerHTML = 'Compare';
}
var str = checkedArray.join(', ');
alert(str);
});
but it seems it is only applicable to the first content of the array. Any idea how I can use a foreach code at this point?
document.getElementById() only supports one name at a time and only returns a single node not an array of nodes. You should use a class:
var views = document.getElementsByClassName('view');
var i = views.length;
while(i--) {
views[i].innerHTML = "Compare";
}
HTML
<label class="view">Compare</label>
Element ID must be unique.
Hope it helps.
Here is the link to the site.
The layout of the page consists of a "fixed" sidebar (left), in which buttons are created when a user clicks the "Add" button, accompanied by their chosen title and amount of points the button is worth. Then, when the button is clicked, the button disappears and the points are added on to the "Points" value, which is in the middle "div" of the page.
On the far right there is an empty div, I tried to make the same kind of thing, except I could never get it to work. What I wanted was to create another similar dynamically created button or "span" of some sort, where when the user clicks it, the points allocated to said button/span are the deducted from the total number of points. I was thinking of it as a redeeming system if that makes sense. Using coins, which I would just assign to be half the number of points.
Also, I was able to simply store the number of points and the level in localStorage, but I wasn't sure how to store the created buttons, so they disappear after every refresh, and I can't figure out how to do it, since they're not specifically coded in?
Also, if possible, how would I go about a notification div that creates an alert for each button that is clicked. The alert would say something along the lines of "You have completed task name", and it would store it in localStorage, so the user can see the buttons that were clicked in notification form.
One more thing, upon creating the button, there is a title and a number of points the user has to assign, under the second input text box, there are 5 different coloured "spans", each representing a different "field" you might say, in this case it's different subject, how would I make it so that when the user clicks one of the "Spans", the button created will be the same colour as the span they clicked?
I know I'm asking for a lot, but I have tried to do all of which I've asked for and have had massive troubles. If anyone thinks they can help me out It would be greatly appreciated. Thank you in advance.
Here is the code, html and javascript. The CSS is bootstrap.
HTML
<div >
<div id='header'>
<h2 style='font-size:71px'>Reward System</h2>
<div>
<ol class="breadcrumb" style="width:58%">
<li class="active">
<center> Home
</li>
<li>
About
</li>
<li>
Refresh </center>
</li>
</ol>
</div></div><center>
<div id='main'>
<div id='rightSide' class='well'>
</div>
<div class='well' id="addc" style='width:520px'>
<div id="addc">
<input class='form-control' maxlength="15" id="btnName" placeholder="New Task"
style='width:480px' type="text"><br>
<input maxlength="3" class='form-control' id="btnPoints" placeholder="Points"
style='width:480px' type="text"><br>
<span class="label label-danger">Mathematics EX1</span>
<span class="label label-primary">Mathematics EX2</span>
<span class="label label-success">Physics</span>
<span class="label label-info">Chemistry</span>
<span class=
"label label-warning">English Advanced</span><br>
<br>
<button id="addBtn" >Add</button>
</div>
</div>
<div class='panel panel-default' style='width:520px;height:100px'>
<h3><Strike>z</strike> Points</span></h3>
<div class='badge' id="result">
0
</div>
</div>
<hr style="width:520px;">
<div class='panel panel-default' style="width:520px;">
<h3>Level</h3>
<p class='badge' style='width:50px' id='lvl'>0</p>
<div class="progress" style='width:300px'>
<div class="progress-bar progress-bar-success" id='perce'
style="width;"></div>
</div>
</div><br>
</div>
<div id='leftSide' class='well'>
<center> <h3> Tasks </h3> </center>
<div class='well' id="container" style='width:260px;height:85%'>
</div>
<div id='reset'>
<button class='btn btn-warning' onclick='clearme()'>Reset</button>
</center>
</div>
</div>
JavaScript
var resDiv = document.getElementById('result');
resDiv.innerText = localStorage.getItem('myResult');
var levelDiv = document.getElementById('lvl');
levelDiv.textContent = localStorage.getItem('myLevel');
var btns = document.querySelectorAll('.btn');
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function() {
addToResult(this.getAttribute('data-points'));
this.parentNode.removeChild(this.nextElementSibling);
this.parentNode.removeChild(this);
});
}
var addBtn = document.getElementById('addBtn');
addBtn.className = "btn btn-default";
addBtn.addEventListener('click', function() {
var container = document.getElementById('container');
var objDiv = document.getElementById("container");
objDiv.scrollTop = objDiv.scrollHeight;
var btnName = document.getElementById('btnName').value;
var btnPoints = parseInt(document.getElementById('btnPoints').value);
if (!btnName)
btnName = "Button ?";
if (!btnPoints)
btnPoints = 50;
var newBtn = document.createElement('button');
var newPnt = document.createElement('span');
newBtn.className = 'btn btn-info';
newBtn.innerText = btnName;
newBtn.setAttribute('data-points', btnPoints);
newBtn.addEventListener('click', function() {
addToResult(this.getAttribute('data-points'));
this.parentNode.removeChild(this.nextElementSibling);
this.parentNode.removeChild(this);
});
newPnt.className = 'label label-default';
newPnt.innerText = "+" + btnPoints;
container.appendChild(newBtn);
container.appendChild(newPnt);
});
function addToResult(pts) {
// NaN is falsy, so you can just use || to make a fall-back to 0
var result = parseInt(resDiv.innerText, 10) || 0,
lvl = 0,
a = 100;
result = result + parseInt(pts, 10) || 0;
var pen = (result/500)*100;
while (result > (5 * a)) {
lvl += 1;
a += 100;
pen -= 100;
}
document.getElementById('perce').style.width = pen +"%";
resDiv.innerText = result;
levelDiv.innerText = lvl;
localStorage.setItem("myResult", result);
localStorage.setItem("myLevel", levelDiv.textContent);
}
function clearme() {
localStorage.clear();
}
To keep your buttons in localStorage you will need to create your own object that holds the button's name and points, then use JSON.stringify to turn an array of these objects into a string. That string can then be used with localStorage.setItem
function MyButtonObject(name,points){
this.name=name;
this.points=points;
}
var list=[new MyButtonObject('example',100)];
localStorage.setItem( 'btnList' , JSON.stringify(list) );
Next I would procede by seperating the code that makes a new buttons into its own function so it can be called when the page loads and you want to rebuild your button elements.
var listJSON=localStorage.setItem( 'btnList' );
var list= listJSON?JSON.parse(listJSON ):[];
list.forEach(function(btn){
makeButtonElements(btn);
});
function makeButtonElements(btn){
var btnName=btn.name, btnPoints=btn.points;
var newBtn = document.createElement('button');
var newPnt = document.createElement('span');
....etc....
Your existing function that creates buttons would call this one as well as creating a new MyButtonObject adding it to the array of said objects and storing that array with localStorage.setItem. The function that removes buttons will need updating to remove the correct object from the array and calling localStorage.setItem as well as adding your planned notification messages (and storing them).
You should probably take some time to plan what other features you might want (such as deleting buttons without scoring their points, displaying notifications etc) and think about how you can break those processes down into functions that can be reused at different points in your program (eg new button/notification created, existing button/notification loaded from storage)
Here is a handy function that copies a style property from one element to another that should help you set the buttons colours the way you want.
function copyStyle(prop,fromEl,toEl){
toEl.style[prop]=window.getComputedStyle(fromEl)[prop];
}
Note: I haven't check or tested any of this code so make sure you read through it and understand what it is meant to do before you start copying and pasting into your own program.