/** * This file is part of JIM (c) 2016 Edward Langley * * See the COPYING document in the root of the source distribution for licensing information. */ PresentationType = (function () { var presentationTypes = {}; // TODO: think through selector better: right now, I think we assume that it // is a class selector and things will break if it isn't we should, // however, probably let it be more general. function PresentationType(name, selector) { if (this instanceof PresentationType) { this.name = name; if (selector === undefined) { selector = '.'+this.name; } this.selector = selector; this.receivers = []; } else { var result = presentationTypes[name]; if (result === undefined) { result = new PresentationType(name); presentationTypes[result.name] = result; } return result; } } PresentationType.prototype = { presentationsTypes: presentationTypes, isOfType(name) { var type = presentationTypes[name]; //console.log(name); //console.log(type); return type.isPrototypeOf(this); }, addReceiver(receiver) { this.receivers.push(receiver); return this.receivers.length - 1; }, removeReceiver(el) { var elIdx = this.receivers.indexOf(el); var result = elIdx !== -1; if (result) { this.receivers.splice(elIdx,1); } return result; }, notifyReceivers(theEvent, self) { if (self === undefined) { self = this; } var outerArgs = Array.prototype.slice.call(arguments); outerArgs.unshift(theEvent, self, self.value); this.receivers.forEach((function (theReceiver) { theReceiver.receive.apply(theReceiver, outerArgs); })); var parent = Object.getPrototypeOf(this); if (parent instanceof PresentationType && parent.receivers !== undefined && parent.receivers !== []) { parent.notifyReceivers(theEvent, self); } }, selectAllTags() { return Array.prototype.slice.call( document.querySelectorAll(this.selector) ); }, selectAll() { var allTags = this.selectAllTags(); return Array.prototype.map.call(allTags, function (el) { return el.ptObject; }); }, bindTags() { var els = this.selectAllTags().filter(function (theEl) { return theEl.ptObject === undefined; }); els.forEach(this.bindEl, this); return this; }, bindEl(theEl) { var content = theEl.textContent.trim(); var value = theEl.value; var bindTypes = theEl.dataset.bind; if (bindTypes !== undefined) { bindTypes = bindTypes.split(','); } else { bindTypes = ['click']; } //console.log('bt',bindTypes); if (! theEl.hasAttribute('value') ) { var tmpVal = theEl.dataset.value; value = tmpVal === undefined ? content : theEl.dataset.value; } return this.wrapTag(theEl, value, bindTypes, content); }, wrapTag(tag, value, bindTypes, content) { var result = Object.assign( Object.create(this), { tag: tag, value: value, display: content, } ); tag.ptObject = result; this.classes.forEach(function (cls) { tag.classList.add(cls); }); bindTypes.forEach(function (event) { //console.log(event); tag.addEventListener(event, result, false); }); if (result.validate()) { return result; } else { this.doError(result); } }, get classes() { var current = this, classes = new Set(); while (current instanceof PresentationType) { if (current.name !== undefined) { classes.add(current.name); } current = Object.getPrototypeOf(current); } return classes; }, extend(name, props) { if (this.children === undefined) { this.children = []; } if (props === undefined) { props = {}; } props.name = name; if (props.selector === undefined) { props.selector = '.' + name; } props.receivers = []; var newType = Object.assign(Object.create(this), props); presentationTypes[name] = newType; this.children.push(newType); return newType; }, makeTag(value, tagName, bindTypes, content) { var newTag = document.createElement(tagName); this.classes.forEach(function (cls) { newTag.classList.add(cls); }); if (bindTypes === undefined) { bindTypes = []; } else if (!(bindTypes instanceof Array)) { content = bindTypes; bindTypes = []; } if (content === undefined) { content = value; } newTag.textContent = content; return this.wrapTag(newTag, value, bindTypes, content); }, handleEvent(theEvent) { //console.log('handling: ',theEvent); var handler = this[theEvent.type]; var result = true; if (handler !== undefined) { result = handler.bind(this)(theEvent); } this.notifyReceivers(theEvent); return result; }, doError(object) { return; }, validate() { return true; }, toggleAll() { var els = this.selectAllTags(); els.forEach(function (el) { el.classList.toggle('activated'); }); }, deactivateAll() { var els = this.selectAllTags(); els.forEach(function (el) { el.classList.remove('activated'); }); }, activateAll() { this.bindTags(); var els = this.selectAllTags(); els.forEach(function (el) { el.classList.add('activated'); }); return els; }, }; var typeType = PresentationType('type'); typeType.generateTags = function (tagName) { if (tagName === undefined) { tagName = 'span'; } return Object.keys(presentationTypes).map( function (type) { var tag = document.createElement(tagName); return this.wrapTag(tag, type, ['click'], type); }, this ); }; return PresentationType; })();