jQuery adding a div after a generated table - javascript

I am sure i have the right logic here and tried after and insertafter but does not seem to work... any ideas?
JS:
if(content) {
var $table = $('<table/>');
$table.addClass('product-table');
$table.append(
'<tr><td><img src="' + content[0].image + '" class="thumbnail"/></td>' +
'<td><strong>' + content[0].title + '</strong></td>' +
'<td>SKU: ' + content[0].sku + '</td>' +
'<td>£' + content[0].price + '</td></tr>'
);
$table.after('<div class="button-container">' +
'view cart' +
'checkout' +
'</div>');
$(notice_content).find(notice_inner).html($table);
}

after method requires that the target element ($table) be in DOM - which it isn't until next statement with .html method.
Just move line with after call after the line with html call:
$(notice_content).find(notice_inner).html($table);
$table.after('<div class="button-container">view cartcheckout</div>');
Useful references:
http://api.jquery.com/after

Related

How can I init accordion in Magento 2 on swatches, on product page

I want to make an accordion for the swatches on the product page.
The switches are built into the file Magento_Swatches/js/swatch-renderer.js
I did a mixin over the _RenderControls function and changed the html structure a bit compared to the original structure.
CODE JS (via mixin)
container.append(
'<div class="' + classes.attributeClass + ' ' + item.code + '" ' +
'attribute-code="' + item.code + '" ' +
'attribute-id="' + item.id + '">' +
label +
'<div class="init-accordion" >' +
'<div data-role="collapsible">' +
'<div class="title-accordion" data-role="trigger">titlu</div>' +
'</div>' +
'<div class="content-accordion" data-role="content">' +
'<div aria-activedescendant="" ' +
'tabindex="0" ' +
'aria-invalid="false" ' +
'aria-required="true" ' +
'role="listbox" ' + listLabel +
'class="' + classes.attributeOptionsWrapper + ' clearfix">' +
options + select +
'</div>' + input +
'</div>' +
'</div>' +
'</div>'
);
I did not put the whole function because it is very long, I only put the part that differs from the original.
I want to initialize an accordion (according to the Magento documentation) on this swatch structure.
The problem is that the accordion does not initialize because the switches are still loaded on the page.
In the template, I would initialize like this
CODE PHTML:
<script>
require(['jquery', 'domReady', 'accordion'], function($, domReady){
domReady(function(){
setTimeout(function(){
$(".init-accordion").accordion({
"active": [1, 2],
"collapsible": true,
"openedState": "active",
"multipleCollapsible": true
});
}, 3000);
});
})
</script>
I used setTimeout and it works, but I want without it.
Do you have any idea how I can do this?
Thank you!

Retrieve Flickr photo title AND description using jQuery

Annoyingly, the FlickrAPI provides the title and description of a photo in two separate methods. I'm having trouble getting the description of an image from Flickr and was wondering if you could highlight the error in my script.
for (var i = 0; i < photos.photo.length; i++) {
var descPhoto = "https://api.flickr.com/services/rest/?method=flickr.photos.getInfo&api_key="+API_KEY+"&photo_id="+photos.photo[i].id+"&format=json&nojsoncallback=1";
var descArr = [];
$.getJSON(descPhoto, function(data) {
var value = data.photo.description._content;
descArr.push(value);
});
link = 'https://farm' + photos.photo[i].farm + '.static.flickr.com/' + photos.photo[i].server + '/' + photos.photo[i].id + '_' + photos.photo[i].secret + '_';
title = this._htmlEscape( photos.photo[i].title );
var lightbox = "lightbox";
listItems +=
'<li ' + 'class="' + liClassNoDots + '">' +
'<a href="' + link + self.options.imageSize + '.jpg" title="' + title + '" class="' + aClassNoDots + '" target="_blank" data-lightbox="' + lightbox + '">' +
<img alt="' + title + '" src="' + link + self.options.thumbnailSize +'.jpg"/>' +
'<div class="hover-box">' +
'<p>' + descArr[i] + '</p>' +
'<button class="box-button view">View larger</button>' +
'<button class="box-button request">Request</button>' +
'</div>';
'</a>' +
'</li>';
}
Getting the title is fine and I've checked by API string calls and they work in the address bar of my browser.
I've used console.log() and the array is printed out correctly and I'm getting the descriptions. However, in each <p> tag the script is returning undefined in each instance.
However, if I run the script through the debugger the parapgraph tags are populated with the descriptions. Can somebody help?!
i think the problem is in following code::
..
$.getJSON(description, function(desc) {
value = desc.photo[ i ].description._content;
});
the service url returns photo object whereas you are using photo array, change to:
..
$.getJSON(description, function(desc) {
value = desc.photo.description._content;
console.log( value );
});

