I'm on a .NET 4.0 environment using jQuery and Visual Studio to write everything, but neither of these facts should matter that much except how to populate the XML data.
I'm starting out with this script which has a lot of markup in it. My task is to get the markup out of the script and to populate the the XML data into the markup in its proper place. I'm trying to keep the presentation and behavior layers as separate as possible by doing this.
function addIcons(IconType) {
var li ="";
var onclickMethod="";
for (var item in hashObject) {
var thumbNail = item.split("_");
if (thumbNail[0] == IconType +"ThumbNail") {
var imagePath = baseUrlThumbNailImages + hashObject[item];
li = li + "<li onclick=IconClick('" + IconType +"',"+ thumbNail[1] + ")><img src=\"" + imagePath + "\" alt=\"" + IconType + " shape\"></li>\n";
}
}
$("#" + IconType + "ThumbNailShapes").append(li);
}
Here's example markup I want as final result:
<ul>
<li onclick="IconClick('Item',1)">
<img src="/images/image_1.png" alt="Item shape" />
</li>
<li onclick="IconClick('Item',2)">
<img src="/images/image_2.png" alt="Item shape" />
</li>
<li onclick="IconClick('Item',3)">
<img src="/images/image_3.png" alt="Item shape" />
</li>
</ul>
While I know I need to take out the line of code that starts li = li + ..., I'm also not familiar enough with OOP to understand how to write a for loop to populate the markup.
So there's two factors that I am not sure how to code:
The blank markup - does the markup need variables to populate it or should javascript do this automatically?
The javascript - I don't know how to recode the javascript to find each list item and image tag to populate the various data.
Do I need the markup to be blank like this, where all the variable data is not there yet?
<ul id="IconThumbnailShapes">
<li onclick="">
<img src="" alt="shape" />
</li>
<li onclick="">
<img src="" alt="shape" />
</li>
<li onclick="">
<img src="" alt="shape" />
</li>
</ul>
I appreciate the insight and help.
I would do it like this.
Let's suppose we have a container DIV#foo where all this code has to reside.
<div id="foo"></div>
We then do this:
$(function() {
// DOM ready
$('#foo').on('click', '#IconThumbnailShapes li', function() {
// Do whatever you have to do with icon
// Second argument there '#IconThu... li' means the event will be trigerred
// as soon as you add your icons, but they don't have to be there
// right now.
});
function addIcons(iconType) {
var s = '<ul id="IconThumbnailShapes">'
var l = '<li><img src="$SRC" alt="$ICON shape" /></li>'
var data = [{...}, {...}, {...}];
var len = data.length;
var datum;
for (var i = len; i; i--) {
datum = data[len - i];
s += l.replace('$SRC', datum.src).replace('$ICON', iconType);
}
s += '</ul>';
$('#foo').html(s);
}
});
So, we do it like this, because we don't want to fire jQuery stuff in the for loop. That kills performance. Instead we set up a deferred even handler for click on the conainer DIV#foo, and we shove the whole bunch of markup into the container as a string.
Related
I want to create a dynamic 'li' elements and want to assign some classes to the 'li' element by a javascript function based on some parameters in the load of the page
I mean i want the function to run on all the 'li' elements i assign the function to.
something like :
in design
<li class="nav-item someFunction("param1","param2")">
</li>
and the 'someFunction' is a javascript function that returns some classes as a string
to make the 'li' element as follows in the end :
after rendering
<li class="nav-item cssClass1 cssClass2 cssClass3 cssClass4">
</li>
Not exactly how you asked it, but here is how you do it with jquery:
CodePen: https://codepen.io/anon/pen/XeJKVL
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<style>
.red{
color:red;
font-size:25px;
}
</style>
<script>
window.onload = function() {
$( "#example" ).addClass("red");
}
</script>
<li id="example">Example</li>
$(document).ready(function(){
$("#ifValueBtn").on("click",function(){
var iFinput=$("#ifValue").val();
if(iFinput==1)
$(".nav-item").addClass("cssClass1");
else if(iFinput==2)
$(".nav-item").addClass("cssClass1 cssClass2");
else
$(".nav-item").addClass("cssClass1 cssClass2 cssClass3");
console.log($(".nav-item").attr("class"));
});
});
.cssClass1{color:red;}
.cssClass2{border:solid 1px #000;}
.cssClass3{font-size:20px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="ifValue" type="number" value="1"/>
<input id="ifValueBtn" type="button" value="Click"/>
<hr>
<ul>
<li class="nav-item">
test
</li>
</ul>
Actually I figured out the answer from you people answered ideas
I create the li items dynamically so I tried to create all the markup for it from database but it didn't work as the functions calls are being copied as string without parsing or compiling it of course
so
I have made the following function :
function someFuncionConvertedItsCodeFromServerSide(parameter1, parameter2,...) {
//somecode that debend on some server side functions, collections, session values, properties
// return css as string
}
and get some parameters from the db as follows in the ajax call example :
$.ajax({
type: 'POST',
url: 'url',
dataType: 'json',
success: function (result) {
for (var i = 0; i < result.array.length; i++) {
var css = someFuncion(result.array[i].id, other parameters .. );
var liItem = "<li class=\"nav-item " + css + " id=\"" + result.array[i].id + "\"> <span class=\"title\" > " + someText + " </span > </li>";
$("#ulId").append(liItem);
}
}
});
so as you can see I created an id for every created li to combine the parameters in one place that can be sent to a javascript function to return the css classes as a string as needed
It's a prototype code of course it needs some modification but that what is done and worked
thank you all guys trying to help I get the idea from our discussion together
tell me If i didn't mark the right answer
I need to change the content of span tag inside of div tag with div id dynamically. I tried this code but it's not working. I think the problem with $('#'+ids[i]). Even I'm getting the information correctly to each id. Any suggestions please.
JavaScript:
var ids = ["Of0UWpK5bEo","1qYMJjTxJnM","8aAab7gxbEg","ZEd6aKdeC8g","qQcFvamzdno","yovbI8DOMpk"];
for (i = 0; i < ids.length; i++) {
$.get("https://www.googleapis.com/youtube/v3/videos?part=snippet,statistics&id="+ ids[i] + "&key=AIzaSyDEm5wGLsWi2G3WG40re-DAJcWioQSpJ6o", function(data){
$('#'+ids[i]).parent().find('.caption').text(data.items[0].snippet.title);
});
}
HTML:
<div id="Of0UWpK5bEo" class="status">
<img src="http://img.youtube.com/vi/Of0UWpK5bEo/0.jpg" height="100px" width="100px"/>
<span class="caption">Text below the image</span>
</div>
I found it to be the problem of variable scope.
This can be solved by using a anonymous function.
Pass the loop variable i to the anonymous function so that ii will be accessible inside the function.
Check out this fiddle.
Here is the snippet.
var ids = ["Of0UWpK5bEo", "1qYMJjTxJnM", "8aAab7gxbEg", "ZEd6aKdeC8g", "qQcFvamzdno", "yovbI8DOMpk"];
var i;
for (i = 0; i < ids.length; i++) {
(function(ii) { // collect into 'ii' here
$.get("https://www.googleapis.com/youtube/v3/videos?part=snippet,statistics&id=" + ids[ii] + "&key=AIzaSyDEm5wGLsWi2G3WG40re-DAJcWioQSpJ6o", function(data) {
$('#' + ids[ii]).html(data.items[0].snippet.title);
});
}(i)); //pass 'i' here
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="Of0UWpK5bEo" class="status">
<img src="http://img.youtube.com/vi/Of0UWpK5bEo/0.jpg" height="100px" width="100px" />
<span class="caption">Text below the image</span>
</div>
What you need is:
$('#'+ids[i]).find('.caption').text(...);
as .caption is the child of the ID in question itself. Hence, .parent() is not required.
A Demo
Also, use var in your loop as below. You'd create a global for no reason, otherwise.
for (var i = 0; i < ids.length; i++) {
As it turned out, it's due to the async behaviour of $.get() and loop being synchronous. So, your loop has already finshed running whereas you may be at your 1st or 2nd ajax request. What you need to do is scope the id value (based in i) into the ajax request, probably by creating a closure, like below.
var ids = ["Of0UWpK5bEo","1qYMJjTxJnM","8aAab7gxbEg"];
for (var i = 0; i < ids.length; i++) {
(function(id) {
$.get("https://www.googleapis.com/youtube/v3/videos?part=snippet,statistics&id="+ id + "&key=AIzaSyDEm5wGLsWi2G3WG40re-DAJcWioQSpJ6o", function(data) {
$('#' + id).find('.caption').text(id); //use data.items[0].snippet.title instead of id
});
}(ids[i]));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="Of0UWpK5bEo" class="status">
<span class="caption">Text below the image</span>
</div>
<div id="1qYMJjTxJnM" class="status">
<span class="caption">Text below the image</span>
</div>
<div id="8aAab7gxbEg" class="status">
<span class="caption">Text below the image</span>
</div>
Here is a working demo using fiddle echo apis.
This code isn't the best written, but I can explain what is going on.
Your fundamental problem is that the value for "i" is no longer what you expect it to be. By the time the results of the AJAX function have completed, it's an undefined value. The correct way to do this is with an iterator:
$.each(ids, function(index, id) {
$.get("..." + id + "...", function(data) {
$("#" + id).parent().find('.caption').text(data.items[0].snippet.title);
});
});
Also, make sure your code is in a "document.ready()" block or you may not be able to find the elements:
$(document).ready(function() {
$.each(ids, function(index, id) {
$.get("..." + id + "...", function(data) {
$("#" + id).parent().find('.caption').text(data.items[0].snippet.title);
});
});
});
That being said, this looks like the interface should be dynamically created in Javascript. That would allow you to avoid many of the issues with matching IDs in tags and searching for sibling tags since you'd already have the reference.
Working fiddle: https://jsfiddle.net/85jeaoqq/
Here's a slightly better version that dynamically creates the images and caption. It includes code to limit the text to 20 characters: https://jsfiddle.net/x7v2zt6f/
I have the following function:
function displayResults(Items) {
$("#result").text("");
$("#result").append('<div class="car-offers">');
$("#result").append('<div class="purple"></div>');
$("#result").append('<img src="images/caroffer.jpg" alt="" title="" width="213" height="117" />');
$("#result").append('<h3>titleeee</h3>'); // ' + Items[i].Title + '
$("#result").append('<span>Year: 2003</span>');
$("#result").append('<span>Milage: 172,000 Km</span>');
$("#result").append('<span class="price">53,000 QR</span>');
$("#result").append('Link');
$("#result").append('</div>');
$("#result").append('<div class="car-offers">');
$("#result").append('<div class="purple"></div>');
$("#result").append('<img src="images/caroffer.jpg" alt="" title="" width="213" height="117" />');
$("#result").append('<h3>titlee22</h3>'); // ' + Items[i].Title + '
$("#result").append('<span>Year: 2003</span>');
$("#result").append('<span>Milage: 172,000 Km</span>');
$("#result").append('<span class="price">53,000 QR</span>');
$("#result").append('Link');
$("#result").append('</div>');
}
my problem is that at run-time the html is being displayed like: <div class="car-offers"></div> so all the page is being messed up
You cannot append incomplete fragments of HTML with .append(). Unlike document.write, jQuery's .append() method parses the passed string into elements before appending them to the DOM.
So when you do:
$("#result").append('<div class="car-offers">');
jQuery parses the given string into a div element and assigns the car-offers value to its className property, then appends the newly created element to the #result element.
Appending the whole HTML string in a single operation will fix that, so jQuery knows how to parse the given string correctly.
Personally, I wouldn't suggest putting that much HTML inside of a JS file. You can consider putting that inside of a div with display:none then simply call .show() on it. Or have it initially in the page, .detach() it storing in a variable and .append() it back when necessary.
You can use a array with join to solve this
function displayResults(Items) {
$("#result").text("");
var array = [];
array.push('<div class="car-offers">');
array.push('<div class="purple"></div>');
array
.push('<img src="images/caroffer.jpg" alt="" title="" width="213" height="117" />');
array.push('<h3>titleeee</h3>'); // ' + Items[i].Title + '
array.push('<span>Year: 2003</span>');
array.push('<span>Milage: 172,000 Km</span>');
array.push('<span class="price">53,000 QR</span>');
array.push('Link');
array.push('</div>');
array.push('<div class="car-offers">');
array.push('<div class="purple"></div>');
array
.push('<img src="images/caroffer.jpg" alt="" title="" width="213" height="117" />');
array.push('<h3>titlee22</h3>'); // ' + Items[i].Title + '
array.push('<span>Year: 2003</span>');
array.push('<span>Milage: 172,000 Km</span>');
array.push('<span class="price">53,000 QR</span>');
array.push('Link');
array.push('</div>');
$("#result").text(array.join(''));
}
This is an issue I've just come across too. An option is to create the div containers first in a loop then populate them after as you require:
for(var i = 0; i < 12; i++){
$(el).append('<li class="scene-block"></li>'); // create container li tags
//fill empty li tags with content
for(var j = 0; j < 2; j++){
$(el).find('li').last().append('<div class="select-a-scene-bg"></div>');
}
}
I generate dynamically a toc for elements of class=faqQuestion.
The answer resides in a class=faqAnswer element which is hidden by default.
By clicking on class=faqQuestion entry it will show up with
$(this).next(".faqAnswer").slideToggle(300);
Everything works as expected.
What I want: by clicking on a toc link i will jump to the target faqQuestion element and show the corresponding faqAnweser element.
The way I generate the toc:
$(document).ready(function(){
var url = window.location.pathname;
$('<ol />').prependTo('#toc')
$(".faqQuestion").each(function(i) {
var current = $(this);
current.attr("id", "entry" + i);
$("#toc ol").append("<li class=\"faqToc\"><a id='link" + i + "' href='" + url + "#entry" +
i + "' entry='" + current.attr("tagName") + "'>" +
current.html() + "</a></li>");
});
This is what I tried, which will jump to the selected faqQuestion but the faqAnswer element is still hidden.
$(".faqToc").click(function(event){
$(this).next(".faqAnswer").slideToggle(300);
});
My problem is this - at least I think so - so I tried something like - which results in "undefined"
var url = $(this).prop("href");
alert(url);
Trying attr instead of prop returns also "undefined".
Can you point out my problem?
I'm trying to improve my Javascript and jQuery know how, so I don't want to use a toc-plugin.
Update: HTML looks like this:
<div id="toc">
<ol>
<li class="faqToc">
...
</li>
<li class="faqToc">
...
</li>
</div>
<p id="entry0" class="faqQuestion">...</p>
<div class="faqAnswer" style="display: none;">...</div>
<p id="entry1" class="faqQuestion">...</p>
<div class="faqAnswer" style="display: none;">...</div>
A very simple way would be to use the index() method since relationship between the TOC elements and the question/answer elements is 1 to 1.
$(".faqToc").click(function(event){
var index=$(this).index(); /* zero based index position of element within it's siblings*/
/* toggle answer element with same index */
$(".faqAnswer").eq(index).slideToggle(300);
});
jQuery API Reference : index()
How can I create an unordered list dynamically using jQuery? I read the image file path (href and src) from an XML file.
<ul>
<li><img id="imageSlide" src="images/test1.png" alt="" /></li>
<li><img id="imageSlide" src="images/test2.png" alt="" /></li>
</ul>
It should create unordered list
based on number of XML nodes in the XML file.
Well, you have to loop over your XML structure and create new LI nodes in the body of that.
var dummyXML = "<foo><dummy>element</dummy><dummy>element</dummy><dummy>element</dummy></foo>";
var HTMLmarkup = '';
$(dummyXML).find('dummy').each(function(){
HTMLmarkup += '<li>' + $(this).text() + '</li>';
});
$('ul').append(HTMLmarkup);
That of course, is just a dummy example. Infact you should consider to use more sophisticated XML traversal systems like XPath (depending on how big your XML file is).
$('ul li').text(function(index) {
return '<a href=images/test' +index +'><img id="imageSlide" src="images/test'+index+'.png" alt="" /></a>';
});