Created
June 28, 2012 10:24
-
-
Save jsmaker/3010529 to your computer and use it in GitHub Desktop.
some inheritance tests on view object
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Element.prototype.__appendChild = Element.prototype.appendChild; | |
//Element.prototype.appendChild = function(){Element.prototype.__appendChild.apply(this, arguments); this.classList.contains('view') && console.log.apply(console, arguments)}; | |
var BObject = function BObject() {}; | |
BObject.$super = function (fn, args, name, parent) { | |
parent = parent || this.parent(); | |
debugger; | |
if (parent) { | |
if (parent.name === name && parent.prototype[fn]) { | |
fn = parent.prototype[fn]; | |
return fn && fn.apply(this, args); | |
} else { | |
this.$super(fn, args,name, parent); | |
} | |
} | |
}; | |
BObject.parent = function () { | |
return undefined; | |
}; | |
BObject.childOf = function (BObjectType) { | |
var obj = this; | |
while (obj) { | |
if (BObjectType === obj.name) { | |
return true; | |
} | |
obj = obj.parent ? obj.parent() : false; | |
} | |
return false; | |
}; | |
BObject.inheritancePath = function (more) { | |
var obj = this; | |
var path = []; | |
while (obj) { | |
if (more) { | |
path.unshift({name:obj.name, constructor:obj}); | |
}else { | |
path.unshift(obj.name); | |
} | |
obj = obj.parent ? obj.parent() : false; | |
} | |
return path; | |
}; | |
BObject.create = function (O1) { | |
console.count(O1.name || O1); | |
if (typeof O1 === 'string') { | |
O1 = (new Function('return function ' + O1 + '(){this.init(arguments);}'))(); | |
} | |
BObject.create.classes[O1.name] = O1; | |
var O2 = this; | |
var parent = function (name) { | |
if (name) { | |
if (O2.name === name) { | |
return O2; | |
} | |
return O2.parent(name); | |
} | |
return O2; | |
}; | |
O1.create = O2.create; | |
O1.inheritancePath = O2.inheritancePath; | |
O1.$super = O2.$super; | |
O1.guid = O2.guid; | |
O1.parent = parent; | |
O1.childOf = O2.childOf; | |
//O1.instance = O1.prototype; | |
O1.prototype = Object.create(O2.prototype); | |
O1.prototype.parent = parent; | |
O1.prototype.guid = O1.guid(O1.name); | |
O1.prototype.constructor = O1; | |
return O1; | |
}; | |
BObject.create.classes = { | |
BObject: BObject | |
}; | |
BObject.guid = function (prefix) { | |
var counterMap = BObject.guid.counterMap; | |
var add = function () { | |
if (counterMap[prefix] >= 0) { | |
counterMap[prefix] += 1; | |
} else { | |
counterMap[prefix] = 0; | |
} | |
return prefix + counterMap[prefix]; | |
}; | |
add.counterMap = counterMap; | |
return add; | |
}; | |
BObject.guid.counterMap = {}; | |
BObject.prototype.guid = BObject.guid('BObject'); | |
BObject.prototype.initialize = function (repeatElement) { | |
this.id = this.guid(); | |
this.props = {}; | |
this.data = {}; | |
}; | |
BObject.prototype.runSuper = function (fn, args) { | |
var parent; | |
if ((parent = this.parent())) { | |
fn = parent.prototype[fn]; | |
return fn && fn.apply(this, args); | |
} | |
}; | |
BObject.prototype.log = function () { | |
var args = Array.prototype.slice.call(arguments) ; | |
args.unshift(this.id + ': '); | |
console.log.apply(console, args); | |
}; | |
BObject.prototype.parent = BObject.parent; | |
BObject.prototype.init = function (args) { | |
var parents; | |
var parent = this.parent(); | |
var stack = []; | |
while (parent) { | |
stack.push(parent.prototype); | |
parent = parent.parent ? parent.parent() : false; | |
} | |
parents = stack.pop(); | |
while (parents) { | |
parents.initialize.apply(this, args); | |
parents = stack.pop(); | |
} | |
this.initialize.apply(this, args); | |
return this; | |
}; | |
BObject.prototype.instanceOf = function (BObjectType) { | |
var obj = this.constructor; | |
while (obj) { | |
if (BObjectType === obj.name) { | |
return true; | |
} | |
obj = obj.parent ? obj.parent() : false; | |
} | |
return false; | |
}; | |
var Observer = BObject.create('Observer'); | |
Observer.prototype.initialize = function () { | |
this.listeners = {}; | |
}; | |
Observer.prototype.set = function (propName, newVlaue, namespace) { | |
var self, | |
oldValue; | |
namespace = namespace || 'this'; | |
if (namespace === 'this') { | |
self = this; | |
} else { | |
self = this[namespace]; | |
if (!self) { | |
self = this[namespace] = {}; | |
} | |
} | |
oldValue = self[propName]; | |
self[propName] = newVlaue; | |
this.fireListeners('propChange', propName, oldValue, newVlaue); | |
return newVlaue; | |
}; | |
Observer.prototype.addListener = function (channel, fn) { | |
this.listeners[channel] = this.listeners[channel] || []; | |
this.listeners[channel].push(fn); | |
}; | |
Observer.prototype.fireListeners = function (channel, propName, oldValue, newVlaue) { | |
var listeners = this.listeners[channel]; | |
if (listeners) { | |
for (var i = 0; i < listeners.length; i++) { | |
listeners[i].apply(this, arguments); | |
} | |
} | |
return this; | |
}; | |
Observer.prototype.getFireStarter = function (channel, propName) { | |
var observer = this; | |
return function(data){ | |
observer.fireListeners(channel, propName, data); | |
}; | |
}; | |
var View = Observer.create('View'); | |
window.View = View; | |
View.createCSS = function (selector, declaration, style_node) { | |
var rules; | |
var i; | |
style_node = View.styleNode || style_node; | |
if (style_node) { | |
rules = style_node.sheet.rules || style_node.sheet.cssRules; | |
for (i = rules.length; i--; 1) { | |
if (rules[i].selectorText === selector) { | |
//style_node.sheet.deleteRule(i); | |
return style_node; | |
} | |
} | |
} | |
// test for IE | |
var ua = navigator.userAgent.toLowerCase(); | |
var isIE = (/msie/.test(ua)) && !(/opera/.test(ua)) && (/win/.test(ua)); | |
// create the style node for all browsers | |
style_node = style_node || (function () { | |
var style_node = document.createElement("style"); | |
style_node.setAttribute("type", "text/css"); | |
style_node.setAttribute("media", "screen"); | |
return style_node; | |
}()); | |
// append a rule for good browsers | |
if (!isIE){ | |
style_node.appendChild(document.createTextNode(selector + " {" + declaration + "}")); | |
} | |
// append the style node | |
document.getElementsByTagName("head")[0].appendChild(style_node); | |
// use alternative methods for IE | |
if (isIE && document.styleSheets && document.styleSheets.length > 0) { | |
var last_style_node = document.styleSheets[document.styleSheets.length - 1]; | |
if (typeof(last_style_node.addRule) === "object"){ | |
last_style_node.addRule(selector, declaration); | |
} | |
} | |
return style_node; | |
} | |
View.styleNode = View.createCSS('*', '-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;'); | |
View.createCSS('.box-view','background:#f3f3f3;margin:10px 0;width:100%;'); | |
View.createCSS('.box-view-node','padding:1%;margin:0;display:inline-block;vertical-align:top;'); | |
View.getAll = function(){ | |
var viewsList = Array.prototype.map.call(document.querySelectorAll('.view'), function(el){ return el.getView()}); | |
console.log(viewsList); | |
return viewsList; | |
} | |
View.prototype.initialize = function () { | |
this.subViews = []; | |
this.domEvents = []; | |
this.strings = {}; | |
this.props.tagName = 'section'; | |
this.props.classNameView = 'view'; | |
return this; | |
}; | |
//View.prototype.createCSS = View.createCSS; | |
View.prototype.createGUI = function (appendTo) { | |
if (!this.node) { | |
this.createMarkup(); | |
this.renderViews(); | |
this.applyCostumGUI(); | |
this.rgisterEvents(); | |
} | |
if (appendTo) { | |
appendTo.appendChild(this.node); | |
} | |
return this.node; | |
}; | |
View.prototype.createMarkup = function () { | |
var view = this; | |
this.node = document.createElement(this.props.tagName); | |
this.node.getView = function () { | |
return view; | |
}; | |
this.node.className = this.props.classNameView; | |
return this.node; | |
}; | |
View.prototype.renderViews = function () { | |
for (var i = 0; i < this.subViews.length; i++) { | |
this.node.appendChild(this.subViews[i].createGUI()); | |
} | |
}; | |
View.prototype.applyCostumGUI = function () { | |
if (this.costumGUI) { | |
return this.costumGUI.apply(this, this); | |
} | |
}; | |
View.prototype.getSubView = function (index) { | |
return this.subViews[index]; | |
}; | |
View.prototype.addSubView = function (view) { | |
view.parentView = this; | |
this.subViews.push(view); | |
view.createGUI(this.node); | |
return view; | |
}; | |
View.prototype.removeSubView = function (index) { | |
var view = this.subViews.splice(index, 1); | |
if (view.length) { | |
view = view[0]; | |
delete view.parentView; | |
this.node.removeChild(view.node); | |
return view; | |
} | |
}; | |
View.prototype.replaceSubView = function (index) { | |
var view = this.subViews.splice(index, 1); | |
if (view.length) { | |
view = view[0]; | |
delete view.parentView; | |
this.node.removeChild(view.node); | |
return view; | |
} | |
}; | |
View.prototype.handleDomEvents = function (type, node, e) { | |
if (node !== this.node) { | |
this.log('target is not node'); | |
} | |
this.log('DomEvent', this, type, node, e); | |
}; | |
View.prototype.rgisterEvents = function () { | |
var view = this; | |
var fnHandler = function (e) { | |
if (!e.cancelBubble) { | |
view.handleDomEvents(e.type, this, e); | |
} | |
}; | |
for (var i = 0; i < this.domEvents.length; i++) { | |
this.node.addEventListener(this.domEvents[i], fnHandler, false); | |
} | |
}; | |
var BoxView = View.create('BoxView'); | |
BoxView.prototype.initialize = function (o) { | |
this.props.classNameView += ' box-view'; | |
this.setInRow(o.inRow); | |
}; | |
BoxView.prototype.setInRow = function (count) { | |
this.props.inRow = count || 1; | |
this.applyBox(); | |
return this.node; | |
}; | |
BoxView.prototype.addSubView = function (view) { | |
View.prototype.addSubView.call(this, view); | |
this.applyBox(); | |
return this.node; | |
}; | |
BoxView.prototype.applyBox = function () { | |
var viewNode; | |
for (var i = 0; i < this.subViews.length; i++) { | |
viewNode = this.subViews[i].node; | |
if (viewNode && !viewNode.classList.contains('box-view-node') || viewNode.dataset.inRow !== this.props.inRow) { | |
viewNode.dataset.inRow = this.props.inRow; | |
viewNode.classList.add('box-view-node'); | |
viewNode.style.cssText = 'width:'+ 100/this.props.inRow +'%;'; | |
} | |
} | |
}; | |
var NodeView = View.create('NodeView'); | |
NodeView.prototype.initialize = function (node) { | |
this.props.classNameView += ' node-view'; | |
this.data.element = node; | |
}; | |
NodeView.prototype.costumGUI = function () { | |
if (typeof this.data.element === 'string') { | |
this.node.innerHTML = this.data.element; | |
} else { | |
this.node.appndChild(this.data.element); | |
} | |
}; | |
var TextView = View.create('TextView'); | |
TextView.prototype.initialize = function (tagName, text) { | |
this.data.text = text; | |
this.props.tagName = tagName; | |
this.props.classNameView += ' text-view'; | |
}; | |
TextView.prototype.costumGUI = function () { | |
if (typeof this.data.text === 'string') { | |
this.node.textContent = this.data.text; | |
} | |
}; | |
var ListView = View.create('ListView'); | |
window.ListView = ListView; | |
ListView.prototype.initialize = function (repeatElement) { | |
this.data.repeatElement = repeatElement; | |
this.props.tagName = 'ul'; | |
this.props.classNameView += ' list-view'; | |
}; | |
ListView.prototype.costumGUI = function () { | |
for (var i = 0; i < this.data.repeatElement.length; i++) { | |
this.addSubView(new TextView('li', this.data.repeatElement[i]+'')); | |
} | |
}; | |
var SimpleListView = View.create('SimpleListView'); | |
window.SimpleListView = SimpleListView; | |
SimpleListView.prototype.initialize = function (repeatElement) { | |
this.data.repeatElement = repeatElement; | |
this.props.tagName = 'ul'; | |
this.props.classNameView += ' simple-list-view'; | |
}; | |
SimpleListView.prototype.costumGUI = function () { | |
var r = ''; | |
for (var i = 0; i < this.data.repeatElement.length; i++) { | |
r += '<li>' + this.data.repeatElement[i] + '</li>' | |
} | |
this.node.innerHTML = r; | |
}; | |
var myView = BoxView.create('myView'); | |
myView.prototype.initialize = function (o) { | |
this.domEvents = ['click', 'change']; | |
this.addSubView(new TextView('h3', o.title)); | |
this.addSubView(new TextView('p', o.text)); | |
this.addSubView(new ListView(o.list)); | |
this.addSubView(new SimpleListView(o.list)); | |
this.createGUI(o.appendTo); | |
this.addListener('propChange', function () { | |
console.log(this, arguments); | |
}); | |
}; | |
myView.prototype.costumGUI = function () { | |
var el = document.createElement('input'); | |
//this.node.appendChild(el); | |
}; | |
myView.prototype.handleDomEvents = function (type, node, e) { | |
this.log(type, node, e, e.target); | |
e.stopPropagation(); | |
}; | |
window.myViewInstance = new myView({ | |
appendTo : document.body, | |
inRow : 3, | |
title : 'Hi this is myView', | |
text : 'this is some text', | |
list : ['item1', 'item2', 'item3', 'item4'], | |
}); | |
var myViewInstance2 = new myView({ | |
appendTo : document.body, | |
inRow : 3, | |
title : 'Hi this is myView', | |
text : 'this is some text', | |
list : ['item1', 'item2', 'item3', 'item4'], | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment