js/core/core-def.js
/**
* @namespace
*
*/
var Ergo = (function(){
var E = {};
/**
* Копирование свойств одного объекта в другой (создание примеси)
* @param {Object} obj целевой объект, которому будут добавлены новые свойства
* @name Ergo.override
* @function
*/
E.merge = function(obj) {
for(var j = 1; j < arguments.length; j++){
var overrides = arguments[j] || {};
for(var i in overrides) {
var desc = Object.getOwnPropertyDescriptor(overrides, i);
if( desc && (desc.set || desc.get) ) {
var descOrig = Object.getOwnPropertyDescriptor(obj, i);
if(descOrig) {
descOrig.set = desc.set || descOrig.set;
descOrig.get = desc.get || descOrig.get;
}
else {
descOrig = desc;
}
Object.defineProperty(obj, i , descOrig);
}
else {
obj[i] = overrides[i];
}
}
}
return obj;
};
// E.merge = function(obj) {
// for(var j = 1; j < arguments.length; j++){
// var overrides = arguments[j] || {};
// for(var i in overrides) {
// var desc = Object.getOwnPropertyDescriptor(overrides, i);
// if( desc && (desc.set || desc.get) ) {
// //
// }
// else {
// obj[i] = overrides[i];
// }
// }
// }
// return obj;
// };
// с объектом сливаются геттеры/сеттеры, которых в нем нет
E.mergeProperties = function(obj) {
for(var j = 1; j < arguments.length; j++){
var overrides = arguments[j] || {};
for(var i in overrides) {
var desc = Object.getOwnPropertyDescriptor(overrides, i);
if( desc && (desc.set || desc.get) ) {
var desc2 = Object.getOwnPropertyDescriptor(obj, i);
if(desc2) {
desc2.set = desc2.set || desc.set;
desc2.get = desc2.get || desc.get;
}
else {
desc2 = desc;
}
Object.defineProperty(obj, i , desc2);
}
}
}
return obj;
};
/**
* Полное копирование свойств одного объекта в другой (перегрузка)
* @param {Object} obj целевой объект, которому будут добавлены новые свойства
* @name @Ergo.deepMerge
* @function
*
*/
E.deepMerge = function(o) {
for(var j = 1; j < arguments.length; j++) {
var srcObj = arguments[j];
// E.each(srcObj, function(p, i){
for(var i in srcObj) {
var desc = Object.getOwnPropertyDescriptor(srcObj, i);
if(desc && (desc.get || desc.set) ) {
var descOrig = Object.getOwnPropertyDescriptor(o, i);
if(descOrig) {
descOrig.set = desc.set || descOrig.set;
descOrig.get = desc.get || descOrig.get;
}
else {
descOrig = desc;
}
Object.defineProperty(o, i , descOrig);
}
else {
var p = srcObj[i];
if( p && p.constructor == Object ){//$.isPlainObject(p) ){
// if(!(i in o) || !$.isPlainObject(o[i])) o[i] = {};
if(!(i in o) || (o[i] && o[i].constructor != Object)) o[i] = {};
Ergo.deepMerge(o[i], p);
}
else if( p && p.constructor == Array ) {//$.isArray(p) ){
// if(!(i in o) || !$.isArray(o[i])) o[i] = [];
if(!(i in o) || (o[i] && o[i].constructor != Array)) o[i] = [];
Ergo.deepMerge(o[i], p);
}
else {
o[i] = p;
}
}
}
}
return o;
};
E.copy = function(srcObj) {
var o = {};
for(var i in srcObj) {
o[i] = srcObj[i];
}
return o;
};
// var ruleTypes = {
// handlers: function(a, b) {
// for(var i in b) {
//
// }
// }
// };
E.rules = {
include: 'list',
set: ['override'],
get: ['override'],
events: ['object', {'*': 'list'}],
as: 'list',
cls: false,//'list',
data: false,
etype: false,
// tag: false,
// cls: 'list',
// stt: 'list',
defaultItem: ['object'],
defaultComponent: ['object'],
nestedItem: ['object'],
// '$*': ['object'],
components: ['object', {'*': ['object']}],
items: ['array', {'*': ['object']}],
states: ['object'],//, {'*': 'list'}],
style: ['override'],//, {'*': 'list'}],
transitions: ['object'],//, {'*': 'list'}]
};
E.mergeOptions = function(o, sources, rules) {
sources = Array.isArray(sources) ? sources : [sources];
rules = rules || E.rules;
for(var i = 0; i < sources.length; i++) {
for(var j in sources[i]) {
var name = (j[0] == '~' || j[0] == '!') ? j.substr(1) : j;
var rule = (rules[name] != null) ? rules[name] : rules['*'];
var a = o[name];
var b = sources[i][j];
// FIXME
if( j[0] == '$' ) {
rule = ['object'];
}
// если определено правило, то опции будут представлять из себя коллекцию
if( rule && rule.constructor === Array ) {
if( b == null ) {
o[name] = b;
}
else if(rule[0] == 'override') {
// o[name] = (a == null) ? b : E.deepMerge(a, b);
o[name] = (a == null) ? E.deepCopy(b) : E.deepMerge(a, b);
}
else if( b.constructor === Object ) {
a = a || {};
b = b;
o[name] = E.mergeOptions(a, b, rule[1]);
}
else if( b.constructor === Array ) {
a = a || [];
b = [b];
o[name] = E.mergeOptions(a, b, rule[1]);
}
// if( /*o[name] != null &&*/ (b.constructor === Object || b.constructor === Array) ) {
// if( rule[0] == 'object' ) {
// a = a || {};
// b = b;
// o[name] = E.mergeOptions(a, b, rule[1]);
// }
// else if( rule[0] == 'array' ) {
// a = a || [];
// b = [b];
// o[name] = E.mergeOptions(a, b, rule[1]);
// }
// else if( rule[0] == 'override' ) {
// o[name] = (a == null) ? b : E.merge(a, b);
// }
//
// }
else {
o[name] = b;
}
// if( b instanceof Object ) {
//
// }
// var a = (rule[0] == 'array') ? (a || []) : (a || {});
// var b = (rule[0] == 'array') ? [b] : b;
}
// else if( rule && rule.constructor === Array ) {
// o[name] = E.mergeOptions(o[name] || [], sources[i][j], rule[0]);
// }
else if( rule === false ) {
o[name] = b;
}
else if( rule ) {
a = Array.isArray(a) ? a : [a];
b = Array.isArray(b) ? b : [b];
if( !o[name] ) {
o[name] = b;
}
else if(j[0] == '!') {
// переписываем опцию
o[name] = b;
}
else if(j[0] == '~') {
// находим разницу
for(var n = 0; n < b.length; n++) {
$ergo.remove(a, b[n]);
}
o[name] = a;
}
// else if( ruleTypes[rule] ) {
// o[name] = ruleTypes[rule].call(this, a, b);
// }
else {
// находим сумму
o[name] = a.concat(b);
}
}
else if( a && b && b.constructor == Object ) {
$ergo.deepMerge(o[name], b);
}
else {
o[name] = $ergo.deepCopy(b);
}
}
}
return o;
}
E.mergeInclude = function(obj, inc) {
// for(var j = 0; j < includes.length; j++) {
// var inc = includes[j];
for(var i in inc) {
var desc = Object.getOwnPropertyDescriptor(inc, i);
if( desc && (desc.set || desc.get) ) {
var desc2 = Object.getOwnPropertyDescriptor(obj, i);
if(desc2) {
desc2.set = desc2.set || desc.set;
desc2.get = desc2.get || desc.get;
}
else {
desc2 = desc;
}
Object.defineProperty(obj, i , desc2);
}
else if(i == 'defaults') {
obj.options = $ergo.mergeOptions({}, [inc[i], obj.options]);
}
else if( i == '_postConstruct' || i == '_preConstruct' || i == '_construct' || i == '_destroy' /*|| i == '_postDestroy' || i == '_preDestroy'*/) {
// skip
}
else if(typeof inc[i] == 'object') {
obj[i] = $ergo.deepMerge(obj[i], inc[i]);
}
else {
obj[i] = inc[i];
}
}
// }
return obj;
};
E.override = E.merge;
E.deepOverride = E.deepMerge;
E.overrideOptions = E.mergeOptions;
E.overrideProperties = E.mergeProperties;
E.overrideInclude = E.mergeInclude;
// var _clear = false;
/*
var smart_override_prop = function(o, srcObj, i, context) {
var p = srcObj[i];
var prefix = i[0];
// var j = i;
// var keep_prefix = !_clear;
if(prefix == '!' || prefix == '+' || prefix == '-') {
i = i.substr(1);
}
else {
prefix = false;
if(i == 'data') prefix = '!'; //<-- поле data не перегружается
if(i == 'mixins') prefix = '+'; //<-- поле mixins сливается
if(i == 'cls') prefix = '+';
if(i == 'as') prefix = '+';
if(i == 'include') prefix = '+';
if(i == 'state') prefix = '+';
if( /^on\S/.test(i) ) prefix = '+';
if(/\/events$/.test(context)) {
prefix = '+';
}
// if(prefix)
// keep_prefix = false;
// Если в целевом объекте присутствует префиксная форма, то берется ее префикс
if('!'+i in o) {
prefix = '!';
// i = '!'+i;
}
else if('+'+i in o) {
prefix = '+';
// i = '+'+i;
}
else if('-'+i in o) {
prefix = '-';
// i = '-'+i;
}
}
if(prefix) {//prefix == '!' || prefix == '+' || prefix == '-') {
var j = prefix + i;
// var j = i.substr(1);
// if(_clear) i = j;
var m = null;
if(prefix == '+') {
m = [];
if(i in o)
m = o[i];
if(j in o)
m = o[j];
if( !Array.isArray(m) ) m = [m];
m = m.concat(p);
o[j] = m;
// if(keep_prefix) {
// o[j] = m;
// if(i in o) delete o[i];
// }
// else {
// o[i] = m;
// if(j in o) delete o[j];
// }
// if(!(i in o)) o[i] = [];
// if( !$.isArray(o[i]) ) o[i] = [o[i]];
// p = o[i].concat(p);
// o[i] = p;
}
else if(prefix == '-') {
m = [];
if(i in o)
m = o[i];
if(j in o)
m = o[j];
if( !Array.isArray(m) ) m = [m];
m = m.concat(p);
o[j] = m;
// TODO
// m = [];
//
// if(i in o)
// m = o[i];
// if(j in o)
// m = o[j];
//
// if( !$.isArray(m) ) m = [m];
//
// if( !$.isArray(p) ) p = [p];
//
// for(var k = 0; k < p.length; k++)
// Ergo.remove_from_array(m, p[k]);
//
//
// if(keep_prefix) {
// o[j] = m;
// if(i in o) delete o[i];
// }
// else {
// o[i] = m;
// if(j in o) delete o[j];
// }
}
else {
m = p;
o[j] = m;
// if(m === undefined) delete o[i];
// o[i] = p;
}
// if(keep_prefix) {
// o[j] = m;
// if(i in o) delete o[i];
// }
// else {
// o[i] = m;
// if(j in o) delete o[j];
// }
// if(j in o && !_clear) delete o[j];
}
else{
//TODO здесь создается полная копия (deep copy) объекта-контейнера
if( p && p.constructor == Object ) {//$.isPlainObject(p) ){
// if(!(i in o) || !$.isPlainObject(o[i])) o[i] = {};
if(!(i in o) || (o[i] && o[i].constructor != Object)) o[i] = {};
smart_override_obj(o[i], p, context+'/'+i);
}
else if( p && p.constructor == Array ){//$.isArray(p) ){
// if(!(i in o) || !$.isArray(o[i])) o[i] = [];
if(!(i in o) || (o[i] && o[i].constructor != Array)) o[i] = [];
smart_override_obj(o[i], p, context+'/'+i);
}
else {
//TODO этот участок кода нужно исправить
// // если элемент в перегружаемом параметре существует, то он может быть обработан специфически
// if(i in o){
// // классы сливаются в одну строку, разделенную пробелом
// // if(i == 'cls') p = o[i] + ' ' + p;
// if( /^on\S/.test(i) ) {
// if( !$.isArray(o[i]) ) o[i] = [o[i]];
// p = o[i].concat(p);
// }
// // if(i == 'state') {
// // p = o[i] + ' ' + p;
// // }
// }
o[i] = p;
}
}
};
var smart_override_obj = function(dest, src, context) {
if(!dest)
dest = {};
for(var i in src) {
smart_override_prop(dest, src, i, context);
}
};
*/
/**
* "Умное" копирование свойств одного объекта в другой (условная перегрузка)
* @param {Object} obj целевой объект, которому будут добавлены новые свойства
* @name @Ergo.smart_override
* @function
*
*/
/*
E.smart_override = function(o) {
// если перегружаемый объект содержит метод smart_override, то используем именно его
if(o && o.smart_override) {
// args будет содержать только список перегрузок
var args = Array.prototype.slice.call(arguments);
args.shift();
return o.smart_override.apply(o, args);
}
// var keep_keys = false;
if(!o) {
// _keep_keys = keep_keys = true;
o = {};
}
// обходим все аргументы, начиная со второго
for(var j = 1; j < arguments.length; j++){
var srcObj = arguments[j];
smart_override_obj(o, srcObj, '');
// for(var i in srcObj)
// smart_override_prop(o, srcObj, i);
// if( $.isArray(srcObj) ){
// for(var i = 0; i < srcObj.length; i++)
// Ergo.utils.overrideProp(o, srcObj, i);
// }
// else {
// }
}
// if(keep_keys)
// _keep_keys = false;
return o;
};
E.smart_build = function(o, key) {
// применяем модификатор +
for(var i in o) {
var prefix = i[0];
if(prefix == '+') {
var j = i.substr(1);
var m = (j in o) ? o[j] : [];
if( !Array.isArray(m) ) m = [m];
m = m.concat(o[i]);
o[j] = m;
delete o[i];
}
if(prefix == '-') {
var j = i.substr(1);
var m = (j in o) ? o[j] : [];
if( !Array.isArray(m) ) m = [m];
for(var n = 0; n < o[i].length; n++) {
for(var k = 0; k < m.length; k++) {
if(m[k] == o[i][n]) m.splice(k, 1);
}
}
delete o[i];
}
if(prefix == '!') {
var j = i.substr(1);
if( o[i] === undefined )
delete o[j];
else
o[j] = o[i];
delete o[i];
}
}
// // применяем модификатор -
// for(var i in o) {
//
// var prefix = i[0];
//
// if(prefix == '-') {
//
// var j = i.substr(1);
//
// var m = (j in o) ? o[j] : [];
// if( !$.isArray(m) ) m = [m];
//
// for(var n = 0; n < o[i].length; n++) {
// for(var k = 0; k < m.length; k++) {
// if(m[k] == o[i][n]) m.splice(k, 1);
// }
// }
//
// delete o[i];
// }
// }
//
// // применяем модификатор !
// for(var i in o) {
//
// var prefix = i[0];
//
// if(prefix == '!') {
//
// var j = i.substr(1);
//
// if( o[i] === undefined )
// delete o[j];
// else
// o[j] = o[i];
//
// delete o[i];
// }
//
// }
if( k == 'shortcuts' || k == 'components' || k == 'items')
return;
// if(i == 'items')
// return;
for(var i in o) {
if(i == 'defaultItem' || i == 'defaultComponent' || i == 'layout' || i == 'nestedItem')
continue;
if(o[i] && o[i].constructor == Object)
E.smart_build(o[i], i);
}
};
*/
/*
E.self_smart_override = function() {
// console.log(this);
// console.log(arguments);
_clear = true;
// обходим все аргументы, начиная со второго
for(var j = 0; j < arguments.length; j++){
var srcObj = arguments[j];
smart_override_obj(this, srcObj, '');
// for(var i in srcObj)
// smart_override_prop(this, srcObj, i);
}
_clear = false;
return this;
};
*/
// E.etypes = function() { return _etypes; }
// E.defineClass = E.declare;
// E.widget = E.object;
/*
E.isFunction = function(obj) { return obj instanceof Function; };
E.isArray = function(obj) {return obj instanceof Array;}
E.isNumber = function(obj) {return typeof obj == 'number';};
E.isBoolean = function(obj) {return typeof obj == 'boolean';};
E.isString = function(obj) {return typeof obj == 'string';};
E.isObject = function(obj) { return obj.constructor == Object; };
*/
// в версии jquery 1.4 появились методы, которые раньше реализовывались в Ergo
/**
* Является ли объект функцией
*
* @name $.isFunction
* @function
* @param {Object} obj
*/
// E.isFunction = $.isFunction;
/**
* Является ли объект массивом
*
* @name $.isArray
* @function
* @param {Object} obj
*/
// E.isArray = $.isArray;
/**
* Является ли объект простым объектом
*
* @name $.isPlainObject
* @function
* @param {Object} obj
*/
// E.isPlainObject = $.isPlainObject;
/**
* Является ли объект строкой
*
* @name $.isString
* @function
* @param {Object} obj
*/
E.isString = $.isString = function(obj) {
return typeof obj == 'string';
};
/**
* Является ли объект логической переменной
*
* @name Ergo.isBoolean
* @function
* @param {Object} obj
*/
E.isBoolean = $.isBoolean = function(obj) {
return typeof obj == 'boolean';
};
/**
* Является ли объект числом
*
* @name $.isNumber
* @function
* @param {Object} obj
*/
// $.isNumber = function(obj) {
// return typeof obj == 'number';
// };
E.isObject = function(obj) {
return obj.constructor === 'object';
}
//---------------------------------------------------
//
// Фильтры
//
//---------------------------------------------------
// E.sort_numbers = function(a, b) {
// return a - b;
// };
E.KeyCode = {
UP: 38,
DOWN: 40,
ENTER: 13,
ESC: 27
};
return E;
})();
//var _dino = Ergo;
// alias for Ergo
var ergo = Ergo;
/**
* @namespace
*/
Ergo.core = {};
/*
* Расширяем базовый класс Array методом удаления элемента
*
* @name Array.prototype.remove
* @function
* @param {Any} val элемент массива
*/
/*
Array.prototype.remove = function(val) {
var index = -1;
for(var i = 0; i < this.length; i++) {
if(this[i] == val) {
index = i;
break;
}
}
if(index != -1) this.splice(index, 1);
return (index != -1);
}
*/
//$ergo = Ergo;
Ergo.globals = {
};