I'm trying to create a "feed" using data received from another site. It comes as an array of similar objects. I've tried a couple of ways of displaying the data but keep changing my mind on the best way to do it. Currently I'm using jQuery loop through the objects and create the same divs for each one by nesting $(<div>).html()
This uses much less code than my previous method of plain javascript to add new elements but I'm not sure if this is the best use of jQuery. Would there be a better way of doing this?
Possibly creating a new JavaScript object for each array element?
EDIT: here's a small snippet of code. It's not closed off and I've changed the class names and variables but it's a rough idea.
$.each(feed.data, function(i, var_name) {
$("<div>").attr({
"id" : var_name.created_time,
"class" : "Post"
}).html(
$("<img>").attr({
"class" : "Picture",
"src" : "some_src" + var_name.id + "/picture"
});
Your method is the least efficient of all the possible methods due to the significant number of function calls made for each individual element.
Although you could add a template engine as suggested, it's worth learning how to create html strings as well, and will find that wrapping each element in $() doesn't really reduce code
var newHtml=[];
$.each(feed.data, function(i, var_name) {
newHtml.push('<div id="'+var_name.created_time+'" class="Post">');
newHtml.push('<img class="Picture" src="some_src"' + var_name.id + '/picture" />');
/* some nested data*/
$.each( var_name.someRepeatingElements), function(i,val){
newHtml.push('<p>'+val.content+'</p>')
});
newHtml.push('</div>')
});
/* after looping all data only make one append to DOM*/
$('#someDiv').append( newHtml.join(''))
Semantically this is easier to read than nesting numerous $.html() calls also
In many cases without a lot of complicated nesting, creating your own strings is less work than creating a template and code to populate template
Related
JS comparative newbie... spent about 3 hours on this so far... Please consider this code if you'd be so kind:
function updateDataFields( mapIDToNewValue )
{
$.each(dataFields, function(key, value)
{
var dataField = $( value );
// var dataField = $(this); // same difference
console.log( dataField );
var iD = dataField.attr('id');
// DOES NOT WORK!!! i.e. going val() on this object does not update the INPUT element on the page!
// dataField.val(mapIDToNewValue[ iD ]);
var thePageElement = $( '#' + iD );
console.log( thePageElement );
console.log( '£ is dataField the same object as thePageElement?' + ( dataField === thePageElement ? 'yes' : 'no, you fool' ));
// DOES WORK:
thePageElement.val( mapIDToNewValue[ iD ] );
});
}
Explanation: dataFields, a file-global variable*, is passed by an outside script which calls this one, using a (fully) global variable which attaches dataFields to itself in piggyback fashion. This data structure, dataFields, consists of all the page elements with the class .dataField. All of these are in fact INPUT HTML elements.
Using the supplied param mapIDToNewValue (from an AJAX call to a dbase), I want to update the respective contents (i.e. text) of these INPUTs. mapIDToNewValue is a map in which the key is the same as the attr( 'id' ) of these dataFields, and the value is the new value which needs to be displayed in the INPUT.
It turns out that thePageElement is not the same object as dataField. When I examine the console output for them both they appear virtually the same... except that dataField, for example, has 0 height, which is enough to chill the soul!
My working hypothesis is that somehow dataFields, when passed from the calling script via this piggyback global variable, somehow turned its contents into "phantom" objects: they have the same id as thePageElement... but are incapable of having any effect on the real page elements themselves!
NB there is no possibility of duplicate ids here, or anything like that.
Any explanation welcome!
* implemented using anonymous function as per here.
later, in response to Patrick Barr's comment:
It's quite involved. Given your use of the word "interesting", I was moved to find out what your rep might be. If you had been a proven JS guru (you may nonetheless be one of course) I'd have been inclined to think that I need to embark on a forensic fault-finding mission.
The context: I'm developing a sort of "MSAccess Forms for MySQL front end" type of a thing, which is sorely lacking out there IMHO. At the moment I'm tackling subforms, and a major aim is to re-use code as much as is humanly possible. I'm rapidly getting out of my depth, not least because of the asynchronicity/concurrency issues that spring up, gorgon-like, at every turn. I'm thinking about how to answer your question in an informative, useful way.
To anyone else: I now realise I have to strip down my project to the bare bones to find out what's going on here... and if still baffled post an SSCCE (as we call it in Java) ... just thought initially that an expert out there might recognise a well-known issue and be able to set me straight.
Having examined things here I now understand what happened (to a degree).
In fact the dataFields Array was obtained from the result of an AJAX call which loaded (or more accurately returned, as the data param in the callback function) an HTML fragment, containing several page elements with class .dataField, which I then gathered by going data.find( '.dataField' ).
But in fact these "page elements", despite having hundreds of properties, just like objects directly "mapping" to page elements, were indeed "phantom" objects: specifically, properties such as clientHeight were 0, seemingly an indication that this is a non-visible object.
It was only when the HTML returned in the AJAX callback was inserted into the document structure (and made visible by setting hidden to false for the encompassing DIV) that this HTML generated real page elements. I then had to select these page elements with class .dataField to get hold of the non-phantom objects (having clientHeight 20 or whatever).
Quite strange, as these initial "phantom" objects did NOT become "real" objects as a consequence of the HTML being added to the document. They remained ... useless (and confusing!).
A project I am working on for works wants a pure JavaScript version of the .data() implementation of jQuery.
I wanted to replicate this.
I did a search and Where is jQuery.data() stored? shows where in jQuery it is stored.
I was hoping that i could just attach a datasegment to an HTML element for accessing later.
Since jQuery is Javascript, I can look there, but it makes use of the jQuery objects, which is what I am trying to abstract. I figured there was some sort of way to associate a hash table like dataset with JavaScript and attach it to an object.
http://jsfiddle.net/npXQx/
shows you can create a .data in the object and then it is preserved. You can access it twice, and the data is there.
This example shows a simple string assignment and a function and it being called multiple times.
var item = document.getElementById("hi");
console.log(item);
item.data = {getType: function(){return this.TYPE},TYPE:"winner"};
var out = item.data.getType();
console.log("out", out);
var two = document.getElementById("hi")
console.log("should say 'winner': ", two.data.getType());
I've been using KendoUI and have been using they're command functions. However to call JS I must call named jS functions. No huge deal. When I use the "This" key word it brings back the entire grid and I mus find a value of a child from a sibling of the same parent elements and i wound up doing this ugly thing. The question I have is how can I turn this "thing" into something jqueryable readable and comprehensible
function AddRole(e) {
var $ParentNode = e.target.parentNode.parentNode.children[1].children[0].getAttribute("value", 0);
}
Sorry, but you have other problems.
If you rely on such a structure e.target.parentNode.parentNode.children[1].children[0], your Markup and JS do not scale at all.
Use the oppurtunity to create scalable and consistent code. Or at least, set some id, class or html5 data attribute on the children[0] element in order to identify it properly.
This problem is about Javascript writing HTML code for video player. I think there are some faster methods(document.createElement,Jquery and etc). Please tell some better and faster methods for this procedure. Thanks in advance
function createPlayer(videoSource){
document.writeln("<div id=\"player\">");
document.writeln("<object width=\"489\" height=\"414\" >");
document.writeln("<param name=\"player\" value=\"bin- debug/FlexPlayer.swf\">");
//etc
document.writeln("</embed>");
document.writeln("</object>");
document.writeln("</div>");
}
Going native with document.createElement will be the fastest. However, if your markup is large, going this way makes it a maintenance nightmare. Also, it is not easy to 'visualize' things.
In those cases, you might want to go for a tradeoff with client side templating solutions such as jQuery templates or underscore templates or John Resig's microtemplating.
Another performance boost is to build your entire markup and add it to DOM at the very end (add children first, then add the parent to DOM).
There is a jQuery function I know of that allows you to create a template HTML snippet which you can later use repeatedly with only 1 or 2 lines of code, adding in variables and appending it to the page.
For this you will need jQuery (latest should be fine) http://jquery.com/
Docs for the tmpl function are here: http://api.jquery.com/jquery.tmpl/
For details on how to use it you'd be best reading an example on the jQuery docs, I've not used it myself so can't write you a good example but there is great stuff on the docs site.
Hope this helps
EDIT:
A less resource intensive way to acheive that function would be to, rather than writing each line in turn to the document, just append them all to a string and then write that once when you are finished.
Eg:
function createPlayer(videoSource){
var html="<div id=\"player\">";
html+="<object width=\"489\" height=\"414\" >";
//etc
document.writeln(html);
}
This is faster because writing a line to the document uses more resources than just appending a string in memory. For MAXIMUM SPEED you could even declare the html var outside of the function and just set it to the markup as one long string, then write it - i.e
var html;
function createPlayer(videoSource){
html="<div id=\"player\"><object width=\"489\" height=\"414\" >"; //and so forth
document.writeln(html);
}
If you can justify the larger download sizes I'd go for the jQuery solution if possible, it's generally a bit more manageable - I've done plenty script generated HTML in the past and it very quickly becomes a pain to maintain. Good luck
You can try this:
function createPlayer(videosource){
var div = document.createElement('div');
div.innerHTML = '<object width=\"489\" height=\"414\" >' +
'.......'
document.body.appendChild(div);
}
For general manipulation and addition of HTML I'd recommend jQuery. It makes the process much easier and quicker.
You will find more information on this here:
jQuery Manipulation Methods - http://api.jquery.com/category/manipulation/
jQuery Tutorials - http://docs.jquery.com/Tutorials
We're considering switching our site from Prototype to jQuery. Being all-too-familiar with Prototype, I'm well aware of the things about Prototype that I find limiting or annoying.
My question for jQuery users is: After working with jQuery for a while, what do you find frustrating? Are there things about jQuery that make you think about switching (back) to Prototype?
I think the only that gets me is that when I do a selection query for a single element I have to remember that it returns an array of elements even though I know there is only one. Normally, this doesn't make any difference unless you want to interact with the element directly instead of through jQuery methods.
Probably the only real issue I've ever ran into is $(this) scope problems. For example, if you're doing a nested for loop over elements and sub elements using the built in JQuery .each() function, what does $(this) refer to? In that case it refers to the inner-most scope, as it should be, but its not always expected.
The simple solution is to just cache $(this) to a variable before drilling further into a chain:
$("li").each(function() {
// cache this
var list_item = $(this);
// get all child a tags
list_item.find("a").each(function() {
// scope of this now relates to a tags
$(this).hide("slow");
});
});
My two pain points have been the bracket hell, can get very confusing
$('.myDiv').append($('<ul />').append($('<li />').text('content')));
My other common issue has to do with the use of JSON in jQuery, I always miss the last comma,
$('.myDiv').tabs({ option1:true, options2:false(, woops)});
Finally, I've been using jQuery for about 6 months now and I don't think I'll ever go back to prototypes. I absolutely love jQuery, and a lot of the tricks they use have helped me learn a lot. one cool trick that I like is using string literals for method calls, I never really did that too much with prototypes.
$('.myDiv')[(add ? 'add' : 'remove') + 'Class']('redText');
(The only thing I can think of is that this is the element instead of a jQuery object in $("...").each(function)-calls, as $(element) is more often used then just the element. And that extremly minor thing is just about it.
Example of the above (simplified and I know that there are other much better ways to do this, I just couldn't think of a better example now):
// Make all divs that has foo=bar pink.
$("div").each(function(){
if($(this).attr("foo") == "bar"){
$(this).css("background", "pink");
}
});
each is a function that takes a function as parameter, that function is called once for each matching element. In the function passed, this refers to the actual browser DOM-element, but I find that you often will want to use some jQuery function on each element, thus having to use $(this). If this had been set to what $(this) is, you'd get shorter code, and you could still access the DOM element object using this.get(0). Now I see the reason for things being as they are, namely that writing $(this) instead of this, is hardly that cumbersome, and in case you can do what you want to do with the DOM element the way it is is faster than the way it could have been, and the other way wouldn't be faster in the case you want $(this).)
I don't think there are any real gotchas, or even any lingering annoyances. The other answers here seem to confirm this - issues are caused simply by the slightly different API and different JavaScript coding style that jQuery encourages.
I started using Prototype a couple of years ago and found it a revelation. So powerful, so elegant. After a few months I tried out jQuery and discovered what power and elegance really are. I don't remember any annoyances. Now I am back working on a project using Prototype and it feels like a step back (to be fair, we're using Prototype 1.5.1).
If you reversed the question - "What Prototype annoyances should I be aware of as a jQuery user?" - you would get a lot more answers.
Nope. Nada. Nyet.
.each:
jQuery (you need Index, even if you're not using it):
$.each(collection, function(index, item) {
item.hide();
});
Prototype (you're usually using the item, so you can omit the index):
collection.each(function(item) {
item.hide();
});
This is really only an annoyance if you're doing a lot of DOM manipulation. PrototypeJs automatically adds its API to DOM Elements, so this works in prototypejs (jQuery of course doesn't do this):
var el = document.createElement("div");
el.addClassName("hello"); // addClassName is a prototypejs method implemented on the native HTMLElement
Even without running the native element through the $() function.
PS: Should note that this doesn't work in IE.