How to generate a unique id? - javascript

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.

Related

How to generate unique ids on a repeated function?

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

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();
}

jQuery not changing the image source attribute on dynamically created image

I am dynamically creating elements on click on my page:
<img
src="/imagecache/large/{{ $issue->first()->image }}"
onclick="magazineDetail(
'{{ $issue->first()->magazine->id }}',
'{{ $issue->first()->magazine->name }}',
'{{ $issue->first()->magazine->summary ?: '' }}',
'{{ $issue->first()->magazine->image ?: '' }}',
'{{ $issue->first()->image }}'
)"
>
I call this script with the click:
function magazineDetail(id, name, summary, issueImage, magazineImage){
images = [];
nextImage = 0;
loadedImages = [];
$('#magazine-detail')[0].innerHTML = '<section id="magazine-detail" class="magazine-detail"><div class="large-6 medium-6 small-12 columns"><div class="magazine-hero"><img id="image" src="/imagecache/cover/' + magazineImage + '" alt="' + name + '" /><div class="magazine-preview-nav"><div class="right-arrow" id="forward"><img src="/img/right-arrow-black.svg" /><p>Neste utgivelse</p></div><div class="left-arrow" id="back"><img src="/img/left-arrow-black.svg" /><p>Forrige utgivelse</p></div></div></div></div><div class="large-6 medium-6 small-12 columns"><div class="row"><div class="small-6 columns magazine-title"><h1 id="name"></h1></div></div><p id="summary"></p><img id="issueImage" src="" alt="" /><p></p><button class="button primary expand">Kjøp abonnement - 1 måned gratis</button><button class="button secondary expand">Bla igjennom arkivet</button></div></section>';
$('#image').attr({"src" : '/imagecache/cover/' + magazineImage, "alt" : name});
$('#name').text(name);
$('#summary').text(summary);
if (issueImage != '') {
$('#issueImage').html('<img src="/imagecache/medium/"' + issueImage + ' alt="' + name + '">');
}
$('html, body').animate({
scrollTop: $("#magazine-detail").offset().top + 1500
}, 1700);
$.getJSON("issue/images",
{ id: id },
function(result){
if (result.length < 2){
$('.magazine-preview-nav').hide();
} else {
$('.magazine-preview-nav').show();
}
$.each(result, function(i, value){
images.push(value);
});
function imagePreload() {
preload();
};
});
console.log(images);
}
There I have <div class="magazine-hero"><img id="image" src="/imagecache/cover/' + magazineImage + '" alt="' + name + '" /> that I am creating in $('#magazine-detail')[0].innerHTML.
Then I have a function that should change the src of that element with the id="image" that is being created on click.
This is the script that takes care of that:
$(document).ready(function () {
imagesIndex = 0;
nextImage = 0;
loadedImages = new Array();
function preload() {
console.log('entered');
for (i = 0; i < 2; i++) {
if (nextImage < images.length) {
var img = new Image();
img.src = '/imagecache/cover/' + images[nextImage];
loadedImages[nextImage] = img;
++nextImage;
}
}
}
$('#magazine-detail').on('click','#forward', function() {
imagesIndex++;
preload();
if (imagesIndex > (loadedImages.length - 1)) {
imagesIndex = loadedImages.length - 1;
}
console.log(loadedImages.length);
console.log(loadedImages[imagesIndex].src);
$('#image').attr({"src" : loadedImages[imagesIndex].src, "alt" : name});
});
$('#magazine-detail').on('click','#forward', function() {
imagesIndex--;
if (imagesIndex < 0) {
imagesIndex = 0;
}
$('#image').attr({"src" : loadedImages[imagesIndex].src, "alt" : name});
});
});
On inspecting the console.logs I see that the new images are being created with the preload function, and that the correct image src is being passed to:
$('#image').attr({"src" : loadedImages[imagesIndex].src, "alt" : name});
But the image on page is not being changed. I should also maybe mention that everything worked fine when I wasn't creating those elements after the page has loaded but had them hiddden.
It seems that there is a minor bug in the $(document).ready(function(){ }); .
The code has 2 click events for same button #forward. Probably one should be assigned to #back button.

.replacewith not working when called a second time

