385 lines
14 KiB
JavaScript
385 lines
14 KiB
JavaScript
"use strict";
|
|
(function view_js() {
|
|
var moduleName = "views/view";
|
|
|
|
var defineArray = [];
|
|
defineArray.push("lib/utils/subscribable");
|
|
defineArray.push("views/helpers/draggable");
|
|
defineArray.push("lib/utils/enum");
|
|
|
|
define(moduleName, defineArray, function view_module() {
|
|
var counter = 0;
|
|
var Subscribable = require("lib/utils/subscribable");
|
|
var Draggable = require("views/helpers/draggable");
|
|
var Enum = require("lib/utils/enum");
|
|
|
|
var View = Subscribable.inherit({
|
|
"className": "View",
|
|
"constructor": function View (controller, options, element) {
|
|
Subscribable.fn.constructor.call(this);
|
|
this._destroying = false;
|
|
|
|
var base = {
|
|
minWidth: 0,
|
|
minHeight: 0,
|
|
maxWidth: Infinity,
|
|
maxHeight: Infinity,
|
|
draggable: false,
|
|
sizeDependency: SizeDependency.straight.independent
|
|
};
|
|
W.extend(base, options);
|
|
|
|
this._id = ++counter;
|
|
this._o = base;
|
|
this._f = controller;
|
|
if (element) {
|
|
this._e = element;
|
|
} else {
|
|
this._e = document.createElement("div");
|
|
}
|
|
this._p = undefined;
|
|
this._w = undefined;
|
|
this._h = undefined;
|
|
this._x = 0;
|
|
this._y = 0;
|
|
|
|
this._initElement();
|
|
|
|
if (this._o.draggable) {
|
|
this._initDraggable();
|
|
}
|
|
|
|
this._f.on("data", this._onData, this);
|
|
this._f.on("clearProperties", this._onClearProperties, this);
|
|
this._f.on("addProperty", this._onAddProperty, this);
|
|
this._f.on("newController", this._onNewController, this);
|
|
|
|
for (var i = 0; i < this._f._controllers.length; ++i) {
|
|
this._onNewController(this._f._controllers[i]);
|
|
}
|
|
//if (this._f.initialized) {
|
|
this._onData(this._f);
|
|
//}
|
|
|
|
View.collection[this._id] = this;
|
|
this._applyProperties();
|
|
},
|
|
"destructor": function() {
|
|
this._destroying = true;
|
|
this._f.off("data", this._onData, this);
|
|
this._f.off("clearProperties", this._onClearProperties, this);
|
|
this._f.off("addProperty", this._onAddProperty, this);
|
|
this._f.off("newController", this._onNewController, this);
|
|
|
|
this.remove()
|
|
if (this._o.draggable) {
|
|
this._dg.destructor();
|
|
}
|
|
|
|
delete View.collection[this._id];
|
|
|
|
Subscribable.fn.destructor.call(this);
|
|
},
|
|
"addClass": function(className) {
|
|
this._e.classList.add(className);
|
|
},
|
|
"_applyProperties": function() {
|
|
for (var i = 0; i < this._f.properties.length; ++i) {
|
|
var prop = this._f.properties[i];
|
|
this._onAddProperty(prop.k, prop.p);
|
|
}
|
|
},
|
|
_closestSize: function(w, h) {
|
|
return { //this is for cases when dimensions depend on each other, must be implemented in child classes
|
|
w: w, //supposed to return closest to given size basing on dependency
|
|
h: h
|
|
}
|
|
},
|
|
"constrainHeight": function(h) {
|
|
h = Math.max(h, this._o.minHeight);
|
|
h = Math.min(h, this._o.maxHeight);
|
|
|
|
return h;
|
|
},
|
|
"constrainWidth": function(w) {
|
|
w = Math.max(w, this._o.minWidth);
|
|
w = Math.min(w, this._o.maxWidth);
|
|
|
|
return w;
|
|
},
|
|
"getAbsolutePosition": function() {
|
|
var pp;
|
|
if (this._p) {
|
|
pp = this._p.getAbsolutePosition();
|
|
} else {
|
|
pp = Object.create(null);
|
|
pp.x = 0;
|
|
pp.y = 0;
|
|
}
|
|
|
|
pp.x += this._x;
|
|
pp.y += this._y;
|
|
|
|
return pp;
|
|
},
|
|
"_initDraggable": function() {
|
|
this._dg = new Draggable(this, {
|
|
snapDistance: this._o.snapDistance
|
|
});
|
|
},
|
|
"_initElement": function() {
|
|
this._e.style.position = "absolute";
|
|
this._e.style.top = "0";
|
|
this._e.style.left = "0";
|
|
this._e.style.boxSizing = "border-box";
|
|
this._e.style.overflow = "hidden";
|
|
this._e.id = this._id;
|
|
},
|
|
"_onAddProperty": function(key, propertyName) {
|
|
var value = View.theme[key];
|
|
if (value) {
|
|
this._e.style[propertyName] = value;
|
|
}
|
|
},
|
|
"_onClearProperties": function() {
|
|
// for (var key in this._e.style) {
|
|
// if (this._e.style.hasOwnProperty(key)) {
|
|
// delete this._e.style[key];
|
|
// }
|
|
// }
|
|
this._initElement();
|
|
this._e.style.left = this._x + "px";
|
|
this._e.style.top = this._y + "px";
|
|
this._e.style.width = this._w + "px";
|
|
this._e.style.height = this._h + "px";
|
|
},
|
|
"_onData": function() {},
|
|
"_onNewController": function() {},
|
|
"remove": function() {
|
|
if (this._p) {
|
|
this._p.removeChild(this);
|
|
delete this._p; //just to make sure
|
|
}
|
|
},
|
|
"removeClass": function(className) {
|
|
this._e.classList.remove(className);
|
|
},
|
|
"_resetTheme": function() {
|
|
this._onClearProperties();
|
|
this._applyProperties();
|
|
},
|
|
"setConstSize": function(w, h) {
|
|
this._o.maxWidth = w;
|
|
this._o.maxHeight = h;
|
|
this._o.minWidth = w;
|
|
this._o.minHeight = h;
|
|
|
|
if (this._w !== undefined && this._h !== undefined) {
|
|
this.setSize(this._w, this._h);
|
|
}
|
|
|
|
this.trigger("changeLimits", this);
|
|
},
|
|
"setLeft": function(l) {
|
|
this._x = l;
|
|
this._e.style.left = this._x + "px";
|
|
},
|
|
"_setLimits": function(minWidth, minHeight, maxWidth, maxHeight) {
|
|
var needToTell = false;
|
|
if (this._o.minWidth !== minWidth) {
|
|
needToTell = true;
|
|
this._o.minWidth = minWidth;
|
|
}
|
|
if (this._o.maxWidth !== maxWidth) {
|
|
needToTell = true;
|
|
this._o.maxWidth = maxWidth;
|
|
}
|
|
if (this._o.minHeight !== minHeight) {
|
|
needToTell = true;
|
|
this._o.minHeight = minHeight;
|
|
}
|
|
if (this._o.maxHeight !== maxHeight) {
|
|
needToTell = true;
|
|
this._o.maxHeight = maxHeight;
|
|
}
|
|
if (needToTell) {
|
|
this.trigger("changeLimits", this);
|
|
if (this._w !== undefined && this._h !== undefined) {
|
|
this.setSize(this._w, this._h);
|
|
}
|
|
}
|
|
|
|
return needToTell && this._events.changeLimits && this._events.changeLimits.length; //to see if someone actually going to listen that event, if not - return result
|
|
},
|
|
"setMaxSize": function(w, h) {
|
|
if (this._o.maxHeight !== h || this._o.maxWidth !== w) {
|
|
this._o.maxWidth = w;
|
|
this._o.maxHeight = h;
|
|
|
|
if (this._w !== undefined && this._h !== undefined) {
|
|
this.setSize(this._w, this._h);
|
|
}
|
|
|
|
this.trigger("changeLimits", this);
|
|
}
|
|
},
|
|
"setMinSize": function(w, h) {
|
|
if (this._o.minHeight !== h || this._o.minWidth !== w) {
|
|
this._o.minWidth = w;
|
|
this._o.minHeight = h;
|
|
|
|
if (this._w !== undefined && this._h !== undefined) {
|
|
this.setSize(this._w, this._h);
|
|
}
|
|
|
|
this.trigger("changeLimits", this);
|
|
}
|
|
},
|
|
"setSize": function(w, h) {
|
|
var nw = this.constrainWidth(w);
|
|
var nh = this.constrainHeight(h);
|
|
|
|
if (this._o.sizeDependency !== SizeDependency.straight.independent) {
|
|
var obj = this._closestSize(nw, nh);
|
|
nw = obj.w;
|
|
nh = obj.h;
|
|
}
|
|
|
|
if (nw !== this._w || nh !== this._h) {
|
|
this._w = nw;
|
|
this._h = nh;
|
|
|
|
this._e.style.width = this._w + "px";
|
|
this._e.style.height = this._h + "px";
|
|
|
|
this.trigger("resize", this._w, this._h);
|
|
}
|
|
},
|
|
"setTop": function(t) {
|
|
this._y = t;
|
|
this._e.style.top = this._y + "px";
|
|
},
|
|
"trySize": function(w, h) {
|
|
return !(w < this._o.minWidth || h < this._o.minHeight || w > this._o.maxWidth || h > this._o.maxHeight)
|
|
},
|
|
"setSizeDependency": function(d) {
|
|
this._o.sizeDependency = d;
|
|
this.trigger("sizeDependencyChange", d);
|
|
},
|
|
"getMinWidthForHeight": function(h) {
|
|
return this._o.minWidth;
|
|
},
|
|
"getMaxWidthForHeight": function(h) {
|
|
return this._o.maxWidth;
|
|
},
|
|
"getMinHeightForWidth": function(w) {
|
|
return this._o.minHeight;
|
|
},
|
|
"getMaxHeightForWidth": function(h) {
|
|
return this._o.maxHeight;
|
|
}
|
|
});
|
|
|
|
View.theme = Object.create(null);
|
|
View.collection = Object.create(null);
|
|
View.setTheme = function(theme) {
|
|
for (var key in this.theme) {
|
|
delete this.theme[key];
|
|
}
|
|
for (var key in theme) {
|
|
if (theme.hasOwnProperty(key)) {
|
|
this.theme[key] = theme[key];
|
|
}
|
|
}
|
|
|
|
for (var id in this.collection) {
|
|
this.collection[id]._resetTheme();
|
|
}
|
|
}
|
|
|
|
View.createByType = function(type, ctrl, opts) {
|
|
var typeName = this.ReversedViewType[type];
|
|
if (typeName === undefined) {
|
|
throw new Error("Unknown ViewType: " + type);
|
|
}
|
|
var Type = this.constructors[typeName];
|
|
if (Type === undefined) {
|
|
throw new Error("Constructor is not loaded yet, something is wrong");
|
|
}
|
|
return new Type(ctrl, opts);
|
|
}
|
|
|
|
View.initialize = function(rc, cb) {
|
|
var deps = [];
|
|
var types = [];
|
|
for (var key in this.ViewTypesPaths) {
|
|
if (this.ViewTypesPaths.hasOwnProperty(key)) {
|
|
if (!rc || rc.indexOf(key) !== -1) {
|
|
deps.push(this.ViewTypesPaths[key]);
|
|
types.push(key);
|
|
}
|
|
}
|
|
}
|
|
require(deps, function() {
|
|
for (var i = 0; i < types.length; ++i) {
|
|
View.constructors[types[i]] = arguments[i];
|
|
}
|
|
cb();
|
|
});
|
|
}
|
|
|
|
View.ViewType = {
|
|
Label: 0,
|
|
|
|
Image: 4,
|
|
Button: 5,
|
|
View: 6,
|
|
Enumeration: 7,
|
|
|
|
Page: 102,
|
|
PanesList: 104,
|
|
Player: 107
|
|
};
|
|
|
|
View.ReversedViewType = {
|
|
"0": "Label",
|
|
|
|
"4": "Image",
|
|
"5": "Button",
|
|
"6": "View",
|
|
"7": "Enumeration",
|
|
|
|
"101": "Nav",
|
|
"102": "Page",
|
|
"104": "PanesList",
|
|
|
|
"107": "Player"
|
|
};
|
|
|
|
View.ViewTypesPaths = {
|
|
Label: "views/label",
|
|
Nav: "views/nav",
|
|
Page: "views/page",
|
|
PanesList: "views/panesList",
|
|
Image: "views/image",
|
|
Button: "views/button",
|
|
Player: "views/player",
|
|
Enumeration: "views/enumeration"
|
|
};
|
|
|
|
View.constructors = {
|
|
View: View
|
|
};
|
|
|
|
var SizeDependency = new Enum("SizeDependency");
|
|
SizeDependency.add("independent");
|
|
SizeDependency.add("straight");
|
|
SizeDependency.add("reversed");
|
|
SizeDependency.add("undefined");
|
|
|
|
View.SizeDependency = SizeDependency;
|
|
|
|
return View;
|
|
});
|
|
})();
|