From 5796e1f97da6a4b2f38f23def07b8fe19dc63b77 Mon Sep 17 00:00:00 2001 From: Ruud Date: Mon, 27 Feb 2012 20:38:18 +0100 Subject: [PATCH] Javascript library updates --- .../static/scripts/library/mootools.js | 346 +++++++++----- .../static/scripts/library/prefix_free.js | 421 +++++++++++++++++- .../static/scripts/library/templated.js | 411 ----------------- couchpotato/templates/_desktop.html | 1 - 4 files changed, 651 insertions(+), 528 deletions(-) delete mode 100644 couchpotato/static/scripts/library/templated.js diff --git a/couchpotato/static/scripts/library/mootools.js b/couchpotato/static/scripts/library/mootools.js index a4d83f8d..9917ad32 100644 --- a/couchpotato/static/scripts/library/mootools.js +++ b/couchpotato/static/scripts/library/mootools.js @@ -8,6 +8,9 @@ web build: packager build: - packager build Core/Class Core/Class.Extras Core/Element Core/Element.Style Core/Element.Delegation Core/Element.Dimensions Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request.JSON Core/Cookie Core/DOMReady +... +*/ + /* --- @@ -17,7 +20,7 @@ description: The heart of MooTools. license: MIT-style license. -copyright: Copyright (c) 2006-2010 [Valerio Proietti](http://mad4milk.net/). +copyright: Copyright (c) 2006-2012 [Valerio Proietti](http://mad4milk.net/). authors: The MooTools production team (http://mootools.net/developers/) @@ -33,8 +36,8 @@ provides: [Core, MooTools, Type, typeOf, instanceOf, Native] (function(){ this.MooTools = { - version: '1.4.2', - build: '552dfd4704fccffed444e0211c50831a2bfe209f' + version: '1.4.5', + build: 'ab8ea8824dc3b24b6666867a2c4ed58ebb762cf0' }; // typeOf, instanceOf @@ -61,6 +64,9 @@ var instanceOf = this.instanceOf = function(item, object){ if (constructor === object) return true; constructor = constructor.parent; } + /**/ + if (!item.hasOwnProperty) return false; + /**/ return item instanceof object; }; @@ -93,8 +99,9 @@ Function.prototype.overloadGetter = function(usePlural){ var self = this; return function(a){ var args, result; - if (usePlural || typeof a != 'string') args = a; + if (typeof a != 'string') args = a; else if (arguments.length > 1) args = arguments; + else if (usePlural) args = [a]; if (args){ result = {}; for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]); @@ -251,14 +258,18 @@ var force = function(name, object, methods){ proto = prototype[key]; if (generic) generic.protect(); - - if (isType && proto){ - delete prototype[key]; - prototype[key] = proto.protect(); - } + if (isType && proto) object.implement(key, proto.protect()); } - if (isType) object.implement(prototype); + if (isType){ + var methodsEnumerable = prototype.propertyIsEnumerable(methods[0]); + object.forEachMethod = function(fn){ + if (!methodsEnumerable) for (var i = 0, l = methods.length; i < l; i++){ + fn.call(prototype, prototype[methods[i]], methods[i]); + } + for (var key in prototype) fn.call(prototype, prototype[key], key) + }; + } return force; }; @@ -429,8 +440,9 @@ Array.implement({ filter: function(fn, bind){ var results = []; - for (var i = 0, l = this.length >>> 0; i < l; i++){ - if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]); + for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this){ + value = this[i]; + if (fn.call(bind, value, i, this)) results.push(value); } return results; }, @@ -1787,8 +1799,14 @@ local.setDocument = function(document){ // contains // FIXME: Add specs: local.contains should be different for xml and html documents? - features.contains = (root && this.isNativeCode(root.contains)) ? function(context, node){ + var nativeRootContains = root && this.isNativeCode(root.contains), + nativeDocumentContains = document && this.isNativeCode(document.contains); + + features.contains = (nativeRootContains && nativeDocumentContains) ? function(context, node){ return context.contains(node); + } : (nativeRootContains && !nativeDocumentContains) ? function(context, node){ + // IE8 does not have .contains on document. + return context === node || ((context === document) ? document.documentElement : context).contains(node); } : (root && root.compareDocumentPosition) ? function(context, node){ return context === node || !!(context.compareDocumentPosition(node) & 16); } : function(context, node){ @@ -2183,7 +2201,7 @@ local.matchSelector = function(node, tag, id, classes, attributes, pseudos){ var i, part, cls; if (classes) for (i = classes.length; i--;){ - cls = node.getAttribute('class') || node.className; + cls = this.getAttribute(node, 'class'); if (!(cls && classes[i].regexp.test(cls))) return false; } if (attributes) for (i = attributes.length; i--;){ @@ -2369,7 +2387,7 @@ var pseudos = { 'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true), 'index': function(node, index){ - return this['pseudo:nth-child'](node, '' + index + 1); + return this['pseudo:nth-child'](node, '' + (index + 1)); }, 'even': function(node){ @@ -2441,10 +2459,6 @@ for (var p in pseudos) local['pseudo:' + p] = pseudos[p]; var attributeGetters = local.attributeGetters = { - 'class': function(){ - return this.getAttribute('class') || this.className; - }, - 'for': function(){ return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for'); }, @@ -2479,7 +2493,7 @@ attributeGetters.MAXLENGTH = attributeGetters.maxLength = attributeGetters.maxle var Slick = local.Slick = (this.Slick || {}); -Slick.version = '1.1.6'; +Slick.version = '1.1.7'; // Slick finder @@ -2638,7 +2652,10 @@ new Type('Element', Element).mirror(function(name){ if (!Browser.Element){ Element.parent = Object; - Element.Prototype = {'$family': Function.from('element').hide()}; + Element.Prototype = { + '$constructor': Element, + '$family': Function.from('element').hide() + }; Element.mirror(function(name, method){ Element.Prototype[name] = method; @@ -2753,16 +2770,17 @@ if (object[1] == 1) Elements.implement('splice', function(){ return result; }.protect()); -Elements.implement(Array.prototype); +Array.forEachMethod(function(method, name){ + Elements.implement(name, method); +}); Array.mirror(Elements); /**/ var createElementAcceptsHTML; try { - var x = document.createElement(''); - createElementAcceptsHTML = (x.name == 'x'); -} catch(e){} + createElementAcceptsHTML = (document.createElement('').name == 'x'); +} catch (e){} var escapeQuotes = function(html){ return ('' + html).replace(/&/g, '&').replace(/"/g, '"'); @@ -2821,7 +2839,11 @@ Document.implement({ element: function(el, nocash){ Slick.uidOf(el); if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){ - el._fireEvent = el.fireEvent; + var fireEvent = el.fireEvent; + // wrapping needed in IE7, or else crash + el._fireEvent = function(type, event){ + return fireEvent(type, event); + }; Object.append(el, Element.Prototype); } return el; @@ -3001,13 +3023,8 @@ Array.forEach([ properties[property.toLowerCase()] = property; }); -Object.append(properties, { - 'html': 'innerHTML', - 'text': (function(){ - var temp = document.createElement('div'); - return (temp.textContent == null) ? 'innerText': 'textContent'; - })() -}); +properties.html = 'innerHTML'; +properties.text = (document.createElement('div').textContent == null) ? 'innerText': 'textContent'; Object.forEach(properties, function(real, key){ propertySetters[key] = function(node, value){ @@ -3056,7 +3073,7 @@ Object.append(propertySetters, { }, 'value': function(node, value){ - node.value = value || ''; + node.value = (value != null) ? value : ''; } }); @@ -3072,10 +3089,31 @@ try { el.type = 'button'; } catch(e){} if (el.type != 'button') propertySetters.type = function(node, value){ node.setAttribute('type', value); }; +el = null; /* */ +/**/ +var input = document.createElement('input'); +input.value = 't'; +input.type = 'submit'; +if (input.value != 't') propertySetters.type = function(node, type){ + var value = node.value; + node.type = type; + node.value = value; +}; +input = null; +/**/ + /* getProperty, setProperty */ +/* */ +var pollutesGetAttribute = (function(div){ + div.random = 'attribute'; + return (div.getAttribute('random') == 'attribute'); +})(document.createElement('div')); + +/* */ + Element.implement({ setProperty: function(name, value){ @@ -3083,8 +3121,21 @@ Element.implement({ if (setter){ setter(this, value); } else { - if (value == null) this.removeAttribute(name); - else this.setAttribute(name, value); + /* */ + if (pollutesGetAttribute) var attributeWhiteList = this.retrieve('$attributeWhiteList', {}); + /* */ + + if (value == null){ + this.removeAttribute(name); + /* */ + if (pollutesGetAttribute) delete attributeWhiteList[name]; + /* */ + } else { + this.setAttribute(name, '' + value); + /* */ + if (pollutesGetAttribute) attributeWhiteList[name] = true; + /* */ + } } return this; }, @@ -3097,6 +3148,18 @@ Element.implement({ getProperty: function(name){ var getter = propertyGetters[name.toLowerCase()]; if (getter) return getter(this); + /* */ + if (pollutesGetAttribute){ + var attr = this.getAttributeNode(name), attributeWhiteList = this.retrieve('$attributeWhiteList', {}); + if (!attr) return null; + if (attr.expando && !attributeWhiteList[name]){ + var outer = this.outerHTML; + // segment by the opening tag and find mention of attribute name + if (outer.substr(0, outer.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(name) < 0) return null; + attributeWhiteList[name] = true; + } + } + /* */ var result = Slick.getAttribute(this, name); return (!result && !Slick.hasAttribute(this, name)) ? null : result; }, @@ -3223,7 +3286,7 @@ var get = function(uid){ }; var clean = function(item){ - var uid = item.uid; + var uid = item.uniqueNumber; if (item.removeEvents) item.removeEvents(); if (item.clearAttributes) item.clearAttributes(); if (uid != null){ @@ -3269,7 +3332,7 @@ Element.implement({ if (node.clearAttributes){ node.clearAttributes(); node.mergeAttributes(element); - node.removeAttribute('uid'); + node.removeAttribute('uniqueNumber'); if (node.options){ var no = node.options, eo = element.options; for (var j = no.length; j--;) no[j].selected = eo[j].selected; @@ -3369,60 +3432,77 @@ Element.Properties.tag = { }; -/**/ -Element.Properties.html = (function(){ +Element.Properties.html = { - var tableTest = Function.attempt(function(){ - var table = document.createElement('table'); - table.innerHTML = ''; - }); + set: function(html){ + if (html == null) html = ''; + else if (typeOf(html) == 'array') html = html.join(''); + this.innerHTML = html; + }, - var wrapper = document.createElement('div'); - - var translations = { - table: [1, '', '
'], - select: [1, ''], - tbody: [2, '', '
'], - tr: [3, '', '
'] - }; - translations.thead = translations.tfoot = translations.tbody; - - /**/ - // technique by jdbarlett - http://jdbartlett.com/innershiv/ - wrapper.innerHTML = ''; - var HTML5Test = wrapper.childNodes.length == 1; - if (!HTML5Test){ - var tags = 'abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' '), - fragment = document.createDocumentFragment(), l = tags.length; - while (l--) fragment.createElement(tags[l]); - fragment.appendChild(wrapper); + erase: function(){ + this.innerHTML = ''; } - /**/ - var html = { - set: function(html){ - if (typeOf(html) == 'array') html = html.join(''); +}; - var wrap = (!tableTest && translations[this.get('tag')]); - /**/ - if (!wrap && !HTML5Test) wrap = [0, '', '']; - /**/ - if (wrap){ - var first = wrapper; - first.innerHTML = wrap[1] + html + wrap[2]; - for (var i = wrap[0]; i--;) first = first.firstChild; - this.empty().adopt(first.childNodes); - } else { - this.innerHTML = html; - } - } - }; +/**/ +// technique by jdbarlett - http://jdbartlett.com/innershiv/ +var div = document.createElement('div'); +div.innerHTML = ''; +var supportsHTML5Elements = (div.childNodes.length == 1); +if (!supportsHTML5Elements){ + var tags = 'abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' '), + fragment = document.createDocumentFragment(), l = tags.length; + while (l--) fragment.createElement(tags[l]); +} +div = null; +/**/ - html.erase = html.set; +/**/ +var supportsTableInnerHTML = Function.attempt(function(){ + var table = document.createElement('table'); + table.innerHTML = ''; + return true; +}); - return html; -})(); -/**/ +/**/ +var tr = document.createElement('tr'), html = ''; +tr.innerHTML = html; +var supportsTRInnerHTML = (tr.innerHTML == html); +tr = null; +/**/ + +if (!supportsTableInnerHTML || !supportsTRInnerHTML || !supportsHTML5Elements){ + + Element.Properties.html.set = (function(set){ + + var translations = { + table: [1, '', '
'], + select: [1, ''], + tbody: [2, '', '
'], + tr: [3, '', '
'] + }; + + translations.thead = translations.tfoot = translations.tbody; + + return function(html){ + var wrap = translations[this.get('tag')]; + if (!wrap && !supportsHTML5Elements) wrap = [0, '', '']; + if (!wrap) return set.call(this, html); + + var level = wrap[0], wrapper = document.createElement('div'), target = wrapper; + if (!supportsHTML5Elements) fragment.appendChild(wrapper); + wrapper.innerHTML = [wrap[1], html, wrap[2]].flatten().join(''); + while (level--) target = target.firstChild; + this.empty().adopt(target.childNodes); + if (!supportsHTML5Elements) fragment.removeChild(wrapper); + wrapper = null; + }; + + })(Element.Properties.html.set); +} +/*
*/ /**/ var testForm = document.createElement('form'); @@ -3454,11 +3534,11 @@ if (testForm.firstChild.value != 's') Element.Properties.value = { } }; +testForm = null; /**/ /**/ -var el = document.createElement('div'); -if (el.getAttributeNode('id')) Element.Properties.id = { +if (document.createElement('div').getAttributeNode('id')) Element.Properties.id = { set: function(id){ this.id = this.getAttributeNode('id').value = id; }, @@ -3494,6 +3574,15 @@ provides: Element.Style var html = document.html; +// +// Check for oldIE, which does not remove styles when they're set to null +var el = document.createElement('div'); +el.style.color = 'red'; +el.style.color = null; +var doesNotRemoveStyles = el.style.color == 'red'; +el = null; +// + Element.Properties.styles = {set: function(styles){ this.setStyles(styles); }}; @@ -3504,17 +3593,19 @@ var hasOpacity = (html.style.opacity != null), var setVisibility = function(element, opacity){ element.store('$opacity', opacity); - element.style.visibility = opacity > 0 ? 'visible' : 'hidden'; + element.style.visibility = opacity > 0 || opacity == null ? 'visible' : 'hidden'; }; var setOpacity = (hasOpacity ? function(element, opacity){ element.style.opacity = opacity; } : (hasFilter ? function(element, opacity){ - if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1; - opacity = (opacity * 100).limit(0, 100).round(); - opacity = (opacity == 100) ? '' : 'alpha(opacity=' + opacity + ')'; - var filter = element.style.filter || element.getComputedStyle('filter') || ''; - element.style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity; + var style = element.style; + if (!element.currentStyle || !element.currentStyle.hasLayout) style.zoom = 1; + if (opacity == null || opacity == 1) opacity = ''; + else opacity = 'alpha(opacity=' + (opacity * 100).limit(0, 100).round() + ')'; + var filter = style.filter || element.getComputedStyle('filter') || ''; + style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity; + if (!style.filter) style.removeAttribute('filter'); } : setVisibility)); var getOpacity = (hasOpacity ? function(element){ @@ -3544,7 +3635,8 @@ Element.implement({ setStyle: function(property, value){ if (property == 'opacity'){ - setOpacity(this, parseFloat(value)); + if (value != null) value = parseFloat(value); + setOpacity(this, value); return this; } property = (property == 'float' ? floatName : property).camelCase(); @@ -3558,6 +3650,11 @@ Element.implement({ value = Math.round(value); } this.style[property] = value; + // + if ((value == '' || value == null) && doesNotRemoveStyles && this.style.removeAttribute){ + this.style.removeAttribute(property); + } + // return this; }, @@ -3579,16 +3676,17 @@ Element.implement({ var color = result.match(/rgba?\([\d\s,]+\)/); if (color) result = result.replace(color[0], color[0].rgbToHex()); } - if (Browser.opera || (Browser.ie && isNaN(parseFloat(result)))){ - if ((/^(height|width)$/).test(property)){ + if (Browser.opera || Browser.ie){ + if ((/^(height|width)$/).test(property) && !(/px$/.test(result))){ var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0; values.each(function(value){ size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt(); }, this); return this['offset' + property.capitalize()] - size + 'px'; } - if (Browser.opera && String(result).indexOf('px') != -1) return result; - if ((/^border(.+)Width|margin|padding/).test(property)) return '0px'; + if (Browser.ie && (/^border(.+)Width|margin|padding/).test(property) && isNaN(parseFloat(result))){ + return '0px'; + } } return result; }, @@ -3940,7 +4038,7 @@ if (!window.addEventListener){ return (this.get('tag') == 'input' && (type == 'radio' || type == 'checkbox')) ? 'propertychange' : 'change' }, condition: function(event){ - return !!(this.type != 'radio' || this.checked); + return this.type != 'radio' || (event.event.propertyName == 'checked' && this.checked); } } } @@ -4641,12 +4739,31 @@ Fx.CSS = new Class({ prepare: function(element, property, values){ values = Array.from(values); - if (values[1] == null){ - values[1] = values[0]; - values[0] = element.getStyle(property); + var from = values[0], to = values[1]; + if (to == null){ + to = from; + from = element.getStyle(property); + var unit = this.options.unit; + // adapted from: https://github.com/ryanmorr/fx/blob/master/fx.js#L299 + if (unit && from.slice(-unit.length) != unit && parseFloat(from) != 0){ + element.setStyle(property, to + unit); + var value = element.getComputedStyle(property); + // IE and Opera support pixelLeft or pixelWidth + if (!(/px$/.test(value))){ + value = element.style[('pixel-' + property).camelCase()]; + if (value == null){ + // adapted from Dean Edwards' http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + var left = element.style.left; + element.style.left = to + unit; + value = element.style.pixelLeft; + element.style.left = left; + } + } + from = (to || 1) / (parseFloat(value) || 1) * (parseFloat(from) || 0); + element.setStyle(property, from + unit); + } } - var parsed = values.map(this.parse); - return {from: parsed[0], to: parsed[1]}; + return {from: this.parse(from), to: this.parse(to)}; }, //parses a value into an array @@ -4834,24 +4951,25 @@ Element.implement({ }, fade: function(how){ - var fade = this.get('tween'), method, to, toggle; - if (how == null) how = 'toggle'; - switch (how){ - case 'in': method = 'start'; to = 1; break; - case 'out': method = 'start'; to = 0; break; - case 'show': method = 'set'; to = 1; break; - case 'hide': method = 'set'; to = 0; break; + var fade = this.get('tween'), method, args = ['opacity'].append(arguments), toggle; + if (args[1] == null) args[1] = 'toggle'; + switch (args[1]){ + case 'in': method = 'start'; args[1] = 1; break; + case 'out': method = 'start'; args[1] = 0; break; + case 'show': method = 'set'; args[1] = 1; break; + case 'hide': method = 'set'; args[1] = 0; break; case 'toggle': var flag = this.retrieve('fade:flag', this.getStyle('opacity') == 1); method = 'start'; - to = flag ? 0 : 1; + args[1] = flag ? 0 : 1; this.store('fade:flag', !flag); toggle = true; break; - default: method = 'start'; to = how; + default: method = 'start'; } if (!toggle) this.eliminate('fade:flag'); - fade[method]('opacity', to); + fade[method].apply(fade, args); + var to = args[args.length - 1]; if (method == 'set' || to != 0) this.setStyle('visibility', to == 0 ? 'hidden' : 'visible'); else fade.chain(function(){ this.element.setStyle('visibility', 'hidden'); diff --git a/couchpotato/static/scripts/library/prefix_free.js b/couchpotato/static/scripts/library/prefix_free.js index 96ed40e4..1ca634ee 100644 --- a/couchpotato/static/scripts/library/prefix_free.js +++ b/couchpotato/static/scripts/library/prefix_free.js @@ -1,2 +1,419 @@ -// StyleFix 1.0.1 & PrefixFree 1.0.4 / by Lea Verou / MIT license -(function(){function b(a,b){return[].slice.call((b||document).querySelectorAll(a))}if(!window.addEventListener)return;var a=window.StyleFix={link:function(b){try{if(b.rel!=="stylesheet"||!b.sheet.cssRules||b.hasAttribute("data-noprefix"))return}catch(c){return}var d=b.href||b.getAttribute("data-href"),e=d.replace(/[^\/]+$/,""),f=b.parentNode,g=new XMLHttpRequest;g.open("GET",d),g.onreadystatechange=function(){if(g.readyState===4){var c=g.responseText;if(c&&b.parentNode){c=a.fix(c,!0,b),e&&(c=c.replace(/url\((?:'|")?(.+?)(?:'|")?\)/gi,function(a,b){return/^([a-z]{3,10}:|\/|#)/i.test(b)?a:'url("'+e+b+'")'}),c=c.replace(RegExp("\\b(behavior:\\s*?url\\('?\"?)"+e,"gi"),"$1"));var d=document.createElement("style");d.textContent=c,d.media=b.media,d.disabled=b.disabled,d.setAttribute("data-href",b.getAttribute("href")),f.insertBefore(d,b),f.removeChild(b)}}},g.send(null),b.setAttribute("data-inprogress","")},styleElement:function(b){var c=b.disabled;b.textContent=a.fix(b.textContent,!0,b),b.disabled=c},styleAttribute:function(b){var c=b.getAttribute("style");c=a.fix(c,!1,b),b.setAttribute("style",c)},process:function(){b('link[rel="stylesheet"]:not([data-inprogress])').forEach(StyleFix.link),b("style").forEach(StyleFix.styleElement),b("[style]").forEach(StyleFix.styleAttribute)},register:function(b,c){(a.fixers=a.fixers||[]).splice(c===undefined?a.fixers.length:c,0,b)},fix:function(b,c){for(var d=0;d3){d.pop();var f=d.join("-");h(f)&&b.indexOf(f)===-1&&b.push(f)}}},h=function(a){return StyleFix.camelCase(a)in f};if(e.length>0)for(var i=0;i 3) { + parts.pop(); + + var shorthand = parts.join('-'); + + if(supported(shorthand) && properties.indexOf(shorthand) === -1) { + properties.push(shorthand); + } + } + } + }, + supported = function(property) { + return StyleFix.camelCase(property) in dummy; + } + + // Some browsers have numerical indices for the properties, some don't + if(style.length > 0) { + for(var i=0; i", - - // The URL to get the template from *instead* of the string - templateUrl: "", - - // A node reference for where this UI widget will be placed...in reference to - element: null, - - // Should this widget be parsed for sub-widgets? - widgetsInTemplate: true, - - // Property mappings (should be an object) - // These override defaults - propertyMappings: null, - - // Default property mappings - // Thse properties on the element will be moved to the respective nodes within the template - defaultPropertyMappings: null, - - // Should messages be debug to the console - debugMode: true - }, - - // Create placeholders for attached points and events - _attachPoints: [], - _attachEvents: [], - - // Parse - parse: function() { - - // Get shortcuts to the options and element - var options = this.options, - nodeRef = options.element = options.element || new Element("div").inject(document.body); - - // *IF* a templateUrl is specified, can't do anything until template is loaded - // Defer parsing until we've got it - if(options.templateUrl && Templated.templates && !Templated.templates[options.templateUrl]) { - this.debug("[Templated:parse] Need to load template from URL: " + options.templateUrl); - this.getTemplate(); - return false; - } - - // If already data-widgetized...gtfo - if(nodeRef.retrieve("widget")) { - this.debug("[Templated:parse] Node already widgetized, leaving ", nodeRef); - return nodeRef.domNode; - } - - // Mix noderef properties with options - options.defaultPropertyMappings = options.defaultPropertyMappings || { // THESE OVERRIDE CLASSES IN THE TEMPLATE!!!! - "id": "domNode", - "style": "domNode", - "class": "domNode" - }; - Object.merge(options, this.getNodeProps(nodeRef)); - - // postMixInProperties runs after options have been mixed with defaults but before - // any templating is done - this.postMixInProperties(); - - // Build rendering - creates the actual nodes, attachpoints, and attachevents - this.buildRendering(); - - // Fire the "postCreate" method, which runs after nodes are created *but* before the nodes are rendered to the page - this.postCreate(); - - // Cleanup creation - this.cleanupCreation(); - - // "Startup": The widget is in the DOM and the widget is ready to go - this.startup(); - - // Return the domNode - this.debug("[Templated:parse] At the end of parse, this is: ", this); - return this.domNode; - }, - - // Creates build rendering - buildRendering: function() { - // Get shortcuts to the options and element - var options = this.options, nodeRef = options.element; - - // Do string substitution on the template - var template = this.template = options.template.substitute(options || {}); - - // Create the DOM node within a DIV that's not rendered to the page - var bitchNode = this.bitchNode = new Element("div", { html: template.trim() }), - domNode = this.domNode = document.id(bitchNode.childNodes[0]); - - // Look for subwidgets if told to... - if(options.widgetsInTemplate) { - this.debug("[Templated:parse] Looking for subwidgets under domNode", domNode); - this.makeSubWidgets(this.domNode); - } - - // Create the attachpoints for me, then my kiddies - this.makeAttachPoints(domNode); - if(options.widgetsInTemplate) domNode.getElements("[" + dataWidgetAttachPoint + "]").each(this.makeAttachPoints, this); - this.debug("[Templated:parse] Creating attachpoints", this._attachPoints); - - // Create the attachevents for me, then my kiddies - this.makeAttachEvents(domNode); - if(options.widgetsInTemplate) domNode.getElements("[" + dataWidgetAttachEvent + "]").each(this.makeAttachEvents, this); - this.debug("Creating attachevents", this._attachEvents); - - // Map properties to nodes within the template - // Mix the custom mappings with the default - // This needs to happen after attachpoints - var mappings = options.propertyMappings ? Object.merge(options.defaultPropertyMappings, options.propertyMappings) : options.defaultPropertyMappings; - Object.each(mappings, function(value, key) { - // Ignore the value if not present in the object - if(!this[value]) return; - // Assign the value to the key - var currentProp = nodeRef.get(key); - if(currentProp != "") this[value].set(key, currentProp); - }.bind(this)); - - // If this widget has a "containerNode", grab it's childNodes *or* inject innerHTML - if(this.containerNode) { - var kids = nodeRef.childNodes; - kids.length ? $$(kids).inject(this.containerNode) : this.containerNode.set("html", nodeRef.get("html")); - } - }, - - // "postMixInProperties" -- Fired after options have been mixed in - postMixInProperties: function() { - this.debug("[Templated:postMixInProperties] postMixInProperties!"); - }, - - // "PostCreate" -- Fired after nodes are created, attachpoints and events are found - postCreate: function() { - this.debug("[Templated:postCreate] postCreate!"); - }, - - // "CleanupCreation" -- Removes the old element, destroys bitch node - cleanupCreation: function() { - // Get hold of the dom node and bitch nodes - var domNode = this.domNode, bitchNode = this.bitchNode, nodeRef = this.options.element; - - // Put the domNode where it should go and destroy the node reference - domNode.replaces(nodeRef); - nodeRef.destroy(); - - // Mark as data-widgetized and store the widget within data - domNode.set(dataWidgetized, true); - domNode.store("widget", this); - - // Remove the bitch node - bitchNode.destroy(); - }, - - // "StartUp" -- Fired when node is in place - startup: function(){ - this.debug("[Templated:startup] startup!"); - }, - - // Focus on focus node, if present - focus: function() { - var node = this.focusNode; - node && node.focus(); - }, - - // Create subwidgets from this - makeSubWidgets: function(domNode) { - if(!domNode) domNode = this.domNode; - domNode.getElements("["+ dataWidgetType +"]:not([" + dataWidgetized + "])").each(function(node){ - // Store the subwidget's attachpoints, attachevents, class type, and properties - var points = node.get(dataWidgetAttachPoint), - events = node.get(dataWidgetAttachEvent), - widgetProps = this.getNodeProps(node), - klass = node.get(dataWidgetType).trim(); - - // Create the widget - if(scope[klass]) { - var widget = new scope[klass](Object.merge(widgetProps, { element: node })); - this.debug("[parse:makeSubWidgets] Creating child widget: ", klass, widget); - // Get access to its dom node - widgetDomNode = widget.domNode; - // Add attachments back to the widget - points && widgetDomNode.set(dataWidgetAttachPoint, points.trim()); - events && widgetDomNode.set(dataWidgetAttachEvent, events.trim()); - } - }, this); - }, - - // Makes attachpoints - makeAttachPoints: function(node) { - var points = node.get(dataWidgetAttachPoint); - if(points) { - points.trim().split(",").each(function(attach) { - attach = attach.trim(); - this[attach] = node.retrieve("widget") || node; - this.debug("[Templated:makeAttachPoints] " + attach, node); - this._attachPoints.push({ node: node, name: attach }); - }, this); - node.set(dataWidgetAttachPoint, ""); - node.set("data-widgetized-attach-point", points); - } - }, - - // Makes attachevents - makeAttachEvents: function(node) { - // Temporarily store this widget's events so they may be added to this.domNode later - var events = node.get(dataWidgetAttachEvent); - // If there are events.... - if(events) { - // For every event found.... - events.trim().split(",").each(function(event) { - // Trim the event - event = event.trim(); - // Split the event:method pair - var eventFn = event.split(":"); - // Trim and rename each piece - var nativeEvent = eventFn[0].trim(), - classEvent = eventFn[1].trim(); - this.debug("[Templated:makeAttachEvents] " + nativeEvent + " / " + classEvent,node); - - // If the method isn't found on this, create a stub for it' - if(!this[classEvent]) { - this.debug("cant find ", classEvent, " in: ", this, " creating sub for it"); - this[classEvent] = function(){}; - } - - // Bind "this" to the event - var ev = this[classEvent].bind(this); - - // Add the event to the domNode - node.addEvent(nativeEvent, ev); - - // Store the event - this._attachEvents.push({ type: nativeEvent, event: ev, node: node }); - }, this); - - // Remove the event from its former place and add to -ized data item - var set = { - "data-widgetized-attach-event": events - }; - set[dataWidgetAttachEvent] = ""; - node.set(set); - //node.set("data-widget-attach-event",""); - //node.set("data-widgetized-attach-event",events); - } - }, - - // Destroy: removes node events - destroy: function() { - // Get reference to domNode - var domNode = this.domNode, events = this._attachEvents, points = this._attachPoints; - - // Clear out children - domNode.getElements("[" + dataWidgetized + "]").each(function(widget) { - widget.destroy(); - }); - - // Remove events - if(events.length) { - events.each(function(event) { - if(event.node) event.node.removeEvents(); - }); - } - // Remove node connections - if(points.length) { - points.each(function(point) { - if(point.name != "domNode") this[point.name] = null; - }, this); - } - // Destroy the dom node and its children, fin - domNode.store("widget", null).destroy(); - }, - - // Gets the in-node properties for a widget - getNodeProps: function(node) { - var props = node.get(dataWidgetProps), - widgetProps = {}; - // Create the widget - if(props) { - // Not using JSON.parse because it's too restricting, especially with quotes - var json = "{" + props.trim() + "}"; - if(JSON && JSON.decode) { // MooTools - widgetProps = JSON.decode(json); - } - else { // Native - eval("widgetProps = " + json); - } - } - return widgetProps; - }, - - debug: function(one, two, three, four) { - if(this.options.debugMode && console && console.log) { - console.log("[" + (this.domNode ? this.domNode.id : "") + "] ", one, two || "", three || "", four || ""); - } - } - }); - - // If Request is available.... - if(Request) { - Templated.templates = {}; - // Return the template - Templated.implement({ - // Method to return cached template or retrieve new one synchronously - getTemplate: function() { - /* - var url = this.options.templateUrl; - // Try to return cached first - if(Templated.templates[url]) { - return Templated.templates[url]; - } - else { - // Send a new request - return new Request({ - url: url, - async: false, // Used to ensure that necessary templates are there - onSuccess: function(template) { - this.options.template = template; - Templated.templates[url] = template; - this.parse(); - }.bind(this) - }).send(); - } - */ - - var url = this.options.templateUrl; - // Try to return cached first - if(!Templated.templates[url]) { - // Send a new request - return new Request({ - url: url, - async: false, // Used to ensure that necessary templates are there - onSuccess: function(template) { - this.options.template = template; - Templated.templates[url] = template; - this.parse(); - }.bind(this), - onFailure: function() { - Templated.templates[url] = Templated.prototype.options.template; - } - }).send(); - } - return Templated.templates[url]; - } - }); - } - - // Allow for parsing of an element and its children - Element.implement({ - parse: function() { - - var elFn = function(element) { - // Get the widget type - var klass = element.get(dataWidgetType); - // If the class exists.... - if(klass && scope[klass]) { - // Create the new class instance - new scope[klass]({ element: element }); - } - else { - window.console && console.log && console.log("klass does not exist! ", klass); - } - }; - - // Grab this and all nodes which are not already widgetized - elFn(this); - $$(this.getElements("["+ dataWidgetType +"]:not(" + dataWidgetized + ")")).each(elFn); - } - }); - - // Get widget from id - document.widget = function(idOrNode) { - return document.id(idOrNode).retrieve("widget") || null; - }; - - -})(this); // Scope limiter \ No newline at end of file diff --git a/couchpotato/templates/_desktop.html b/couchpotato/templates/_desktop.html index 7ec3fd95..0f6ab5b6 100644 --- a/couchpotato/templates/_desktop.html +++ b/couchpotato/templates/_desktop.html @@ -13,7 +13,6 @@ {% if not env.get('dev') %} {% endif %} -