I have the following markup:
<fieldset>
<legend>Headline Events...</legend>
<div style="width:100%; margin-top:10px;">
<div style="width:100%; float:none;" class="clear-fix">
<div style="width:400px; float:left; margin-bottom:8px;">
<div style="width:150px; float:left; text-align:right; padding-top:7px;">
Team Filter:
</div>
<div style="width:250px; float:left;">
<input id="teamFilter" style="width: 100%" />
</div>
</div>
<div style="width:400px; float:left; margin-bottom:8px;">
<div style="width:150px; float:left; text-align:right; padding-top:7px;">
Type Filter:
</div>
<div style="width:250px; float:left;">
<input id="typeFilter" style="width: 100%" />
</div>
</div>
</div>
</div>
<div id="diaryTable" name="diaryTable" class="clear-fix">
Getting latest Headlines...
</div>
</fieldset>
I also have the following scripts
<script>
function teamFilterChange(e) {
//alert(this.value());
setCookie('c_team', this.value(), 90);
$c1 = getCookie('c_team');
$c2 = getCookie('c_type');
var param = "true|" + $c1 + "|" + $c2;
outputHLDiaryEntries(param);
}
function typeFilterChange(e) {
//alert(this.value());
setCookie('c_type', this.value(), 90);
$c1 = getCookie('c_team');
$c2 = getCookie('c_type');
var param = "true|" + $c1 + "|" + $c2;
outputHLDiaryEntries(param);
}
// This optional function html-encodes messages for display in the page.
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
function outputHLDiaryEntries(param) {
var url = "Home/DiaryEntries/";
var data = "id=" + param;
$.post(url, data, function (json) {
var n = json.length;
alert(n + ' ' + json);
if(n == 0){
//json is 0 length this happens when there were no errors and there were no results
$('#diaryTable').replaceWith("<span style='color:#e00;'><strong>Sorry: </strong> There are no headline events found. Check your filters.</span>");
} else {
//json has a length so it may be results or an error message
//if jsom[0].dID is undefined then this mean that json contains the error message from an exception
if (typeof json[0].dID != 'undefined') {
//json[0].dDI has a value so we
//output the json formatted results
var out = "";
var i;
var a = "N" //used to change the class for Normal and Alternate rows
for (i = 0; i < json.length; i++) {
out += '<div class="dOuter' + a + '">';
out += '<div class="dInner">' + json[i].dDate + '</div>';
out += '<div class="dInner">' + json[i].dRef + '</div>';
out += '<div class="dInner">' + json[i].dTeam + '</div>';
out += '<div class="dInner">' + json[i].dCreatedBy + '</div>';
out += '<div class="dType ' + json[i].dType + '">' + json[i].dType + '</div>';
out += '<div class="dServer">' + json[i].dServer + '</div>';
out += '<div class="dComment">' + htmlEncode(json[i].dComment) + '</div></div>';
//toggle for normal - alternate rows
if (a == "N") {
a = "A";
} else {
a = "N";
}
}
//output our formated data to the diaryTable div
$('#diaryTable').replaceWith(out);
} else {
//error so output json string
$('#diaryTable').replaceWith(json);
}
}
}, 'json');
}
$(document).ready(function () {
//Set User Preferences
//First check cookies and if null or empty set to default values
var $c1 = getCookie('c_team');
if ($c1 == "") {
//team cookie does not exists or has expired
setCookie('c_team', 'ALL', 90);
$c1 = "ALL";
}
var $c2 = getCookie('c_type');
if ($c2 == "") {
//type cookie does not exists or has expired
setCookie('c_type', "ALL", 90);
$c2 = "ALL";
}
// create DropDownList from input HTML element
//teamFilter
$("#teamFilter").kendoDropDownList({
dataTextField: "SupportTeamText",
dataValueField: "SupportTeamValue",
dataSource: {
transport: {
read: {
dataType: "json",
url: "Home/SupportTeams?i=1",
}
}
}
});
var teamFilter = $("#teamFilter").data("kendoDropDownList");
teamFilter.bind("change", teamFilterChange);
teamFilter.value($c1);
//typeFilter
$("#typeFilter").kendoDropDownList({
dataTextField: "dTypeText",
dataValueField: "dTypeValue",
dataSource: {
transport: {
read: {
dataType: "json",
url: "Home/DiaryTypes?i=1",
}
}
}
});
var typeFilter = $("#typeFilter").data("kendoDropDownList");
typeFilter.bind("change", typeFilterChange);
typeFilter.value($c2);
// Save the reference to the SignalR hub
var dHub = $.connection.DiaryHub;
// Invoke the function to be called back from the server
// when changes are detected
// Create a function that the hub can call back to display new diary HiLights.
dHub.client.addNewDiaryHiLiteToPage = function (name, message) {
// Add the message to the page.
$('#discussion').append('<li><strong>' + htmlEncode(name)
+ '</strong>: ' + htmlEncode(message) + '</li>');
};
// Start the SignalR client-side listener
$.connection.hub.start().done(function () {
// Do here any initialization work you may need
var param = "true|" + $c1 + "|" + $c2;
outputHLDiaryEntries(param)
});
});
</script>
On initial page load the outputHLDiaryEntries function is called when the signalR hub is started. If I then change any of the dropdownlists this calls the outputHLDiaryEntries but the $('#diaryTable').replaceWith(); does not work. If I refresh the page the correct data is displayed.
UPDATE!
Based on A.Wolff's comments I fixed the issue by wrapping the content I needed with the same element I was replacing... by adding the following line at the beginning of the outputHLDiartEntries function...
var outStart = '<div id="diaryTable" name="diaryTable" class="clear-fix">';
var outEnd = '</div>';
and then changing each of the replaceWith so that they included the wrappers e.g.
$('#diaryTable').replaceWith(outStart + out + outEnd);
replaceWith() replaces element itself, so then on any next call to $('#diaryTable') will return empty matched set.
You best bet is to replace element's content instead, e.g:
$('#diaryTable').html("<span>New content</span>");
I had the same problem with replaceWith() not working when called a second time.
This answer helped me figure out what I was doing wrong.
The change I made was assigning the same id to the new table I was creating.
Then when I would call my update function again, it would create a new table, assign it the same id, grab the previous table by the id, and replace it.
let newTable = document.createElement('table');
newTable.id = "sameId";
//do the work to create the table here
let oldTable = document.getElementById('sameId');
oldTable.replaceWith(newTable);

