I understand the basic idea of javascript constructor like
function Person(name){
this.name = name
}
Person.prototype.sayhi = function(){
return this.name+' says hi !!! '
}
var bob = new Person('bob')
bob.name // bob
bob.sayhi // bob says hi !!!
but lets say if i want to create a Album in real webapp, the server send an array of json data
like:[{'id':1,'album_name':'test','user':'user_id'}]
, each array item should be an album, now i want to construct this album as div element using this array item,how can i do that?
the reason why i want this is that if i can construct an album as real div element,then i can do this
Album.prototype.open = function(){
//some action
}
album = new Album(jdata)
album.click(function(){
this.open()
})
is this possible , how to define this constructor , i think this may have something to do with constructor return value which really confuse me!!!
I understand the basic idea of javascript constructor like
function Person(name){
this.name = name
}
Person.prototype.sayhi = function(){
return this.name+' says hi !!! '
}
var bob = new Person('bob')
bob.name // bob
bob.sayhi // bob says hi !!!
but lets say if i want to create a Album in real webapp, the server send an array of json data
like:[{'id':1,'album_name':'test','user':'user_id'}]
, each array item should be an album, now i want to construct this album as div element using this array item,how can i do that?
the reason why i want this is that if i can construct an album as real div element,then i can do this
Album.prototype.open = function(){
//some action
}
album = new Album(jdata)
album.click(function(){
this.open()
})
is this possible , how to define this constructor , i think this may have something to do with constructor return value which really confuse me!!!
Share Improve this question asked Mar 21, 2013 at 8:04 paynestrikepaynestrike 4,66814 gold badges49 silver badges71 bronze badges 4-
There is actually a
Person.constructor = function(){}
available. – Jared Farrish Commented Mar 21, 2013 at 8:05 - 1 @JaredFarrish accessing or changing a constructor of a constructor is not particularly useful. – John Dvorak Commented Mar 21, 2013 at 8:08
- Which constructor of a constructor are you referring? – Jared Farrish Commented Mar 21, 2013 at 8:09
- While in some browsers DOM elements implement prototype inheritance, some browsers do not implement any kind of inheritance. It isn't required by any specification so you shouldn't expect them to. See What’s wrong with extending the DOM. – RobG Commented Mar 21, 2013 at 9:38
3 Answers
Reset to default 3You can do the following:
var i, data, Albom, albom;
Albom = function Albom(data) {
var i,
div = document.createElement('div');
for(i in data) {
div.setAttribute('data-'+i, data[i]);
}
div.innerHTML = data.album_name;
for(i in this) {
if(typeof this[i] === 'function') {
div[i] = this[i].bind(div);
} else {
div[i] = this[i];
}
}
return div;
};
Albom.prototype.open = function open() {
alert(this.getAttribute('data-id'));
};
data = [
{'id':1,'album_name':'test1','user':'user_id1'},
{'id':2,'album_name':'test2','user':'user_id2'}
];
for(i in data) {
albom = new Albom(data[i]);
document.body.appendChild(albom);
}
Now new Albom(data)
will produce new DOM element that has attributes from provided data
object and will have all prototype properties and functions inside created element that will be executed in scope of this DOM element (so you can refer to this
inside that methods).
For example you will be able to call albom.open()
and an alert with text 2
will pop-up.
Working example you can see at: http://jsbin./isepay/10/edit
Create some template files with classes matching the object keys, and then cycle through the keys and populate the template file. For example:
function Album (album) {
this.template = $('#template').clone().removeAttr('id');
this.album = album;
}
Album.prototype.html = function () {
var i, val;
for (i in this.album) {
if (!this.album.hasOwnProperty(i)) {
continue;
}
val = this.album[i];
this.template.find("." + i).html(val);
}
console.log(this.template);
return this.template;
}
var foo = new Album({
title: 'Cheap Thrills',
artist: 'Frank Zappa',
genre: 'Rock and Roll'
});
$('#main').html(foo.html());
that's a one-size-fits-all attempt, though it won't really fit all needs. You can set conditions or what-have-you for cases where this solution doesn't fit your needs. For example, if the data is an image url, setting the innerHTML isn't very useful, so you would instead set the 'src' attribute, or create an img tag with an SRC attribute.
A template file might look like this:
<div class="album">
<div class="user"></div>
<span class="foo"></span>
<textarea class="bar"></textarea>
</div>
Here's a quick fiddle: http://jsfiddle/bxw7Z/
If you don't like the idea of using classes, try data-attributes instead.
I think your approach is wrong. You should render the response JSON object using any client side templating engine (For e.g. Handlebars.JS).
Then define constructor & prototype methods like
function album(container){
this.container=container
}
album.prototype.open=function() {
container.show();
}
album.prototype.renderHTML=function(jdata) {
//This is handlebar.js code
template=$('#albumTemplate').text();
piledTemplate=Handlebars.pile(template);
renderedTemplate=piledTemplate(jdata);
container.html(renderedTemplate);
}
Once this is done, you have album class ready & can start using it like this
var container=document.getElementById('myalbum001'),
album=new album(container);
container.on('click',function(e){
album.render(jdata); //You can get jdata by making AJAX call before this line
album.open()
}
I will remend you to quickly take a glance at Handlebar.js