<commit_before>define(function() {

  var Ceci = function (element, def) {

    Object.keys(def).filter(function (item) {
      return Ceci._reserved.indexOf(item) === -1;
    }).forEach(function (key) {
      var entry = def[key];
      if (typeof entry === 'function') {
        element[key] = function() {
          entry.apply(element, arguments);
        }
      }
    });

    element.defaultListener = def.defaultListener;

    element.subscriptionListeners = [];

    if(def.listeners) {
      Object.keys(def.listeners).forEach(function (key) {
        var entry = def.listeners[key];
        var entryType = typeof entry;

        if (entryType === 'function') {
          element[key] = function() {
            entry.apply(element, arguments);
          };
          element.subscriptionListeners.push(key);
        }
        else {
          throw "Listener \"" + key + "\" is not a function.";
        }
      });
    }

    element.emit = function (data) {
      if(element.broadcastChannel === Ceci._emptyChannel) return;
      var e = new CustomEvent(element.broadcastChannel, {bubbles: true, detail: data});
      element.dispatchEvent(e);
      console.log(element.id + " -> " + element.broadcastChannel);
    };

    // init must always be a function, even if it does nothing
    element.init = function () {};
    if(def.init) {
      element.init = function() {
        def.init.apply(element, arguments);
      };
    }

    // pass along the broadcast property
    element.broadcast = def.broadcast;

    // allow for event cleanup when removing an element from the DOM
    element._flatheadListeners = [];

    // add an event listener and record it got added by this element
    element.setupEventListener = function(item, event, fn) {
      item.addEventListener(event, fn);
      element._flatheadListeners.push({
        item: item,
        event: event,
        fn: fn
      });
    };

    // remove a specific event listener associated with this element
    element.discardEventListener = function(item, event, fn) {
      var listeners = element._flatheadListeners;
      for(var i=listeners.length-1, e; i>=0; i--) {
        e = listeners[i]
        if (e.item === item && e.event === event && e.fn === fn) {
          item.removeEventListener(event, fn);
          listeners.splice(i,1);
          return;
        }
      }
    };

    // remove this element from the DOM, after cleaning up all
    // outstanding event listeners
    element.removeSafely = function() {
      element._flatheadListeners.forEach(function(e) {
        e.item.removeEventListener(e.event, e.fn);
      });
      element._flatheadListeners = [];
      if (element.parentNode) {
        element.parentNode.removeChild(element);
      }
    }

    // run any plugins that hook into the constructor
    Ceci._plugins.constructor.forEach(function(plugin) {
      plugin(element, def);
    });
  }

  Ceci._reserved = ['init', 'listeners', 'defaultListener'];

  Ceci.reserveKeyword = function(keyword) {
    Ceci._reserved.push(keyword);
  }

  Ceci._plugins = {
    constructor: []
  }

  Ceci.registerCeciPlugin = function(eventName, plugin) {
    Ceci._plugins[eventName].push(plugin);
  }

  Ceci._defaultBroadcastChannel = "blue";
  Ceci._defaultListeningChannel = "blue";
  Ceci._emptyChannel = "false";

  Ceci._components = {};

  // this function is only called once, when an element is instantiated.
  function getBroadcastChannel(element, original) {
    // get <broadcast> element information
    var broadcast = original.getElementsByTagName('broadcast')[0];
    if (broadcast){
      var channel = broadcast.getAttribute("on");
      if (channel) {
        return channel;
      }
    }
    // if no broadcast channel is specified, but this is a broadcast
    // element, use the default channel. Otherwise, don't broadcast
    return (element.broadcast ? Ceci._defaultBroadcastChannel : Ceci._emptyChannel);
  }

  // this function is only called once, when an element is instantiated.
  function getSubscriptions(element, original) {
    var subscriptions = original.getElementsByTagName('listen');
    subscriptions = Array.prototype.slice.call(subscriptions);

    if(subscriptions.length === 0) {
      if(!element.defaultListener) {
        return [];
      }
      return [{
        listener: element.defaultListener,
        channel: Ceci._defaultListeningChannel
      }];
    }

    subscriptions = subscriptions.map(function (e) {
      var channel = e.getAttribute("on");
      var listener = e.getAttribute("for");

      return {
        listener: listener,
        channel: channel
      };
    });

    return subscriptions;
  }

  function setupBroadcastLogic(element, original) {
    // get <broadcast> rules from the original declaration
    element.broadcastChannel = getBroadcastChannel(element, original);
    if(element.onBroadcastChannelChanged) {
      element.onBroadcastChannelChanged(element.broadcastChannel);
    }
    // set property on actual on-page element
    element.setBroadcastChannel = function(channel) {
      element.broadcastChannel = channel;
      if(element.onBroadcastChannelChanged) {
        element.onBroadcastChannelChanged(channel);
      }
    };
  }

  function setupSubscriptionLogic(element, original) {
    // get <listen> rules from the original declaration
    element.subscriptions = getSubscriptions(element, original);
    if(element.onSubscriptionChannelChanged) {
      element.subscriptions.forEach(function(s){
        element.onSubscriptionChannelChanged(s.channel, s.listener);
      });
    }
    var generateListener = function(element, channel, listener) {
      return function(e) {
        if(e.target.id !== element.id) {
          console.log(element.id + " <- " + channel + "/" + listener);
          element[listener](e.detail, channel);
        }
      }
    }
    // set properties on actual on-page element
    element.setSubscription = function(channel, listener) {
      var append = true, fn;
      element.subscriptions.forEach(function(s) {
        if(s.listener === listener) {
          // remove the old event listening
          fn = element[listener].listeningFunction;
          if(fn) {
            console.log("removing "+s.channel+"/"+listener+" pair");
            element.discardEventListener(document, s.channel, fn);
          }
          // update the channel
          s.channel = channel;
          // bind the new event listening
          if(channel !== Ceci._emptyChannel) {
            fn = generateListener(element, s.channel, s.listener);
            console.log("adding "+s.channel+"/"+listener+" pair");
            element.setupEventListener(document, s.channel, fn);
          } else {
            fn = false;
          }
          element[listener].listeningFunction = fn;
          append = false;
        }
      });
      if(append) {
        fn = generateListener(element, channel, listener);
        element[listener].listeningFunction = fn;
        console.log("adding "+channel+"/"+listener+" pair");
        element.setupEventListener(document, channel, fn);
        element.subscriptions.push({
          listener: listener,
          channel: channel
        });
      }
      if(element.onSubscriptionChannelChanged) {
        element.onSubscriptionChannelChanged(channel, listener);
      }
    };
    element.removeSubscription = function(channel, listener) {
      var filter = function(s) {
        return !(s.channel === channel && s.listener === listener);
      };
      // single arg: remove listener, regardless of its channel
      if(channel && !listener) {
        listener = channel;
        filter = function(s) {
          return (s.listener !== listener);
        };
      }
      e.subscriptions = e.subscriptions.filter(filter);
    };

    element.subscriptions.forEach(function (s) {
      var fn = generateListener(element, s.channel, s.listener);
      element[s.listener].listeningFunction = fn;
      element.setupEventListener(document, s.channel, fn);
    });

  }

  Ceci.convertElement = function (element, callback) {
    var def = Ceci._components[element.localName],
        original = element.cloneNode(true);

    // real content
    element._innerHTML = element.innerHTML;
    element._innerText = element.innerText;

    if (def.template){
      element.innerHTML = def.template.innerHTML;
    }

    if (def.description) {
      element.description = def.description;
    }

    var postConstructorHook = function() {
      postConstructorHook.called = true;
      setupBroadcastLogic(element, original);
      setupSubscriptionLogic(element, original);
      element.init();
      callback(element);
    };
    postConstructorHook.called = false;

    def.constructor.call(element, function() {
      postConstructorHook();
    });

    if (typeof element.init === 'function') {
      if(!postConstructorHook.called) {
        postConstructorHook();
      }
    }
  };

  Ceci.processComponent = function (element) {
    var name = element.getAttribute('name');
    var template = element.querySelector('template');
    var script = element.querySelector('script[type="text/ceci"]');
    var description = element.querySelector('description');

    var generator = null;

    try{
      generator = new Function("Ceci", "return function(callback) {" + script.innerHTML+ "}");
    }
    catch(e){
      if (e.name === 'SyntaxError') {
        e.message += " in definition of component \"" + name + "\".";
        throw e;
      }
      else {
        throw e;
      }
    }
    var constructor = generator(Ceci);

    Ceci._components[name] = {
      template: template,
      constructor: constructor,
      description: description
    };

    var existingElements = document.querySelectorAll(name);
    Array.prototype.forEach.call(existingElements, function (existingElement) {
      Ceci.convertElement(existingElement);
    });
  };

  function scrape (callOnComplete) {
    var elements = document.querySelectorAll('element');
    elements = Array.prototype.slice.call(elements);
    elements.forEach(Ceci.processComponent);
    if (callOnComplete){
      callOnComplete(Ceci._components);
    }
  }

  Ceci.load = function (callOnComplete) {
    var ceciLinks = document.querySelectorAll('link[rel=component][type="text/ceci"]');

    if (ceciLinks.length) {
      var linksLeft = ceciLinks.length;
      Array.prototype.forEach.call(ceciLinks, function (componentLink) {
        var xhr = new XMLHttpRequest(),
            docURL = componentLink.getAttribute('href');
        xhr.open('GET', docURL ,true);
        xhr.onload = function (e) {
          var fragment = document.createElement('div');
          fragment.setAttribute("style","display:none!important");
          fragment.innerHTML = xhr.response;
          if (document.body.firstChild) {
            document.body.insertBefore(fragment, document.body.firstChild);
          }
          else {
            document.body.appendChild(fragment);
          }
          if (--linksLeft === 0) {
            scrape(callOnComplete);
          }
        };
        xhr.send(null);
      });
    }
    else {
      scrape(callOnComplete);
    }
  };

  return Ceci;
});
<commit_msg>Adding emptyChannel property to Ceci for the designer et all to reference.<commit_after>define(function() {

  var Ceci = function (element, def) {

    Object.keys(def).filter(function (item) {
      return Ceci._reserved.indexOf(item) === -1;
    }).forEach(function (key) {
      var entry = def[key];
      if (typeof entry === 'function') {
        element[key] = function() {
          entry.apply(element, arguments);
        }
      }
    });

    element.defaultListener = def.defaultListener;

    element.subscriptionListeners = [];

    if(def.listeners) {
      Object.keys(def.listeners).forEach(function (key) {
        var entry = def.listeners[key];
        var entryType = typeof entry;

        if (entryType === 'function') {
          element[key] = function() {
            entry.apply(element, arguments);
          };
          element.subscriptionListeners.push(key);
        }
        else {
          throw "Listener \"" + key + "\" is not a function.";
        }
      });
    }

    element.emit = function (data) {
      if(element.broadcastChannel === Ceci._emptyChannel) return;
      var e = new CustomEvent(element.broadcastChannel, {bubbles: true, detail: data});
      element.dispatchEvent(e);
      console.log(element.id + " -> " + element.broadcastChannel);
    };

    // init must always be a function, even if it does nothing
    element.init = function () {};
    if(def.init) {
      element.init = function() {
        def.init.apply(element, arguments);
      };
    }

    // pass along the broadcast property
    element.broadcast = def.broadcast;

    // allow for event cleanup when removing an element from the DOM
    element._flatheadListeners = [];

    // add an event listener and record it got added by this element
    element.setupEventListener = function(item, event, fn) {
      item.addEventListener(event, fn);
      element._flatheadListeners.push({
        item: item,
        event: event,
        fn: fn
      });
    };

    // remove a specific event listener associated with this element
    element.discardEventListener = function(item, event, fn) {
      var listeners = element._flatheadListeners;
      for(var i=listeners.length-1, e; i>=0; i--) {
        e = listeners[i]
        if (e.item === item && e.event === event && e.fn === fn) {
          item.removeEventListener(event, fn);
          listeners.splice(i,1);
          return;
        }
      }
    };

    // remove this element from the DOM, after cleaning up all
    // outstanding event listeners
    element.removeSafely = function() {
      element._flatheadListeners.forEach(function(e) {
        e.item.removeEventListener(e.event, e.fn);
      });
      element._flatheadListeners = [];
      if (element.parentNode) {
        element.parentNode.removeChild(element);
      }
    }

    // run any plugins that hook into the constructor
    Ceci._plugins.constructor.forEach(function(plugin) {
      plugin(element, def);
    });
  }

  Ceci._reserved = ['init', 'listeners', 'defaultListener'];

  Ceci.reserveKeyword = function(keyword) {
    Ceci._reserved.push(keyword);
  }

  Ceci._plugins = {
    constructor: []
  }

  Ceci.registerCeciPlugin = function(eventName, plugin) {
    Ceci._plugins[eventName].push(plugin);
  }

  Ceci._defaultBroadcastChannel = "blue";
  Ceci._defaultListeningChannel = "blue";
  Ceci._emptyChannel = "false";
  Object.defineProperty(Ceci, "emptyChannel", {
    enumerable: false,
    configurable: false,
    writable: false,
    value: Ceci._emptyChannel
  });

  Ceci._components = {};

  // this function is only called once, when an element is instantiated.
  function getBroadcastChannel(element, original) {
    // get <broadcast> element information
    var broadcast = original.getElementsByTagName('broadcast')[0];
    if (broadcast){
      var channel = broadcast.getAttribute("on");
      if (channel) {
        return channel;
      }
    }
    // if no broadcast channel is specified, but this is a broadcast
    // element, use the default channel. Otherwise, don't broadcast
    return (element.broadcast ? Ceci._defaultBroadcastChannel : Ceci._emptyChannel);
  }

  // this function is only called once, when an element is instantiated.
  function getSubscriptions(element, original) {
    var subscriptions = original.getElementsByTagName('listen');
    subscriptions = Array.prototype.slice.call(subscriptions);

    if(subscriptions.length === 0) {
      if(!element.defaultListener) {
        return [];
      }
      return [{
        listener: element.defaultListener,
        channel: Ceci._defaultListeningChannel
      }];
    }

    subscriptions = subscriptions.map(function (e) {
      var channel = e.getAttribute("on");
      var listener = e.getAttribute("for");

      return {
        listener: listener,
        channel: channel
      };
    });

    return subscriptions;
  }

  function setupBroadcastLogic(element, original) {
    // get <broadcast> rules from the original declaration
    element.broadcastChannel = getBroadcastChannel(element, original);
    if(element.onBroadcastChannelChanged) {
      element.onBroadcastChannelChanged(element.broadcastChannel);
    }
    // set property on actual on-page element
    element.setBroadcastChannel = function(channel) {
      element.broadcastChannel = channel;
      if(element.onBroadcastChannelChanged) {
        element.onBroadcastChannelChanged(channel);
      }
    };
  }

  function setupSubscriptionLogic(element, original) {
    // get <listen> rules from the original declaration
    element.subscriptions = getSubscriptions(element, original);
    if(element.onSubscriptionChannelChanged) {
      element.subscriptions.forEach(function(s){
        element.onSubscriptionChannelChanged(s.channel, s.listener);
      });
    }
    var generateListener = function(element, channel, listener) {
      return function(e) {
        if(e.target.id !== element.id) {
          console.log(element.id + " <- " + channel + "/" + listener);
          element[listener](e.detail, channel);
        }
      }
    }
    // set properties on actual on-page element
    element.setSubscription = function(channel, listener) {
      var append = true, fn;
      element.subscriptions.forEach(function(s) {
        if(s.listener === listener) {
          // remove the old event listening
          fn = element[listener].listeningFunction;
          if(fn) {
            console.log("removing "+s.channel+"/"+listener+" pair");
            element.discardEventListener(document, s.channel, fn);
          }
          // update the channel
          s.channel = channel;
          // bind the new event listening
          if(channel !== Ceci._emptyChannel) {
            fn = generateListener(element, s.channel, s.listener);
            console.log("adding "+s.channel+"/"+listener+" pair");
            element.setupEventListener(document, s.channel, fn);
          } else {
            fn = false;
          }
          element[listener].listeningFunction = fn;
          append = false;
        }
      });
      if(append) {
        fn = generateListener(element, channel, listener);
        element[listener].listeningFunction = fn;
        console.log("adding "+channel+"/"+listener+" pair");
        element.setupEventListener(document, channel, fn);
        element.subscriptions.push({
          listener: listener,
          channel: channel
        });
      }
      if(element.onSubscriptionChannelChanged) {
        element.onSubscriptionChannelChanged(channel, listener);
      }
    };
    element.removeSubscription = function(channel, listener) {
      var filter = function(s) {
        return !(s.channel === channel && s.listener === listener);
      };
      // single arg: remove listener, regardless of its channel
      if(channel && !listener) {
        listener = channel;
        filter = function(s) {
          return (s.listener !== listener);
        };
      }
      e.subscriptions = e.subscriptions.filter(filter);
    };

    element.subscriptions.forEach(function (s) {
      var fn = generateListener(element, s.channel, s.listener);
      element[s.listener].listeningFunction = fn;
      element.setupEventListener(document, s.channel, fn);
    });

  }

  Ceci.convertElement = function (element, callback) {
    var def = Ceci._components[element.localName],
        original = element.cloneNode(true);

    // real content
    element._innerHTML = element.innerHTML;
    element._innerText = element.innerText;

    if (def.template){
      element.innerHTML = def.template.innerHTML;
    }

    if (def.description) {
      element.description = def.description;
    }

    var postConstructorHook = function() {
      postConstructorHook.called = true;
      setupBroadcastLogic(element, original);
      setupSubscriptionLogic(element, original);
      element.init();
      callback(element);
    };
    postConstructorHook.called = false;

    def.constructor.call(element, function() {
      postConstructorHook();
    });

    if (typeof element.init === 'function') {
      if(!postConstructorHook.called) {
        postConstructorHook();
      }
    }
  };

  Ceci.processComponent = function (element) {
    var name = element.getAttribute('name');
    var template = element.querySelector('template');
    var script = element.querySelector('script[type="text/ceci"]');
    var description = element.querySelector('description');

    var generator = null;

    try{
      generator = new Function("Ceci", "return function(callback) {" + script.innerHTML+ "}");
    }
    catch(e){
      if (e.name === 'SyntaxError') {
        e.message += " in definition of component \"" + name + "\".";
        throw e;
      }
      else {
        throw e;
      }
    }
    var constructor = generator(Ceci);

    Ceci._components[name] = {
      template: template,
      constructor: constructor,
      description: description
    };

    var existingElements = document.querySelectorAll(name);
    Array.prototype.forEach.call(existingElements, function (existingElement) {
      Ceci.convertElement(existingElement);
    });
  };

  function scrape (callOnComplete) {
    var elements = document.querySelectorAll('element');
    elements = Array.prototype.slice.call(elements);
    elements.forEach(Ceci.processComponent);
    if (callOnComplete){
      callOnComplete(Ceci._components);
    }
  }

  Ceci.load = function (callOnComplete) {
    var ceciLinks = document.querySelectorAll('link[rel=component][type="text/ceci"]');

    if (ceciLinks.length) {
      var linksLeft = ceciLinks.length;
      Array.prototype.forEach.call(ceciLinks, function (componentLink) {
        var xhr = new XMLHttpRequest(),
            docURL = componentLink.getAttribute('href');
        xhr.open('GET', docURL ,true);
        xhr.onload = function (e) {
          var fragment = document.createElement('div');
          fragment.setAttribute("style","display:none!important");
          fragment.innerHTML = xhr.response;
          if (document.body.firstChild) {
            document.body.insertBefore(fragment, document.body.firstChild);
          }
          else {
            document.body.appendChild(fragment);
          }
          if (--linksLeft === 0) {
            scrape(callOnComplete);
          }
        };
        xhr.send(null);
      });
    }
    else {
      scrape(callOnComplete);
    }
  };

  return Ceci;
});
<|endoftext|>


