-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrenderable.js
More file actions
166 lines (147 loc) · 4.68 KB
/
renderable.js
File metadata and controls
166 lines (147 loc) · 4.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/**
* @file Provides a simple way to render a js object of a particular format into a DOMElement
* @author jec006
*/
// create a closure so we don't muck up the global environment with functions ect.
(function () {
// ------ define some private helper methods ------ //
/**
* takes an item and returns either its classname or its type if it has no class
* @param item - any variable/item
*/
var classname = function (item) {
var rtype = typeof item;
if(typeof(item.constructor.name) != 'undefined'){
rtype = item.constructor.name;
}
return rtype;
}
var parseContent = function(content){
switch (classname(content)) {
case 'String' :
case 'object' : //this is for older versions of IE that like to hide HTMLElements constructors
case 'Array' :
return content;
break;
case 'Object' :
return Renderable.create(content);
}
}
/**
* Define a Renderable Class
* @param tag - the tagName, e.g. div
* @param attrs - the attributes for the item, must be the js version i.e. className not class
* @param content - the content of the created element, either text, a renderable Object, a Renderable
* or an array of renderable Objects or Renderables
*/
var Renderable = function(tag, attrs, content){
this.tag = tag;
this.attrs = attrs;
this.content = parseContent(content);
}
/**
* Turn a renderable into a DOMElement
*/
Renderable.prototype.render = function(){
var el;
// handle arrays separately as we will need to loop through and append the elements after the fact
var localContent = false;
if(classname(this.content) == 'Array'){
//make sure we copy it to local
localContent = this.content.slice(0);
this.content = '';
}
switch (this.tag) {
case 'table' :
//TODO: Implement this
break;
case 'list' :
//TODO: Implement this
break;
case 'checkboxes' :
//TODO: Implement this
break;
default:
el = mCreate.createElement(this.tag, this.content||'', this.attrs||{});
break;
}
// add in the items from content if content was an array
if(localContent){
for(var index in localContent){
var renderable = localContent[index];
if(classname(renderable) == 'Renderable'){
el.appendChild(renderable.render());
} else {
//try to parse the item, otherwise just try to append it
var parsed = Renderable.create(renderable);
if(parsed) {
el.appendChild(parsed.render());
} else {
try {
el.appendChild(renderable);
} catch (err) {
this.log(err.description);
}
}
}
}
}
//return the rendered DOMElement
return el;
};
/**
* Attach a renderable to a dom element and return the attached element
*/
Renderable.prototype.attach = function(el){
if(typeof(el.appendChild) == 'function'){
var child = this.render();
el.appendChild(child);
return child;
} else {
this.log('Failed to attach child - invalid parameter el.', el);
return null;
}
}
/**
* Method for logging messages to console
* arguments is passed unaltered to the console.log function should it exist
*
* You can turn off logging by setting Renderable.prototype.hideDebugging = true
*/
Renderable.prototype.log = function(){
if(!this.hideDebugging && typeof(window.console) != 'undefined' && typeof(window.console.log) == 'function'){
console.log.apply(console, arguments);
}
}
/**
* Creates a Renderable from a renderable object
* @param renderable - a renderable object
* @return a Renderable or false on failure
*/
Renderable.create = function(renderable) {
switch (classname(renderable)) {
case 'Array' :
//at this level, we can't create a DOMElement without a container for the child elements
var obj = {
'tag' : 'div',
'attributes' : {'className' : 'renderable-container'},
'content' : renderable
};
return Renderable.create(obj);
break;
case 'Renderable' :
return renderable;
break;
case 'Object' :
if(renderable.tag) {
return new Renderable(renderable.tag, renderable.attributes||[], renderable.content||'');
}
break;
}
//if we made it down here we couldn't create it so return an empty string to prevent breakage
Renderable.prototype.log('Failure creating renderable', renderable);
return '';
}
//declare this globally
window.Renderable = Renderable;
})();