3m5-coco
Advanced tools
Comparing version 0.2.0 to 0.3.0
# Coco changelog | ||
## 0.3.0 | ||
- Use Babel 7 with preset env | ||
## 0.2.0 | ||
@@ -4,0 +8,0 @@ |
@@ -91,4 +91,9 @@ var gulp = require('gulp'), | ||
.pipe(babel({ | ||
presets: ['es2015', 'stage-2', 'stage-3'], | ||
plugins: ['es6-promise'] | ||
presets: [ | ||
['@babel/env', { | ||
useBuiltIns: 'entry', | ||
corejs: 'core-js@2', | ||
modules: 'cjs', | ||
}] | ||
] | ||
})) | ||
@@ -95,0 +100,0 @@ .pipe(gulp.dest('lib/')); |
"use strict"; | ||
require("core-js/modules/es6.array.copy-within"); | ||
require("core-js/modules/es6.array.fill"); | ||
require("core-js/modules/es6.array.find"); | ||
require("core-js/modules/es6.array.find-index"); | ||
require("core-js/modules/es7.array.flat-map"); | ||
require("core-js/modules/es6.array.from"); | ||
require("core-js/modules/es7.array.includes"); | ||
require("core-js/modules/es6.array.iterator"); | ||
require("core-js/modules/es6.array.of"); | ||
require("core-js/modules/es6.array.sort"); | ||
require("core-js/modules/es6.array.species"); | ||
require("core-js/modules/es6.date.to-primitive"); | ||
require("core-js/modules/es6.function.has-instance"); | ||
require("core-js/modules/es6.function.name"); | ||
require("core-js/modules/es6.map"); | ||
require("core-js/modules/es6.math.acosh"); | ||
require("core-js/modules/es6.math.asinh"); | ||
require("core-js/modules/es6.math.atanh"); | ||
require("core-js/modules/es6.math.cbrt"); | ||
require("core-js/modules/es6.math.clz32"); | ||
require("core-js/modules/es6.math.cosh"); | ||
require("core-js/modules/es6.math.expm1"); | ||
require("core-js/modules/es6.math.fround"); | ||
require("core-js/modules/es6.math.hypot"); | ||
require("core-js/modules/es6.math.imul"); | ||
require("core-js/modules/es6.math.log1p"); | ||
require("core-js/modules/es6.math.log10"); | ||
require("core-js/modules/es6.math.log2"); | ||
require("core-js/modules/es6.math.sign"); | ||
require("core-js/modules/es6.math.sinh"); | ||
require("core-js/modules/es6.math.tanh"); | ||
require("core-js/modules/es6.math.trunc"); | ||
require("core-js/modules/es6.number.constructor"); | ||
require("core-js/modules/es6.number.epsilon"); | ||
require("core-js/modules/es6.number.is-finite"); | ||
require("core-js/modules/es6.number.is-integer"); | ||
require("core-js/modules/es6.number.is-nan"); | ||
require("core-js/modules/es6.number.is-safe-integer"); | ||
require("core-js/modules/es6.number.max-safe-integer"); | ||
require("core-js/modules/es6.number.min-safe-integer"); | ||
require("core-js/modules/es6.number.parse-float"); | ||
require("core-js/modules/es6.number.parse-int"); | ||
require("core-js/modules/es6.object.assign"); | ||
require("core-js/modules/es7.object.define-getter"); | ||
require("core-js/modules/es7.object.define-setter"); | ||
require("core-js/modules/es7.object.entries"); | ||
require("core-js/modules/es6.object.freeze"); | ||
require("core-js/modules/es6.object.get-own-property-descriptor"); | ||
require("core-js/modules/es7.object.get-own-property-descriptors"); | ||
require("core-js/modules/es6.object.get-own-property-names"); | ||
require("core-js/modules/es6.object.get-prototype-of"); | ||
require("core-js/modules/es7.object.lookup-getter"); | ||
require("core-js/modules/es7.object.lookup-setter"); | ||
require("core-js/modules/es6.object.prevent-extensions"); | ||
require("core-js/modules/es6.object.to-string"); | ||
require("core-js/modules/es6.object.is"); | ||
require("core-js/modules/es6.object.is-frozen"); | ||
require("core-js/modules/es6.object.is-sealed"); | ||
require("core-js/modules/es6.object.is-extensible"); | ||
require("core-js/modules/es6.object.keys"); | ||
require("core-js/modules/es6.object.seal"); | ||
require("core-js/modules/es6.object.set-prototype-of"); | ||
require("core-js/modules/es7.object.values"); | ||
require("core-js/modules/es6.promise"); | ||
require("core-js/modules/es7.promise.finally"); | ||
require("core-js/modules/es6.reflect.apply"); | ||
require("core-js/modules/es6.reflect.construct"); | ||
require("core-js/modules/es6.reflect.define-property"); | ||
require("core-js/modules/es6.reflect.delete-property"); | ||
require("core-js/modules/es6.reflect.get"); | ||
require("core-js/modules/es6.reflect.get-own-property-descriptor"); | ||
require("core-js/modules/es6.reflect.get-prototype-of"); | ||
require("core-js/modules/es6.reflect.has"); | ||
require("core-js/modules/es6.reflect.is-extensible"); | ||
require("core-js/modules/es6.reflect.own-keys"); | ||
require("core-js/modules/es6.reflect.prevent-extensions"); | ||
require("core-js/modules/es6.reflect.set"); | ||
require("core-js/modules/es6.reflect.set-prototype-of"); | ||
require("core-js/modules/es6.regexp.constructor"); | ||
require("core-js/modules/es6.regexp.flags"); | ||
require("core-js/modules/es6.regexp.match"); | ||
require("core-js/modules/es6.regexp.replace"); | ||
require("core-js/modules/es6.regexp.split"); | ||
require("core-js/modules/es6.regexp.search"); | ||
require("core-js/modules/es6.regexp.to-string"); | ||
require("core-js/modules/es6.set"); | ||
require("core-js/modules/es6.symbol"); | ||
require("core-js/modules/es7.symbol.async-iterator"); | ||
require("core-js/modules/es6.string.anchor"); | ||
require("core-js/modules/es6.string.big"); | ||
require("core-js/modules/es6.string.blink"); | ||
require("core-js/modules/es6.string.bold"); | ||
require("core-js/modules/es6.string.code-point-at"); | ||
require("core-js/modules/es6.string.ends-with"); | ||
require("core-js/modules/es6.string.fixed"); | ||
require("core-js/modules/es6.string.fontcolor"); | ||
require("core-js/modules/es6.string.fontsize"); | ||
require("core-js/modules/es6.string.from-code-point"); | ||
require("core-js/modules/es6.string.includes"); | ||
require("core-js/modules/es6.string.italics"); | ||
require("core-js/modules/es6.string.iterator"); | ||
require("core-js/modules/es6.string.link"); | ||
require("core-js/modules/es7.string.pad-start"); | ||
require("core-js/modules/es7.string.pad-end"); | ||
require("core-js/modules/es6.string.raw"); | ||
require("core-js/modules/es6.string.repeat"); | ||
require("core-js/modules/es6.string.small"); | ||
require("core-js/modules/es6.string.starts-with"); | ||
require("core-js/modules/es6.string.strike"); | ||
require("core-js/modules/es6.string.sub"); | ||
require("core-js/modules/es6.string.sup"); | ||
require("core-js/modules/es7.string.trim-left"); | ||
require("core-js/modules/es7.string.trim-right"); | ||
require("core-js/modules/es6.typed.array-buffer"); | ||
require("core-js/modules/es6.typed.int8-array"); | ||
require("core-js/modules/es6.typed.uint8-array"); | ||
require("core-js/modules/es6.typed.uint8-clamped-array"); | ||
require("core-js/modules/es6.typed.int16-array"); | ||
require("core-js/modules/es6.typed.uint16-array"); | ||
require("core-js/modules/es6.typed.int32-array"); | ||
require("core-js/modules/es6.typed.uint32-array"); | ||
require("core-js/modules/es6.typed.float32-array"); | ||
require("core-js/modules/es6.typed.float64-array"); | ||
require("core-js/modules/es6.weak-map"); | ||
require("core-js/modules/es6.weak-set"); | ||
require("core-js/modules/web.timers"); | ||
require("core-js/modules/web.immediate"); | ||
require("core-js/modules/web.dom.iterable"); | ||
require("regenerator-runtime/runtime"); | ||
// Rewrite modern console methods for olders browsers (like IE 9/10) | ||
if (!window.console) { | ||
window.console = {}; | ||
window.console = {}; | ||
} | ||
if (!window.console.debug) { | ||
window.console.debug = window.console.log || function () {}; | ||
window.console.debug = window.console.log || function () {}; | ||
} | ||
if (!window.console.error) { | ||
window.console.error = window.console.log || function () {}; | ||
window.console.error = window.console.log || function () {}; | ||
} | ||
if (!window.console.warn) { | ||
window.console.warn = window.console.log || function () {}; | ||
} | ||
window.console.warn = window.console.log || function () {}; | ||
} //IE support | ||
//IE support | ||
var Event = Event || window.Event; | ||
Event.prototype.stopPropagation = Event.prototype.stopPropagation || function () { | ||
this.cancelBubble = true; | ||
this.cancelBubble = true; | ||
}; | ||
Event.prototype.preventDefault = Event.prototype.preventDefault || function () { | ||
this.returnValue = false; | ||
}; | ||
this.returnValue = false; | ||
}; //add $compute function to all functions | ||
//add $compute function to all functions | ||
/** $compute function to register change listeners to properties in Coco.Model */ | ||
if (!Function.prototype.$compute) { | ||
Function.prototype.$compute = function () { | ||
var fn = this; | ||
var args = Array.prototype.slice.call(arguments); | ||
Function.prototype.$compute = function () { | ||
var fn = this; | ||
var args = Array.prototype.slice.call(arguments); | ||
/** | ||
* We capsule the function and the $compute properties, because our this context is the function and not the | ||
* model. When the model gets instantiated we call this returned function with the model context, set the observers | ||
* and return the original function (with assigned model context) back to the initial model property. | ||
*/ | ||
/** | ||
* We capsule the function and the $compute properties, because our this context is the function and not the | ||
* model. When the model gets instantiated we call this returned function with the model context, set the observers | ||
* and return the original function (with assigned model context) back to the initial model property. | ||
*/ | ||
var retFn = function retFn(targetAttribute, observers) { | ||
for (var i = 0; i < args.length; i++) { | ||
observers.push({ | ||
attribute: args[i], | ||
target: targetAttribute, | ||
old: fn.call(this) | ||
}); | ||
} | ||
var retFn = function retFn(targetAttribute, observers) { | ||
for (var i = 0; i < args.length; i++) { | ||
observers.push({ | ||
attribute: args[i], | ||
target: targetAttribute, | ||
old: fn.call(this) | ||
}); | ||
} | ||
return fn.$bind(this); | ||
}; | ||
return fn.$bind(this); | ||
}; // Assign a flag to the function, that we can distinct between normal functions as attributes and computed properties. | ||
// Assign a flag to the function, that we can distinct between normal functions as attributes and computed properties. | ||
retFn.isComputed = true; | ||
return retFn; | ||
}; | ||
} | ||
retFn.isComputed = true; | ||
return retFn; | ||
}; | ||
} // Dependencies | ||
// Dependencies | ||
var Coco = Coco || {}; | ||
@@ -65,15 +325,13 @@ | ||
$ = require("jquery"); | ||
window.$ = $; | ||
window.jQuery = $; | ||
window.jQuery = $; //require non public Coco classes | ||
//use babel-polyfill for IE support | ||
require("babel-polyfill"); | ||
require("./service/Coco.ServiceContainer.js"); | ||
//require non public Coco classes | ||
require("./service/Coco.ServiceContainer.js"); | ||
require("./helpers/HandlebarsHelpers.js"); | ||
require("./router/Coco.RouterService.js"); | ||
var Translator = require("./lib/Coco.Translator.js"); | ||
/** | ||
@@ -104,96 +362,86 @@ * Class: .Coco | ||
*/ | ||
Coco.SDK = dejavu.Class.declare({ | ||
$name: "Coco.Init", | ||
//////////////////////////////////////////////////////////// | ||
//////// CONFIGURATION | ||
config: { | ||
baseUrl: "/", //server context path | ||
router: { | ||
loaderDelay: 300 // When views are swapped by Router, this time adjusts when the loading class | ||
}, | ||
restService: { //restService configuration | ||
path: "rest/", //restService path | ||
cacheGet: 0 //cache time in SECONDS for GET Requests of same url, value lower than 0 causes unlimited cache | ||
} | ||
}, | ||
//////// CLASS DEFINITIONS | ||
Event: require("./event/Coco.Event.js"), | ||
ModelEvent: require("./event/Coco.ModelEvent.js"), | ||
RestServiceEvent: require("./event/Coco.RestServiceEvent.js"), | ||
RouterEvent: require("./event/Coco.RouterEvent.js"), | ||
TranslatorEvent: require("./event/Coco.TranslatorEvent.js"), | ||
ViewEvent: require("./event/Coco.ViewEvent.js"), | ||
Coco.SDK = dejavu.Class.declare({ | ||
$name: "Coco.Init", | ||
//////////////////////////////////////////////////////////// | ||
//////// CONFIGURATION | ||
config: { | ||
baseUrl: "/", | ||
//server context path | ||
router: { | ||
loaderDelay: 300 // When views are swapped by Router, this time adjusts when the loading class | ||
EventDispatcher: require("./event/Coco.EventDispatcher.js"), | ||
}, | ||
restService: { | ||
//restService configuration | ||
path: "rest/", | ||
//restService path | ||
cacheGet: 0 //cache time in SECONDS for GET Requests of same url, value lower than 0 causes unlimited cache | ||
//PACKAGE MODEL | ||
Model: require("./model/Coco.Model.js"), | ||
Collection: require("./model/Coco.Collection.js"), | ||
} | ||
}, | ||
//////// CLASS DEFINITIONS | ||
Event: require("./event/Coco.Event.js"), | ||
ModelEvent: require("./event/Coco.ModelEvent.js"), | ||
RestServiceEvent: require("./event/Coco.RestServiceEvent.js"), | ||
RouterEvent: require("./event/Coco.RouterEvent.js"), | ||
TranslatorEvent: require("./event/Coco.TranslatorEvent.js"), | ||
ViewEvent: require("./event/Coco.ViewEvent.js"), | ||
EventDispatcher: require("./event/Coco.EventDispatcher.js"), | ||
//PACKAGE MODEL | ||
Model: require("./model/Coco.Model.js"), | ||
Collection: require("./model/Coco.Collection.js"), | ||
//PACKAGE SERVICE | ||
Service: require("./service/Coco.Service.js"), | ||
ServiceProvider: require("./service/Coco.ServiceProvider.js"), | ||
//PACKAGE ROUTER | ||
Router: require("./router/Coco.Router.js"), | ||
//REST | ||
BaseRestService: require("./service/Coco.BaseRestService.js"), | ||
//PACKAGE LIB | ||
Math: require("./lib/Coco.Math.js"), | ||
Utils: require("./lib/Coco.Utils.js"), | ||
Storage: require("./lib/Coco.Storage.js"), | ||
StringUtils: require("./lib/Coco.StringUtils.js"), | ||
URLHelper: require("./lib/Coco.URLHelper.js"), | ||
//PACKAGE VIEW | ||
View: require("./view/Coco.View.js"), | ||
ChildView: require("./view/Coco.ChildView.js"), | ||
//i18n Translator | ||
Translator: new Translator(), | ||
//////// CLASS DEFINITIONS END | ||
//////////////////////////////////////////////////////////// | ||
$statics: { | ||
version: "0.3.0", | ||
initialized: false | ||
}, | ||
initialize: function initialize() { | ||
console.logWithDate = true; | ||
//PACKAGE SERVICE | ||
Service: require("./service/Coco.Service.js"), | ||
ServiceProvider: require("./service/Coco.ServiceProvider.js"), | ||
try { | ||
Handlebars; | ||
} catch (error) { | ||
console.error(error); | ||
throw new Error("Missing Handlebars! include npm-module 'handlebars' into your project!"); | ||
} | ||
//PACKAGE ROUTER | ||
Router: require("./router/Coco.Router.js"), | ||
try { | ||
$; | ||
} catch (error) { | ||
console.error(error); | ||
throw new Error("Missing jQuery! Install jQuery to use Coco.SDK ", error); | ||
} | ||
//REST | ||
BaseRestService: require("./service/Coco.BaseRestService.js"), | ||
//PACKAGE LIB | ||
Math: require("./lib/Coco.Math.js"), | ||
Utils: require("./lib/Coco.Utils.js"), | ||
Storage: require("./lib/Coco.Storage.js"), | ||
StringUtils: require("./lib/Coco.StringUtils.js"), | ||
URLHelper: require("./lib/Coco.URLHelper.js"), | ||
//PACKAGE VIEW | ||
View: require("./view/Coco.View.js"), | ||
ChildView: require("./view/Coco.ChildView.js"), | ||
//i18n Translator | ||
Translator: new Translator(), | ||
//////// CLASS DEFINITIONS END | ||
//////////////////////////////////////////////////////////// | ||
$statics: { | ||
version: "0.2.0", | ||
initialized: false | ||
}, | ||
initialize: function initialize() { | ||
console.logWithDate = true; | ||
try { | ||
Handlebars; | ||
} catch (error) { | ||
console.error(error); | ||
throw new Error("Missing Handlebars! include npm-module 'handlebars' into your project!"); | ||
} | ||
try { | ||
$; | ||
} catch (error) { | ||
console.error(error); | ||
throw new Error("Missing jQuery! Install jQuery to use Coco.SDK ", error); | ||
} | ||
console.debug("-------------------------------------------"); | ||
console.debug("Coco.js v" + this.$static.version + " initialized. Coco.config on startup: ", $.extend({}, this.config)); | ||
console.debug("Bugreport@ GitHub: https://github.com/3m5/coco/issues"); | ||
console.debug("Handlebars v" + Handlebars.VERSION); | ||
console.debug("registered Handlebars helpers: ", Handlebars.helpers); | ||
console.debug("jQuery v" + $().jquery); | ||
console.debug("-------------------------------------------"); | ||
$("body").trigger(this.Event.INITIALIZED); | ||
this.initialized = true; | ||
} | ||
console.debug("-------------------------------------------"); | ||
console.debug("Coco.js v" + this.$static.version + " initialized. Coco.config on startup: ", $.extend({}, this.config)); | ||
console.debug("Bugreport@ GitHub: https://github.com/3m5/coco/issues"); | ||
console.debug("Handlebars v" + Handlebars.VERSION); | ||
console.debug("registered Handlebars helpers: ", Handlebars.helpers); | ||
console.debug("jQuery v" + $().jquery); | ||
console.debug("-------------------------------------------"); | ||
$("body").trigger(this.Event.INITIALIZED); | ||
this.initialized = true; | ||
} | ||
}); | ||
module.exports = new Coco.SDK(); |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -29,3 +29,2 @@ /** | ||
data: null, | ||
//available types are: | ||
@@ -38,2 +37,3 @@ $constants: { | ||
INITIALIZED: 'coco:initialized', | ||
/** | ||
@@ -44,2 +44,3 @@ * Event: ADD | ||
ADD: 'coco:add', | ||
/** | ||
@@ -50,2 +51,3 @@ * Event: AUTHORIZATION_FAILED | ||
AUTHORIZATION_FAILED: 'coco:authorization_failed', | ||
/** | ||
@@ -56,2 +58,3 @@ * Event: CHANGE | ||
CHANGE: 'coco:change', | ||
/** | ||
@@ -62,2 +65,3 @@ * Event: CHANGE_KEY | ||
CHANGE_KEY: 'coco:change:', | ||
/** | ||
@@ -68,2 +72,3 @@ * Event: DESTROY | ||
DESTROY: 'coco:destroy', | ||
/** | ||
@@ -74,2 +79,3 @@ * Event: INTERNAL_SERVER_ERROR | ||
INTERNAL_SERVER_ERROR: 'coco:internal_server_error', | ||
/** | ||
@@ -80,2 +86,3 @@ * Event: INVALID | ||
INVALID: 'coco:invalid', | ||
/** | ||
@@ -86,2 +93,3 @@ * Event: REMOVE | ||
REMOVE: 'coco:remove', | ||
/** | ||
@@ -92,2 +100,3 @@ * Event: RENDER | ||
RENDER: 'coco:render', | ||
/** | ||
@@ -98,2 +107,3 @@ * Event: RESET | ||
RESET: 'coco:reset', | ||
/** | ||
@@ -104,2 +114,3 @@ * Event: REST_SERVER_ERROR | ||
REST_SERVER_ERROR: 'coco:rest-server-error', | ||
/** | ||
@@ -110,2 +121,3 @@ * Event: SORTED | ||
SORTED: 'coco:sorted', | ||
/** | ||
@@ -112,0 +124,0 @@ * Event: VALID |
"use strict"; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
@@ -16,270 +16,276 @@ /** | ||
module.exports = dejavu.Class.declare({ | ||
$name: "Coco.EventDispatcher", | ||
$name: "Coco.EventDispatcher", | ||
/** | ||
* Private map of listeners. | ||
*/ | ||
__listeners: {}, | ||
/** | ||
* Private map of listeners. | ||
*/ | ||
__listeners: {}, | ||
$abstracts: { | ||
/** | ||
* Function: {abstract} getId() | ||
* | ||
* returns unique identifier for inheritance, it's needed to get unique event context | ||
* | ||
* If you inherit from Coco.Event you always have to implement this function. | ||
* | ||
* @returns: {String} uid | ||
*/ | ||
getId: function getId() {} | ||
}, | ||
$abstracts: { | ||
/** | ||
* Function: {abstract} getId() | ||
/** | ||
* Ctor. | ||
*/ | ||
initialize: function initialize() {}, | ||
/** | ||
* Function: addEventListener | ||
* | ||
* returns unique identifier for inheritance, it's needed to get unique event context | ||
* Description: | ||
* Adds an event listener to this class. Save the returned event listener handle for removing this listener again. | ||
* | ||
* If you inherit from Coco.Event you always have to implement this function. | ||
* Parameter: | ||
* @param {string} eventType - The event type to listen to | ||
* | ||
* @returns: {String} uid | ||
* @param {Function} listener - The event listener function | ||
* | ||
* @param {boolean} $once - Flag if the listener should only listen for first event | ||
* | ||
* Return: | ||
* @returns {Symbol} listener handle for removing event listeners again | ||
*/ | ||
getId: function getId() {} | ||
}, | ||
addEventListener: function addEventListener(eventType, listener, $once) { | ||
if (eventType == null) { | ||
throw new Error("Missing eventType parameter in " + this.$name + ".addEventListener", _typeof(eventType), eventType); | ||
} | ||
/** | ||
* Ctor. | ||
*/ | ||
initialize: function initialize() {}, | ||
if (typeof eventType !== 'string') { | ||
throw new Error("Invalid eventType parameter in " + this.$name + ".addEventListener ", _typeof(eventType), eventType); | ||
} | ||
/** | ||
* Function: addEventListener | ||
* | ||
* Description: | ||
* Adds an event listener to this class. Save the returned event listener handle for removing this listener again. | ||
* | ||
* Parameter: | ||
* @param {string} eventType - The event type to listen to | ||
* | ||
* @param {Function} listener - The event listener function | ||
* | ||
* @param {boolean} $once - Flag if the listener should only listen for first event | ||
* | ||
* Return: | ||
* @returns {Symbol} listener handle for removing event listeners again | ||
*/ | ||
addEventListener: function addEventListener(eventType, listener, $once) { | ||
if (eventType == null) { | ||
throw new Error("Missing eventType parameter in " + this.$name + ".addEventListener", typeof eventType === "undefined" ? "undefined" : _typeof(eventType), eventType); | ||
} | ||
if (typeof eventType !== 'string') { | ||
throw new Error("Invalid eventType parameter in " + this.$name + ".addEventListener ", typeof eventType === "undefined" ? "undefined" : _typeof(eventType), eventType); | ||
} | ||
if (listener == null) { | ||
throw new Error("Missing listener parameter in " + this.$name + ".addEventListener"); | ||
} | ||
if (typeof listener !== 'function') { | ||
throw new Error("Invalid listener parameter in " + this.$name + ".addEventListener"); | ||
} | ||
if (listener == null) { | ||
throw new Error("Missing listener parameter in " + this.$name + ".addEventListener"); | ||
} | ||
// create unique handle by ES6 Symbol | ||
var handle = Symbol(); | ||
if (typeof listener !== 'function') { | ||
throw new Error("Invalid listener parameter in " + this.$name + ".addEventListener"); | ||
} // create unique handle by ES6 Symbol | ||
// create array of listeners if not exists yet | ||
if (!$.isArray(this.__listeners[eventType])) { | ||
this.__listeners[eventType] = []; | ||
} | ||
// create listener object | ||
var listenerObject = { | ||
handle: handle, | ||
listener: listener | ||
}; | ||
var handle = Symbol(); // create array of listeners if not exists yet | ||
if ($once) { | ||
listenerObject.once = true; | ||
} | ||
this.__listeners[eventType].push(listenerObject); | ||
if (!$.isArray(this.__listeners[eventType])) { | ||
this.__listeners[eventType] = []; | ||
} // create listener object | ||
return handle; | ||
}, | ||
/** | ||
* Function: addOnceEventListener | ||
* | ||
* Adds an event listener to this class that will only be called on first event. Save the returned event listener handle for removing this listener again. | ||
* | ||
* Parameter: | ||
* @param {string} eventType - The event type to listen to | ||
* | ||
* @param {Function} listener - The event listener function | ||
* | ||
* Return: | ||
* @returns {number} listener handle for removing event listeners again | ||
*/ | ||
addOnceEventListener: function addOnceEventListener(eventType, listener) { | ||
return this.addEventListener(eventType, listener, true); | ||
}, | ||
var listenerObject = { | ||
handle: handle, | ||
listener: listener | ||
}; | ||
/** | ||
* Function: removeAllEventListener | ||
* | ||
* Removes all event listener from this class. | ||
*/ | ||
removeAllEventListener: function removeAllEventListener() { | ||
delete this.__listeners; | ||
this.__listeners = {}; | ||
}, | ||
if ($once) { | ||
listenerObject.once = true; | ||
} | ||
this.__listeners[eventType].push(listenerObject); | ||
/** | ||
* Function: removeEventListener | ||
* | ||
* Removes an event listener from this class. If there is no such event listener the method does nothing. | ||
* | ||
* Parameter: | ||
* @param {Symbol|String} handle - The event type to remove all event listeners for or the event handle to remove a specific event listener. | ||
*/ | ||
removeEventListener: function removeEventListener(eventTypeOrHandle) { | ||
if (eventTypeOrHandle == null) { | ||
throw new Error("Missing parameter in " + this.$name + ".removeEventListener"); | ||
} | ||
if (typeof eventTypeOrHandle === 'string') { | ||
this.__removeEventListenerByEventType(eventTypeOrHandle); | ||
} else if ((typeof eventTypeOrHandle === "undefined" ? "undefined" : _typeof(eventTypeOrHandle)) === "symbol") { | ||
this.__removeEventListenerByHandle(eventTypeOrHandle); | ||
} else if ((typeof eventTypeOrHandle === "undefined" ? "undefined" : _typeof(eventTypeOrHandle)) === "object" && ("" + eventTypeOrHandle).indexOf("Symbol()") > -1) { | ||
//for older browsers | ||
this.__removeEventListenerByHandle(eventTypeOrHandle); | ||
} else { | ||
console.error(this.$name + ".removeEventListener - Parameter: ", eventTypeOrHandle); | ||
throw new Error("Invalid parameter in " + this.$name + ".removeEventListener"); | ||
} | ||
}, | ||
return handle; | ||
}, | ||
/** | ||
* Function: hasEventListener | ||
* | ||
* Checks if there is an event listener for the given event type. | ||
* | ||
* Parameter: | ||
* @param {string} eventType - The event type to check for event listeners. | ||
* | ||
* Return: | ||
* @returns {boolean} true if the event dispatcher has event listeners for the given event type | ||
*/ | ||
hasEventListener: function hasEventListener(eventType) { | ||
if (eventType == null) { | ||
throw new Error("Missing eventType parameter in " + this.$name + ".hasEventListener", typeof eventType === "undefined" ? "undefined" : _typeof(eventType), eventType); | ||
} | ||
if (typeof eventType !== 'string') { | ||
throw new Error("Invalid eventType parameter in " + this.$name + ".hasEventListener", typeof eventType === "undefined" ? "undefined" : _typeof(eventType), eventType); | ||
} | ||
/** | ||
* Function: addOnceEventListener | ||
* | ||
* Adds an event listener to this class that will only be called on first event. Save the returned event listener handle for removing this listener again. | ||
* | ||
* Parameter: | ||
* @param {string} eventType - The event type to listen to | ||
* | ||
* @param {Function} listener - The event listener function | ||
* | ||
* Return: | ||
* @returns {number} listener handle for removing event listeners again | ||
*/ | ||
addOnceEventListener: function addOnceEventListener(eventType, listener) { | ||
return this.addEventListener(eventType, listener, true); | ||
}, | ||
return $.isArray(this.__listeners[eventType]) && this.__listeners[eventType].length > 0; | ||
}, | ||
/** | ||
* Function: removeAllEventListener | ||
* | ||
* Removes all event listener from this class. | ||
*/ | ||
removeAllEventListener: function removeAllEventListener() { | ||
delete this.__listeners; | ||
this.__listeners = {}; | ||
}, | ||
/** | ||
* Function: __removeEventListenerByEventType | ||
* | ||
* Removes all event listener with for the given event type from this class. | ||
* | ||
* Parameter: | ||
* @param {string} eventType - The event type to remove all event listeners for. | ||
*/ | ||
__removeEventListenerByEventType: function __removeEventListenerByEventType(eventType) { | ||
// check if we have event listeners | ||
if (this.__listeners[eventType] == null || this.__listeners[eventType].length == 0) { | ||
return; | ||
} | ||
/** | ||
* Function: removeEventListener | ||
* | ||
* Removes an event listener from this class. If there is no such event listener the method does nothing. | ||
* | ||
* Parameter: | ||
* @param {Symbol|String} handle - The event type to remove all event listeners for or the event handle to remove a specific event listener. | ||
*/ | ||
removeEventListener: function removeEventListener(eventTypeOrHandle) { | ||
if (eventTypeOrHandle == null) { | ||
throw new Error("Missing parameter in " + this.$name + ".removeEventListener"); | ||
} | ||
delete this.__listeners[eventType]; | ||
}, | ||
if (typeof eventTypeOrHandle === 'string') { | ||
this.__removeEventListenerByEventType(eventTypeOrHandle); | ||
} else if (_typeof(eventTypeOrHandle) === "symbol") { | ||
this.__removeEventListenerByHandle(eventTypeOrHandle); | ||
} else if (_typeof(eventTypeOrHandle) === "object" && ("" + eventTypeOrHandle).indexOf("Symbol()") > -1) { | ||
//for older browsers | ||
this.__removeEventListenerByHandle(eventTypeOrHandle); | ||
} else { | ||
console.error(this.$name + ".removeEventListener - Parameter: ", eventTypeOrHandle); | ||
throw new Error("Invalid parameter in " + this.$name + ".removeEventListener"); | ||
} | ||
}, | ||
/** | ||
* Function: __removeEventListenerByHandle | ||
* | ||
* Removes an event listener with the given handle from this class. | ||
* | ||
* Parameter: | ||
* @param {number} handle - The event listener handle to remove. | ||
*/ | ||
__removeEventListenerByHandle: function __removeEventListenerByHandle(handle) { | ||
// iterate over all event types | ||
for (var eventType in this.__listeners) { | ||
var listeners = this.__listeners[eventType]; | ||
/** | ||
* Function: hasEventListener | ||
* | ||
* Checks if there is an event listener for the given event type. | ||
* | ||
* Parameter: | ||
* @param {string} eventType - The event type to check for event listeners. | ||
* | ||
* Return: | ||
* @returns {boolean} true if the event dispatcher has event listeners for the given event type | ||
*/ | ||
hasEventListener: function hasEventListener(eventType) { | ||
if (eventType == null) { | ||
throw new Error("Missing eventType parameter in " + this.$name + ".hasEventListener", _typeof(eventType), eventType); | ||
} | ||
// iterate over all listeners for this event type | ||
var i = -1; | ||
var foundHandle = false; | ||
while (++i < listeners.length) { | ||
var listener = listeners[i]; | ||
if (listener.handle === handle) { | ||
// found matching handle | ||
listeners.splice(i, 1); | ||
foundHandle = true; | ||
break; | ||
} | ||
} | ||
if (typeof eventType !== 'string') { | ||
throw new Error("Invalid eventType parameter in " + this.$name + ".hasEventListener", _typeof(eventType), eventType); | ||
} | ||
// cleanup | ||
if (foundHandle) { | ||
if (listeners.length == 0) { | ||
// remove listeners array | ||
delete this.__listeners[eventType]; | ||
} | ||
break; | ||
} | ||
} | ||
}, | ||
return $.isArray(this.__listeners[eventType]) && this.__listeners[eventType].length > 0; | ||
}, | ||
/** | ||
* Function: _dispatchEvent | ||
* | ||
* Dispatches an event to all event listeners. If there are no event listeners nothing happens. | ||
* | ||
* Parameter: | ||
* @param {Coco.Event} event - The event type to dispatch. You can supply a string as shortcut when you don't want to pass any parameters to the event listener. | ||
*/ | ||
_dispatchEvent: function _dispatchEvent(event) { | ||
if (event == null) { | ||
throw new Error("Missing event parameter in " + this.$name + "._dispatchEvent"); | ||
} | ||
/** | ||
* Function: __removeEventListenerByEventType | ||
* | ||
* Removes all event listener with for the given event type from this class. | ||
* | ||
* Parameter: | ||
* @param {string} eventType - The event type to remove all event listeners for. | ||
*/ | ||
__removeEventListenerByEventType: function __removeEventListenerByEventType(eventType) { | ||
// check if we have event listeners | ||
if (this.__listeners[eventType] == null || this.__listeners[eventType].length == 0) { | ||
return; | ||
} | ||
// get event type | ||
var eventType = null; | ||
var hasEventParam = false; | ||
//console.warn("check eventType: ", event); | ||
if (typeof event === 'string') { | ||
eventType = event; | ||
} else if (event instanceof require("./Coco.Event.js")) { | ||
eventType = event.type; | ||
hasEventParam = true; | ||
} else { | ||
throw new Error("Unknown event parameter in " + this.$name + "._dispatchEvent. Must be typeof string!"); | ||
} | ||
delete this.__listeners[eventType]; | ||
}, | ||
// check if we have event listeners | ||
if (!this.hasEventListener(eventType)) { | ||
//no listern, do not dispatch event/ do not call listener | ||
return; | ||
} | ||
var listeners = this.__listeners[eventType]; | ||
/** | ||
* Function: __removeEventListenerByHandle | ||
* | ||
* Removes an event listener with the given handle from this class. | ||
* | ||
* Parameter: | ||
* @param {number} handle - The event listener handle to remove. | ||
*/ | ||
__removeEventListenerByHandle: function __removeEventListenerByHandle(handle) { | ||
// iterate over all event types | ||
for (var eventType in this.__listeners) { | ||
var listeners = this.__listeners[eventType]; // iterate over all listeners for this event type | ||
// iterate over all event listeners | ||
var i = -1; | ||
while (++i < listeners.length) { | ||
if (listeners[i] == null || listeners[i].listener == null) { | ||
console.warn("invalid eventlistener registered: ", listeners[i]); | ||
continue; | ||
} | ||
var i = -1; | ||
var foundHandle = false; | ||
if (hasEventParam) { | ||
// dispatch event | ||
listeners[i].listener(event); | ||
} else { | ||
// call listener without event as shortcut for "dispatchEvent('MYEVENT')" | ||
listeners[i].listener(); | ||
} | ||
while (++i < listeners.length) { | ||
var listener = listeners[i]; | ||
if (listeners[i] && listeners[i].once) { | ||
// remove once listener | ||
listeners.splice(i, 1); | ||
i--; | ||
} | ||
} | ||
if (listener.handle === handle) { | ||
// found matching handle | ||
listeners.splice(i, 1); | ||
foundHandle = true; | ||
break; | ||
} | ||
} // cleanup | ||
// check if we just removed the last once listener | ||
if (listeners.length == 0) { | ||
// ... and remove event type array from listeners map | ||
delete this.__listeners[eventType]; | ||
} | ||
} | ||
if (foundHandle) { | ||
if (listeners.length == 0) { | ||
// remove listeners array | ||
delete this.__listeners[eventType]; | ||
} | ||
break; | ||
} | ||
} | ||
}, | ||
/** | ||
* Function: _dispatchEvent | ||
* | ||
* Dispatches an event to all event listeners. If there are no event listeners nothing happens. | ||
* | ||
* Parameter: | ||
* @param {Coco.Event} event - The event type to dispatch. You can supply a string as shortcut when you don't want to pass any parameters to the event listener. | ||
*/ | ||
_dispatchEvent: function _dispatchEvent(event) { | ||
if (event == null) { | ||
throw new Error("Missing event parameter in " + this.$name + "._dispatchEvent"); | ||
} // get event type | ||
var eventType = null; | ||
var hasEventParam = false; //console.warn("check eventType: ", event); | ||
if (typeof event === 'string') { | ||
eventType = event; | ||
} else if (event instanceof require("./Coco.Event.js")) { | ||
eventType = event.type; | ||
hasEventParam = true; | ||
} else { | ||
throw new Error("Unknown event parameter in " + this.$name + "._dispatchEvent. Must be typeof string!"); | ||
} // check if we have event listeners | ||
if (!this.hasEventListener(eventType)) { | ||
//no listern, do not dispatch event/ do not call listener | ||
return; | ||
} | ||
var listeners = this.__listeners[eventType]; // iterate over all event listeners | ||
var i = -1; | ||
while (++i < listeners.length) { | ||
if (listeners[i] == null || listeners[i].listener == null) { | ||
console.warn("invalid eventlistener registered: ", listeners[i]); | ||
continue; | ||
} | ||
if (hasEventParam) { | ||
// dispatch event | ||
listeners[i].listener(event); | ||
} else { | ||
// call listener without event as shortcut for "dispatchEvent('MYEVENT')" | ||
listeners[i].listener(); | ||
} | ||
if (listeners[i] && listeners[i].once) { | ||
// remove once listener | ||
listeners.splice(i, 1); | ||
i--; | ||
} | ||
} // check if we just removed the last once listener | ||
if (listeners.length == 0) { | ||
// ... and remove event type array from listeners map | ||
delete this.__listeners[eventType]; | ||
} | ||
} | ||
}); |
@@ -13,44 +13,47 @@ "use strict"; | ||
*/ | ||
module.exports = dejavu.Class.declare({ | ||
$name: "Coco.ModelEvent", | ||
$extends: Coco.Event, | ||
$name: "Coco.ModelEvent", | ||
$extends: Coco.Event, | ||
/** | ||
* Variable: model | ||
* | ||
* Description: | ||
* <Coco.Model> or <Coco.Collection> that dispatched this event. | ||
*/ | ||
model: null, | ||
/** | ||
* Variable: key | ||
* | ||
* Description: | ||
* Key that has changed in case of an change event. | ||
*/ | ||
key: null, | ||
/** | ||
* Variable: model | ||
* | ||
* Description: | ||
* <Coco.Model> or <Coco.Collection> that dispatched this event. | ||
*/ | ||
model: null, | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {string} type - the type of this event | ||
* | ||
* @param {Coco.Model|Coco.Collection} model - The <Coco.Model> or <Coco.Collection> that dispatched the event | ||
* | ||
* @param {string} $key - {optional} The key in the <Coco.Collection> that has changed in case of an change event | ||
*/ | ||
initialize: function initialize(type, model, $key) { | ||
this.$super(type); | ||
if (model == null) { | ||
throw new Error("Missing model parameter in " + this.$name + ".initialize"); | ||
} | ||
if (!(model instanceof require("../model/Coco.Model.js") || model instanceof require("../model/Coco.Collection.js"))) { | ||
throw new Error("Invalid model parameter in " + this.$name + ".initialize. Must be Coco.Model or Coco.Collection!"); | ||
} | ||
/** | ||
* Variable: key | ||
* | ||
* Description: | ||
* Key that has changed in case of an change event. | ||
*/ | ||
key: null, | ||
this.model = model; | ||
this.key = $key; | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {string} type - the type of this event | ||
* | ||
* @param {Coco.Model|Coco.Collection} model - The <Coco.Model> or <Coco.Collection> that dispatched the event | ||
* | ||
* @param {string} $key - {optional} The key in the <Coco.Collection> that has changed in case of an change event | ||
*/ | ||
initialize: function initialize(type, model, $key) { | ||
this.$super(type); | ||
if (model == null) { | ||
throw new Error("Missing model parameter in " + this.$name + ".initialize"); | ||
} | ||
if (!(model instanceof require("../model/Coco.Model.js") || model instanceof require("../model/Coco.Collection.js"))) { | ||
throw new Error("Invalid model parameter in " + this.$name + ".initialize. Must be Coco.Model or Coco.Collection!"); | ||
} | ||
this.model = model; | ||
this.key = $key; | ||
} | ||
}); |
@@ -13,39 +13,41 @@ "use strict"; | ||
*/ | ||
module.exports = dejavu.Class.declare({ | ||
$name: "Coco.RestServiceEvent", | ||
$extends: Coco.Event, | ||
$name: "Coco.RestServiceEvent", | ||
$extends: Coco.Event, | ||
/** | ||
* Variable: error | ||
* | ||
* Description: | ||
* {object} the (response) error | ||
*/ | ||
error: null, | ||
/** | ||
* Variable: error | ||
* | ||
* Description: | ||
* {object} the (response) error | ||
*/ | ||
error: null, | ||
/** | ||
* Variable: status | ||
* | ||
* Description: | ||
* {int} the (response) error state (default: -1) | ||
*/ | ||
status: -1, | ||
/** | ||
* Variable: status | ||
* | ||
* Description: | ||
* {int} the (response) error state (default: -1) | ||
*/ | ||
status: -1, | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {string} type - The type of this dispatched the event | ||
* @param {int} status - http status of RESTService Response | ||
* @param {object} error - the error object | ||
*/ | ||
initialize: function initialize(type, status, $error) { | ||
this.$super(type); | ||
if (status == null) { | ||
throw new Error("Missing status parameter in " + this.$name + ".initialize"); | ||
} | ||
this.status = status; | ||
this.error = $error; | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {string} type - The type of this dispatched the event | ||
* @param {int} status - http status of RESTService Response | ||
* @param {object} error - the error object | ||
*/ | ||
initialize: function initialize(type, status, $error) { | ||
this.$super(type); | ||
if (status == null) { | ||
throw new Error("Missing status parameter in " + this.$name + ".initialize"); | ||
} | ||
this.status = status; | ||
this.error = $error; | ||
} | ||
}); |
@@ -13,63 +13,69 @@ "use strict"; | ||
*/ | ||
module.exports = dejavu.Class.declare({ | ||
$name: "Coco.RouterEvent", | ||
$extends: Coco.Event, | ||
$name: "Coco.RouterEvent", | ||
$extends: Coco.Event, | ||
/** | ||
* Variable: newRoute {object} | ||
* | ||
* Description: | ||
* the new route changed to | ||
*/ | ||
newRoute: null, | ||
/** | ||
* Variable: oldRoute {object} | ||
* | ||
* the old route changed from | ||
*/ | ||
oldRoute: null, | ||
$constants: { | ||
/** | ||
* Variable: newRoute {object} | ||
* | ||
* Description: | ||
* the new route changed to | ||
* Event: CHANGE_ROUTE | ||
* Called in <Coco.RouterService> when the url changed. | ||
*/ | ||
newRoute: null, | ||
CHANGE_ROUTE: 'coco:route:change', | ||
/** | ||
* Variable: oldRoute {object} | ||
* | ||
* the old route changed from | ||
* Event: FIRE_ROUTE | ||
*/ | ||
oldRoute: null, | ||
FIRE_ROUTE: 'coco:route:fire', | ||
$constants: { | ||
/** | ||
* Event: CHANGE_ROUTE | ||
* Called in <Coco.RouterService> when the url changed. | ||
*/ | ||
CHANGE_ROUTE: 'coco:route:change', | ||
/** | ||
* Event: FIRE_ROUTE | ||
*/ | ||
FIRE_ROUTE: 'coco:route:fire', | ||
/** | ||
* Event: HIDE_VIEW | ||
* Called in <Coco.RouterService> when the url changed. | ||
*/ | ||
HIDE_VIEW: 'coco:view:hide', | ||
/** | ||
* Event: SHOW_VIEW | ||
* Called in <Coco.RouterService> when the url changed. | ||
*/ | ||
SHOW_VIEW: 'coco:view:show' | ||
}, | ||
/** | ||
* Event: HIDE_VIEW | ||
* Called in <Coco.RouterService> when the url changed. | ||
*/ | ||
HIDE_VIEW: 'coco:view:hide', | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {string} type - The type that dispatched the event | ||
* @param {object} newRoute - The new route changed to | ||
* @param {object} oldRoute - The old route changed from | ||
* Event: SHOW_VIEW | ||
* Called in <Coco.RouterService> when the url changed. | ||
*/ | ||
initialize: function initialize(type, newRoute, oldRoute) { | ||
this.$super(type); | ||
if (newRoute == null) { | ||
throw new Error("Missing newRoute parameter in " + this.$name + ".initialize"); | ||
} | ||
this.newRoute = newRoute; | ||
if (oldRoute == null) { | ||
throw new Error("Missing oldRoute parameter in " + this.$name + ".initialize"); | ||
} | ||
this.oldRoute = oldRoute; | ||
SHOW_VIEW: 'coco:view:show' | ||
}, | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {string} type - The type that dispatched the event | ||
* @param {object} newRoute - The new route changed to | ||
* @param {object} oldRoute - The old route changed from | ||
*/ | ||
initialize: function initialize(type, newRoute, oldRoute) { | ||
this.$super(type); | ||
if (newRoute == null) { | ||
throw new Error("Missing newRoute parameter in " + this.$name + ".initialize"); | ||
} | ||
this.newRoute = newRoute; | ||
if (oldRoute == null) { | ||
throw new Error("Missing oldRoute parameter in " + this.$name + ".initialize"); | ||
} | ||
this.oldRoute = oldRoute; | ||
} | ||
}); |
@@ -13,37 +13,38 @@ "use strict"; | ||
*/ | ||
module.exports = dejavu.Class.declare({ | ||
$name: "Coco.TranslatorEvent", | ||
$extends: Coco.Event, | ||
$name: "Coco.TranslatorEvent", | ||
$extends: Coco.Event, | ||
/** | ||
* Variable: locale {string} | ||
* | ||
* Description: | ||
* the current locale | ||
*/ | ||
locale: null, | ||
$constants: { | ||
/** | ||
* Variable: locale {string} | ||
* | ||
* Description: | ||
* the current locale | ||
* Event: CHANGE_LOCALE | ||
* Called in <Coco.Translator> when the locale was changed. | ||
*/ | ||
locale: null, | ||
CHANGE_LOCALE: 'coco:locale:change' | ||
}, | ||
$constants: { | ||
/** | ||
* Event: CHANGE_LOCALE | ||
* Called in <Coco.Translator> when the locale was changed. | ||
*/ | ||
CHANGE_LOCALE: 'coco:locale:change' | ||
}, | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {string} type - The type that dispatched the event | ||
* @param {string} locale - The current locale | ||
*/ | ||
initialize: function initialize(type, locale) { | ||
this.$super(type); | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {string} type - The type that dispatched the event | ||
* @param {string} locale - The current locale | ||
*/ | ||
initialize: function initialize(type, locale) { | ||
this.$super(type); | ||
if (locale == null) { | ||
throw new Error("Missing locale parameter in " + this.$name + ".initialize"); | ||
} | ||
this.locale = locale; | ||
if (locale == null) { | ||
throw new Error("Missing locale parameter in " + this.$name + ".initialize"); | ||
} | ||
this.locale = locale; | ||
} | ||
}); |
@@ -13,31 +13,34 @@ "use strict"; | ||
*/ | ||
module.exports = dejavu.Class.declare({ | ||
$name: "Coco.ViewEvent", | ||
$extends: Coco.Event, | ||
$name: "Coco.ViewEvent", | ||
$extends: Coco.Event, | ||
/** | ||
* Variable: view | ||
* | ||
* Description: | ||
* <Coco.View> that dispatched this event. | ||
*/ | ||
view: null, | ||
/** | ||
* Variable: view | ||
* | ||
* Description: | ||
* <Coco.View> that dispatched this event. | ||
*/ | ||
view: null, | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {<Coco.View>} view - The <Coco.View> that dispatched the event | ||
*/ | ||
initialize: function initialize(type, view) { | ||
this.$super(type); | ||
if (view == null) { | ||
throw new Error("Missing view parameter in " + this.$name + ".initialize"); | ||
} | ||
if (!(view instanceof require("../view/Coco.View.js"))) { | ||
throw new Error("Invalid view parameter in " + this.$name + ".initialize. Must be Coco.View!"); | ||
} | ||
this.view = view; | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {<Coco.View>} view - The <Coco.View> that dispatched the event | ||
*/ | ||
initialize: function initialize(type, view) { | ||
this.$super(type); | ||
if (view == null) { | ||
throw new Error("Missing view parameter in " + this.$name + ".initialize"); | ||
} | ||
if (!(view instanceof require("../view/Coco.View.js"))) { | ||
throw new Error("Invalid view parameter in " + this.$name + ".initialize. Must be Coco.View!"); | ||
} | ||
this.view = view; | ||
} | ||
}); |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -7,130 +7,127 @@ /** | ||
*/ | ||
var Handlebars = require('handlebars/runtime'); | ||
var Handlebars = require('handlebars/runtime'), | ||
JSON = require("JSON"); | ||
Handlebars.registerHelper('getText', function (key, $replace) { | ||
var Coco = require("../Coco.Init.js"); //console.log(".$replace: ", $replace); | ||
//if $replace is not set in template, its not null here, its an handlebars object... | ||
Handlebars.registerHelper('getText', function (key, $replace) { | ||
var Coco = require("../Coco.Init.js"); | ||
//console.log(".$replace: ", $replace); | ||
//if $replace is not set in template, its not null here, its an handlebars object... | ||
if (typeof $replace == "number") { | ||
//keep numbers working | ||
$replace = [$replace]; | ||
} else { | ||
if (typeof $replace != "string") { | ||
$replace = null; | ||
} else { | ||
if ($replace.indexOf(":") > -1) { | ||
try { | ||
//parse strings to object/ array | ||
$replace = JSON.parse($replace); | ||
} catch (error) { | ||
//keep strings & numbers | ||
$replace = [$replace]; | ||
} | ||
} else { | ||
$replace = [$replace]; | ||
} | ||
} | ||
} | ||
return Coco.Translator.get(key, $replace); | ||
if (typeof $replace == "number") { | ||
//keep numbers working | ||
$replace = [$replace]; | ||
} else { | ||
if (typeof $replace != "string") { | ||
$replace = null; | ||
} else { | ||
if ($replace.indexOf(":") > -1) { | ||
try { | ||
//parse strings to object/ array | ||
$replace = JSON.parse($replace); | ||
} catch (error) { | ||
//keep strings & numbers | ||
$replace = [$replace]; | ||
} | ||
} else { | ||
$replace = [$replace]; | ||
} | ||
} | ||
} | ||
return Coco.Translator.get(key, $replace); | ||
}); | ||
Handlebars.registerHelper('ifNot', function (v1, options) { | ||
if (!v1) { | ||
return options.fn(this); | ||
} | ||
if (!v1) { | ||
return options.fn(this); | ||
} | ||
return options.inverse(this); | ||
return options.inverse(this); | ||
}); | ||
Handlebars.registerHelper('nl2br', function (value) { | ||
if (!value) { | ||
return ""; | ||
} | ||
Handlebars.registerHelper('nl2br', function (value) { | ||
if (!value) { | ||
return ""; | ||
} | ||
return value.replace(/\n/g, "<br/>"); | ||
return value.replace(/\n/g, "<br/>"); | ||
}); | ||
Handlebars.registerHelper('ifCond', function (v1, operator, v2, options) { | ||
switch (operator) { | ||
case '==': | ||
return v1 == v2 ? options.fn(this) : options.inverse(this); | ||
Handlebars.registerHelper('ifCond', function (v1, operator, v2, options) { | ||
switch (operator) { | ||
case '==': | ||
return v1 == v2 ? options.fn(this) : options.inverse(this); | ||
case '!=': | ||
return v1 != v2 ? options.fn(this) : options.inverse(this); | ||
case '===': | ||
return v1 === v2 ? options.fn(this) : options.inverse(this); | ||
case '<': | ||
return v1 < v2 ? options.fn(this) : options.inverse(this); | ||
case '<=': | ||
return v1 <= v2 ? options.fn(this) : options.inverse(this); | ||
case '>': | ||
return v1 > v2 ? options.fn(this) : options.inverse(this); | ||
case '>=': | ||
return v1 >= v2 ? options.fn(this) : options.inverse(this); | ||
case '&&': | ||
return v1 && v2 ? options.fn(this) : options.inverse(this); | ||
case '||': | ||
return v1 || v2 ? options.fn(this) : options.inverse(this); | ||
default: | ||
return options.inverse(this); | ||
} | ||
case '!=': | ||
return v1 != v2 ? options.fn(this) : options.inverse(this); | ||
case '===': | ||
return v1 === v2 ? options.fn(this) : options.inverse(this); | ||
case '<': | ||
return v1 < v2 ? options.fn(this) : options.inverse(this); | ||
case '<=': | ||
return v1 <= v2 ? options.fn(this) : options.inverse(this); | ||
case '>': | ||
return v1 > v2 ? options.fn(this) : options.inverse(this); | ||
case '>=': | ||
return v1 >= v2 ? options.fn(this) : options.inverse(this); | ||
case '&&': | ||
return v1 && v2 ? options.fn(this) : options.inverse(this); | ||
case '||': | ||
return v1 || v2 ? options.fn(this) : options.inverse(this); | ||
default: | ||
return options.inverse(this); | ||
} | ||
}); | ||
Handlebars.registerHelper('add', function (v1, v2) { | ||
return Number(v1) + Number(v2); | ||
return Number(v1) + Number(v2); | ||
}); | ||
Handlebars.registerHelper('sub', function (v1, v2) { | ||
return Number(v1) - Number(v2); | ||
return Number(v1) - Number(v2); | ||
}); | ||
Handlebars.registerHelper('concat', function (v1, v2) { | ||
return v1 + v2; | ||
return v1 + v2; | ||
}); | ||
Handlebars.registerHelper('for', function (from, to, step, block) { | ||
var accum = ''; | ||
Handlebars.registerHelper('for', function (from, to, step, block) { | ||
var accum = ''; | ||
for (var i = from; i < to; i += step) { | ||
accum += block.fn(i); | ||
} | ||
return accum; | ||
for (var i = from; i < to; i += step) { | ||
accum += block.fn(i); | ||
} | ||
return accum; | ||
}); | ||
Handlebars.registerHelper('is', function (v1, v2, options) { | ||
console.error("Handlebars.Helper 'is' is deprecated! use 'ifCond' instead!"); | ||
console.error("Handlebars.Helper 'is' is deprecated! use 'ifCond' instead!"); | ||
}); | ||
Handlebars.registerHelper('isNot', function (v1, v2, options) { | ||
console.error("Handlebars.Helper 'isNot' is deprecated! use 'ifCond' instead!"); | ||
console.error("Handlebars.Helper 'isNot' is deprecated! use 'ifCond' instead!"); | ||
}); | ||
Handlebars.registerHelper('isGreater', function (v1, v2, options) { | ||
console.error("Handlebars.Helper 'isGreater' is deprecated! use 'ifCond' instead!"); | ||
console.error("Handlebars.Helper 'isGreater' is deprecated! use 'ifCond' instead!"); | ||
}); | ||
Handlebars.registerHelper('isGreaterThan', function (v1, v2, options) { | ||
console.error("Handlebars.Helper 'isGreaterThan' is deprecated! use 'ifCond' instead!"); | ||
console.error("Handlebars.Helper 'isGreaterThan' is deprecated! use 'ifCond' instead!"); | ||
}); | ||
Handlebars.registerHelper('isLess', function () { | ||
console.error("Handlebars.Helper 'isLess' is deprecated! use 'ifCond' instead!"); | ||
console.error("Handlebars.Helper 'isLess' is deprecated! use 'ifCond' instead!"); | ||
}); | ||
Handlebars.registerHelper('isLessThan', function () { | ||
console.error("Handlebars.Helper 'isLessThan' is deprecated! use 'ifCond' instead!"); | ||
console.error("Handlebars.Helper 'isLessThan' is deprecated! use 'ifCond' instead!"); | ||
}); | ||
Handlebars.registerHelper('testIf', function () { | ||
var args = Array.prototype.slice.call(arguments); | ||
var args = Array.prototype.slice.call(arguments); // We just have one argument (besides options), so this one is just a regular | ||
// We just have one argument (besides options), so this one is just a regular | ||
if (args.length === 2) { | ||
return args[0] == true ? args[1].fn(this) : args[1].inverse(this); | ||
} | ||
if (args.length === 2) { | ||
return args[0] == true ? args[1].fn(this) : args[1].inverse(this); | ||
} | ||
if (v1 <= v2) { | ||
return options.fn(this); | ||
} | ||
if (v1 <= v2) { | ||
return options.fn(this); | ||
} | ||
return options.inverse(this); | ||
return options.inverse(this); | ||
}); |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -7,57 +7,56 @@ /** | ||
*/ | ||
function measure(msg, $scope) { | ||
if ($scope) { | ||
if (measure.scopes.hasOwnProperty($scope)) { | ||
var ms = new Date().getTime(); | ||
if ($scope) { | ||
if (measure.scopes.hasOwnProperty($scope)) { | ||
var ms = new Date().getTime(); | ||
if (measure.scopes[$scope].time !== null) { | ||
console.log(ms - measure.scopes[$scope].time, $scope + ' - ' + msg); | ||
} else { | ||
measure.scopes[$scope].startTime = ms; | ||
console.log(0, $scope + ' - ' + msg); | ||
} | ||
measure.scopes[$scope].time = ms; | ||
return; | ||
} | ||
measure.scopes[$scope] = { time: new Date().getTime(), startTime: new Date().getTime(), endTime: null }; | ||
console.log('start scope', $scope); | ||
if (measure.scopes[$scope].time !== null) { | ||
console.log(ms - measure.scopes[$scope].time, $scope + ' - ' + msg); | ||
} else { | ||
measure.scopes[$scope].startTime = ms; | ||
console.log(0, $scope + ' - ' + msg); | ||
} | ||
return; | ||
measure.scopes[$scope].time = ms; | ||
return; | ||
} | ||
console.log(new Date().getTime(), msg); | ||
measure.scopes[$scope] = { | ||
time: new Date().getTime(), | ||
startTime: new Date().getTime(), | ||
endTime: null | ||
}; | ||
console.log('start scope', $scope); | ||
console.log(0, $scope + ' - ' + msg); | ||
return; | ||
} | ||
console.log(new Date().getTime(), msg); | ||
} | ||
measure.scopes = {}; | ||
measure.resetScope = function (scope) { | ||
if (measure.scopes.hasOwnProperty(scope)) { | ||
measure.scopes[scope].time = null; | ||
measure.scopes[scope].startTime = null; | ||
measure.scopes[scope].endTime = null; | ||
} | ||
if (measure.scopes.hasOwnProperty(scope)) { | ||
measure.scopes[scope].time = null; | ||
measure.scopes[scope].startTime = null; | ||
measure.scopes[scope].endTime = null; | ||
} | ||
}; | ||
measure.endScope = function (scope, $reset) { | ||
if (measure.scopes.hasOwnProperty(scope)) { | ||
measure.scopes[scope].endTime = new Date().getTime(); | ||
if (measure.scopes.hasOwnProperty(scope)) { | ||
measure.scopes[scope].endTime = new Date().getTime(); | ||
console.log('Total time of Scope ' + scope, measure.scopes[scope].endTime - measure.scopes[scope].startTime); | ||
console.log('Total time of Scope ' + scope, measure.scopes[scope].endTime - measure.scopes[scope].startTime); | ||
if ($reset !== false) { | ||
measure.resetScope(scope); | ||
} | ||
if ($reset !== false) { | ||
measure.resetScope(scope); | ||
} | ||
} | ||
}; | ||
measure.getTotalTimeOfScope = function (scope) { | ||
if (measure.scopes.hasOwnProperty(scope)) { | ||
console.log('Total time of Scope ' + scope, measure.scopes[scope].endTime - measure.scopes[scope].startTime); | ||
} | ||
if (measure.scopes.hasOwnProperty(scope)) { | ||
console.log('Total time of Scope ' + scope, measure.scopes[scope].endTime - measure.scopes[scope].startTime); | ||
} | ||
}; |
@@ -13,232 +13,252 @@ "use strict"; | ||
*/ | ||
'use strict'; | ||
Coco.File = dejavu.Class.declare({ | ||
//className | ||
$name: "Coco.File", | ||
//className | ||
$name: "Coco.File", | ||
initialize: function initialize() { | ||
console.error("Do not instantiate static class: " + this.$name); | ||
}, | ||
$finals: { | ||
$statics: { | ||
/** | ||
* Function: saveAs(blob, name) | ||
* | ||
* Description: | ||
* A {static} saveAs() FileSaver implementation. | ||
* | ||
* By Eli Grey, http://eligrey.com | ||
* License: X11/MIT | ||
* See LICENSE.md | ||
* | ||
* needs global variable 'window' | ||
* jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, plusplus: true | ||
* | ||
* @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js | ||
* | ||
* Parameter: | ||
* Blob blob - Blob of data to save | ||
* String name - filename of download target file | ||
**/ | ||
saveAs: navigator.msSaveBlob && navigator.msSaveBlob.bind(navigator) || function (view) { | ||
"use strict"; //prevent errors in IE8, this fixes nothing! | ||
initialize: function initialize() { | ||
console.error("Do not instantiate static class: " + this.$name); | ||
}, | ||
if (typeof view.document.createElementNS !== 'function') { | ||
return false; | ||
} | ||
$finals: { | ||
$statics: { | ||
var doc = view.document // only get URL when necessary in case BlobBuilder.js hasn't overridden it yet | ||
, | ||
get_URL = function get_URL() { | ||
return view.URL || view.webkitURL || view; | ||
}, | ||
URL = view.URL || view.webkitURL || view, | ||
save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"), | ||
can_use_save_link = "download" in save_link, | ||
click = function click(node) { | ||
var event = doc.createEvent("MouseEvents"); | ||
event.initMouseEvent("click", true, false, view, 0, 0, 0, 0, 0, false, false, false, false, 0, null); | ||
node.dispatchEvent(event); | ||
}, | ||
webkit_req_fs = view.webkitRequestFileSystem, | ||
req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem, | ||
throw_outside = function throw_outside(ex) { | ||
(view.setImmediate || view.setTimeout)(function () { | ||
throw ex; | ||
}, 0); | ||
}, | ||
force_saveable_type = "application/octet-stream", | ||
fs_min_size = 0, | ||
deletion_queue = [], | ||
process_deletion_queue = function process_deletion_queue() { | ||
var i = deletion_queue.length; | ||
/** | ||
* Function: saveAs(blob, name) | ||
* | ||
* Description: | ||
* A {static} saveAs() FileSaver implementation. | ||
* | ||
* By Eli Grey, http://eligrey.com | ||
* License: X11/MIT | ||
* See LICENSE.md | ||
* | ||
* needs global variable 'window' | ||
* jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, plusplus: true | ||
* | ||
* @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js | ||
* | ||
* Parameter: | ||
* Blob blob - Blob of data to save | ||
* String name - filename of download target file | ||
**/ | ||
saveAs: navigator.msSaveBlob && navigator.msSaveBlob.bind(navigator) || function (view) { | ||
"use strict"; | ||
while (i--) { | ||
var file = deletion_queue[i]; | ||
//prevent errors in IE8, this fixes nothing! | ||
if (typeof file === "string") { | ||
// file is an object URL | ||
URL.revokeObjectURL(file); | ||
} else { | ||
// file is a File | ||
file.remove(); | ||
} | ||
} | ||
if (typeof view.document.createElementNS !== 'function') { | ||
return false; | ||
} | ||
deletion_queue.length = 0; // clear queue | ||
}, | ||
dispatch = function dispatch(filesaver, event_types, event) { | ||
event_types = [].concat(event_types); | ||
var i = event_types.length; | ||
var doc = view.document | ||
// only get URL when necessary in case BlobBuilder.js hasn't overridden it yet | ||
, | ||
get_URL = function get_URL() { | ||
return view.URL || view.webkitURL || view; | ||
}, | ||
URL = view.URL || view.webkitURL || view, | ||
save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"), | ||
can_use_save_link = "download" in save_link, | ||
click = function click(node) { | ||
var event = doc.createEvent("MouseEvents"); | ||
event.initMouseEvent("click", true, false, view, 0, 0, 0, 0, 0, false, false, false, false, 0, null); | ||
node.dispatchEvent(event); | ||
}, | ||
webkit_req_fs = view.webkitRequestFileSystem, | ||
req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem, | ||
throw_outside = function throw_outside(ex) { | ||
(view.setImmediate || view.setTimeout)(function () { | ||
throw ex; | ||
}, 0); | ||
}, | ||
force_saveable_type = "application/octet-stream", | ||
fs_min_size = 0, | ||
deletion_queue = [], | ||
process_deletion_queue = function process_deletion_queue() { | ||
var i = deletion_queue.length; | ||
while (i--) { | ||
var file = deletion_queue[i]; | ||
if (typeof file === "string") { | ||
// file is an object URL | ||
URL.revokeObjectURL(file); | ||
} else { | ||
// file is a File | ||
file.remove(); | ||
} | ||
} | ||
deletion_queue.length = 0; // clear queue | ||
}, | ||
dispatch = function dispatch(filesaver, event_types, event) { | ||
event_types = [].concat(event_types); | ||
var i = event_types.length; | ||
while (i--) { | ||
var listener = filesaver["on" + event_types[i]]; | ||
if (typeof listener === "function") { | ||
try { | ||
listener.call(filesaver, event || filesaver); | ||
} catch (ex) { | ||
throw_outside(ex); | ||
} | ||
} | ||
} | ||
}, | ||
FileSaver = function FileSaver(blob, name) { | ||
// First try a.download, then web filesystem, then object URLs | ||
var filesaver = this, | ||
type = blob.type, | ||
blob_changed = false, | ||
object_url, | ||
target_view, | ||
get_object_url = function get_object_url() { | ||
var object_url = get_URL().createObjectURL(blob); | ||
deletion_queue.push(object_url); | ||
return object_url; | ||
}, | ||
dispatch_all = function dispatch_all() { | ||
dispatch(filesaver, "writestart progress write writeend".split(" ")); | ||
} | ||
// on any filesys errors revert to saving with object URLs | ||
, | ||
fs_error = function fs_error() { | ||
// don't create more object URLs than needed | ||
if (blob_changed || !object_url) { | ||
object_url = get_object_url(blob); | ||
} | ||
if (target_view) { | ||
target_view.location.href = object_url; | ||
} | ||
filesaver.readyState = filesaver.DONE; | ||
dispatch_all(); | ||
}, | ||
abortable = function abortable(func) { | ||
return function () { | ||
if (filesaver.readyState !== filesaver.DONE) { | ||
return func.apply(this, arguments); | ||
} | ||
}; | ||
}, | ||
create_if_not_found = { create: true, exclusive: false }, | ||
slice; | ||
filesaver.readyState = filesaver.INIT; | ||
if (!name) { | ||
name = "download"; | ||
} | ||
if (can_use_save_link) { | ||
object_url = get_object_url(blob); | ||
save_link.href = object_url; | ||
save_link.download = name; | ||
click(save_link); | ||
filesaver.readyState = filesaver.DONE; | ||
dispatch_all(); | ||
return; | ||
} | ||
// Object and web filesystem URLs have a problem saving in Google Chrome when | ||
// viewed in a tab, so I force save with application/octet-stream | ||
// http://code.google.com/p/chromium/issues/detail?id=91158 | ||
if (view.chrome && type && type !== force_saveable_type) { | ||
slice = blob.slice || blob.webkitSlice; | ||
blob = slice.call(blob, 0, blob.size, force_saveable_type); | ||
blob_changed = true; | ||
} | ||
// Since I can't be sure that the guessed media type will trigger a download | ||
// in WebKit, I append .download to the filename. | ||
// https://bugs.webkit.org/show_bug.cgi?id=65440 | ||
if (webkit_req_fs && name !== "download") { | ||
name += ".download"; | ||
} | ||
if (type === force_saveable_type || webkit_req_fs) { | ||
target_view = view; | ||
} else { | ||
target_view = view.open(); | ||
} | ||
if (!req_fs) { | ||
while (i--) { | ||
var listener = filesaver["on" + event_types[i]]; | ||
if (typeof listener === "function") { | ||
try { | ||
listener.call(filesaver, event || filesaver); | ||
} catch (ex) { | ||
throw_outside(ex); | ||
} | ||
} | ||
} | ||
}, | ||
FileSaver = function FileSaver(blob, name) { | ||
// First try a.download, then web filesystem, then object URLs | ||
var filesaver = this, | ||
type = blob.type, | ||
blob_changed = false, | ||
object_url, | ||
target_view, | ||
get_object_url = function get_object_url() { | ||
var object_url = get_URL().createObjectURL(blob); | ||
deletion_queue.push(object_url); | ||
return object_url; | ||
}, | ||
dispatch_all = function dispatch_all() { | ||
dispatch(filesaver, "writestart progress write writeend".split(" ")); | ||
} // on any filesys errors revert to saving with object URLs | ||
, | ||
fs_error = function fs_error() { | ||
// don't create more object URLs than needed | ||
if (blob_changed || !object_url) { | ||
object_url = get_object_url(blob); | ||
} | ||
if (target_view) { | ||
target_view.location.href = object_url; | ||
} | ||
filesaver.readyState = filesaver.DONE; | ||
dispatch_all(); | ||
}, | ||
abortable = function abortable(func) { | ||
return function () { | ||
if (filesaver.readyState !== filesaver.DONE) { | ||
return func.apply(this, arguments); | ||
} | ||
}; | ||
}, | ||
create_if_not_found = { | ||
create: true, | ||
exclusive: false | ||
}, | ||
slice; | ||
filesaver.readyState = filesaver.INIT; | ||
if (!name) { | ||
name = "download"; | ||
} | ||
if (can_use_save_link) { | ||
object_url = get_object_url(blob); | ||
save_link.href = object_url; | ||
save_link.download = name; | ||
click(save_link); | ||
filesaver.readyState = filesaver.DONE; | ||
dispatch_all(); | ||
return; | ||
} // Object and web filesystem URLs have a problem saving in Google Chrome when | ||
// viewed in a tab, so I force save with application/octet-stream | ||
// http://code.google.com/p/chromium/issues/detail?id=91158 | ||
if (view.chrome && type && type !== force_saveable_type) { | ||
slice = blob.slice || blob.webkitSlice; | ||
blob = slice.call(blob, 0, blob.size, force_saveable_type); | ||
blob_changed = true; | ||
} // Since I can't be sure that the guessed media type will trigger a download | ||
// in WebKit, I append .download to the filename. | ||
// https://bugs.webkit.org/show_bug.cgi?id=65440 | ||
if (webkit_req_fs && name !== "download") { | ||
name += ".download"; | ||
} | ||
if (type === force_saveable_type || webkit_req_fs) { | ||
target_view = view; | ||
} else { | ||
target_view = view.open(); | ||
} | ||
if (!req_fs) { | ||
fs_error(); | ||
return; | ||
} | ||
fs_min_size += blob.size; | ||
req_fs(view.TEMPORARY, fs_min_size, abortable(function (fs) { | ||
fs.root.getDirectory("saved", create_if_not_found, abortable(function (dir) { | ||
var save = function save() { | ||
dir.getFile(name, create_if_not_found, abortable(function (file) { | ||
file.createWriter(abortable(function (writer) { | ||
writer.onwriteend = function (event) { | ||
target_view.location.href = file.toURL(); | ||
deletion_queue.push(file); | ||
filesaver.readyState = filesaver.DONE; | ||
dispatch(filesaver, "writeend", event); | ||
}; | ||
writer.onerror = function () { | ||
var error = writer.error; | ||
if (error.code !== error.ABORT_ERR) { | ||
fs_error(); | ||
return; | ||
} | ||
fs_min_size += blob.size; | ||
req_fs(view.TEMPORARY, fs_min_size, abortable(function (fs) { | ||
fs.root.getDirectory("saved", create_if_not_found, abortable(function (dir) { | ||
var save = function save() { | ||
dir.getFile(name, create_if_not_found, abortable(function (file) { | ||
file.createWriter(abortable(function (writer) { | ||
writer.onwriteend = function (event) { | ||
target_view.location.href = file.toURL(); | ||
deletion_queue.push(file); | ||
filesaver.readyState = filesaver.DONE; | ||
dispatch(filesaver, "writeend", event); | ||
}; | ||
writer.onerror = function () { | ||
var error = writer.error; | ||
if (error.code !== error.ABORT_ERR) { | ||
fs_error(); | ||
} | ||
}; | ||
"writestart progress write abort".split(" ").forEach(function (event) { | ||
writer["on" + event] = filesaver["on" + event]; | ||
}); | ||
writer.write(blob); | ||
filesaver.abort = function () { | ||
writer.abort(); | ||
filesaver.readyState = filesaver.DONE; | ||
}; | ||
filesaver.readyState = filesaver.WRITING; | ||
}), fs_error); | ||
}), fs_error); | ||
}; | ||
dir.getFile(name, { create: false }, abortable(function (file) { | ||
// delete file if it already exists | ||
file.remove(); | ||
save(); | ||
}), abortable(function (ex) { | ||
if (ex.code === ex.NOT_FOUND_ERR) { | ||
save(); | ||
} else { | ||
fs_error(); | ||
} | ||
})); | ||
}), fs_error); | ||
}), fs_error); | ||
}, | ||
FS_proto = FileSaver.prototype, | ||
saveAs = function saveAs(blob, name) { | ||
return new FileSaver(blob, name); | ||
}; | ||
FS_proto.abort = function () { | ||
var filesaver = this; | ||
filesaver.readyState = filesaver.DONE; | ||
dispatch(filesaver, "abort"); | ||
}; | ||
FS_proto.readyState = FS_proto.INIT = 0; | ||
FS_proto.WRITING = 1; | ||
FS_proto.DONE = 2; | ||
} | ||
}; | ||
FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null; | ||
"writestart progress write abort".split(" ").forEach(function (event) { | ||
writer["on" + event] = filesaver["on" + event]; | ||
}); | ||
writer.write(blob); | ||
view.addEventListener("unload", process_deletion_queue, false); | ||
return saveAs; | ||
}(window) | ||
} | ||
filesaver.abort = function () { | ||
writer.abort(); | ||
filesaver.readyState = filesaver.DONE; | ||
}; | ||
filesaver.readyState = filesaver.WRITING; | ||
}), fs_error); | ||
}), fs_error); | ||
}; | ||
dir.getFile(name, { | ||
create: false | ||
}, abortable(function (file) { | ||
// delete file if it already exists | ||
file.remove(); | ||
save(); | ||
}), abortable(function (ex) { | ||
if (ex.code === ex.NOT_FOUND_ERR) { | ||
save(); | ||
} else { | ||
fs_error(); | ||
} | ||
})); | ||
}), fs_error); | ||
}), fs_error); | ||
}, | ||
FS_proto = FileSaver.prototype, | ||
saveAs = function saveAs(blob, name) { | ||
return new FileSaver(blob, name); | ||
}; | ||
FS_proto.abort = function () { | ||
var filesaver = this; | ||
filesaver.readyState = filesaver.DONE; | ||
dispatch(filesaver, "abort"); | ||
}; | ||
FS_proto.readyState = FS_proto.INIT = 0; | ||
FS_proto.WRITING = 1; | ||
FS_proto.DONE = 2; | ||
FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null; | ||
view.addEventListener("unload", process_deletion_queue, false); | ||
return saveAs; | ||
}(window) | ||
} | ||
} | ||
}); |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -11,56 +11,54 @@ /** | ||
module.exports = dejavu.Class.declare({ | ||
$name: "Math", | ||
$name: "Math", | ||
$finals: { | ||
$statics: { | ||
/** | ||
* Function: {final static} isNumber(x) | ||
* | ||
* Description: | ||
* checks if a given variable is a number | ||
* | ||
* returns: | ||
* | ||
* boolean | ||
*/ | ||
isNumber: function isNumber(x) { | ||
return !isNaN(parseFloat(x)); | ||
}, | ||
$finals: { | ||
$statics: { | ||
/** | ||
* Function: {final static} isNumber(x) | ||
* | ||
* Description: | ||
* checks if a given variable is a number | ||
* | ||
* returns: | ||
* | ||
* boolean | ||
*/ | ||
isNumber: function isNumber(x) { | ||
return !isNaN(parseFloat(x)); | ||
}, | ||
/** | ||
* Function: {final static} round(value, precision) | ||
* | ||
* Description: | ||
* rounds a float to a given precision. | ||
* | ||
* Parameter: | ||
* @param {Number} value - The value to round. | ||
* @param {Number} $precision - {optional} The number of decimals. If omitted, the function will round to an Integer | ||
* | ||
* Return: | ||
* @returns {number} | ||
*/ | ||
round: function round(value, $precision) { | ||
$precision = $precision != null ? $precision : 0; | ||
return Math.round((value + 0.0000001) * Math.pow(10, $precision)) / Math.pow(10, $precision); | ||
}, | ||
/** | ||
* Function: {final static} round(value, precision) | ||
* | ||
* Description: | ||
* rounds a float to a given precision. | ||
* | ||
* Parameter: | ||
* @param {Number} value - The value to round. | ||
* @param {Number} $precision - {optional} The number of decimals. If omitted, the function will round to an Integer | ||
* | ||
* Return: | ||
* @returns {number} | ||
*/ | ||
round: function round(value, $precision) { | ||
$precision = $precision != null ? $precision : 0; | ||
/** | ||
* Function: {final static} random(noOfDigits) | ||
* | ||
* Description: | ||
*/ | ||
random: function random(noOfDigits) { | ||
var charset = '123456789'; | ||
var ret = ''; | ||
return Math.round((value + 0.0000001) * Math.pow(10, $precision)) / Math.pow(10, $precision); | ||
}, | ||
for (var i = 0; i < noOfDigits; i++) { | ||
ret += charset.substr(Math.floor(Math.random() * 9), 1); | ||
} | ||
/** | ||
* Function: {final static} random(noOfDigits) | ||
* | ||
* Description: | ||
*/ | ||
random: function random(noOfDigits) { | ||
var charset = '123456789'; | ||
var ret = ''; | ||
for (var i = 0; i < noOfDigits; i++) { | ||
ret += charset.substr(Math.floor(Math.random() * 9), 1); | ||
} | ||
return parseInt(ret); | ||
} | ||
} | ||
return parseInt(ret); | ||
} | ||
} | ||
} | ||
}); |
"use strict"; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var JSON = require("JSON"); | ||
/** | ||
@@ -13,165 +12,166 @@ * Class: Coco.Storage | ||
module.exports = dejavu.Class.declare({ | ||
$name: 'Storage', | ||
$name: 'Storage', | ||
$statics: { | ||
/** | ||
* holds a boolean, that checks if the localStorage is available. | ||
*/ | ||
isAvailable: function isAvailable() { | ||
if (window) { | ||
try { | ||
return window.localStorage != null; | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
} | ||
$statics: { | ||
/** | ||
* holds a boolean, that checks if the localStorage is available. | ||
*/ | ||
isAvailable: function isAvailable() { | ||
if (window) { | ||
try { | ||
return window.localStorage != null; | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
} | ||
console.warn("No window.localStorage available!"); | ||
return false; | ||
}, | ||
console.warn("No window.localStorage available!"); | ||
return false; | ||
}, | ||
/** | ||
* Function: has(key) | ||
* | ||
* Description: | ||
* Checks if the key is in the localStorage. | ||
* | ||
* Parameter: | ||
* @param {string} key | ||
* | ||
* Return: | ||
* @returns {boolean} | ||
*/ | ||
has: function has(key) { | ||
if (this.isAvailable()) { | ||
return window.localStorage.hasOwnProperty(key); | ||
} | ||
return false; | ||
}, | ||
/** | ||
* Function: has(key) | ||
* | ||
* Description: | ||
* Checks if the key is in the localStorage. | ||
* | ||
* Parameter: | ||
* @param {string} key | ||
* | ||
* Return: | ||
* @returns {boolean} | ||
*/ | ||
has: function has(key) { | ||
if (this.isAvailable()) { | ||
return window.localStorage.hasOwnProperty(key); | ||
} | ||
/** | ||
* Function: get(key) | ||
* | ||
* Description: | ||
* Returns the value of the key. | ||
* If value is an object, the method will try to parse it and then return the parsed object. | ||
* | ||
* Parameter: | ||
* @param {string} key | ||
* | ||
* Return: | ||
* @returns {*} | ||
*/ | ||
get: function get(key) { | ||
if (this.isAvailable()) { | ||
var value = window.localStorage.getItem(key); | ||
return false; | ||
}, | ||
try { | ||
value = JSON.parse(value); | ||
} catch (e) {} | ||
/** | ||
* Function: get(key) | ||
* | ||
* Description: | ||
* Returns the value of the key. | ||
* If value is an object, the method will try to parse it and then return the parsed object. | ||
* | ||
* Parameter: | ||
* @param {string} key | ||
* | ||
* Return: | ||
* @returns {*} | ||
*/ | ||
get: function get(key) { | ||
if (this.isAvailable()) { | ||
var value = window.localStorage.getItem(key); | ||
return value; | ||
} | ||
try { | ||
value = JSON.parse(value); | ||
} catch (e) {} | ||
return null; | ||
}, | ||
return value; | ||
} | ||
/** | ||
* Function: set(key, value) | ||
* | ||
* Description: | ||
* Saves a key and it's value to the localStorage. | ||
* If the value is an object, the function will stringify it. | ||
* | ||
* Parameter: | ||
* @param {string} key | ||
* @param {*} value | ||
*/ | ||
set: function set(key, value) { | ||
if (this.isAvailable()) { | ||
if ((typeof value === "undefined" ? "undefined" : _typeof(value)) === 'object') { | ||
value = JSON.stringify(value); | ||
} | ||
return null; | ||
}, | ||
window.localStorage.setItem(key, value); | ||
} | ||
}, | ||
/** | ||
* Function: set(key, value) | ||
* | ||
* Description: | ||
* Saves a key and it's value to the localStorage. | ||
* If the value is an object, the function will stringify it. | ||
* | ||
* Parameter: | ||
* @param {string} key | ||
* @param {*} value | ||
*/ | ||
set: function set(key, value) { | ||
if (this.isAvailable()) { | ||
if (_typeof(value) === 'object') { | ||
value = JSON.stringify(value); | ||
} | ||
/** | ||
* Function: copy(sourceKey, targetKey, $deleteSource) | ||
* | ||
* Description: | ||
* Copies a value to another destination. | ||
* | ||
* @param {string} sourceKey - Where lives the value that should be copied | ||
* @param {string} targetKey - The destination | ||
* @param {boolean} $deleteSource - {optional} If set to true the sourceKey will be deleted. | ||
*/ | ||
copy: function copy(sourceKey, targetKey, $deleteSource) { | ||
if (this.isAvailable()) { | ||
if (window.localStorage.hasOwnProperty(sourceKey)) { | ||
window.localStorage.setItem(targetKey, window.localStorage.getItem(sourceKey)); | ||
} | ||
window.localStorage.setItem(key, value); | ||
} | ||
}, | ||
if ($deleteSource) { | ||
window.localStorage.removeItem(sourceKey); | ||
} | ||
} | ||
}, | ||
/** | ||
* Function: copy(sourceKey, targetKey, $deleteSource) | ||
* | ||
* Description: | ||
* Copies a value to another destination. | ||
* | ||
* @param {string} sourceKey - Where lives the value that should be copied | ||
* @param {string} targetKey - The destination | ||
* @param {boolean} $deleteSource - {optional} If set to true the sourceKey will be deleted. | ||
*/ | ||
copy: function copy(sourceKey, targetKey, $deleteSource) { | ||
if (this.isAvailable()) { | ||
if (window.localStorage.hasOwnProperty(sourceKey)) { | ||
window.localStorage.setItem(targetKey, window.localStorage.getItem(sourceKey)); | ||
} | ||
/** | ||
* Function: remove(key) | ||
* | ||
* Description: | ||
* Removes a key and it's value from the localStorage. | ||
* | ||
* Parameter: | ||
* @param {string} key | ||
*/ | ||
remove: function remove(key) { | ||
if (this.isAvailable()) { | ||
window.localStorage.removeItem(key); | ||
} | ||
}, | ||
if ($deleteSource) { | ||
window.localStorage.removeItem(sourceKey); | ||
} | ||
} | ||
}, | ||
/** | ||
* Function: clear() | ||
* | ||
* Description: | ||
* Clears the locationStorage. | ||
*/ | ||
clear: function clear() { | ||
if (this.isAvailable()) { | ||
window.localStorage.clear(); | ||
} | ||
}, | ||
/** | ||
* Function: remove(key) | ||
* | ||
* Description: | ||
* Removes a key and it's value from the localStorage. | ||
* | ||
* Parameter: | ||
* @param {string} key | ||
*/ | ||
remove: function remove(key) { | ||
if (this.isAvailable()) { | ||
window.localStorage.removeItem(key); | ||
} | ||
}, | ||
/** | ||
* Function: getUsedSpace() | ||
* | ||
* Description: | ||
* Returns the number of kilobyte of memory the localStorage has taken. | ||
* | ||
* Return: | ||
* @returns {null|Number} | ||
*/ | ||
getUsedSpace: function getUsedSpace($key) { | ||
if (this.isAvailable()) { | ||
var values = ''; | ||
/** | ||
* Function: clear() | ||
* | ||
* Description: | ||
* Clears the locationStorage. | ||
*/ | ||
clear: function clear() { | ||
if (this.isAvailable()) { | ||
window.localStorage.clear(); | ||
} | ||
}, | ||
if ($key) { | ||
values = window.localStorage.hasOwnProperty($key) ? window.localStorage.getItem($key) : ''; | ||
} else { | ||
for (var key in window.localStorage) { | ||
if (window.localStorage.hasOwnProperty(key)) { | ||
values += window.localStorage[key]; | ||
} | ||
} | ||
} | ||
/** | ||
* Function: getUsedSpace() | ||
* | ||
* Description: | ||
* Returns the number of kilobyte of memory the localStorage has taken. | ||
* | ||
* Return: | ||
* @returns {null|Number} | ||
*/ | ||
getUsedSpace: function getUsedSpace($key) { | ||
if (this.isAvailable()) { | ||
var values = ''; | ||
return values ? 3 + values.length * 16 / (8 * 1024) : 0; | ||
} | ||
if ($key) { | ||
values = window.localStorage.hasOwnProperty($key) ? window.localStorage.getItem($key) : ''; | ||
} else { | ||
for (var key in window.localStorage) { | ||
if (window.localStorage.hasOwnProperty(key)) { | ||
values += window.localStorage[key]; | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
} | ||
return values ? 3 + values.length * 16 / (8 * 1024) : 0; | ||
} | ||
return null; | ||
} | ||
} | ||
}); |
@@ -13,26 +13,24 @@ /** | ||
module.exports = dejavu.Class.declare({ | ||
$name: "Coco.StringUtils", | ||
initialize: function initialize() { | ||
console.error("Do not instantiate static class: " + this.$name); | ||
}, | ||
$finals: { | ||
$statics: { | ||
/** | ||
* Function: {final static} isEmpty | ||
* | ||
* Description: | ||
* | ||
* checks if given string is null or empty | ||
* | ||
* returns: | ||
* | ||
* boolean | ||
*/ | ||
isEmpty: function isEmpty(string) { | ||
return string == null || string === "" || string.length === 0; | ||
} | ||
} | ||
$name: "Coco.StringUtils", | ||
initialize: function initialize() { | ||
console.error("Do not instantiate static class: " + this.$name); | ||
}, | ||
$finals: { | ||
$statics: { | ||
/** | ||
* Function: {final static} isEmpty | ||
* | ||
* Description: | ||
* | ||
* checks if given string is null or empty | ||
* | ||
* returns: | ||
* | ||
* boolean | ||
*/ | ||
isEmpty: function isEmpty(string) { | ||
return string == null || string === "" || string.length === 0; | ||
} | ||
} | ||
} | ||
}); |
"use strict"; | ||
var JSON = require("JSON"), | ||
_ = require("underscore"), | ||
TranslatorEvent = require("../event/Coco.TranslatorEvent.js"); | ||
var TranslatorEvent = require("../event/Coco.TranslatorEvent.js"); | ||
/** | ||
@@ -18,2 +15,4 @@ * Package: lib | ||
*/ | ||
module.exports = dejavu.Class.declare({ | ||
@@ -73,2 +72,3 @@ $name: "Coco.Translator", | ||
} | ||
_this.setLocale($locale); | ||
@@ -81,2 +81,3 @@ | ||
_this.createDomain(_this.__domain); | ||
_this.fill(data, true); | ||
@@ -139,5 +140,5 @@ | ||
} | ||
if (key.split('.').length > 1) { | ||
var array = this.__messages[this.__locale + ':' + this.__domain]; | ||
$.each(key.split('.'), function (i, e) { | ||
@@ -148,8 +149,9 @@ if (array == null) { | ||
} | ||
array = array[e]; | ||
}); | ||
string = array; | ||
} else { | ||
var data = this.__messages[this.__locale + ':' + this.__domain]; | ||
if (data == null) { | ||
@@ -159,2 +161,3 @@ console.error("Could not find label with key: " + key); | ||
} | ||
string = data[key]; | ||
@@ -164,4 +167,4 @@ } | ||
if (string == null || typeof string != "string") { | ||
console.warn("Could not find label with key: " + key, string); | ||
//return objects or arrays from i18n file | ||
console.warn("Could not find label with key: " + key, string); //return objects or arrays from i18n file | ||
return string == null ? "" : string; | ||
@@ -201,2 +204,3 @@ } | ||
var msgs = {}; | ||
for (var key in this.__messages) { | ||
@@ -209,2 +213,3 @@ if (this.__messages.hasOwnProperty(key)) { | ||
} | ||
return msgs; | ||
@@ -343,4 +348,6 @@ } | ||
} | ||
var oldLocale = this.__locale; | ||
this.__locale = newLocale; | ||
if (oldLocale != this.__locale) { | ||
@@ -347,0 +354,0 @@ this._dispatchEvent(new TranslatorEvent(TranslatorEvent.CHANGE_LOCALE, this.__locale)); |
@@ -12,30 +12,26 @@ /** | ||
module.exports = dejavu.Class.declare({ | ||
$name: "Coco.URLHelper", | ||
initialize: function initialize() { | ||
console.error("Do not instantiate static class: " + this.$name); | ||
}, | ||
$finals: { | ||
$statics: { | ||
/** | ||
* Function: getUrlVars (static) | ||
* | ||
* Description: | ||
* {final static} parses current url for GET parameter | ||
* | ||
* Return: | ||
* @returns {Map} of given URL GET-Parameters | ||
*/ | ||
getUrlVars: function getUrlVars() { | ||
var vars = new Map(); | ||
window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) { | ||
vars.set(key, value); | ||
}); | ||
return vars; | ||
} | ||
} | ||
$name: "Coco.URLHelper", | ||
initialize: function initialize() { | ||
console.error("Do not instantiate static class: " + this.$name); | ||
}, | ||
$finals: { | ||
$statics: { | ||
/** | ||
* Function: getUrlVars (static) | ||
* | ||
* Description: | ||
* {final static} parses current url for GET parameter | ||
* | ||
* Return: | ||
* @returns {Map} of given URL GET-Parameters | ||
*/ | ||
getUrlVars: function getUrlVars() { | ||
var vars = new Map(); | ||
window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) { | ||
vars.set(key, value); | ||
}); | ||
return vars; | ||
} | ||
} | ||
} | ||
}); |
"use strict"; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
@@ -14,249 +14,252 @@ var Coco = Coco || {}; | ||
*/ | ||
Coco.Utils = module.exports = dejavu.Class.declare({ | ||
$name: "Utils", | ||
$name: "Utils", | ||
/** | ||
* Constants: | ||
* These constants are used to cast or type test variables. | ||
* | ||
* @public | ||
*/ | ||
//$constants: { | ||
/** | ||
* Constant: BOOLEAN | ||
* | ||
* for boolean casting | ||
* | ||
*/ | ||
BOOLEAN: 0, | ||
/** | ||
* Constant: INTEGER | ||
* | ||
* for integer casting | ||
*/ | ||
INTEGER: 1, | ||
/** | ||
* Constants: | ||
* These constants are used to cast or type test variables. | ||
* | ||
* @public | ||
*/ | ||
//$constants: { | ||
/** | ||
* Constant: FLOAT | ||
* | ||
* for float casting | ||
*/ | ||
FLOAT: 2, | ||
/** | ||
* Constant: BOOLEAN | ||
* | ||
* for boolean casting | ||
* | ||
*/ | ||
BOOLEAN: 0, | ||
/** | ||
* Constant: STRING | ||
* | ||
* for string casting | ||
*/ | ||
STRING: 3, | ||
/** | ||
* Constant: INTEGER | ||
* | ||
* for integer casting | ||
*/ | ||
INTEGER: 1, | ||
/** | ||
* Constant: OBJECT | ||
* | ||
* for object casting | ||
*/ | ||
OBJECT: 4, | ||
/** | ||
* Constant: FLOAT | ||
* | ||
* for float casting | ||
*/ | ||
FLOAT: 2, | ||
/** | ||
* Constant: ARRAY | ||
* | ||
* for array casting | ||
*/ | ||
ARRAY: 5, | ||
/** | ||
* Constant: STRING | ||
* | ||
* for string casting | ||
*/ | ||
STRING: 3, | ||
/** | ||
* Constant: NULL | ||
* | ||
* for null casting | ||
*/ | ||
NULL: 6, | ||
/** | ||
* Constant: OBJECT | ||
* | ||
* for object casting | ||
*/ | ||
OBJECT: 4, | ||
/** | ||
* Constant: ARRAY | ||
* | ||
* for array casting | ||
*/ | ||
ARRAY: 5, | ||
/** | ||
* Constant: NULL | ||
* | ||
* for null casting | ||
*/ | ||
NULL: 6, | ||
/** | ||
* Constant: UNDEFINED | ||
* | ||
* for undefined casting | ||
*/ | ||
UNDEFINED: 99, | ||
//}, | ||
$statics: { | ||
__id: 0 | ||
}, | ||
//$finals: { | ||
// $statics: { | ||
/** | ||
* Function: sizeOfObject | ||
* | ||
* Paramter: | ||
* @param {object} obj | ||
* | ||
* Return: | ||
* @return {number} - number of object properties | ||
*/ | ||
sizeOfObject: function sizeOfObject(obj) { | ||
var size = 0, | ||
key; | ||
for (key in obj) { | ||
if (obj.hasOwnProperty(key)) size++; | ||
} | ||
return size; | ||
}, | ||
/** | ||
* Function: uniqueId | ||
* | ||
* Description: | ||
* {final static} Generates a unique id with an optional prefix. Be careful: It's only unique if all generated ids use the | ||
* same function and it's only unique while lifetime of application. | ||
* | ||
* Parameter: | ||
* @param {string} $prefix - {optional} optional prefix for unique id. Is not allowed to contain a number. | ||
* | ||
* Return: | ||
* @returns {string|number} - created unique id | ||
*/ | ||
uniqueId: function uniqueId($prefix) { | ||
if (/[0-9]$/.test($prefix)) { | ||
throw new Error("$prefix is not allowed to end with a number in Coco.Utils.uniqueId()."); | ||
} | ||
var id = ++Coco.Utils.$static.__id + ''; | ||
var x = $prefix ? "" + $prefix + id : id; | ||
return x; | ||
}, | ||
/** | ||
* Function: randomId | ||
* | ||
* Description: | ||
* {final static} Generates a random id with an optional prefix. | ||
* | ||
* Parameter: | ||
* @param {string} $prefix - {optional} optional prefix for random id. | ||
* | ||
* Return: | ||
* @returns {string|number} - created random id | ||
*/ | ||
randomId: function randomId($prefix) { | ||
var rand = window.btoa(Math.floor(Math.random() * 5000000) + '' + new Date().getTime() + '' + ++Coco.Utils.$static.__id); | ||
return $prefix ? "" + $prefix + rand.substr(0, 32) : rand.substr(0, 32); | ||
}, | ||
/** | ||
* Function: isMobile : {Android, BlackBerry, iOS, Opera, Windows, any} | ||
* | ||
* {final static} object for mobile detection | ||
*/ | ||
isMobile: { | ||
/** | ||
* Constant: UNDEFINED | ||
* Function: isMobile.Android | ||
* | ||
* for undefined casting | ||
* returns matched navigator String if Android device detected, otherwise null | ||
*/ | ||
UNDEFINED: 99, | ||
//}, | ||
$statics: { | ||
__id: 0 | ||
Android: function Android() { | ||
return navigator && navigator.userAgent && navigator.userAgent.match(/Android/i); | ||
}, | ||
//$finals: { | ||
// $statics: { | ||
/** | ||
* Function: sizeOfObject | ||
* Function: isMobile.BlackBerry | ||
* | ||
* Paramter: | ||
* @param {object} obj | ||
* | ||
* Return: | ||
* @return {number} - number of object properties | ||
* returns matched navigator String if BlackBerry device detected, otherwise null | ||
*/ | ||
sizeOfObject: function sizeOfObject(obj) { | ||
var size = 0, | ||
key; | ||
BlackBerry: function BlackBerry() { | ||
return navigator && navigator.userAgent && navigator.userAgent.match(/BlackBerry/i); | ||
}, | ||
for (key in obj) { | ||
if (obj.hasOwnProperty(key)) size++; | ||
} | ||
return size; | ||
}, | ||
/** | ||
* Function: uniqueId | ||
* Function: isMobile.BlackBerry | ||
* | ||
* Description: | ||
* {final static} Generates a unique id with an optional prefix. Be careful: It's only unique if all generated ids use the | ||
* same function and it's only unique while lifetime of application. | ||
* | ||
* Parameter: | ||
* @param {string} $prefix - {optional} optional prefix for unique id. Is not allowed to contain a number. | ||
* | ||
* Return: | ||
* @returns {string|number} - created unique id | ||
* returns matched navigator String if BlackBerry device detected, otherwise null | ||
*/ | ||
uniqueId: function uniqueId($prefix) { | ||
if (/[0-9]$/.test($prefix)) { | ||
throw new Error("$prefix is not allowed to end with a number in Coco.Utils.uniqueId()."); | ||
} | ||
var id = ++Coco.Utils.$static.__id + ''; | ||
var x = $prefix ? "" + $prefix + id : id; | ||
return x; | ||
iOS: function iOS() { | ||
return navigator && navigator.userAgent && navigator.userAgent.match(/iPhone|iPad|iPod/i); | ||
}, | ||
/** | ||
* Function: randomId | ||
* Function: isMobile.Opera | ||
* | ||
* Description: | ||
* {final static} Generates a random id with an optional prefix. | ||
* | ||
* Parameter: | ||
* @param {string} $prefix - {optional} optional prefix for random id. | ||
* | ||
* Return: | ||
* @returns {string|number} - created random id | ||
* returns matched navigator String if Opera Mini device detected, otherwise null | ||
*/ | ||
randomId: function randomId($prefix) { | ||
var rand = window.btoa(Math.floor(Math.random() * 5000000) + '' + new Date().getTime() + '' + ++Coco.Utils.$static.__id); | ||
return $prefix ? "" + $prefix + rand.substr(0, 32) : rand.substr(0, 32); | ||
Opera: function Opera() { | ||
return navigator && navigator.userAgent && navigator.userAgent.match(/Opera Mini/i); | ||
}, | ||
/** | ||
* Function: isMobile : {Android, BlackBerry, iOS, Opera, Windows, any} | ||
* Function: isMobile.Windows | ||
* | ||
* {final static} object for mobile detection | ||
* returns matched navigator String if IEMobile device detected, otherwise null | ||
*/ | ||
isMobile: { | ||
/** | ||
* Function: isMobile.Android | ||
* | ||
* returns matched navigator String if Android device detected, otherwise null | ||
*/ | ||
Android: function Android() { | ||
return navigator && navigator.userAgent && navigator.userAgent.match(/Android/i); | ||
}, | ||
/** | ||
* Function: isMobile.BlackBerry | ||
* | ||
* returns matched navigator String if BlackBerry device detected, otherwise null | ||
*/ | ||
BlackBerry: function BlackBerry() { | ||
return navigator && navigator.userAgent && navigator.userAgent.match(/BlackBerry/i); | ||
}, | ||
/** | ||
* Function: isMobile.BlackBerry | ||
* | ||
* returns matched navigator String if BlackBerry device detected, otherwise null | ||
*/ | ||
iOS: function iOS() { | ||
return navigator && navigator.userAgent && navigator.userAgent.match(/iPhone|iPad|iPod/i); | ||
}, | ||
/** | ||
* Function: isMobile.Opera | ||
* | ||
* returns matched navigator String if Opera Mini device detected, otherwise null | ||
*/ | ||
Opera: function Opera() { | ||
return navigator && navigator.userAgent && navigator.userAgent.match(/Opera Mini/i); | ||
}, | ||
/** | ||
* Function: isMobile.Windows | ||
* | ||
* returns matched navigator String if IEMobile device detected, otherwise null | ||
*/ | ||
Windows: function Windows() { | ||
return navigator && navigator.userAgent && navigator.userAgent.match(/IEMobile/i); | ||
}, | ||
/** | ||
* Function: isMobile.any | ||
* | ||
* returns matched navigator String if any mobile device detected, otherwise null | ||
*/ | ||
any: function any() { | ||
return Coco.Utils.$static.isMobile.Android() || Coco.Utils.$static.isMobile.BlackBerry() || Coco.Utils.$static.isMobile.iOS() || Coco.Utils.$static.isMobile.Opera() || Coco.Utils.$static.isMobile.Windows(); | ||
} | ||
Windows: function Windows() { | ||
return navigator && navigator.userAgent && navigator.userAgent.match(/IEMobile/i); | ||
}, | ||
/** | ||
* Function: cast | ||
* Function: isMobile.any | ||
* | ||
* Description: | ||
* {final static} Cast value to a specific type. | ||
* | ||
* Parameter: | ||
* @param {*} value - The value to cast | ||
* | ||
* @param {Number} type - The type to cast the value to. Should refer to <Coco.Utils.Constants> | ||
* | ||
* @param {string|Number} $key - optional $key is needed if type is Coco.Util.OBJECT | ||
* returns matched navigator String if any mobile device detected, otherwise null | ||
*/ | ||
cast: function cast(value, type, $key) { | ||
switch (type) { | ||
case Coco.Utils.INTEGER: | ||
return parseInt(value, 10); | ||
any: function any() { | ||
return Coco.Utils.$static.isMobile.Android() || Coco.Utils.$static.isMobile.BlackBerry() || Coco.Utils.$static.isMobile.iOS() || Coco.Utils.$static.isMobile.Opera() || Coco.Utils.$static.isMobile.Windows(); | ||
} | ||
}, | ||
case Coco.Utils.BOOLEAN: | ||
return parseInt(value, 10) === 1 || value === "true" || value === "1"; | ||
/** | ||
* Function: cast | ||
* | ||
* Description: | ||
* {final static} Cast value to a specific type. | ||
* | ||
* Parameter: | ||
* @param {*} value - The value to cast | ||
* | ||
* @param {Number} type - The type to cast the value to. Should refer to <Coco.Utils.Constants> | ||
* | ||
* @param {string|Number} $key - optional $key is needed if type is Coco.Util.OBJECT | ||
*/ | ||
cast: function cast(value, type, $key) { | ||
switch (type) { | ||
case Coco.Utils.INTEGER: | ||
return parseInt(value, 10); | ||
case Coco.Utils.FLOAT: | ||
return parseFloat(value); | ||
case Coco.Utils.BOOLEAN: | ||
return parseInt(value, 10) === 1 || value === "true" || value === "1"; | ||
case Coco.Utils.STRING: | ||
return value.toString(); | ||
case Coco.Utils.FLOAT: | ||
return parseFloat(value); | ||
case Coco.Utils.ARRAY: | ||
return value instanceof Array ? value : [value]; | ||
case Coco.Utils.STRING: | ||
return value.toString(); | ||
case Coco.Utils.OBJECT: | ||
if ((typeof value === "undefined" ? "undefined" : _typeof(value)) === 'object') { | ||
return value; | ||
} | ||
case Coco.Utils.ARRAY: | ||
return value instanceof Array ? value : [value]; | ||
if (typeof $key !== 'undefined') { | ||
var o = {}; | ||
o[$key] = value; | ||
case Coco.Utils.OBJECT: | ||
if (_typeof(value) === 'object') { | ||
return value; | ||
} | ||
return o; | ||
} | ||
if (typeof $key !== 'undefined') { | ||
var o = {}; | ||
o[$key] = value; | ||
return o; | ||
} | ||
throw new Error('Cannot cast value ' + value + ' to object because no $key is given in Coco.Utils.cast().'); | ||
break; | ||
throw new Error('Cannot cast value ' + value + ' to object because no $key is given in Coco.Utils.cast().'); | ||
break; | ||
case Coco.Utils.NULL: | ||
return null; | ||
case Coco.Utils.NULL: | ||
return null; | ||
default: | ||
return value; | ||
} | ||
default: | ||
return value; | ||
} | ||
//} | ||
//} | ||
} //} | ||
//} | ||
}); | ||
module.exports = new Coco.Utils(); |
@@ -5,2 +5,3 @@ "use strict"; | ||
_ = require("underscore"); | ||
Coco.Event = require("../event/Coco.Event.js"), Coco.EventDispatcher = require("../event/Coco.EventDispatcher.js"), Coco.ModelEvent = require("../event/Coco.ModelEvent.js"), Coco.Utils = require("../lib/Coco.Utils.js"), Coco.Model = require("./Coco.Model.js"), Coco.Math = require("../lib/Coco.Math.js"); | ||
@@ -17,719 +18,716 @@ /** | ||
*/ | ||
module.exports = dejavu.Class.declare({ | ||
$name: 'Collection', | ||
$name: 'Collection', | ||
$extends: Coco.EventDispatcher, | ||
$extends: Coco.EventDispatcher, | ||
/** | ||
* The internal collection id. | ||
*/ | ||
__id: null, | ||
/** | ||
* The internal collection id. | ||
*/ | ||
__id: null, | ||
/** | ||
* A private class identifier, copied from `this.$name` | ||
*/ | ||
__$name: "Collection", | ||
/** | ||
* A private class identifier, copied from `this.$name` | ||
*/ | ||
__$name: "Collection", | ||
/** | ||
* Variable: _models | ||
* {protected} Array of Coco.Model objects. | ||
*/ | ||
_models: [], | ||
/** | ||
* Variable: _models | ||
* {protected} Array of Coco.Model objects. | ||
*/ | ||
_models: [], | ||
/** | ||
* Variable: __handles | ||
* {private} Map of EventListener-handles for models from _models-Array | ||
*/ | ||
__handles: null, | ||
/** | ||
* Variable: __handles | ||
* {private} Map of EventListener-handles for models from _models-Array | ||
*/ | ||
__handles: null, | ||
/** | ||
* Variable: _modelClass | ||
* The class of the models. Calling <Coco.Collection.createOne> and <Coco.Collection.add> will always add models | ||
* with the class referred here. | ||
* {protected} | ||
*/ | ||
_modelClass: null, | ||
/** | ||
* Variable: _modelClass | ||
* The class of the models. Calling <Coco.Collection.createOne> and <Coco.Collection.add> will always add models | ||
* with the class referred here. | ||
* {protected} | ||
*/ | ||
_modelClass: null, | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {Array} $models - The models to add initial. | ||
*/ | ||
initialize: function initialize($models) { | ||
if (this._modelClass == null || !this._modelClass.prototype || this._modelClass.prototype.__$name !== 'Model' && this._modelClass.$parent && this._modelClass.$parent.prototype.__$name !== 'Model') { | ||
throw new Error("Cannot create Collection '" + this.$name + "' with '_modelClass' being null or not extending from Coco.Model."); | ||
} | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {Array} $models - The models to add initial. | ||
*/ | ||
initialize: function initialize($models) { | ||
if (this._modelClass == null || !this._modelClass.prototype || this._modelClass.prototype.__$name !== 'Model' && this._modelClass.$parent && this._modelClass.$parent.prototype.__$name !== 'Model') { | ||
throw new Error("Cannot create Collection '" + this.$name + "' with '_modelClass' being null or not extending from Coco.Model."); | ||
} | ||
this.__$name = this.$name; | ||
this.__id = Coco.Utils.uniqueId("c"); | ||
this.__handles = new Map(); | ||
this.__$name = this.$name; | ||
this.__id = Coco.Utils.uniqueId("c"); | ||
this._onInitialize($models); | ||
this.__handles = new Map(); | ||
if ($models != null) { | ||
this.add($models); | ||
} | ||
}, | ||
this._onInitialize($models); | ||
/** | ||
* Function: _onInitialize | ||
* Function is called after class is initialized, but BEFORE models are added. | ||
* | ||
* Parameter: | ||
* @param {Array} $models - The models to add initial. You can change those by altering the this parameter. | ||
*/ | ||
_onInitialize: function _onInitialize($models) {}, | ||
if ($models != null) { | ||
this.add($models); | ||
} | ||
}, | ||
/** | ||
* Function: add | ||
* Adds an array of models to the collection. This can be either an instance of Coco.Model or attributes or an Array | ||
* containing one of both. | ||
* | ||
* Parameter: | ||
* @param {Coco.Model|Object|Array} attributes - Array of models to add. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.ADD> event with each model that has been added. | ||
*/ | ||
add: function add(attributes) { | ||
var _this = this; | ||
/** | ||
* Function: _onInitialize | ||
* Function is called after class is initialized, but BEFORE models are added. | ||
* | ||
* Parameter: | ||
* @param {Array} $models - The models to add initial. You can change those by altering the this parameter. | ||
*/ | ||
_onInitialize: function _onInitialize($models) {}, | ||
if (attributes == null) { | ||
return; | ||
} | ||
/** | ||
* Function: add | ||
* Adds an array of models to the collection. This can be either an instance of Coco.Model or attributes or an Array | ||
* containing one of both. | ||
* | ||
* Parameter: | ||
* @param {Coco.Model|Object|Array} attributes - Array of models to add. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.ADD> event with each model that has been added. | ||
*/ | ||
add: function add(attributes) { | ||
var _this = this; | ||
if (!(attributes instanceof Array)) { | ||
attributes = [attributes]; | ||
} | ||
if (attributes == null) { | ||
return; | ||
} | ||
var model = null; | ||
if (!(attributes instanceof Array)) { | ||
attributes = [attributes]; | ||
} | ||
for (var i = 0; i < attributes.length; i++) { | ||
if (attributes[i] == null) { | ||
continue; | ||
} // If attribute is a model store it, otherwise create a new model and set it's attributes. | ||
var model = null; | ||
for (var i = 0; i < attributes.length; i++) { | ||
if (attributes[i] == null) { | ||
continue; | ||
} | ||
model = !(attributes[i] instanceof this._modelClass) ? new this._modelClass(attributes[i]) : attributes[i]; | ||
var handle = model.addEventListener(Coco.Event.DESTROY, function (event) { | ||
_this.__onModelDestroy(event); | ||
}, true); | ||
// If attribute is a model store it, otherwise create a new model and set it's attributes. | ||
model = !(attributes[i] instanceof this._modelClass) ? new this._modelClass(attributes[i]) : attributes[i]; | ||
this._models.push(model); | ||
var handle = model.addEventListener(Coco.Event.DESTROY, function (event) { | ||
_this.__onModelDestroy(event); | ||
}, true); | ||
this._models.push(model); | ||
this._addModelHandle(handle, model); | ||
this._addModelHandle(handle, model); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.ADD, model)); | ||
} | ||
}, | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.ADD, model)); | ||
} | ||
}, | ||
/** | ||
* Function: _addModelHandle | ||
* | ||
* stores all handles for one model, to delete eventlistener, after rmoving model from collection | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - model to add handle for | ||
* | ||
* @param {Symbol} handle - handle to add | ||
* | ||
* @protected | ||
*/ | ||
_addModelHandle: function _addModelHandle(handle, model) { | ||
var mh = this.__handles.get(model.getId()); | ||
if (mh == null) { | ||
mh = []; | ||
} | ||
mh.push(handle); | ||
this.__handles.set(model.getId(), mh); | ||
}, | ||
/** | ||
* Function: _addModelHandle | ||
* | ||
* stores all handles for one model, to delete eventlistener, after rmoving model from collection | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - model to add handle for | ||
* | ||
* @param {Symbol} handle - handle to add | ||
* | ||
* @protected | ||
*/ | ||
_addModelHandle: function _addModelHandle(handle, model) { | ||
var mh = this.__handles.get(model.getId()); | ||
if (mh == null) { | ||
mh = []; | ||
} | ||
/** | ||
* Function: _removeModelHandles | ||
* | ||
* removes all handles for given model | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - model to remove EventListener from | ||
* @protected | ||
*/ | ||
_removeModelHandles: function _removeModelHandles(model) { | ||
var mh = this.__handles.get(model.getId()); | ||
if (mh != null && mh.length > 0) { | ||
for (var i = 0; i < mh.length; i++) { | ||
model.removeEventListener(mh[i]); | ||
} | ||
} | ||
this.__handles.delete(model.getId()); | ||
}, | ||
mh.push(handle); | ||
this.__handles.set(model.getId(), mh); | ||
}, | ||
/** | ||
* Function: insertAt | ||
* Add a model a the specified index to the collection | ||
* | ||
* Parameter: | ||
* @param {integer} index - The index position. | ||
* | ||
* @param {Coco.Model} model - The <Coco.Model> instance to add. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.ADD> event | ||
*/ | ||
insertAt: function insertAt(index, model) { | ||
if (model instanceof this._modelClass) { | ||
if (index >= 0 && index <= this._models.length) { | ||
this._models.splice(index, 0, model); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.ADD, model)); | ||
} else { | ||
throw new Error("index out of bound error"); | ||
} | ||
} | ||
}, | ||
/** | ||
* Function: _removeModelHandles | ||
* | ||
* removes all handles for given model | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - model to remove EventListener from | ||
* @protected | ||
*/ | ||
_removeModelHandles: function _removeModelHandles(model) { | ||
var mh = this.__handles.get(model.getId()); | ||
/** | ||
* Function: createOne | ||
* Creates a new model based on given attributes. | ||
* | ||
* Parameter: | ||
* @param {Object} $attributes - {optional} The attributes the new model should have. | ||
* | ||
* Return: | ||
* @return {Coco.Model} - The created model. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.ADD> event. | ||
*/ | ||
createOne: function createOne($attributes) { | ||
var _this2 = this; | ||
if (mh != null && mh.length > 0) { | ||
for (var i = 0; i < mh.length; i++) { | ||
model.removeEventListener(mh[i]); | ||
} | ||
} | ||
if ($attributes instanceof this._modelClass) { | ||
return null; | ||
} | ||
this.__handles.delete(model.getId()); | ||
}, | ||
var model = new this._modelClass($attributes); | ||
/** | ||
* Function: insertAt | ||
* Add a model a the specified index to the collection | ||
* | ||
* Parameter: | ||
* @param {integer} index - The index position. | ||
* | ||
* @param {Coco.Model} model - The <Coco.Model> instance to add. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.ADD> event | ||
*/ | ||
insertAt: function insertAt(index, model) { | ||
if (model instanceof this._modelClass) { | ||
if (index >= 0 && index <= this._models.length) { | ||
this._models.splice(index, 0, model); | ||
var handle = model.addEventListener(Coco.Event.DESTROY, function (event) { | ||
_this2.__onModelDestroy(event); | ||
}, true); | ||
this._models.push(model); | ||
this._addModelHandle(handle, model); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.ADD, model)); | ||
} else { | ||
throw new Error("index out of bound error"); | ||
} | ||
} | ||
}, | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.ADD, model)); | ||
/** | ||
* Function: createOne | ||
* Creates a new model based on given attributes. | ||
* | ||
* Parameter: | ||
* @param {Object} $attributes - {optional} The attributes the new model should have. | ||
* | ||
* Return: | ||
* @return {Coco.Model} - The created model. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.ADD> event. | ||
*/ | ||
createOne: function createOne($attributes) { | ||
var _this2 = this; | ||
return model; | ||
}, | ||
if ($attributes instanceof this._modelClass) { | ||
return null; | ||
} | ||
/** | ||
* Function: has | ||
* checks for existing model in collection. | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - An <Coco.Model> instance | ||
* | ||
* Return: | ||
* @returns {boolean} - True if model is in Collection | ||
*/ | ||
has: function has(model) { | ||
for (var i = 0; i < this._models.length; i++) { | ||
if (model.isEqual(this._models[i])) { | ||
return true; | ||
} | ||
} | ||
var model = new this._modelClass($attributes); | ||
var handle = model.addEventListener(Coco.Event.DESTROY, function (event) { | ||
_this2.__onModelDestroy(event); | ||
}, true); | ||
return false; | ||
}, | ||
this._models.push(model); | ||
/** | ||
* Function: reset | ||
* Removes all models from the collection. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.REMOVE> event for each model that gets removed. | ||
* | ||
* Triggers <Coco.Event.RESET> event. | ||
* | ||
* Return: | ||
* @return {Coco.Collection} - The <Coco.Collection> instance. | ||
*/ | ||
reset: function reset() { | ||
for (var i = 0; i < this._models.length; i++) { | ||
//remove all model handles | ||
this._removeModelHandles(this._models[i]); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.REMOVE, this._models[i])); | ||
} | ||
this._models = []; | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.RESET, this)); | ||
this._addModelHandle(handle, model); | ||
return this; | ||
}, | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.ADD, model)); | ||
/** | ||
* Function: remove | ||
* Removes one model. | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - The instance of <Coco.Model> to remove. | ||
* | ||
* @param {boolean} $silent - If set to true the model won't trigger the <Coco.Event.REMOVE> event. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.REMOVE> event if $silent is not set to true. | ||
*/ | ||
remove: function remove(model, $silent) { | ||
if (model == null) { | ||
console.warn(this.$name + ": can't delete null object!"); | ||
return; | ||
} | ||
for (var i = 0; i < this._models.length; i++) { | ||
if (model.isEqual(this._models[i])) { | ||
this.removeAt(i, $silent); | ||
break; | ||
} | ||
} | ||
}, | ||
return model; | ||
}, | ||
/** | ||
* Function: removeAt | ||
* Removes model at specific index position. | ||
* | ||
* Parameter: | ||
* @param {integer} index - The index position. | ||
* | ||
* @param {boolean} $silent - {optional} If set to true the model won't trigger the `remove` event. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.REMOVE> event if $silent is not set to true. | ||
*/ | ||
removeAt: function removeAt(index, $silent) { | ||
if (this._models.length > index) { | ||
var m = this._models.splice(index, 1); | ||
/** | ||
* Function: has | ||
* checks for existing model in collection. | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - An <Coco.Model> instance | ||
* | ||
* Return: | ||
* @returns {boolean} - True if model is in Collection | ||
*/ | ||
has: function has(model) { | ||
for (var i = 0; i < this._models.length; i++) { | ||
if (model.isEqual(this._models[i])) { | ||
return true; | ||
} | ||
} | ||
this._removeModelHandles(m[0]); | ||
return false; | ||
}, | ||
if ($silent !== true) { | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.REMOVE, m[0])); | ||
} | ||
} | ||
}, | ||
/** | ||
* Function: reset | ||
* Removes all models from the collection. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.REMOVE> event for each model that gets removed. | ||
* | ||
* Triggers <Coco.Event.RESET> event. | ||
* | ||
* Return: | ||
* @return {Coco.Collection} - The <Coco.Collection> instance. | ||
*/ | ||
reset: function reset() { | ||
for (var i = 0; i < this._models.length; i++) { | ||
//remove all model handles | ||
this._removeModelHandles(this._models[i]); | ||
/** | ||
* Function: getAt | ||
* Gets model at specific index. | ||
* | ||
* Parameter: | ||
* @param {integer} index - The index position. | ||
* | ||
* Return: | ||
* @return {Coco.Model} - The remove <Coco.Model> instance. | ||
*/ | ||
getAt: function getAt(index) { | ||
if (index >= this._models.length || index < 0) { | ||
return null; | ||
} | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.REMOVE, this._models[i])); | ||
} | ||
return this._models[index]; | ||
}, | ||
this._models = []; | ||
/** | ||
* Function: indexOf | ||
* Gets the index of a model. | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - An <Coco.Model> instance | ||
* | ||
* Return: | ||
* @return {Number} - The index of the <Coco.Model> instance. | ||
*/ | ||
indexOf: function indexOf(model) { | ||
for (var i = 0; i < this._models.length; i++) { | ||
if (model.isEqual(this._models[i])) { | ||
return i; | ||
} | ||
} | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.RESET, this)); | ||
return -1; | ||
}, | ||
return this; | ||
}, | ||
/** | ||
* Function: getAll | ||
* Gets all models as <Coco.Model> instances. | ||
* | ||
* Return: | ||
* @return {Array} - Array of <Coco.Model> instances. | ||
*/ | ||
getAll: function getAll() { | ||
return this._models; | ||
}, | ||
/** | ||
* Function: remove | ||
* Removes one model. | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - The instance of <Coco.Model> to remove. | ||
* | ||
* @param {boolean} $silent - If set to true the model won't trigger the <Coco.Event.REMOVE> event. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.REMOVE> event if $silent is not set to true. | ||
*/ | ||
remove: function remove(model, $silent) { | ||
if (model == null) { | ||
console.warn(this.$name + ": can't delete null object!"); | ||
return; | ||
} | ||
/** | ||
* Function: getAllAttributes | ||
* Gets all models. This returns an array of all attributes of all models, not the Coco.Model instances. | ||
* every model has its own entry | ||
* | ||
* Return: | ||
* @returns {Array} - Array of attributes of <Coco.Model> instances. | ||
*/ | ||
getAllAttributes: function getAllAttributes() { | ||
var models = []; | ||
for (var i = 0; i < this._models.length; i++) { | ||
if (model.isEqual(this._models[i])) { | ||
this.removeAt(i, $silent); | ||
break; | ||
} | ||
} | ||
}, | ||
$.each(this._models, function (i, e) { | ||
// Add all attributes of current model | ||
models.push(e.getAttributes()); | ||
}); | ||
/** | ||
* Function: removeAt | ||
* Removes model at specific index position. | ||
* | ||
* Parameter: | ||
* @param {integer} index - The index position. | ||
* | ||
* @param {boolean} $silent - {optional} If set to true the model won't trigger the `remove` event. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.REMOVE> event if $silent is not set to true. | ||
*/ | ||
removeAt: function removeAt(index, $silent) { | ||
if (this._models.length > index) { | ||
var m = this._models.splice(index, 1); | ||
return models; | ||
}, | ||
this._removeModelHandles(m[0]); | ||
/** | ||
* Function: each | ||
* Iterates over all objects in the collection and executes a given callback function for every model. | ||
* | ||
* If the callback returns false, the each function breaks. | ||
* | ||
* Parameter: | ||
* @param {Function} callback - The method to execute for each model. Parameters are Coco.Model instance and index. | ||
*/ | ||
each: function each(callback) { | ||
if (this._models == null) { | ||
return false; | ||
} | ||
for (var i = 0; i < this._models.length; i++) { | ||
if (callback(this._models[i], i) === false) { | ||
break; | ||
} | ||
} | ||
}, | ||
if ($silent !== true) { | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.REMOVE, m[0])); | ||
} | ||
} | ||
}, | ||
/** | ||
* Function: push | ||
* Adds a model at the end of the collection. | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - The <Coco.Model> instance to add. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.ADD> event | ||
*/ | ||
push: function push(model) { | ||
var _this3 = this; | ||
/** | ||
* Function: getAt | ||
* Gets model at specific index. | ||
* | ||
* Parameter: | ||
* @param {integer} index - The index position. | ||
* | ||
* Return: | ||
* @return {Coco.Model} - The remove <Coco.Model> instance. | ||
*/ | ||
getAt: function getAt(index) { | ||
if (index >= this._models.length || index < 0) { | ||
return null; | ||
} | ||
if (model instanceof this._modelClass) { | ||
var handle = model.addEventListener(Coco.Event.DESTROY, function (event) { | ||
_this3.__onModelDestroy(event); | ||
}, true); | ||
this._models.push(model); | ||
this._addModelHandle(handle, model); | ||
return this._models[index]; | ||
}, | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.ADD, model)); | ||
} | ||
}, | ||
/** | ||
* Function: indexOf | ||
* Gets the index of a model. | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - An <Coco.Model> instance | ||
* | ||
* Return: | ||
* @return {Number} - The index of the <Coco.Model> instance. | ||
*/ | ||
indexOf: function indexOf(model) { | ||
for (var i = 0; i < this._models.length; i++) { | ||
if (model.isEqual(this._models[i])) { | ||
return i; | ||
} | ||
} | ||
/** | ||
* Function: pop | ||
* Removes and returns the last model from the collection. | ||
* | ||
* Return | ||
* @return {Coco.Model} - The removed <Coco.Model> instance. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.REMOVE> event | ||
*/ | ||
pop: function pop() { | ||
var model = this._models.pop(); | ||
return -1; | ||
}, | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.REMOVE, model)); | ||
/** | ||
* Function: getAll | ||
* Gets all models as <Coco.Model> instances. | ||
* | ||
* Return: | ||
* @return {Array} - Array of <Coco.Model> instances. | ||
*/ | ||
getAll: function getAll() { | ||
return this._models; | ||
}, | ||
return model; | ||
}, | ||
/** | ||
* Function: getAllAttributes | ||
* Gets all models. This returns an array of all attributes of all models, not the Coco.Model instances. | ||
* every model has its own entry | ||
* | ||
* Return: | ||
* @returns {Array} - Array of attributes of <Coco.Model> instances. | ||
*/ | ||
getAllAttributes: function getAllAttributes() { | ||
var models = []; | ||
$.each(this._models, function (i, e) { | ||
// Add all attributes of current model | ||
models.push(e.getAttributes()); | ||
}); | ||
return models; | ||
}, | ||
/** | ||
* Function: unshift | ||
* Adds a model at the beginning of the collection. | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - The <Coco.Model> instance to add. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.ADD> event | ||
*/ | ||
unshift: function unshift(model) { | ||
if (model instanceof this._modelClass) { | ||
//TODO ???? | ||
//this._removeModelHandles(model); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.ADD, model)); | ||
return this._models.unshift(model); | ||
} | ||
}, | ||
/** | ||
* Function: each | ||
* Iterates over all objects in the collection and executes a given callback function for every model. | ||
* | ||
* If the callback returns false, the each function breaks. | ||
* | ||
* Parameter: | ||
* @param {Function} callback - The method to execute for each model. Parameters are Coco.Model instance and index. | ||
*/ | ||
each: function each(callback) { | ||
if (this._models == null) { | ||
return false; | ||
} | ||
/** | ||
* Function: shift | ||
* Removes and returns the first model from the collection. | ||
* | ||
* Return: | ||
* @return {Coco.Model} - The removed <Coco.Model> instance. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.REMOVE> event | ||
*/ | ||
shift: function shift() { | ||
var model = this._models.shift(); | ||
for (var i = 0; i < this._models.length; i++) { | ||
if (callback(this._models[i], i) === false) { | ||
break; | ||
} | ||
} | ||
}, | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.REMOVE, model)); | ||
/** | ||
* Function: push | ||
* Adds a model at the end of the collection. | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - The <Coco.Model> instance to add. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.ADD> event | ||
*/ | ||
push: function push(model) { | ||
var _this3 = this; | ||
return model; | ||
}, | ||
if (model instanceof this._modelClass) { | ||
var handle = model.addEventListener(Coco.Event.DESTROY, function (event) { | ||
_this3.__onModelDestroy(event); | ||
}, true); | ||
/** | ||
* Function: findBy | ||
* Finds models by given query object. The object contains attributes and their values and findBy will match this | ||
* against the collections models. | ||
* | ||
* Parameter: | ||
* @param {object} query - The object of attributes and values to look for in the collection. | ||
* | ||
* Return: | ||
* @return {Array} - Array of matched <Coco.Model> instances. | ||
*/ | ||
findBy: function findBy(query) { | ||
var models = []; | ||
var valid = false; | ||
this._models.push(model); | ||
$.each(this._models, function (i, e) { | ||
valid = true; | ||
this._addModelHandle(handle, model); | ||
$.each(query, function (key, value) { | ||
if (!e.has(key) || e.get(key) != value) { | ||
valid = false; | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.ADD, model)); | ||
} | ||
}, | ||
return false; | ||
} | ||
}); | ||
/** | ||
* Function: pop | ||
* Removes and returns the last model from the collection. | ||
* | ||
* Return | ||
* @return {Coco.Model} - The removed <Coco.Model> instance. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.REMOVE> event | ||
*/ | ||
pop: function pop() { | ||
var model = this._models.pop(); | ||
if (valid) { | ||
models.push(e); | ||
} | ||
}); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.REMOVE, model)); | ||
return models; | ||
}, | ||
return model; | ||
}, | ||
/** | ||
* Function: findOneBy | ||
* Acts like findBy but returns the first matched model. | ||
* | ||
* Parameter: | ||
* @param {object} query - The object of attributes and values to look for in the collection. | ||
* | ||
* Return: | ||
* @return {Coco.Model|null} - First matched <Coco.Model> instance of null. | ||
*/ | ||
findOneBy: function findOneBy(query) { | ||
var model = null; | ||
var valid = false; | ||
/** | ||
* Function: unshift | ||
* Adds a model at the beginning of the collection. | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - The <Coco.Model> instance to add. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.ADD> event | ||
*/ | ||
unshift: function unshift(model) { | ||
if (model instanceof this._modelClass) { | ||
//TODO ???? | ||
//this._removeModelHandles(model); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.ADD, model)); | ||
$.each(this._models, function (i, e) { | ||
valid = true; | ||
return this._models.unshift(model); | ||
} | ||
}, | ||
$.each(query, function (key, value) { | ||
if (!e.has(key) || e.get(key) != value) { | ||
valid = false; | ||
/** | ||
* Function: shift | ||
* Removes and returns the first model from the collection. | ||
* | ||
* Return: | ||
* @return {Coco.Model} - The removed <Coco.Model> instance. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.REMOVE> event | ||
*/ | ||
shift: function shift() { | ||
var model = this._models.shift(); | ||
return false; | ||
} | ||
}); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.REMOVE, model)); | ||
if (valid) { | ||
model = e; | ||
return model; | ||
}, | ||
return false; | ||
} | ||
}); | ||
/** | ||
* Function: findBy | ||
* Finds models by given query object. The object contains attributes and their values and findBy will match this | ||
* against the collections models. | ||
* | ||
* Parameter: | ||
* @param {object} query - The object of attributes and values to look for in the collection. | ||
* | ||
* Return: | ||
* @return {Array} - Array of matched <Coco.Model> instances. | ||
*/ | ||
findBy: function findBy(query) { | ||
var models = []; | ||
var valid = false; | ||
$.each(this._models, function (i, e) { | ||
valid = true; | ||
$.each(query, function (key, value) { | ||
if (!e.has(key) || e.get(key) != value) { | ||
valid = false; | ||
return false; | ||
} | ||
}); | ||
return model; | ||
}, | ||
if (valid) { | ||
models.push(e); | ||
} | ||
}); | ||
return models; | ||
}, | ||
/** | ||
* Function: removeBy | ||
* removes all matched models from current collection | ||
* | ||
* Parameter: | ||
* @param {object} query - The object of attributes and values to look for in the collection. | ||
* | ||
* Return: | ||
* @return {Array} - all removed models | ||
*/ | ||
removeBy: function removeBy(query, $silent) { | ||
var _this4 = this; | ||
/** | ||
* Function: findOneBy | ||
* Acts like findBy but returns the first matched model. | ||
* | ||
* Parameter: | ||
* @param {object} query - The object of attributes and values to look for in the collection. | ||
* | ||
* Return: | ||
* @return {Coco.Model|null} - First matched <Coco.Model> instance of null. | ||
*/ | ||
findOneBy: function findOneBy(query) { | ||
var model = null; | ||
var valid = false; | ||
$.each(this._models, function (i, e) { | ||
valid = true; | ||
$.each(query, function (key, value) { | ||
if (!e.has(key) || e.get(key) != value) { | ||
valid = false; | ||
return false; | ||
} | ||
}); | ||
var models = []; | ||
var modelIndex = []; | ||
var valid; | ||
$.each(this._models, function (i, e) { | ||
valid = true; | ||
if (valid) { | ||
model = e; | ||
return false; | ||
} | ||
}); | ||
return model; | ||
}, | ||
$.each(query, function (key, value) { | ||
if (!e.has(key) || e.get(key) != value) { | ||
valid = false; | ||
/** | ||
* Function: removeBy | ||
* removes all matched models from current collection | ||
* | ||
* Parameter: | ||
* @param {object} query - The object of attributes and values to look for in the collection. | ||
* | ||
* Return: | ||
* @return {Array} - all removed models | ||
*/ | ||
removeBy: function removeBy(query, $silent) { | ||
var _this4 = this; | ||
return false; | ||
} | ||
}); | ||
var models = []; | ||
var modelIndex = []; | ||
var valid; | ||
$.each(this._models, function (i, e) { | ||
valid = true; | ||
$.each(query, function (key, value) { | ||
if (!e.has(key) || e.get(key) != value) { | ||
valid = false; | ||
return false; | ||
} | ||
}); | ||
if (valid) { | ||
models.push(e); | ||
modelIndex.push(i); | ||
} | ||
}); | ||
if (valid) { | ||
models.push(e); | ||
modelIndex.push(i); | ||
} | ||
}); | ||
_.each(modelIndex, function (index) { | ||
_this4.removeAt(index, $silent); | ||
}); | ||
_.each(modelIndex, function (index) { | ||
_this4.removeAt(index, $silent); | ||
}); | ||
return models; | ||
}, | ||
return models; | ||
}, | ||
/** | ||
* Function: sortByProperty | ||
* sorts all models in collection by property | ||
* | ||
* Parameter: | ||
* @param {String }propertyName - name of property to sort on | ||
* | ||
* @param {boolean} $descending - (optional) sort direction: descending (default) == true | ||
*/ | ||
sortByProperty: function sortByProperty(propertyName, $descending) { | ||
if ($descending == null) { | ||
$descending = true; | ||
} | ||
/** | ||
* Function: sortByProperty | ||
* sorts all models in collection by property | ||
* | ||
* Parameter: | ||
* @param {String }propertyName - name of property to sort on | ||
* | ||
* @param {boolean} $descending - (optional) sort direction: descending (default) == true | ||
*/ | ||
sortByProperty: function sortByProperty(propertyName, $descending) { | ||
if ($descending == null) { | ||
$descending = true; | ||
} | ||
var val; | ||
var val; | ||
this._models.sort(function (a, b) { | ||
if (a === b) { | ||
return 0; | ||
} | ||
this._models.sort(function (a, b) { | ||
if (a === b) { | ||
return 0; | ||
} | ||
if (a == null) { | ||
//b is not null | ||
return $descending ? 1 : -1; | ||
} | ||
if (a == null) { | ||
//b is not null | ||
return $descending ? 1 : -1; | ||
} | ||
if (b == null) { | ||
//a is not null | ||
return $descending ? -1 : 1; | ||
} | ||
if (b == null) { | ||
//a is not null | ||
return $descending ? -1 : 1; | ||
} | ||
if (a.get(propertyName) === b.get(propertyName)) { | ||
return 0; | ||
} | ||
if (a.get(propertyName) === b.get(propertyName)) { | ||
return 0; | ||
} | ||
if (a.get(propertyName) == null) { | ||
return $descending ? 1 : -1; | ||
} | ||
if (a.get(propertyName) == null) { | ||
return $descending ? 1 : -1; | ||
} | ||
if (b.get(propertyName) == null) { | ||
return $descending ? -1 : 1; | ||
} | ||
if (b.get(propertyName) == null) { | ||
return $descending ? -1 : 1; | ||
} | ||
if (Coco.Math.isNumber(a.get(propertyName))) { | ||
val = parseFloat(a.get(propertyName)) < parseFloat(b.get(propertyName)) ? 1 : parseFloat(a.get(propertyName)) === parseFloat(b.get(propertyName)) ? 0 : -1; | ||
return $descending ? val : -1 * val; | ||
} | ||
if (Coco.Math.isNumber(a.get(propertyName))) { | ||
val = parseFloat(a.get(propertyName)) < parseFloat(b.get(propertyName)) ? 1 : parseFloat(a.get(propertyName)) === parseFloat(b.get(propertyName)) ? 0 : -1; | ||
return $descending ? val : -1 * val; | ||
} //sort alphabetically - UPPER letters are sorted BEFOR lower letters!!! --> convert all letters to lower case | ||
//sort alphabetically - UPPER letters are sorted BEFOR lower letters!!! --> convert all letters to lower case | ||
if (typeof a.get(propertyName) == "string") { | ||
val = a.get(propertyName).toLowerCase() < b.get(propertyName).toLowerCase() ? 1 : a.get(propertyName).toLowerCase() === b.get(propertyName).toLowerCase() ? 0 : -1; | ||
return $descending ? val : -1 * val; | ||
} | ||
//other | ||
val = a.get(propertyName) < b.get(propertyName) ? 1 : a.get(propertyName) === b.get(propertyName) ? 0 : -1; | ||
if (typeof a.get(propertyName) == "string") { | ||
val = a.get(propertyName).toLowerCase() < b.get(propertyName).toLowerCase() ? 1 : a.get(propertyName).toLowerCase() === b.get(propertyName).toLowerCase() ? 0 : -1; | ||
return $descending ? val : -1 * val; | ||
} //other | ||
return $descending ? val : -1 * val; | ||
}); | ||
}, | ||
/** | ||
* Function: size | ||
* Returns the size of the collection. | ||
* | ||
* Return: | ||
* @return {integer} - The size of the collection. | ||
*/ | ||
size: function size() { | ||
return this._models.length; | ||
}, | ||
val = a.get(propertyName) < b.get(propertyName) ? 1 : a.get(propertyName) === b.get(propertyName) ? 0 : -1; | ||
return $descending ? val : -1 * val; | ||
}); | ||
}, | ||
/** | ||
* Function: where | ||
* | ||
* Description: | ||
* Looks through each value in the list, filters models by given object properties | ||
* | ||
* @return {array} - returning an array of all the values that contain all of the key-value pairs listed in properties. | ||
*/ | ||
where: function where(propertyObject) { | ||
return _.where(this.getAllAttributes(), propertyObject); | ||
}, | ||
/** | ||
* Function: size | ||
* Returns the size of the collection. | ||
* | ||
* Return: | ||
* @return {integer} - The size of the collection. | ||
*/ | ||
size: function size() { | ||
return this._models.length; | ||
}, | ||
/** | ||
* Function: where | ||
* | ||
* Description: | ||
* Looks through each value in the list, filters models by given object properties | ||
* | ||
* @return {array} - returning an array of all the values that contain all of the key-value pairs listed in properties. | ||
*/ | ||
where: function where(propertyObject) { | ||
return _.where(this.getAllAttributes(), propertyObject); | ||
}, | ||
/** | ||
* Function: __onModelDestroy | ||
* | ||
* EventListener for Coco.Event.DESTROY - Event | ||
* | ||
* Removes a model from the collection when it's destroyed. | ||
* | ||
* Parameter: | ||
* @param {Coco.ModelEvent} model - model to remove | ||
* @private | ||
*/ | ||
__onModelDestroy: function __onModelDestroy(event) { | ||
this.remove(event.model, true); | ||
}, | ||
/** | ||
* Function: __onModelDestroy | ||
* | ||
* EventListener for Coco.Event.DESTROY - Event | ||
* | ||
* Removes a model from the collection when it's destroyed. | ||
* | ||
* Parameter: | ||
* @param {Coco.ModelEvent} model - model to remove | ||
* @private | ||
*/ | ||
__onModelDestroy: function __onModelDestroy(event) { | ||
this.remove(event.model, true); | ||
}, | ||
/** | ||
* Function: getId | ||
* Returns the internal id. Useful for comparison between different objects. If two object have the same id, | ||
* they are identical. | ||
* | ||
* Return: | ||
* @return {string} - The internal collection id. | ||
*/ | ||
getId: function getId() { | ||
return this.__id; | ||
}, | ||
/** | ||
* Function: getId | ||
* Returns the internal id. Useful for comparison between different objects. If two object have the same id, | ||
* they are identical. | ||
* | ||
* Return: | ||
* @return {string} - The internal collection id. | ||
*/ | ||
getId: function getId() { | ||
return this.__id; | ||
}, | ||
/** | ||
* Function: isEqual | ||
* Checks if two collections are the same | ||
* | ||
* Parameter: | ||
* @param {Coco.Collection} collection - The <Coco.Collection> instance to compare | ||
* | ||
* Return: | ||
* @return {boolean} - True if both collections are the same instance, otherwise false. | ||
*/ | ||
isEqual: function isEqual(collection) { | ||
return this.__id === collection.getId(); | ||
}, | ||
/** | ||
* Function: isEqual | ||
* Checks if two collections are the same | ||
* | ||
* Parameter: | ||
* @param {Coco.Collection} collection - The <Coco.Collection> instance to compare | ||
* | ||
* Return: | ||
* @return {boolean} - True if both collections are the same instance, otherwise false. | ||
*/ | ||
isEqual: function isEqual(collection) { | ||
return this.__id === collection.getId(); | ||
}, | ||
/** | ||
* Function: destroy | ||
* Destroy the collection. Destroying the collection will remove and destroy | ||
* all attached models. | ||
*/ | ||
destroy: function destroy() { | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.DESTROY, this)); | ||
/** | ||
* Function: destroy | ||
* Destroy the collection. Destroying the collection will remove and destroy | ||
* all attached models. | ||
*/ | ||
destroy: function destroy() { | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.DESTROY, this)); | ||
this.each(function (model) { | ||
// Destroy all models | ||
model.destroy(); | ||
}); | ||
this.removeAllEventListener(); | ||
} | ||
this.each(function (model) { | ||
// Destroy all models | ||
model.destroy(); | ||
}); | ||
this.removeAllEventListener(); | ||
} | ||
}); |
"use strict"; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
@@ -11,3 +11,2 @@ var Coco = Coco || {}; | ||
Coco.ModelEvent = require("../event/Coco.ModelEvent.js"); | ||
/** | ||
@@ -36,624 +35,621 @@ * Class: Coco.Model | ||
*/ | ||
module.exports = Coco.Model = dejavu.Class.declare({ | ||
$name: 'Model', | ||
$name: 'Model', | ||
$extends: Coco.ServiceProvider, | ||
$extends: Coco.ServiceProvider, | ||
/** | ||
* The internal model id. | ||
*/ | ||
__id: 0, | ||
/** | ||
* The internal model id. | ||
*/ | ||
__id: 0, | ||
/** | ||
* A private class identifier, copied from `this.$name` | ||
*/ | ||
__$name: "Model", | ||
/** | ||
* A private class identifier, copied from `this.$name` | ||
*/ | ||
__$name: "Model", | ||
/** | ||
* The current attributes of the model. | ||
* | ||
* @type {Object} | ||
*/ | ||
__attributes: {}, | ||
/** | ||
* The current attributes of the model. | ||
* | ||
* @type {Object} | ||
*/ | ||
__attributes: {}, | ||
/** | ||
* The status of the attributes on instantiation. Used to check if the model has changed since it was created. | ||
* | ||
* @type {Object} | ||
*/ | ||
__initialAttributes: null, | ||
/** | ||
* The status of the attributes on instantiation. Used to check if the model has changed since it was created. | ||
* | ||
* @type {Object} | ||
*/ | ||
__initialAttributes: null, | ||
/** | ||
* Hold probable validation error. You can retrieve this with `this.getValidationError()`. It's set internally by | ||
* the `this.isValid()` method. | ||
* | ||
* @type {Object} | ||
*/ | ||
__validationError: null, | ||
/** | ||
* Hold probable validation error. You can retrieve this with `this.getValidationError()`. It's set internally by | ||
* the `this.isValid()` method. | ||
* | ||
* @type {Object} | ||
*/ | ||
__validationError: null, | ||
/** | ||
* Array of observers registered by the $compute flag on computed functions. | ||
*/ | ||
__observers: [], | ||
/** | ||
* Array of observers registered by the $compute flag on computed functions. | ||
*/ | ||
__observers: [], | ||
/** | ||
* Variable: _defaults | ||
* | ||
* Description: | ||
* The default attributes that are assigned to each new instance of the model. | ||
* Default values can be overwritten on instantiation. | ||
* | ||
* @type {Object} | ||
*/ | ||
_defaults: {}, | ||
/** | ||
* Variable: _defaults | ||
* | ||
* Description: | ||
* The default attributes that are assigned to each new instance of the model. | ||
* Default values can be overwritten on instantiation. | ||
* | ||
* @type {Object} | ||
*/ | ||
_defaults: {}, | ||
/** | ||
* Variable: _etherKeys | ||
* | ||
* Description: | ||
* The ether keys, that can be demanded by all Coco.View instances. | ||
* | ||
* @type {Array} | ||
*/ | ||
_etherKeys: [], | ||
/** | ||
* Variable: _etherKeys | ||
* | ||
* Description: | ||
* The ether keys, that can be demanded by all Coco.View instances. | ||
* | ||
* @type {Array} | ||
*/ | ||
_etherKeys: [], | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {Object} $attributes - {optional} The attributes that are set to the models attributes on creation. | ||
*/ | ||
initialize: function initialize($attributes) { | ||
this.__$name = this.$name; | ||
this.__id = Coco.Utils.uniqueId("m"); | ||
/** | ||
* Function: Constructor | ||
* | ||
* Parameter: | ||
* @param {Object} $attributes - {optional} The attributes that are set to the models attributes on creation. | ||
*/ | ||
initialize: function initialize($attributes) { | ||
this.__$name = this.$name; | ||
this.__id = Coco.Utils.uniqueId("m"); | ||
if ($attributes != null) { | ||
for (var i in this._defaults) { | ||
// Check if the value of the attributes key is a function and if so, delete it (because we don't want to overwrite the computed properties) | ||
if (this._defaults.hasOwnProperty(i) && typeof this._defaults[i] === 'function' && $attributes.hasOwnProperty(i)) { | ||
delete $attributes[i]; | ||
} | ||
} | ||
} | ||
if ($attributes != null) { | ||
for (var i in this._defaults) { | ||
this.__attributes = $.extend({}, this._defaults, $attributes != null ? $attributes : {}); | ||
this.__attributes = this.__setObservers(this.__attributes); | ||
this.__initialAttributes = $.extend({}, this.__attributes); | ||
// Check if the value of the attributes key is a function and if so, delete it (because we don't want to overwrite the computed properties) | ||
if (this._defaults.hasOwnProperty(i) && typeof this._defaults[i] === 'function' && $attributes.hasOwnProperty(i)) { | ||
delete $attributes[i]; | ||
} | ||
} | ||
} | ||
this._setCollections(); | ||
this.__attributes = $.extend({}, this._defaults, $attributes != null ? $attributes : {}); | ||
this.__attributes = this.__setObservers(this.__attributes); | ||
this.__initialAttributes = $.extend({}, this.__attributes); | ||
this._setCollections(); | ||
this._onInitialize(); | ||
}, | ||
this._onInitialize(); | ||
}, | ||
/** | ||
* Function: _onInitialize | ||
* | ||
* Description: | ||
* Is called at the end of the initialize method and acts like the hook in <Coco.View> | ||
* | ||
* @protected | ||
*/ | ||
_onInitialize: function _onInitialize() {}, | ||
/** | ||
* Function: _onInitialize | ||
* | ||
* Description: | ||
* Is called at the end of the initialize method and acts like the hook in <Coco.View> | ||
* | ||
* @protected | ||
*/ | ||
_onInitialize: function _onInitialize() {}, | ||
/** | ||
* Function: _setCollections | ||
* | ||
* Description: | ||
* Overwrite this function in your model if you have collections inside the model. You need to set the default | ||
* | ||
* parameters with `new <Coco.Collection> ()` to ensure that a new collection is created. | ||
* | ||
* @protected | ||
*/ | ||
_setCollections: function _setCollections() {}, | ||
/** | ||
* Function: _setCollections | ||
* | ||
* Description: | ||
* Overwrite this function in your model if you have collections inside the model. You need to set the default | ||
* | ||
* parameters with `new <Coco.Collection> ()` to ensure that a new collection is created. | ||
* | ||
* @protected | ||
*/ | ||
_setCollections: function _setCollections() {}, | ||
/** | ||
* Sets the observers and assigns the correct context to the computed properties functions. | ||
* | ||
* @param attributes | ||
* @returns {*} | ||
* @private | ||
*/ | ||
__setObservers: function __setObservers(attributes) { | ||
for (var i in attributes) { | ||
if (attributes.hasOwnProperty(i) && typeof attributes[i] === 'function' && attributes[i].isComputed === true) { | ||
attributes[i] = attributes[i].call(this, i, this.__observers); | ||
} | ||
/** | ||
* Sets the observers and assigns the correct context to the computed properties functions. | ||
* | ||
* @param attributes | ||
* @returns {*} | ||
* @private | ||
*/ | ||
__setObservers: function __setObservers(attributes) { | ||
for (var i in attributes) { | ||
if (attributes.hasOwnProperty(i) && typeof attributes[i] === 'function' && attributes[i].isComputed === true) { | ||
attributes[i] = attributes[i].call(this, i, this.__observers); | ||
} | ||
} | ||
return attributes; | ||
}, | ||
/** | ||
* We trigger the target attribute keys, when an observed attribute changed. | ||
* | ||
* @param attribute | ||
* @private | ||
*/ | ||
__triggerObservers: function __triggerObservers(attribute) { | ||
for (var i in this.__observers) { | ||
if (this.__observers.hasOwnProperty(i) && this.__observers[i].attribute === attribute) { | ||
var newValue = this.get(this.__observers[i].target); | ||
if (newValue !== this.__observers[i].old) { | ||
//this.trigger(Coco.Event.CHANGE_KEY + this.__observers[i].target, newValue, this.__observers[i].old); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.CHANGE_KEY + this.__observers[i].target, this, this.__observers[i].target)); | ||
this.__observers[i].old = newValue; | ||
} | ||
} | ||
} | ||
}, | ||
return attributes; | ||
}, | ||
/** | ||
* Function: add | ||
* Adds a new key value pair(s) to the attributes. If key already exists, <Coco.Model.set> will be called instead. | ||
* | ||
* Parameter: | ||
* @param {string} attribute - The new attribute to add | ||
* | ||
* @param {*} value - The attributes value. | ||
* | ||
* Return: | ||
* @returns {Coco.Model} - The <Coco.Model> instance. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.ADD> event if attribute did not exist before. | ||
*/ | ||
add: function add(attribute, value) { | ||
var object = {}; | ||
typeof attribute === 'string' ? object[attribute] = value : object = attribute; | ||
/** | ||
* We trigger the target attribute keys, when an observed attribute changed. | ||
* | ||
* @param attribute | ||
* @private | ||
*/ | ||
__triggerObservers: function __triggerObservers(attribute) { | ||
for (var i in this.__observers) { | ||
if (this.__observers.hasOwnProperty(i) && this.__observers[i].attribute === attribute) { | ||
var newValue = this.get(this.__observers[i].target); | ||
for (var key in object) { | ||
if (object.hasOwnProperty(key)) { | ||
// Check for existing key in attributes | ||
if (!this.__attributes.hasOwnProperty(key)) { | ||
// Key does not exist, so add it | ||
this.__attributes[key] = object[key]; //this.trigger(Coco.Event.ADD, key, object[key], this); | ||
if (newValue !== this.__observers[i].old) { | ||
//this.trigger(Coco.Event.CHANGE_KEY + this.__observers[i].target, newValue, this.__observers[i].old); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.CHANGE_KEY + this.__observers[i].target, this, this.__observers[i].target)); | ||
this.__observers[i].old = newValue; | ||
} | ||
} | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.ADD, this)); | ||
} else { | ||
// Key exists, set new value | ||
this.set(key, object[key]); | ||
} | ||
}, | ||
} | ||
} | ||
/** | ||
* Function: add | ||
* Adds a new key value pair(s) to the attributes. If key already exists, <Coco.Model.set> will be called instead. | ||
* | ||
* Parameter: | ||
* @param {string} attribute - The new attribute to add | ||
* | ||
* @param {*} value - The attributes value. | ||
* | ||
* Return: | ||
* @returns {Coco.Model} - The <Coco.Model> instance. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.ADD> event if attribute did not exist before. | ||
*/ | ||
add: function add(attribute, value) { | ||
var object = {}; | ||
return this; | ||
}, | ||
typeof attribute === 'string' ? object[attribute] = value : object = attribute; | ||
/** | ||
* Function: set | ||
* Sets one or more attributes. | ||
* | ||
* Parameter: | ||
* @param {string|object} attribute - If a string is given, Coco will use this value as key, if object is given, Coco will overwrite all matched attributes of the object. | ||
* | ||
* @param {*} $value - {optional} The attributes value, if attribute is a string. | ||
* | ||
* Return: | ||
* @returns {Coco.Model} - The <Coco.Model> instance. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.CHANGE> event. | ||
* | ||
* Triggers <Coco.Event.CHANGE_KEY> value on each changes attribute. | ||
*/ | ||
set: function set(attribute, $value) { | ||
var object = {}; | ||
var oldObject = $.extend(true, {}, this.__attributes); | ||
var changed = false; | ||
typeof attribute === 'string' ? object[attribute] = $value : object = attribute; | ||
for (var key in object) { | ||
if (object.hasOwnProperty(key)) { | ||
// Check for existing key in attributes | ||
if (!this.__attributes.hasOwnProperty(key)) { | ||
// Key does not exist, so add it | ||
this.__attributes[key] = object[key]; | ||
for (var key in object) { | ||
if (object.hasOwnProperty(key)) { | ||
this.__attributes[key] = object[key]; // TODO: deep check for objects. | ||
//this.trigger(Coco.Event.ADD, key, object[key], this); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.ADD, this)); | ||
} else { | ||
// Key exists, set new value | ||
this.set(key, object[key]); | ||
} | ||
} | ||
} | ||
if (object[key] !== oldObject[key]) { | ||
changed = true; // Throw special key changed event | ||
//this.trigger(Coco.Event.CHANGE_KEY + key, object[key], this, oldObject[key]); | ||
return this; | ||
}, | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.CHANGE_KEY + key, this, key)); // Trigger all dependent computed attributes when an observed attribute changed. | ||
/** | ||
* Function: set | ||
* Sets one or more attributes. | ||
* | ||
* Parameter: | ||
* @param {string|object} attribute - If a string is given, Coco will use this value as key, if object is given, Coco will overwrite all matched attributes of the object. | ||
* | ||
* @param {*} $value - {optional} The attributes value, if attribute is a string. | ||
* | ||
* Return: | ||
* @returns {Coco.Model} - The <Coco.Model> instance. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.CHANGE> event. | ||
* | ||
* Triggers <Coco.Event.CHANGE_KEY> value on each changes attribute. | ||
*/ | ||
set: function set(attribute, $value) { | ||
var object = {}; | ||
var oldObject = $.extend(true, {}, this.__attributes); | ||
var changed = false; | ||
typeof attribute === 'string' ? object[attribute] = $value : object = attribute; | ||
this.__triggerObservers(key); | ||
} | ||
} | ||
} | ||
for (var key in object) { | ||
if (object.hasOwnProperty(key)) { | ||
this.__attributes[key] = object[key]; | ||
if (changed) { | ||
// Throw default changed event | ||
//this.trigger(Coco.Event.CHANGE, object, this, oldObject); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.CHANGE, this)); | ||
} | ||
// TODO: deep check for objects. | ||
if (object[key] !== oldObject[key]) { | ||
changed = true; | ||
return this; | ||
}, | ||
// Throw special key changed event | ||
//this.trigger(Coco.Event.CHANGE_KEY + key, object[key], this, oldObject[key]); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.CHANGE_KEY + key, this, key)); | ||
/** | ||
* Function: get | ||
* Gets a value by key. If no key is passed the whole object is returned. This can be also achieved by calling `this.getAll`. | ||
* | ||
* Parameter: | ||
* @param {string} $attribute - {optional} The key to return the value of | ||
* | ||
* @param {integer} $castTo - {optional} Parse the value to given type. Should refer to a constant from `Coco.Util` | ||
* | ||
* @param {boolean} $fix - {optional} If set to `true` the casted value will be saved to the attributes. | ||
* | ||
* Return: | ||
* @returns {*} - The value of the key. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.CHANGE> and <Coco.Event.Event_CHANGE_KEY> events, if $fix is set to true. | ||
*/ | ||
get: function get($attribute, $castTo, $fix) { | ||
if ($attribute == null) { | ||
// Return all attributes of this model | ||
var ret = {}; | ||
// Trigger all dependent computed attributes when an observed attribute changed. | ||
this.__triggerObservers(key); | ||
} | ||
} | ||
for (var i in this.__attributes) { | ||
if (this.__attributes.hasOwnProperty(i)) { | ||
ret[i] = typeof this.__attributes[i] === 'function' && this.__attributes[i].isComputed ? this.__attributes[i]() : this.__attributes[i]; | ||
} | ||
} | ||
if (changed) { | ||
// Throw default changed event | ||
//this.trigger(Coco.Event.CHANGE, object, this, oldObject); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.CHANGE, this)); | ||
return ret; | ||
} | ||
if ($castTo == null) { | ||
// Return value of given key | ||
if (this.__attributes.hasOwnProperty($attribute)) { | ||
// If value is a function, call it | ||
if (typeof this.__attributes[$attribute] === 'function' && this.__attributes[$attribute].isComputed) { | ||
return this.__attributes[$attribute].call(this); | ||
} | ||
return this; | ||
}, | ||
return this.__attributes[$attribute]; | ||
} else { | ||
throw new Error("Tried to get '" + $attribute + "' in model '" + this.$name + "'. The key does not exist. Maybe you have a typo."); | ||
} | ||
} | ||
/** | ||
* Function: get | ||
* Gets a value by key. If no key is passed the whole object is returned. This can be also achieved by calling `this.getAll`. | ||
* | ||
* Parameter: | ||
* @param {string} $attribute - {optional} The key to return the value of | ||
* | ||
* @param {integer} $castTo - {optional} Parse the value to given type. Should refer to a constant from `Coco.Util` | ||
* | ||
* @param {boolean} $fix - {optional} If set to `true` the casted value will be saved to the attributes. | ||
* | ||
* Return: | ||
* @returns {*} - The value of the key. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.CHANGE> and <Coco.Event.Event_CHANGE_KEY> events, if $fix is set to true. | ||
*/ | ||
get: function get($attribute, $castTo, $fix) { | ||
if ($attribute == null) { | ||
// Return all attributes of this model | ||
var ret = {}; | ||
if ($fix == null) { | ||
console.log("Coco.Utils.cast ... ???"); | ||
return this.__attributes.hasOwnProperty($attribute) ? Coco.Utils.cast(this.__attributes[$attribute], $castTo, $attribute) : null; | ||
} | ||
for (var i in this.__attributes) { | ||
if (this.__attributes.hasOwnProperty(i)) { | ||
ret[i] = typeof this.__attributes[i] === 'function' && this.__attributes[i].isComputed ? this.__attributes[i]() : this.__attributes[i]; | ||
} | ||
} | ||
if (this.__attributes.hasOwnProperty($attribute)) { | ||
// Save casted value into this attributes | ||
this.cast($attribute, $castTo); | ||
return this.__attributes[$attribute]; | ||
} | ||
return ret; | ||
} | ||
throw new Error("Tried to get '" + $attribute + "' in model '" + this.$name + "'. The key does not exist. Maybe you have a typo."); | ||
}, | ||
if ($castTo == null) { | ||
// Return value of given key | ||
if (this.__attributes.hasOwnProperty($attribute)) { | ||
// If value is a function, call it | ||
if (typeof this.__attributes[$attribute] === 'function' && this.__attributes[$attribute].isComputed) { | ||
return this.__attributes[$attribute].call(this); | ||
} | ||
/** | ||
* Function: boundGet | ||
* A bound variant of <Coco.Model.get> | ||
* | ||
* Parameter: | ||
* @param {string} $key - {optional} The key to return the value of | ||
* @param {integer} $castTo - {optional} Parse the value to given type. Should refer to a constant from `Coco.Util` | ||
* @param {boolean} $fix - {optional} If set to `true` the casted value will be saved to the attributes. | ||
* | ||
* Return: | ||
* @returns {*} - The value of the key | ||
*/ | ||
boundGet: function ($key, $castTo, $fix) { | ||
return this.get($key, $castTo, $fix); | ||
}.$bound(), | ||
return this.__attributes[$attribute]; | ||
} else { | ||
throw new Error("Tried to get '" + $attribute + "' in model '" + this.$name + "'. The key does not exist. Maybe you have a typo."); | ||
} | ||
} | ||
/** | ||
* Function: getAttributes | ||
* Returns the attributes object. | ||
* | ||
* Return: | ||
* @returns {Object} - All attributes of the model instance. | ||
*/ | ||
getAttributes: function getAttributes() { | ||
var attributes = {}; | ||
var keys = this.getKeys(); | ||
if ($fix == null) { | ||
console.log("Coco.Utils.cast ... ???"); | ||
return this.__attributes.hasOwnProperty($attribute) ? Coco.Utils.cast(this.__attributes[$attribute], $castTo, $attribute) : null; | ||
} | ||
for (var i = 0; i < keys.length; i++) { | ||
var key = keys[i]; | ||
var value = this.get(key); | ||
if (this.__attributes.hasOwnProperty($attribute)) { | ||
// Save casted value into this attributes | ||
this.cast($attribute, $castTo); | ||
if (value instanceof Coco.Model) { | ||
//resolve all Coco.Models | ||
value = value.getAttributes(); | ||
} | ||
return this.__attributes[$attribute]; | ||
} | ||
if (value instanceof Coco.Collection) { | ||
//resolve all Coco.Collections | ||
value = value.getAllAttributes(); | ||
} | ||
throw new Error("Tried to get '" + $attribute + "' in model '" + this.$name + "'. The key does not exist. Maybe you have a typo."); | ||
}, | ||
if (value instanceof Array) { | ||
//search for Coco.Models within an array | ||
var val = []; | ||
/** | ||
* Function: boundGet | ||
* A bound variant of <Coco.Model.get> | ||
* | ||
* Parameter: | ||
* @param {string} $key - {optional} The key to return the value of | ||
* @param {integer} $castTo - {optional} Parse the value to given type. Should refer to a constant from `Coco.Util` | ||
* @param {boolean} $fix - {optional} If set to `true` the casted value will be saved to the attributes. | ||
* | ||
* Return: | ||
* @returns {*} - The value of the key | ||
*/ | ||
boundGet: function ($key, $castTo, $fix) { | ||
return this.get($key, $castTo, $fix); | ||
}.$bound(), | ||
for (var j = 0; j < value.length; j++) { | ||
var innerValue = value[j]; | ||
/** | ||
* Function: getAttributes | ||
* Returns the attributes object. | ||
* | ||
* Return: | ||
* @returns {Object} - All attributes of the model instance. | ||
*/ | ||
getAttributes: function getAttributes() { | ||
var attributes = {}; | ||
var keys = this.getKeys(); | ||
if (innerValue instanceof Coco.Model) { | ||
innerValue = innerValue.getAttributes(); | ||
} | ||
for (var i = 0; i < keys.length; i++) { | ||
var key = keys[i]; | ||
var value = this.get(key); | ||
if (innerValue instanceof Coco.Collection) { | ||
innerValue = innerValue.getAllAttributes(); | ||
} | ||
if (value instanceof Coco.Model) { | ||
//resolve all Coco.Models | ||
value = value.getAttributes(); | ||
} | ||
val.push(innerValue); | ||
} | ||
if (value instanceof Coco.Collection) { | ||
//resolve all Coco.Collections | ||
value = value.getAllAttributes(); | ||
} | ||
value = val; | ||
} | ||
if (value instanceof Array) { | ||
//search for Coco.Models within an array | ||
var val = []; | ||
attributes[key] = value; | ||
} | ||
for (var j = 0; j < value.length; j++) { | ||
var innerValue = value[j]; | ||
return attributes; | ||
}, | ||
if (innerValue instanceof Coco.Model) { | ||
innerValue = innerValue.getAttributes(); | ||
} | ||
/** | ||
* Function: getKeys | ||
* Returns all attribute keys as an array. | ||
* | ||
* Return: | ||
* @return {Array} - All attribute keys of the model instance as an Array. | ||
*/ | ||
getKeys: function getKeys() { | ||
// Check for ECMA5 | ||
if (typeof Object.keys === "function") { | ||
return Object.keys(this.__attributes); | ||
} | ||
if (innerValue instanceof Coco.Collection) { | ||
innerValue = innerValue.getAllAttributes(); | ||
} | ||
var keys = []; | ||
val.push(innerValue); | ||
} | ||
for (var k in this.__attributes) { | ||
if (this.__attributes.hasOwnProperty(k)) { | ||
keys.push(k); | ||
} | ||
} | ||
value = val; | ||
} | ||
return keys; | ||
}, | ||
attributes[key] = value; | ||
} | ||
/** | ||
* Function: has | ||
* Returns `true` if the value is defined, otherwise `false`. | ||
* | ||
* Parameter: | ||
* @param {string} key - The attribute to check for it's existence. | ||
* | ||
* @param {boolean} $strict - {optional} If set to true, also attributes with the value null will return false | ||
* | ||
* Return: | ||
* @return {boolean} - True if the key exists, otherwise false. | ||
*/ | ||
has: function has(key, $strict) { | ||
if ($strict) { | ||
// Check also for defined value | ||
return this.__attributes.hasOwnProperty(key) && this.__attributes[key] != null && this.__attributes[key].length !== 0; | ||
} // Check only for key | ||
return attributes; | ||
}, | ||
/** | ||
* Function: getKeys | ||
* Returns all attribute keys as an array. | ||
* | ||
* Return: | ||
* @return {Array} - All attribute keys of the model instance as an Array. | ||
*/ | ||
getKeys: function getKeys() { | ||
// Check for ECMA5 | ||
if (typeof Object.keys === "function") { | ||
return Object.keys(this.__attributes); | ||
} | ||
return this.__attributes.hasOwnProperty(key); | ||
}, | ||
var keys = []; | ||
/** | ||
* Function: is | ||
* Checks if `key` is type of the parameter `type`. | ||
* | ||
* Parameter: | ||
* @param {string} attribute - The models attribute to check | ||
* @param {integer} type - The type to check for. Should refer to a constant from `Coco.Util` | ||
* | ||
* Return: | ||
* @return {boolean} True if the typed is matched, otherwise false. | ||
*/ | ||
is: function is(attribute, type) { | ||
console.log("Coco.Utils. type"); | ||
for (var k in this.__attributes) { | ||
if (this.__attributes.hasOwnProperty(k)) { | ||
keys.push(k); | ||
} | ||
} | ||
if (!this.__attributes.hasOwnProperty(attribute)) { | ||
return type === Coco.Utils.UNDEFINED; | ||
} | ||
return keys; | ||
}, | ||
var value = this.__attributes[attribute]; | ||
/** | ||
* Function: has | ||
* Returns `true` if the value is defined, otherwise `false`. | ||
* | ||
* Parameter: | ||
* @param {string} key - The attribute to check for it's existence. | ||
* | ||
* @param {boolean} $strict - {optional} If set to true, also attributes with the value null will return false | ||
* | ||
* Return: | ||
* @return {boolean} - True if the key exists, otherwise false. | ||
*/ | ||
has: function has(key, $strict) { | ||
if ($strict) { | ||
// Check also for defined value | ||
return this.__attributes.hasOwnProperty(key) && this.__attributes[key] != null && this.__attributes[key].length !== 0; | ||
} | ||
switch (type) { | ||
case Coco.Utils.INTEGER: | ||
return typeof value === 'number' && value % 1 == 0; | ||
// Check only for key | ||
return this.__attributes.hasOwnProperty(key); | ||
}, | ||
case Coco.Utils.FLOAT: | ||
// Returns false, if we have an integer value or sth like this: 1.0 | ||
return typeof value === 'number' && value % 1 != 0; | ||
/** | ||
* Function: is | ||
* Checks if `key` is type of the parameter `type`. | ||
* | ||
* Parameter: | ||
* @param {string} attribute - The models attribute to check | ||
* @param {integer} type - The type to check for. Should refer to a constant from `Coco.Util` | ||
* | ||
* Return: | ||
* @return {boolean} True if the typed is matched, otherwise false. | ||
*/ | ||
is: function is(attribute, type) { | ||
console.log("Coco.Utils. type"); | ||
if (!this.__attributes.hasOwnProperty(attribute)) { | ||
return type === Coco.Utils.UNDEFINED; | ||
} | ||
case Coco.Utils.STRING: | ||
return typeof value === 'string'; | ||
var value = this.__attributes[attribute]; | ||
case Coco.Utils.ARRAY: | ||
return value instanceof Array; | ||
switch (type) { | ||
case Coco.Utils.INTEGER: | ||
return typeof value === 'number' && value % 1 == 0; | ||
case Coco.Utils.OBJECT: | ||
return _typeof(value) === 'object' && !(value instanceof Array); | ||
case Coco.Utils.FLOAT: | ||
// Returns false, if we have an integer value or sth like this: 1.0 | ||
return typeof value === 'number' && value % 1 != 0; | ||
case Coco.Utils.NULL: | ||
return value === null; | ||
case Coco.Utils.STRING: | ||
return typeof value === 'string'; | ||
default: | ||
return false; | ||
} | ||
}, | ||
case Coco.Utils.ARRAY: | ||
return value instanceof Array; | ||
/** | ||
* Function: remove($key) | ||
* Removes a key from the model. | ||
* | ||
* Parameter: | ||
* @param {string} key - The key to remove. | ||
*/ | ||
remove: function remove(key) { | ||
if (this.has(key)) { | ||
delete this.__attributes[key]; | ||
} | ||
}, | ||
case Coco.Utils.OBJECT: | ||
return (typeof value === "undefined" ? "undefined" : _typeof(value)) === 'object' && !(value instanceof Array); | ||
/** | ||
* Function reset | ||
* Resets the attributes of a model to its defaults. | ||
* | ||
* Parameter: | ||
* @param {boolean} $toDefaults - {optional} if set to true the model will be reset with the `this._defaults` object. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.RESET> event. | ||
*/ | ||
reset: function reset($toDefaults) { | ||
var collections = {}; | ||
case Coco.Utils.NULL: | ||
return value === null; | ||
for (var i in this.__attributes) { | ||
if (this.__attributes.hasOwnProperty(i) && this.__attributes[i] instanceof Coco.Event) { | ||
collections[i] = this.__attributes[i].reset(); | ||
} | ||
} | ||
default: | ||
return false; | ||
} | ||
}, | ||
if ($toDefaults) { | ||
this.__attributes = $.extend({}, this._defaults, collections); | ||
this.__initialAttributes = $.extend({}, this.__attributes); | ||
} else { | ||
this.__attributes = $.extend({}, this.__initialAttributes, collections); | ||
} //this.trigger(Coco.Event.RESET); | ||
/** | ||
* Function: remove($key) | ||
* Removes a key from the model. | ||
* | ||
* Parameter: | ||
* @param {string} key - The key to remove. | ||
*/ | ||
remove: function remove(key) { | ||
if (this.has(key)) { | ||
delete this.__attributes[key]; | ||
} | ||
}, | ||
/** | ||
* Function reset | ||
* Resets the attributes of a model to its defaults. | ||
* | ||
* Parameter: | ||
* @param {boolean} $toDefaults - {optional} if set to true the model will be reset with the `this._defaults` object. | ||
* | ||
* Event: | ||
* Triggers <Coco.Event.RESET> event. | ||
*/ | ||
reset: function reset($toDefaults) { | ||
var collections = {}; | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.RESET, this)); | ||
}, | ||
for (var i in this.__attributes) { | ||
if (this.__attributes.hasOwnProperty(i) && this.__attributes[i] instanceof Coco.Event) { | ||
collections[i] = this.__attributes[i].reset(); | ||
} | ||
} | ||
/** | ||
* Function: cast | ||
* Casts a attributes value to given `type` and stores it to the attributes. | ||
* | ||
* Parameter: | ||
* @param {string} attribute - The attribute key | ||
* @param {integer} type - The type to cast to. Should refer to a constant from `Coco.Utils` | ||
* | ||
* Return: | ||
* @return {*} - The casted value of the attribute. | ||
* | ||
* Event: | ||
* See <Coco.Model.set> for information what events are triggered. | ||
*/ | ||
cast: function cast(attribute, type) { | ||
this.set(attribute, Coco.Utils.cast(this.get(attribute), type, attribute)); | ||
return this.get(attribute); | ||
}, | ||
if ($toDefaults) { | ||
this.__attributes = $.extend({}, this._defaults, collections); | ||
this.__initialAttributes = $.extend({}, this.__attributes); | ||
} else { | ||
this.__attributes = $.extend({}, this.__initialAttributes, collections); | ||
} | ||
/** | ||
* Function: isValid | ||
* Checks if model is valid by calling user specified `this._validate` function. | ||
* | ||
* Return: | ||
* @return {boolean} | ||
* | ||
* Event: | ||
* @event Triggers `invalid` if model validation failed, otherwise `valid` | ||
*/ | ||
isValid: function isValid() { | ||
this.__validationError = null; | ||
//this.trigger(Coco.Event.RESET); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.RESET, this)); | ||
}, | ||
var result = this._validate(this.getAttributes()); | ||
/** | ||
* Function: cast | ||
* Casts a attributes value to given `type` and stores it to the attributes. | ||
* | ||
* Parameter: | ||
* @param {string} attribute - The attribute key | ||
* @param {integer} type - The type to cast to. Should refer to a constant from `Coco.Utils` | ||
* | ||
* Return: | ||
* @return {*} - The casted value of the attribute. | ||
* | ||
* Event: | ||
* See <Coco.Model.set> for information what events are triggered. | ||
*/ | ||
cast: function cast(attribute, type) { | ||
this.set(attribute, Coco.Utils.cast(this.get(attribute), type, attribute)); | ||
if (result !== true) { | ||
this.__validationError = result; //this.trigger(Coco.Event.INVALID, result, this); | ||
return this.get(attribute); | ||
}, | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.INVALID, this)); | ||
/** | ||
* Function: isValid | ||
* Checks if model is valid by calling user specified `this._validate` function. | ||
* | ||
* Return: | ||
* @return {boolean} | ||
* | ||
* Event: | ||
* @event Triggers `invalid` if model validation failed, otherwise `valid` | ||
*/ | ||
isValid: function isValid() { | ||
this.__validationError = null; | ||
var result = this._validate(this.getAttributes()); | ||
return false; | ||
} else { | ||
//this.trigger(Coco.Event.VALID, this); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.VALID, this)); | ||
} | ||
if (result !== true) { | ||
this.__validationError = result; | ||
return true; | ||
}, | ||
//this.trigger(Coco.Event.INVALID, result, this); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.INVALID, this)); | ||
/** | ||
* Function: _validate | ||
* Is called by `this.isValid` from within the model. Return anything but `true` to indicate that the validation failed. | ||
* | ||
* Parameter: | ||
* @param {object} attrs - The attributes of the model | ||
* | ||
* Return: | ||
* @return {*} | ||
* | ||
* @protected | ||
*/ | ||
_validate: function _validate(attrs) { | ||
return true; | ||
}, | ||
return false; | ||
} else { | ||
//this.trigger(Coco.Event.VALID, this); | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.VALID, this)); | ||
} | ||
/** | ||
* Function: getValidationError | ||
* Returns the validation errors. | ||
* | ||
* Return: | ||
* @return {null|Object} | ||
*/ | ||
getValidationError: function getValidationError() { | ||
return this.__validationError; | ||
}, | ||
return true; | ||
}, | ||
/** | ||
* Function: getEtherKeys | ||
* Returns the ether keys. | ||
* | ||
* Return: | ||
* @return {Array} | ||
*/ | ||
getEtherKeys: function getEtherKeys() { | ||
return this._etherKeys; | ||
}, | ||
/** | ||
* Function: _validate | ||
* Is called by `this.isValid` from within the model. Return anything but `true` to indicate that the validation failed. | ||
* | ||
* Parameter: | ||
* @param {object} attrs - The attributes of the model | ||
* | ||
* Return: | ||
* @return {*} | ||
* | ||
* @protected | ||
*/ | ||
_validate: function _validate(attrs) { | ||
return true; | ||
}, | ||
/** | ||
* Function: getId | ||
* Returns the internal id. Useful for comparison between different objects. If two object have the same id, | ||
* they are identical. | ||
* | ||
* Return: | ||
* @return {string} | ||
*/ | ||
getId: function getId() { | ||
return this.__id; | ||
}, | ||
/** | ||
* Function: getValidationError | ||
* Returns the validation errors. | ||
* | ||
* Return: | ||
* @return {null|Object} | ||
*/ | ||
getValidationError: function getValidationError() { | ||
return this.__validationError; | ||
}, | ||
/** | ||
* Function: isEqual | ||
* Checks if two models are the same | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - The <Coco.Model> instance | ||
* | ||
* Return: | ||
* @return {boolean} - True if both are equal. | ||
*/ | ||
isEqual: function isEqual(model) { | ||
return this.__id === model.getId(); | ||
}, | ||
/** | ||
* Function: getEtherKeys | ||
* Returns the ether keys. | ||
* | ||
* Return: | ||
* @return {Array} | ||
*/ | ||
getEtherKeys: function getEtherKeys() { | ||
return this._etherKeys; | ||
}, | ||
/** | ||
* Function: destroy | ||
* Destroy the model | ||
*/ | ||
destroy: function destroy() { | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.DESTROY, this)); //remove all eventListener | ||
/** | ||
* Function: getId | ||
* Returns the internal id. Useful for comparison between different objects. If two object have the same id, | ||
* they are identical. | ||
* | ||
* Return: | ||
* @return {string} | ||
*/ | ||
getId: function getId() { | ||
return this.__id; | ||
}, | ||
/** | ||
* Function: isEqual | ||
* Checks if two models are the same | ||
* | ||
* Parameter: | ||
* @param {Coco.Model} model - The <Coco.Model> instance | ||
* | ||
* Return: | ||
* @return {boolean} - True if both are equal. | ||
*/ | ||
isEqual: function isEqual(model) { | ||
return this.__id === model.getId(); | ||
}, | ||
/** | ||
* Function: destroy | ||
* Destroy the model | ||
*/ | ||
destroy: function destroy() { | ||
this._dispatchEvent(new Coco.ModelEvent(Coco.Event.DESTROY, this)); | ||
//remove all eventListener | ||
this.removeAllEventListener(); | ||
} | ||
this.removeAllEventListener(); | ||
} | ||
}); |
@@ -18,120 +18,117 @@ "use strict"; | ||
*/ | ||
module.exports = dejavu.Class.declare({ | ||
$name: 'Router', | ||
$name: 'Router', | ||
$extends: Coco.ServiceProvider, | ||
$inject: ['router'], | ||
__id: Coco.Utils.uniqueId("r"), | ||
$extends: Coco.ServiceProvider, | ||
/** | ||
* A jQuery element where the view gets appended to. | ||
*/ | ||
__$container: null, | ||
$inject: ['router'], | ||
/** | ||
* Function: Constructor | ||
* | ||
* Description: | ||
* Initialize the routing functionality of Coco. | ||
* | ||
* @param selector {string} - A CSS selector to append the current views. | ||
* @param routing {Object} - A object containing routing information. | ||
* @param $initialPath {Object} - A optional $initialPath to start the application with. Defaults to '/' | ||
*/ | ||
initialize: function initialize(selector, routing, $initialPath) { | ||
var _this = this; | ||
__id: Coco.Utils.uniqueId("r"), | ||
//you HAVE to use constructor, because of the given variables | ||
this.$super(); | ||
/** | ||
* A jQuery element where the view gets appended to. | ||
*/ | ||
__$container: null, | ||
this._getService("router").addEventListener(Coco.RouterEvent.SHOW_VIEW, function () { | ||
_this.__onShowView(); | ||
}); | ||
/** | ||
* Function: Constructor | ||
* | ||
* Description: | ||
* Initialize the routing functionality of Coco. | ||
* | ||
* @param selector {string} - A CSS selector to append the current views. | ||
* @param routing {Object} - A object containing routing information. | ||
* @param $initialPath {Object} - A optional $initialPath to start the application with. Defaults to '/' | ||
*/ | ||
initialize: function initialize(selector, routing, $initialPath) { | ||
var _this = this; | ||
this._getService("router").addEventListener(Coco.RouterEvent.HIDE_VIEW, function () { | ||
_this.__onHideView(); | ||
}); | ||
//you HAVE to use constructor, because of the given variables | ||
this.$super(); | ||
this.__$container = $(selector); | ||
this.$services.router.setContainer(this.__$container); // Copy the routing object to prevent any modification during application lifetime. | ||
this._getService("router").addEventListener(Coco.RouterEvent.SHOW_VIEW, function () { | ||
_this.__onShowView(); | ||
}); | ||
this._getService("router").addEventListener(Coco.RouterEvent.HIDE_VIEW, function () { | ||
_this.__onHideView(); | ||
}); | ||
this.__createRouting($.extend({}, routing), $initialPath); | ||
}, | ||
this.__$container = $(selector); | ||
/** | ||
* Adds the routing object to the routerService and starts the routing. | ||
* | ||
* @param routing | ||
* @param $initialPath | ||
* @private | ||
*/ | ||
__createRouting: function __createRouting(routing, $initialPath) { | ||
for (var i in routing) { | ||
if (routing.hasOwnProperty(i)) { | ||
this.$services.router.addRoute(i, routing[i]); | ||
} | ||
} | ||
this.$services.router.setContainer(this.__$container); | ||
this.$services.router.start($initialPath); | ||
}, | ||
// Copy the routing object to prevent any modification during application lifetime. | ||
this.__createRouting($.extend({}, routing), $initialPath); | ||
}, | ||
/** | ||
* This function checks if the cached routing anchor is still in the DOM or has been removed or replaced during | ||
* the lifetime of the application. | ||
* | ||
* @returns {boolean} | ||
* @private | ||
*/ | ||
__isRoutingAnchorStillInDom: function __isRoutingAnchorStillInDom() { | ||
return this.__$container.closest('body').length > 0; | ||
}, | ||
/** | ||
* Adds the routing object to the routerService and starts the routing. | ||
* | ||
* @param routing | ||
* @param $initialPath | ||
* @private | ||
*/ | ||
__createRouting: function __createRouting(routing, $initialPath) { | ||
for (var i in routing) { | ||
if (routing.hasOwnProperty(i)) { | ||
this.$services.router.addRoute(i, routing[i]); | ||
} | ||
} | ||
/** | ||
* Reselect the routing anchor, if it has been replaced. | ||
* | ||
* @private | ||
*/ | ||
__reselectAnchor: function __reselectAnchor() { | ||
this.__$container = $(this.__$container.selector); | ||
}, | ||
this.$services.router.start($initialPath); | ||
}, | ||
/** | ||
* Show the new view. | ||
* | ||
* @param $dom {Array} - {optional} The dom of the view | ||
* @private | ||
*/ | ||
__onShowView: function __onShowView($dom) { | ||
if (!this.__isRoutingAnchorStillInDom()) { | ||
this.__reselectAnchor(); | ||
} | ||
/** | ||
* This function checks if the cached routing anchor is still in the DOM or has been removed or replaced during | ||
* the lifetime of the application. | ||
* | ||
* @returns {boolean} | ||
* @private | ||
*/ | ||
__isRoutingAnchorStillInDom: function __isRoutingAnchorStillInDom() { | ||
return this.__$container.closest('body').length > 0; | ||
}, | ||
this.__$container.append($dom); | ||
/** | ||
* Reselect the routing anchor, if it has been replaced. | ||
* | ||
* @private | ||
*/ | ||
__reselectAnchor: function __reselectAnchor() { | ||
this.__$container = $(this.__$container.selector); | ||
}, | ||
window.scrollTo(0, 0); | ||
}, | ||
/** | ||
* Show the new view. | ||
* | ||
* @param $dom {Array} - {optional} The dom of the view | ||
* @private | ||
*/ | ||
__onShowView: function __onShowView($dom) { | ||
if (!this.__isRoutingAnchorStillInDom()) { | ||
this.__reselectAnchor(); | ||
} | ||
/** | ||
* Hide the old view. | ||
* | ||
* @private | ||
*/ | ||
__onHideView: function __onHideView() { | ||
if (!this.__isRoutingAnchorStillInDom()) { | ||
this.__reselectAnchor(); | ||
} | ||
}, | ||
this.__$container.append($dom); | ||
window.scrollTo(0, 0); | ||
}, | ||
/** | ||
* Hide the old view. | ||
* | ||
* @private | ||
*/ | ||
__onHideView: function __onHideView() { | ||
if (!this.__isRoutingAnchorStillInDom()) { | ||
this.__reselectAnchor(); | ||
} | ||
}, | ||
/** | ||
* Function: getId | ||
* returns unique id of this ServiceProvider | ||
* | ||
* @returns {String} | ||
*/ | ||
getId: function getId() { | ||
return this.__id; | ||
} | ||
/** | ||
* Function: getId | ||
* returns unique id of this ServiceProvider | ||
* | ||
* @returns {String} | ||
*/ | ||
getId: function getId() { | ||
return this.__id; | ||
} | ||
}); |
@@ -21,557 +21,571 @@ "use strict"; | ||
*/ | ||
'use strict'; | ||
Coco.RouterService = dejavu.Class.declare({ | ||
$name: 'RouterService', | ||
$name: 'RouterService', | ||
$extends: Coco.Service, | ||
$serviceId: 'router', | ||
$extends: Coco.Service, | ||
/** | ||
* Holds the routing object, that defines routes and their corresponding views that should be shown. | ||
*/ | ||
__routes: {}, | ||
$serviceId: 'router', | ||
/** | ||
* Holds the current route plus it's current mapped arguments. | ||
*/ | ||
__currentRoute: null, | ||
/** | ||
* Holds the routing object, that defines routes and their corresponding views that should be shown. | ||
*/ | ||
__routes: {}, | ||
/** | ||
* If the hashchange event has been triggered, a next route will be determined that is stored here and copied to | ||
* __currentRoute after the views have been switched. | ||
*/ | ||
__nextRoute: null, | ||
/** | ||
* Holds the current route plus it's current mapped arguments. | ||
*/ | ||
__currentRoute: null, | ||
/** | ||
* The path history to refer to for back and forth manipulation. | ||
*/ | ||
__pathHistory: [], | ||
/** | ||
* If the hashchange event has been triggered, a next route will be determined that is stored here and copied to | ||
* __currentRoute after the views have been switched. | ||
*/ | ||
__nextRoute: null, | ||
/** | ||
* The current path history index. | ||
*/ | ||
__pathHistoryIndex: -1, | ||
/** | ||
* The path history to refer to for back and forth manipulation. | ||
*/ | ||
__pathHistory: [], | ||
/** | ||
* Function: _onServicesInjected | ||
* | ||
* Description: | ||
* override callback, after service initialization was completed | ||
* | ||
* Event: | ||
* triggers <Coco.RouterEvent>(Coco.RouterEvent.HIDE_VIEW, ...) when current views is hidden | ||
* triggers <Coco.RouterEvent>(Coco.RouterEvent.CHANGE_ROUTE, ...) when route is changing | ||
*/ | ||
_onServicesInjected: function _onServicesInjected() { | ||
var _this = this; | ||
$(window).on('hashchange', function (event) { | ||
_this.__onRouteChanged(event); | ||
}); | ||
/** | ||
* The current path history index. | ||
*/ | ||
__pathHistoryIndex: -1, | ||
/** | ||
* Function: _onServicesInjected | ||
* The syntax in the helper is e.g. "id:id, linkOne:someKeyInTheModel" | ||
* We split the string to a array of these key1:key2 pairs. | ||
* | ||
* Description: | ||
* override callback, after service initialization was completed | ||
* | ||
* Event: | ||
* triggers <Coco.RouterEvent>(Coco.RouterEvent.HIDE_VIEW, ...) when current views is hidden | ||
* triggers <Coco.RouterEvent>(Coco.RouterEvent.CHANGE_ROUTE, ...) when route is changing | ||
* In the for loop we then split the key1:key2 and add key1 as key to the parsedParams object and the value of | ||
* key2 as the key1 value. | ||
*/ | ||
_onServicesInjected: function _onServicesInjected() { | ||
var _this = this; | ||
$(window).on('hashchange', function (event) { | ||
_this.__onRouteChanged(event); | ||
}); | ||
Handlebars.registerHelper('route', function (v1, v2) { | ||
var params = []; | ||
/** | ||
* The syntax in the helper is e.g. "id:id, linkOne:someKeyInTheModel" | ||
* We split the string to a array of these key1:key2 pairs. | ||
* | ||
* In the for loop we then split the key1:key2 and add key1 as key to the parsedParams object and the value of | ||
* key2 as the key1 value. | ||
*/ | ||
Handlebars.registerHelper('route', function (v1, v2) { | ||
var params = []; | ||
if (typeof v2 == 'string') { | ||
params = v2.replace(/\s+/g, '').split(','); | ||
} | ||
if (typeof v2 == 'string') { | ||
params = v2.replace(/\s+/g, '').split(','); | ||
} | ||
var parsedParams = {}; | ||
var key; | ||
var parsedParams = {}; | ||
var key; | ||
for (var i = 0; i < params.length; i++) { | ||
if (params[i].indexOf(':') === -1) { | ||
if (_this.hasOwnProperty(params[i])) { | ||
parsedParams[params[i]] = _this[params[i]]; | ||
} else { | ||
throw new Error('Error while generating route "' + v1 + '". Model has no key "' + params[i] + '".'); | ||
} | ||
} else { | ||
key = params[i].substring(params[i].indexOf(':') + 1); | ||
for (var i = 0; i < params.length; i++) { | ||
if (params[i].indexOf(':') === -1) { | ||
if (_this.hasOwnProperty(params[i])) { | ||
parsedParams[params[i]] = _this[params[i]]; | ||
} else { | ||
throw new Error('Error while generating route "' + v1 + '". Model has no key "' + params[i] + '".'); | ||
} | ||
} else { | ||
key = params[i].substring(params[i].indexOf(':') + 1); | ||
if (_this.hasOwnProperty(key)) { | ||
parsedParams[params[i].substr(0, params[i].indexOf(':'))] = _this[key]; | ||
} else { | ||
parsedParams[params[i].substr(0, params[i].indexOf(':'))] = key; | ||
} | ||
} | ||
} | ||
if (_this.hasOwnProperty(key)) { | ||
parsedParams[params[i].substr(0, params[i].indexOf(':'))] = _this[key]; | ||
} else { | ||
parsedParams[params[i].substr(0, params[i].indexOf(':'))] = key; | ||
} | ||
} | ||
} | ||
return _this.generateUrl(v1, parsedParams); | ||
}); | ||
return _this.generateUrl(v1, parsedParams); | ||
}); | ||
Handlebars.registerHelper('routeParam', function (key, value) { | ||
return key + ":" + value; | ||
}); | ||
}, | ||
setContainer: function setContainer($container) { | ||
this.$container = $container; | ||
}, | ||
Handlebars.registerHelper('routeParam', function (key, value) { | ||
return key + ":" + value; | ||
}); | ||
}, | ||
/** | ||
* Function: start($path) | ||
* Start the Routing. | ||
* | ||
* Parameter: | ||
* @param {string} $path - {optional} If a path is given, the routing starts with this path. | ||
*/ | ||
start: function start($path) { | ||
if ($path == null) { | ||
$path = '/'; | ||
} //only accept valid deeplinks! | ||
setContainer: function setContainer($container) { | ||
this.$container = $container; | ||
}, | ||
/** | ||
* Function: start($path) | ||
* Start the Routing. | ||
* | ||
* Parameter: | ||
* @param {string} $path - {optional} If a path is given, the routing starts with this path. | ||
*/ | ||
start: function start($path) { | ||
if ($path == null) { | ||
$path = '/'; | ||
} | ||
//only accept valid deeplinks! | ||
if (window.location.hash.length > 0 && this.__matchRoute(window.location.hash)) { | ||
$(window).trigger('hashchange'); | ||
} else { | ||
window.location.hash = $path; | ||
} | ||
}, | ||
if (window.location.hash.length > 0 && this.__matchRoute(window.location.hash)) { | ||
$(window).trigger('hashchange'); | ||
} else { | ||
window.location.hash = $path; | ||
} | ||
}, | ||
/** | ||
* Function: addRoute(name, params) | ||
* Add a route. | ||
* | ||
* @param name {string} - The name of the route. | ||
* @param params {object} - The params of the route (view object or constructor and path) | ||
*/ | ||
addRoute: function addRoute(name, params) { | ||
if (this.__routes.hasOwnProperty(name)) { | ||
throw new Error('Route "' + name + '" is already defined.'); | ||
} | ||
/** | ||
* Function: addRoute(name, params) | ||
* Add a route. | ||
* | ||
* @param name {string} - The name of the route. | ||
* @param params {object} - The params of the route (view object or constructor and path) | ||
*/ | ||
addRoute: function addRoute(name, params) { | ||
if (this.__routes.hasOwnProperty(name)) { | ||
throw new Error('Route "' + name + '" is already defined.'); | ||
} | ||
this.__routes[name] = params; | ||
}, | ||
this.__routes[name] = params; | ||
}, | ||
/** | ||
* Function: generateUrl(route, $params) | ||
* Generate a url by a route name and optional arguments to fill the placeholders. | ||
* | ||
* Parameter: | ||
* @param {string} route - The route name | ||
* @param {object} $params - {optional} A object of parameters for the given route | ||
*/ | ||
generateUrl: function generateUrl(route, $params) { | ||
if (!this.__routes.hasOwnProperty(route)) { | ||
throw new Error('Route "' + route + '" does not exist.'); | ||
} | ||
/** | ||
* Function: generateUrl(route, $params) | ||
* Generate a url by a route name and optional arguments to fill the placeholders. | ||
* | ||
* Parameter: | ||
* @param {string} route - The route name | ||
* @param {object} $params - {optional} A object of parameters for the given route | ||
*/ | ||
generateUrl: function generateUrl(route, $params) { | ||
if (!this.__routes.hasOwnProperty(route)) { | ||
throw new Error('Route "' + route + '" does not exist.'); | ||
} | ||
if ($params) { | ||
var parts = this.__routes[route].path.slice(1).replace(/[()]/g, '').split('/'); | ||
if ($params) { | ||
var parts = this.__routes[route].path.slice(1).replace(/[()]/g, '').split('/'); | ||
for (var i = 0; i < parts.length; i++) { | ||
if (parts[i].indexOf(':') === 0) { | ||
if ($params.hasOwnProperty(parts[i].substr(1))) { | ||
parts[i] = $params[parts[i].substr(1)]; | ||
} else { | ||
parts.splice(i, 1); | ||
i--; | ||
} | ||
} | ||
} | ||
parts.unshift(''); | ||
return '#' + parts.join('/'); | ||
for (var i = 0; i < parts.length; i++) { | ||
if (parts[i].indexOf(':') === 0) { | ||
if ($params.hasOwnProperty(parts[i].substr(1))) { | ||
parts[i] = $params[parts[i].substr(1)]; | ||
} else { | ||
parts.splice(i, 1); | ||
i--; | ||
} | ||
} | ||
} | ||
return this.__routes[route].path.replace(/\(.*\)/g, ''); | ||
}, | ||
parts.unshift(''); | ||
return '#' + parts.join('/'); | ||
} | ||
/** | ||
* Function: getCurrentRoute() | ||
* Returns the current route object. | ||
* | ||
* Return: | ||
* @return {object} - The current route object. | ||
*/ | ||
getCurrentRoute: function getCurrentRoute() { | ||
return this.__currentRoute; | ||
}, | ||
return this.__routes[route].path.replace(/\(.*\)/g, ''); | ||
}, | ||
/** | ||
* Function: setPath(path) | ||
* Set the new path programmatically. | ||
* | ||
* Parameter: | ||
* @param path {string} - The path the application should be set to. | ||
*/ | ||
setPath: function setPath(path) { | ||
window.location.hash = path; | ||
}, | ||
/** | ||
* Function: getCurrentRoute() | ||
* Returns the current route object. | ||
* | ||
* Return: | ||
* @return {object} - The current route object. | ||
*/ | ||
getCurrentRoute: function getCurrentRoute() { | ||
return this.__currentRoute; | ||
}, | ||
/** | ||
* Function: callPath(path) | ||
* Set the new path programmatically. | ||
* | ||
* Parameter: | ||
* @param route {string} - The route the application should be set to. | ||
* @param $params {object} - An object containing the parameters. | ||
*/ | ||
callRoute: function callRoute(route, $params) { | ||
window.location.hash = this.generateUrl(route, $params); | ||
}, | ||
/** | ||
* Function: setPath(path) | ||
* Set the new path programmatically. | ||
* | ||
* Parameter: | ||
* @param path {string} - The path the application should be set to. | ||
*/ | ||
setPath: function setPath(path) { | ||
window.location.hash = path; | ||
}, | ||
/** | ||
* Function: hasRoute(route) | ||
* Returns true if the route exists. | ||
* | ||
* @param route {string} - The route name | ||
* @returns {boolean} | ||
*/ | ||
hasRoute: function hasRoute(route) { | ||
return this.__routes.hasOwnProperty(route); | ||
}, | ||
/** | ||
* Function: callPath(path) | ||
* Set the new path programmatically. | ||
* | ||
* Parameter: | ||
* @param route {string} - The route the application should be set to. | ||
* @param $params {object} - An object containing the parameters. | ||
*/ | ||
callRoute: function callRoute(route, $params) { | ||
window.location.hash = this.generateUrl(route, $params); | ||
}, | ||
/** | ||
* Function history | ||
* returns array with historical path objects, without current path | ||
* | ||
* @params {Integer} steps - steps needed for history, -1 for whole history | ||
* @returns {Array} | ||
*/ | ||
history: function history(steps, duplicates) { | ||
var history = []; | ||
if (steps == -1) { | ||
steps = this.__pathHistory.length - 1; | ||
} | ||
steps = Math.min(this.__pathHistory.length - 1, steps); | ||
var routes = []; | ||
var counter = 1; | ||
for (var i = this.__pathHistory.length - 1; i >= this.__pathHistory.length - 1 - steps; i--) { | ||
var pHistory = this.__pathHistory[i]; | ||
if (!duplicates) { | ||
if (routes.indexOf(pHistory) > -1) { | ||
//no duplicates allowed | ||
continue; | ||
} | ||
} | ||
routes.push(pHistory); | ||
//send steps back to reach this route | ||
var route = $.extend(true, { back: counter }, this.__getRoute(pHistory)); | ||
counter++; | ||
history.unshift(route); | ||
}; | ||
/** | ||
* Function: hasRoute(route) | ||
* Returns true if the route exists. | ||
* | ||
* @param route {string} - The route name | ||
* @returns {boolean} | ||
*/ | ||
hasRoute: function hasRoute(route) { | ||
return this.__routes.hasOwnProperty(route); | ||
}, | ||
return history; | ||
}, | ||
/** | ||
* Function history | ||
* returns array with historical path objects, without current path | ||
* | ||
* @params {Integer} steps - steps needed for history, -1 for whole history | ||
* @returns {Array} | ||
*/ | ||
history: function history(steps, duplicates) { | ||
var history = []; | ||
clearHistory: function clearHistory() { | ||
this.__pathHistory = []; | ||
this.__pathHistoryIndex = -1; | ||
}, | ||
if (steps == -1) { | ||
steps = this.__pathHistory.length - 1; | ||
} | ||
/** | ||
* Function: goback() | ||
* Go back given steps in history, delete | ||
*/ | ||
goback: function goback(steps) { | ||
if (steps > 0 && steps < this.__pathHistory.length) { | ||
//drop current route | ||
var newPath = this.__pathHistory.pop(); | ||
//drop previous routes | ||
while (steps > 0) { | ||
newPath = this.__pathHistory.pop(); | ||
steps--; | ||
} | ||
this.__pathHistoryIndex = this.__pathHistory.length - 1; | ||
this.setPath(newPath); | ||
} | ||
}, | ||
steps = Math.min(this.__pathHistory.length - 1, steps); | ||
var routes = []; | ||
var counter = 1; | ||
/** | ||
* Function: back() | ||
* Go back one step in history. | ||
*/ | ||
back: function back() { | ||
if (this.__pathHistoryIndex > 0 && this.__pathHistoryIndex <= this.__pathHistory.length) { | ||
this.setPath(this.__pathHistory[--this.__pathHistoryIndex]); | ||
} | ||
}, | ||
for (var i = this.__pathHistory.length - 1; i >= this.__pathHistory.length - 1 - steps; i--) { | ||
var pHistory = this.__pathHistory[i]; | ||
/** | ||
* Function: forward() | ||
* Go one step forward in history. | ||
*/ | ||
forward: function forward() { | ||
if (this.__pathHistoryIndex - 1 < this.__pathHistory.length) { | ||
this.setPath(this.__pathHistory[++this.__pathHistoryIndex]); | ||
if (!duplicates) { | ||
if (routes.indexOf(pHistory) > -1) { | ||
//no duplicates allowed | ||
continue; | ||
} | ||
}, | ||
} | ||
/** | ||
* Function: go(steps) | ||
* Go a specified number of steps back or forth in history. | ||
* | ||
* Parameter: | ||
* @param {Number} steps - A signed integer indicating how many steps to go. Values below zero go back, values above go forth in History. | ||
*/ | ||
go: function go(steps) { | ||
if (steps === 0) { | ||
return; | ||
} | ||
routes.push(pHistory); //send steps back to reach this route | ||
var i = this.__pathHistoryIndex += steps; | ||
var route = $.extend(true, { | ||
back: counter | ||
}, this.__getRoute(pHistory)); | ||
counter++; | ||
history.unshift(route); | ||
} | ||
if (i > 0 && i < this.__pathHistory.length) { | ||
window.location.hash = this.__pathHistory[i]; | ||
} | ||
}, | ||
; | ||
return history; | ||
}, | ||
clearHistory: function clearHistory() { | ||
this.__pathHistory = []; | ||
this.__pathHistoryIndex = -1; | ||
}, | ||
/** | ||
* Adds the current hash value of the location to the pathHistory array. | ||
* | ||
* @param {string} path - The path to add to the history. | ||
* @private | ||
*/ | ||
__pushPathToHistory: function __pushPathToHistory(path) { | ||
this.__pathHistory.splice(++this.__pathHistoryIndex, this.__pathHistory.length - this.__pathHistoryIndex, path); | ||
}, | ||
/** | ||
* Function: goback() | ||
* Go back given steps in history, delete | ||
*/ | ||
goback: function goback(steps) { | ||
if (steps > 0 && steps < this.__pathHistory.length) { | ||
//drop current route | ||
var newPath = this.__pathHistory.pop(); //drop previous routes | ||
/** | ||
* Callback for hashchange event. Tries to match a route. | ||
* If a route has been found this.__fireRoute will be called. | ||
* | ||
* @private | ||
*/ | ||
__onRouteChanged: function __onRouteChanged() { | ||
if (this.__matchRoute(window.location.hash)) { | ||
this.__fireRoute(); | ||
} | ||
}, | ||
/** | ||
* Tries to match a route by taken the given path and returns route object. | ||
* | ||
* @param {string} path - The path from the current url | ||
* @param {boolean} duplicates - Allow duplicates? | ||
* @return {boolean} | ||
* | ||
* @private | ||
*/ | ||
__getRoute: function __getRoute(path, duplicates) { | ||
path = path.slice(2); | ||
var pathParts = path.split('/'), | ||
matched; | ||
while (steps > 0) { | ||
newPath = this.__pathHistory.pop(); | ||
steps--; | ||
} | ||
var addedRoutes = []; | ||
for (var i in this.__routes) { | ||
if (this.__routes.hasOwnProperty(i)) { | ||
var routeRegex = this.__convertToRegex(this.__routes[i].path.slice(1)); | ||
matched = true; | ||
this.__pathHistoryIndex = this.__pathHistory.length - 1; | ||
this.setPath(newPath); | ||
} | ||
}, | ||
if (path.match(routeRegex) === null) { | ||
matched = false; | ||
} | ||
/** | ||
* Function: back() | ||
* Go back one step in history. | ||
*/ | ||
back: function back() { | ||
if (this.__pathHistoryIndex > 0 && this.__pathHistoryIndex <= this.__pathHistory.length) { | ||
this.setPath(this.__pathHistory[--this.__pathHistoryIndex]); | ||
} | ||
}, | ||
if (matched) { | ||
if (!duplicates) { | ||
if (addedRoutes.indexOf[i] > -1) { | ||
//no duplicates allowed | ||
continue; | ||
} | ||
} | ||
addedRoutes.push(i); | ||
/** | ||
* Function: forward() | ||
* Go one step forward in history. | ||
*/ | ||
forward: function forward() { | ||
if (this.__pathHistoryIndex - 1 < this.__pathHistory.length) { | ||
this.setPath(this.__pathHistory[++this.__pathHistoryIndex]); | ||
} | ||
}, | ||
var routeParts = this.__routes[i].path.slice(1).replace(/[()]/g, '').split('/'); | ||
/** | ||
* Function: go(steps) | ||
* Go a specified number of steps back or forth in history. | ||
* | ||
* Parameter: | ||
* @param {Number} steps - A signed integer indicating how many steps to go. Values below zero go back, values above go forth in History. | ||
*/ | ||
go: function go(steps) { | ||
if (steps === 0) { | ||
return; | ||
} | ||
this.__mapArguments(pathParts, routeParts, this.__routes[i]); | ||
//copy route object, add route label | ||
var r = $.extend(true, { key: i }, this.__routes[i]); | ||
//replace path variables | ||
for (var parts = 0; parts < routeParts.length; parts++) { | ||
r.path = r.path.replace(routeParts[parts], pathParts[parts]); | ||
} | ||
var i = this.__pathHistoryIndex += steps; | ||
//delete view from route | ||
delete r.view; | ||
return r; | ||
} | ||
} | ||
} | ||
if (i > 0 && i < this.__pathHistory.length) { | ||
window.location.hash = this.__pathHistory[i]; | ||
} | ||
}, | ||
return null; | ||
}, | ||
/** | ||
* Adds the current hash value of the location to the pathHistory array. | ||
* | ||
* @param {string} path - The path to add to the history. | ||
* @private | ||
*/ | ||
__pushPathToHistory: function __pushPathToHistory(path) { | ||
this.__pathHistory.splice(++this.__pathHistoryIndex, this.__pathHistory.length - this.__pathHistoryIndex, path); | ||
}, | ||
/** | ||
* Tries to match a route by taken the given path and returns boolean flag. | ||
* | ||
* @param {string} path - The path from the current url | ||
* @return {boolean} | ||
* @private | ||
*/ | ||
__matchRoute: function __matchRoute(path) { | ||
path = path.slice(2); | ||
var pathParts = path.split('/'), | ||
matched; | ||
/** | ||
* Callback for hashchange event. Tries to match a route. | ||
* If a route has been found this.__fireRoute will be called. | ||
* | ||
* @private | ||
*/ | ||
__onRouteChanged: function __onRouteChanged() { | ||
if (this.__matchRoute(window.location.hash)) { | ||
this.__fireRoute(); | ||
} | ||
}, | ||
for (var i in this.__routes) { | ||
if (this.__routes.hasOwnProperty(i)) { | ||
var routeRegex = this.__convertToRegex(this.__routes[i].path.slice(1)); | ||
matched = true; | ||
/** | ||
* Tries to match a route by taken the given path and returns route object. | ||
* | ||
* @param {string} path - The path from the current url | ||
* @param {boolean} duplicates - Allow duplicates? | ||
* @return {boolean} | ||
* | ||
* @private | ||
*/ | ||
__getRoute: function __getRoute(path, duplicates) { | ||
path = path.slice(2); | ||
var pathParts = path.split('/'), | ||
matched; | ||
var addedRoutes = []; | ||
if (path.match(routeRegex) === null) { | ||
matched = false; | ||
} | ||
for (var i in this.__routes) { | ||
if (this.__routes.hasOwnProperty(i)) { | ||
var routeRegex = this.__convertToRegex(this.__routes[i].path.slice(1)); | ||
if (matched) { | ||
var routeParts = this.__routes[i].path.slice(1).replace(/[()]/g, '').split('/'); | ||
this.__nextRoute = this.__mapArguments(pathParts, routeParts, this.__routes[i]); | ||
this.__nextRoute.key = i; | ||
matched = true; | ||
return true; | ||
} | ||
} | ||
if (path.match(routeRegex) === null) { | ||
matched = false; | ||
} | ||
return false; | ||
}, | ||
if (matched) { | ||
if (!duplicates) { | ||
if (addedRoutes.indexOf[i] > -1) { | ||
//no duplicates allowed | ||
continue; | ||
} | ||
} | ||
__convertToRegex: function __convertToRegex(route) { | ||
var optionalParam = /\((.*?)\)/g; | ||
var namedParam = /(\(\?)?:\w+/g; | ||
addedRoutes.push(i); | ||
route = route.replace(optionalParam, '(?:$1)?').replace(namedParam, function (match, optional) { | ||
return optional ? match : '([^/?]+)'; | ||
}); | ||
var routeParts = this.__routes[i].path.slice(1).replace(/[()]/g, '').split('/'); | ||
return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$'); | ||
}, | ||
this.__mapArguments(pathParts, routeParts, this.__routes[i]); //copy route object, add route label | ||
/** | ||
* Maps the arguments from the hash path to the currently matched route. | ||
* | ||
* @param {Array} pathParts | ||
* @param {Array} routeParts | ||
* @param {object} nextRoute | ||
* @return {object} | ||
* @private | ||
*/ | ||
__mapArguments: function __mapArguments(pathParts, routeParts, nextRoute) { | ||
var mode = 0; | ||
if (nextRoute.paramsAsObject != null && nextRoute.paramsAsObject) { | ||
mode = 1; | ||
} | ||
var r = $.extend(true, { | ||
key: i | ||
}, this.__routes[i]); //replace path variables | ||
nextRoute.args = []; | ||
for (var parts = 0; parts < routeParts.length; parts++) { | ||
r.path = r.path.replace(routeParts[parts], pathParts[parts]); | ||
} //delete view from route | ||
if (mode === 1) { | ||
nextRoute.args.push({}); | ||
delete r.view; | ||
return r; | ||
} | ||
} | ||
} | ||
for (var i = 0; i < routeParts.length; i++) { | ||
if (routeParts[i].indexOf(':') === 0) { | ||
if (!isNaN(pathParts[i])) { | ||
pathParts[i] = Number(pathParts[i]); | ||
} | ||
return null; | ||
}, | ||
if (mode === 0) { | ||
nextRoute.args.push(pathParts[i]); | ||
} else { | ||
nextRoute.args[0][routeParts[i].substring(1)] = pathParts[i]; | ||
} | ||
} | ||
} | ||
/** | ||
* Tries to match a route by taken the given path and returns boolean flag. | ||
* | ||
* @param {string} path - The path from the current url | ||
* @return {boolean} | ||
* @private | ||
*/ | ||
__matchRoute: function __matchRoute(path) { | ||
path = path.slice(2); | ||
var pathParts = path.split('/'), | ||
matched; | ||
return nextRoute; | ||
}, | ||
for (var i in this.__routes) { | ||
if (this.__routes.hasOwnProperty(i)) { | ||
var routeRegex = this.__convertToRegex(this.__routes[i].path.slice(1)); | ||
/** | ||
* Fires a route and executes the attached callback methods of the view that will be showed and the view that will | ||
* be hidden. | ||
* | ||
* @private | ||
*/ | ||
__fireRoute: function __fireRoute() { | ||
//do not fire route, if it is the same as previous | ||
if (this.__nextRoute && this.__currentRoute && this.__nextRoute.key == this.__currentRoute.key && JSON.stringify(this.__nextRoute.args) == JSON.stringify(this.__currentRoute.args)) { | ||
return false; | ||
} | ||
matched = true; | ||
if (this.__currentRoute != null) { | ||
// The onPause method of a view can return a value that is pushed to the params to the next active view. | ||
this.__callRouteView(this.__currentRoute); | ||
this.__callRouteMethod(this.__currentRoute, 'onPause'); | ||
if (path.match(routeRegex) === null) { | ||
matched = false; | ||
} | ||
this.__callRouteView(this.__nextRoute); | ||
if (matched) { | ||
var routeParts = this.__routes[i].path.slice(1).replace(/[()]/g, '').split('/'); | ||
if (this.__nextRoute == null || this.__nextRoute.view == null) { | ||
console.error("invalid route called! ", this.__nextRoute); | ||
return; | ||
this.__nextRoute = this.__mapArguments(pathParts, routeParts, this.__routes[i]); | ||
this.__nextRoute.key = i; | ||
return true; | ||
} | ||
} | ||
} | ||
if (this.__currentRoute != null) { | ||
//this.trigger(Coco.Event.HIDE_VIEW); | ||
//this.trigger(Coco.Event.HIDE_VIEW + this.__currentRoute.view.$name); | ||
//dispatch event for router | ||
this._dispatchEvent(new Coco.RouterEvent(Coco.RouterEvent.HIDE_VIEW, $.extend({}, this.__nextRoute), $.extend({}, this.__currentRoute))); | ||
return false; | ||
}, | ||
__convertToRegex: function __convertToRegex(route) { | ||
var optionalParam = /\((.*?)\)/g; | ||
var namedParam = /(\(\?)?:\w+/g; | ||
route = route.replace(optionalParam, '(?:$1)?').replace(namedParam, function (match, optional) { | ||
return optional ? match : '([^/?]+)'; | ||
}); | ||
return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$'); | ||
}, | ||
//dispatch event for view | ||
this._dispatchEvent(new Coco.RouterEvent(Coco.RouterEvent.HIDE_VIEW + this.__currentRoute.view.$name, $.extend({}, this.__nextRoute), $.extend({}, this.__currentRoute))); | ||
/** | ||
* Maps the arguments from the hash path to the currently matched route. | ||
* | ||
* @param {Array} pathParts | ||
* @param {Array} routeParts | ||
* @param {object} nextRoute | ||
* @return {object} | ||
* @private | ||
*/ | ||
__mapArguments: function __mapArguments(pathParts, routeParts, nextRoute) { | ||
var mode = 0; | ||
this.__currentRoute.view.deactivate(); | ||
} | ||
if (nextRoute.paramsAsObject != null && nextRoute.paramsAsObject) { | ||
mode = 1; | ||
} | ||
this.__nextRoute.view.activate(); | ||
nextRoute.args = []; | ||
//call this AFTER deactivating current view, because current view can be also NEXT view - and so, all events are killed | ||
this.__callRouteMethod(this.__nextRoute, 'onActive'); | ||
if (mode === 1) { | ||
nextRoute.args.push({}); | ||
} | ||
if (this.__currentRoute && this.__currentRoute.view.$name == this.__nextRoute.view.$name) { | ||
// If we navigate to the same view, don't add new route to history array | ||
// Just replace the last one with new value | ||
this.__pathHistory[this.__pathHistory.length - 1] = window.location.hash; | ||
for (var i = 0; i < routeParts.length; i++) { | ||
if (routeParts[i].indexOf(':') === 0) { | ||
if (!isNaN(pathParts[i])) { | ||
pathParts[i] = Number(pathParts[i]); | ||
} | ||
if (mode === 0) { | ||
nextRoute.args.push(pathParts[i]); | ||
} else { | ||
// Otherwise add new route path to history array | ||
this.__pushPathToHistory(window.location.hash); | ||
nextRoute.args[0][routeParts[i].substring(1)] = pathParts[i]; | ||
} | ||
} | ||
} | ||
this._dispatchEvent(new Coco.RouterEvent(Coco.RouterEvent.CHANGE_ROUTE, $.extend({}, this.__nextRoute), $.extend({}, this.__currentRoute))); | ||
return nextRoute; | ||
}, | ||
this.__currentRoute = $.extend({}, this.__nextRoute); | ||
/** | ||
* Fires a route and executes the attached callback methods of the view that will be showed and the view that will | ||
* be hidden. | ||
* | ||
* @private | ||
*/ | ||
__fireRoute: function __fireRoute() { | ||
//do not fire route, if it is the same as previous | ||
if (this.__nextRoute && this.__currentRoute && this.__nextRoute.key == this.__currentRoute.key && JSON.stringify(this.__nextRoute.args) == JSON.stringify(this.__currentRoute.args)) { | ||
return false; | ||
} | ||
this.__callRouteMethod(this.__nextRoute, 'onRenderedActive'); | ||
if (this.__currentRoute != null) { | ||
// The onPause method of a view can return a value that is pushed to the params to the next active view. | ||
this.__callRouteView(this.__currentRoute); | ||
this.__nextRoute = null; | ||
}, | ||
this.__callRouteMethod(this.__currentRoute, 'onPause'); | ||
} | ||
/** | ||
* Calls the onActive or onPause callback of the view. | ||
* | ||
* @param {object} route - The route object where the view lies in | ||
*/ | ||
__callRouteView: function __callRouteView(route) { | ||
if (typeof route.view === 'function') { | ||
console.debug("callRouteView: ", route); | ||
if (route.model && route.model instanceof Coco.Model) { | ||
route.view = new route.view(route.model); | ||
} else { | ||
route.view = new route.view(); | ||
} | ||
} | ||
}, | ||
this.__callRouteView(this.__nextRoute); | ||
__callRouteMethod: function __callRouteMethod(route, method) { | ||
if (method === 'onPause') { | ||
//deactivated views do not need any eventhandler! | ||
route.view.undelegateEvents(); | ||
return route.view[method](); | ||
} else if (method === 'onActive') { | ||
//route.view.delegateEvents(); | ||
return route.view[method].apply(route.view, this.__nextRoute.args); | ||
} else if (typeof route.view[method] === 'function') { | ||
route.view[method].apply(route.view, this.__nextRoute.args); | ||
} | ||
if (this.__nextRoute == null || this.__nextRoute.view == null) { | ||
console.error("invalid route called! ", this.__nextRoute); | ||
return; | ||
} | ||
if (this.__currentRoute != null) { | ||
//this.trigger(Coco.Event.HIDE_VIEW); | ||
//this.trigger(Coco.Event.HIDE_VIEW + this.__currentRoute.view.$name); | ||
//dispatch event for router | ||
this._dispatchEvent(new Coco.RouterEvent(Coco.RouterEvent.HIDE_VIEW, $.extend({}, this.__nextRoute), $.extend({}, this.__currentRoute))); //dispatch event for view | ||
this._dispatchEvent(new Coco.RouterEvent(Coco.RouterEvent.HIDE_VIEW + this.__currentRoute.view.$name, $.extend({}, this.__nextRoute), $.extend({}, this.__currentRoute))); | ||
this.__currentRoute.view.deactivate(); | ||
} | ||
this.__nextRoute.view.activate(); //call this AFTER deactivating current view, because current view can be also NEXT view - and so, all events are killed | ||
this.__callRouteMethod(this.__nextRoute, 'onActive'); | ||
if (this.__currentRoute && this.__currentRoute.view.$name == this.__nextRoute.view.$name) { | ||
// If we navigate to the same view, don't add new route to history array | ||
// Just replace the last one with new value | ||
this.__pathHistory[this.__pathHistory.length - 1] = window.location.hash; | ||
} else { | ||
// Otherwise add new route path to history array | ||
this.__pushPathToHistory(window.location.hash); | ||
} | ||
this._dispatchEvent(new Coco.RouterEvent(Coco.RouterEvent.CHANGE_ROUTE, $.extend({}, this.__nextRoute), $.extend({}, this.__currentRoute))); | ||
this.__currentRoute = $.extend({}, this.__nextRoute); | ||
this.__callRouteMethod(this.__nextRoute, 'onRenderedActive'); | ||
this.__nextRoute = null; | ||
}, | ||
/** | ||
* Calls the onActive or onPause callback of the view. | ||
* | ||
* @param {object} route - The route object where the view lies in | ||
*/ | ||
__callRouteView: function __callRouteView(route) { | ||
if (typeof route.view === 'function') { | ||
console.debug("callRouteView: ", route); | ||
if (route.model && route.model instanceof Coco.Model) { | ||
route.view = new route.view(route.model); | ||
} else { | ||
route.view = new route.view(); | ||
} | ||
} | ||
}, | ||
__callRouteMethod: function __callRouteMethod(route, method) { | ||
if (method === 'onPause') { | ||
//deactivated views do not need any eventhandler! | ||
route.view.undelegateEvents(); | ||
return route.view[method](); | ||
} else if (method === 'onActive') { | ||
//route.view.delegateEvents(); | ||
return route.view[method].apply(route.view, this.__nextRoute.args); | ||
} else if (typeof route.view[method] === 'function') { | ||
route.view[method].apply(route.view, this.__nextRoute.args); | ||
} | ||
} | ||
}); //.$service(); | ||
//instantiate Service automatically | ||
module.exports = new Coco.RouterService(); |
"use strict"; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var RestServiceEvent = require("../event/Coco.RestServiceEvent.js"); | ||
var Event = require("../event/Coco.Event.js"); | ||
var JSON = require("JSON"); | ||
/** | ||
@@ -19,417 +19,468 @@ * Class: Coco.BaseRestService | ||
*/ | ||
module.exports = dejavu.AbstractClass.declare({ | ||
/** | ||
* Class name. | ||
*/ | ||
$name: "Coco.BaseRestService", | ||
/** | ||
* Class name. | ||
*/ | ||
$name: "Coco.BaseRestService", | ||
/** | ||
* Super class: Coco.Service | ||
*/ | ||
$extends: require("./Coco.Service.js"), | ||
/** | ||
* Super class: Coco.Service | ||
*/ | ||
$extends: require("./Coco.Service.js"), | ||
/** | ||
* cache for GET requests | ||
*/ | ||
_getCache: null, | ||
/** | ||
* cache for GET requests | ||
*/ | ||
_getCache: null, | ||
/** | ||
* cache for POST requests | ||
*/ | ||
_postCache: null, | ||
/** | ||
* cache for POST requests | ||
*/ | ||
_postCache: null, | ||
/** | ||
* The REST service path. | ||
*/ | ||
_restServicePath: null, | ||
/** | ||
* The REST service path. | ||
*/ | ||
_restServicePath: null, | ||
$constants: { | ||
XHR_FIELDS: { | ||
withCredentials: true | ||
}, | ||
CROSSDOMAIN: true | ||
}, | ||
$constants: { | ||
XHR_FIELDS: { | ||
withCredentials: true | ||
}, | ||
CROSSDOMAIN: true | ||
}, | ||
/** | ||
* Ctor. | ||
*/ | ||
initialize: function initialize() { | ||
//call constructor for service registration | ||
this.$super(); | ||
/** | ||
* Ctor. | ||
*/ | ||
initialize: function initialize() { | ||
//call constructor for service registration | ||
this.$super(); | ||
this._onInitialize(); | ||
}, | ||
this._onInitialize(); | ||
}, | ||
/** | ||
* Function: _onInitialize | ||
* | ||
* is called after class was initialized | ||
* @protected | ||
*/ | ||
_onInitialize: function _onInitialize() {}, | ||
/** | ||
* Function: _onInitialize | ||
* | ||
* is called after class was initialized | ||
* @protected | ||
*/ | ||
_onInitialize: function _onInitialize() {}, | ||
_validateParameterIsBoolean: function _validateParameterIsBoolean(param, onError) { | ||
if (param != null && typeof param != "boolean") { | ||
onError({ | ||
status: 99, | ||
responseText: "Parameter is not type of Boolean" | ||
}); | ||
return false; | ||
} | ||
_validateParameterIsBoolean: function _validateParameterIsBoolean(param, onError) { | ||
if (param != null && typeof param != "boolean") { | ||
onError({ status: 99, responseText: "Parameter is not type of Boolean" }); | ||
return false; | ||
} | ||
return true; | ||
}, | ||
return true; | ||
}, | ||
_validateParameterIsInteger: function _validateParameterIsInteger(param, onError) { | ||
if (param != null && parseInt(param) !== param) { | ||
onError({ | ||
status: 99, | ||
responseText: "Parameter is not type of Integer" | ||
}); | ||
return false; | ||
} | ||
_validateParameterIsInteger: function _validateParameterIsInteger(param, onError) { | ||
if (param != null && parseInt(param) !== param) { | ||
onError({ status: 99, responseText: "Parameter is not type of Integer" }); | ||
return false; | ||
} | ||
return true; | ||
}, | ||
return true; | ||
}, | ||
_validateParameterIsFloat: function _validateParameterIsFloat(param, onError) { | ||
if (param != null && typeof param !== "number") { | ||
onError({ | ||
status: 99, | ||
responseText: "Parameter is not type of Number" | ||
}); | ||
return false; | ||
} | ||
_validateParameterIsFloat: function _validateParameterIsFloat(param, onError) { | ||
if (param != null && typeof param !== "number") { | ||
onError({ status: 99, responseText: "Parameter is not type of Number" }); | ||
return false; | ||
} | ||
return true; | ||
}, | ||
_validateParameterIsArray: function _validateParameterIsArray(param, onError) { | ||
if (param != null && !Array.isArray(param)) { | ||
onError({ status: 99, responseText: "Parameter is not type of Array" }); | ||
return false; | ||
} | ||
return true; | ||
}, | ||
return true; | ||
}, | ||
_validateParameterIsArray: function _validateParameterIsArray(param, onError) { | ||
if (param != null && !Array.isArray(param)) { | ||
onError({ | ||
status: 99, | ||
responseText: "Parameter is not type of Array" | ||
}); | ||
return false; | ||
} | ||
_validateParameterClass: function _validateParameterClass(param, paramType, onError) { | ||
if (param != null && !(param instanceof paramType)) { | ||
onError({ status: 99, responseText: "Parameter is not type of " + (typeof paramType === "undefined" ? "undefined" : _typeof(paramType)) }); | ||
return false; | ||
} | ||
return true; | ||
}, | ||
return true; | ||
}, | ||
_validateParameterClass: function _validateParameterClass(param, paramType, onError) { | ||
if (param != null && !(param instanceof paramType)) { | ||
onError({ | ||
status: 99, | ||
responseText: "Parameter is not type of " + _typeof(paramType) | ||
}); | ||
return false; | ||
} | ||
/** | ||
* Function: _buildEndpointURL | ||
* | ||
* Builds the full endpoint URL absolute to the host. The URL looks like: | ||
* [CONTEXT-PATH]/[REST-PATH]/[ENDPOINT] | ||
* | ||
* Parameter: | ||
* | ||
* @param {string} endpoint the REST endpoint | ||
*/ | ||
_buildEndpointURL: function _buildEndpointURL(endpoint, pathParameter) { | ||
var Coco = require("../Coco.Init.js"); | ||
if (this._restServicePath == null) { | ||
throw new Error(this.$serviceId + "._restServicePath not set!"); | ||
} | ||
if (Coco.config.baseUrl == null) { | ||
throw new Error("Coco.config.baseUrl not set! ", Coco.config); | ||
} | ||
if (!Coco.config.restService || Coco.config.restService.path == null) { | ||
throw new Error("Coco.config.restService.path not set! ", Coco.config); | ||
} | ||
if (endpoint == null) { | ||
endpoint = ""; | ||
} | ||
var finalUrl = Coco.config.baseUrl + Coco.config.restService.path + this._restServicePath + endpoint; | ||
if (pathParameter && pathParameter.length > 0) { | ||
finalUrl = this._replacePathParameters(finalUrl, pathParameter); | ||
} | ||
return finalUrl; | ||
}, | ||
return true; | ||
}, | ||
_replacePathParameters: function _replacePathParameters(path, pathParameter) { | ||
do { | ||
var paramStart = path.indexOf("{"); | ||
if (paramStart < 0) { | ||
break; | ||
} | ||
var paramEnd = paramStart; | ||
var depth = 1; | ||
do { | ||
paramEnd++; | ||
var c = path.substring(paramEnd, paramEnd + 1); | ||
if (c === "{") { | ||
depth++; | ||
} else if (c === "}") { | ||
depth--; | ||
} | ||
} while (depth > 0 && paramEnd + 1 < path.length); | ||
paramEnd++; | ||
if (paramEnd > path.length) { | ||
break; | ||
} | ||
var pathDefinition = path.substring(paramStart, paramEnd); | ||
var paramName = pathDefinition.substring(1, pathDefinition.length - 1); | ||
if (paramName.indexOf(":") > 0) { | ||
paramName = paramName.substring(0, paramName.indexOf(":")); | ||
} | ||
var value = null; | ||
for (var i = 0; i < pathParameter.length; i++) { | ||
if (pathParameter[i].name === paramName) { | ||
value = pathParameter[i].replacement; | ||
break; | ||
} | ||
} | ||
if (value == null) { | ||
console.error("missing path parameter: " + paramName + " not set... ", pathParameter); | ||
} | ||
//replace position | ||
path = path.substring(0, paramStart) + value + path.substring(paramEnd); | ||
} while (true); | ||
/** | ||
* Function: _buildEndpointURL | ||
* | ||
* Builds the full endpoint URL absolute to the host. The URL looks like: | ||
* [CONTEXT-PATH]/[REST-PATH]/[ENDPOINT] | ||
* | ||
* Parameter: | ||
* | ||
* @param {string} endpoint the REST endpoint | ||
*/ | ||
_buildEndpointURL: function _buildEndpointURL(endpoint, pathParameter) { | ||
var Coco = require("../Coco.Init.js"); | ||
return path; | ||
}, | ||
if (this._restServicePath == null) { | ||
throw new Error(this.$serviceId + "._restServicePath not set!"); | ||
} | ||
/** | ||
* Function: __call {private} | ||
* | ||
* Calls the given endpoint via jQuery ajax function using the given method, data and callbacks. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {string} method the request method ('GET', 'POST', 'PUT' or 'DELETE') | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
*/ | ||
__call: function __call(endpoint, pathParameter, method, data, xhrFields, callbackSuccess, callbackError, $contentType) { | ||
var _this = this; | ||
if (Coco.config.baseUrl == null) { | ||
throw new Error("Coco.config.baseUrl not set! ", Coco.config); | ||
} | ||
var url = this._buildEndpointURL(endpoint, pathParameter); | ||
var Coco = require("../Coco.Init.js"); | ||
if (!Coco.config.restService || Coco.config.restService.path == null) { | ||
throw new Error("Coco.config.restService.path not set! ", Coco.config); | ||
} | ||
var cacheKey = url; | ||
if ($contentType) { | ||
cacheKey = cacheKey + $contentType; | ||
} | ||
if (endpoint == null) { | ||
endpoint = ""; | ||
} | ||
if (method == "GET") { | ||
if (this._getCache == null) { | ||
this._getCache = new Map(); | ||
} | ||
var finalUrl = Coco.config.baseUrl + Coco.config.restService.path + this._restServicePath + endpoint; | ||
var cacheData = this._getCache.get(cacheKey); | ||
if (cacheData != null) { | ||
//cached entry found | ||
if (cacheData.cocoTimeout == null || cacheData.cocoTimeout > new Date().getTime()) { | ||
//parse stringed cached response | ||
var cacheDataResponse = JSON.parse(cacheData.response); | ||
if (callbackSuccess) { | ||
callbackSuccess(cacheDataResponse); | ||
} | ||
return Promise.resolve(cacheDataResponse); | ||
} | ||
//cache timed out, delete it | ||
this._getCache.delete(cacheKey); | ||
} | ||
} | ||
if (pathParameter && pathParameter.length > 0) { | ||
finalUrl = this._replacePathParameters(finalUrl, pathParameter); | ||
} | ||
//delete empty keys from data object | ||
Object.keys(data).forEach(function (k) { | ||
if (typeof data[k] != 'boolean' && typeof data[k] != 'number' && !data[k]) { | ||
delete data[k]; | ||
} | ||
}); | ||
return finalUrl; | ||
}, | ||
_replacePathParameters: function _replacePathParameters(path, pathParameter) { | ||
do { | ||
var paramStart = path.indexOf("{"); | ||
//console.debug("Calling REST service (method: '" + method + "', URL: " + url + ") with data: ", data); | ||
return $.ajax({ | ||
url: url, | ||
type: method, | ||
xhrFields: xhrFields, | ||
contentType: $contentType || false, | ||
crossDomain: this.$self.CROSSDOMAIN, //enable crossdomain calls - implement serverside! | ||
data: data, | ||
dataType: 'json', //dont use jsonp for RESTservices, only GET requests allowed with jsonp | ||
processData: window.FormData && data instanceof FormData ? false : true, | ||
success: function success(response) { | ||
if (method == "GET") { | ||
if (Coco.config.restService.cacheGet < 0) { | ||
//unlimited caching | ||
_this._getCache.set(cacheKey, { response: JSON.stringify(response) }); | ||
} else { | ||
if (Coco.config.restService.cacheGet > 0) { | ||
var timeout = new Date(new Date().getTime() + 1000 * Coco.config.restService.cacheGet); | ||
if (paramStart < 0) { | ||
break; | ||
} | ||
// todo when array - don't make object from array | ||
_this._getCache.set(cacheKey, { cocoTimeout: timeout, response: JSON.stringify(response) }); | ||
} else { | ||
//cache disabled | ||
} | ||
} | ||
} | ||
var paramEnd = paramStart; | ||
var depth = 1; | ||
callbackSuccess(response); | ||
}, | ||
error: function error(_error) { | ||
if (_error != null && _error.status == 401) { | ||
//Authorization failed - throw Event | ||
//this.trigger(Coco.Event.AUTHORIZATION_FAILED); | ||
_this._dispatchEvent(new RestServiceEvent(Event.AUTHORIZATION_FAILED, _error.status, _error)); | ||
} else if (_error != null && _error.status == 500) { | ||
//Authorization failed - throw Event | ||
//this.trigger(Coco.Event.INTERNAL_SERVER_ERROR, error); | ||
_this._dispatchEvent(new RestServiceEvent(Event.INTERNAL_SERVER_ERROR, _error.status, _error)); | ||
} else { | ||
_this._dispatchEvent(new RestServiceEvent(Event.REST_SERVER_ERROR, _error.status, _error)); | ||
} | ||
do { | ||
paramEnd++; | ||
var c = path.substring(paramEnd, paramEnd + 1); | ||
if (callbackError != null) { | ||
callbackError(_error); | ||
} | ||
} | ||
}); | ||
}, | ||
if (c === "{") { | ||
depth++; | ||
} else if (c === "}") { | ||
depth--; | ||
} | ||
} while (depth > 0 && paramEnd + 1 < path.length); | ||
/** | ||
* Function: _get | ||
* | ||
* Delegates to _call using 'GET' method. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {array} pathParameter Array | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
*/ | ||
_get: function _get(endpoint, pathParameter, data, xhrFields, callbackSuccess, callbackError) { | ||
if (!Array.isArray(pathParameter)) { | ||
throw new Error("2nd parameter has to be pathParameter array, but was: " + (typeof pathParameter === "undefined" ? "undefined" : _typeof(pathParameter))); | ||
} | ||
return this.__call(endpoint, pathParameter, 'GET', data, xhrFields, callbackSuccess, callbackError, false); | ||
}, | ||
paramEnd++; | ||
/** | ||
* Function: _post | ||
* | ||
* Delegates to _call using 'POST' method. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
* | ||
* @param {string} contentType | ||
*/ | ||
_post: function _post(endpoint, pathParameter, data, xhrFields, callbackSuccess, callbackError, contentType) { | ||
if (!Array.isArray(pathParameter)) { | ||
throw new Error("2nd parameter has to be pathParameter array, but was: " + (typeof pathParameter === "undefined" ? "undefined" : _typeof(pathParameter))); | ||
} | ||
return this.__call(endpoint, pathParameter, 'POST', data, xhrFields, callbackSuccess, callbackError, contentType); | ||
}, | ||
if (paramEnd > path.length) { | ||
break; | ||
} | ||
/** | ||
* Function: _postJson | ||
* | ||
* Delegates to _call using 'POST' method, contentType 'application/json' and | ||
* stringifys the data object. | ||
* Use this method if you consume a (complexly JSON) mapped object on server-side. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
*/ | ||
_postJson: function _postJson(endpoint, pathParameter, data, xhrFields, callbackSuccess, callbackError) { | ||
if (!Array.isArray(pathParameter)) { | ||
throw new Error("2nd parameter has to be pathParameter array, but was: " + (typeof pathParameter === "undefined" ? "undefined" : _typeof(pathParameter))); | ||
} | ||
return this.__call(endpoint, pathParameter, 'POST', JSON.stringify(data), xhrFields, callbackSuccess, callbackError, 'application/json'); | ||
}, | ||
var pathDefinition = path.substring(paramStart, paramEnd); | ||
var paramName = pathDefinition.substring(1, pathDefinition.length - 1); | ||
/** | ||
* Function: _put | ||
* | ||
* Delegates to _call using 'PUT' method. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
* | ||
* @param {string} contentType | ||
*/ | ||
_put: function _put(endpoint, pathParameter, data, xhrFields, callbackSuccess, callbackError, contentType) { | ||
if (!Array.isArray(pathParameter)) { | ||
throw new Error("2nd parameter has to be pathParameter array, but was: " + (typeof pathParameter === "undefined" ? "undefined" : _typeof(pathParameter))); | ||
} | ||
return this.__call(endpoint, pathParameter, 'PUT', data, xhrFields, callbackSuccess, callbackError, contentType); | ||
}, | ||
if (paramName.indexOf(":") > 0) { | ||
paramName = paramName.substring(0, paramName.indexOf(":")); | ||
} | ||
/** | ||
* Function: _putJson | ||
* | ||
* Delegates to _call using 'PUT' method. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
*/ | ||
_putJson: function _putJson(endpoint, pathParameter, data, xhrFields, callbackSuccess, callbackError) { | ||
if (!Array.isArray(pathParameter)) { | ||
throw new Error("2nd parameter has to be pathParameter array, but was: " + (typeof pathParameter === "undefined" ? "undefined" : _typeof(pathParameter))); | ||
} | ||
return this.__call(endpoint, pathParameter, 'PUT', JSON.stringify(data), xhrFields, callbackSuccess, callbackError, 'application/json'); | ||
}, | ||
var value = null; | ||
/** | ||
* Function: _delete | ||
* | ||
* Delegates to _call using 'DELETE' method. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
*/ | ||
_delete: function _delete(endpoint, pathParameter, data, xhrFields, callbackSuccess, callbackError, contentType) { | ||
if (!Array.isArray(pathParameter)) { | ||
throw new Error("2nd parameter has to be pathParameter array, but was: " + (typeof pathParameter === "undefined" ? "undefined" : _typeof(pathParameter))); | ||
} | ||
return this.__call(endpoint, pathParameter, 'DELETE', data, xhrFields, callbackSuccess, callbackError, contentType); | ||
} | ||
for (var i = 0; i < pathParameter.length; i++) { | ||
if (pathParameter[i].name === paramName) { | ||
value = pathParameter[i].replacement; | ||
break; | ||
} | ||
} | ||
if (value == null) { | ||
console.error("missing path parameter: " + paramName + " not set... ", pathParameter); | ||
} //replace position | ||
path = path.substring(0, paramStart) + value + path.substring(paramEnd); | ||
} while (true); | ||
return path; | ||
}, | ||
/** | ||
* Function: __call {private} | ||
* | ||
* Calls the given endpoint via jQuery ajax function using the given method, data and callbacks. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {string} method the request method ('GET', 'POST', 'PUT' or 'DELETE') | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
*/ | ||
__call: function __call(endpoint, pathParameter, method, data, xhrFields, callbackSuccess, callbackError, $contentType) { | ||
var _this = this; | ||
var url = this._buildEndpointURL(endpoint, pathParameter); | ||
var Coco = require("../Coco.Init.js"); | ||
var cacheKey = url; | ||
if ($contentType) { | ||
cacheKey = cacheKey + $contentType; | ||
} | ||
if (method == "GET") { | ||
if (this._getCache == null) { | ||
this._getCache = new Map(); | ||
} | ||
var cacheData = this._getCache.get(cacheKey); | ||
if (cacheData != null) { | ||
//cached entry found | ||
if (cacheData.cocoTimeout == null || cacheData.cocoTimeout > new Date().getTime()) { | ||
//parse stringed cached response | ||
var cacheDataResponse = JSON.parse(cacheData.response); | ||
if (callbackSuccess) { | ||
callbackSuccess(cacheDataResponse); | ||
} | ||
return Promise.resolve(cacheDataResponse); | ||
} //cache timed out, delete it | ||
this._getCache.delete(cacheKey); | ||
} | ||
} //delete empty keys from data object | ||
Object.keys(data).forEach(function (k) { | ||
if (typeof data[k] != 'boolean' && typeof data[k] != 'number' && !data[k]) { | ||
delete data[k]; | ||
} | ||
}); //console.debug("Calling REST service (method: '" + method + "', URL: " + url + ") with data: ", data); | ||
return $.ajax({ | ||
url: url, | ||
type: method, | ||
xhrFields: xhrFields, | ||
contentType: $contentType || false, | ||
crossDomain: this.$self.CROSSDOMAIN, | ||
//enable crossdomain calls - implement serverside! | ||
data: data, | ||
dataType: 'json', | ||
//dont use jsonp for RESTservices, only GET requests allowed with jsonp | ||
processData: window.FormData && data instanceof FormData ? false : true, | ||
success: function success(response) { | ||
if (method == "GET") { | ||
if (Coco.config.restService.cacheGet < 0) { | ||
//unlimited caching | ||
_this._getCache.set(cacheKey, { | ||
response: JSON.stringify(response) | ||
}); | ||
} else { | ||
if (Coco.config.restService.cacheGet > 0) { | ||
var timeout = new Date(new Date().getTime() + 1000 * Coco.config.restService.cacheGet); // todo when array - don't make object from array | ||
_this._getCache.set(cacheKey, { | ||
cocoTimeout: timeout, | ||
response: JSON.stringify(response) | ||
}); | ||
} else {//cache disabled | ||
} | ||
} | ||
} | ||
callbackSuccess(response); | ||
}, | ||
error: function error(_error) { | ||
if (_error != null && _error.status == 401) { | ||
//Authorization failed - throw Event | ||
//this.trigger(Coco.Event.AUTHORIZATION_FAILED); | ||
_this._dispatchEvent(new RestServiceEvent(Event.AUTHORIZATION_FAILED, _error.status, _error)); | ||
} else if (_error != null && _error.status == 500) { | ||
//Authorization failed - throw Event | ||
//this.trigger(Coco.Event.INTERNAL_SERVER_ERROR, error); | ||
_this._dispatchEvent(new RestServiceEvent(Event.INTERNAL_SERVER_ERROR, _error.status, _error)); | ||
} else { | ||
_this._dispatchEvent(new RestServiceEvent(Event.REST_SERVER_ERROR, _error.status, _error)); | ||
} | ||
if (callbackError != null) { | ||
callbackError(_error); | ||
} | ||
} | ||
}); | ||
}, | ||
/** | ||
* Function: _get | ||
* | ||
* Delegates to _call using 'GET' method. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {array} pathParameter Array | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
*/ | ||
_get: function _get(endpoint, pathParameter, data, xhrFields, callbackSuccess, callbackError) { | ||
if (!Array.isArray(pathParameter)) { | ||
throw new Error("2nd parameter has to be pathParameter array, but was: " + _typeof(pathParameter)); | ||
} | ||
return this.__call(endpoint, pathParameter, 'GET', data, xhrFields, callbackSuccess, callbackError, false); | ||
}, | ||
/** | ||
* Function: _post | ||
* | ||
* Delegates to _call using 'POST' method. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
* | ||
* @param {string} contentType | ||
*/ | ||
_post: function _post(endpoint, pathParameter, data, xhrFields, callbackSuccess, callbackError, contentType) { | ||
if (!Array.isArray(pathParameter)) { | ||
throw new Error("2nd parameter has to be pathParameter array, but was: " + _typeof(pathParameter)); | ||
} | ||
return this.__call(endpoint, pathParameter, 'POST', data, xhrFields, callbackSuccess, callbackError, contentType); | ||
}, | ||
/** | ||
* Function: _postJson | ||
* | ||
* Delegates to _call using 'POST' method, contentType 'application/json' and | ||
* stringifys the data object. | ||
* Use this method if you consume a (complexly JSON) mapped object on server-side. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
*/ | ||
_postJson: function _postJson(endpoint, pathParameter, data, xhrFields, callbackSuccess, callbackError) { | ||
if (!Array.isArray(pathParameter)) { | ||
throw new Error("2nd parameter has to be pathParameter array, but was: " + _typeof(pathParameter)); | ||
} | ||
return this.__call(endpoint, pathParameter, 'POST', JSON.stringify(data), xhrFields, callbackSuccess, callbackError, 'application/json'); | ||
}, | ||
/** | ||
* Function: _put | ||
* | ||
* Delegates to _call using 'PUT' method. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
* | ||
* @param {string} contentType | ||
*/ | ||
_put: function _put(endpoint, pathParameter, data, xhrFields, callbackSuccess, callbackError, contentType) { | ||
if (!Array.isArray(pathParameter)) { | ||
throw new Error("2nd parameter has to be pathParameter array, but was: " + _typeof(pathParameter)); | ||
} | ||
return this.__call(endpoint, pathParameter, 'PUT', data, xhrFields, callbackSuccess, callbackError, contentType); | ||
}, | ||
/** | ||
* Function: _putJson | ||
* | ||
* Delegates to _call using 'PUT' method. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
*/ | ||
_putJson: function _putJson(endpoint, pathParameter, data, xhrFields, callbackSuccess, callbackError) { | ||
if (!Array.isArray(pathParameter)) { | ||
throw new Error("2nd parameter has to be pathParameter array, but was: " + _typeof(pathParameter)); | ||
} | ||
return this.__call(endpoint, pathParameter, 'PUT', JSON.stringify(data), xhrFields, callbackSuccess, callbackError, 'application/json'); | ||
}, | ||
/** | ||
* Function: _delete | ||
* | ||
* Delegates to _call using 'DELETE' method. | ||
* | ||
* Parameter: | ||
* @param {string} endpoint the REST endpoint | ||
* | ||
* @param {object} data the request data | ||
* | ||
* @param {object} xhrFields | ||
* | ||
* @param {function} callbackSuccess the success handler | ||
* | ||
* @param {function} callbackError the error handler | ||
*/ | ||
_delete: function _delete(endpoint, pathParameter, data, xhrFields, callbackSuccess, callbackError, contentType) { | ||
if (!Array.isArray(pathParameter)) { | ||
throw new Error("2nd parameter has to be pathParameter array, but was: " + _typeof(pathParameter)); | ||
} | ||
return this.__call(endpoint, pathParameter, 'DELETE', data, xhrFields, callbackSuccess, callbackError, contentType); | ||
} | ||
}); |
@@ -8,3 +8,2 @@ "use strict"; | ||
Coco.StringUtils = Coco.StringUtils || require("../lib/Coco.StringUtils.js"); | ||
/** | ||
@@ -21,5 +20,5 @@ * Class: Coco.Service | ||
*/ | ||
module.exports = dejavu.AbstractClass.declare({ | ||
$name: 'Service', | ||
$extends: Coco.ServiceProvider, | ||
@@ -49,6 +48,6 @@ | ||
throw new Error(this.$name + " has no service id!"); | ||
} | ||
//inject this service into ServiceContainer | ||
} //inject this service into ServiceContainer | ||
Coco.ServiceContainer.addService(this); | ||
this.$super(); | ||
@@ -55,0 +54,0 @@ }, |
@@ -13,40 +13,41 @@ "use strict"; | ||
*/ | ||
module.exports = Coco.ServiceContainer = dejavu.Class.declare({ | ||
$name: 'Coco.ServiceContainer', | ||
$extends: Coco.EventDispatcher, | ||
$name: 'Coco.ServiceContainer', | ||
$extends: Coco.EventDispatcher, | ||
$statics: { | ||
__services: {}, | ||
$statics: { | ||
__services: {}, | ||
/** | ||
* Function addService | ||
* | ||
* {static} function to add service class | ||
* | ||
* @param serviceInstance | ||
*/ | ||
addService: function addService(serviceInstance) { | ||
console.debug("register service for Coco: ", serviceInstance.$serviceId); | ||
if (!this.$static.__services.hasOwnProperty(serviceInstance.$serviceId)) { | ||
this.$static.__services[serviceInstance.$serviceId] = serviceInstance; | ||
} else { | ||
throw new Error("Service '" + serviceInstance.$serviceId + "' already defined with class '" + serviceInstance.$name + "'."); | ||
} | ||
} | ||
}, | ||
/** | ||
* Function: getService | ||
* Function addService | ||
* | ||
* Return the service | ||
* {static} function to add service class | ||
* | ||
* @param serviceId | ||
* @param serviceInstance | ||
*/ | ||
getService: function getService(serviceId) { | ||
if (this.$static.__services.hasOwnProperty(serviceId)) { | ||
return this.$static.__services[serviceId]; | ||
} | ||
addService: function addService(serviceInstance) { | ||
console.debug("register service for Coco: ", serviceInstance.$serviceId); | ||
throw new Error("Service '" + serviceId + "' does not exist. Maybe you forgot to initialize your service at the end of the declaration of your class, or you did not require the serviceClass.js"); | ||
if (!this.$static.__services.hasOwnProperty(serviceInstance.$serviceId)) { | ||
this.$static.__services[serviceInstance.$serviceId] = serviceInstance; | ||
} else { | ||
throw new Error("Service '" + serviceInstance.$serviceId + "' already defined with class '" + serviceInstance.$name + "'."); | ||
} | ||
} | ||
}, | ||
/** | ||
* Function: getService | ||
* | ||
* Return the service | ||
* | ||
* @param serviceId | ||
*/ | ||
getService: function getService(serviceId) { | ||
if (this.$static.__services.hasOwnProperty(serviceId)) { | ||
return this.$static.__services[serviceId]; | ||
} | ||
throw new Error("Service '" + serviceId + "' does not exist. Maybe you forgot to initialize your service at the end of the declaration of your class, or you did not require the serviceClass.js"); | ||
} | ||
}); |
@@ -6,3 +6,2 @@ "use strict"; | ||
Coco.ServiceContainer = require("./Coco.ServiceContainer.js"); | ||
/** | ||
@@ -18,81 +17,83 @@ * Class: Coco.ServiceProvider | ||
*/ | ||
module.exports = dejavu.AbstractClass.declare({ | ||
$name: 'ServiceProvider', | ||
$name: 'ServiceProvider', | ||
$extends: Coco.EventDispatcher, | ||
$extends: Coco.EventDispatcher, | ||
/** | ||
* Variable: $inject | ||
* Array to inject other services, simply provide an array of service ids. | ||
*/ | ||
$inject: [], | ||
/** | ||
* Variable: $inject | ||
* Array to inject other services, simply provide an array of service ids. | ||
*/ | ||
$inject: [], | ||
/** | ||
* Variable: $services | ||
* The services will be filled on instantiation of the class. | ||
* Key is the serviceId and value is the service instance. | ||
*/ | ||
$services: {}, | ||
initialize: function initialize() { | ||
this._injectServices(); | ||
}, | ||
/** | ||
* Variable: $services | ||
* The services will be filled on instantiation of the class. | ||
* Key is the serviceId and value is the service instance. | ||
*/ | ||
$services: {}, | ||
/** | ||
* Function: _injectServices | ||
* | ||
* {protected} function is called in constructor to inject services defined in $services-Array, deletes itself after calling 1st time | ||
*/ | ||
_injectServices: function _injectServices() { | ||
if (this.__injectServices != null) { | ||
this.__injectServices(); | ||
} else { | ||
console.warn("Services already injected, do not call this._injectServices twice!"); | ||
return; | ||
} // Protect the ServiceContainer | ||
initialize: function initialize() { | ||
this._injectServices(); | ||
}, | ||
/** | ||
* Function: _injectServices | ||
* | ||
* {protected} function is called in constructor to inject services defined in $services-Array, deletes itself after calling 1st time | ||
*/ | ||
_injectServices: function _injectServices() { | ||
if (this.__injectServices != null) { | ||
this.__injectServices(); | ||
} else { | ||
console.warn("Services already injected, do not call this._injectServices twice!"); | ||
return; | ||
} | ||
// Protect the ServiceContainer | ||
delete this.__injectServices; | ||
this._onServicesInjected(); | ||
}, | ||
delete this.__injectServices; | ||
/** | ||
* Function: _onServicesInjected | ||
* | ||
* {protected} function is called after services were injected, use it as hook to prevent overriding constructor | ||
*/ | ||
_onServicesInjected: function _onServicesInjected() {}, | ||
this._onServicesInjected(); | ||
}, | ||
/** | ||
* Function: _onServicesInjected | ||
* | ||
* {protected} function is called after services were injected, use it as hook to prevent overriding constructor | ||
*/ | ||
_onServicesInjected: function _onServicesInjected() {}, | ||
/** | ||
* __injectServices | ||
* | ||
* {private} function injects service instances | ||
*/ | ||
__injectServices: function __injectServices() { | ||
var serviceContainer = new Coco.ServiceContainer(); | ||
/** | ||
* __injectServices | ||
* | ||
* {private} function injects service instances | ||
*/ | ||
__injectServices: function __injectServices() { | ||
var serviceContainer = new Coco.ServiceContainer(); | ||
for (var i = 0; i < this.$inject.length; i++) { | ||
console.debug(this.$name + ".inject service: " + this.$inject[i]); | ||
this.$services[this.$inject[i]] = serviceContainer.getService(this.$inject[i]); | ||
} | ||
}, | ||
for (var i = 0; i < this.$inject.length; i++) { | ||
console.debug(this.$name + ".inject service: " + this.$inject[i]); | ||
this.$services[this.$inject[i]] = serviceContainer.getService(this.$inject[i]); | ||
} | ||
}, | ||
/** | ||
* Function: _getService(serviceId) | ||
* | ||
* {protected} returns special service by given service id | ||
* | ||
* Parameter: | ||
* @param serviceId - String service id to get | ||
* | ||
* Return: | ||
* @returns {Coco.Service} service | ||
*/ | ||
_getService: function _getService(serviceId) { | ||
var service = this.$services[serviceId]; | ||
if (service == null) { | ||
console.error(this.$name + " service " + serviceId + " not injected!"); | ||
} | ||
return service; | ||
/** | ||
* Function: _getService(serviceId) | ||
* | ||
* {protected} returns special service by given service id | ||
* | ||
* Parameter: | ||
* @param serviceId - String service id to get | ||
* | ||
* Return: | ||
* @returns {Coco.Service} service | ||
*/ | ||
_getService: function _getService(serviceId) { | ||
var service = this.$services[serviceId]; | ||
if (service == null) { | ||
console.error(this.$name + " service " + serviceId + " not injected!"); | ||
} | ||
return service; | ||
} | ||
}); |
@@ -0,0 +0,0 @@ /** |
"use strict"; | ||
var Coco = Coco || {}; | ||
Coco.Utils = Coco.Utils || require("../lib/Coco.Utils.js"); | ||
@@ -9,3 +8,2 @@ Coco.Model = Coco.Model || require("../model/Coco.Model.js"); | ||
Coco.View = Coco.View || require("./Coco.View.js"); | ||
/** | ||
@@ -23,68 +21,63 @@ * Class: Coco.ChildView | ||
*/ | ||
module.exports = Coco.ChildView = dejavu.Class.declare({ | ||
$name: 'Coco.ChildView', | ||
$name: 'Coco.ChildView', | ||
$extends: Coco.View, | ||
$extends: Coco.View, | ||
/** | ||
* Ctor. | ||
* | ||
* @param {Coco.Model|Coco.Collection} $model Can be a new or existing model. | ||
* @param {Object} $syncModelWithForms Override default options of view (optional). | ||
* @param {string} $template Will override `this._template` | ||
*/ | ||
initialize: function initialize($model, $syncModelWithForms, $template) { | ||
this._injectServices(); //kill service injection | ||
/** | ||
* Ctor. | ||
* | ||
* @param {Coco.Model|Coco.Collection} $model Can be a new or existing model. | ||
* @param {Object} $syncModelWithForms Override default options of view (optional). | ||
* @param {string} $template Will override `this._template` | ||
*/ | ||
initialize: function initialize($model, $syncModelWithForms, $template) { | ||
this._injectServices(); | ||
//kill service injection | ||
this._injectServices = null; | ||
this._injectServices = null; // Assign new id to the view object | ||
// Assign new id to the view object | ||
this.__id = Coco.Utils.uniqueId("v"); | ||
this.__id = Coco.Utils.uniqueId("v"); | ||
var modelSet = false; // Set the model if given | ||
var modelSet = false; | ||
if ($model instanceof Coco.Model) { | ||
modelSet = true; | ||
this.setModel($model); | ||
} // Set the collection if given | ||
// Set the model if given | ||
if ($model instanceof Coco.Model) { | ||
modelSet = true; | ||
this.setModel($model); | ||
} | ||
// Set the collection if given | ||
if (!modelSet && $model instanceof Coco.Collection) { | ||
modelSet = true; | ||
this.setCollection($model); | ||
} | ||
if (!modelSet && $model instanceof Coco.Collection) { | ||
modelSet = true; | ||
this.setCollection($model); | ||
} | ||
if ($model && !modelSet) { | ||
console.error("Invalid model object! Coco.Model or Coco.Collection expected, given: ", $model); | ||
} | ||
if ($model && !modelSet) { | ||
console.error("Invalid model object! Coco.Model or Coco.Collection expected, given: ", $model); | ||
} // Extend the options | ||
// Extend the options | ||
this._options.syncModelWithForm = null != $syncModelWithForms ? $syncModelWithForms : false; | ||
// Set the template | ||
this._template = typeof $template !== 'undefined' && null != $template ? $template : this._template; | ||
this._options.syncModelWithForm = null != $syncModelWithForms ? $syncModelWithForms : false; // Set the template | ||
// Call this._onInitialize before this.$el is set, to prevent any multiple rendering on initialization. | ||
this._onInitialize(); | ||
this._template = typeof $template !== 'undefined' && null != $template ? $template : this._template; // Call this._onInitialize before this.$el is set, to prevent any multiple rendering on initialization. | ||
// Create the html wrapper element. | ||
this.$el = $(this._anchor); | ||
this.$el.attr('data-coco', this.__id); | ||
this._onInitialize(); // Create the html wrapper element. | ||
this._configure(); | ||
}, | ||
/** | ||
* Function: autoRender() | ||
* Calls render. This function is used when ChildViews are added to another View. If the user does not want to | ||
* automatically render his ChildViews, override this function and leave it empty. | ||
* | ||
* Return: | ||
* @return Coco.View - The current <Coco.View> instance. | ||
*/ | ||
autoRender: function autoRender() { | ||
return this.render(); | ||
} | ||
this.$el = $(this._anchor); | ||
this.$el.attr('data-coco', this.__id); | ||
this._configure(); | ||
}, | ||
/** | ||
* Function: autoRender() | ||
* Calls render. This function is used when ChildViews are added to another View. If the user does not want to | ||
* automatically render his ChildViews, override this function and leave it empty. | ||
* | ||
* Return: | ||
* @return Coco.View - The current <Coco.View> instance. | ||
*/ | ||
autoRender: function autoRender() { | ||
return this.render(); | ||
} | ||
}); |
"use strict"; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
/** @namespace **/ | ||
var Coco = Coco || {}; | ||
Coco.Event = require("../event/Coco.Event.js"); | ||
@@ -14,4 +13,4 @@ Coco.RouterEvent = require("../event/Coco.RouterEvent.js"); | ||
Coco.Model = require("../model/Coco.Model.js"); | ||
Coco.Collection = require("../model/Coco.Collection.js"); | ||
//! do not require ChildView here!, because there is no Coco.View class during require process ! | ||
Coco.Collection = require("../model/Coco.Collection.js"); //! do not require ChildView here!, because there is no Coco.View class during require process ! | ||
/** | ||
@@ -27,7 +26,6 @@ * Class: Coco.View | ||
*/ | ||
module.exports = Coco.View = dejavu.Class.declare({ | ||
$name: 'Coco.View', | ||
$extends: Coco.ServiceProvider, | ||
$statics: { | ||
@@ -55,4 +53,3 @@ /** | ||
*/ | ||
_add: function _add(model) { | ||
//var etherObjects = {}; | ||
_add: function _add(model) {//var etherObjects = {}; | ||
//var etherModel = model.getEtherKeys(); | ||
@@ -94,3 +91,3 @@ // | ||
return value.slice(); | ||
} else if ((typeof value === "undefined" ? "undefined" : _typeof(value)) === 'object') { | ||
} else if (_typeof(value) === 'object') { | ||
//return object clone to protect original model | ||
@@ -237,16 +234,13 @@ return $.extend({}, value); | ||
this.$super(); | ||
this.$super(); // Assign new id to the view object | ||
// Assign new id to the view object | ||
this.__id = Coco.Utils.uniqueId("v"); | ||
var modelSet = false; // Set the model if given | ||
var modelSet = false; | ||
// Set the model if given | ||
if ($model instanceof Coco.Model) { | ||
modelSet = true; | ||
this.setModel($model); | ||
} | ||
} // Set the collection if given | ||
// Set the collection if given | ||
if ($model instanceof Coco.Collection) { | ||
@@ -259,8 +253,7 @@ modelSet = true; | ||
console.error("Invalid model object! Coco.Model or Coco.Collection expected, given: ", $model); | ||
} | ||
} // Extend the options | ||
// Extend the options | ||
this._options.syncModelWithForm = null != $syncModelWithForms ? $syncModelWithForms : false; | ||
// Call this._onInitialize before this.$el is set, to prevent any multiple rendering on initialization. | ||
this._options.syncModelWithForm = null != $syncModelWithForms ? $syncModelWithForms : false; // Call this._onInitialize before this.$el is set, to prevent any multiple rendering on initialization. | ||
this._onInitialize(); | ||
@@ -272,14 +265,16 @@ | ||
}); | ||
} | ||
} // Create the html wrapper element. | ||
// Create the html wrapper element. | ||
this.$el = $(this._anchor); | ||
if (this.$el == null || this.$el.length == 0) { | ||
console.error(this.$name + "-anchor [" + this._anchor + "] not found in DOM: ", this.$el); | ||
} | ||
this.$el.attr('data-coco', this.__id); | ||
this._configure(); | ||
this._configure(); //we only use precompiled templates | ||
//we only use precompiled templates | ||
if (this._template != null) { | ||
@@ -362,2 +357,3 @@ //no autorender anymore! | ||
} | ||
this._collection = collection; | ||
@@ -414,3 +410,2 @@ | ||
_onFirstRender: function _onFirstRender() {}, | ||
onPreActive: function onPreActive() { | ||
@@ -457,7 +452,8 @@ this.$el.attr('data-coco', this.__id); | ||
throw new Error("Could not render Coco.View [" + this.$name + "], no template found! ", this._template); | ||
} | ||
} // If 'locale' parameter exists in Coco.config - send locale information to template | ||
// This parameter will be used by 'handlebars-intl' extension (formatjs) | ||
// If 'locale' parameter exists in Coco.config - send locale information to template | ||
// This parameter will be used by 'handlebars-intl' extension (formatjs) | ||
var localeObject = {}; | ||
var coco = require('../Coco.Init'); | ||
@@ -473,5 +469,5 @@ | ||
}; | ||
} | ||
} //we use require now, so hbs templates are precompiled, just add the model here | ||
//we use require now, so hbs templates are precompiled, just add the model here | ||
var html = this._template(this._getHBSModel(), localeObject); | ||
@@ -483,3 +479,2 @@ | ||
if (this.__isActive) { | ||
// Empty/append ONLY IF the $el inside main container is not THE SAME | ||
@@ -494,7 +489,8 @@ if (this._getRouter() && this._getRouter().$container.children().first()[0] != this.$el[0]) { | ||
if (this._firstRendered === false) { | ||
this._firstRendered = true; | ||
//use delayed callback, to let the DOM get rendered | ||
this._firstRendered = true; //use delayed callback, to let the DOM get rendered | ||
setTimeout(function () { | ||
_this2._onFirstRender(); | ||
//also call delegate events delayed | ||
_this2._onFirstRender(); //also call delegate events delayed | ||
_this2.delegateEvents(); | ||
@@ -558,5 +554,4 @@ | ||
_getHBSModel: function _getHBSModel() { | ||
var props = {}; | ||
var props = {}; //use only simple comparison, to catch null and undefined | ||
//use only simple comparison, to catch null and undefined | ||
if (this._collection != null || this._model != null) { | ||
@@ -572,2 +567,3 @@ /** | ||
} | ||
props = this._collection == null ? this._model.getAttributes() : { | ||
@@ -593,3 +589,2 @@ collection: { | ||
this.render(); | ||
return this.$el.get(); | ||
@@ -622,2 +617,3 @@ }, | ||
this._model.destroy(); | ||
this._model = null; | ||
@@ -628,8 +624,8 @@ } | ||
this._collection.destroy(); | ||
this._collection = null; | ||
} | ||
this.removeAllEventListener(); | ||
this.removeAllEventListener(); //stop listening jQuery events | ||
//stop listening jQuery events | ||
this.undelegateEvents(); | ||
@@ -696,2 +692,3 @@ this.removeAllChildViews(); | ||
var $container = this.$el.find(selector); | ||
if (!$addToAllMatching) { | ||
@@ -712,3 +709,2 @@ $container = $container.first(); | ||
} | ||
/** | ||
@@ -720,2 +716,3 @@ * Call child views _onFirstRender. Because this method is called after the first rendering, but has no effect | ||
return view; | ||
@@ -741,16 +738,15 @@ }, | ||
this.__childViews[selector] = []; | ||
} | ||
} // Create virtual DOM element | ||
// Create virtual DOM element | ||
var $virtualElement = $(document.createDocumentFragment()); | ||
// Append all childviews to it | ||
var $virtualElement = $(document.createDocumentFragment()); // Append all childviews to it | ||
collection.each(function (model) { | ||
var view_instance = new view_definition(model); | ||
_this5.__childViews[selector].push(view_instance); | ||
$virtualElement.append(view_instance.getDOM()); | ||
}); | ||
}); // Append virtual element to actual HTML | ||
// Append virtual element to actual HTML | ||
this.$el.find(selector).first().append($virtualElement); | ||
@@ -771,3 +767,2 @@ }, | ||
var ret = this.__childViews[selector]; | ||
return ret instanceof Array ? ret : []; | ||
@@ -835,2 +830,3 @@ }, | ||
} | ||
return 0; | ||
@@ -882,2 +878,3 @@ }, | ||
this.__childViews[views][i].remove(); | ||
this.__childViews[views].splice(i, 1); | ||
@@ -957,5 +954,5 @@ | ||
_this6._model = null; | ||
}, true); | ||
}, true); //this works only with 1 model | ||
//this works only with 1 model | ||
if (this._options.syncModelWithForm) { | ||
@@ -990,5 +987,4 @@ this.$el.on('change', 'select, textarea, input', function (e) { | ||
view.delegateEvents(null); | ||
}); | ||
}); //do not delegate events twice | ||
//do not delegate events twice | ||
return; | ||
@@ -1010,5 +1006,5 @@ } | ||
throw new Error("The callback function '" + callback + "' does not exist in '" + this.$name + "'."); | ||
} | ||
} //TODO remove dejavu binding | ||
//TODO remove dejavu binding | ||
this.$el.on(event, selector, this[callback].$bind(this)); | ||
@@ -1040,5 +1036,4 @@ } | ||
var event = key.substr(0, key.indexOf(' ')); | ||
var selector = key.substr(key.indexOf(' ') + 1); | ||
var selector = key.substr(key.indexOf(' ') + 1); //remove evenhandler | ||
//remove evenhandler | ||
this.$el.off(event, selector); | ||
@@ -1068,3 +1063,2 @@ } | ||
$duration = null != $duration ? $duration : 100; | ||
this.$(selector).animate(properties, $duration, $callback); | ||
@@ -1101,11 +1095,8 @@ }, | ||
}, | ||
isActive: function isActive() { | ||
return this.__isActive; | ||
}, | ||
activate: function activate() { | ||
this.__isActive = true; | ||
}, | ||
deactivate: function deactivate() { | ||
@@ -1112,0 +1103,0 @@ this.__isActive = false; |
{ | ||
"name": "3m5-coco", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"description": "a simple MVC Framework", | ||
@@ -32,15 +32,13 @@ "main": "lib/Coco.Init.js", | ||
{ | ||
"name": "Erik Neumann", | ||
"email": "erik.neumann@3m5.de" | ||
"name": "Erik Swars", | ||
"email": "erik.swars@3m5.de" | ||
}, | ||
{ | ||
"name": "Sergey Rizovs", | ||
"email": "sergey.rizovs@3m5.de" | ||
"name": "Lukas Gerlach", | ||
"email": "lukas.gerlach@3m5.de" | ||
} | ||
], | ||
"devDependencies": { | ||
"babel-plugin-es6-promise": "^1.0.0", | ||
"babel-preset-es2015": "^6.9.0", | ||
"babel-preset-stage-2": "^6.11.0", | ||
"babel-preset-stage-3": "^6.11.0", | ||
"@babel/core": "^7.4.3", | ||
"@babel/preset-env": "^7.4.3", | ||
"browserify": "^13.0.0", | ||
@@ -50,3 +48,3 @@ "domain": "0.0.1", | ||
"gulp": "^3.9.1", | ||
"gulp-babel": "^6.1.2", | ||
"gulp-babel": "^8.0.0", | ||
"gulp-clean": "^0.3.2", | ||
@@ -64,6 +62,7 @@ "gulp-concat": "^2.5.2", | ||
}, | ||
"peerDependencies": { | ||
"@babel/polyfill": "^7.4.3", | ||
"jquery": "^2.2.4" | ||
}, | ||
"dependencies": { | ||
"JSON": "^1.0.0", | ||
"babel-polyfill": "^6.9.1", | ||
"jquery": "^2.2.4", | ||
"underscore": "^1.8.3" | ||
@@ -70,0 +69,0 @@ }, |
@@ -0,0 +0,0 @@ <p align="center"> |
Sorry, the diff of this file is not supported yet
425866
3
18
36
7709
+ Added@babel/polyfill@7.12.1(transitive)
+ Addedregenerator-runtime@0.13.11(transitive)
- RemovedJSON@^1.0.0
- Removedbabel-polyfill@^6.9.1
- Removedjquery@^2.2.4
- RemovedJSON@1.0.0(transitive)
- Removedbabel-polyfill@6.26.0(transitive)
- Removedbabel-runtime@6.26.0(transitive)
- Removedregenerator-runtime@0.10.50.11.1(transitive)