<commit_before>define(function() {

  var getChannel = function(name) {
    return "flathead:" + name;
  }

  var Ceci = function (element, def) {

    Object.keys(def).filter(function (item) {
      return Ceci._reserved.indexOf(item) === -1;
    }).forEach(function (key) {
      var entry = def[key];
      if (typeof entry === 'function') {
        element[key] = entry;
      }
    });

    if (!def.defaultListener){
      def.defaultListener = Object.keys(def.listeners)[0];
    }

    element.subscriptionListeners = [];

    Object.keys(def.listeners).forEach(function (key) {
      var entry = def.listeners[key];
      var entryType = typeof entry;

      if (entryType === 'function') {
        element[key] = entry;
        element.subscriptionListeners.push(key);
      }
      else {
        throw "Listener \"" + key + "\" is not a function.";
      }
    });

    var defaultListener = def.defaultListener;
    if (!defaultListener){
      defaultListener = Object.keys(def.listeners)[0];
    }
    element.defaultListener = def.listeners[defaultListener];

    else {
      element.defaultListener = function(data){
        console.log("No default listener set");
      }
    }

    element.emit = function (data) {
      var e = new CustomEvent(getChannel(element.broadcastChannel), {bubbles: true, detail: data});
      element.dispatchEvent(e);
      // console.log(element.id + " -> " + element.broadcastChannel);
    };

    element.init = function() {
      if (def.init) {
        def.init.call(element);
      }
    };

    Ceci._plugins.constructor.forEach(function(plugin) {
      plugin(element, def);
    });
  }

  Ceci._reserved = ['init', 'listeners', 'defaultListener'];

  Ceci.reserveKeyword = function(keyword) {
    Ceci._reserved.push(keyword);
  }

  Ceci._plugins = {
    constructor: []
  }

  Ceci.registerCeciPlugin = function(eventName, plugin) {
    Ceci._plugins[eventName].push(plugin);
  }

  Ceci.defaultChannel = "blue";

  Ceci._components = {};

  function getBroadcastChannel(element) {
    var broadcast = element.getElementsByTagName('broadcast')[0];
    if (broadcast){
      var channel = broadcast.getAttribute("on");
      if (channel) {
        return channel;
      }
    }
    return Ceci.defaultChannel;
  }

  function getSubscriptions(element) {
    var subscriptions = element.getElementsByTagName('listen');
    subscriptions = Array.prototype.slice.call(subscriptions);

    if(subscriptions.length === 0) {
      return [{
        listener: 'defaultListener',
        channel: Ceci.defaultChannel
      }];
    }

    subscriptions = subscriptions.map(function (e) {
      var channel = e.getAttribute("on");
      var listener = e.getAttribute("for");

      return {
        listener: listener,
        channel: (channel ? channel : Ceci.defaultChannel)
      };
    });

    return subscriptions;
  }

  function setupBroadcastLogic(e) {
    console.log("binding "+(e.id || '[unknown id]')+" broadcast channel");
    e.broadcastChannel = getBroadcastChannel(e);
    e.setBroadcastChannel = function(channel) {
      e.broadcastChannel = channel;
    }
  }

  function setupSubscriptionLogic(e, defaultListener) {
    console.log("binding "+(e.id || '[unknown id]')+" subscription channels");
    e.subscriptions = getSubscriptions(e, defaultListener);
    e.setSubscription = function(channel, listener) {
      var append = true;
      e.subscriptions.forEach(function(s) {
        if(s.listener === listener) {
          s.channel = channel;
          append = false;
        }
      });
      if(append) {
        e.subscriptions.push({
          listener: listener,
          channel: channel
        });
      }
    };
    e.removeSubscription = function(channel, listener) {
      e.subscriptions = e.subscriptions.filter(function(s) {
        return !(s.channel === channel && s.listener === listener);
      })
    };
  }

  Ceci.convertElement = function (element) {
    var def = Ceci._components[element.localName];
    console.log(element);

    // channel logic
    setupBroadcastLogic(element);
    setupSubscriptionLogic(element, def.defaultListener);

    // real content
    element._innerHTML = element.innerHTML;
    element._innerText = element.innerText;
    if (def.template){
      element.innerHTML = def.template.innerHTML;
    }

    def.contructor.call(element, def.initParams | {});

    element.subscriptions.forEach(function (subscription) {
//      console.log(
//        "Adding event listener for",
//        element.id + '.' + subscription.listener + '(<data>)',
//        "on",
//        subscription.channel
//      );
      document.addEventListener(getChannel(subscription.channel), function(e) {
        if(e.target !== element) {
          // console.log(element.id + " <- " + subscription.channel);
          element[subscription.listener](e.detail, subscription.channel);
        }
        return true;
      })
    });

    element.init();
  };

  Ceci.processComponent = function (element) {
    var name = element.getAttribute('name');
    var template = element.querySelector('template');
    var script = element.querySelector('script[type="text/ceci"]');

    try{
      var generator = new Function("Ceci", "return function() {" + script.innerHTML+ "}");
    }
    catch(e){
      if (e.name === 'SyntaxError') {
        e.message += " in definition of component \"" + name + "\".";
        throw e;
      }
      else {
        throw e;
      }
    }
    var contructor = generator(Ceci);

    Ceci._components[name] = {
      template: template,
      contructor: contructor
    };

    var existingElements = document.querySelectorAll(name);
    Array.prototype.forEach.call(existingElements, function (existingElement) {
      Ceci.convertElement(existingElement);
    });
  };

  Ceci.load = function (callback) {
    function scrape (callback) {
      var elements = document.querySelectorAll('element');
      elements = Array.prototype.slice.call(elements);
      elements.forEach(Ceci.processComponent);
      if (callback){
        callback(Ceci._components);
      }
    }

    var ceciLinks = document.querySelectorAll('link[rel=component][type="text/ceci"]');

    if (ceciLinks.length) {
      var linksLeft = ceciLinks.length;
      Array.prototype.forEach.call(ceciLinks, function (componentLink) {
        var xhr = new XMLHttpRequest(),
            docURL = componentLink.getAttribute('href');
        xhr.open('GET', docURL ,true);
        xhr.onload = function (e) {
          var fragment = document.createElement('div');
          fragment.innerHTML = xhr.response;
          if (document.body.firstChild) {
            document.body.insertBefore(fragment, document.body.firstChild);
          }
          else {
            document.body.appendChild(fragment);
          }
          if (--linksLeft === 0) {
            scrape(callback);
          }
        };
        xhr.send(null);
      });
    }
    else {
      scrape(callback);
    }
  };

  return Ceci;
});
<commit_msg>accidental code left in<commit_after>define(function() {

  var getChannel = function(name) {
    return "flathead:" + name;
  }

  var Ceci = function (element, def) {

    Object.keys(def).filter(function (item) {
      return Ceci._reserved.indexOf(item) === -1;
    }).forEach(function (key) {
      var entry = def[key];
      if (typeof entry === 'function') {
        element[key] = entry;
      }
    });

    if (!def.defaultListener){
      def.defaultListener = Object.keys(def.listeners)[0];
    }

    element.subscriptionListeners = [];

    Object.keys(def.listeners).forEach(function (key) {
      var entry = def.listeners[key];
      var entryType = typeof entry;

      if (entryType === 'function') {
        element[key] = entry;
        element.subscriptionListeners.push(key);
      }
      else {
        throw "Listener \"" + key + "\" is not a function.";
      }
    });

    var defaultListener = def.defaultListener;
    if (!defaultListener){
      defaultListener = Object.keys(def.listeners)[0];
    }
    element.defaultListener = def.listeners[defaultListener];

    element.emit = function (data) {
      var e = new CustomEvent(getChannel(element.broadcastChannel), {bubbles: true, detail: data});
      element.dispatchEvent(e);
      // console.log(element.id + " -> " + element.broadcastChannel);
    };

    element.init = function() {
      if (def.init) {
        def.init.call(element);
      }
    };

    Ceci._plugins.constructor.forEach(function(plugin) {
      plugin(element, def);
    });
  }

  Ceci._reserved = ['init', 'listeners', 'defaultListener'];

  Ceci.reserveKeyword = function(keyword) {
    Ceci._reserved.push(keyword);
  }

  Ceci._plugins = {
    constructor: []
  }

  Ceci.registerCeciPlugin = function(eventName, plugin) {
    Ceci._plugins[eventName].push(plugin);
  }

  Ceci.defaultChannel = "blue";

  Ceci._components = {};

  function getBroadcastChannel(element) {
    var broadcast = element.getElementsByTagName('broadcast')[0];
    if (broadcast){
      var channel = broadcast.getAttribute("on");
      if (channel) {
        return channel;
      }
    }
    return Ceci.defaultChannel;
  }

  function getSubscriptions(element) {
    var subscriptions = element.getElementsByTagName('listen');
    subscriptions = Array.prototype.slice.call(subscriptions);

    if(subscriptions.length === 0) {
      return [{
        listener: 'defaultListener',
        channel: Ceci.defaultChannel
      }];
    }

    subscriptions = subscriptions.map(function (e) {
      var channel = e.getAttribute("on");
      var listener = e.getAttribute("for");

      return {
        listener: listener,
        channel: (channel ? channel : Ceci.defaultChannel)
      };
    });

    return subscriptions;
  }

  function setupBroadcastLogic(element, oriting) {
    console.log("binding "+(element.id || '[unknown id]')+" broadcast channel");
    element.broadcastChannel = getBroadcastChannel(element);
    element.setBroadcastChannel = function(channel) {
      element.broadcastChannel = channel;
    }
  }

  function setupSubscriptionLogic(element, defaultListener) {
    console.log("binding "+(element.id || '[unknown id]')+" subscription channels");
    element.subscriptions = getSubscriptions(element, defaultListener);
    element.setSubscription = function(channel, listener) {
      var append = true;
      element.subscriptions.forEach(function(s) {
        if(s.listener === listener) {
          s.channel = channel;
          append = false;
        }
      });
      if(append) {
        element.subscriptions.push({
          listener: listener,
          channel: channel
        });
      }
    };
    e.removeSubscription = function(channel, listener) {
      e.subscriptions = e.subscriptions.filter(function(s) {
        return !(s.channel === channel && s.listener === listener);
      })
    };
  }

  Ceci.convertElement = function (element) {
    var def = Ceci._components[element.localName],
        original = element.cloneNode(true);

    // real content
    element._innerHTML = element.innerHTML;
    element._innerText = element.innerText;
    if (def.template){
      element.innerHTML = def.template.innerHTML;
    }

    def.contructor.call(element, def.initParams | {});

    // channel logic
    setupBroadcastLogic(element, original);
    setupSubscriptionLogic(element, original);

    element.subscriptions.forEach(function (subscription) {
//      console.log(
//        "Adding event listener for",
//        element.id + '.' + subscription.listener + '(<data>)',
//        "on",
//        subscription.channel
//      );
      document.addEventListener(getChannel(subscription.channel), function(e) {
        if(e.target !== element) {
          // console.log(element.id + " <- " + subscription.channel);
          element[subscription.listener](e.detail, subscription.channel);
        }
        return true;
      })
    });

    element.init();
  };

  Ceci.processComponent = function (element) {
    var name = element.getAttribute('name');
    var template = element.querySelector('template');
    var script = element.querySelector('script[type="text/ceci"]');

    try{
      var generator = new Function("Ceci", "return function() {" + script.innerHTML+ "}");
    }
    catch(e){
      if (e.name === 'SyntaxError') {
        e.message += " in definition of component \"" + name + "\".";
        throw e;
      }
      else {
        throw e;
      }
    }
    var contructor = generator(Ceci);

    Ceci._components[name] = {
      template: template,
      contructor: contructor
    };

    var existingElements = document.querySelectorAll(name);
    Array.prototype.forEach.call(existingElements, function (existingElement) {
      Ceci.convertElement(existingElement);
    });
  };

  Ceci.load = function (callback) {
    function scrape (callback) {
      var elements = document.querySelectorAll('element');
      elements = Array.prototype.slice.call(elements);
      elements.forEach(Ceci.processComponent);
      if (callback){
        callback(Ceci._components);
      }
    }

    var ceciLinks = document.querySelectorAll('link[rel=component][type="text/ceci"]');

    if (ceciLinks.length) {
      var linksLeft = ceciLinks.length;
      Array.prototype.forEach.call(ceciLinks, function (componentLink) {
        var xhr = new XMLHttpRequest(),
            docURL = componentLink.getAttribute('href');
        xhr.open('GET', docURL ,true);
        xhr.onload = function (e) {
          var fragment = document.createElement('div');
          fragment.innerHTML = xhr.response;
          if (document.body.firstChild) {
            document.body.insertBefore(fragment, document.body.firstChild);
          }
          else {
            document.body.appendChild(fragment);
          }
          if (--linksLeft === 0) {
            scrape(callback);
          }
        };
        xhr.send(null);
      });
    }
    else {
      scrape(callback);
    }
  };

  return Ceci;
});
<|endoftext|>


