Commit 43a8a2f4 authored by Bas Lijnse's avatar Bas Lijnse

Removed itwc.js from client again (was restored in merge with master)

parent f3f9750a
//#### iTasks Web Client ####//
//This javascript program defines the web-based run-time environment of iTasks programs
itwc = itwc || {};
itwc.global = {};
//#### UTILITY FUNCTIONS ####//
itwc.util = {};
itwc.util.urlEncode = function (obj) {
var parts = [];
for(k in obj) {
parts.push(k+'='+encodeURIComponent(obj[k]));
}
return parts.join('&');
};
itwc.util.equalArgs = function (a1,a2) { //Shallow array comparison
var i, len = a1.length;
if(a2.length !== len) {
return false;
}
for(i = 0; i < len; i++) {
if(a1[i] !== a2[i]) {
return false;
}
}
return true;
}
//Define a new prototype object by extending the prototype of an existing one
itwc.extend = function(inheritFrom,definition) {
var c = function() {};
c.prototype = new inheritFrom();
for(k in definition) {
c.prototype[k] = definition[k];
}
return c;
}
//#### GENERIC UI COMPONENT BASE DEFINITIONS ####//
itwc.Component = function() {};
itwc.Component.prototype = {
isContainer: false,
defaultWidth: 'flex',
defaultHeight: 'wrap',
defaultMargins: [0,0,0,00],
init: function(definition, parentCmp) {
var me = this;
me.domEl = null;
me.targetEl = null;
me.parentCmp = parentCmp || null;
me.items = [];
me.processDefinition(definition);
me.hotkeyListener = null;
},
processDefinition: function(definition) {
var me = this;
//Initialize component properties
//from the definition
me.definition = definition || {};
me.type = (definition && definition.xtype) || 'itwc_component';
//Parse margins
if(definition.margins) {
me.margins = definition.margins.split(' ').map(function(m) { return (m | 0) });
} else {
me.margins = me.defaultMargins;
}
},
render: function(itemIdx, isLast) {
var me = this;
me.domId = 'itwc-' + itwc.DOMID++;
//Create and initialize dom element
me.domEl = document.createElement(me.domTag);
me.targetEl = me.domEl;
me.initDOMEl(itemIdx);
me.initSize(itemIdx, isLast);
me.domEl.id = me.domId;
},
//Configurable properties for initializing the DOM element
domTag: 'div',
initDOMEl: function(itemIdx) {
},
initSize: function(itemIdx,isLast) {
var me = this,
el = me.domEl,
width = me.definition.itwcWidth || me.defaultWidth,
height = me.definition.itwcHeight || me.defaultHeight,
direction = me.parentCmp.definition.direction || me.parentCmp.defaultDirection;
//Set width
if(width === 'flex') {
if(direction == 'horizontal') {
el.style.flex = 1;
el.style.webkitFlex = 1;
} else {
el.style.alignSelf = 'stretch';
el.style.webkitAlignSelf = 'stretch';
}
} else if (width === 'wrap') {
if(direction == 'horizontal') {
el.classList.add('wrapping-horizontal');
}
} else {
el.style.width = width + 'px';
el.style.minWidth = width + 'px';
}
//Set height
if(height === 'flex') {
if(direction == 'vertical') {
el.style.flex = 1;
el.style.webkitFlex = 1;
} else {
el.style.alignSelf = 'stretch';
el.style.webkitAlignSelf = 'stretch';
}
} else if (height === 'wrap') {
if(direction == 'vertical') {
el.classList.add('wrapping-vertical');
}
} else {
el.style.height = height + 'px';
el.style.minHeight = height + 'px';
}
//Set margins
me.initMargins(itemIdx,isLast);
//Set padding
if(me.definition.padding) {
el.style.padding = me.definition.padding.split(' ').map(function(s) { return s + 'px'}).join(' ');
}
//If a container, set alignment
if(me.isContainer) {
me.initItemLayout();
}
},
initMargins: function(itemIdx,isLast) {
var me = this,
el = me.domEl,
width = me.definition.itwcWidth || me.defaultWidth,
height = me.definition.itwcHeight || me.defaultHeight,
direction = me.parentCmp.definition.direction || me.parentCmp.defaultDirection,
valign = me.parentCmp.definition.valign || 'top',
halign = me.parentCmp.definition.halign || 'left';
//Set margins as specified
el.style.margin = me.margins.map(function(s) { return s + 'px'}).join(' ');
//Set margins to auto based on alignment of parent
if(direction == 'vertical') {
if(width !== 'flex') {
switch(halign) {
case 'left': el.style.marginRight = 'auto'; break;
case 'center': el.style.marginRight = 'auto'; el.style.marginLeft = 'auto'; break;
case 'right': el.style.marginLeft = 'auto'; break;
}
}
//If this element is the first, maybe also adjust top margin;
if(itemIdx === 0 && (valign == 'middle' || valign == 'bottom')) {
el.style.marginTop = 'auto';
}
//If this element is the last, maybe also adjust bottom margin;
if(isLast && (valign == 'middle' || 'top')) {
el.style.marginBottom = 'auto';
}
} else {
if(height !== 'flex') {
switch(valign) {
case 'top': el.style.marginBottom = 'auto'; break;
case 'middle': el.style.marginBottom = 'auto'; el.style.marginTop = 'auto'; break;
case 'bottom': el.style.marginTop = 'auto'; break;
}
}
//If this element is the first, maybe also adjust left margin;
if(itemIdx === 0 && (halign == 'center' || halign == 'right')) {
el.style.marginLeft = 'auto';
}
//If this element is the last, maybe also adjust right margin;
if(isLast && (halign == 'center' || halign == 'left')) {
el.style.marginRight = 'auto';
}
}
},
initItemLayout: function() {
var me = this,
el = me.targetEl,
horizontal = ((me.definition.direction && me.definition.direction) == 'horizontal') || false;
el.classList.add(horizontal ? 'hcontainer' : 'vcontainer');
},
afterAdd: function() {
var me = this;
if(me.items && me.items.length) {
me.items.forEach(function(cmp) {
cmp.afterAdd();
});
}
},
afterShow: function() {
var me = this;
if(me.items && me.items.length) {
me.items.forEach(function(cmp) {
cmp.afterShow();
});
}
},
afterResize: function() {
var me = this;
if(me.items && me.items.length) {
me.items.forEach(function(cmp) {
cmp.afterResize();
});
}
},
beforeDOMRemove: function() {
var me = this;
if(me.items && me.items.length) {
me.items.forEach(function(cmp) {
cmp.beforeDOMRemove();
});
}
},
applyUpdate: function(operation,args) {
var me = this;
if(me[operation] && typeof me[operation] == 'function') {
//Check first if we already applied this update
me.appliedUpdates = me.appliedUpdates || [];
var nextAppliedUpdate = me.appliedUpdates.shift();
if(nextAppliedUpdate instanceof Array) {
if(nextAppliedUpdate[0] == operation && itwc.util.equalArgs(nextAppliedUpdate[1],args)) {
//On a match we are done
return
} else {
delete(me.appliedUpdates);
}
}
me[operation].apply(me,args);
} else {
console.log("Unsupported operation on component", me, operation,args);
}
},
addAlreadyAppliedUpdate(operation,args) {
//Sometimes we already know we will get an update from the server that we already applied.
//If we have already changed in the meantime, this update should not be applied
var me = this;
me.appliedUpdates = me.appliedUpdates || [];
me.appliedUpdates.push([operation,args]);
},
getChildIndex: function() {
var me = this,
siblings = me.parentCmp.items,
num = siblings.length,
i;
for(i = 0; i < num; i++) {
if(siblings[i].domId === me.domId) {
return i;
}
}
return -1;
},
setHotkeys: function(hotkeys) {
var me = this;
me.hotkeys = hotkeys;
if(me.hotkeys.length === 0 && me.hotkeyListener) {
me.domEl.removeEventListener('keyup',me.hotkeyListener);
me.hotkeyListener = null;
} else {
me.hotkeyListener = me.domEl.addEventListener('keyup',function(e) {
me.hotkeys.forEach(function(hotkey) {
if(e.keyCode === hotkey[0].key) {
itwc.controller.sendActionEvent(hotkey[1].taskId,hotkey[1].actionId);
}
});
});
}
},
setTaskId: function(taskId) {
this.definition.taskId = taskId;
}
};
itwc.Container = itwc.extend(itwc.Component,{
isContainer: true,
defaultDirection: 'vertical',
afterItemAdded: null,
afterItemRemoved: null
});
itwc.Panel = itwc.extend(itwc.Container,{
panelEl: null,
headerEl: null,
titleEl: null,
closeEl: null,
menuEl: null,
initDOMEl: function() {
this.initPanel();
},
initPanel: function() {
var me = this;
if(!me.panelEl) {
me.panelEl = me.domEl;
}
me.targetEl = document.createElement('div');
me.targetEl.classList.add('inner');
me.panelEl.appendChild(me.targetEl);
},
createHeaderEl: function() {
var me = this;
me.headerEl = document.createElement('div');
me.headerEl.classList.add('header');
me.panelEl.insertBefore(me.headerEl,me.panelEl.childNodes[0]);
},
createTitleEl: function() {
var me = this;
me.titleEl = document.createElement('span');
if(me.headerEl.childNodes.length) {
me.headerEl.insertBefore(me.titleEl,me.headerEl.childNodes[0]);
} else {
me.headerEl.appendChild(me.titleEl);
}
},
createCloseEl: function() {
var me = this;
me.closeEl = document.createElement('a');
me.closeEl.innerHTML = 'x';
me.closeEl.href = '#';
me.closeEl.classList.add('close');
me.closeEl.addEventListener('click',function(e) {
itwc.controller.sendActionEvent(me.definition.closeTaskId,'Close');
e.preventDefault();
},me);
if(me.headerEl.childNodes.length) {
me.headerEl.insertBefore(me.closeEl,me.headerEl.childNodes[me.headerEl.childNodes.length - 1]);
} else {
me.headerEl.appendChild(me.closeEl);
}
},
createMenuEl: function(definition) {
var me = this;
me.menu = new itwc.component.itwc_menubar();
me.menu.definition = definition;
me.menu.init(definition, me);
me.menu.render(0,false);
me.menuEl = me.menu.domEl;
me.domEl.insertBefore(me.menuEl,me.targetEl);
},
setTitle: function(title) {
var me = this;
if(title) {
if(!me.headerEl) { me.createHeaderEl();}
if(!me.titleEl) { me.createTitleEl();}
me.titleEl.innerHTML = title;
} else {
if(me.titleEl) {
me.headerEl.removeChild(me.titleEl);
me.titleEl = null;
}
if(me.headerEl && !me.headerEl.childNodes.length) {
me.domEl.removeChild(me.headerEl);
me.headerEl = null;
}
}
},
setCloseTaskId: function(taskId) {
var me = this;
me.definition.closeTaskId = taskId;
if(taskId) {
if(!me.headerEl) { me.createHeaderEl();}
if(!me.closeEl) { me.createCloseEl();}
} else {
if(me.closeEl) {
me.headerEl.removeChild(me.closeEl);
me.closeEl = null;
}
if(me.headerEl && !me.headerEl.childNodes.length) {
me.domEl.removeChild(me.headerEl);
me.headerEl = null;
}
}
},
setMenu: function(items) {
var me = this;
if(items) {
if(!me.menuEl) {
me.createMenuEl({xtype: 'itwc_menubar', items: items});
}
} else { //remove
if(me.menuEl) {
me.menu.beforeDOMRemove();
me.domEl.removeChild(me.menuEl);
me.menuEl = null;
me.menu = null;
}
}
}
});
itwc.Layer = itwc.extend(itwc.Panel,{
maximize: false,
modal: false,
defaultVpos: 'middle',
defaultHpos: 'center',
initDOMEl: function() {
this.initLayer();
},
initLayer: function() {
var me = this, wrapEl;
me.domEl.classList.add('layer');
me.initPanel();
//If the layer is modal, we need to wrap the element in an additional full size
//div that masks everything beneath it
if(me.modal) {
me.domEl = document.createElement('div');
me.domEl.classList.add('modal-masker');
me.domEl.appendChild(me.panelEl);
}
},
initSize: function() {
var me = this;
//Layers are put directly in the body and sized by the controller
if(me.maximize || me.modal) {
this.domEl.style.width = window.innerWidth;
this.domEl.style.height = window.innerHeight;
}
//Children are size using their iTasks attributes
me.initItemLayout();
}
});
//#### CORE UI COMPONENT DEFINITIONS ####//
itwc.component = {};
itwc.component.itwc_menubar = itwc.extend(itwc.Container, {
defaultDirection: 'horizontal',
initDOMEl: function() {
var me = this,
el = me.domEl;
el.classList.add('toolbar');
},
initSize: function() {},
initItemLayout: function() {}
});
itwc.component.itwc_menubutton = itwc.extend(itwc.Component, {
initDOMEl: function() {
var me = this,
el = me.domEl,
linkEl, menuEl;
el.classList.add('menu-item');
//Menu button
linkEl = document.createElement('a');
linkEl.href = '#';
linkEl.innerHTML = me.definition.text;
el.appendChild(linkEl)
//Menu items
me.menu = new itwc.component.itwc_menu();
me.menu.init({xtype: 'itwc_menu', items: me.definition.menu},me);
me.menu.render(0,false);
el.appendChild(me.menu.domEl);
},
initSize: function() {} //Don't size
});
itwc.component.itwc_menu = itwc.extend(itwc.Container,{
xtype: 'itwc_menu',
initDOMEl: function() {
var me = this,
el = me.domEl;
el.classList.add('menu');
},
initSize: function() {} //Don't size
});
itwc.component.itwc_actionmenuitem = itwc.extend(itwc.Component,{
initDOMEl: function() {
var me = this,
el = me.domEl,
iconEl, linkEl;
el.classList.add('submenu-item');
me.disabled = me.definition.disabled;
linkEl = document.createElement('a');
linkEl.href = '#';
linkEl.innerHTML = me.definition.text;
linkEl.addEventListener('click',function(e) {
if(!me.disabled) {
itwc.controller.sendActionEvent(me.definition.taskId,me.definition.actionId);
}
e.preventDefault();
});
el.appendChild(linkEl)
},
initSize: function() {} //Don't size
});
itwc.component.itwc_submenuitem = itwc.extend(itwc.Container,{
initDOMEl: function() {
var me = this,
el = me.domEl,
iconEl, linkEl;
me.disabled = me.definition.disabled;
el.classList.add('submenu-item');
linkEl = document.createElement('a');
linkEl.href = '#';
linkEl.innerHTML = me.definition.text;
el.appendChild(linkEl)
//Menu items
me.menu = new itwc.component.itwc_menu();
me.menu.init({xtype: 'itwc_menu', items: me.definition.menu},me);
me.menu.render(0,false);
el.appendChild(me.menu.domEl);
},
initSize: function() {} //Don't size
});
itwc.component.itwc_viewport = itwc.extend(itwc.Layer,{
initDOMEl: function() {
var me = this;
me.windows = [];
me.maximize = true;
me.domEl.classList.add('viewport');
me.initLayer();
if(me.definition.menu) {
me.setMenu(me.definition.menu);
}
itwc.controller.instanceProxies[me.definition.instanceNo] = itwc.controller.remoteProxy;
itwc.controller.remoteProxy.addInstance(me.definition.instanceNo,me.definition.instanceKey,me);
},
beforeDOMRemove: function() {
var me = this;
itwc.controller.remoteProxy.removeInstance(me.definition.instanceNo);
},
setTitle: function(title) {
document.title = title || '';
},
reset: function() {
}
});
itwc.component.itwc_window = itwc.extend(itwc.Layer, {
defaultMargins: [10,10,10,10],
movable: false,
initDOMEl: function() {
var me = this;
switch(me.definition.windowType) {
case 'modal':
me.modal = true;
me.domEl.classList.add('modal-window');
break;
case 'bubble':
me.domEl.classList.add('notification-bubble');
break;
default:
me.movable = true;
me.domEl.classList.add('floating-window');
}
me.initLayer();
me.setTitle(me.definition.title);
me.setCloseTaskId(me.definition.closeTaskId);
if(me.definition.menu) {
me.setMenu(me.definition.menu);
}
if(me.movable && me.headerEl) {
me.headerEl.addEventListener('mousedown', me.onStartDrag.bind(me));
me.headerEl.style.cursor = 'move';
}
},
initSize: function() {
var me = this,
el = me.panelEl,
width = me.definition.itwcWidth || me.defaultWidth,
height = me.definition.itwcHeight || me.defaultHeight;
if(width != 'flex' && width != 'wrap') {
el.style.width = width + 'px';
el.style.minWidth = width + 'px';
}
if(height != 'flex' && height != 'wrap') {
el.style.height = height + 'px';
el.style.minHeight = height + 'px';
}
if(me.modal) {
me.domEl.style.width = window.innerWidth + 'px';
me.domEl.style.height = window.innerHeight + 'px';
}
me.initItemLayout();
},
onStartDrag: function(e) {
var me = this;
e.preventDefault();
me.lastX = e.clientX;
me.lastY = e.clientY;
me.onDragging_ = me.onDragging.bind(me);
me.onStopDrag_ = me.onStopDrag.bind(me);
window.addEventListener('mousemove', me.onDragging_);
window.addEventListener('mouseup', me.onStopDrag_);
},
onDragging: function(e) {
var me = this,
newX = e.clientX,
newY = e.clientY,
diffY = newY - me.lastY,
diffX = newX - me.lastX,
left, top;
left = parseInt(document.defaultView.getComputedStyle(me.panelEl,'').getPropertyValue('left'),10);
top = parseInt(document.defaultView.getComputedStyle(me.panelEl,'').getPropertyValue('top'),10);
me.panelEl.style.left = ((left < 0) ? 0 : (left + diffX)) + 'px';
me.panelEl.style.top = ((top < 0) ? 0 : (top + diffY)) + 'px';
me.lastX = newX;
me.lastY = newY;
},