/** * @file repeater.js * @version 20170907 ms * @type JS * @use menu.js * GUI-Komponente zur Listendarstellung/Wiederholung von Steuerelementefeldern */ /** * @class KRepeater * @constructor * @param o * @param {object} opts: - none defined at this time - * @param {KRepeaterBridge} bridge */ function KRepeater(o, opts, bridge){ this.res = { Copy: {de:"Kopieren", en:"Copy"}, Cut: {de:"Ausschneiden", en:"Cut"}, Paste: {de:"Einfügen", en:"Paste"}, }; this.Lang = "de"; this.DefaultLang = "en"; this.outerO = o; this.o = document.createElement("div"); this.o.style.position = "relative"; o.appendChild(this.o); var m = this; this.o.onclick = this.outerO.onclick = function(e) { if(e.button) m.MenuOpen(e); }; this.o.oncontextmenu = this.outerO.oncontextmenu = function(e) { m.MenuOpen(e); }; this.opts=opts || {}; this.bridge=bridge; //this.bridge=new KRepeaterBridge(); this.Clear(); if(this.scroll) this.Resize(); }; KRepeater.prototype.s=function(id){ var r=this.res[id]; if(r && Object.keys(r).length) return r[this.Lang] || r[this.DefaultLang] || r[Object.keys(r)[0]]; else return "["+id+"]"; }; KRepeater.prototype.Clear=function(){ this.recs=[]; this.MenuClose(); if(this.bridge) this.bridge.ClearClipboard(this); this.Redraw(); }; /** * @fn Add * @memberof KRepeater * @params type,id,icon,values,selected,template */ KRepeater.prototype.Add=function(type,id,icon,values,selected,template){ this.Insert(-1,type,id,icon,values,selected,template); }; /** * @fn Insert * @memberof KRepeater * @params index,type,id,icon,values,selected,template */ KRepeater.prototype.Insert=function(index,type,id,icon,values,selected,template,movable,copyable,noneselectable){ var item={type:type,id:id,icon:icon,values:values,selected:selected,template:template,movable:movable,copyable:copyable,noneselectable:noneselectable}; if(index>-1) this.recs.splice(index,0,item); else this.recs.push(item); this.Redraw(); }; /** * @fn AddNew * @memberof KRepeater * @params type,caption */ KRepeater.prototype.AddNew=function(type,caption){ this.recs.push({new:true,id:0,type:type,values:{caption:caption}}); this.Redraw(); }; /** * @fn InsertNew * @memberof KRepeater * @params index,type,caption */ KRepeater.prototype.InsertNew=function(index,type,caption){ this.recs.splice(index,0,{new:true,id:0,type:type,values:{caption:caption}}); this.Redraw(); }; /** * @fn Count * @memberof KRepeater * @return {int} */ KRepeater.prototype.Count=function(){ return this.recs.length; }; /** * @fn Remove * @memberof KRepeater * @param {int} index */ KRepeater.prototype.Remove=function(index){ if(this.recs[index].o) this.o.removeChild(this.recs[index].o); this.recs.splice(index,1); this.Redraw(); }; /** * @fn RemoveById * @memberof KRepeater * @param */ KRepeater.prototype.RemoveById=function(type,id){ var i=this.FindItem(type,id); if(i>-1) this.Remove(i); }; /** * @fn RemoveByType * @memberof KRepeater * @param type */ KRepeater.prototype.RemoveByType=function(type){ for(var a=this.recs.length-1;a>=0;a--) if(this.recs[a].type==type) this.Remove(a); }; /** * @fn ResetItem * @memberof KRepeater * @params type,id,icon,values,template */ KRepeater.prototype.ResetItem=function(type,id,icon,values,template){ var i=this.FindItem(type,id); if(i==-1) return; this.recs[i].icon=icon; this.recs[i].values=values; this.recs[i].template=template; delete this.recs[i].loaded; this.Redraw(); }; /** * @fn FindItem * @memberof KRepeater * @param {string} type * @param {int} id * @return {int} index */ KRepeater.prototype.FindItem=function(type, id){ for(var a=0; a < this.recs.length; a++) if(this.recs[a].id == id && this.recs[a].type == type) return a; return -1; }; /** * @fn Redraw * @memberof KRepeater * Private method. */ KRepeater.prototype.Redraw=function(){ if(scroll) { var numRows = Math.ceil(this.recs.length / this.itemsPerRow); if(this.horizontal) this.o.style.width = (numRows * this.itemWidth) + "px"; else this.o.style.height = (numRows * this.itemHeight) + "px"; } for(var a = 0; a < this.recs.length; a++) { if(this.recs[a].o) { this.PlaceItem(a); this.recs[a].o.style.opacity = this.bridge && this.bridge.clipboardModeCut && this.bridge.clipboard.indexOf(this.recs[a]) > -1? "0.4" : ""; } } this.LoadVisibleItems(); }; /** * @fn LoadVisibleItems * @memberof KRepeater */ KRepeater.prototype.LoadVisibleItems=function(){ if(this.horizontal){ var itemVisibleFrom=Math.floor(this.outerO.scrollLeft/this.itemWidth)*this.itemsPerRow; var itemVisibleTo=Math.ceil((this.outerO.scrollLeft+this.outerO.offsetWidth)/this.itemWidth)*this.itemsPerRow-1; }else{ var itemVisibleFrom=Math.floor(this.outerO.scrollTop/this.itemHeight)*this.itemsPerRow; var itemVisibleTo=Math.ceil((this.outerO.scrollTop+this.outerO.offsetHeight)/this.itemHeight)*this.itemsPerRow-1; } if(itemVisibleTo>=this.recs.length) itemVisibleTo=this.recs.length-1; for(var a=itemVisibleFrom;a<=itemVisibleTo;a++) if(!this.recs[a].loaded) this.LoadItem(a); }; /** * @fn PlaceItem * @memberof KRepeater * @param */ KRepeater.prototype.PlaceItem=function(i){ var rec=this.recs[i]; var row=i/this.itemsPerRow; var col=(row-Math.floor(row))*this.itemsPerRow; row=Math.floor(row); if(this.horizontal){ this.itemHeight=this.o.clientHeight/this.itemsPerRow; rec.o.style.left=(row*this.itemWidth)+"px"; rec.o.style.top=(col*this.itemHeight)+"px"; }else{ this.itemWidth=this.o.clientWidth/this.itemsPerRow; rec.o.style.left=(col*this.itemWidth)+"px"; rec.o.style.top=(row*this.itemHeight)+"px"; } rec.o.style.width=(this.itemWidth-(this.itemBorderWidth+this.itemPadding)*2)+"px"; rec.o.style.height=(this.itemHeight-(this.itemBorderWidth+this.itemPadding)*2)+"px"; }; /** * @fn GetColor * @memberof KRepeater * @param * @return */ KRepeater.prototype.GetColor=function(colors,type){ if(typeof colors==="string") return colors; else return colors[type]; }; /** * @fn GetClass * @memberof KRepeater * @params classes,type * @return */ KRepeater.prototype.GetClass=function(classes,type){ if(typeof classes==="string") return classes; else return classes[type]; }; /** * @fn SetStyle * @memberof KRepeater * @params o,isSelected,isNew,type */ KRepeater.prototype.SetStyle=function(o,isSelected,isNew,type){ // If classes are defined then set it otherwise set colors: if(this.selectedClass) o.className=this.GetClass(isSelected?(isNew?this.selectedNewClass:this.selectedClass):(isNew?this.unselectedNewClass:this.unselectedClass),type); else o.style.background=this.GetColor(isSelected?(isNew?this.selectedColorNew:this.selectedColor):(isNew?this.unselectedColorNew:this.unselectedColor),type); }; /** * @fn LoadItem(i) * @memberof KRepeater * @param index */ KRepeater.prototype.LoadItem=function(index){ var rec=this.recs[index]; rec.loaded=true; var o=document.createElement("div"); this.SetStyle(o,rec.selected,rec.new,rec.type); o.style.position="absolute"; o.style.margin=this.itemPadding+"px"; o.style.border=this.itemBorderWidth+"px "+(rec.new?"dashed":"solid")+" "+this.itemBorderColor; o.style.overflow="hidden"; this.o.appendChild(o); if(rec.o) this.o.removeChild(rec.o); rec.o=o; this.PlaceItem(index); var t=rec.template?rec.template:(rec.new?this.NewTemplate:this.ItemTemplate); t=t.replace("{icon}",rec.icon?rec.icon:""); if(typeof rec.values=="object") for(var key in rec.values) t=t.replace(new RegExp("{"+key+"}",'g'),rec.values[key]==null?'':rec.values[key]); o.appendChild(KRepeater.Html2Object(t)); var m = this; o.onclick = function(e) { if(e.button) { m.MenuOpen(e, rec); } else { if(rec.new) m.NewItemClicked(e, rec); else m.ItemClicked(e, rec); } }; o.oncontextmenu = function(e) { m.MenuOpen(e, rec); }; this.AfterLoadItem(o, rec); }; /** * @fn AfterLoad o,rec * @memberof KRepeater * @params o,rec * Public method. */ KRepeater.prototype.AfterLoadItem=function(o,rec){ // to be overwritten }; /** * @fn * @memberof KRepeater */ KRepeater.prototype.Scroll=function(){ this.LoadVisibleItems(); }; /** * @fn Select * @memberof KRepeater * @param {int} index * @param {bool} add: keep selected items selected */ KRepeater.prototype.Select=function(index, add){ if(!this.multiSelect || !add) for(var a = 0; a < this.recs.length; a++) if(this.recs[a].selected) this.UnSelect(a); if(index < 0) return; var rec = this.recs[index]; rec.selected = true; if(rec.o) this.SetStyle(rec.o, true, rec.new, rec.type); }; /** * @fn UnSelect * @memberof KRepeater * @param {int} index */ KRepeater.prototype.UnSelect=function(index){ var rec = this.recs[index]; rec.selected = false; if(rec.o) this.SetStyle(rec.o, false, rec.new, rec.type); }; /** * @fn UnSelectAll * @memberof KRepeater */ KRepeater.prototype.UnSelectAll=function(){ this.Select(-1); }; /** * @fn ItemClicked * @memberof KRepeater * @param {HTMLEvent} e * @param {object} rec */ KRepeater.prototype.ItemClicked=function(e, rec){ var i = this.FindItem(rec.type, rec.id); if(i == -1) return; if(this.multiSelect && rec.selected && e.ctrlKey) { this.UnSelect(i); } else { if (!rec.noneselectable) this.Select(i, e.ctrlKey); this.Clicked(rec.type, rec.id); } }; /** * @fn NewItemClicked * @memberof KRepeater * @param {HTMLEvent} e * @param {object} rec */ KRepeater.prototype.NewItemClicked=function(e,rec){ var i=this.FindItem(rec.type,0); if (!rec.noneselectable) this.Select(i); this.NewClicked(rec.type); }; /** * @fn Clicked * @memberof KRepeater * @param {string} type * @param {int} id * Public method. */ KRepeater.prototype.Clicked=function(type,id){ // to be overwritten }; /** * @fn NewClicked * @memberof KRepeater * @param {string} type * Public method. */ KRepeater.prototype.NewClicked=function(type){ // to be overwritten }; /** * @fn MenuOpen * @memberof KRepeater * @param {HTMLEvent} e * @param {object:KRepeater record} item * Private method. */ KRepeater.prototype.MenuOpen=function(e, item){ if(!this.bridge) return; var index = item? this.FindItem(item.type, item.id) : -1; //if(index == -1 || !this.recs[index].id) this.UnSelectAll(); else if(!this.recs[index].selected) this.Select(index); if(index != -1 && this.recs[index].id && !this.recs[index].selected) this.ItemClicked(e, item); //this.Select(index); this.menu = new KMenu(this); var movable = [], copyable = []; for(var a = 0; a < this.recs.length; a++) { if(this.recs[a].selected) { if(this.recs[a].movable) movable.push(this.recs[a]); if(this.recs[a].copyable) copyable.push(this.recs[a]); } } if(copyable.length) this.menu.Insert(this.s("Copy"),"",this,"Copy",copyable); if(movable.length) this.menu.Insert(this.s("Cut"),"",this,"Cut",movable); if(this.bridge.clipboard.length && this!=this.bridge.clipboardClient && this.allowPaste(this.bridge.clipboard)) this.menu.Insert(this.s("Paste"),"",this,"Paste"); if(this.menu.Count()) this.menu.Pop(e.clientX+3,e.clientY+3); else this.menu=null; e.stopPropagation();e.preventDefault(); }; /** * @fn allowPaste * @memberof KRepeater * @param {array:KRepeater record} items * Public method. */ KRepeater.prototype.allowPaste=function(items){ // can be overwritten; must return true to show "Paste" option in context menu return false; }; /** * @fn MenuClose * @memberof KRepeater * Private method. */ KRepeater.prototype.MenuClose=function(){ if(this.menu) this.menu.Close(); }; /** * @fn MenuClosed * @memberof KRepeater * Required callback method of KMenu. */ KRepeater.prototype.MenuClosed=function(){ this.menu=null; }; /** * @fn Copy * @memberof KRepeater * @param {array:KRepeater record} items * Private method. */ KRepeater.prototype.Copy=function(items){ this.bridge.Copy(this,items); }; /** * @fn Cut * @memberof KRepeater * @param {array:KRepeater record} items * Private method. */ KRepeater.prototype.Cut=function(items){ this.bridge.Cut(this,items); }; /** * @fn Paste * @memberof KRepeater * Private method. */ KRepeater.prototype.Paste=function(){ if(!this.bridge) return; for(var a=0; a
{caption}"; /** * @var {string} NewTemplate */ KRepeater.prototype.NewTemplate="
+
{caption}
"; /** * @class KRepeaterBridge */ function KRepeaterBridge(){ this.clipboardClient=null; this.clipboard=[]; this.clipboardModeCut=false; /** * @fn Copy * @memberof KRepeaterBridge * @param {KRepeater} client * @param {array:KRepeater record} items */ this.Copy=function(client,items){ this.ClearClipboard(client); this.clipboardClient=client; this.clipboard=items; this.clipboardModeCut=false; client.Redraw(); }; /** * @fn Cut * @memberof KRepeaterBridge * @param {KRepeater} client * @param {array:KRepeater record} items */ this.Cut=function(client,items){ this.ClearClipboard(client); this.clipboardClient=client; this.clipboard=items; this.clipboardModeCut=true; client.Redraw(); }; /** * @fn ClearClipboard * @memberof KRepeaterBridge * @param {KRepeater} client */ this.ClearClipboard=function(client){ this.clipboard=[]; if(this.clipboardClient && this.clipboardClient!=client) this.clipboardClient.Redraw(); }; /** * @fn ReloadSourceClient * @memberof KRepeaterBridge * @param {KRepeater} client */ this.ReloadSourceClient=function(client){ if(this.clipboardClient && this.clipboardClient!=client) this.clipboardClient.Load(); }; };