Build dynamic menu from multiple metadata files
I have a JavaScript loop that displays the images from an NFT collection and uses the class names to create a filter. Currently the filter menu is hard-coded, but I would like to build it dynamically from the metadata.
var loopFunction = function(dataIsLoading) { // the loop
let itemID = "";
var itemSource = "Azuki";
var itemURI = "https://ikzttp.mypinata.cloud/ipfs/QmQFkLSQysj94s5GvTHPyzTxrawwtjgiiYS2TBLgrvw8CW/"
for (let i = 0; i < 100; i++) {
itemID += [i];
$.getJSON(itemURI+i, function(data) {
// alert(data.name);
var eachItem = "";
var itemName = data.name;
var traits = data.attributes;
var classes = "";
var traitList = "";
$.each(data.attributes,function(index,entry) { // k (key), v (value) / i (index), e (entry)
var str = entry.value;
str = str.replace(/ /g, '');
classes += '' + entry.trait_type + '' + str + ' ';
traitList += '<span class="item-trait-type">' + entry.trait_type + ':</span> ' + str + '<br />';
});
eachItem += '<div class="cstm-grid-item cstm-width-1-2 cstm-width-large-1-3 cstm-width-x-large-1-4 ' +classes+'" id="'+i+'">';
eachItem += '<div class="img-placeholder">';
eachItem += '<img class="lazy" data-src="https://ikzttp.mypinata.cloud/ipfs/QmYDvPAXtiJg7s8JdRBSLWdgSphQdac8j1YuQNNxcGE1hg/'+i+'.png" width="100%" height="auto" />';
eachItem += '</div>';
eachItem += '<span class="item-title">'+itemName+'</span>';
eachItem += '<p class="item-traits">'
eachItem += traitList;
eachItem += '</p>'
eachItem += '</div>';
$('.cstm-grid').append(eachItem);
});
}
};
I have all of the data, but building the menu is difficult to do dynamically without the the menu having duplicate values. I just need the single base category (trait type) and the single values for that trait type. The final output should look something like:
<ul>
<li>
<h2>Trait Type 1</h2><!-- the category -->
<ul>
<li>red</li><!-- the value -->
<li>blue</li><!-- the value -->
</ul>
</li>
<li>
<h2>Trait Type 2</h2><!-- the category -->
<ul>
<li>sunglasses</li><!-- the value -->
<li>hat</li><!-- the value -->
</ul>
</li>
</ul>
Related
I am displaying the content after fetching it via ajax using jquery so the content is dynamic,
var i, j;
var product_names = [];
var product_image = [];
var product_rate = [];
var product_amount = [];
var product_category = [];
$.ajax({
url: BASE_URL + '/getOrgServices?orgId=' + orgId,
type: 'GET',
success: function(result) {
//console.log(result);
for (i in result) {
product_names[i] = result[i].name;
product_image[i] = result[i].imgurl;
product_rate[i] = result[i].rate;
product_amount[i] = result[i].amount;
product_category[i] = result[i].categories;
}
for(i in product_category){
var html = '<div class="prod-content"><ul id="products">';
html += '<li class="row product-listing">';
html += '<div class="product-img-container"><img class="product-img" src="' + product_image[i] + '"></div>';
html += '<div class="container product-listing-details"><h6 id="product-title">' + product_names[i] + '</h6><div id="product-description">' + product_amount[i] + '</div><br><div id="product-cost">' + product_rate[i] + '</div></div>';
html += '<div id="product-add">';
html += '<button class="add-button" type="button" role="button">ADD</button>';
html += '<span class="quantity"><input class="item-quantity" type="number" value="0" min="0" max="50" step="1"></span>';
html += '</div></li> </ul></div>'
//adding elements to all category
var id_str = '#' + new_id[0];
$(id_str).append(html);
}
}
Now in the below function i want to access the name of one h6 product_name at a time so is there any method to do so like if I could select
$(".add-button").click(function() {
//here i want to add items to cart on button click (means the button clicked its corresponding item should be added to cart )
});
is the cart part of the html code
<div class="order">
<ul id="products">
<li>
//here i want to append the added item
</li>
</ul>
</div>
To get all h6 you can do similar thing as below, without jQuery.
$(".add-button").click(function() {
console.log("click");
document.querySelectorAll("div.prod-content h6").forEach((function(elem) {
console.log(elem.innerText);
if (parseInt(elem.innerText) > 0) {
console.log(elem);
}
}));
});
Basically, I'm making a TODO list, the functions are save and delete records, which are already implemented and mark as important and mark as done, which are the functions that I'm having trouble with.
This is the method that I use to retrieve the items saved in Local Storage as an array.
function get_todos() {
var todos = new Array;
var todos_str = localStorage.getItem('todo');
if (todos_str !== null) {
todos = JSON.parse(todos_str);
}
return todos;
}
This is the method that I use to save records in Local Storage
function add() {
var task = "00"+document.getElementById('task').value;
var todos = get_todos();
todos.push(task);
localStorage.setItem('todo', JSON.stringify(todos));
show();
return false;
}
As you can see, I add the records with two 00 at the beginning, the first number is 0 when that item of the TODO list is "undone", and 1 when it is marked as done, the second number is 0 when that item if the TODO list is "not important", and 1 when it is marked as important, for changing those numbers on the local storage, I do this:-
//if the second digit is 0 then the task is not important
function markAsImportant(){
var id = parseInt(this.getAttribute('id'));
var todos = get_todos();
var task = todos[id].replaceAt(1, "1");
console.log(task);
todos.splice(id, 0, task);
todos.splice(id+1, 1);
localStorage.setItem('todo', JSON.stringify(todos));
show();
return false;
}
That method is already well implemented and working as it should.
Now, knowing what item of the TODO is important and which one is not, I simply want to add a class to the items which second character is a one, and that is what I try to do here:-
function show() {
var todos = get_todos();
var html = '<div class="list">';
for(var i=0; i<todos.length; i++) {
//HERE HERE HERE HERE HERE
if (todos[i].charAt(1) == '1') {
console.log("important");
$('.item').addClass('important');
}
else{
console.log("not important");
}
html += '<div class="item"> <input type="checkbox" class="check" id="' + i + '"> ' +' <div class="title">' + todos[i].substring(2) + '</div> <div class="tools"> <span class="tag" id="' + i + '"> <img class="important-img" src="resources/important.png"> </span> <span class="delete remove " id="' + i + '"> <img src="resources/thrash.png"> </span> </div></div>';
};
html += '</div>';
document.getElementById('todos').innerHTML = html;
var deleteButtons = document.getElementsByClassName('remove');
for (var i=0; i < deleteButtons.length; i++) {
deleteButtons[i].addEventListener('click', remove);
};
var doneButtons = document.getElementsByClassName('check');
for (var i=0; i < doneButtons.length; i++) {
doneButtons[i].addEventListener('click', markAsDone);
};
var importantButtons = document.getElementsByClassName('tag');
for (var i=0; i < importantButtons.length; i++) {
importantButtons[i].addEventListener('click', markAsImportant);
};
var listItems = document.getElementsByClassName('item');
for (var i=0; i < listItems.length; i++) {
console.log(listItems[i]);
$(listItems[i]).attr('id', i);
};
}
But it simply won't add anything at all to the .item tags, how can I make it actually add the class important to the items that I want ?
You are not adding the html to DOM so $(".item") won't work. This should work:
for (var i = 0; i < todos.length; i++) {
html += '<div class="item';
if (todos[i].charAt(1) == '1') {
console.log("important");
html += ' important'; // The space must be there, so change just the "important" bit, but don't remove the space
} else {
console.log("not important");
}
html += '"><input type="checkbox" class="check" id="' + i + '"> ' + ' <div class="title">' + todos[i].substring(2) + '</div> <div class="tools"> <span class="tag" id="' + i + '"> <img class="important-img" src="resources/important.png"> </span> <span class="delete remove " id="' + i + '"> <img src="resources/thrash.png"> </span> </div></div>';
}
Paste this instead your for loop and post the result in comments under this answer.
I want to display and list with icon and text. List is link to specific URL. I am storing all these in a array but image is not populating from the array. here is a spinet.
var mainPanel = [ {
icon : "images/green/home.png",
title : "Home",
url : "#tilehome-page"
}, {
icon : "images/green/home.png",
title : "Mayor's Conner)",
url : "#mayorsmessage-page"
}, {
icon : "images/green/home.png",
title : "Report A Problem",
url : "#reportaproblem-page"
} ];
function createmenuPnl() {
var items = '';
//ul = $(".mainMenu:empty");
var ulStr = "<ul>";
for (var i = 0; i < mainPanel.length; i++) {
items += '<li><a href="' + mainPanel[i].url + '"> + mainPanel[i].title
+ '</a></li>';
}
ulStr+= items;
ulStr+='</ul>';
console.log('The ulStr formed is:'+ulStr);
$("#cssmenu").append(ulStr);
$("#cssmenu").trigger( "updatelayout" );
}
All I want is to add image icon dynamically in the list
you forget single quote just before mainPanel[i].title.. it should be like this..
items += '<li><a href="' + mainPanel[i].url + '">' + mainPanel[i].title
+ '</a></li>';
Here we go
The problem is in your loop for
for (var i = 0; i < mainPanel.length; i++) {
// after '"> need one '
items += '<li><a href="' + mainPanel[i].url + '">' + mainPanel[i].title
+ '</a></li>';
}
I have multiple XML files which contain TV Listings each file is one TV channel. I want to be able to search by program title and display the results in a html table. So far I have been able to search by one XML file - so by one channel. I want to be able to search by multiple channels using user input via an input box and search button. The XML I have looks like:
<?xml version="1.0" encoding="UTF-8"?>
<channel id="sky_one" source="Sky" date="25/11/2014">
<programme>
<desc>Tony's motorcycle bursts into flames between his legs while town planner Liz is left in agony after her half-tonne horse bolts and lands on top of her. Also in HD</desc>
<title>The Real A & E</title>
<end>0630</end>
<start>0600</start>
</programme>
(only a snippet)
The jQuery that I have so far, which works for one channel looks like:
$(document).ready(function () {
//GLOBAL VAR
var keyword = '';
var pub = '';
var i = 0;
$("#searchButton").click(function () {
keyword = $("input#term").val();
//Reset any message
var errMsg = '';
pub = '';
if (keyword == '') {
errMsg += 'Please enter a search term';
} else {
searchThis();
}
if (errMsg != '') {
pub += '<div class="error">';
pub += errMsg;
pub += '</div>';
}
//Show error
$('#result').html(pub);
});
// ----------------------------------------- SKY NEWS -----------------------------------------------------------
function searchThis() {
$.ajax({
type: "GET",
url: "https://scm.ulster.ac.uk/~B00533474/workspace/COM554/assignment_2/CR/sky_one.xml",
dataType: "xml",
success: function (xml) {
loadPublication(xml)
}
});
}
function loadPublication(xmlData) {
i = 0;
var row;
var searchExp = "";
$(xmlData).find('programme').each(function () {
var title = $(this).find('title').text();
var desc = $(this).find('desc').text();
var start = $(this).find('start').text();
//Format the keyword expression
var exp = new RegExp(keyword, "gi");
//Match to Title of programme
searchExp = title.match(exp);
if (searchExp != null) {
//Start building the result
if ((i % 2) == 0) {
row = 'even';
} else {
row = 'odd';
}
i++;
pub += '<tr class="row ' + row + '">';
pub += '<td valign="top" class="col1">' + title + '</td>';
pub += '<td valign="top" class="col2">' + desc + '</td>';
pub += '<td valign="top" class="col3">' + start + '</td>';
pub += '</tr>' + 'n';
}
});
if (i == 0) {
pub += '<div class="error">';
pub += 'No Result was Found';
pub += '</div>' + 'n';
//Populate the result
$('#result').html(pub);
} else {
//Pass the result set
showResult(pub);
}
}
function showResult(resultSet) {
//Show the result
pub = '<div class="message">There are ' + i + ' results!</div>';
pub += '<table id="grid" class="table-bordered">';
pub += '<thead><tr>' + 'n';
pub += '<th class="col1"> </th>';
pub += '<th class="col2">Title</th>';
pub += '<th class="col3">Desc</th>';
pub += '<th class="col4">Start</th>';
pub += '</tr></thead>';
pub += '<tbody>';
pub += resultSet;
pub += '<hr class="horule" />';
pub += '</tbody>';
pub += '</table>';
//Populate
$('#result').html(pub)
}
});
And the html is as follows:
<input type="text" id="term" placeholder="Search by program title..."></div>
</div>
<input type="button" id="searchButton" value="Search" class="btn btn-primary" />
<div id="result"> </div>
I had an the idea of using the xml files as variables then using .when and .then to utilize the xml files, although I am not quite sure how to implement these, something like:
// Open the xml file
var sky1 = 'https://scm.ulster.ac.uk/~B00533474/workspace/COM554/assignment_2/CR/sky_one.xml',
bbc1 = 'https://scm.ulster.ac.uk/~B00533474/workspace/COM554/assignment_2/CR/bbc1.xml',
skyn = 'https://scm.ulster.ac.uk/~B00533474/workspace/COM554/assignment_2/CR/sky_news.xml';
$.when(
$.ajax( sky1 ),
$.ajax( bbc1 ),
$.ajax( skyn )
).then(function( skyone, bbcone, skynews ) {
var sky1p = $(skyone).find('programme'),
bbc1p = $(bbcone).find('programme'),
skynp = $(skynews).find('programme');
//sky one
sky1p.each(function() {
//DO Search
//sky one
skynp.each(function() {
//DO Search
//sky one
bbcp.each(function() {
//DO Search
The intended output is a html table with the title, description and program time. If anyone could help that would be great!
trying to prepend my list in jquery mobile but I just can't get the divider to be on top of the most recent item added to the listview.
I've tried prepending the item that's being added but it then switches the divider to the bottom.
function loadScanItems(tx, rs) {
var rowOutput = "";
var $scanItems = $('#scanItems');
$scanItems.empty();
var bubbleCount = 0;
for (var i = 0; i < rs.rows.length; i++) {
bubbleCount = bubbleCount + 1;
//rowOutput += renderScan(rs.rows.item(i));
var row = rs.rows.item(i)
var now = row.added_on;
var date = get_date(now);
rowOutput += '<li data-icon="false"><div class="ui-grid-b"><div class="ui-block-a" style="width:50%"><h3>Su # ' + row.sunum + '</h3><p> Bin # ' + row.binnum + '</p></div><p class="ui-li-aside"><strong>' + date + '</strong></p><div class="ui-block-b" style="width:20%"></div><div class="ui-block-c" style="width:25%"><br><p>User: ' + row.userid + '</p></div></div></li>';
// rowOutput += '<li>' + row.sunum + row.binnum+ "<a href='javascript:void(0);' onclick='webdb.deleteScan(" + row.ID + ");'>Delete</a></li>";
}
$scanItems.append('<li data-role="list-divider">Scanned Items <span class="ui-li-count">' + bubbleCount + '</span></li>').listview('refresh');
$scanItems.append(rowOutput).listview('refresh');
}
The code is above with it correctly formatted with the divider on top but the list items being appended to the bottom instead of prepended to the top.
Thanks!
The problem is that your are building a string with all the scan items. That string already has an order so whether you prepend or append makes no difference. Try this simple change.
Change:
rowOutput += '<li data-icon="false">...</li>';
to:
rowOutput = '<li data-icon="false">...</li>' + rowOutput;
This will put your rowOutput string in the correct order before appending to the listview.
Here is a working DEMO