I am building app with php and jquery and it has many ajax loads and functionalities. What i would like to know is what is the most widely used and acceptable way of accessing dom elements with jquery and adding events to it using jquery and javascript and if there is any rule of thumb to follow for the following instances.(and how i do them now)
A query generates a list of records and each record has to be edited and deleted.
The generated records look like this
Record1
Record1
Record2
Record2
Record3
Record3
and my jquery code handle them would be
$(".edit").click(function() {
var currentElementId = $(this).attr("id").replace("edit-id-","");
$("#ajaxdiv").load("ajaxpage.php","editid="+currentElementId);
});
is this type of stuff ok? i mean is there any other way to do stuff like this especially when this gets more complicated like have to add 3 more identifiers to id and then exploding them and finding out each of the identifiers separately. Any guidelines here to follow.?
If you simply need to have something that can be cleaner, maybe you can consider bind the record into one
meaningful div, and use .live() to bind the event handlers
i.e.,
<div data-rec-id = '300'>
...
<span class='link del' data-act='del'>Delete</span>
<span class='link edit' data-act='edit'>Edit</span>
</div>
<div data-rec-id = '301'>
...
<span class='link del' data-act='del'>Delete</span>
<span class='link edit' data-act='edit'>Edit</span>
</div>
$('.edit').live('click', function(){
var id = $(this).closest('[data-rec-id]').attr('data-rec-id');
$("#ajaxdiv").load("ajaxpage.php","editid="+id);
});
or even generic:
$('.link').live('click', function(){
var id = $(this).closest('[data-rec-id]').attr('data-rec-id');
var action = $(this).attr('data-act');
$("#ajaxdiv").load("ajaxpage.php","id="+id+"&act="+action);
});
Please don't use something like:
<a href="javascript:;" ...
or I would suggest you use some robust framework. e.g., http://documentcloud.github.com/backbone/
I think the way you've done it is acceptable. You're mostly concerned about manually doing string processing to fetch the element ID? That is a little messy but not too bad.
If you don't want to do it that way, you might consider attaching a separate event handler to each a element when you create them, and have that event handler know the ID as a closure variable. But that will consume more memory, so it will depend on how many of those links you have.
I've found using using the web server to server up static web pages with the only dynamic content being json passed back and forth, is the best overall approach. We post JSON, and get JSON back from the server. This is used to design the page. This makes the web server become a data communication rather than heavy lifting the page constructing. This also add the ability for an API structure you can give out to ppl and they can write apps for it. For example, the web site and the mobile application use the same API interface.
Related
I am beginner in jQuery and asp.net. I created a simple chat application using SignalR, the design of which you can find here fiddle
How can I create a new instance of that chat design whenever a user has been call by other user while he/she were in chat from before with other user. Here I think I can convert it to User Control. but I dont want to have same Id's which I am using for other chat design and those generated instances should work differently, I mean if userA calls userB and at the same time userC calls userB then they must be created in such a way that they must be unique in handling there own calls (just like FB Chat).
The another issue may arise after successfully creating a new instance is that they might not be get attached to the jQuery functions and server side code automatically. If so, anyway to solve this too?
Before asking here I searched alot (maybe I dont know the exact keyword to search for).
EDIT: Many jQuery developers suggested me to go with Knockout.js or Backbone.js or simple jQuery. But I think there is some simple way to achieve this using ASP.NET functions like User Control or HTTP Handlers (or something else). About which I dont know anything. So, please suggest me which concept to opt for ? and please give detailed explanation(if possible with simple example).
jquery related answers are also welcome.
Single Instance
Multiple Instances
Use JQuery to populate or popup new instance of chat but change your ids using jquery. I would suggest have all your styling and ids done according to a parent container so you can easily grap the parent, duplicate it and change the IDs or content.
I would keep a non filled chat window with ID's like "updateme1" updateme2 etc and then once i get it as a template i will replace all ids one by one with relevant content.
You are doing it right and i dont think its signalR that you need to look into. SignalR would be able to help you pass on specific parameters like "requirechatwindow=true or false" based on if this person is in chat with current person but you can always do this on client as well by going through current open chat sessions. If current chat session does not contain a chat between A and B then open new window with new ID and put a data-from= A and data-to=B as a palceholder so you know this chat is between A and B etc
Hope this helps
UPDATED Fiddle and technique
Here is the fix on Your fiddle edited to show creation and multiple ids I had to adjust some of your css to view the boxes in different location
Updated the code with some comments
The technique is simple:
You create a html template on your page might be in a hidden region
You then use that to create new element in a container and have a handle to pickup this element for example in my code the currentid is my handle but i know the container name so i will only pickup template populated within the actual container to avoid conflict with template itself.
Assign a new id and then you can use any events or any speacial objects on there.
You can then pickup new elements from the new id or any other handle you might have inside them. For example i have just added a click even on it with confirm to hide it.
$('#doubleme').click(function(){
var currentid = $("#chattemplate .chat-outline").attr('data-tid');
var newid = parseInt(currentid,10) + 1;
$("#chatcontainers").append($("#chattemplate").html());
$("#chatcontainers .chat-outline").attr('id',"id"+newid);
$("#chattemplate .chat-outline").attr('data-tid',newid);
});
You only need these five lines of code actually and if you go to fiddle i have commented all of them but they are easy to understand. I am using selectors used in fiddle but these can be further optimised with attributes like data-handle-for or whatever name you can give.
If you are considering this for SignalR then within your hub response of new request you can call the intiate chat window which can setup everything on the client. Any subsequent messages using that data handle can be updated within this new chat window.
For example i assume you create a new group called "chatwindow7" and "chatwindow8" which makes its round trip in your send method and so on get broadcast to only user with this group. Then each user might have multiple windows open but you only need to pickup chatwindow7 for messages with that data handle and update it and so on.
If you are using one-to-one chat users only then you can use connection id as well which means all messages broadcasted will have both sender and reciever (by deafault) connection ID and you only need to pickup the window with connection id handle and update its list of messages or whatever.
The simplest way to do this is to replace the id attributes with class attributes.
<div id="chat-outline">
...
</div>
becomes
<div class="chat-outline">
...
</div>
And update your CSS appropriately.
.chat-outline
{
background-color: gray;
....
}
Then use a text/template tag to make it available to jQuery.
<script type="text/template" id="chat-template">
<div class="chat-outline">
...
</div>
</script>
Note that because browsers ignore script types they don't recognise, this will be ignored by the html rendering engine, but as it has an id, it will be visible to jQuery, and can be accessed thus:
<div id="container">
</div>
<script type="text/javascript">
$(function() {
var chatTemplate = $('#chat-template').html();
$('#container').append(chatTemplate); // First instance
$('#container').append(chatTemplate); // Second instance
$('#container').append(chatTemplate); // Third instance
});
</script>
Of course, if your code needs an id attribute as a handle for a chat instance, you can create a function that creates the chat-instance html given an id. In this case I'll use underscore to provide random-id, template, and iteration functions, but it is easy to use another library, or write your own.
<div id="container">
</div>
<script type="text/template" id="chat-template">
<div class="chat-outline" id="<%= id %>">
...
</div>
</script>
<script type="text/javascript">
var createChatInstance(idstring) {
return _.template($('#chat-template').html(), { id: idstring });
}
$(function() {
var chatTemplate = $('#chat-template').html();
// Create an array of 3 unique ids by which chat instances will be accessed.
var chatIds = [_.uniqueId('chat-outline'),
_.uniqueId('chat-outline'),
_.uniqueId('chat-outline')];
_.each(chatIds, function(chatId) {
$('#container').append(createChatInstance(chatId));
});
// You now have an array of 3 unique ids matching 3 divs.
// You can access individual sub-divs via descendent class matching from the id
// thus: $('#' + chatIds[n] + ' .chat-message').keyup(...code handling event...);
});
</script>
At this point, if you want to take the architecture further, you really do need to consider investigating something like backbone.js.
Hope this helps.
Example code
var jqxhr=$.getJSON("http://search.twitter.com/search.json?callback=?",{q:query},
function(data) {
... question.
});
Question
Now i need to create for each tweet result something like this (for example...)
<article class="tweet">
<header>
<img class ="tweet_img"src="data.profile_image_url"/>
</header>
<p class="tweet-text">data.text</p>
</article>
Well, i know several ways to append each result to the document:
Creating a big HTML string and add the data from JSONP and append this to some container.
Create a p element, a header element... work with them and after that append a final Element to some container.
Now the question is: with your experience what is the correct way to do this?
I mean the correct way using good principles.
Please dont ask about the html, it's dumb example.
Thanks.
Well, best practices will tell you not to use the innerHTML property of a DOM element, which is what you'd be doing with option 1. But unless you are concerned about immediately operating on the code with Javascript, attaching events, or security concerns around tag injection (I don't know how much this is an issue anymore) then creating an HTML string and inserting it using innerHTML is going to be a lot quicker and easier to update.
There are several valid approaches that each have their own advantages...
The technique of just generating the HTML as a string in your java code and adding it with .innerHTML is known to be one of the fastest performing approaches...but it provides very little validation of your HTML.
Alternatively, you can build the HTML using DOM methods directly, creating tags and appending them to build the structure. This is generally safer in that you have more validation going on, but the DOM methods are extremely wordy, which makes them a bit painful to type...and the code is even more verbose as you have to add attributes one at a time as well.
My personal preference, especially since you're already using JQuery, would be to build the tags and text nodes using JQuery, and put them together using JQuery, which allows you to do so in bite-sized, more human-verifiable units, without becoming overly verbose.
This also has the advantage that JQuery's methods of producing new tags give you additional support for older browsers that did not adhere to DOM standards. Hopefully you don't actually have to care whether your page works for those older browsers, but more compatibility never hurts either.
In that approach, you'd write something like the following:
var article = $('<article class="tweet"></article>');
var header = $('<header></header>');
var image = $('<img class="tweet_img" src="' + data.profile_image_url + '"></img>');
var tweet = $('<p class="tweet-text">' + data.text + '</p>');
header.append(image);
article.append(header, tweet);
$("#id_of_content_area_to_add_the_tweet_to").append(article);
The cleanest way I know how is to use a template system like Mustache, instead of "HTML in JS"
var template = html_string, //HTML from a string or from AJAX
data = {...data...}, //structured data
html = $(Mustache.render(template,data)); //wrap in jQuery to operate
html.appendTo(somewhere_in_DOM);
If you want to attach some event handlers to the elements then you should generate them separately.
But if you don't want to attach any event handler then i will recommend first method
$("body").append('<article class="tweet"><header><img class ="tweet_img" src="'+data.profile_image_url+'"/></header><p class="tweet-text">'+data.text+'</p></article>')
I will recommend you to use some Template engine like Handlebars.js Which is the right solution for your problem.
Which is having many more options which has many more conditional options which can be useful in feature. Just visit the above link you will have some idea.
In JSF, what would be the "right" and "clean" way to integrate JavaScript i.e. into a composite-compenent? I am a fan of Unobtrusive JavaScript, and separating HTML from JS from CSS. What would be a good way to have as little quirks as possible? This is what I like the best so far:
<composite:interface>
// ...
</composite:interface>
<composite:implementation>
// ...
<script> initSomething('#{cc.clientId}'); </script>
</composite:implementation>
What I don't like is, to use language A to generate language B. Basically the same goes for event handlers and stuff. My favorite would be to attach those handlers via <insert favorite DOM JavaScript library here>. Is this possible? How do you do this kind of integration?
I'd say that what you've there is the best you can get, provided that you're absolutely positive that the HTML element's nature is so unique that you absolutely need to select it by an ID, every time again.
If the HTML representation is not that unique (I can imagine that a Facelets template or include file might contain application-wide unique HTML elements like header, menu, footer, etc, but a composite component which can be reused multiple times in a single view? I can't for life imagine that), then you could also consider using an unique classname and hook initialization on it.
E.g. /resources/composites/yourComposite.xhtml
<cc:implementation>
<h:outputScript library="composites" name="yourComposite.js" target="head" />
<div id="#{cc.clientId}" class="your-composite">
...
</div>
</cc:implementation>
with in the /resources/composites/yourComposite.js (assuming that you're using jQuery)
var $yourComposites = $(".your-composite");
// ...
You can if necessary extract the autogenerated HTML element ID for each of them in a jQuery.each():
$yourComposites.each(function(index, yourComposite) {
var id = yourComposite.id;
// ...
});
I'm writing an application with some client-side JS that I use to update the DOM reasonably often.
The thing is that doing something like:
$('#id').html('<div class="' + class + '">' + content + '</div>');
multiple times and leaving HTML lying randomly round your JavaScript isn't very pretty and difficult to maintain.
Is there a JavaScript equivalent (or alternate solution) to the way Lithium handles this in it's view helpers.
See:
http://li3.me/docs/lithium/template/Helper::_render()
http://li3.me/docs/lithium/util/String::insert()
For examples.
Basically in the PHP version you would make an associate array of common strings and a simple method to replace to replace certain marked parts of those strings with variables of the same name.
Another silly example (psuedo-code:)
var strings = {
'div': '<div {:attr}>{:content}</div>'
};
console.log(render('div', {id: 'newElem'}, 'Hello, World!'));
// Output: <div id="newElem">Hello, World!</div>
If you have any better suggestions on how you handle storing HTML in your JavaScript and keep it from going all over the place then I'd very much like to hear it.
Yes, use jQuery templates or Underscore templates (my favorite) or any other JS templating engine out there.
Also, check this question for a discussion on performance of templating engines: Improve jQuery template performance
If you don't want to use a templating system, and have many html snippets that must be created many times, then you can use another technique :
Create a div in your main html file, give it a specific css class or id
Using css, make this div invisible
Inside is div, create the "template" divs, each one will contain a "snippet", each one with proper class or id
Using js (jquery, whatever) when you need it, clone the "template" div, append it where you need it, and then customize it.
Using jquery this is very easy, and your template "divs" are asy accessible to any html designer.
I'm on a mobile device now, and posting code snippets is a bit difficult, but let me know if want some examples.
jQuery encourages you to dynamically construct your DOM nodes instead of doing string concatenation:
$("#id").html(
$("<div />").addClass(class).text(content))
In general, you can use the jQuery attribute methods to construct such nodes, and many of these methods take mappings as you say you like. For example:
$("#id").append(
$("<div />")
.attr({id: "newElem"})
.css({width: "100%", color: "red"}))
I've been using JSON to handle AJAX functionality in my rails applications ever since I heard about it, because using RJS/rendering HTML "felt" wrong because it violated MVC. The first AJAX-heavy project I worked on ended up with 20-30 controller actions tied directly to specific UI-behaviors and my view code spread over controller actions, partials and rjs files. Using JSON allows you to keep view specific code in the view, and only talk to view agnostic/RESTful controller actions via AJAX to get needed data.
The one headache I've found from using pure JSON is that you have to 'render' HTML via JS, which in the case of AJAX that has to update DOM-heavy elements, can be a real pain. I end up with long string building code like
// ...ajax
success: function(records){
$(records).each(function(record){
var html = ('<div id="blah">' + record.attr +
etc +
')
})
}
where etc is 10-15 lines of dynamically constructing HTML based on record data. Besides of the annoyance, a more serious draw back to this approach is the duplication of the HTML structure (in the template and in the JS).* Is there a better practice for this approach?
(My motivation for finally reaching out is I am now tasked with updating HTML so complex it required two nested loops of Ruby code to render in the first place. Duplicating that in Javascript seems insane.)
One thing I've considered is loading static partial files directly from the file system, but this seems a bit much.
I like the idea of templating. In my experience it can really clean up that messy string manipulation!
There are many solutions, for example, check out John Resig's (creator of jQuery):
http://ejohn.org/blog/javascript-micro-templating/
I would go with creating an HTML structure that contains placeholders for the elements you'll need to update via AJAX. How much structure it applies will depend on what you're updating; if you know the number of elements you'll have ahead of time, it would be something to the effect of
<div id="article1">
<div id="article1Headline"></div>
<div id="article1Copy"></div>
<div id="article1AuthorInfo"></div>
</div>
<div id="article2">
<div id="article2Headline"></div>
<div id="article2Copy"></div>
<div id="article2AuthorInfo"></div>
</div>
You then write code that references the id of each element directly, and inserts into the .innerHTML property (or whatever syntactically more sugary way jquery has of doing same thing). IMHO, it's not really so terrible to have to assign the contents of each element, the part that you don't want to have to sprinkle through your AJAX functions is the HTML structure itself; in your app the content is volatile anyway.
However, it looks like you might have a list of an unknown number of elements, in that case it may be that you'd need to just put in a placeholder:
<div id="articleList"></div>
In that case I don't really see a way to avoid building the HTML structure in the javascript calls, but a reasonable amount of decomposition of your javascript should help that:
function addArticle( headline, copy, authorInfo, i ){
createDiv( "article" + i + "Headline", headline );
createDiv( "article" + i + "Copy", copy);
createDiv( "article" + i + "AuthorInfo", authorInfo );
}
(not working code of course, but you get the idea,)
You could use the load function in jQuery;
This loads the content of a page into a div like this:
$('#content').load("content/" + this.href.split('#')[1] + ".html", '', checkResponse);
Just make a dynamic view and you are good to go...
Just happened to find exactly what I was looking for: Jaml