How to generate unique ids on a repeated function? - javascript

I have the following function called twice:
function (data) {
$.each(data.items, function(i,item) {
var $items = $('<div class="col-sm-4 grid-item"><div class="thumbnail"><input type="checkbox" name="thing_'+i+'" value="valuable" id="thing_'+i+'"/><label for="thing_'+i+'"><img class="img-responsive" src="' + item.link + '"></label></div></div>');`enter code here`
It generates checkboxes and I am generating the identifier name for and id with the i, giving me:
thing_1
thing_2
thing_3
The problem is that when I run the function the second time, the i starts again, resulting in duplicated ids and name and for

Use an IIFE:
var uniqueId = (function() {
var counter = 0;
return function(prefix) {
counter++;
return prefix ? prefix + '' + counter : counter;
}
})();
console.log(uniqueId()); // 1
console.log(uniqueId()); // 2
console.log(uniqueId('thing_')); // thing_3
console.log(uniqueId('thing_')); // thing_4
You would integrate it in your code like this:
function (data) {
$.each(data.items, function(i, item) {
var uniq = uniqueId('thing_');
var $items = $('<div class="col-sm-4 grid-item">'.concat(
'<div class="thumbnail">',
'<input type="checkbox" name="', uniq, '" value="valuable" id="', uniq, '" />',
'<label for="', uniq, '">',
'<img class="img-responsive" src="' + item.link + '">',
'</label>',
'</div>',
'</div>'));
I broke your huge HTML mess on multiply lines using String.prototype.concat

Related

How to display data below each other in javascript

Hi guys please direct me how to this I want my result appear below each other please refer to my code below:
function displayData(e)
{
var html = '';
var html2 = '';
$searchcontainer = $('#searchcontainer');
var mapDiv = document.getElementById('mapContainer'), i = 0,
dataIndex, tooltipDiv, key
mapMarkers = $(mapDiv).find('.e-mapMarker'), index = 0;
for (i = 0; i < mapMarkers.length; i++)
{
if (e.target.parentNode.parentNode == mapMarkers[i])
{
index = i;
}
}
html += '<div id="infocontainer">';
html += '<div class="p-image"><img src="src/images/retrofit.png"/></div>';
html += '<div class="popupdetail">';
html += '<div class="p-name"> Site Name: ' + flsSites[index].site_name + '</div>';
html += '<div class="p-name"> Site Status: ' + flsSites[index].status + '</div>';
html += '<div class="p-name"> Country: ' + flsSites[index].country_name + '</div>';
html += '</div>';
html += '</div>';
$searchcontainer = $('#searchcontainer');
if (!$(this).data('rightCont')) {
$(this).data('rightCont', $('<div class="rightcontainer">' +
'<img id="productimage" src="src/images/retrofit.png" onClick="DisplayProfileCard()"/>' +
'<div id="imagedetail">' +
'<span class="details">Product Type' + Sites[index].serial_number + '</span>' +
'<span class="details">Version / Size <img class="row_one_icon lightbulb_icon" id="lightbulb" src="src/images/lightbulb1.png" onClick="LightBulb()" /><img id="convert" class="row_one_icon arrow_icon" src="src/images/arrow_Off.png" onClick="Conversion()"/><img id="lightning" class="row_one_icon" src="src/images/lightningOff.png" onClick="Lightning()"/><img id="bullseye" class="row_one_icon bullseye" src="src/images/bullseye_off.png" onClick="BullsEye()"/></span>' +
'<span class="details">Estimated annual Spend <img class="row_one_icon ribbon" src="src/images/ribbon1.png"/><img class="row_one_icon map" src="src/images/map1.png"/><img class="row_one_icon paper_stack" id="paper" src="src/images/paper_stack_Off.png" onclick="PaperStack()"/><img class="row_one_icon chain" id="chain" src="src/images/chain_Off.png" onClick="ChainLink()"/></span>' +
'<span class="details">Site name / manufacturer</span>' +
'<span class="details">Selling Sales Eng</span>' +
'</div></div>').appendTo($searchcontainer));
}
$searchcontainer.find('.rightcontainer').removeClass('background');
$(this).data('rightCont').addClass('background');
now my code here works like this if I hover over a marker in the map it will display the result to my searchcontainer div but if I hover another item it will display the other result BUT it will overwrite the previous result instead of displaying it below
Many thanks in advance
Your call to $(this).data overwrites the contents of rightCont each time it is executed. Read more on the JQuery API. The .appendTo(...) call should be sufficient.
That being said, using string manipulation to create HTML code is stylistically terrible. Look at something like Vue.js, Handlebars, Angular, React, or just any other frontend MVC framework- they are tools designed for easily binding Javascript data to HTML, rather than manually inserting it using string manipulation.

jQuery: function in dynamic generated list item doesn't work

I build a function to display a value in a HTML element for a
<input type="range">
object.
My function works fine:
var rangeValues = { "50": "Fifty" , "100": "Hundred" , "...": "..." };
$(function Skilllevel() {
$('#rangeText').text(rangeValues[$('#rangeInput').val()]);
$('#rangeInput').on('input change', function ()
{
$('#rangeText').text(rangeValues[$(this).val()]);
});
});
See example in jsfiddle
My problem now is the following:
I putted the function Skilllevel() into a $.each(result, function and into it, it doesn't work, because every entry from my second JSON file var urlBewerbungID = "json.php"; generated one separate list element in $("#ergebnisSkill").append(
The second JSON looks very simple, like this:
[
"item1",
"item2",
"item3"
]
My complete function:
//Skills selektieren
var rangeValues = {
"0": "Keine",
"33": "Anfänger",
"66": "Fortgeschritten",
"99": "Profi"
};
//Abfrage, welche Stelle gewählt wurde
$('#bewerbungID').on('change', function() {
var bewerbungID = ($('#bewerbungID').val());
console.log("BewerbungsID gewählt: " + bewerbungID);
//Zuerst das #HTML Element leeren
$("#ergebnisSkill").empty();
$(document).ready(function() {
var urlBewerbungID = "json.php";
$.getJSON(urlBewerbungID, function(result) {
console.log(result);
$.each(result, function(i, field) {
var skill = field;
//Skill liste erstellen
$(function Skilllevel() {
$('#rangeText').text(rangeValues[$('#rangeInput').val()]);
$('#rangeInput').on('input change', function() {
$('#rangeText').text(rangeValues[$(this).val()]);
});
});
//Jetzt HTML Element neu befüllen
$("#ergebnisSkill").append(
'<li>' +
'<div class="item-content">' +
'<div class="item-media"><i class="icon f7-icons">star</i></div>' +
'<div class="item-inner">' +
'<div class="item-title label">' + skill + '<br> <span id="rangeText"></span></div>' +
'<div class="item-input">' +
'<div class="range-slider">' +
'<input type="range" id="rangeInput" min="0" max="99" value="0" step="33">' +
'</div>' +
'</div>' +
'</div>' +
'</div>' +
'</li>'
);
});
});
});
});
Your code is inside out.
You need document.ready to wrap the event handlers.
Use class instead of IDs, IDs need to be unique
use delegation - currently you have a function per result which does not work.
You need the skills functionality assigned to each result but delegated - see how a click on the ergebnisSkill will be captured by the rangeInput:
//Skills selektieren
var rangeValues = {
"0": "Keine",
"33": "Anfänger",
"66": "Fortgeschritten",
"99": "Profi"
};
$(document).ready(function() {
//Skill liste erstellen
$("#ergebnisSkill").on('input change', ".rangeInput", function() { // delegation
$(this).closest("item-inner") // a parent div
.find('.rangeText') // the input field
.text(rangeValues[$(this).val()]);
});
//Abfrage, welche Stelle gewählt wurde
$('#bewerbungID').on('change', function() {
var bewerbungID = ($('#bewerbungID').val());
console.log("BewerbungsID gewählt: " + bewerbungID);
//Zuerst das #HTML Element leeren
$("#ergebnisSkill").empty();
var urlBewerbungID = "json.php";
$.getJSON(urlBewerbungID, function(result) {
console.log(result);
$.each(result, function(i, field) {
var skill = field;
//Jetzt HTML Element neu befüllen
$("#ergebnisSkill").append(
'<li>' +
'<div class="item-content">' +
' <div class="item-media"><i class="icon f7-icons">star</i></div>' +
' <div class="item-inner">' +
' <div class="item-title label">' + skill + '<br> <span class="rangeText"></span></div>' +
' <div class="item-input">' +
' <div class="range-slider">' +
' <input type="range" class="rangeInput" min="0" max="99" value="0" step="33">' +
' </div>' +
' </div>' +
' </div>' +
'</div>' +
'</li>'
);
});
});
});
});

How to generate a unique id?

I am running twice the call to google in order to get 20 images (google by default only gives you a set of 10 images for a single call).
However, I need to generate a single unique id for each element i get. Here it is the jQuery I am using but the second set of 10 images gets the same id as per the previous set:
function loadImage() {
var uniqueId = (function() {
var counter = 0;
return function(prefix) {
counter++;
return prefix ? prefix + '' + counter : counter;
}
})();
// GOOGLE IMAGES FRONT
function createGoogleImagesLoad(initialValue) {
var termS;
termS = $("#usp-title").val();
var _start = initialValue || 1;
var imagesCount = 10;
var myCx = 'MY_CX';
var myKey = 'MY_KEY';
var $grid = $('.grid').packery({
itemSelector: '.grid-item',
percentPosition: true
});
return function() {
$.getJSON("https://www.googleapis.com/customsearch/v1", {
q: termS,
alt: "json",
searchType: "image",
cx: myCx,
num: imagesCount,
start: _start,
key: myKey,
language: "it",
rights: "cc_publicdomain, cc_attribute",
filter: "1",
safe: "high",
imgType: "photo",
fileType: "jpg"
},
function (data) {
$.each(data.items, function(i, item) {
var uniq = uniqueId('thing_');
var $items = $('<div class="col-xs-12 col-md-6 grid-item">'.concat(
'<div class="thumbnail">',
'<input type="checkbox" name="', uniq, '" value="valuable" id="', uniq, '" />',
'<label for="', uniq, '">',
'<img class="img-responsive" src="' + item.link + '">',
'</label>',
'</div>',
'</div>'));
$grid.append( $items ).packery( 'appended', $items );
$grid.imagesLoaded().progress( function() {
$grid.packery();
$('body').on('change', '.grid .thumbnail :checkbox', function () {
var urls = [];
$(':checkbox:checked').each(function () {
urls.push($(this).next('label').find('img').attr('src'));
});
var str = '';
urls.forEach(function (url) {
str += '<div class="col-xs-12 col-md-6 grid-item"><div class="thumbnail"><img onerror="hideContainer(this)" src="' + url + '"/></div></div>';
});
$('#usp-custom-4').val(str);
});
});
});
});
_start += imagesCount;
}
}
var googleImagesFront = createGoogleImagesLoad();
googleImagesFront();
}
Are you calling loadImage() twice? That's the problem, it regenerates the uniqueId function each time, resetting counter to 0. Move the uniqueId function outside of loadImage and it should fix it.
If you want an unique id you can use this library that implements the standard RFC4122, its use is very simple, you need just add the library and choose the method of the version that you want generate:
console.log('UUID v1:', uuid.v1());
console.log('UUID v4:', uuid.v4());
<script src="https://cdnjs.cloudflare.com/ajax/libs/node-uuid/1.4.7/uuid.min.js"></script>
The variable counter is always getting initialized when you are calling the function. If you place var counter = 0; this variable globally or outside the function then you should be able to get unique ids.

Try to figure out how to show content based on window.location.hash

Im using JSON and passing data through the href tag and using a click event to show specific items from a product database. My question is that I have code in the script that assigns a unique window hash to each product. It takes the product name and strips the spaces.
How can I show the correct item on the page if the hash tag matches the item when linking from an external url?
For example, when one of the items is clicked on the page the url will show something like www.website.com#CherryTomatoes.
Obviously I cant link to this from another website because the hash only exists when the click event is fired. I want to be able to automatically show the correct item when using an external link. Below is my code hope someone can help me out with this!
//display product category based on click
$("#displayall").click(function(event){
displayAll();
});
//display all products function
function displayAll() {
var categoryImage = '';
$.each(json, function (i, item) {
categoryImage += '<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">' + '' + '<img class="img-responsive img-hover productImagesCategory" src="' + item.imageURL + '">' + '<h3>' + item.itemName + '</h3>' + '' + '</div>';
});
$('#imagesCategoryProducts').hide().html(categoryImage).fadeIn('slow');
//show individual product function on click
$(".showProduct").click(function(event){
//hide all current products
$('#productCategories').hide();
//get passed data from other function
var clickedItemName = '<h1>' + $(this).data('itemname') + '</h1>';
var clickedItemUPC = $(this).data('itemupc');
var clickedItemOZ = '<h2>' + $(this).data('itemoz') + '</h2>';
var clickedItemDescription = '<p>' + $(this).data('itemdescription') + '</p>';
var clickedItemImage = '<img class="img-responsive img-rounded center-block" src="' + $(this).data('itemimage') + '">';
var clickedItemGluten = $(this).data('itemgluten');
var clickedItemBPA = $(this).data('itembpa');
var clickedItemGMO = $(this).data('itemgmo');
var clickedItemPageURL = $(this).data('itempageurl');
//check if clicked data equals correct item
$.each(json, function (i, item) {
if (item.itemName === clickedItemName) {
clickedItemName
}
if (item.itemFullUPC === clickedItemUPC) {
clickedItemUPC
}
if (item.itemPackSize === clickedItemOZ) {
clickedItemOZ
}
if (item.itemDescription === clickedItemDescription) {
clickedItemDescription
}
if (item.imageURL === clickedItemImage) {
clickedItemImage
}
if (item.itemGlutenFree === clickedItemGluten) {
clickedItemGluten
}
if (item.itemBPAFree === clickedItemBPA) {
clickedItemBPA
}
if (item.itemGMOFree === clickedItemGMO) {
clickedItemGMO
}
//assign window hash to each product
if (item.itemName === clickedItemPageURL) {
event.preventDefault();
clickedItemPageURL = clickedItemPageURL.replace(/\s/g, '');
window.location.hash = clickedItemPageURL;
}
});
//remove extra characters from UPC
var originalUPC = clickedItemUPC;
var strippedUPC = '<h2>' + originalUPC.slice(1, -1); + '</h2>';
//show individual product information
$('#productSocialShare').show();
$('#individualProduct').show();
$('#relatedProducts').show();
//append product information to appropriate DIV
$('#productTitle').html(clickedItemName);
$('#productUPC').html(strippedUPC);
$('#productOZ').html(clickedItemOZ);
$('#productDescription').html(clickedItemDescription);
$('#productImage').html(clickedItemImage);
//check if gluten free is true and show image
if (clickedItemGluten == "Y") {
clickedItemGluten = '<img class="img-responsive img-rounded img-margin" src="../images/misc/gluten_free_test.jpg">';
$('#productGlutenFree').html(clickedItemGluten);
$('#productGlutenFree').show();
} else {
$('#productGlutenFree').hide();
}
//check if bpa free is true and show image
if (clickedItemBPA == "Y") {
clickedItemBPA = '<img class="img-responsive img-rounded img-margin" src="../images/misc/bpa_free_test.jpg">';
$('#productBPAFree').html(clickedItemBPA);
$('#productBPAFree').show();
} else {
$('#productBPAFree').hide();
}
//check if gmo free is true and show image
if (clickedItemGMO == "Y") {
clickedItemGMO = '<img class="img-responsive img-rounded img-margin" src="../images/misc/gmo_test.jpg">';
$('#productGMOFree').html(clickedItemGMO);
$('#productGMOFree').show();
} else {
$('#productGMOFree').hide();
}
});
closeNav();
}

Masonry why arranging in single column overlapping

I am using the appended function to append elements to an already initialized masonry instance, but all of my tiles are being laid out in a single column and many are overlapping. Can you see what I am doing wrong?
function placeNewsTiles(news){ //places news tiles
var length = (news.data.length > 20) ? 20 : news.data.length;
var $container = $('#news');
var elems ="";
for(var i = 0; i < length; i++){
elems += '<div class="pageNewsItem" id="'+ count + i + '">\
<div class="textWrap">\
<a href="' + news.data[i]._url + '">\
<strong>' + news.data[i]._title + '</strong>\
</a>\
<span class="source">' + news.data[i]._source + '</span>\
</div>\
<div class="imageWrap"></div>\
<div class="thumbsOverlay" style="display:none">\
<div class="thumbs">\
<div>\
<img src="../images/Thumbs-Up-2.png" />\
<img src="../images/Thumbs-Down-2.png" />\
</div>\
</div>\
</div>\
</div>';
getTileImage({total: news.count, i:count + "" + i, url:news.data[i]._url});
}
elems = $(elems);
$('#news').append(elems).imagesLoaded(function(){
$('#news').masonry( 'appended', elems, true );
});
newsPage = 0;
count++;
hoverTiles();
}
$(document).ready(function() {
newClock();
readyLogin();
var $container = $('#news');
//$container.imagesLoaded( function() {
$container.masonry({itemSelector: '.pageNewsItem'});
//});
obtainSearchQuery();
});
On this line, try triggering layout once items are appended:
$('#news').masonry( 'appended', elems, true ).masonry('layout');
I've seen examples with and without the extra .masonry() call, but it might work.

Categories

Resources