<commit_before>(function(global) {
  'use strict';

  var prop = function(initialValue) {
    var cache = initialValue;
    return function(value) {
      if (typeof value === 'undefined')
        return cache;
      cache = value;
      markDirty(this);
    };
  };

  var markDirty = (function() {
    var dirtyComponents = [];
    var requestId = null;
    var callback = function() {
      dirtyComponents.forEach(function(component) {
        component.redraw();
      });
      dirtyComponents = [];
      requestId = null;
    };
    return function(component) {
      if (typeof document === 'undefined')
        return;
      if (dirtyComponents.indexOf(component) === -1)
        dirtyComponents.push(component);
      if (requestId !== null)
        return;
      requestId = dom.animate(callback);
    };
  })();

  var diffObj = function(newObj, oldObj) {
    var diff = {};
    for (var key in newObj) {
      if (newObj[key] !== oldObj[key])
        diff[key] = newObj[key];
    }
    return diff;
  };

  var dom = {};

  dom.el = function(selector) {
    if (selector[0] === '<') {
      selector = selector.match(/<(.+)>/)[1];
      return document.createElement(selector);
    }
    return document.querySelector(selector);
  };

  dom.attr = function(el, props) {
    for (var prop in props) {
      el.setAttribute(prop, props[prop]);
    }
  };

  dom.css = function(el, props) {
    var style = el.style;
    for (var prop in props) {
      style[prop] = props[prop];
    }
  };

  dom.append = function(parent, el) {
    parent.appendChild(el);
  };

  dom.remove = function(el) {
    el.parentNode.removeChild(el);
  };

  dom.text = function(el, s) {
    el.textContent = s;
  };

  dom.html = function(el, s) {
    el.innerHTML = s;
  };

  dom.animate = function(callback) {
    return window.requestAnimationFrame(callback);
  };

  var Node = function(option) {
    this.content = prop(option.content || '');
    this.contentType = prop(option.contentType || Node.CONTENT_TYPE_TEXT);
    this.x = prop(option.x || 0);
    this.y = prop(option.y || 0);
    this.width = prop(option.width || 75);
    this.height = prop(option.height || 30);
    this.backgroundColor = prop(option.backgroundColor || '#a7cbe6');
    this.borderColor = prop(option.borderColor || '#333');
    this.borderWidth = prop(option.borderWidth || 2);
    this.textColor = prop(option.textColor || '#333');
    this.element = prop(null);
    this.parentElement = prop(null);
    this.cache = prop({});
  };

  Node.prototype.text = function(text) {
    if (typeof text === 'undefined')
      return this.content();
    this.content(text);
    this.contentType(Node.CONTENT_TYPE_TEXT);
  };

  Node.prototype.html = function(html) {
    if (typeof html === 'undefined')
      return this.content();
    this.content(html);
    this.contentType(Node.CONTENT_TYPE_HTML);
  };

  Node.prototype.style = function() {
    var contentType = this.contentType();
    var lineHeight = (contentType === Node.CONTENT_TYPE_TEXT) ? this.height() : 14;
    var textAlign = (contentType === Node.CONTENT_TYPE_TEXT) ? 'center' : 'left';
    var translate = 'translate(' + this.x() + 'px, ' + this.y() + 'px)';
    var borderWidthOffset = this.borderWidth() * 2;
    return {
      backgroundColor: this.backgroundColor(),
      border: this.borderWidth() + 'px solid ' + this.borderColor(),
      borderRadius: '4px',
      color: this.textColor(),
      height: (this.height() - borderWidthOffset) + 'px',
      lineHeight: (lineHeight - borderWidthOffset) + 'px',
      MozTransform: translate,
      msTransform: translate,
      overflow: 'hidden',
      position: 'absolute',
      textAlign: textAlign,
      textOverflow: 'ellipsis',
      transform: translate,
      webkitTransform: translate,
      whiteSpace: 'nowrap',
      width: (this.width() - borderWidthOffset) + 'px'
    };
  };

  Node.prototype.redraw = function() {
    var content = this.content();
    var contentType = this.contentType();
    var style = this.style();
    var element = this.element();
    var parentElement = this.parentElement();
    var cache = this.cache();

    if (!parentElement && !element)
      return;

    // add element
    if (parentElement && !element) {
      element = dom.el('
');
      this.element(element);
      this.redraw();
      dom.append(parentElement, element);
      return;
    }

    // remove element
    if (!parentElement && element) {
      dom.remove(element);
      this.element(null);
      this.cache({});
      return;
    }

    if (content !== cache.content) {
      if (contentType === Node.CONTENT_TYPE_TEXT)
        dom.text(element, content);
      else if (contentType === Node.CONTENT_TYPE_HTML)
        dom.html(element, content);
      cache.content = content;
    }

    var diffStyle = diffObj(style, cache.style || {});
    dom.css(element, diffStyle);
    cache.style = style;
  };

  Node.CONTENT_TYPE_TEXT = 'text';
  Node.CONTENT_TYPE_HTML = 'html';

  var Link = function(option) {
    this.content = prop(option.content || '');
    this.contentType = prop(option.contentType || Link.CONTENT_TYPE_TEXT);
    this.x = prop(option.x || 60);
    this.y = prop(option.y || 30);
    this.width = prop(option.width || 50);
    this.height = prop(option.height || 20);
    this.backgroundColor = prop(option.backgroundColor || 'white');
    this.borderColor = prop(option.borderColor || '#333');
    this.borderWidth = prop(option.borderWidth || 2);
    this.textColor = prop(option.textColor || '#333');
    this.sourceX = prop(option.sourceX || option.x - 45 || 15);
    this.sourceY = prop(option.sourceY || option.y || 30);
    this.targetX = prop(option.targetX || option.x + 45 || 105);
    this.targetY = prop(option.targetY || option.y || 30);
    this.lineColor = prop(option.lineColor || '#333');
    this.lineWidth = prop(option.lineWidth || 2);
    this.element = prop(null);
    this.parentElement = prop(null);
    this.cache = prop({});
  };

  Link.prototype.text = function(text) {
    if (typeof text === 'undefined')
      return this.content();
    this.content(text);
    this.contentType(Link.CONTENT_TYPE_TEXT);
  };

  Link.prototype.html = function(html) {
    if (typeof html === 'undefined')
      return this.content();
    this.content(html);
    this.contentType(Link.CONTENT_TYPE_HTML);
  };

  Link.prototype.pathContainerStyle = function() {
    return {
      overflow: 'visible',
      position: 'absolute'
    };
  };

  Link.prototype.pathAttributes = function() {
    var d = ['M', this.sourceX(), this.sourceY(),
             'L', this.x(), this.y(),
             'L', this.targetX(), this.targetY()].join(' ');
    return {
      d: d,
      fill: 'none',
      stroke: this.lineColor(),
      'stroke-linecap': 'round',
      'stroke-width': this.lineWidth()
    };
  };

  Link.prototype.contentStyle = function() {
    var contentType = this.contentType();
    var lineHeight = (contentType === Link.CONTENT_TYPE_TEXT) ? this.height() : 14;
    var textAlign = (contentType === Link.CONTENT_TYPE_TEXT) ? 'center' : 'left';
    var x = this.x() - this.width() / 2;
    var y = this.y() - this.height() / 2;
    var translate = 'translate(' + x + 'px, ' + y + 'px)';
    var borderWidthOffset = this.borderWidth() * 2;
    return {
      backgroundColor: this.backgroundColor(),
      border: this.borderWidth() + 'px solid ' + this.borderColor(),
      borderRadius: '4px',
      color: this.textColor(),
      height: (this.height() - borderWidthOffset) + 'px',
      lineHeight: (lineHeight - borderWidthOffset) + 'px',
      MozTransform: translate,
      msTransform: translate,
      overflow: 'hidden',
      position: 'absolute',
      textAlign: textAlign,
      textOverflow: 'ellipsis',
      transform: translate,
      webkitTransform: translate,
      whiteSpace: 'nowrap',
      width: (this.width() - borderWidthOffset) + 'px'
    };
  };

  Link.prototype.redraw = function() {
    var content = this.content();
    var contentType = this.contentType();
    var pathAttributes = this.pathAttributes();
    var contentStyle = this.contentStyle();
    var element = this.element();
    var parentElement = this.parentElement();
    var cache = this.cache();

    var pathContainerElement;
    var pathElement;
    var contentElement;

    if (!parentElement && !element)
      return;

    // add element
    if (parentElement && !element) {
      element = dom.el('
');
      this.element(element);
      dom.html(element, '<svg><path></path></svg>

');
      pathContainerElement = element.children[0];
      dom.css(pathContainerElement, this.pathContainerStyle());
      this.redraw();
      dom.append(parentElement, element);
      return;
    }

    // remove element
    if (!parentElement && element) {
      dom.remove(element);
      this.element(null);
      this.cache({});
      return;
    }

    // update path element
    pathElement = element.children[0].childNodes[0];

    var diffPathAttributes = diffObj(pathAttributes, cache.pathAttributes || {});
    dom.attr(pathElement, diffPathAttributes);
    cache.pathAttributes = pathAttributes;

    // update content element
    contentElement = element.children[1];

    if (content !== cache.content) {
      if (contentType === Link.CONTENT_TYPE_TEXT)
        dom.text(contentElement, content);
      else if (contentType === Link.CONTENT_TYPE_HTML)
        dom.html(contentElement, content);
      cache.content = content;
    }

    var diffContentStyle = diffObj(contentStyle, cache.contentStyle || {});
    dom.css(contentElement, diffContentStyle);
    cache.contentStyle = contentStyle;
  };

  Link.CONTENT_TYPE_TEXT = 'text';
  Link.CONTENT_TYPE_HTML = 'html';

  var Cmap = function(element) {
    if (!(this instanceof Cmap))
      return new Cmap(element);

    this.element = prop(element);

    markDirty(this);
  };

  Cmap.prototype.createNode = function(option) {
    return new Node(option || {});
  };

  Cmap.prototype.createLink = function(option) {
    return new Link(option || {});
  };

  Cmap.prototype.add = function(child) {
    child.parentElement(this.element());
  };

  Cmap.prototype.remove = function(child) {
    child.parentElement(null);
  };

  Cmap.prototype.style = function() {
    return {
      color: '#333',
      cursor: 'default',
      fontFamily: 'sans-serif',
      fontSize: '14px',
      MozUserSelect: 'none',
      msUserSelect: 'none',
      position: 'relative',
      userSelect: 'none',
      webkitUserSelect: 'none'
    };
  };

  Cmap.prototype.redraw = function() {
    var element = this.element();

    if (!element) {
      element = dom.el('
');
      this.element(element);
    }

    dom.css(element, this.style());
  };

  if (typeof module !== 'undefined' && module.exports)
    module.exports = Cmap;
  else
    global.Cmap = Cmap;
})(this);<commit_msg>Refactor code for getting the difference between two objects<commit_after>(function(global) {
  'use strict';

  var prop = function(initialValue) {
    var cache = initialValue;
    return function(value) {
      if (typeof value === 'undefined')
        return cache;
      cache = value;
      markDirty(this);
    };
  };

  var markDirty = (function() {
    var dirtyComponents = [];
    var requestId = null;
    var callback = function() {
      dirtyComponents.forEach(function(component) {
        component.redraw();
      });
      dirtyComponents = [];
      requestId = null;
    };
    return function(component) {
      if (typeof document === 'undefined')
        return;
      if (dirtyComponents.indexOf(component) === -1)
        dirtyComponents.push(component);
      if (requestId !== null)
        return;
      requestId = dom.animate(callback);
    };
  })();

  var diffObj = function(newObj, oldObj) {
    var diff = {};
    for (var key in newObj) {
      if (newObj[key] !== oldObj[key])
        diff[key] = newObj[key];
    }
    return diff;
  };

  var dom = {};

  dom.el = function(selector) {
    if (selector[0] === '<') {
      selector = selector.match(/<(.+)>/)[1];
      return document.createElement(selector);
    }
    return document.querySelector(selector);
  };

  dom.attr = function(el, props) {
    for (var prop in props) {
      el.setAttribute(prop, props[prop]);
    }
  };

  dom.css = function(el, props) {
    var style = el.style;
    for (var prop in props) {
      style[prop] = props[prop];
    }
  };

  dom.append = function(parent, el) {
    parent.appendChild(el);
  };

  dom.remove = function(el) {
    el.parentNode.removeChild(el);
  };

  dom.text = function(el, s) {
    el.textContent = s;
  };

  dom.html = function(el, s) {
    el.innerHTML = s;
  };

  dom.animate = function(callback) {
    return window.requestAnimationFrame(callback);
  };

  var Node = function(option) {
    this.content = prop(option.content || '');
    this.contentType = prop(option.contentType || Node.CONTENT_TYPE_TEXT);
    this.x = prop(option.x || 0);
    this.y = prop(option.y || 0);
    this.width = prop(option.width || 75);
    this.height = prop(option.height || 30);
    this.backgroundColor = prop(option.backgroundColor || '#a7cbe6');
    this.borderColor = prop(option.borderColor || '#333');
    this.borderWidth = prop(option.borderWidth || 2);
    this.textColor = prop(option.textColor || '#333');
    this.element = prop(null);
    this.parentElement = prop(null);
    this.cache = prop({});
  };

  Node.prototype.text = function(text) {
    if (typeof text === 'undefined')
      return this.content();
    this.content(text);
    this.contentType(Node.CONTENT_TYPE_TEXT);
  };

  Node.prototype.html = function(html) {
    if (typeof html === 'undefined')
      return this.content();
    this.content(html);
    this.contentType(Node.CONTENT_TYPE_HTML);
  };

  Node.prototype.style = function() {
    var contentType = this.contentType();
    var lineHeight = (contentType === Node.CONTENT_TYPE_TEXT) ? this.height() : 14;
    var textAlign = (contentType === Node.CONTENT_TYPE_TEXT) ? 'center' : 'left';
    var translate = 'translate(' + this.x() + 'px, ' + this.y() + 'px)';
    var borderWidthOffset = this.borderWidth() * 2;
    return {
      backgroundColor: this.backgroundColor(),
      border: this.borderWidth() + 'px solid ' + this.borderColor(),
      borderRadius: '4px',
      color: this.textColor(),
      height: (this.height() - borderWidthOffset) + 'px',
      lineHeight: (lineHeight - borderWidthOffset) + 'px',
      MozTransform: translate,
      msTransform: translate,
      overflow: 'hidden',
      position: 'absolute',
      textAlign: textAlign,
      textOverflow: 'ellipsis',
      transform: translate,
      webkitTransform: translate,
      whiteSpace: 'nowrap',
      width: (this.width() - borderWidthOffset) + 'px'
    };
  };

  Node.prototype.redraw = function() {
    var content = this.content();
    var contentType = this.contentType();
    var style = this.style();
    var element = this.element();
    var parentElement = this.parentElement();
    var cache = this.cache();

    if (!parentElement && !element)
      return;

    // add element
    if (parentElement && !element) {
      element = dom.el('
');
      this.element(element);
      this.redraw();
      dom.append(parentElement, element);
      return;
    }

    // remove element
    if (!parentElement && element) {
      dom.remove(element);
      this.element(null);
      this.cache({});
      return;
    }

    if (content !== cache.content) {
      if (contentType === Node.CONTENT_TYPE_TEXT)
        dom.text(element, content);
      else if (contentType === Node.CONTENT_TYPE_HTML)
        dom.html(element, content);
      cache.content = content;
    }

    dom.css(element, cache.style ? diffObj(style, cache.style) : style);
    cache.style = style;
  };

  Node.CONTENT_TYPE_TEXT = 'text';
  Node.CONTENT_TYPE_HTML = 'html';

  var Link = function(option) {
    this.content = prop(option.content || '');
    this.contentType = prop(option.contentType || Link.CONTENT_TYPE_TEXT);
    this.x = prop(option.x || 60);
    this.y = prop(option.y || 30);
    this.width = prop(option.width || 50);
    this.height = prop(option.height || 20);
    this.backgroundColor = prop(option.backgroundColor || 'white');
    this.borderColor = prop(option.borderColor || '#333');
    this.borderWidth = prop(option.borderWidth || 2);
    this.textColor = prop(option.textColor || '#333');
    this.sourceX = prop(option.sourceX || option.x - 45 || 15);
    this.sourceY = prop(option.sourceY || option.y || 30);
    this.targetX = prop(option.targetX || option.x + 45 || 105);
    this.targetY = prop(option.targetY || option.y || 30);
    this.lineColor = prop(option.lineColor || '#333');
    this.lineWidth = prop(option.lineWidth || 2);
    this.element = prop(null);
    this.parentElement = prop(null);
    this.cache = prop({});
  };

  Link.prototype.text = function(text) {
    if (typeof text === 'undefined')
      return this.content();
    this.content(text);
    this.contentType(Link.CONTENT_TYPE_TEXT);
  };

  Link.prototype.html = function(html) {
    if (typeof html === 'undefined')
      return this.content();
    this.content(html);
    this.contentType(Link.CONTENT_TYPE_HTML);
  };

  Link.prototype.pathContainerStyle = function() {
    return {
      overflow: 'visible',
      position: 'absolute'
    };
  };

  Link.prototype.pathAttributes = function() {
    var d = ['M', this.sourceX(), this.sourceY(),
             'L', this.x(), this.y(),
             'L', this.targetX(), this.targetY()].join(' ');
    return {
      d: d,
      fill: 'none',
      stroke: this.lineColor(),
      'stroke-linecap': 'round',
      'stroke-width': this.lineWidth()
    };
  };

  Link.prototype.contentStyle = function() {
    var contentType = this.contentType();
    var lineHeight = (contentType === Link.CONTENT_TYPE_TEXT) ? this.height() : 14;
    var textAlign = (contentType === Link.CONTENT_TYPE_TEXT) ? 'center' : 'left';
    var x = this.x() - this.width() / 2;
    var y = this.y() - this.height() / 2;
    var translate = 'translate(' + x + 'px, ' + y + 'px)';
    var borderWidthOffset = this.borderWidth() * 2;
    return {
      backgroundColor: this.backgroundColor(),
      border: this.borderWidth() + 'px solid ' + this.borderColor(),
      borderRadius: '4px',
      color: this.textColor(),
      height: (this.height() - borderWidthOffset) + 'px',
      lineHeight: (lineHeight - borderWidthOffset) + 'px',
      MozTransform: translate,
      msTransform: translate,
      overflow: 'hidden',
      position: 'absolute',
      textAlign: textAlign,
      textOverflow: 'ellipsis',
      transform: translate,
      webkitTransform: translate,
      whiteSpace: 'nowrap',
      width: (this.width() - borderWidthOffset) + 'px'
    };
  };

  Link.prototype.redraw = function() {
    var content = this.content();
    var contentType = this.contentType();
    var pathAttributes = this.pathAttributes();
    var contentStyle = this.contentStyle();
    var element = this.element();
    var parentElement = this.parentElement();
    var cache = this.cache();

    var pathContainerElement;
    var pathElement;
    var contentElement;

    if (!parentElement && !element)
      return;

    // add element
    if (parentElement && !element) {
      element = dom.el('
');
      this.element(element);
      dom.html(element, '<svg><path></path></svg>

');
      pathContainerElement = element.children[0];
      dom.css(pathContainerElement, this.pathContainerStyle());
      this.redraw();
      dom.append(parentElement, element);
      return;
    }

    // remove element
    if (!parentElement && element) {
      dom.remove(element);
      this.element(null);
      this.cache({});
      return;
    }

    // update path element
    pathElement = element.children[0].childNodes[0];

    dom.attr(pathElement, cache.pathAttributes ? diffObj(pathAttributes, cache.pathAttributes) : pathAttributes);
    cache.pathAttributes = pathAttributes;

    // update content element
    contentElement = element.children[1];

    if (content !== cache.content) {
      if (contentType === Link.CONTENT_TYPE_TEXT)
        dom.text(contentElement, content);
      else if (contentType === Link.CONTENT_TYPE_HTML)
        dom.html(contentElement, content);
      cache.content = content;
    }

    dom.css(contentElement, cache.contentStyle ? diffObj(contentStyle, cache.contentStyle) : contentStyle);
    cache.contentStyle = contentStyle;
  };

  Link.CONTENT_TYPE_TEXT = 'text';
  Link.CONTENT_TYPE_HTML = 'html';

  var Cmap = function(element) {
    if (!(this instanceof Cmap))
      return new Cmap(element);

    this.element = prop(element);

    markDirty(this);
  };

  Cmap.prototype.createNode = function(option) {
    return new Node(option || {});
  };

  Cmap.prototype.createLink = function(option) {
    return new Link(option || {});
  };

  Cmap.prototype.add = function(child) {
    child.parentElement(this.element());
  };

  Cmap.prototype.remove = function(child) {
    child.parentElement(null);
  };

  Cmap.prototype.style = function() {
    return {
      color: '#333',
      cursor: 'default',
      fontFamily: 'sans-serif',
      fontSize: '14px',
      MozUserSelect: 'none',
      msUserSelect: 'none',
      position: 'relative',
      userSelect: 'none',
      webkitUserSelect: 'none'
    };
  };

  Cmap.prototype.redraw = function() {
    var element = this.element();

    if (!element) {
      element = dom.el('
');
      this.element(element);
    }

    dom.css(element, this.style());
  };

  if (typeof module !== 'undefined' && module.exports)
    module.exports = Cmap;
  else
    global.Cmap = Cmap;
})(this);<|endoftext|>


<commit_before>'use strict';

rect(15, 15, 50, 50);
<commit_msg>initial code for stage<commit_after>'use strict';

// draw the background
background(127, 131, 231);

// draw the floor
var yGround = 500;
fill(156,102,17); // brown
rect(0,yGround,600,600-yGround);

// draw a pipe coming out of floor
fill(141,199,17); // green
rect(400,400,100,50);
rect(410,450,80,50);

// box
fill(216,216,216);
rect(0,0,100,100);
line(0,0,100,100);
line(100,0,0,100);

<|endoftext|>


<commit_before>var components = {
	core: {
		meta: {
			path: 'components/prism-core.js',
			option: 'mandatory'
		},
		'core': 'Core'
	},
	themes: {
		meta: {
			path: '{id}.css',
			link: 'index.html?theme={id}',
			exclusive: true
		},
		'prism': {
			title: 'Default',
			option: 'default'
		},
		'prism-dark': 'Dark',
		'prism-funky': 'Funky',
		'okaidia': 'Okaidia'
	},
	languages: {
		meta: {
			path: 'components/prism-{id}'
		},
		'markup': {
			title: 'Markup',
			option: 'default'
		},
		'css': {
			title: 'CSS',
			option: 'default'
		},
		'clike': {
			title: 'C-like',
			option: 'default'
		},
		'javascript': {
			title: 'JavaScript',
			option: 'default',
			require: 'clike'
		},
		'java' : {
			title: 'Java',
			require: 'clike'
		},
		'php' : {
			title: 'PHP',
			require: 'clike'
		},
		'coffeescript': {
			title: 'CoffeeScript',
			require: 'javascript'
		},
		'scss': {
			title: 'Sass (Scss)',
			require: 'css'
		},
		'bash' : {
			title: 'Bash',
			require: 'clike'
		},
		'c': {
			title: 'C',
			require: 'clike'
		},
		'cpp': {
			title: 'C++',
			require: 'c'
		},
		'python': {
			title: 'Python'
		},
		'sql': {
			title: 'SQL'
		}
	},
	plugins: {
		meta: {
			path: 'plugins/{id}/prism-{id}',
			link: 'plugins/{id}/',
			hasCSS: true
		},
		'line-highlight': 'Line Highlight',
		'show-invisibles': 'Show Invisibles',
		'autolinker': 'Autolinker',
		'wpd': 'WebPlatform Docs'
	}
};

(function(){

if(!document.body.addEventListener) {
	return;
}

$$('[data-src]').forEach(function(element) {
	var src = element.getAttribute('data-src'),
	    html = element.getAttribute('data-type') === 'text/html',
	    contentProperty = html? 'innerHTML' : 'textContent';

	$u.xhr({
		url: src,
		callback: function(xhr) {
			try {
				element[contentProperty] = xhr.responseText;

				// Run JS

				$$('script', element).forEach(function (script) {
					var after = script.nextSibling, parent = script.parentNode;
					parent.removeChild(script);
					document.head.appendChild(script);
				});

				$u.event.fire(element, 'contentreceived', {
					src: src
				});
			}
			catch (e) {}
		}
	});
});

document.body.addEventListener('contentreceived', function(evt) {
	var pre = evt.target;

	if(!/pre/i.test(pre.nodeName)) {
		return;
	}

	var language = {
		'js': 'javascript',
		'css': 'css',
		'html': 'markup',
		'svg': 'markup'
	}[(evt.src.match(/\.(\w+)$/) || [,''])[1]];

	var code = document.createElement('code');

	code.className = 'lang-' + language;

	code.textContent = pre.textContent;
	pre.textContent = '';

	pre.appendChild(code);

	Prism.highlightElement(code);
});

})();

/**
 * Table of contents
 */
(function(){
var toc = document.createElement('ol');

$$('body > section > h1').forEach(function(h1) {
	var section = h1.parentNode,
	    text = h1.textContent,
	    id = h1.id || section.id;

	// Assign id if one does not exist
	if (!id) {
		id = text.toLowerCase();

		// Replace spaces with hyphens, only keep first 10 words
		id = id.split(/\s+/g, 10).join('-');

		// Remove non-word characters
		id = id.replace(/[^\w-]/g, '');

		section.id = id;
	}

	// Linkify heading text
	if (h1.children.length === 0) {
		h1.innerHTML = '';

		$u.element.create('a', {
			properties: {
				href: '#' + id
			},
			contents: text,
			inside: h1
		});
	}

	$u.element.create('li', {
		contents: {
			tag: 'a',
			properties: {
				href: '#' + (h1.id || section.id)
			},
			contents: text
		},
		inside: toc
	});
});

if (toc.children.length > 0) {
	$u.element.create('section', {
		properties: {
			id: 'toc'
		},
		contents: [{
			tag: 'h1',
			contents: 'On this page'
		}, toc],
		before: $('body > section')
	});
}

})();

// calc()
(function(){
	if(!window.PrefixFree) return;

	if (PrefixFree.functions.indexOf('calc') == -1) {
		var style = document.createElement('_').style;
		style.width = 'calc(1px + 1%)'

		if(!style.width) {
			// calc not supported
			var header = $('header'),
			    footer = $('footer');

			function calculatePadding() {
				header.style.padding =
				footer.style.padding = '30px ' + (innerWidth/2 - 450) + 'px';
			}

			addEventListener('resize', calculatePadding);
			calculatePadding();
		}
	}
})();

(function() {
var p = $u.element.create('p', {
	properties: {
		id: 'theme'
	},
	contents: {
		tag: 'p',
		contents: 'Theme:'
	},
	after: '.intro'
});

var themes = components.themes;
var current = (location.search.match(/theme=([\w-]+)/) || [])[1];

if (!(current in themes)) {
	current = undefined;
}

if (current === undefined) {
	var stored = localStorage.getItem('theme');

	current = stored in themes? current = stored : 'prism';
}

function setTheme(id) {
	var link = $$('link[href^="prism"]')[0];

	link.href = themes.meta.path.replace(/\{id}/g, id);
	localStorage.setItem('theme', id);
}

for (var id in themes) {

	if (id === 'meta') {
		continue;
	}

	$u.element.create('input', {
		properties: {
			type: 'radio',
			name: "theme",
			id: 'theme=' + id,
			checked: current === id,
			value: id,
			onclick: function () {
				setTheme(this.value);
			}
		},
		inside: p
	});

	$u.element.create('label', {
		properties: {
			htmlFor: 'theme=' + id
		},
		contents: themes[id].title || themes[id],
		inside: p
	});
}

setTheme(current);
})();

(function(){

function listPlugins(ul) {
	for (var id in components.plugins) {
		if (id == 'meta') {
			continue;
		}

		var plugin = components.plugins[id];

		$u.element.create('li', {
			contents: {
				tag: 'a',
				prop: {
					href: 'plugins/' + id
				},
				contents: plugin.title || plugin
			},
			inside: ul
		});
	}
}

$$('.plugin-list').forEach(listPlugins);

})();
<commit_msg>added Groovy language to download options<commit_after>var components = {
	core: {
		meta: {
			path: 'components/prism-core.js',
			option: 'mandatory'
		},
		'core': 'Core'
	},
	themes: {
		meta: {
			path: '{id}.css',
			link: 'index.html?theme={id}',
			exclusive: true
		},
		'prism': {
			title: 'Default',
			option: 'default'
		},
		'prism-dark': 'Dark',
		'prism-funky': 'Funky',
		'okaidia': 'Okaidia'
	},
	languages: {
		meta: {
			path: 'components/prism-{id}'
		},
		'markup': {
			title: 'Markup',
			option: 'default'
		},
		'css': {
			title: 'CSS',
			option: 'default'
		},
		'clike': {
			title: 'C-like',
			option: 'default'
		},
		'javascript': {
			title: 'JavaScript',
			option: 'default',
			require: 'clike'
		},
		'java' : {
			title: 'Java',
			require: 'clike'
		},
		'php' : {
			title: 'PHP',
			require: 'clike'
		},
		'coffeescript': {
			title: 'CoffeeScript',
			require: 'javascript'
		},
		'scss': {
			title: 'Sass (Scss)',
			require: 'css'
		},
		'bash' : {
			title: 'Bash',
			require: 'clike'
		},
		'c': {
			title: 'C',
			require: 'clike'
		},
		'cpp': {
			title: 'C++',
			require: 'c'
		},
		'python': {
			title: 'Python'
		},
		'sql': {
			title: 'SQL'
		},
		'groovy': {
			title: 'Groovy',
			require: 'clike'
		}
	},
	plugins: {
		meta: {
			path: 'plugins/{id}/prism-{id}',
			link: 'plugins/{id}/',
			hasCSS: true
		},
		'line-highlight': 'Line Highlight',
		'show-invisibles': 'Show Invisibles',
		'autolinker': 'Autolinker',
		'wpd': 'WebPlatform Docs'
	}
};

(function(){

if(!document.body.addEventListener) {
	return;
}

$$('[data-src]').forEach(function(element) {
	var src = element.getAttribute('data-src'),
	    html = element.getAttribute('data-type') === 'text/html',
	    contentProperty = html? 'innerHTML' : 'textContent';

	$u.xhr({
		url: src,
		callback: function(xhr) {
			try {
				element[contentProperty] = xhr.responseText;

				// Run JS

				$$('script', element).forEach(function (script) {
					var after = script.nextSibling, parent = script.parentNode;
					parent.removeChild(script);
					document.head.appendChild(script);
				});

				$u.event.fire(element, 'contentreceived', {
					src: src
				});
			}
			catch (e) {}
		}
	});
});

document.body.addEventListener('contentreceived', function(evt) {
	var pre = evt.target;

	if(!/pre/i.test(pre.nodeName)) {
		return;
	}

	var language = {
		'js': 'javascript',
		'css': 'css',
		'html': 'markup',
		'svg': 'markup'
	}[(evt.src.match(/\.(\w+)$/) || [,''])[1]];

	var code = document.createElement('code');

	code.className = 'lang-' + language;

	code.textContent = pre.textContent;
	pre.textContent = '';

	pre.appendChild(code);

	Prism.highlightElement(code);
});

})();

/**
 * Table of contents
 */
(function(){
var toc = document.createElement('ol');

$$('body > section > h1').forEach(function(h1) {
	var section = h1.parentNode,
	    text = h1.textContent,
	    id = h1.id || section.id;

	// Assign id if one does not exist
	if (!id) {
		id = text.toLowerCase();

		// Replace spaces with hyphens, only keep first 10 words
		id = id.split(/\s+/g, 10).join('-');

		// Remove non-word characters
		id = id.replace(/[^\w-]/g, '');

		section.id = id;
	}

	// Linkify heading text
	if (h1.children.length === 0) {
		h1.innerHTML = '';

		$u.element.create('a', {
			properties: {
				href: '#' + id
			},
			contents: text,
			inside: h1
		});
	}

	$u.element.create('li', {
		contents: {
			tag: 'a',
			properties: {
				href: '#' + (h1.id || section.id)
			},
			contents: text
		},
		inside: toc
	});
});

if (toc.children.length > 0) {
	$u.element.create('section', {
		properties: {
			id: 'toc'
		},
		contents: [{
			tag: 'h1',
			contents: 'On this page'
		}, toc],
		before: $('body > section')
	});
}

})();

// calc()
(function(){
	if(!window.PrefixFree) return;

	if (PrefixFree.functions.indexOf('calc') == -1) {
		var style = document.createElement('_').style;
		style.width = 'calc(1px + 1%)'

		if(!style.width) {
			// calc not supported
			var header = $('header'),
			    footer = $('footer');

			function calculatePadding() {
				header.style.padding =
				footer.style.padding = '30px ' + (innerWidth/2 - 450) + 'px';
			}

			addEventListener('resize', calculatePadding);
			calculatePadding();
		}
	}
})();

(function() {
var p = $u.element.create('p', {
	properties: {
		id: 'theme'
	},
	contents: {
		tag: 'p',
		contents: 'Theme:'
	},
	after: '.intro'
});

var themes = components.themes;
var current = (location.search.match(/theme=([\w-]+)/) || [])[1];

if (!(current in themes)) {
	current = undefined;
}

if (current === undefined) {
	var stored = localStorage.getItem('theme');

	current = stored in themes? current = stored : 'prism';
}

function setTheme(id) {
	var link = $$('link[href^="prism"]')[0];

	link.href = themes.meta.path.replace(/\{id}/g, id);
	localStorage.setItem('theme', id);
}

for (var id in themes) {

	if (id === 'meta') {
		continue;
	}

	$u.element.create('input', {
		properties: {
			type: 'radio',
			name: "theme",
			id: 'theme=' + id,
			checked: current === id,
			value: id,
			onclick: function () {
				setTheme(this.value);
			}
		},
		inside: p
	});

	$u.element.create('label', {
		properties: {
			htmlFor: 'theme=' + id
		},
		contents: themes[id].title || themes[id],
		inside: p
	});
}

setTheme(current);
})();

(function(){

function listPlugins(ul) {
	for (var id in components.plugins) {
		if (id == 'meta') {
			continue;
		}

		var plugin = components.plugins[id];

		$u.element.create('li', {
			contents: {
				tag: 'a',
				prop: {
					href: 'plugins/' + id
				},
				contents: plugin.title || plugin
			},
			inside: ul
		});
	}
}

$$('.plugin-list').forEach(listPlugins);

})();
<|endoftext|>


<commit_before>// Copy file
// Credit: Isaac Schlueter
// http://groups.google.com/group/nodejs/msg/ef4de0b516f7d5b8

'use strict';

var isCallable       = require('es5-ext/object/is-callable')
  , normalizeOptions = require('es5-ext/object/normalize-options')
  , deferred         = require('deferred')
  , fs               = require('fs')
  , path             = require('path')
  , mkdir            = require('./mkdir')

  , dirname = path.dirname, resolve = path.resolve
  , createReadStream = fs.createReadStream
  , createWriteStream = fs.createWriteStream

  , copy;

copy = function (source, dest, options) {
	var def = deferred(), read, write;

	try {
		read = createReadStream(source);
	} catch (e) {
		return def.reject(e);
	}
	try {
		write = createWriteStream(dest, options);
	} catch (e1) {
		read.destroy();
		return def.reject(e1);
	}

	read.on('error', function (e) {
		write.destroy();
		def.reject(e);
	});
	write.on('error', function (e) {
		read.destroy();
		if ((e.code === 'ENOENT') && options.intermediate) {
			def.resolve(mkdir(dirname(resolve(dest)), { intermediate: true })(function () {
				options = normalizeOptions(options);
				delete options.intermediate;
				return copy(source, dest, options);
			}));
			return;
		}
		def.reject(e);
	});
	read.pipe(write);
	write.on('close', def.resolve);

	return def.promise;
};
copy.returnsPromise = true;

module.exports = exports = function (source, dest/*, options, cb*/) {
	var options = Object(arguments[2]), cb = arguments[3];
	if ((cb == null) && isCallable(options)) {
		cb = options;
		options = {};
	}

	return copy(String(source), String(dest), options).cb(cb);
};
exports.copy = copy;
exports.returnsPromise = true;
<commit_msg>-- convention<commit_after>// Copy file
// Credit: Isaac Schlueter
// http://groups.google.com/group/nodejs/msg/ef4de0b516f7d5b8

'use strict';

var isCallable       = require('es5-ext/object/is-callable')
  , normalizeOptions = require('es5-ext/object/normalize-options')
  , deferred         = require('deferred')
  , fs               = require('fs')
  , path             = require('path')
  , mkdir            = require('./mkdir')

  , dirname = path.dirname, resolve = path.resolve
  , createReadStream = fs.createReadStream, createWriteStream = fs.createWriteStream;

var copy = function (source, dest, options) {
	var def = deferred(), read, write;

	try {
		read = createReadStream(source);
	} catch (e) {
		return def.reject(e);
	}
	try {
		write = createWriteStream(dest, options);
	} catch (e1) {
		read.destroy();
		return def.reject(e1);
	}

	read.on('error', function (e) {
		write.destroy();
		def.reject(e);
	});
	write.on('error', function (e) {
		read.destroy();
		if ((e.code === 'ENOENT') && options.intermediate) {
			def.resolve(mkdir(dirname(resolve(dest)), { intermediate: true })(function () {
				options = normalizeOptions(options);
				delete options.intermediate;
				return copy(source, dest, options);
			}));
			return;
		}
		def.reject(e);
	});
	read.pipe(write);
	write.on('close', def.resolve);

	return def.promise;
};
copy.returnsPromise = true;

module.exports = exports = function (source, dest/*, options, cb*/) {
	var options = Object(arguments[2]), cb = arguments[3];
	if ((cb == null) && isCallable(options)) {
		cb = options;
		options = {};
	}

	return copy(String(source), String(dest), options).cb(cb);
};
exports.copy = copy;
exports.returnsPromise = true;
<|endoftext|>


<commit_before>// Core of fnfnen.
// Variables  {{{1

var DUMMY_SINCE_ID = 1;
var MAX_COUNT = 200;
var TWITTER_API_URI = 'http://api.twitter.com/1/';
var TWITTER_UI_URI = 'http://twitter.com/';
var UPDATE_INTERVAL = 5 * 60 * 1000;  // in milliseconds

var g_seq = (new Date).getTime();
var g_since_id = null;
var g_update_timer = null;
var g_user = null;

// Code  {{{1
function authenticate()  //{{{2
{
  call_twitter_api(TWITTER_UI_URI,
                   'account/verify_credentials',
                   {'callback': 'callback_authenticate',
                    'seq': g_seq++});
  return;
}

function callback_authenticate(d)
{
  if (d.error)
    return alert(d.error);

  g_user = d;

  update();
  return;
}

function before_post()  //{{{2
{
  // FIXME: Disable or warn too long tweet.
  return true;
}

function call_twitter_api(base_uri, api_name, parameters)  //{{{2
{
  var ps = [];
  for (var key in parameters)
    ps.push(key + '=' + parameters[key]);

  g_lcds_nodes[api_name] = load_cross_domain_script(
    base_uri + api_name + '.json' + '?' + ps.join('&'),
    g_lcds_nodes[api_name]
 );
}

var g_lcds_nodes = {}

function create_element(element_name)  //{{{2
{
  return $(document.createElement(element_name));
}

function html_from_tweet(tweet)  //{{{2
{
  // FIXME: More information
  return (''
          /* screen name */
          + ''
          + tweet.user.screen_name
          + ''
          /* text */
          + ''
          + tweet.text
          + ''
         );
}

function load_cross_domain_script(uri, node)  //{{{2
{
  if (node && node.parentNode)
    node.parentNode.removeChild(node);

  node = document.createElement("script");
  node.src = uri;
  node.type = "text/javascript";
  document.body.appendChild(node);

  return node;
}

function show_tweets(d, node_column)  //{{{2
{
  // d = [{newest-tweet}, ..., {oldest-tweet}]
  if (d.length == 0)
    return 0;

  var node_tweet_hub = create_element('div');
  var node_dummy_tweet = create_element('div');

  node_tweet_hub.append(node_dummy_tweet);
  node_tweet_hub.addClass('tweet-hub');

  for (var i in d) {
    var node_tweet = create_element('div');
    node_tweet.addClass('tweet');
    node_tweet.html(html_from_tweet(d[i]));
    node_tweet.data('json', d[i]);

    node_tweet_hub.prepend(node_tweet);
  }

  node_dummy_tweet.remove();

  node_column.append(node_tweet_hub);
  return d.length;
}

function update()  //{{{2
{
  if (!g_user)
    return authenticate();

  call_twitter_api(TWITTER_API_URI,
                   'statuses/home_timeline',
                   {'callback': 'callback_update',
                    'count': MAX_COUNT,
                    'seq': g_seq++,
                    'since_id': g_since_id || DUMMY_SINCE_ID});
  return;
}

function callback_update(d)
{
  $('#i_last_updated_time').text('Last updated: ' + new Date().toString());

  if (d.error)
  {
    $('#i_error_message').text(d.error);
    alert(d.error);
    return;
  }

  if (g_since_id) {
    for (var i = 0; i < d.length; i++) {
      if (d[i].id <= g_since_id)
        d.splice(i--, 1);
    }
  }

  var NEWEST_TWEET_INDEX = 0;
  g_since_id = d[NEWEST_TWEET_INDEX].id;

  show_tweets(d, $("#column_home"));
  return;
}

// Main  {{{1

$(document).ready(function(){
  $('#column_home').empty();
  $('#i_error_message').empty();

  var node_iframe = create_element('iframe');
  node_iframe.attr('name', 'xpost');
  node_iframe.attr('src', 'about:blank');
  node_iframe.css('display', 'none');
  $('body').append(node_iframe);
  $('#post_form').attr('target', 'xpost');
  $('#post_form').submit(before_post);

  $('#update_button').click(function(){
    update();
  });
  g_update_timer = setInterval(update, UPDATE_INTERVAL);
});

// __END__  {{{1
// vim: expandtab shiftwidth=2 softtabstop=2
// vim: foldmethod=marker
<commit_msg>Refactor - Add comments on Main<commit_after>// Core of fnfnen.
// Variables  {{{1

var DUMMY_SINCE_ID = 1;
var MAX_COUNT = 200;
var TWITTER_API_URI = 'http://api.twitter.com/1/';
var TWITTER_UI_URI = 'http://twitter.com/';
var UPDATE_INTERVAL = 5 * 60 * 1000;  // in milliseconds

var g_seq = (new Date).getTime();
var g_since_id = null;
var g_update_timer = null;
var g_user = null;

// Code  {{{1
function authenticate()  //{{{2
{
  call_twitter_api(TWITTER_UI_URI,
                   'account/verify_credentials',
                   {'callback': 'callback_authenticate',
                    'seq': g_seq++});
  return;
}

function callback_authenticate(d)
{
  if (d.error)
    return alert(d.error);

  g_user = d;

  update();
  return;
}

function before_post()  //{{{2
{
  // FIXME: Disable or warn too long tweet.
  return true;
}

function call_twitter_api(base_uri, api_name, parameters)  //{{{2
{
  var ps = [];
  for (var key in parameters)
    ps.push(key + '=' + parameters[key]);

  g_lcds_nodes[api_name] = load_cross_domain_script(
    base_uri + api_name + '.json' + '?' + ps.join('&'),
    g_lcds_nodes[api_name]
 );
}

var g_lcds_nodes = {}

function create_element(element_name)  //{{{2
{
  return $(document.createElement(element_name));
}

function html_from_tweet(tweet)  //{{{2
{
  // FIXME: More information
  return (''
          /* screen name */
          + ''
          + tweet.user.screen_name
          + ''
          /* text */
          + ''
          + tweet.text
          + ''
         );
}

function load_cross_domain_script(uri, node)  //{{{2
{
  if (node && node.parentNode)
    node.parentNode.removeChild(node);

  node = document.createElement("script");
  node.src = uri;
  node.type = "text/javascript";
  document.body.appendChild(node);

  return node;
}

function show_tweets(d, node_column)  //{{{2
{
  // d = [{newest-tweet}, ..., {oldest-tweet}]
  if (d.length == 0)
    return 0;

  var node_tweet_hub = create_element('div');
  var node_dummy_tweet = create_element('div');

  node_tweet_hub.append(node_dummy_tweet);
  node_tweet_hub.addClass('tweet-hub');

  for (var i in d) {
    var node_tweet = create_element('div');
    node_tweet.addClass('tweet');
    node_tweet.html(html_from_tweet(d[i]));
    node_tweet.data('json', d[i]);

    node_tweet_hub.prepend(node_tweet);
  }

  node_dummy_tweet.remove();

  node_column.append(node_tweet_hub);
  return d.length;
}

function update()  //{{{2
{
  if (!g_user)
    return authenticate();

  call_twitter_api(TWITTER_API_URI,
                   'statuses/home_timeline',
                   {'callback': 'callback_update',
                    'count': MAX_COUNT,
                    'seq': g_seq++,
                    'since_id': g_since_id || DUMMY_SINCE_ID});
  return;
}

function callback_update(d)
{
  $('#i_last_updated_time').text('Last updated: ' + new Date().toString());

  if (d.error)
  {
    $('#i_error_message').text(d.error);
    alert(d.error);
    return;
  }

  if (g_since_id) {
    for (var i = 0; i < d.length; i++) {
      if (d[i].id <= g_since_id)
        d.splice(i--, 1);
    }
  }

  var NEWEST_TWEET_INDEX = 0;
  g_since_id = d[NEWEST_TWEET_INDEX].id;

  show_tweets(d, $("#column_home"));
  return;
}

// Main  {{{1

$(document).ready(function(){
  // Misc.
  $('#column_home').empty();
  $('#i_error_message').empty();

  // To post.
    // Add a secret iframe to hide interaction with Twitter.
  var node_iframe = create_element('iframe');
  node_iframe.attr('name', 'xpost');
  node_iframe.attr('src', 'about:blank');
  node_iframe.css('display', 'none');
  $('body').append(node_iframe);
  $('#post_form').attr('target', 'xpost');
    // Event handlers.
  $('#post_form').submit(before_post);

  // To update.
  $('#update_button').click(function(){
    update();
  });
  g_update_timer = setInterval(update, UPDATE_INTERVAL);
});

// __END__  {{{1
// vim: expandtab shiftwidth=2 softtabstop=2
// vim: foldmethod=marker
<|endoftext|>


<commit_before>// Copyright (c) 2009, Anton Korenyushkin
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the author nor the names of contributors may be
//       used to endorse or promote products derived from this software
//       without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

(function ()
{
  function publish(constructor, name) {
    constructor.prototype[name] = constructor.prototype['_' + name];
  }

  publish(ak.AK, 'setObjectProp');
  publish(ak.AK, 'compile');
  publish(ak.AK, 'readCode');
  publish(ak.AK, 'hash');
  publish(ak.Script, 'run');
  publish(ak.App, 'call');
  publish(ak.Type, 'int');
  publish(ak.Type, 'serial');
  publish(ak.Type, 'default');
  publish(ak.Type, 'unique');
  publish(ak.Type, 'foreign');
  publish(ak.Type, 'check');
  publish(ak.Query, 'perform');
  publish(ak.Query, 'only');
  publish(ak.Query, 'where');
  publish(ak.Query, 'by');
  publish(ak.SubRel, 'update');
  publish(ak.SubRel, 'del');
  publish(ak.Constrs, 'unique');
  publish(ak.Constrs, 'foreign');
  publish(ak.Constrs, 'check');
  publish(ak.DB, 'query');
  publish(ak.DB, 'createRel');
  publish(ak.DB, 'dropRels');
  publish(ak.Rel, 'insert');
  publish(ak.Rel, 'drop');
  publish(ak.Rel, 'all');
  publish(ak.Rel, 'getInts');
  publish(ak.Rel, 'getSerials');
  publish(ak.Rel, 'getDefaults');
  publish(ak.Rel, 'getUniques');
  publish(ak.Rel, 'getForeigns');
  publish(ak.Data, 'toString');
  publish(ak.FS, 'read');
  publish(ak.FS, 'list');
  publish(ak.FS, 'exists');
  publish(ak.FS, 'isDir');
  publish(ak.FS, 'isFile');
  publish(ak.FS, 'makeDir');
  publish(ak.FS, 'write');
  publish(ak.FS, 'rename');
  publish(ak.FS, 'copyFile');

  ak.appName = ak._appName;

  // Property access modes for ak.setObjectProp
  // Could be combined using '|' operator.
  ak.NONE        = 0;
  ak.READ_ONLY   = 1 << 0;
  ak.DONT_ENUM   = 1 << 1;
  ak.DONT_DELETE = 1 << 2;

  // SubRel is inherited from Query
  ak.SubRel.prototype.__proto__ = ak.Query.prototype;

  // Dates should be in UTC on the server
  Date.prototype.toString = Date.prototype.toUTCString;

  ak.fs.remove = function (path) {
    if (ak.fs.isDir(path)) {
      var children = ak.fs.list(path);
      for (var i = 0; i < children.length; ++i)
        arguments.callee(path + '/' + children[i]);
    }
    ak.fs._remove(path);
  };

  ak.setObjectProp(
    ak.Query.prototype, 'whose', ak.DONT_ENUM,
    function () {
      var query = this.where.apply(this, arguments);
      if (query.length != 1)
        throw Error('whose() query got ' + query.length + ' tuples');
      return query[0];
    });

  ak.setObjectProp(
    ak.Query.prototype, 'field', ak.DONT_ENUM,
    function (name) {
      var query = this.only(name);
      var result = [];
      for (var i = 0; i < query.length; ++i)
        result.push(query[i][name]);
      return result;
    });

  ak.setObjectProp(
    ak.SubRel.prototype, 'set', ak.DONT_ENUM,
    function (obj) {
      var args = [{}];
      var index = 0;
      for (var field in obj) {
        args[0][field] = '$' + (++index);
        args.push(obj[field]);
      }
      return this.update.apply(this, args);
    });

  function makeRelDelegation(func_name) {
    ak.Rel.prototype[func_name] = function () {
      return ak.SubRel.prototype[func_name].apply(this.all(), arguments);
    };
  }

  makeRelDelegation('where');
  makeRelDelegation('whose');
  makeRelDelegation('only');
  makeRelDelegation('by');
  makeRelDelegation('field');
  makeRelDelegation('update');
  makeRelDelegation('updateByValues');
  makeRelDelegation('delete');

  ak.TmpFile.prototype.read = function () {
    return ak.fs.read(this);
  };

  ak.defaultHeaders = {'Content-Type': 'text/html; charser=utf-8'};

  ak.Response = function (content/* = '' */,
                         status/* = 200 */,
                         headers/* = ak.defaultHeaders */) {
    this.content = content || '';
    this.status = status || 200;
    this.headers = headers || ak.defaultHeaders;
  };

  ak._main = function (data) {
    var request = eval('(' + data + ')');
    request.data = ak._data;
    request.files = {};
    // request.fileNames.length and ak._files.length are guaranteed to be equal
    for (var i = 0; i < ak._files.length; ++i)
      request.files[request.fileNames[i]] = ak._files[i];
    delete request.fileNames;
    request.requester = ak._requesterAppName;

    var response = __main__(request);
    var headerLines = [];
    for (var name in response.headers)
      headerLines.push(name + ': ' + response.headers[name]);
    return (response.status + '\n' +
            headerLines.join('\n') +
            '\n\n' + response.content);
  };

})();
<commit_msg>Renamed TmpFile to TempFile.<commit_after>// Copyright (c) 2009, Anton Korenyushkin
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the author nor the names of contributors may be
//       used to endorse or promote products derived from this software
//       without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

(function ()
{
  function publish(constructor, name) {
    constructor.prototype[name] = constructor.prototype['_' + name];
  }

  publish(ak.AK, 'setObjectProp');
  publish(ak.AK, 'compile');
  publish(ak.AK, 'readCode');
  publish(ak.AK, 'hash');
  publish(ak.Script, 'run');
  publish(ak.App, 'call');
  publish(ak.Type, 'int');
  publish(ak.Type, 'serial');
  publish(ak.Type, 'default');
  publish(ak.Type, 'unique');
  publish(ak.Type, 'foreign');
  publish(ak.Type, 'check');
  publish(ak.Query, 'perform');
  publish(ak.Query, 'only');
  publish(ak.Query, 'where');
  publish(ak.Query, 'by');
  publish(ak.SubRel, 'update');
  publish(ak.SubRel, 'del');
  publish(ak.Constrs, 'unique');
  publish(ak.Constrs, 'foreign');
  publish(ak.Constrs, 'check');
  publish(ak.DB, 'query');
  publish(ak.DB, 'createRel');
  publish(ak.DB, 'dropRels');
  publish(ak.Rel, 'insert');
  publish(ak.Rel, 'drop');
  publish(ak.Rel, 'all');
  publish(ak.Rel, 'getInts');
  publish(ak.Rel, 'getSerials');
  publish(ak.Rel, 'getDefaults');
  publish(ak.Rel, 'getUniques');
  publish(ak.Rel, 'getForeigns');
  publish(ak.Data, 'toString');
  publish(ak.FS, 'read');
  publish(ak.FS, 'list');
  publish(ak.FS, 'exists');
  publish(ak.FS, 'isDir');
  publish(ak.FS, 'isFile');
  publish(ak.FS, 'makeDir');
  publish(ak.FS, 'write');
  publish(ak.FS, 'rename');
  publish(ak.FS, 'copyFile');

  ak.appName = ak._appName;

  // Property access modes for ak.setObjectProp
  // Could be combined using '|' operator.
  ak.NONE        = 0;
  ak.READ_ONLY   = 1 << 0;
  ak.DONT_ENUM   = 1 << 1;
  ak.DONT_DELETE = 1 << 2;

  // SubRel is inherited from Query
  ak.SubRel.prototype.__proto__ = ak.Query.prototype;

  // Dates should be in UTC on the server
  Date.prototype.toString = Date.prototype.toUTCString;

  ak.fs.remove = function (path) {
    if (ak.fs.isDir(path)) {
      var children = ak.fs.list(path);
      for (var i = 0; i < children.length; ++i)
        arguments.callee(path + '/' + children[i]);
    }
    ak.fs._remove(path);
  };

  ak.setObjectProp(
    ak.Query.prototype, 'whose', ak.DONT_ENUM,
    function () {
      var query = this.where.apply(this, arguments);
      if (query.length != 1)
        throw Error('whose() query got ' + query.length + ' tuples');
      return query[0];
    });

  ak.setObjectProp(
    ak.Query.prototype, 'field', ak.DONT_ENUM,
    function (name) {
      var query = this.only(name);
      var result = [];
      for (var i = 0; i < query.length; ++i)
        result.push(query[i][name]);
      return result;
    });

  ak.setObjectProp(
    ak.SubRel.prototype, 'set', ak.DONT_ENUM,
    function (obj) {
      var args = [{}];
      var index = 0;
      for (var field in obj) {
        args[0][field] = '$' + (++index);
        args.push(obj[field]);
      }
      return this.update.apply(this, args);
    });

  function makeRelDelegation(func_name) {
    ak.Rel.prototype[func_name] = function () {
      return ak.SubRel.prototype[func_name].apply(this.all(), arguments);
    };
  }

  makeRelDelegation('where');
  makeRelDelegation('whose');
  makeRelDelegation('only');
  makeRelDelegation('by');
  makeRelDelegation('field');
  makeRelDelegation('update');
  makeRelDelegation('updateByValues');
  makeRelDelegation('delete');

  ak.TempFile.prototype.read = function () {
    return ak.fs.read(this);
  };

  ak.defaultHeaders = {'Content-Type': 'text/html; charser=utf-8'};

  ak.Response = function (content/* = '' */,
                         status/* = 200 */,
                         headers/* = ak.defaultHeaders */) {
    this.content = content || '';
    this.status = status || 200;
    this.headers = headers || ak.defaultHeaders;
  };

  ak._main = function (data) {
    var request = eval('(' + data + ')');
    request.data = ak._data;
    request.files = {};
    // request.fileNames.length and ak._files.length are guaranteed to be equal
    for (var i = 0; i < ak._files.length; ++i)
      request.files[request.fileNames[i]] = ak._files[i];
    delete request.fileNames;
    request.requester = ak._requesterAppName;

    var response = __main__(request);
    var headerLines = [];
    for (var name in response.headers)
      headerLines.push(name + ': ' + response.headers[name]);
    return (response.status + '\n' +
            headerLines.join('\n') +
            '\n\n' + response.content);
  };

})();
<|endoftext|>