jQuery Mobile refresh collapsible

I have a few <div data-role="collapsible">...</div>in my page (I don't use a collapsible set because I want the possibility to open several at once) and then I remove them and create a few new ones with Javascript. Now I want them to have the jQuery Mobile Styling, but whatever I do, they won't refresh. I tried:
$("parentdiv").refresh();
$("parentdiv").trigger("create");
$(".ui-collapsible").refresh();
$(".ui-collapsible").trigger("create");
I even put a collapsible-set around each one and tried to do the refresh with this (described in the jQuery Mobile Documentation)
I add the new divs with $("<div data-role="collapsible">...</div>").insertBefore("#foo");
What is the proper way to do it? And is the content getting displayed in jQuery Mobile style, too, after the refresh?
UPDATE
The content of the collapsible was not refreshed here is my code:
var newColla = "<div id=\"colla" + i + "\" data-role=\"collapsible\" data-collapsed=\"true\" data-collapsed-icon=\"minus\" data-expanded-icon=\"bars\">" +
"<h3 id=\"" + matrikelnummer + "\">" + matrikelnummer + " " + studentName + "</h3><div class=\"colla-content\">" +
"<div data-role=\"fieldcontain\" style=\"margin:0px;width:100%;text-align:right;\">" +
"Teilnehmer bearbeiten" +
"Teilnehmer löschen" +
"</div>";
// Für jede ausgewählte Aufgabe einen Slider hinzufügen
for (var j = 0; j < aufgaben.length; j++) {
newColla += "<label for=\"slider_mini\">Aufgabe " + aufgaben[j] + ": (max." + allMaxPoints[j] + "Pkt.)</label>" +
"<input type=\"range\" name=\"slider_mini_" + matrikelnummer + "_" + aufgaben[j] +"\" class=\"slider-mini allSliders\" id=\"slider_mini_" + matrikelnummer + "_" + aufgaben[j] + "\" " + theme + " step= 0.5 value=\"0\"" +
"min=\"0.0\" max=\"" + allMaxPoints[j] + "\" data-highlight=\"true\" data-mini=\"true\" />";
}
newColla += "</div></div>";
$(newColla).collapsible().trigger("create").insertAfter("#timer");
All you need is to use .collapsible(), there is no refresh method for collapsible widget.
$(document).on("pageinit", function () {
var collapsible = '<div data-role="collapsible"><h3>Heading</h3><p>Contents</p></div>';
$("[data-role=content]").append($(collapsible).collapsible());
});
Demo
Try this one:
$( ".selector" ).collapsibleset( "refresh" );

Javascript doing what is expected

I am dynamically adding <script> tags with javascript & jQuery into my html file whenever a button is pushed. Everything gets added in correctly but only one of the two .click jQuery action functions is working. I can't seem to figure out why. No errors in console. I made sure i used \' and \" in the correct places.
$('#classBox').append('<tr id=\"' + tempCHAR + tempNUM + '\">'
+ '<td>'
+ '<i id=\"' + tempCHAR + tempNUM + '\" class=\"icon-remove-sign\">'
+ '</i> '
+ '<a id=\"' + tempCHAR + tempNUM + '\"" href=\"https://cms.psu.edu/section/default.asp?id=' + urlHOLDER + '\" target="framehidden">'
+ tempYEAR + ': ' + tempCHAR + tempNUM + ', Section ' + tempSEC
+ '</a>'
+ '</td>'
+ '</tr>'
+ '<script>'
+ '$(\'#' + tempCHAR + tempNUM + '\').click(function() {'
+ '$(\'tr\').remove(\'tr#' + tempCHAR + tempNUM + '\');'
+ '});'
+ '$(\'a#\'' + tempCHAR + tempNUM + ').click(function() {'
+ '$(\'#framehidden\').attr(\'src\', $(\'a\', this).attr(\'href\')));'
+ '});'
+ '</script>');
The indents are just for me to more easily read what I'm doing. That wouldn't be the problem would it?
If thats too impossible to read then here it is in normal view.
$('a#'IST130).click(function() {
$('#framehidden').attr('src', $('a', this).attr('href')));
});
$('#IST130').click(function() {
$('tr').remove('tr#IST130');
});
I have like 30 other .click functions that all work perfectly but I just cannot figure out what is going wrong here. Any hints?
Since .append() is instant (ie. synchronous), there is absolutely no need to put that stuff in a <script> tag. Instead, try this:
$('#classBox').append('<tr id=\"' + tempCHAR + tempNUM + '\">'
+ '<td>'
+ '<i id=\"' + tempCHAR + tempNUM + '\" class=\"icon-remove-sign\">'
+ '</i> '
+ '<a id=\"' + tempCHAR + tempNUM + '\"" href=\"https://cms.psu.edu/section/default.asp?id=' + urlHOLDER + '\" target="framehidden">'
+ tempYEAR + ': ' + tempCHAR + tempNUM + ', Section ' + tempSEC
+ '</a>'
+ '</td>'
+ '</tr>');
$('#' + tempCHAR + tempNUM).click(function() {
$('tr').remove('tr#' + tempCHAR + tempNUM);
});
$('a#' + tempCHAR + tempNUM).click(function() {
$('#framehidden').attr('src', $('a', this).attr('href')));
});
That being said, your code is HORRIBLY invalid. IDs MUST be unique. I'll leave you to fix that in whatever way works best for you, but yeah.
Your error (or at least one of them) is on this line:
+ '$(\'a#\'' + tempCHAR + tempNUM + ').click(function() {'
Just have an extra single quote there that needs to be moved to the end of the $() block:
+ '$(\'a#' + tempCHAR + tempNUM + '\').click(function() {'
In your example at the end you have $('a#'IST130). Pretty sure that should read $('a#IST130)`
To correct it, change the generation for that ID to:
'$(\'a#' + tempCHAR + tempNUM + '\')...
Additionally, since you are dynamically adding the elements, their click events may not bind properly, depending on exactly when your code is executing.
You can use jquery on to set a bind for the events on a permanent element. In this case #classBox looks like a good bet. It might look something like this (where this would be inside a normal script block and outside of your dynamic stuff:
$('#classBox').on('click','a',function () {
$('#framehidden').attr('src', $('a', this).attr('href')));
});
$('#classBox').on('click',function () {
$(this).closest('tr').remove();
});
Note: Completely untested - intended as a guide!
After you fix the syntax errors, also be sure the click events aren't being attached before the append() code has run.
I can't tell which order the code runs in the actual page - if you're appending the elements before the click events are being attached, the elements may not exist yet. You can use jQuery's delegate method to ensure the events are called for all elements, no matter when they're appended to the DOM.
For example:
$('body').delegate('.anchorClassName', 'click', function(e){});

