Advertisement
P0lip

bragi

Nov 21st, 2014
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2. /**
  3.  *    Copyright 2014 Opera Software ASA
  4.  *
  5.  *    Licensed under the Apache License, Version 2.0 (the "License");
  6.  *    you may not use this file except in compliance with the License.
  7.  *    You may obtain a copy of the License at
  8.  *
  9.  *        http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  *    Unless required by applicable law or agreed to in writing, software
  12.  *    distributed under the License is distributed on an "AS IS" BASIS,
  13.  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  *    See the License for the specific language governing permissions and
  15.  *    limitations under the License.
  16.  *
  17.  **/
  18. Element.prototype.matchesSelector || (Element.prototype.matchesSelector = Element.prototype.webkitMatchesSelector || function(selector) { // what about other vendor prefixes, is it meant to run only on Webkit? ;)
  19.   if(this.parentNode) {
  20.     var sel = this.parentNode.querySelectorAll(selector);
  21.     var i = 0;
  22.     while (sel[++i] !== this);
  23.       return !!sel[i];
  24.   }
  25. });
  26.  
  27. (function() {
  28.   'use strict';
  29.  
  30.   this.createTemplate = function() {
  31.     // A special element name. We don't create an element for a template that
  32.     // starts with this element but instead merge it with its parent context.
  33.     var TEXT_NODE_NAME = '#text';
  34.     var ObjToString = Object.prototype.toString;
  35.     var ATTRS = 1;
  36.     return function(tmpl){
  37.       var ele = null;
  38.       var elementName = tmpl[0];
  39.       var i = 0;
  40.       var attrs = null;
  41.       if (typeof elementName === 'string' && elementName !== TEXT_NODE_NAME) {
  42.         i++;
  43.         ele = document.createElement(elementName);
  44.         if (ObjToString.call(tmpl[ATTRS]) === '[object Object]') {
  45.           i++;
  46.           if (attrs = tmpl[ATTRS]) {
  47.             for (var prop in attrs) {
  48.               if (typeof attrs[prop] === 'string') {
  49.                 ele.setAttribute(prop, attrs[prop]);
  50.               }
  51.             }
  52.           }
  53.         }
  54.       } else {
  55.         if (elementName === TEXT_NODE_NAME) {
  56.           i++;
  57.         }
  58.         ele = document.createDocumentFragment();
  59.       }
  60.       for (var len = tmpl.length; i < len; i++) {
  61.         if (typeof tmpl[i] === 'string') {
  62.           ele.appendChild(document.createTextNode(tmpl[i]));
  63.         } else if (tmpl[i]) {
  64.           ele.appendChild(window.bragi.createTemplate(tmpl[i]));
  65.         }
  66.       }
  67.       return ele;
  68.     };
  69.   }();
  70.  
  71.   /**
  72.    * Creates a template array from the localized string which contains
  73.    * placeholders, replacing placeholders with templates specified in the
  74.    * replacementMap.
  75.    *
  76.    * @param  {String} string The localized string to process.
  77.    * @param  {Object} replacementMap The map with templates specified for each
  78.    *         placeholder. First placeholder in the string is marked with a '$1'.
  79.    * @return {Array} The resulting template.
  80.    */
  81.   this.createTemplateFromStringF = function(stringToProcess, replacementMap) {
  82.     var result = ['#text'];
  83.     var $number = /\$[$1-9]/;
  84.     var matchPlaceholder;
  85.     while (matchPlaceholder = $number.exec(stringToProcess)) {
  86.       var placeholder = matchPlaceholder[0];
  87.       var placeholderPosition = matchPlaceholder.index;
  88.       var currentStringSlice = stringToProcess.substr(0, placeholderPosition);
  89.       // Save remaining for the next iteration.
  90.       stringToProcess = stringToProcess.slice(placeholderPosition + placeholder.length);
  91.  
  92.       if (placeholder == '$$') {
  93.         currentStringSlice += '$';
  94.       } else if (placeholder != '$$') {
  95.         var placeholderTemplate = replacementMap[placeholder];
  96.         result.push(placeholderTemplate);
  97.       }
  98.       if (currentStringSlice !== '') {
  99.         result.push(currentStringSlice);
  100.       }
  101.       if (stringToProcess !== '') {
  102.         result.push(stringToProcess);
  103.       }
  104.  
  105.       return result;
  106.     }
  107.   };
  108.   window.EventHandler = function(type, isCapturing, handlerKey) {
  109.     return this.init_(type, isCapturing, handlerKey);
  110.   };
  111.  
  112.   Element.prototype.appendTemplate = function(tmpl) {
  113.     return this.appendChild(window.bragi.createTemplate(tmpl));
  114.   };
  115.  
  116.   Element.prototype.cleanAppendTemplate = function(tmpl) {
  117.     this.textContent = '';
  118.     return this.appendTemplate(tmpl);
  119.   };
  120.  
  121.   Element.prototype.replaceWithTemplate = function() {
  122.     var slice = Array.prototype.slice;
  123.     return function(tmpl){
  124.       var parent = this.parentNode;
  125.       if (parent) {
  126.         var documentFragment = document.createDocumentFragment();
  127.         documentFragment.appendTemplate(tmpl);
  128.         var ret = slice.call(documentFragment.childNodes);
  129.         parent.replaceChild(documentFragment, this);
  130.         return ret;
  131.       }
  132.       return null;
  133.     };
  134.   }();
  135.  
  136.   Element.prototype.getAncestor = function(selector) {
  137.     var ele = this;
  138.     while (ele) {
  139.       if (ele.matchesSelector(selector)) {
  140.         return ele;
  141.       }
  142.       ele = ele.parentElement;
  143.     }
  144.     return null;
  145.   };
  146.  
  147.   Element.prototype.getAncestorAttr = function(name) {
  148.     var ele = this;
  149.     while (ele && !ele.hasAttribute(name)) {
  150.       ele = ele.parentElement;
  151.     }
  152.     return ele && ele.hasAttribute(name) ? ele.getAttribute(name) : null;
  153.   };
  154.  
  155.   var handlers_ = Object.create ? {'true': Object.create(null), 'false': Object.create(null)} : {'true': [], 'false': []};
  156.   var handler_ = function(handler_map, event) {
  157.     var ele = event.target;
  158.     while (ele && !event.cancelBubble) {
  159.       var name = ele.getAttribute('data-handler');
  160.       if (name && handler_map[name])
  161.         handler_map[name](event, ele);
  162.       ele = ele.parentElement;
  163.     }
  164.   };
  165.   function EventHandler(){}
  166.   EventHandler.prototype.init_ = function(type, isCapturing) {
  167.     isCapturing = !!isCapturing;
  168.     if (handlers_[isCapturing][type]) {
  169.       return handlers_[isCapturing][type];
  170.     }
  171.     var handler_map = handlers_[isCapturing][type] = Object.create ? Object.create(null) : {};
  172.     var handler = handler_.bind(this, handler_map);
  173.     document.addEventListener(type, handler, isCapturing);
  174.     return handler_map;
  175.   };
  176.   EventHandler.register = function(type, name, handler, isCapturing) {
  177.     isCapturing = !!isCapturing;
  178.     (handlers_[isCapturing][type] || new EventHandler(type, isCapturing))[name] = handler;
  179.   };
  180.   EventHandler.unregister = function(type, name, handler, isCapturing) {
  181.     var handler_map = handlers_[!!isCapturing][type];
  182.     if (handler_map && handler_map[name] === handler)
  183.       handler_map[name] = null;
  184.   };
  185.  
  186. }).call(window.bragi || (window.bragi = {}));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement