Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
292 lines
No EOL
5.9 KiB
JavaScript
Executable file
292 lines
No EOL
5.9 KiB
JavaScript
Executable file
(function(define){define(function(require,exports,module){
|
|
'use strict';
|
|
|
|
/**
|
|
* Module Dependencies
|
|
*/
|
|
|
|
var events = require('evt');
|
|
|
|
/**
|
|
* Locals
|
|
*/
|
|
|
|
var counter = 1;
|
|
var noop = function() {};
|
|
|
|
/**
|
|
* Exports
|
|
*/
|
|
|
|
module.exports = View;
|
|
|
|
/**
|
|
* Base view class. Accepts
|
|
* or creates a root element
|
|
* which we template into.
|
|
*
|
|
* @constructor
|
|
*/
|
|
function View(options) {
|
|
options = options || {};
|
|
this.el = options.el || this.el || document.createElement(this.tag);
|
|
this.el.id = this.el.id || ('view' + counter++);
|
|
this.name = options.name || this.name;
|
|
this.els = {};
|
|
|
|
if (!this.el.className) {
|
|
if (this.name) this.el.className = this.name;
|
|
if (this.className) this.el.className += ' ' + this.className;
|
|
}
|
|
|
|
bindAll(this);
|
|
this.initialize.apply(this, arguments);
|
|
}
|
|
|
|
/**
|
|
* Base view prototype,
|
|
* mixed in event emitter.
|
|
*
|
|
* @type {Object}
|
|
*/
|
|
events(View.prototype);
|
|
|
|
// Allow for 'emit' or
|
|
// 'fire' to trigger events
|
|
View.prototype.fire = View.prototype.fire || View.prototype.emit;
|
|
|
|
/**
|
|
* Default tagName
|
|
*
|
|
* @type {String}
|
|
*/
|
|
View.prototype.tag = 'div';
|
|
View.prototype.name = 'noname';
|
|
|
|
/**
|
|
* Appends the root element
|
|
* to the given parent.
|
|
*
|
|
* @param {Element} parent
|
|
* @return {View}
|
|
*/
|
|
View.prototype.appendTo = function(parent) {
|
|
if (!parent) return this;
|
|
parent.appendChild(this.el);
|
|
this.fire('inserted');
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Prepends the root element
|
|
* to the given parent.
|
|
*
|
|
* @param {Element} parent
|
|
* @return {View}
|
|
*/
|
|
View.prototype.prependTo = function(parent) {
|
|
if (!parent) return this;
|
|
var first = parent.firstChild;
|
|
|
|
if (first) parent.insertBefore(this.el, first);
|
|
else this.appendTo(parent);
|
|
|
|
this.fire('inserted');
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Convenient shorthand
|
|
* querySelector.
|
|
*
|
|
* @param {String} query
|
|
* @return { Element | null}
|
|
*/
|
|
View.prototype.find = function(query) {
|
|
return this.el.querySelector(query);
|
|
};
|
|
|
|
/**
|
|
* Removes the element from
|
|
* its current DOM location.
|
|
*
|
|
* @param {Object} options
|
|
* @return {View}
|
|
*/
|
|
View.prototype.remove = function(options) {
|
|
var silent = options && options.silent;
|
|
var parent = this.el.parentNode;
|
|
if (!parent) return this;
|
|
parent.removeChild(this.el);
|
|
if (!silent) this.fire('remove');
|
|
return this;
|
|
};
|
|
|
|
View.prototype.set = function(key, value) {
|
|
value = value === undefined ? '' : value;
|
|
this.el.setAttribute(toDashed(key), value);
|
|
};
|
|
|
|
View.prototype.get = function(key) {
|
|
return this.el.getAttribute(key);
|
|
};
|
|
|
|
/**
|
|
* Returns a function that when called
|
|
* will .set() the given key.
|
|
*
|
|
* If a value is passed to .setter(),
|
|
* that value will always be used
|
|
* when the returned function is called.
|
|
* Else the value passed to the given
|
|
* function will be used.
|
|
*
|
|
* Example:
|
|
*
|
|
* var setter = this.setter('key', 'value');
|
|
* setter(); //=> this.set('key', 'value');
|
|
* setter('value2'); //=> this.set('key', 'value');
|
|
*
|
|
* var setter = this.setter('key');
|
|
* setter('value'); //=> this.set('key', 'value');
|
|
* setter(); //=> this.set('key');
|
|
*
|
|
* @param {String} key
|
|
* @param {*} value
|
|
* @return {Function}
|
|
*/
|
|
View.prototype.setter = function(key, forced) {
|
|
var self = this;
|
|
return function(passed) {
|
|
var value = forced !== undefined ? forced : passed;
|
|
self.set(key, value);
|
|
};
|
|
};
|
|
|
|
View.prototype.enable = function(key, value) {
|
|
switch(arguments.length) {
|
|
case 0:
|
|
value = true;
|
|
key = 'enabled';
|
|
break;
|
|
case 1:
|
|
if (typeof key === 'boolean') {
|
|
value = key;
|
|
key = 'enabled';
|
|
} else {
|
|
value = true;
|
|
key = key ? key + '-enabled' : 'enabled';
|
|
}
|
|
break;
|
|
default:
|
|
key = key ? key + '-enabled' : 'enabled';
|
|
}
|
|
this.set(key, !!value);
|
|
};
|
|
|
|
View.prototype.disable = function(key) {
|
|
this.enable(key, false);
|
|
};
|
|
|
|
View.prototype.enabler = function(key) {
|
|
return (function(value) { this.enable(key, value); }).bind(this);
|
|
};
|
|
|
|
View.prototype.hide = function(key) {
|
|
this.toggle(key, false);
|
|
};
|
|
|
|
View.prototype.show = function(key) {
|
|
this.toggle(key, true);
|
|
};
|
|
|
|
View.prototype.toggle = function(key, value) {
|
|
if (arguments.length === 1 && typeof key === 'boolean') {
|
|
value = key;
|
|
key = '';
|
|
} else {
|
|
key = key ? key + '-' : '';
|
|
}
|
|
|
|
this.el.classList.toggle(key + 'hidden', !value);
|
|
this.el.classList.toggle(key + 'visible', value);
|
|
};
|
|
|
|
/**
|
|
* Removes the element from
|
|
* it's current context, firing
|
|
* a 'destroy' event to allow
|
|
* views to perform cleanup.
|
|
*
|
|
* Then clears any internal
|
|
* references to aid GC.
|
|
*
|
|
* @return {[type]} [description]
|
|
*/
|
|
View.prototype.destroy = function(options) {
|
|
var noRemove = options && options.noRemove;
|
|
if (!noRemove) this.remove();
|
|
this.fire('destroy');
|
|
this.el = null;
|
|
};
|
|
|
|
View.prototype.toString = function() {
|
|
return '[object View]';
|
|
};
|
|
|
|
// Overwrite as required
|
|
View.prototype.initialize = noop;
|
|
View.prototype.template = function() { return ''; };
|
|
|
|
/**
|
|
* Extends the base view
|
|
* class with the given
|
|
* properties.
|
|
*
|
|
* TODO: Pull this out to
|
|
* standalone module.
|
|
*
|
|
* @param {Object} properties
|
|
* @return {Function}
|
|
*/
|
|
View.extend = function(props) {
|
|
var Parent = this;
|
|
|
|
// The extended constructor
|
|
// calls the parent constructor
|
|
var Child = function() {
|
|
Parent.apply(this, arguments);
|
|
};
|
|
|
|
Child.prototype = Object.create(Parent.prototype);
|
|
Child.extend = View.extend;
|
|
mixin(Child.prototype, props);
|
|
|
|
return Child;
|
|
};
|
|
|
|
function toDashed(s) {
|
|
return s.replace(/\W+/g, '-')
|
|
.replace(/([a-z\d])([A-Z])/g, '$1-$2')
|
|
.toLowerCase();
|
|
}
|
|
|
|
function mixin(a, b) {
|
|
for (var key in b) { a[key] = b[key]; }
|
|
return a;
|
|
}
|
|
|
|
function bindAll(object) {
|
|
var key;
|
|
var fn;
|
|
for (key in object) {
|
|
fn = object[key];
|
|
if (typeof fn === 'function') {
|
|
object[key] = fn.bind(object);
|
|
}
|
|
}
|
|
}
|
|
|
|
});})((function(n,w){return typeof define=='function'&&define.amd?
|
|
define:typeof module=='object'?function(c){c(require,exports,module);}:function(c){
|
|
var m={exports:{}},r=function(n){return w[n];};w[n]=c(r,m.exports,m)||m.exports;};})('view',this)); |