/******************************************************************************
@owner: SVSi
@author: Arthur Johnson
@functions: Widget Class for widget objects
@Widget
*******************************************************************************/
var initDiagonal;
var initFontSize;

function getContentDiagonal(){
    var contentWidth = $("#content").width();
    var contentHeight = $("#content").height();
    return contentWidth * contentWidth + contentHeight * contentHeight;
}

//*************  WIDGET CLASS  ***************//
	function Widget(opts){
	
		if (undef(opts)) opts = {};
		
		if (undef(pb.widgetindex)) pb.widgetindex = 0;
		
	//**************************** CORE ******************************//
		if (opts.hasOwnProperty('core')){
			this.core = opts.core;
			if (undef(opts.copyid)) this.core.id = pb.uniqueId('Widget-'+(pb.widgetindex++));
			if (!undef(opts.type)) this.core.type = opts.type;
		}
		else {
		
			this.core = {};
			
			this.core.id = opts.hasOwnProperty('id') ? opts.id : pb.uniqueId('Widget-'+(pb.widgetindex++));
			this.core.set = opts.hasOwnProperty('set') ? opts.set : 'default';
			this.core.type = opts.hasOwnProperty('type') ? opts.type : 'default';
			this.core.scale = opts.hasOwnProperty('scale') ? opts.scale : 1;			
			this.core.scripts = opts.hasOwnProperty('scripts') ? opts.scripts : ['',''];
			this.core.conditional = opts.hasOwnProperty('conditional') ? opts.conditional : false;
			this.core.elementHTML = opts.hasOwnProperty('elementHTML') ? opts.elementHTML : '';
			this.core.className = opts.hasOwnProperty('className') ? opts.className : '';
			this.core.style = opts.hasOwnProperty('style') ? opts.style : '';	
			this.core.basewidth = opts.hasOwnProperty('basewidth') ? opts.basewidth : 80;
			this.core.baseheight = opts.hasOwnProperty('baseheight') ? opts.baseheight : 80;
			this.core.basetop = opts.hasOwnProperty('basetop') ? opts.basetop : 0;
			this.core.baseleft = opts.hasOwnProperty('baseleft') ? opts.baseleft : 0;			
			this.core.draggedoffsetx = opts.hasOwnProperty('draggedoffsetx') ? opts.draggedoffsetx : 0;
			this.core.draggedoffsety = opts.hasOwnProperty('draggedoffsety') ? opts.draggedoffsety : 0;			
			this.core.touchpanelkeys = opts.hasOwnProperty('touchpanelkeys') ? opts.touchpanelkeys : [];
			this.core.updating = opts.hasOwnProperty('updating') ? opts.updating : false;
			this.core.update = opts.hasOwnProperty('update') ? opts.update : noop;
			this.core.responsive = opts.hasOwnProperty('responsive') ? opts.responsive : false;
			this.core.keepaspect = opts.hasOwnProperty('keepaspect') ? opts.keepaspect : false;
			this.core.draggable = opts.hasOwnProperty('draggable') ? opts.draggable : false;
			this.core.zvalue = opts.hasOwnProperty('zvalue') ? opts.zvalue : 1;

		}
	
	//**************************** PANEL *****************************//
		this.panel = opts.hasOwnProperty('panel') ? opts.panel : false;
	
	//*************************** ELEMENT ****************************//
		this.element = document.createElement("div");	
		this.element.style.cssText += this.core.style;
		this.element.id = this.core.id;
		this.element.className = this.core.className;
		this.element.className += ' draggable clonable';
				
	//**************************** PARTS *****************************//
		this.parts = opts.hasOwnProperty('parts') ? opts.parts : [];
		
		for (var i=0; i<this.parts.length;i++){
			if (this.parts[i].element) this.element.appendChild(this.parts[i].element);
			this.parts[i].widget = this;
		}
	
	//**************************** INIT ******************************//
		//console.log('wcore', this.core.type);
		if (this.core.type !== 'default' && this.core.type !== 'user'){
			//this.core.set = this.core.type;
			this.core.type = 'user';
		}
		pb[this.core.type].widgets.push(this);
		
		this.init = opts.hasOwnProperty('init') ? opts.init : noop;
		this.update = opts.hasOwnProperty('update') ? opts.update : noop;
		this.ontopanel = opts.hasOwnProperty('ontopanel') ? opts.ontopanel : noop;
		this.hoverin = opts.hasOwnProperty('hoverin') ? opts.hoverin : noop;
		this.hoverout = opts.hasOwnProperty('hoverout') ? opts.hoverout : noop;
		this.resize = opts.hasOwnProperty('resize') ? opts.resize : noop;
		this.doubleclick = opts.hasOwnProperty('doubleclick') ? opts.doubleclick : noop;
		
		this.core.previouslocation = {top: this.element.style.top, left: this.element.style.left};
		
		if (!activepanel) this.element.title = this.element.id;
		else this.element.title = '';

		if (typeof this.init == 'function') this.init();
		
	}
	Widget.prototype = {
		_show: function(){
			$(this.element).show(); this.core.__hidden = false;
		},
		_hide: function(){
			$(this.element).hide(); this.core.__hidden = true;
		},
		show: function(){
			$(this.element).show();
		},
		hide: function(){
			$(this.element).hide();
		},
		fadein: function(time){
			$(this.element).stop().fadeIn(time*1000);
		},
		fadeIn: function(time){
			$(this.element).stop().fadeIn(time*1000);
		},
		fadeout: function(time){
			$(this.element).stop().fadeOut();
		},
		fadeOut: function(time){
			$(this.element).stop().fadeOut(time*1000);
		},
		animate: function(opts, time, ease, onComplete){
			$(this.element).stop().animate(opts, time*1000, ease, onComplete);
		},
		animate3d: function(opts){
		
			var from = opts.from;
			var to = opts.to;
			var ease = opts.ease;
			
			if (!from || !to) return;
			
			var nopts = {};
			nopts.object = this.element;
			nopts.time = (opts.time || 1.0);
			if (ease) nopts.ease = ease;
			nopts.props = from;
			nopts.to = to;
		
			tweencss(nopts);
			
		},
		setStyle: function(s){
			if (typeof s == 'string'){
				if (this.element) this.element.style.cssText = s;
				this.states[this.currentstate].style = s;
			}
			if (typeof s == 'object'){
				$(this.element).css(s);
			}
			window.onresize();
		},
		setOpacity: function(t){
			if (this.element) this.element.style.opacity = t;
		},
		setLeft: function(l){
			if (this.element) this.element.style.left = l + 'px';
			this.left = l;
		},
		setTop: function(t){
			if (this.element) this.element.style.top = t + 'px';
			this.left = t;
		},
		setPosition: function(l,t){
			if (this.element) this.element.style.left = l + 'px';
			if (this.element) this.element.style.top = t + 'px';
			this.left = l;
			this.top = t;
		},
		setZ: function(z){
			if (this.element) this.element.style.zIndex = z;
			this.core.zvalue = z;
		},
		setWidth: function(w){
			if (this.element) this.element.style.width = w + 'px';
			this.actualwidth = w;
		},
		setHeight: function(h){
			if (this.element) this.element.style.height = h + 'px';
			this.actualheight = h;
		},
		setSize: function(w, h){
			if (w !== null){
				if (this.element) this.element.style.width = w + 'px';
				this.actualwidth = w;
			}
			if (!undef(h) && h !== null){
				if (this.element) this.element.style.height = h + 'px';
				this.actualheight = h;
			}
			window.onresize();
		},
		setPositionCenter: function(x, y){
			if (x !== null){
				if (this.element) this.element.style.left = (x - $(this.element).outerWidth()/2) + 'px';
				this.left = parseFloat(this.element.style.left);
			}
			if (!undef(y) && y !== null){
				if (this.element) this.element.style.top = (y - $(this.element).outerHeight()/2) + 'px';
				this.top = parseFloat(this.element.style.top);
			}
		},
		addState: function(){
			
		},
		getPositionCenter: function(){
			var result = {};
			result.x = parseFloat(this.element.style.left) + ($(this.element).outerWidth()/2);
			result.y = parseFloat(this.element.style.top) + ($(this.element).outerHeight()/2);
			return result;
		},
		remove: function(opts){
			this.panel.removeChild(this);
		},
		scaleTo: function(s){
			this.scale = s;
			$(this.element).css('transform', 'scale('+s+','+s+')');
		},
		clone: function(opts){
		
			if (undef(opts)) opts = {};
			
			var extrastyle = opts.hasOwnProperty('extrastyle') ? opts.extrastyle : '';
			this.core.style = this.element.style.cssText + extrastyle;
			
			var newparts = [];
			for (var i=0; i<this.parts.length; i++){
				newparts.push(this.parts[i].clone());
			}
			
			var newcore = deepCopy(this.core);
			//if (!opts.copyid) newcore.id = pb.uniqueId('Widget-'+(pb.widgetindex++));
		
			var newwidget = new Widget({	
				core: newcore,
				parts: newparts
			});
			
			for (var property in this) {
				if (this.hasOwnProperty(property) && property != 'panel' &&
					property != 'core' && property != 'element' && property != 'parts' &&
					property != 'container' && property != 'library' && property != 'action'){
					//console.log('cloneprop: ', property);
					newwidget[property] = this[property];
				}
			}
			
			newwidget.element.style.cssText += this.element.style.cssText
				+ ' ' + extrastyle + ' background-size: 100% 100%; margin: 0px;';
			
			if (!undef(opts.library)) newwidget.library = opts.library;
			
			var oldwidgetid = this.core.id;			
			var newwidgetid = newwidget.core.id;
			
			if (newwidget.core.scripts){
				for (var i=0; i<newwidget.core.scripts.length; i++){
					newwidget.core.scripts[i] = 
						newwidget.core.scripts[i].replaceAll(oldwidgetid, newwidgetid);
				}
			}
			
			return newwidget;
			
		},
		clickEvent: {
			down: noop,
			up: noop
		},
		resize: function(){
			for (var k=0; k<this.parts.length; k++){
				if (this.parts[k].resize) this.parts[k].resize();
			}
		},
		click: function(){
			
			if (pb.currentpanel){
			
				if (this.panel){
				
					if (pb.shiftdown){
					
						if (this.element.className.indexOf('outlined') != -1){
							$('.outlined').removeClass('first');
							$(this.element).addClass('outlined');
							$(this.element).addClass('first');
						}
						else {
							if ($('.outlined').length == 0) $(this.element).addClass('first');
							$(this.element).addClass('outlined');
						}
						
					}
					else {
					
						if (this.element.className.indexOf('outlined') != -1){
							$('.outlined').removeClass('first');
							$(this.element).addClass('outlined');
							$(this.element).addClass('first');
						}
						else {
							$('.outlined').removeClass('outlined').removeClass('first');
							$(this.element).addClass('outlined');
							$($('.outlined')[0]).addClass('first');
						}
						
					}
					
					$('.outlinedjson').removeClass('outlinedjson');
					
					if ($('.outlined').exists()){
						var r = [];
						$('.outlined').each(function(){
							var type = false, set = false;
							var item = pb.getItem(this.id);
							if (item instanceof Button) type = 'button';
							if (item instanceof Widget){
								type = 'widget'; set = item.core.set;
							}
							r.push({id: this.id, type: type, set: set});
						});
						ng.selected = r;
					}
					else ng.selected = false;
				
				}
				else {				
					$('.libraryselected').removeClass('libraryselected');
					$(this.element).addClass('libraryselected');
				}
			
			}
		
			if (pb.project.textEditing){
			
				if (pb.project.textEditing.core.text)
					pb.project.textEditing.core.text = 
					$(pb.project.textEditing.textnode)[0].innerHTML;
				
				for (k in CKEDITOR.instances){
					var instance = CKEDITOR.instances[k];
					instance.destroy();
				}
				
				if (pb.project.textEditing.textnode) {
					$(pb.project.textEditing.textnode).attr('contenteditable', 'false');
					$(pb.project.textEditing.textnode).blur();
					$(pb.project.textEditing.textnode).addClass('item_child');
					allDescendantsAddClass(pb.project.textEditing.textnode, 'ck_edit');
					$(pb.project.textEditing.textnode).children().addClass( 'ck_edit' );
				}
				else {
					$(pb.project.textEditing.element).attr('contenteditable', 'false');
					$(pb.project.textEditing.element).blur();
					$(pb.project.textEditing.element).addClass('item_child');
					if (pb.project.textEditing.element) 
						allDescendantsAddClass(pb.project.textEditing.element, 'ck_edit');
					$(pb.project.textEditing.element).children().addClass( 'ck_edit' );
				}
				pb.project.textEditing = false;
				$(this.textnode).removeClass('selectable');
				
			}
			
		},
		clickup: noop,
		dragging: function(offx, offy){
		
			this.element.style.zIndex = 24000;
			this.element.style.position = 'absolute';

			var elebounds = this.element.getBoundingClientRect();
			var s = pb.currentpanel.core.scale;
			var doffsetx = -this.core.draggedoffsetx;
			var doffsety = -this.core.draggedoffsety;
			var oy = 0;
			var ox = 0;
			
			if (!this.panel){
				doffsetx = doffsetx*s;
				doffsety = doffsety*s;
			}

			this.element.style.left = ox + (doffsetx + pb.mouse.x) - ($(this.element).outerWidth()*(1-s)/2) + 'px';			
			this.element.style.top = oy + (doffsety + pb.mouse.y) - ($(this.element).outerHeight()*(1-s)/2) + 'px';

			$(this.element).css('-webkit-transform',
				'scale('+pb.currentpanel.core.scale+','+pb.currentpanel.core.scale+')');

		},
		drop: function(){
		
			if (undef(pb.project)) return;
			if (undef(pb.currentpanel)) return;
			if (undef(pb.currentpanel.element)) return;
			
			var oy = -1;
			var ox = -1;
			var s = pb.currentpanel.core.scale;
			var doffsetx = -this.core.draggedoffsetx;
			var doffsety = -this.core.draggedoffsety;
			var elebox = this.element.getBoundingClientRect();
			var bbox = pb.currentpanel.element.getBoundingClientRect();
			
			var els = pb.mouse.elementsOver();
			
			var found = false;
			for (var i=els.length; i--;){
				if (/SubPanel-/.test(els[i].id)){
					var subpanel = get(els[i].id); if ($(subpanel.element).hasClass('first') || $(subpanel.element).hasClass('outlined')) continue;
					if (!subpanel.children) subpanel.children = [];
					if (this.subpanel){removeFromArray(get(this.subpanel).children, this.core.id);}
					if (subpanel.children.indexOf(this.core.id) === -1) subpanel.children.push(this.core.id);
					this.subpanel = subpanel.core.id;
					found = true;
					break;
				}
			}
			if (!found && this.subpanel){
				var subpanel = get(this.subpanel); var self = this;
				if (subpanel.children.indexOf(this.core.id) !== -1){
					pb.openDialog({
						title: 'Confirm',
						content: '<br><center>Remove item(s) from subpanel?</center>',
						confirm: 'ok', cancel: 'cancel',
						style: {height: '120px'},
						onConfirm: function(){
							pb.closeDialog(); removeFromArray(subpanel.children, self.core.id); self.subpanel = false;
						},
						onCancel: function(){
							pb.closeDialog(); 
						}
					});
					
				}
			}
			
			if (this.panel){
			
				if (pb.mouse.isOverElement(document.getElementById('button-library-pane'))){	
					if (this.library == 'panel') addUserButton(this);
				}
				
				$(this.element).remove();
				pb.currentpanel.element.appendChild(this.element);
				this.element.style.zIndex = this.core.zvalue;
				this.library = 'panel';
				
				//todo move to constrain
				if (pb.snap_to_panel && doffsetx + pb.mouse.pagex < bbox.left) 
					this.element.style.left = 0 + 'px';
				else if (pb.snap_to_panel && doffsetx + pb.mouse.pagex > bbox.right - $(this.element).outerWidth()*s) 
					this.element.style.left = $(pb.currentpanel.element).outerWidth() 
						- $(this.element).outerWidth() - 2 + 'px';
				else this.element.style.left = (doffsetx + pb.mouse.x)/s - bbox.left/s + ox + 'px';
					
				if (pb.snap_to_panel && doffsety + pb.mouse.pagey < bbox.top)
					this.element.style.top = 0 + 'px';
				else if (pb.snap_to_panel && doffsety + pb.mouse.pagey > bbox.bottom - $(this.element).outerHeight() * s)
					this.element.style.top = $(pb.currentpanel.element).outerHeight() 
						- $(this.element).outerHeight() - 2 + 'px';
				else this.element.style.top = (doffsety + pb.mouse.y)/s - bbox.top/s + oy + 'px';
				
				this.makeResizable();
				
				tweencss({object: this.element, time: 0, props: {scale: 1.0}, to: {scale: 1.0} });
				
				if (pb.mouse.isOverElement(document.getElementById('button-library-pane'))){	
					this.element.style.top = this.core.previouslocation.top;
					this.element.style.left = this.core.previouslocation.left;
				}
				
				this.core.previouslocation = {top: this.element.style.top, left: this.element.style.left};

			}
			else {
			
				if (pb.currentpanel && !pb.mouse.isOverElement($('#tools-panel')[0]) &&
					pb.mouse.isOverElement(pb.currentpanel.element)){
					
					var taction = new Action({ type: 'drop', items: [this] });
					pb.saveaction(taction);
						
					$(this.element).remove();
			
					this.element.style.zIndex = this.core.zvalue;
					this.library = 'panel';
					
					this.setPosition(
						doffsetx + pb.mouse.x/s - bbox.left/s + ox,
						doffsety + pb.mouse.y/s - bbox.top/s + oy
					);
					
					this.element.className = this.element.className.replace(/cloneable/g, '');
					this.core.texteditable = true;	
					this.element.className += ' draggable ';
					
					this.makeResizable();
					
					this.element.style.width = this.basewidth + 'px';
					this.element.style.height = this.baseheight + 'px';
					
					this.panel = pb.currentpanel;
					this.panel.addChild(this);
					
					this.constrain();
					
					this.core.responsive = true;
					this.core.left = parseFloat(this.element.style.left);
					this.core.top = parseFloat(this.element.style.top);
						
					tweencss({ object: this.element, time: 0, props: {scale: 1.0}, to: {scale: 1.0} });
					
					this.core.previouslocation = {top: this.element.style.top, left: this.element.style.left};
					
					pb.updateTree();

					this.ontopanel();
					
				}
				else this.destroy();
			}
			
			if (this.subpanel){
				var _bbox = get(this.subpanel).element.getBoundingClientRect();
				var _cbox = this.element.getBoundingClientRect();
				var _pbox = this.panel.element.getBoundingClientRect();
				this._x = _cbox.left - _bbox.left - _pbox.left;
				this._y = _cbox.top - _bbox.top - _pbox.top;
				this.element.style.zIndex = parseInt(get(this.subpanel).element.style.zIndex) + 1;
			}
			
		},
		constrain: function(){
		
			var bbox = pb.currentpanel.element.getBoundingClientRect();
			var elebox = this.element.getBoundingClientRect();
			var ox = 0; var oy = 0;
		
			if (elebox.left < bbox.left) this.element.style.left = '0px';
			if (elebox.top < bbox.top) this.element.style.top = '0px';
			if (elebox.right > bbox.right) this.element.style.left =
				$(pb.currentpanel.element).outerWidth()
				- $(this.element).outerWidth() + ox + 'px';
			if (elebox.bottom > bbox.bottom) this.element.style.top =
				$(pb.currentpanel.element).outerHeight()
				- $(this.element).outerHeight() + oy + 'px';
				
		},
		makeResizable: function(){
			
			$(this.element).resizable({
				autoHide: true,
				containment: 'parent', 
				handles: 'n, e, s, w, se, sw, nw, ne',
				resize: function (e, ui){	
					
					var s = pb.currentpanel.core.scale;
					var bbox = pb.currentpanel.element.getBoundingClientRect();
					var elebox = this.element.getBoundingClientRect();
					
					var changeWidth = ui.size.width - ui.originalSize.width;
					
					var newWidth = ui.originalSize.width + changeWidth/s;
				 
					var changeHeight = ui.size.height - ui.originalSize.height;
					var newHeight = ui.originalSize.height + changeHeight/s; 
					
					this.element.style.width = newWidth+'px';
					this.element.style.height = newHeight+'px';
					
					var oldtop = this.element.style.top;
	
					if (ui.handle == 'w' || ui.handle == 'nw' || ui.handle == 'sw'){
						console.log('nw');
						this.element.style.left = ((pb.mouse.x - bbox.left)/s) + 'px';
					}
					if (ui.handle == 'n' || ui.handle == 'nw' || ui.handle == 'ne'){
						console.log('ne');
						this.element.style.top = ((pb.mouse.y - bbox.top)/s) + 'px';
					}
					
					var elebox = this.element.getBoundingClientRect();
					if (pb.snap_to_panel && elebox.right >= bbox.right)
						this.element.style.width = newWidth - ((elebox.right - bbox.right)/s) + 'px';
					if (pb.snap_to_panel && elebox.bottom >= bbox.bottom)
						this.element.style.height = newHeight - ((elebox.bottom - bbox.bottom)/s) + 'px';
					if (pb.snap_to_panel && elebox.top <= bbox.top){
						if (this._lastsizey) this.element.style.height = this._lastsizey;
						this.element.style.top = '0px';
					}
					if (pb.snap_to_panel && elebox.left <= bbox.left){
						if (this._lastsizex) this.element.style.width = this._lastsizex;
						this.element.style.left = '0px';
					}
				
					this.resize();
					for (var k=0;k<this.parts.length;k++){
						if (this.parts[k].resize) this.parts[k].resize();
					}
					
					this._lastsizex = this.element.style.width;
					this._lastsizey = this.element.style.height;
					this._lastleft = this.element.style.left;
					this._lasttop = this.element.style.top;
					
				}.bind(this),
				start: function(e, ui) {
					this.action = new Action({
						type: 'size',
						items: [this],
						oldvalues: [{width: this.element.style.width, height: this.element.style.height}]
					});
				}.bind(this),
				stop: function(e, ui) {
					this.action.newvalues = [{width: this.element.style.width, height: this.element.style.height}];
					pb.saveaction(this.action);
				}.bind(this)
			}); 
			
		},
		setStyle: function(s){
			if (this.element) this.element.style.cssText = s;
			this.states[this.currentstate].style = s;
		},
		setLeft: function(l){
			if (this.element) this.element.style.left = l + 'px';
			this.left = l;
		},
		setTop: function(t){
			if (this.element) this.element.style.top = t + 'px';
			this.left = t;
		},
		setPosition: function(l,t){
			if (this.element) this.element.style.left = l + 'px';
			if (this.element) this.element.style.top = t + 'px';
			this.left = l;
			this.top = t;
		},
		setWidth: function(w){
			if (this.element) this.element.style.width = w + 'px';
			this.actualwidth = w;
		},
		setHeight: function(h){
			if (this.element) this.element.style.height = h + 'px';
			this.actualheight = h;
		},
		setSize: function(w, h){
			if (this.element) this.element.style.width = w + 'px';
			if (this.element) this.element.style.height = h + 'px';
			this.actualwidth = w;
			this.actualheight = h;
		},
		setSizeSmart: function(w, h){
			if (w !== null){
				if (this.element){
					var oldleft = parseFloat(this.element.style.left);
					var oldw = parseFloat(this.element.style.width);
					this.element.style.width = w + 'px';
					this.element.style.left = oldleft - (w-oldw);
				}
				this.actualwidth = w;
			}
			if (!undef(h) && h !== null){
				if (this.element){
					var oldtop = parseFloat(this.element.style.top);
					var oldh = parseFloat(this.element.style.height);
					this.element.style.height = h + 'px';
					this.element.style.top = oldtop - (h-oldh);
				}
				this.actualheight = h;
			}
			window.onresize();
		},
		setZ: function(z){
			if (this.element) this.element.style.zIndex = z;
			this.core.zvalue = z;
		},
		setPositionCenter: function(x,y){
			if (this.element){
				this.element.style.left = (x - $(this.element).outerWidth()/2) + 'px';
				this.element.style.top = (y - $(this.element).outerHeight()/2) + 'px';
			}
			this.left = parseInt(this.element.style.left);
			this.top = parseInt(this.element.style.top);
		},
		getPositionCenter: function(){
			var result = {};
			result.x = parseInt(this.element.style.left) + ($(this.element).outerWidth()/2);
			result.y = parseInt(this.element.style.top) + ($(this.element).outerHeight()/2);
			return result;
		},
		getWidthToHeight: function(){
			return this.width/this.height;
		},
		getHeightToWidth: function(){
			return this.height/this.width;
		},
		getActualWidth: function(){
			return parseInt(this.element.style.width);
		},
		getActualHeight: function(){
			return parseInt(this.element.style.width);
		},
		//destroy: function(){
		//	if (this.element.parentNode) this.element.parentNode.removeChild(this.element);
		//	removeFromArray(this.library, this);
		//},
		destroy: function(){
			$(this.element).remove();
			removeFromArray(this.library, this);
		},
		restore: function(){
			this.panel.addChild(this);
			this.library.push(this);
		},
		addPart: function(part){
			this.parts.push(part);
			this.element.appendChild(part.element);
		},
		getChild: function(name){
			for (var i = 0; i < this.children.length; i++){
				if (this.children[i].name === name) return this.children[i];
			}
			return null;
		},
		getChildById: function(id){
			for (var i = 0; i < this.children.length; i++){
				if (this.children[i].id === id) return this.children[i];
			}
			return null;
		},
		getChildrenByClass: function(classname){
			var children = [];
			
			for (var i = 0; i < this.children.length; i++){
				var classlist = this.children[i].className.split(' ');
				if (arrayContains(classlist, classname)) children.push(this.children[i]);
			}
			if (children.length > 0) return children;
			else return null;
		}
	}
//**************  END WIDGET  ****************//