(function () {/**
* @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/almond for details
*/
//Going sloppy to avoid 'use strict' string cost, but strict practices should
//be followed.
/*jslint sloppy: true */
/*global setTimeout: false */
var requirejs, require, define;
(function (undef) {
var main, req, makeMap, handlers,
defined = {},
waiting = {},
config = {},
defining = {},
hasOwn = Object.prototype.hasOwnProperty,
aps = [].slice,
jsSuffixRegExp = /\.js$/;
function hasProp(obj, prop) {
return hasOwn.call(obj, prop);
}
/**
* Given a relative module name, like ./something, normalize it to
* a real name that can be mapped to a path.
* @param {String} name the relative name
* @param {String} baseName a real name that the name arg is relative
* to.
* @returns {String} normalized name
*/
function normalize(name, baseName) {
var nameParts, nameSegment, mapValue, foundMap, lastIndex,
foundI, foundStarMap, starI, i, j, part,
baseParts = baseName && baseName.split("/"),
map = config.map,
starMap = (map && map['*']) || {};
//Adjust any relative paths.
if (name && name.charAt(0) === ".") {
//If have a base name, try to normalize against it,
//otherwise, assume it is a top-level require that will
//be relative to baseUrl in the end.
if (baseName) {
name = name.split('/');
lastIndex = name.length - 1;
// Node .js allowance:
if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
}
//Lop off the last part of baseParts, so that . matches the
//"directory" and not name of the baseName's module. For instance,
//baseName of "one/two/three", maps to "one/two/three.js", but we
//want the directory, "one/two" for this normalization.
name = baseParts.slice(0, baseParts.length - 1).concat(name);
//start trimDots
for (i = 0; i < name.length; i += 1) {
part = name[i];
if (part === ".") {
name.splice(i, 1);
i -= 1;
} else if (part === "..") {
if (i === 1 && (name[2] === '..' || name[0] === '..')) {
//End of the line. Keep at least one non-dot
//path segment at the front so it can be mapped
//correctly to disk. Otherwise, there is likely
//no path mapping for a path starting with '..'.
//This can still fail, but catches the most reasonable
//uses of ..
break;
} else if (i > 0) {
name.splice(i - 1, 2);
i -= 2;
}
}
}
//end trimDots
name = name.join("/");
} else if (name.indexOf('./') === 0) {
// No baseName, so this is ID is resolved relative
// to baseUrl, pull off the leading dot.
name = name.substring(2);
}
}
//Apply map config if available.
if ((baseParts || starMap) && map) {
nameParts = name.split('/');
for (i = nameParts.length; i > 0; i -= 1) {
nameSegment = nameParts.slice(0, i).join("/");
if (baseParts) {
//Find the longest baseName segment match in the config.
//So, do joins on the biggest to smallest lengths of baseParts.
for (j = baseParts.length; j > 0; j -= 1) {
mapValue = map[baseParts.slice(0, j).join('/')];
//baseName segment has config, find if it has one for
//this name.
if (mapValue) {
mapValue = mapValue[nameSegment];
if (mapValue) {
//Match, update name to the new value.
foundMap = mapValue;
foundI = i;
break;
}
}
}
}
if (foundMap) {
break;
}
//Check for a star map match, but just hold on to it,
//if there is a shorter segment match later in a matching
//config, then favor over this star map.
if (!foundStarMap && starMap && starMap[nameSegment]) {
foundStarMap = starMap[nameSegment];
starI = i;
}
}
if (!foundMap && foundStarMap) {
foundMap = foundStarMap;
foundI = starI;
}
if (foundMap) {
nameParts.splice(0, foundI, foundMap);
name = nameParts.join('/');
}
}
return name;
}
function makeRequire(relName, forceSync) {
return function () {
//A version of a require function that passes a moduleName
//value for items that may need to
//look up paths relative to the moduleName
var args = aps.call(arguments, 0);
//If first arg is not require('string'), and there is only
//one arg, it is the array form without a callback. Insert
//a null so that the following concat is correct.
if (typeof args[0] !== 'string' && args.length === 1) {
args.push(null);
}
return req.apply(undef, args.concat([relName, forceSync]));
};
}
function makeNormalize(relName) {
return function (name) {
return normalize(name, relName);
};
}
function makeLoad(depName) {
return function (value) {
defined[depName] = value;
};
}
function callDep(name) {
if (hasProp(waiting, name)) {
var args = waiting[name];
delete waiting[name];
defining[name] = true;
main.apply(undef, args);
}
if (!hasProp(defined, name) && !hasProp(defining, name)) {
throw new Error('No ' + name);
}
return defined[name];
}
//Turns a plugin!resource to [plugin, resource]
//with the plugin being undefined if the name
//did not have a plugin prefix.
function splitPrefix(name) {
var prefix,
index = name ? name.indexOf('!') : -1;
if (index > -1) {
prefix = name.substring(0, index);
name = name.substring(index + 1, name.length);
}
return [prefix, name];
}
/**
* Makes a name map, normalizing the name, and using a plugin
* for normalization if necessary. Grabs a ref to plugin
* too, as an optimization.
*/
makeMap = function (name, relName) {
var plugin,
parts = splitPrefix(name),
prefix = parts[0];
name = parts[1];
if (prefix) {
prefix = normalize(prefix, relName);
plugin = callDep(prefix);
}
//Normalize according
if (prefix) {
if (plugin && plugin.normalize) {
name = plugin.normalize(name, makeNormalize(relName));
} else {
name = normalize(name, relName);
}
} else {
name = normalize(name, relName);
parts = splitPrefix(name);
prefix = parts[0];
name = parts[1];
if (prefix) {
plugin = callDep(prefix);
}
}
//Using ridiculous property names for space reasons
return {
f: prefix ? prefix + '!' + name : name, //fullName
n: name,
pr: prefix,
p: plugin
};
};
function makeConfig(name) {
return function () {
return (config && config.config && config.config[name]) || {};
};
}
handlers = {
require: function (name) {
return makeRequire(name);
},
exports: function (name) {
var e = defined[name];
if (typeof e !== 'undefined') {
return e;
} else {
return (defined[name] = {});
}
},
module: function (name) {
return {
id: name,
uri: '',
exports: defined[name],
config: makeConfig(name)
};
}
};
main = function (name, deps, callback, relName) {
var cjsModule, depName, ret, map, i,
args = [],
callbackType = typeof callback,
usingExports;
//Use name if no relName
relName = relName || name;
//Call the callback to define the module, if necessary.
if (callbackType === 'undefined' || callbackType === 'function') {
//Pull out the defined dependencies and pass the ordered
//values to the callback.
//Default to [require, exports, module] if no deps
deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
for (i = 0; i < deps.length; i += 1) {
map = makeMap(deps[i], relName);
depName = map.f;
//Fast path CommonJS standard dependencies.
if (depName === "require") {
args[i] = handlers.require(name);
} else if (depName === "exports") {
//CommonJS module spec 1.1
args[i] = handlers.exports(name);
usingExports = true;
} else if (depName === "module") {
//CommonJS module spec 1.1
cjsModule = args[i] = handlers.module(name);
} else if (hasProp(defined, depName) ||
hasProp(waiting, depName) ||
hasProp(defining, depName)) {
args[i] = callDep(depName);
} else if (map.p) {
map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
args[i] = defined[depName];
} else {
throw new Error(name + ' missing ' + depName);
}
}
ret = callback ? callback.apply(defined[name], args) : undefined;
if (name) {
//If setting exports via "module" is in play,
//favor that over return value and exports. After that,
//favor a non-undefined return value over exports use.
if (cjsModule && cjsModule.exports !== undef &&
cjsModule.exports !== defined[name]) {
defined[name] = cjsModule.exports;
} else if (ret !== undef || !usingExports) {
//Use the return value from the function.
defined[name] = ret;
}
}
} else if (name) {
//May just be an object definition for the module. Only
//worry about defining if have a module name.
defined[name] = callback;
}
};
requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
if (typeof deps === "string") {
if (handlers[deps]) {
//callback in this case is really relName
return handlers[deps](callback);
}
//Just return the module wanted. In this scenario, the
//deps arg is the module name, and second arg (if passed)
//is just the relName.
//Normalize module name, if it contains . or ..
return callDep(makeMap(deps, callback).f);
} else if (!deps.splice) {
//deps is a config object, not an array.
config = deps;
if (config.deps) {
req(config.deps, config.callback);
}
if (!callback) {
return;
}
if (callback.splice) {
//callback is an array, which means it is a dependency list.
//Adjust args if there are dependencies
deps = callback;
callback = relName;
relName = null;
} else {
deps = undef;
}
}
//Support require(['a'])
callback = callback || function () {};
//If relName is a function, it is an errback handler,
//so remove it.
if (typeof relName === 'function') {
relName = forceSync;
forceSync = alt;
}
//Simulate async callback;
if (forceSync) {
main(undef, deps, callback, relName);
} else {
//Using a non-zero value because of concern for what old browsers
//do, and latest browsers "upgrade" to 4 if lower value is used:
//http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
//If want a value immediately, use require('id') instead -- something
//that works in almond on the global level, but not guaranteed and
//unlikely to work in other AMD implementations.
setTimeout(function () {
main(undef, deps, callback, relName);
}, 4);
}
return req;
};
/**
* Just drops the config on the floor, but returns req in case
* the config return value is used.
*/
req.config = function (cfg) {
return req(cfg);
};
/**
* Expose module registry for debugging and tooling
*/
requirejs._defined = defined;
define = function (name, deps, callback) {
if (typeof name !== 'string') {
throw new Error('See almond README: incorrect module build, no module name');
}
//This module may not have dependencies
if (!deps.splice) {
//deps is not an array, so probably means
//an object literal or factory function for
//the value. Adjust args.
callback = deps;
deps = [];
}
if (!hasProp(defined, name) && !hasProp(waiting, name)) {
waiting[name] = [name, deps, callback];
}
};
define.amd = {
jQuery: true
};
}());
define("libs/almond", function(){});
(function(factory){
if(typeof define != "undefined"){
define('dcl/mini',[], factory);
}else if(typeof module != "undefined"){
module.exports = factory();
}else{
dcl = factory();
}
})(function(){
"use strict";
var counter = 0, cname = "constructor", pname = "prototype", empty = {}, mix;
function dcl(superClass, props){
var bases = [0], proto, base, ctor, meta, connectionMap,
output, vector, superClasses, i, j = 0, n;
if(superClass){
if(superClass instanceof Array){
// mixins: C3 MRO
connectionMap = {};
superClasses = superClass.slice(0).reverse();
for(i = superClasses.length - 1; i >= 0; --i){
base = superClasses[i];
// pre-process a base
// 1) add a unique id
base._uniqueId = base._uniqueId || counter++;
// 2) build a connection map and the base list
if((proto = base._meta)){ // intentional assignment
for(vector = proto.bases, j = vector.length - 1; j > 0; --j){
n = vector[j]._uniqueId;
connectionMap[n] = (connectionMap[n] || 0) + 1;
}
superClasses[i] = vector.slice(0);
}else{
superClasses[i] = [base];
}
}
// build output
output = {};
c: while(superClasses.length){
for(i = 0; i < superClasses.length; ++i){
vector = superClasses[i];
base = vector[0];
n = base._uniqueId;
if(!connectionMap[n]){
if(!output[n]){
bases.push(base);
output[n] = 1;
}
vector.shift();
if(vector.length){
--connectionMap[vector[0]._uniqueId];
}else{
superClasses.splice(i, 1);
}
continue c;
}
}
// error
dcl._error("cycle", props, superClasses);
}
// calculate a base class
superClass = superClass[0];
j = bases.length - ((meta = superClass._meta) && superClass === bases[bases.length - (j = meta.bases.length)] ? j : 1) - 1; // intentional assignments
}else{
// 1) add a unique id
superClass._uniqueId = superClass._uniqueId || counter++;
// 2) single inheritance
bases = bases.concat((meta = superClass._meta) ? meta.bases : superClass); // intentional assignment
}
}
// create a base class
proto = superClass ? dcl.delegate(superClass[pname]) : {};
// the next line assumes that constructor is actually named "constructor", should be changed if desired
vector = superClass && (meta = superClass._meta) ? dcl.delegate(meta.weaver) : {constructor: 2}; // intentional assignment
// create prototype: mix in mixins and props
for(; j > 0; --j){
base = bases[j];
meta = base._meta;
dcl.mix(proto, meta && meta.ownProps || base[pname]);
if(meta){
for(n in (superClasses = meta.weaver)){ // intentional assignment
vector[n] = (+vector[n] || 0) | superClasses[n];
}
}
}
for(n in props){
if(isSuper(meta = props[n])){ // intentional assignment
vector[n] = +vector[n] || 0;
}else{
proto[n] = meta;
}
}
// create stubs with fake constructor
//
meta = {bases: bases, ownProps: props, weaver: vector, chains: {}};
// meta information is coded like that:
// bases: an array of super classes (bases) and mixins
// ownProps: a bag of immediate prototype properties for the constructor
// weaver: a bag of chain instructions (before is 1, after is 2)
// chains: a bag of chains (ordered arrays)
bases[0] = {_meta: meta, prototype: proto};
buildStubs(meta, proto);
ctor = proto[cname];
// put in place all decorations and return a constructor
ctor._meta = meta;
ctor[pname] = proto;
//proto.constructor = ctor; // uncomment if constructor is not named "constructor"
bases[0] = ctor;
// each constructor may have two properties on it:
// _meta: a meta information object as above
// _uniqueId: a unique number, which is used to id the constructor
return dcl._postprocess(ctor); // fully prepared constructor
}
// decorators
function Super(f){ this.around = f; }
function isSuper(f){ return f && f.spr instanceof Super; }
// utilities
function allKeys(o){
var keys = [];
for(var name in o){
keys.push(name);
}
return keys;
}
(mix = function(a, b){
for(var n in b){
a[n] = b[n];
}
})(dcl, {
// piblic API
mix: mix,
delegate: function(o){
return Object.create(o);
},
allKeys: allKeys,
Super: Super,
superCall: function superCall(f){ return dcl._makeSuper(f); },
// protected API starts with _ (don't use it!)
// make a Super marker
_makeSuper: function makeSuper(advice, S){ var f = function(){}; f.spr = new (S || Super)(advice); return f; },
// post-processor for a constructor, can be used to add more functionality
// or augment its behavior
_postprocess: function(ctor){ return ctor; }, // identity, used to hang on advices
// error function, augmented by debug.js
_error: function(msg){ throw Error("dcl: " + msg); },
// supercall instantiation, augmented by debug.js
_instantiate: function(advice, previous, node){ var t = advice.spr.around(previous); t.ctr = advice.ctr; return t; },
// the "buildStubs()" helpers, can be overwritten
_extractChain: function(bases, name, advice){
var i = bases.length - 1, chain = [], base, f, around = advice == "around";
for(; base = bases[i]; --i){
// next line contains 5 intentional assignments
if((f = base._meta) ? (f = f.ownProps).hasOwnProperty(name) && (isSuper(f = f[name]) ? (around ? f.spr.around : (f = f.spr[advice])) : around) : around && (f = name == cname ? base : base[pname][name]) && f !== empty[name]){
f.ctr = base;
chain.push(f);
}
}
return chain;
},
_stubChain: function(chain){ // this is "after" chain
var l = chain.length, f;
return !l ? 0 : l == 1 ?
(f = chain[0], function(){
f.apply(this, arguments);
}) :
function(){
for(var i = 0; i < l; ++i){
chain[i].apply(this, arguments);
}
};
},
_stubSuper: function(chain, name){
var i = 0, f, p = empty[name];
for(; f = chain[i]; ++i){
p = isSuper(f) ? (chain[i] = dcl._instantiate(f, p, name)) : f;
}
return name != cname ? p : function(){ p.apply(this, arguments); };
},
_stubChainSuper: function(chain, stub, name){
var i = 0, f, diff, pi = 0;
for(; f = chain[i]; ++i){
if(isSuper(f)){
diff = i - pi;
chain[i] = dcl._instantiate(f, !diff ? 0 : diff == 1 ? chain[pi] : stub(chain.slice(pi, i)), name);
pi = i;
}
}
diff = i - pi;
return !diff ? 0 : diff == 1 && name != cname ? chain[pi] : stub(pi ? chain.slice(pi) : chain);
},
_stub: /*generic stub*/ function(id, bases, name, chains){
var f = chains[name] = dcl._extractChain(bases, name, "around");
return (id ? dcl._stubChainSuper(f, dcl._stubChain, name) : dcl._stubSuper(f, name)) || function(){};
}
});
function buildStubs(meta, proto){
var weaver = meta.weaver, bases = meta.bases, chains = meta.chains;
for(var name in weaver){
proto[name] = dcl._stub(weaver[name], bases, name, chains);
}
}
return dcl;
});
(function(factory){
if(typeof define != "undefined"){
define('dcl/dcl',["./mini"], factory);
}else if(typeof module != "undefined"){
module.exports = factory(require("./mini"));
}else{
dcl = factory(dcl);
}
})(function(dcl){
"use strict";
function nop(){}
var Advice = dcl(dcl.Super, {
//declaredClass: "dcl.Advice",
constructor: function(){
this.before = this.around.before;
this.after = this.around.after;
this.around = this.around.around;
}
});
function advise(advice){ return dcl._makeSuper(advice, Advice); }
function makeAOPStub(before, after, around){
var beforeChain = before || nop,
afterChain = after || nop,
aroundChain = around || nop,
stub = function(){
var r, thrown;
// running the before chain
beforeChain.apply(this, arguments);
// running the around chain
try{
r = aroundChain.apply(this, arguments);
}catch(e){
r = e;
thrown = true;
}
// running the after chain
afterChain.call(this, arguments, r);
if(thrown){
throw r;
}
return r;
};
stub.advices = {before: before, after: after, around: around};
return stub;
}
function chain(id){
return function(ctor, name){
var meta = ctor._meta, rule;
if(meta){
rule = +meta.weaver[name] || 0;
if(rule && rule != id){
dcl._error("set chaining", name, ctor, id, rule);
}
meta.weaver[name] = id;
}
};
}
dcl.mix(dcl, {
// public API
Advice: Advice,
advise: advise,
// expose helper methods
before: function(f){ return dcl.advise({before: f}); },
after: function(f){ return dcl.advise({after: f}); },
around: dcl.superCall,
// chains
chainBefore: chain(1),
chainAfter: chain(2),
isInstanceOf: function(o, ctor){
if(o instanceof ctor){
return true;
}
var t = o.constructor._meta, i;
if(t){
for(t = t.bases, i = t.length - 1; i >= 0; --i){
if(t[i] === ctor){
return true;
}
}
}
return false;
},
// protected API starts with _ (don't use it!)
_stub: /*generic stub*/ function(id, bases, name, chains){
var f = chains[name] = dcl._extractChain(bases, name, "around"),
b = dcl._extractChain(bases, name, "before").reverse(),
a = dcl._extractChain(bases, name, "after");
f = id ? dcl._stubChainSuper(f, id == 1 ? function(f){ return dcl._stubChain(f.reverse()); } : dcl._stubChain, name) : dcl._stubSuper(f, name);
return !b.length && !a.length ? f || function(){} : makeAOPStub(dcl._stubChain(b), dcl._stubChain(a), f);
}
});
return dcl;
});
define('wcDocker/types',[], function () {
//stub
var wcDocker = {};
/**
* Enumerated Docking positions.
* @version 3.0.0
* @memberOf module:wcDocker
* @enum {String} module:wcDocker.DOCK
*/
wcDocker.DOCK = {
/** A floating panel that blocks input until closed */
MODAL: 'modal',
/** A floating panel */
FLOAT: 'float',
/** Docks to the top of a target or window */
TOP: 'top',
/** Docks to the left of a target or window */
LEFT: 'left',
/** Docks to the right of a target or window */
RIGHT: 'right',
/** Docks to the bottom of a target or window */
BOTTOM: 'bottom',
/** Docks as another tabbed item along with the target */
STACKED: 'stacked'
};
/**
* Enumerated Layout wcDocker.
* @memberOf module:wcDocker
* @version 3.0.0
* @enum {String} module:wcDocker.LAYOUT
*/
wcDocker.LAYOUT = {
/** Contains a single div item without management using a {@link module:wcLayoutSimple}, it is up to you to populate it however you wish. */
SIMPLE: 'wcLayoutSimple',
/** Manages a table grid layout using {@link module:wcLayoutTable}, this is the default layout used if none is specified. **/
TABLE: 'wcLayoutTable'
};
/**
* Enumerated Internal events
* @version 3.0.0
* @memberOf module:wcDocker
* @enum {String} module:wcDocker.EVENT
*/
wcDocker.EVENT = {
/** When the panel is initialized */
INIT: 'panelInit',
/** When all panels have finished loading */
LOADED: 'dockerLoaded',
/** When the panel is updated */
UPDATED: 'panelUpdated',
/**
* When the panel has changed its visibility
* This event is called with the current visibility state as the first parameter.
*/
VISIBILITY_CHANGED: 'panelVisibilityChanged',
/** When the user begins moving any panel from its current docked position */
BEGIN_DOCK: 'panelBeginDock',
/** When the user finishes moving or docking a panel */
END_DOCK: 'panelEndDock',
/** When the user brings any panel within a tabbed frame into focus */
GAIN_FOCUS: 'panelGainFocus',
/** When the user leaves focus on any panel within a tabbed frame */
LOST_FOCUS: 'panelLostFocus',
/** When the panel is about to be closed, but before it closes. If any event handler returns a falsey value, the close action will be canceled. */
CLOSING: 'panelClosing',
/** When the panel is being closed */
CLOSED: 'panelClosed',
/** When a persistent panel is being hidden */
PERSISTENT_CLOSED: 'panelPersistentClosed',
/** When a persistent panel is being shown */
PERSISTENT_OPENED: 'panelPersistentOpened',
/** When a custom button is clicked, See [wcPanel.addButton]{@link module:wcPanel~addButton} */
BUTTON: 'panelButton',
/** When the panel has moved from floating to a docked position */
ATTACHED: 'panelAttached',
/** When the panel has moved from a docked position to floating */
DETACHED: 'panelDetached',
/**
* When the user has started moving the panel (top-left coordinates changed)
* This event is called with an object of the current {x, y} position as the first parameter.
*/
MOVE_STARTED: 'panelMoveStarted',
/**
* When the user has finished moving the panel
* This event is called with an object of the current {x, y} position as the first parameter.
*/
MOVE_ENDED: 'panelMoveEnded',
/**
* When the top-left coordinates of the panel has changed
* This event is called with an object of the current {x, y} position as the first parameter.
*/
MOVED: 'panelMoved',
/**
* When the user has started resizing the panel (width or height changed)
* This event is called with an object of the current {width, height} size as the first parameter.
*/
RESIZE_STARTED: 'panelResizeStarted',
/**
* When the user has finished resizing the panel
* This event is called with an object of the current {width, height} size as the first parameter.
*/
RESIZE_ENDED: 'panelResizeEnded',
/**
* When the panels width or height has changed
* This event is called with an object of the current {width, height} size as the first parameter.
*/
RESIZED: 'panelResized',
/** This only happens with floating windows when the order of the windows have changed. */
ORDER_CHANGED: 'panelOrderChanged',
/** When the contents of the panel has been scrolled */
SCROLLED: 'panelScrolled',
/** When the layout is being saved, See [wcDocker.save]{@link module:wcDocker#save} */
SAVE_LAYOUT: 'layoutSave',
/** When the layout is being restored, See [wcDocker.restore]{@link module:wcDocker#restore} */
RESTORE_LAYOUT: 'layoutRestore',
/** When the current tab on a custom tab widget associated with this panel has changed, See {@link module:wcTabFrame} */
CUSTOM_TAB_CHANGED: 'customTabChanged',
/** When a tab has been closed on a custom tab widget associated with this panel, See {@link module:wcTabFrame} */
CUSTOM_TAB_CLOSED: 'customTabClosed'
};
/**
* The name of the placeholder panel.
* @private
* @memberOf module:wcDocker
* @constant {String} module:wcDocker.PANEL_PLACEHOLDER
*/
wcDocker.PANEL_PLACEHOLDER = '__wcDockerPlaceholderPanel';
/**
* Used when [adding]{@link module:wcDocker#addPanel} or [moving]{@link module:wcDocker#movePanel} a panel to designate the target location as collapsed.
* Must be used with [docking]{@link module:wcDocker.DOCK} positions LEFT, RIGHT, or BOTTOM only.
* @memberOf module:wcDocker
* @constant {String} module:wcDocker.COLLAPSED
*/
wcDocker.COLLAPSED = '__wcDockerCollapsedPanel';
/**
* Used for the splitter bar orientation.
* @version 3.0.0
* @memberOf module:wcDocker
* @enum {Boolean} module:wcDocker.ORIENTATION
*/
wcDocker.ORIENTATION = {
/** Top and Bottom panes */
VERTICAL: false,
/** Left and Right panes */
HORIZONTAL: true
};
/**
* Used to determine the position of tabbed widgets for stacked panels.
* Note: Not supported on IE8 or below.
* @version 3.0.0
* @enum {String} module:wcDocker.TAB
* @memberOf module:wcDocker
*/
wcDocker.TAB = {
/** The default, puts tabs at the top of the frame */
TOP: 'top',
/** Puts tabs on the left side of the frame */
LEFT: 'left',
/** Puts tabs on the right side of the frame */
RIGHT: 'right',
/** Puts tabs on the bottom of the frame */
BOTTOM: 'bottom'
};
return wcDocker;
});
/** @module wcBase */
define('wcDocker/base',[
"dcl/dcl"
], function(dcl) {
/**
* Base class for all docker classes
* @class module:wcBase
*/
return dcl(null, {
/**
* Returns this or the docker's options
* @TODO: better looking through the parents?
* @function module:wcBase#getOptions
* @returns {Object|null}
*/
getOptions: function() {
return this._options || this.docker()._options || {};
},
/**
* Return an option found in this or in the docker.
* @function module:wcBase#option
* @param name
* @param _default {Object|null}
* @returns {Object|null}
*/
option: function(name,_default) {
return this.getOptions()[name] || _default;
},
/**
* Class eq function
* @function module:wcBase#instanceOf
* @param {string} what
* @param {object} [who]
* @returns {boolean}
*/
instanceOf: function(what, who) {
who = who || this;
return !!(who && (who.declaredClass.indexOf(what)!=-1));
},
/**
* Retrieves the main [docker]{@link module:wcDocker} instance.
* @function module:wcBase#docker
* @returns {module:wcDocker} - The top level docker object.
*/
docker: function(startNode) {
var parent = startNode || this._parent;
while (parent && !(parent.instanceOf('wcDocker'))) {
parent = parent._parent;
}
return parent;
},
/**
* Return a module (dcl) by class name.
* @function module:wcBase#__getClass
* @param name {string} the class name, for instance "wcPanel", "wcSplitter" and so forth. Please see in wcDocker#defaultClasses for available class names.
* @returns {object} the dcl module found in options
* @private
*/
__getClass: function(name) {
return this.getOptions()[name+'Class'];
}
});
});
/** @module wcPanel */
define('wcDocker/panel',[
"dcl/dcl",
"./types",
"./base"
], function (dcl, wcDocker, base) {
/**
* @class module:wcPanel
* The public interface for the docking panel, it contains a number of convenience
* functions and layout that manages the contents of the panel.
*/
var Module = dcl(base, {
declaredClass: 'wcPanel',
/**
* @memberOf module:wcPanel
* PRIVATE - Use [wcDocker.addPanel]{@link module:wcDocker#addPanel}, [wcDocker.removePanel]{@link module:wcDocker#removePanel}, and
* [wcDocker.movePanel]{@link module:wcDocker#movePanel} to manage panels, this should never be constructed directly
* by the user.
* @param {module:wcBase} parent - The parent.
* @param {String} type - The name identifier for the panel.
* @param {module:wcPanel~options} [options] - An options object passed from registration of the panel.
*/
constructor: function (parent, type, options) {
/**
* An options object for the [panel]{@link module:wcPanel} constructor.
* @typedef module:wcPanel~options
* @property {String} [icon] - A CSS classname that represents the icon that should display on this panel's tab widget.
* @property {String} [faicon] - An icon name using the [Font-Awesome]{@link http://fortawesome.github.io/Font-Awesome/} library.
* @property {String|Boolean} [title] - A custom title to display for this panel, if false, title bar will not be shown.
* @property {Number|String} [detachToWidth=600] - Determines the new width when the panel is detached (0 = Don't change). Can be a pixel value, or a string with a 'px' or '%' suffix.
* @property {Number|String} [detachToHeight=400] - Determines the new height when the panel is detached (0 = Don't change). Can be a pixel value, or a string with a 'px' or '%' suffix.
*/
/**
* The outer container element of the panel.
* @member {external:jQuery~Object}
*/
this.$container = null;
this._parent = parent;
this.$icon = null;
this.$title = null;
this.$titleText = null;
this.$loading = null;
this._panelObject = null;
this._initialized = false;
this._collapseDirection = undefined;
this._type = type;
this._title = type;
this._titleVisible = true;
this._options = options;
this._layout = null;
this._buttonList = [];
this._actualPos = {
x: 0.5,
y: 0.5
};
this._actualSize = {
x: 0,
y: 0
};
this._resizeData = {
time: -1,
timeout: false,
delta: 150
};
this._pos = {
x: 0.5,
y: 0.5
};
this._moveData = {
time: -1,
timeout: false,
delta: 150
};
this._size = {
x: -1,
y: -1
};
this._minSize = {
x: 100,
y: 100
};
this._maxSize = {
x: Infinity,
y: Infinity
};
this._scroll = {
x: 0,
y: 0
};
this._scrollable = {
x: true,
y: true
};
this._collapsible = true;
this._overflowVisible = false;
this._moveable = true;
this._closeable = true;
this._resizeVisible = true;
this._isVisible = false;
this._events = {};
this.__init();
},
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Public Functions
///////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets, or Sets the title for this panel.
* Titles appear in the tab widget associated with the panel.
* @function module:wcPanel#title
* @param {String|Boolean} title - If supplied, sets the new title (this can be html text). If false, the title bar will be removed.
* @returns {String|Boolean} - The current title.
*/
title: function (title) {
if (typeof title !== 'undefined') {
if (title === false) {
this._titleVisible = false;
this.$titleText.html(this._type);
} else {
this._title = title;
this.$titleText.html(title);
}
if (this.$icon) {
this.$titleText.prepend(this.$icon);
}
if (this._parent && this._parent.instanceOf('wcFrame')) {
this._parent.__updateTabs();
}
}
return this._title;
},
/**
* Retrieves the registration info of the panel as declared from
* [wcDocker.registerPanelType]{@link module:wcDocker#registerPanelType};
* @function module:wcPanel#info
* @returns {module:wcDocker~registerOptions} - Registered options of the panel type.
* @see [wcDocker.panelTypeInfo]{@link module:wcDocker#panelTypeInfo}.
*/
info: function () {
return this.docker().panelTypeInfo(this._type);
},
/**
* Retrieves the layout instance.
* @function module:wcPanel#layout
* @returns {module:wcLayoutSimple|wcLayoutTable} - The layout instance.
*/
layout: function () {
return this._layout;
},
/**
* Brings this panel into focus. If it is floating, it will be moved to the front of all other panels.
* @function module:wcPanel#focus
* @param {Boolean} [flash] - If true, in addition to bringing the panel into focus, it will also flash for the user.
*/
focus: function (flash) {
var docker = this.docker();
if (docker) {
docker.__focus(this._parent, flash);
for (var i = 0; i < this._parent._panelList.length; ++i) {
if (this._parent._panelList[i] === this && this._parent._curTab !== i) {
this._parent.panel(i);
break;
}
}
}
},
/**
* @callback wcPanel~CollapseDirection
* @see module:wcPanel#collapseDirection
* @param {module:wcDocker~Bounds} bounds - The bounds of this panel relative to the wcDocker container.
* @returns {module:wcDocker.DOCK} - A collapse direction to use, must only be LEFT, RIGHT, or BOTTOM
*/
/**
* Gets, or Sets the collapse direction for this panel.
* @function module:wcPanel#collapseDirection
* @param {module:wcPanel~CollapseDirection|wcDocker.DOCK} direction - The collapse direction to use for this panel.
If this value is omitted, the default collapse direction will be used.
*/
collapseDirection: function (direction) {
this._collapseDirection = direction;
},
/**
* Retrieves whether this panel can be seen by the user.
* @function module:wcPanel#isVisible
* @returns {Boolean} - Visibility state.
*/
isVisible: function () {
return this._isVisible;
},
/**
* Retrieves whether this panel is floating.
* @function module:wcPanel#isFloating
* @returns {Boolean}
*/
isFloating: function () {
if (this._parent && this._parent.instanceOf('wcFrame')) {
return this._parent._isFloating;
}
return false;
},
/**
* Retrieves whether this panel is in focus.
* @function module:wcPanel#isInFocus
* @return {Boolean}
*/
isInFocus: function () {
var docker = this.docker();
if (docker && this._parent && this._parent.instanceOf('wcFrame')) {
return this._parent === docker._focusFrame;
}
return false;
},
/**
* Creates a new custom button that will appear in the title bar when the panel is active.
* @function module:wcPanel#addButton
* @param {String} name - The name of the button, to identify it later.
* @param {String} className - A CSS class name to apply to the button.
* @param {String} text - Text to apply to the button.
* @param {String} tip - Tooltip text for the user.
* @param {Boolean} [isTogglable] - If true, will make the button toggle on and off per click.
* @param {String} [toggleClassName] - If this button is toggleable, you can designate an optional CSS class name that will replace the original class name.
*/
addButton: function (name, className, text, tip, isTogglable, toggleClassName) {
this._buttonList.push({
name: name,
className: className,
toggleClassName: toggleClassName,
text: text,
tip: tip,
isTogglable: isTogglable,
isToggled: false
});
if (this._parent && this._parent.instanceOf('wcFrame')) {
this._parent.__update();
}
},
/**
* Removes a custom button from the panel.
* @function module:wcPanel#removeButton
* @param {String} name - The name identifier for the button to remove.
* @returns {Boolean} - Success or failure.
*/
removeButton: function (name) {
for (var i = 0; i < this._buttonList.length; ++i) {
if (this._buttonList[i].name === name) {
this._buttonList.splice(i, 1);
if (this._parent && this._parent.instanceOf('wcFrame')) {
this._parent.__onTabChange();
}
if (this._parent && this._parent.instanceOf('wcFrame')) {
this._parent.__update();
}
return true;
}
}
return false;
},
/**
* Gets, or Sets the current toggle state of a custom button that was
* added using [wcPanel.addButton]{@link module:wcPanel#addButton}.
* @function module:wcPanel#buttonState
* @param {String} name - The name identifier of the button.
* @param {Boolean} [toggleState] - If supplied, will assign a new toggle state to the button.
* @returns {Boolean} - The current toggle state of the button.
*/
buttonState: function (name, toggleState) {
for (var i = 0; i < this._buttonList.length; ++i) {
if (this._buttonList[i].name === name) {
if (typeof toggleState !== 'undefined') {
this._buttonList[i].isToggled = toggleState;
if (this._parent && this._parent.instanceOf('wcFrame')) {
this._parent.__onTabChange();
}
}
if (this._parent && this._parent.instanceOf('wcFrame')) {
this._parent.__update();
}
return this._buttonList[i].isToggled;
}
}
return false;
},
/**
* Gets, or Sets the default position of the panel if it is floating. Warning: after the panel has been initialized, this value no longer reflects the current position of the panel.
* @function module:wcPanel#initPos
* @param {Number|String} [x] - If supplied, sets the horizontal position of the floating panel. Can be a percentage position, or a string with a 'px' or '%' suffix.
* @param {Number|String} [y] - If supplied, sets the vertical position of the floating panel. Can be a percentage position, or a string with a 'px' or '%' suffix.
* @returns {module:wcDocker~Coordinate} - The current default position of the panel.
*/
initPos: function (x, y) {
if (typeof x !== 'undefined') {
var docker = this.docker();
if (docker) {
this._pos.x = docker.__stringToPercent(x, docker.$container.width());
} else {
this._pos.x = x;
}
}
if (typeof y !== 'undefined') {
var docker = this.docker();
if (docker) {
this._pos.y = docker.__stringToPercent(y, docker.$container.height());
} else {
this._pos.y = y;
}
}
return {x: this._pos.x, y: this._pos.y};
},
/**
* Gets, or Sets the desired size of the panel. Warning: after the panel has been initialized, this value no longer reflects the current size of the panel.
* @function module:wcPanel#initSize
* @param {Number|String} [x] - If supplied, sets the desired initial horizontal size of the panel. Can be a pixel position, or a string with a 'px' or '%' suffix.
* @param {Number|String} [y] - If supplied, sets the desired initial vertical size of the panel. Can be a pixel position, or a string with a 'px' or '%' suffix.
* @returns {module:wcDocker~Size} - The current initial size of the panel.
*/
initSize: function (x, y) {
if (typeof x !== 'undefined') {
var docker = this.docker();
if (docker) {
this._size.x = docker.__stringToPixel(x, docker.$container.width());
} else {
this._size.x = x;
}
}
if (typeof y !== 'undefined') {
var docker = this.docker();
if (docker) {
this._size.y = docker.__stringToPixel(y, docker.$container.height());
} else {
this._size.y = y;
}
}
return {x: this._size.x, y: this._size.y};
},
/**
* Gets, or Sets the minimum size constraint of the panel.
* @function module:wcPanel#minSize
* @param {Number|String} [x] - If supplied, sets the desired minimum horizontal size of the panel. Can be a pixel position, or a string with a 'px' or '%' suffix.
* @param {Number|String} [y] - If supplied, sets the desired minimum vertical size of the panel. Can be a pixel position, or a string with a 'px' or '%' suffix.
* @returns {module:wcDocker~Size} - The current minimum size.
*/
minSize: function (x, y) {
if (typeof x !== 'undefined') {
var docker = this.docker();
if (docker) {
this._minSize.x = docker.__stringToPixel(x, docker.$container.width());
} else {
this._minSize.x = x;
}
}
if (typeof y !== 'undefined') {
var docker = this.docker();
if (docker) {
this._minSize.y = docker.__stringToPixel(y, docker.$container.height());
} else {
this._minSize.y = y;
}
}
return {x: this._minSize.x, y: this._minSize.y};
},
/**
* Gets, or Sets the maximum size constraint of the panel.
* @function module:wcPanel#maxSize
* @param {Number|String} [x] - If supplied, sets the desired maximum horizontal size of the panel. Can be a pixel position, or a string with a 'px' or '%' suffix.
* @param {Number|String} [y] - If supplied, sets the desired maximum vertical size of the panel. Can be a pixel position, or a string with a 'px' or '%' suffix.
* @returns {module:wcDocker~Size} - The current maximum size.
*/
maxSize: function (x, y) {
if (typeof x !== 'undefined') {
var docker = this.docker();
if (docker) {
this._maxSize.x = docker.__stringToPixel(x, docker.$container.width());
} else {
this._maxSize.x = x;
}
}
if (typeof y !== 'undefined') {
var docker = this.docker();
if (docker) {
this._maxSize.y = docker.__stringToPixel(y, docker.$container.height());
} else {
this._maxSize.y = y;
}
}
return {x: this._maxSize.x, y: this._maxSize.y};
},
/**
* Retrieves the width of the panel contents.
* @function module:wcPanel#width
* @returns {Number} - Panel width.
*/
width: function () {
if (this.$container) {
return this.$container.width();
}
return 0.0;
},
/**
* Retrieves the height of the panel contents.
* @function module:wcPanel#height
* @returns {Number} - Panel height.
*/
height: function () {
if (this.$container) {
return this.$container.height();
}
return 0.0;
},
/**
* Sets the icon for the panel, shown in the panels tab widget. Must be a css class name that contains the icon.
* @function module:wcPanel#icon
* @param {String} icon - The icon class name.
*/
icon: function (icon) {
if (!this.$icon) {
this.$icon = $('