Creating dynamic html with json taking too much time

I am working on preparing some dynamic html with jquery and json object. but the problem is that when my json object has around 1500 rows it takes ages to load.
is there a way to load the thing faster.
Some code.
$(jQuery.each(jsonObject.AvailableColumns, function (i, l) {
if (type == "manual") {
innerList1 += '<li newText="" valueFormat="' + l.ValueFormat + '" scaleID="' + l.ScaleID + '" scaleType="' + l.ScaleType + '" hasWeights="' + l.HasWeights + '" customColumnType="' + l.CustomColumnType + '" class="" id="li_' + controlId + '"><span id="span_' + controlId + '" title = "' + l.QuestionText + '">' + getDisplayString(l.QuestionText) + '</span><a class="actionLeft"></a></li>';
}
else if (type = "exportall") {
innerList2 += CreateLiWithSpans('li_' + controlId, l.QuestionText, true, false, l.ScaleID, l.ScaleType, l.HasWeights, l.CustomColumnType, l.ValueFormat);
}
controlId++;
}));
$("#itemList").html(innerlist1);
EDIT : createliwithspan method
function CreateLiWithSpans(id, html, isLeft, isAddAll, scaleID, scaleType, hasWeights, customColumnType, valueFormat, newText) {
var ancClass = isLeft ? 'actionRight' : 'actionLeft';
var liObject = "";
if (newText == null) {
newText = "";
}
if (isLeft) {
liObject = '<li newtext="' + newText + '" valueFormat="' + valueFormat + '" scaleID="' + scaleID + '" scaleType="' + scaleType + '" hasWeights="' + hasWeights + '" customColumnType="' + customColumnType + '" class="" id="' + id + '"><span id="span_' + id + '" title = "' + html + '">' + getDisplayString(html) + '</span><span style="margin:0 10px 0 20px;pagging:0"><input title = "' + (newText == "" ? html : newText) + '" type="text" id="' + id + 'displayText" value="' + (newText == "" ? html : newText) + '" /><span style="color:Red; width:100%;" id="' + id + 'displayTextError"></span></span><span style="float:left">' + CreateDropDown('ddl_' + id, valueFormat, hasWeights) + '</span><a class="' + ancClass + '"></a></li>';
}
else {
liObject = '<li newtext="' + newText + '" valueFormat="' + valueFormat + '" scaleID="' + scaleID + '" scaleType="' + scaleType + '" hasWeights="' + hasWeights + '" customColumnType="' + customColumnType + '" class="" id="' + id + '"><span id="span_' + id + '" title = "' + html + '">' + getDisplayString(html) + '</span><a class="' + ancClass + '"></a></li>';
}
return liObject;
}
You can use for loop instead of jQuery.each, that will be faster. Store the itemCount before the loop, and use that:
itemCount = jsonData.items.length;
for(var i = 0; i < itemCount; i++ ) {
...
You can also use use an array instead of string concatenation, like so:
var innerList = [];
... // inside the loop
innerList.push(CreateLiWithSpans('li_' + controlId, l.QuestionText, true, false, l.ScaleID, l.ScaleType, l.HasWeights, l.CustomColumnType, l.ValueFormat));
... // after the loop
$("#itemList").html(innerList.join(''));
This will be faster in IE, I'm not sure about other js engines.
These two methods will not make a significant difference, so you should try implementing a client side pagination from json. (Not by hiding and showing divs, by rendering only visible page into the DOM).
Instead of waiting for the loop to end to append your data, why not actively append the data as you process it. This will allow the user to get immediate feedback instead of waiting for the whole thing to process. Other than this, I'd stick with my original comment to page the data.
$(jQuery.each(jsonObject.AvailableColumns, function (i, l) {
if (type == "manual") {
$("#itemList").append( '<li newText="" valueFormat="' + l.ValueFormat + '" scaleID="' + l.ScaleID + '" scaleType="' + l.ScaleType + '" hasWeights="' + l.HasWeights + '" customColumnType="' + l.CustomColumnType + '" class="" id="li_' + controlId + '"><span id="span_' + controlId + '" title = "' + l.QuestionText + '">' + getDisplayString(l.QuestionText) + '</span><a class="actionLeft"></a></li>');
}
else if (type = "exportall") {
$("#itemList2").append(CreateLiWithSpans('li_' + controlId, l.QuestionText, true, false, l.ScaleID, l.ScaleType, l.HasWeights, l.CustomColumnType, l.ValueFormat));
}
controlId++;
}));
Try replacing jQuery.each with a plain old for...in loop. Using jQuery.each adds overhead that you don't need.
Don't concatenate strings inside your loop. Instead, .push them onto an array variable and use .join('') to build the string all at once at the end.
You may need to eliminate CreateLiWithSpans as a separate function in order to fully implement (2).
Changing from using jQuery.each to a standard javascript for loop should speed it up a bit. Make sure that you save the length to a variable like this though:
for(var i = 0, len = jsonObject.AvailableColumns.length; i < len; i++){
var l = jsonObject.AvailableColumns[i];
// Continue with rest of code
}
Probably won't be a huge increase but every little helps.
Also try lowering the number of function calls you make as these have added overhead (not usually an issue, but in a large loop it can help). Unless the code is shared between functions try doing it inline and see how much that speeds it up.

Categories

Resources