RenderStack¶
-
class
webix.
RenderStack
()¶ Renderstack mixin
References¶
- helpers
assert()
,assert_error()
,bind()
,clone()
,extend()
,log()
,template()
,toFunctor()
,type()
.
External references¶
Code¶
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 167 168 169 170 171 172 173 | webix.RenderStack={
$init:function(){
webix.assert(this.data,"RenderStack :: Component doesn't have DataStore");
webix.assert(webix.template,"webix.template :: webix.template is not accessible");
//used for temporary HTML elements
//automatically nulified during destruction
this._html = document.createElement("DIV");
this.data.attachEvent("onIdChange", webix.bind(this._render_change_id, this));
this.attachEvent("onItemClick", this._call_onclick);
//create copy of default type, and set it as active one
if (!this.types){
this.types = { "default" : this.type };
this.type.name = "default";
}
this.type = webix.clone(this.type);
},
customize:function(obj){
webix.type(this,obj);
},
item_setter:function(value){
return this.type_setter(value);
},
type_setter:function(value){
if(!this.types[value])
this.customize(value);
else {
this.type = webix.clone(this.types[value]);
if (this.type.css)
this._contentobj.className+=" "+this.type.css;
}
if (this.type.on_click)
webix.extend(this.on_click, this.type.on_click);
return value;
},
template_setter:function(value){
this.type.template=webix.template(value);
},
//convert single item to HTML text (templating)
_toHTML:function(obj){
var mark = this.data._marks[obj.id];
//check if related template exist
webix.assert((!obj.$template || this.type["template"+obj.$template]),"RenderStack :: Unknown template: "+obj.$template);
this.callEvent("onItemRender",[obj]);
return this.type.templateStart(obj,this.type, mark)+(obj.$template?this.type["template"+obj.$template]:this.type.template)(obj,this.type,mark)+this.type.templateEnd(obj, this.type,mark);
},
//convert item to HTML object (templating)
_toHTMLObject:function(obj){
this._html.innerHTML = this._toHTML(obj);
return this._html.firstChild;
},
_render_change_id:function(old, newid){
var obj = this.getItemNode(old);
if (obj) {
obj.setAttribute(this._id, newid);
this._htmlmap[newid] = this._htmlmap[old];
delete this._htmlmap[old];
}
},
//calls function that is set in onclick property
_call_onclick:function(){
if (this._settings.click){
var code = webix.toFunctor(this._settings.click, this.$scope);
if (code && code.call) code.apply(this,arguments);
}
},
//return html container by its ID
//can return undefined if container doesn't exists
getItemNode:function(search_id){
if (this._htmlmap)
return this._htmlmap[search_id];
//fill map if it doesn't created yet
this._htmlmap={};
var t = this._dataobj.childNodes;
for (var i=0; i < t.length; i++){
var id = t[i].getAttribute(this._id); //get item's
if (id)
this._htmlmap[id]=t[i];
}
//call locator again, when map is filled
return this.getItemNode(search_id);
},
//return id of item from html event
locate:function(e){ return webix.html.locate(e,this._id); },
/*change scrolling state of top level container, so related item will be in visible part*/
showItem:function(id){
var html = this.getItemNode(id);
if (html&&this.scrollTo){
var txmin = Math.abs(this._contentobj.offsetLeft-html.offsetLeft);
var txmax = txmin + html.offsetWidth;
var tymin = Math.abs(this._contentobj.offsetTop-html.offsetTop);
var tymax = tymin + html.offsetHeight;
var state = this.getScrollState();
var x = state.x;
if (x > txmin || x + this._content_width < txmax )
x = txmin;
var y = state.y;
if (y > tymin || y + this._content_height < tymax )
y = tymin - 5;
this.scrollTo(x,y);
if(this._setItemActive)
this._setItemActive(id);
}
},
//update view after data update
//method calls low-level rendering for related items
//when called without parameters - all view refreshed
render:function(id,data,type){
if (!this.isVisible(this._settings.id) || this.$blockRender)
return;
if (webix.debug_render)
webix.log("Render: "+this.name+"@"+this._settings.id+", mode:"+(type||"#")+", item:"+(id||"#"));
if (id){
var cont = this.getItemNode(id); //get html element of updated item
switch(type){
case "paint":
case "update":
//in case of update - replace existing html with updated one
if (!cont) return;
var t = this._htmlmap[id] = this._toHTMLObject(data);
webix.html.insertBefore(t, cont);
webix.html.remove(cont);
break;
case "delete":
//in case of delete - remove related html
if (!cont) return;
webix.html.remove(cont);
delete this._htmlmap[id];
break;
case "add":
//in case of add - put new html at necessary position
var t = this._htmlmap[id] = this._toHTMLObject(data);
webix.html.insertBefore(t, this.getItemNode(this.data.getNextId(id)), this._dataobj);
break;
case "move":
//moving without repainting the item
webix.html.insertBefore(this.getItemNode(id), this.getItemNode(this.data.getNextId(id)), this._dataobj);
break;
default:
webix.assert_error("Unknown render command: "+type);
break;
}
} else {
//full reset
if (this.callEvent("onBeforeRender",[this.data])){
/*if (this.getScrollState)
var scroll = this.getScrollState();*/
//getRange - returns all elements
(this._renderobj||this._dataobj).innerHTML = this.data.getRange().map(this._toHTML,this).join("");
this._htmlmap = null; //clear map, it will be filled at first getItemNode
this.callEvent("onAfterRender",[]);
var t = this._dataobj.offsetHeight;
/*if (this.getScrollState)
this.scrollTo(scroll.x, scroll.y);*/
}
}
}
};
|