Assigning user input to object with variable in its index

I am trying to using the JS to take user input and modify certain object attributes based on the user's input. I am storing the object's index in the select's alt attribute in order to use that to update the correct object. I'm getting an error: element[Payment_Format_name] is undefined
The WF.php file takes data from a CSV and formats it into a mulch-dimensional object.
$(document).ready(function() {
$.getJSON('WF.php', function(data) {
var newDiv, NewDiv2, NewDiv3,InvoiceInfo, count, DeliveryMethod, PaymentFormat, Payment_Format_id, Payment_Format_name;
count = 0;
$.each(data, function(index, element) {
count = count + 1;
//document.write (count);
newDiv = $('<div/>').addClass('row').appendTo('#showdata');
newDiv3 = $('<div/>').addClass('hd').appendTo(newDiv);
$('<div class="hd_field">' + element['PmtRec']['RcvrParty']['Name']['Name1'] + '</div>').appendTo(newDiv3);
if (element['PmtRec']['PmtMethod'] === 'CHK'){
$('<div class="hd_field">Delivery Method: <select alt="Delivery_Method" " id="Delivery' + count +'" class="Delivery_Method"><option value="100" selected="selected">US Mail</option><option value="300">Foreign Mail</option><option value="J00">Certified Mail with Return Receipt</option></select><div id="Selected_Method' + count +'"></div></div>').appendTo(newDiv3);
}
else if (element['PmtRec']['PmtMethod'] === 'DAC') {
$('<div class="hd_field">Payment Format: <select alt="'+index +'" id="Payment_' + count +'" class="Payment_Format"><option value="CTX" selected="selected">Company to Company</option><option value="PPD">Company to Person</option></select><div id="Selected_Format'+count+'"></div></div>').appendTo(newDiv3);
}
$('<div class="hd_field">' + 'Total: ' + element['PmtRec']['CurAmt'] + '</div>').appendTo(newDiv3);
InvoiceInfo = element['PmtRec']['PmtDetail']['InvoiceInfo'];
$.each(InvoiceInfo, function(index, element) {
newDiv2 = $('<div/>').addClass('sub_row').appendTo(newDiv);
$('<div class="field">' + element['InvoiceNum'] + '</div>').appendTo(newDiv2);
$('<div class="field">' + element['NetCurAmt'] + '</div>').appendTo(newDiv2);
});
$('select.Payment_Format').change(function(){
Payment_Format_id = ($(this).attr('id').match(/[\d]+$/));
Payment_Format_name = ($(this).attr('alt'));
//alert(Payment_Format_name);
PaymentFormat = ($(this).val());
element[Payment_Format_name] = Payment_Format_name;
element[Payment_Format_name]['PmtRec']['PmtFormat'] = PaymentFormat;
$('#Selected_Format' + Payment_Format_id).text('Selected Format: ' + element[Payment_Format] );
});
});
console.log(data);
});
});
PHP (this is a snippet, I'm actually creating a lot more elements here)
if (($handle = fopen('upload/BEN-new.csv', "r")) === FALSE) {
die('Error opening file');
}
$headers = fgetcsv($handle, 1024, ',');
$cardCodes = array();
$payments = array();
$details = array ();
while ($row = fgetcsv($handle, 1024, ",")) {
$cardCodes[] = array_combine($headers, $row);
}
$prevCode = '';
foreach ($cardCodes as $key => $value) {
$payments[$value['CardCode']]['PmtRec']['PmtCrDr'] = 'C';
$payments[$value['CardCode']]['PmtRec']['PmtFormat'] = 'CTX';
fclose($handle);
echo json_encode($payments)
Ok, so for starters,
$('select.Payment_Format').change(function(){
Payment_Format_id = ($(this).attr('id').match(/[\d]+$/));
Payment_Format_name = ($(this).attr('alt'));
PaymentFormat = ($(this).val());
element[Payment_Format_name] = Payment_Format_name;
element[Payment_Format_name]['PmtRec']['PmtFormat'] = PaymentFormat;
$('#Selected_Format' + Payment_Format_id).text('Selected Format: ' + element[Payment_Format] );
});
});
is not what you want - this function is reassigned to the change event of the 'select.Payment_Fomat' element for each iteration of $.each(data, function(index, element). The event listener should be added outside the $.each function, inside the $.getJson call and it needs to loop over the elements object, and try to find the correct data to update.
Apologies for the uselessness earlier, it was 5am and apparently I was slightly delusional.

Categories

Resources