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

  // bc.vc, shortcut, dirty hack
  $.register({
    rule: {
      host: /^bc\.vc$/,
      query: /^.+(https?:\/\/.+)/,
    },
    start: function (m) {
      $.openLink(m.query[1]);
    },
  });

  // bc.vc, shortcut
  // FIXME may cut hash or query string
  $.register({
    rule: {
      host: /^bc\.vc$/,
      path: /^.+(https?:\/\/.+)$/,
    },
    start: function (m) {
      $.openLink(m.path[1]);
    },
  });

  function decompress (script, unzip) {
    if (!unzip) {
      return script;
    }
    var matches = script.match(/eval(.*)/);
    matches = matches[1];
    script = eval(matches);
    return script;
  }

  function searchScript (unzip) {
    var content = $.$$('script').find(function (script) {
      if (script.innerHTML.indexOf('make_log') < 0) {
        return _.nop;
      }
      return script.innerHTML;
    });
    if (content) {
      return {
        direct: false,
        script: decompress(content.payload, unzip),
      };
    }
    content = $.$$('script').find(function (script) {
      if (script.innerHTML.indexOf('click_log') < 0) {
        return _.nop;
      }
      return script.innerHTML;
    });
    if (content) {
      return {
        direct: true,
        script: decompress(content.payload, unzip),
      };
    }
    throw _.NoPicAdsError('script changed');
  }

  function knockServer (script, dirtyFix) {
    var matches = script.match(/\$.post\('([^']*)'[^{]+(\{opt:'make_log'[^}]+\}\}),/i);
    var make_url = matches[1];
    var make_opts = eval('(' + matches[2] + ')');

    var i = setInterval(function () {
      $.post(make_url, make_opts, function (text) {
        if (dirtyFix) {
          // dirty fix for tr5.in
          text = text.match(/\{.+\}/)[0];
        }
        var jj = JSON.parse(text);
        if (jj.message) {
          clearInterval(i);
          $.openLink(jj.message.url);
        }
      });
    }, 1000);
  }

  function knockServer2 (script) {
    // somehow I must use jQuery AJAX
    var post = unsafeWindow.$.post;
    // mock a fake AJAX function
    unsafeWindow.$.post = function (a, b, c) {
      if (typeof c === 'function') {
        setTimeout(function () {
          var data = {
            error: false,
            message: {
              url: '#',
            },
          };
          c(JSON.stringify(data));
        }, 1000);
      }
    };

    var matches = script.match(/\$.post\('([^']*)'[^{]+(\{opt:'make_log'[^}]+\}\}),/i);
    var make_url = matches[1];
    var make_opts = eval('(' + matches[2] + ')');

    function makeLog () {
        make_opts.opt = 'make_log';
        post(make_url, make_opts, function (text) {
          var data = JSON.parse(text);
          _.info('make_log', data);
          if (!data.message) {
            checksLog();
            return;
          }

          $.openLink(data.message.url);
        });
    }

    function checkLog () {
      make_opts.opt = 'check_log';
      post(make_url, make_opts, function (text) {
        var data = JSON.parse(text);
        _.info('check_log', data);
        if (!data.message) {
          checkLog();
          return;
        }

        makeLog();
      });
    }

    function checksLog () {
      make_opts.opt = 'checks_log';
      post(make_url, make_opts, function () {
        _.info('checks_log');
        checkLog();
      });
    }

    checksLog();
  }

  // bc.vc
  $.register({
    rule: {
      host: /^bc\.vc$/,
      path: /^\/.+/,
    },
    ready: function () {
      $.removeNodes('iframe');

      var result = searchScript(false);
      if (!result.direct) {
        knockServer2(result.script);
      } else {
        result = result.script.match(/top\.location\.href = '([^']+)'/);
        if (!result) {
          throw new _.NoPicAdsError('script changed');
        }
        result = result[1];
        $.openLink(result);
      }
    },
  });

  function run () {
    // prevent redirection by iframe
    $.removeNodes('iframe');

    var result = searchScript(true);
    if (!result.direct) {
      knockServer(result.script);
    } else {
      result = result.script.match(/top\.location\.href='([^']+)'/);
      if (!result) {
        throw new _.NoPicAdsError('script changed');
      }
      result = result[1];
      $.openLink(result);
    }
  }

  // adli.pw
  $.register({
    rule: {
      host: /^adli\.pw$/,
      path: /^\/[^.]+$/,
    },
    ready: run,
  });

  $.register({
    rule: {
      host: /^(adcrun|ysear)\.ch|(fly2url|urlwiz|xafox)\.com|(zpoz|ultry)\.net|(wwy|myam)\.me|ssl\.gs|link\.tl|xip\.ir|hit\.us|shortit\.in|(adbla|tl7)\.us|www\.adjet\.eu|srk\.gs|cun\.bz$/,
      path: /^\/.+/,
    },
    ready: run,
  });

  $.register({
    rule: {
      host: /^adtr\.im$/,
      path: /^\/.+/,
    },
    ready: function(){
      var f = $.$('iframe.fly_frame');
      if (f) {
        $.openLink(f.src);
      } else {
        run();
      }
    }
  });

    $.register({
    rule: {
      host: /^ad5\.eu$/,
      path: /^\/[^.]+$/,
    },
    ready: function() {
      $.removeNodes('iframe');
      var s = searchScript(true);

      // Find the form
      var m = s.script.match(/(<form name="form1"method="post".*(?!<\\form>)<\/form>)/);

      if (!m) {return;}

      m = m[1];

      // Set the correct timezone
      var tz = -(new Date().getTimezoneOffset()/60);
      m = m.replace("'+timezone+'",tz);

      // Wrap the form into a useless div
      var d = document.createElement('div');
      d.setAttribute('id','NoPicAdsFTW');
      d.setAttribute('style', 'display:none;');

      // Feed with the right form
      d.innerHTML = m;
      document.body.appendChild(d);

      // Redirect to next page
      $('#NoPicAdsFTW > form[name=form1]').submit();
    },
  });

  $.register({
    rule: {
      host: /^tr5\.in$/,
      path: /^\/.+/,
    },
    ready: function () {
      $.removeNodes('iframe');

      var content = searchScript();
      var matches = content.match(/eval(.*)/);
      matches = matches[1];
      content = eval(matches);

      knockServer(content, true);
    },
  });

})();

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<commit_msg>Add support for ysear.ch iframed links<commit_after>(function () {
  'use strict';

  // bc.vc, shortcut, dirty hack
  $.register({
    rule: {
      host: /^bc\.vc$/,
      query: /^.+(https?:\/\/.+)/,
    },
    start: function (m) {
      $.openLink(m.query[1]);
    },
  });

  // bc.vc, shortcut
  // FIXME may cut hash or query string
  $.register({
    rule: {
      host: /^bc\.vc$/,
      path: /^.+(https?:\/\/.+)$/,
    },
    start: function (m) {
      $.openLink(m.path[1]);
    },
  });

  function decompress (script, unzip) {
    if (!unzip) {
      return script;
    }
    var matches = script.match(/eval(.*)/);
    matches = matches[1];
    script = eval(matches);
    return script;
  }

  function searchScript (unzip) {
    var content = $.$$('script').find(function (script) {
      if (script.innerHTML.indexOf('make_log') < 0) {
        return _.nop;
      }
      return script.innerHTML;
    });
    if (content) {
      return {
        direct: false,
        script: decompress(content.payload, unzip),
      };
    }
    content = $.$$('script').find(function (script) {
      if (script.innerHTML.indexOf('click_log') < 0) {
        return _.nop;
      }
      return script.innerHTML;
    });
    if (content) {
      return {
        direct: true,
        script: decompress(content.payload, unzip),
      };
    }
    throw _.NoPicAdsError('script changed');
  }

  function knockServer (script, dirtyFix) {
    var matches = script.match(/\$.post\('([^']*)'[^{]+(\{opt:'make_log'[^}]+\}\}),/i);
    var make_url = matches[1];
    var make_opts = eval('(' + matches[2] + ')');

    var i = setInterval(function () {
      $.post(make_url, make_opts, function (text) {
        if (dirtyFix) {
          // dirty fix for tr5.in
          text = text.match(/\{.+\}/)[0];
        }
        var jj = JSON.parse(text);
        if (jj.message) {
          clearInterval(i);
          $.openLink(jj.message.url);
        }
      });
    }, 1000);
  }

  function knockServer2 (script) {
    // somehow I must use jQuery AJAX
    var post = unsafeWindow.$.post;
    // mock a fake AJAX function
    unsafeWindow.$.post = function (a, b, c) {
      if (typeof c === 'function') {
        setTimeout(function () {
          var data = {
            error: false,
            message: {
              url: '#',
            },
          };
          c(JSON.stringify(data));
        }, 1000);
      }
    };

    var matches = script.match(/\$.post\('([^']*)'[^{]+(\{opt:'make_log'[^}]+\}\}),/i);
    var make_url = matches[1];
    var make_opts = eval('(' + matches[2] + ')');

    function makeLog () {
        make_opts.opt = 'make_log';
        post(make_url, make_opts, function (text) {
          var data = JSON.parse(text);
          _.info('make_log', data);
          if (!data.message) {
            checksLog();
            return;
          }

          $.openLink(data.message.url);
        });
    }

    function checkLog () {
      make_opts.opt = 'check_log';
      post(make_url, make_opts, function (text) {
        var data = JSON.parse(text);
        _.info('check_log', data);
        if (!data.message) {
          checkLog();
          return;
        }

        makeLog();
      });
    }

    function checksLog () {
      make_opts.opt = 'checks_log';
      post(make_url, make_opts, function () {
        _.info('checks_log');
        checkLog();
      });
    }

    checksLog();
  }

  // bc.vc
  $.register({
    rule: {
      host: /^bc\.vc$/,
      path: /^\/.+/,
    },
    ready: function () {
      $.removeNodes('iframe');

      var result = searchScript(false);
      if (!result.direct) {
        knockServer2(result.script);
      } else {
        result = result.script.match(/top\.location\.href = '([^']+)'/);
        if (!result) {
          throw new _.NoPicAdsError('script changed');
        }
        result = result[1];
        $.openLink(result);
      }
    },
  });

  function run () {
    // prevent redirection by iframe
    $.removeNodes('iframe');

    var result = searchScript(true);
    if (!result.direct) {
      knockServer(result.script);
    } else {
      result = result.script.match(/top\.location\.href='([^']+)'/);
      if (!result) {
        throw new _.NoPicAdsError('script changed');
      }
      result = result[1];
      $.openLink(result);
    }
  }

  // adli.pw
  $.register({
    rule: {
      host: /^adli\.pw$/,
      path: /^\/[^.]+$/,
    },
    ready: run,
  });

  $.register({
    rule: {
      host: /^adcrun\.ch|(fly2url|urlwiz|xafox)\.com|(zpoz|ultry)\.net|(wwy|myam)\.me|ssl\.gs|link\.tl|xip\.ir|hit\.us|shortit\.in|(adbla|tl7)\.us|www\.adjet\.eu|srk\.gs|cun\.bz$/,
      path: /^\/.+/,
    },
    ready: run,
  });

  $.register({
    rule: {
      host: /^adtr\.im|ysear\.ch$/,
      path: /^\/.+/,
    },
    ready: function(){
      var f = $.$('iframe.fly_frame');
      if (f) {
        $.openLink(f.src);
      } else {
        run();
      }
    }
  });

    $.register({
    rule: {
      host: /^ad5\.eu$/,
      path: /^\/[^.]+$/,
    },
    ready: function() {
      $.removeNodes('iframe');
      var s = searchScript(true);

      // Find the form
      var m = s.script.match(/(<form name="form1"method="post".*(?!<\\form>)<\/form>)/);

      if (!m) {return;}

      m = m[1];

      // Set the correct timezone
      var tz = -(new Date().getTimezoneOffset()/60);
      m = m.replace("'+timezone+'",tz);

      // Wrap the form into a useless div
      var d = document.createElement('div');
      d.setAttribute('id','NoPicAdsFTW');
      d.setAttribute('style', 'display:none;');

      // Feed with the right form
      d.innerHTML = m;
      document.body.appendChild(d);

      // Redirect to next page
      $('#NoPicAdsFTW > form[name=form1]').submit();
    },
  });

  $.register({
    rule: {
      host: /^tr5\.in$/,
      path: /^\/.+/,
    },
    ready: function () {
      $.removeNodes('iframe');

      var content = searchScript();
      var matches = content.match(/eval(.*)/);
      matches = matches[1];
      content = eval(matches);

      knockServer(content, true);
    },
  });

})();

// ex: ts=2 sts=2 sw=2 et
// sublime: tab_size 2; translate_tabs_to_spaces true; detect_indentation false; use_tab_stops true;
// kate: space-indent on; indent-width 2;
<|endoftext|>


<commit_before>/*!Private
 TODO:？？？ path  转换path描述？？？
 Todo: 多个canvas同时执行动画 test
 Todo: 中断某个元素的动画
 Todo: 增加一组元素的动画，只设置一个CallBack

    animator = new Animator();

    matrix属性: scale, rotate, translate, transform

    attr属性:

    //group
    el.animate(object, number, function);

    el.animate({
      scale: [x, y],
      rotate: [a, x, y],
      opacity: value
    }, step, function(){});

    //callback
    el.animate({}, function(){});

 */
(function() {
  var lastTime = 0,
    vendors = ['webkit', 'moz', 'o', 'ms'],
    x,
    l,
    currTime,
    time2call,
    id;

  for(x = 0, l = vendors.length; x < l && !window.requestAnimationFrame; ++x) {
    SI.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
    SI.cancelAnimationFrame =
      window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
  }

  if (!SI.requestAnimationFrame){
    SI.requestAnimationFrame = function(callback, element) {
      currTime = Date.now();
      time2call = Math.max(0, 16 - (currTime - lastTime));
      id = window.setTimeout(function() { callback(currTime + time2call); },
        time2call);
      lastTime = currTime + time2call;
      return id;
    };
  }

  if (!SI.cancelAnimationFrame){
    SI.cancelAnimationFrame = function(id) {
      clearTimeout(id);
    };
  }
}());

var Animator = new Class;
Animator.include({
  init: function(){
    this.amtArr = [];
    this.stamp = null;
    this.timer = null;
    this.timeDiff = 1;
  },
  add: function(el, arr){
    var self = this,
      amtArr = self.amtArr,
      oldStatus = amtArr.length,
      _id = 'ani_' + getUniqId(),
      hl = arr[1]||500,
      cfg = el.cfg,
      am = extend(true, {}, arr[0]),
      cb = arr[2] || function(){},
      k,
      v;

    for(k in am){
      v = am[k];
      switch(k){
        case 'translate':
          am[k] = {
            st: [v[0]/hl, v[1]/hl],
            src: [0, 0],
            tar: v
          };
          break;
        case 'rotate':
          v[1]= v[1] || 0;
          v[2] = v[2] || 0;
          am[k] = {
            st: [v[0]/hl, 0, 0],
            src: [0, v[1], v[2]],
            tar: v
          };
          break;
        case 'scale':
          v[1] = v[1] || v[0];
          v[2] = v[2] || 0;
          v[3] = v[3] || 0;
          am[k] = {
            st: [ (v[0]-1)/hl, (v[1]-1)/hl, 0, 0 ],
            src: [1, 1, v[2], v[3]],
            tar: v
          };
          break;
        case 'fillStyle':
        case 'strokeStyle':
          cfg[k] = hex2num(cfg[k] || '#fff');
          v = hex2num(v);
          am[k] = {
            src: cfg[k],
            st: [(v[0] - cfg[k][0])/hl, (v[1] - cfg[k][1])/hl, (v[2] - cfg[k][2])/hl],
            tar: v
          };
          break;
        default:
          cfg[k] = cfg[k] || 0;
          am[k] = {
            src: cfg[k],
            st: [(v[0] - cfg[k][0])/hl, (v[1] - cfg[k][1])/hl, (v[2] - cfg[k][2])/hl],
            tar: v
          };
          break;
      }
    }

    amtArr.push([el, am, hl, cb, Date.now(), _id]);
    if(oldStatus == 0){ //不为0则有action在执行
      self.action();
    }
    return _id;
  },
  remove: function(_id){
    var amtArr = this.amtArr,
      len = amtArr.length;
    while(len--){
      if(amtArr[5] == _id) amtArr.splice(i, 1);
    }
  },
  pause: function(){
    this.pauseArr = this.amtArr;
    this.pauseStamp = Date.now();
    this.amtArr = [];
  },
  process: function(){
    var amtAttr = this.pauseArr,
      pauseTime = Date.now() - this.pauseStamp,
      len = amtAttr.length;
    while(len--){
      amtAttr[len][4] += pauseTime;
    }
    this.amtArr = amtAttr;
    this.pauseArr = [];
    this.timeDiff = 1;
    this.checkStatus();
  },
  abort: function(){
    this.init();
  },
  action: function(){
    var self = this,
      amtArr = self.amtArr,
      td = self.timeDiff,
      el,
      paper,
      am,
      hl,
      cb,
      src,
      st,
      tar,
      tem,
      pt,
      done,
      len,
      i,
      v,
      k,
      val;
    self.stamp = Date.now();

    len = amtArr.length;

    while(len--){
      v = amtArr[len];
      el = v[0];
      am = v[1];
      hl = v[2];
      cb = v[3];
      stime = v[4];
      pt = (self.stamp - stime);
      done = (hl <= pt);
      el.matrix = [1, 0, 0, 1, 0, 0];
      paper = el.paper;

      for(k in am){
        val = am[k];
        src = val.src;
        st = val.st;
        tar = val.tar;
        if(k.search(/scale|rotate|translate|transform/) != -1){
          if(done){
            el[k].apply(el, tar);
          }else{
            i = src.length;
            while(i--){
              src[i] += (st[i] * td);
            }
            el[k].apply(el, src);
          }
        }else if(k.search(/fillStyle|strokeStyle|shadowColor/) != -1){
          tem = {};
          if(done){
            tem[k] = rgb2hex.apply(this, tar);
            el.attr(tem);
          }else{
            i = src.length;
            while(i--){
              src[i] += (st[i] * td);
            }
            tem[k] = rgb2hex.apply(this, src);
            el.attr(tem);
          }
        }else{
          tem = {};
          if(done){
            tem[k] = tar;
            el.attr(tem);
          }else{
            src += (st * td);
            tem[k] = src;
            el.attr(tem);
            val.src = src;
          }
        }

      }
      paper.render();
      if(done){
        amtArr.splice(len, 1);
        cb.call(el);
      }
    }
    SI.cancelAnimationFrame(self.timer);
    self.timer = SI.requestAnimationFrame(function(){
      self.timeDiff = Date.now() - self.stamp;
      self.checkStatus();
    });
  },
  checkStatus: function(){
    var self = this;
    if(self.amtArr.length !== 0){
      self.action();
    }else{
      self.init();
    }
  }
});

//主动画控制器
var sanimator = new Animator();
<commit_msg>修正一些小bug<commit_after>/*!Private
 TODO:？？？ path  转换path描述？？？
 Todo: 多个canvas同时执行动画 test
 Todo: 中断某个元素的动画
 Todo: 增加一组元素的动画，只设置一个CallBack

    animator = new Animator();

    matrix属性: scale, rotate, translate, transform

    attr属性:

    //group
    el.animate(object, number, function);

    el.animate({
      scale: [x, y],
      rotate: [a, x, y],
      opacity: value
    }, step, function(){});

    //callback
    el.animate({}, function(){});

 */
(function() {
  var lastTime = 0,
    vendors = ['webkit', 'moz', 'o', 'ms'],
    x,
    l,
    currTime,
    time2call,
    id;

  for(x = 0, l = vendors.length; x < l && !window.requestAnimationFrame; ++x) {
    SI.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
    SI.cancelAnimationFrame =
      window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
  }

  if (!SI.requestAnimationFrame){
    SI.requestAnimationFrame = function(callback) {
      currTime = Date.now();
      time2call = Math.max(0, 16 - (currTime - lastTime));
      id = window.setTimeout(function() { callback(currTime + time2call); },
        time2call);
      lastTime = currTime + time2call;
      return id;
    };
  }

  if (!SI.cancelAnimationFrame){
    SI.cancelAnimationFrame = function(id) {
      clearTimeout(id);
    };
  }
}());

var Animator = new Class;
Animator.include({
  init: function(){
    this.amtArr = [];
    this.stamp = null;
    this.timer = null;
    this.timeDiff = 1;
  },
  add: function(el, arr){
    var self = this,
      amtArr = self.amtArr,
      oldStatus = amtArr.length,
      _id = 'ani_' + getUniqId(),
      hl = arr[1]||500,
      cfg = el.cfg,
      am = extend(true, {}, arr[0]),
      cb = arr[2] || function(){},
      k,
      v;

    for(k in am){
      v = am[k];
      switch(k){
        case 'translate':
          am[k] = {
            st: [v[0]/hl, v[1]/hl],
            src: [0, 0],
            tar: v
          };
          break;
        case 'rotate':
          v[1]= v[1] || 0;
          v[2] = v[2] || 0;
          am[k] = {
            st: [v[0]/hl, 0, 0],
            src: [0, v[1], v[2]],
            tar: v
          };
          break;
        case 'scale':
          v[1] = v[1] || v[0];
          v[2] = v[2] || 0;
          v[3] = v[3] || 0;
          am[k] = {
            st: [ (v[0]-1)/hl, (v[1]-1)/hl, 0, 0 ],
            src: [1, 1, v[2], v[3]],
            tar: v
          };
          break;
        case 'fillStyle':
        case 'strokeStyle':
          cfg[k] = hex2num(cfg[k] || '#fff');
          v = hex2num(v);
          am[k] = {
            src: cfg[k],
            st: [(v[0] - cfg[k][0])/hl, (v[1] - cfg[k][1])/hl, (v[2] - cfg[k][2])/hl],
            tar: v
          };
          break;
        default:
          cfg[k] = cfg[k] || 0;
          am[k] = {
            src: cfg[k],
            st: [(v[0] - cfg[k][0])/hl, (v[1] - cfg[k][1])/hl, (v[2] - cfg[k][2])/hl],
            tar: v
          };
          break;
      }
    }

    amtArr.push([el, am, hl, cb, Date.now(), _id]);
    if(oldStatus == 0){ //不为0则有action在执行
      self.action();
    }
    return _id;
  },
  remove: function(_id){
    var amtArr = this.amtArr,
      len = amtArr.length;
    while(len--){
      if(amtArr[5] == _id) amtArr.splice(len, 1);
    }
  },
  pause: function(){
    this.pauseArr = this.amtArr;
    this.pauseStamp = Date.now();
    this.amtArr = [];
  },
  process: function(){
    var amtAttr = this.pauseArr,
      pauseTime = Date.now() - this.pauseStamp,
      len = amtAttr.length;
    while(len--){
      amtAttr[len][4] += pauseTime;
    }
    this.amtArr = amtAttr;
    this.pauseArr = [];
    this.timeDiff = 1;
    this.checkStatus();
  },
  abort: function(){
    this.init();
  },
  action: function(){
    var self = this,
      amtArr = self.amtArr,
      td = self.timeDiff,
      el,
      paper,
      am,
      hl,
      cb,
      src,
      st,
      tar,
      tem,
      pt,
      done,
      len,
      i,
      v,
      k,
      sTime,
      val,
      selfStamp;

    selfStamp = self.stamp = Date.now();

    len = amtArr.length;

    while(len--){
      v = amtArr[len];
      el = v[0];
      am = v[1];
      hl = v[2];
      cb = v[3];
      sTime = v[4];
      pt = (selfStamp - sTime);
      done = (hl <= pt);
      el.matrix = [1, 0, 0, 1, 0, 0];
      paper = el.paper;

      for(k in am){
        val = am[k];
        src = val.src;
        st = val.st;
        tar = val.tar;
        if(k.search(/scale|rotate|translate|transform/) != -1){
          if(done){
            el[k].apply(el, tar);
          }else{
            i = src.length;
            while(i--){
              src[i] += (st[i] * td);
            }
            el[k].apply(el, src);
          }
        }else if(k.search(/fillStyle|strokeStyle|shadowColor/) != -1){
          tem = {};
          if(done){
            tem[k] = rgb2hex.apply(this, tar);
            el.attr(tem);
          }else{
            i = src.length;
            while(i--){
              src[i] += (st[i] * td);
            }
            tem[k] = rgb2hex.apply(this, src);
            el.attr(tem);
          }
        }else{
          tem = {};
          if(done){
            tem[k] = tar;
            el.attr(tem);
          }else{
            src += (st * td);
            tem[k] = src;
            el.attr(tem);
            val.src = src;
          }
        }

      }
      paper.render();
      if(done){
        amtArr.splice(len, 1);
        cb.call(el);
      }
    }
    SI.cancelAnimationFrame(self.timer);
    self.timer = SI.requestAnimationFrame(function(){
      self.timeDiff = Date.now() - self.stamp;
      self.checkStatus();
    });
  },
  checkStatus: function(){
    var self = this;
    if(self.amtArr.length !== 0){
      self.action();
    }else{
      self.init();
    }
  }
});

//主动画控制器
var sanimator = new Animator();
<|endoftext|>


<commit_before>/* SmartCollection
 * (c) 2015 by StackEngine under the MIT license
 */

angular.module('SmartCollection', [])
.factory('SmartCollection', function($http){
  return function(config) {

    var loaded = false;
    var routes = config.routes || {};
    var key = config.key || 'id';
    var items = [];
    var itemIndex = {};
    var pendingItems = {};
    var promises = {};
    var model = config.model || (function GenericModel(attrs) {
      var self = this;
      angular.forEach(attrs, function(value, key) {
        self[key] = value;
      });
    });

    // PRIVATE INTERFACE ------------------------------------------------

    var performRequest = function(routeName, item) {
      var collection = this;
      var route = routes[routeName];

      // Do some sanity checking to make sure required values exist.
      if (!route) throw "Unknown route named '"+routeName+"'";
      angular.forEach(['url', 'method'], function(key) {
        if (!route[key]) {
          throw "Route '"+routeName+"' does not have required parameter: "+key;
        }
      });

      // Convert plain a plain key item to an object so we support both query types
      if (typeof item !== 'object') {
        var obj = {};
        obj[key] = item;
        item = obj;
      }

      // Compose the URL we will be using.
      var url = route.url;
      if (typeof url == 'function') {
        url = route.url.call();
      }
      url = composeUrl(item, url, route.urlKeys);

      // If a request is already in process for this route, lets just
      // piggyback.  Instead of issuing another request, just return the
      // previous promise.
      var promiseKey = route.method+' '+url;
      if (promises[promiseKey]) {
        return promises[promiseKey];
      }

      // Transform the parameters if necessary.
      var params = angular.copy(item);
      if (route.transformRequestData) {
        params = route.transformRequestData(item);
      }
      if (route.requestPrefix) {
        var newParams = {};
        newParams[route.requestPrefix] = params;
        params = newParams;
      }

      var promise = $http[route.method](url, params)
        .then(function(response) {
          var data = response.data;
          if (route.responsePrefix) {
            data = data[route.responsePrefix];
          }
          if (route.transformResponseData) {
            data = route.transformResponseData(response.data, item)
          }

          // GET requests will set loaded to true.  This is just a convenience
          // way to know if items have been retrieved.
          if (route.method.toLowerCase() == 'get') {
            loaded = true;
          }

          if (route.responseType == 'array') {
            updateAllItems(data);
            return items;
          } else if (route.responseType == 'one') {
            updateOneItem(data);
            return items[data[key]];
          } else if (route.responseType == 'remove') {
            // Ignores the response from the API but removes the item from our
            // collection.
            removeItem(item);
            return items;
          } else if (route.responseType == 'ignore' || typeof response.routeType == 'undefined') {
            // By default we will ignore everything sent back from the API.
            return data;
          } else {
            throw "Unknown route responseType '"+route.responseType+"' for route "+routeName;
          }
        })
        .finally(function() {
          // clean up after ourselves -- since this request is complete, remove
          // our cached promise reference so future requests to this route will
          // generate a new request.
          delete promises[promiseKey];
        });

      promises[promiseKey] = promise;
      return promise;
    };

    var updateAllItems = function(data) {
      // Add new items and update existing items with new values
      var currentKeys = {};
      angular.forEach(data, function(item) {
        updateOneItem(item);
        currentKeys[item[key]] = 1;
      });
      // Remove items from the array and index.
      for (var i=0; i < items.length; i++) {
        var currentItem = items[i]
        if (!currentKeys[currentItem[key]]) {
          items.splice(i, 1);
          delete itemIndex[currentItem[key]];
          i--; // decrement since we removed one value from the array
        }
      }
    };

    var updateOneItem = function(data) {
      injectItem(new model(data));
    };

    var removeItem = function(item) {
      for (var i=0; i < items.length; i++) {
        var currentItem = items[i];
        if (currentItem[key] == item[key]) {
          items.splice(i, 1);
          delete itemIndex[currentItem[key]]
          return;
        }
      }
    };

    var injectItem = function(item) {
      if (itemIndex[item[key]]) {
        angular.extend(itemIndex[item[key]], item);
      } else if (pendingItems[item[key]]) {
        itemIndex[item[key]] = angular.extend(pendingItems[item[key]], item);
        items.push(itemIndex[item[key]]);
        delete pendingItems[item[key]];
      } else {
        itemIndex[item[key]] = item;
        items.push(item);
      }
    };

    // Takes a url pattern and replaces variables with values from item as
    // mapped by the keys hash.  For example "/users/:id" becomes "/users/3".
    var composeUrl = function(item, url, keys) {
      var matches;
      while (matches = url.match(/:([^\/\?$]+)/)) {
        url = url.replace(matches[0], item[matches[1]]);
      }
      return url;
    };

    // PUBLIC INTERFACE ------------------------------------------------

    var SmartCollection = function() {};
    SmartCollection.prototype.items = function() { return items; };
    SmartCollection.prototype.item = function(keyValue) {
      var pendingObj = null;
      if (typeof keyValue == 'object') {
        pendingObj = keyValue;
        keyValue = pendingObj[key];
      }

      if (typeof itemIndex[keyValue] !== 'undefined') {
        return itemIndex[keyValue];
      } else if (typeof pendingItems[keyValue] !== 'undefined') {
        return pendingItems[keyValue];
      } else {
        var obj = pendingObj || {};
        obj[key] = keyValue;
        pendingItems[keyValue] = new model(obj);
        return pendingItems[keyValue];
      }
    };

    // Create a function for each route dynamically
    angular.forEach(routes, function(route, routeName) {
      if (SmartCollection.prototype[routeName])
        throw "Cannot create a route using reserved name '"+routeName+"'";
      SmartCollection.prototype[routeName] = function(item) {
        return performRequest(routeName, item);
      };
    });

    return new SmartCollection();
  };
});
<commit_msg>pull id from object after it has been transformed<commit_after>/* SmartCollection
 * (c) 2015 by StackEngine under the MIT license
 */

angular.module('SmartCollection', [])
.factory('SmartCollection', function($http){
  return function(config) {

    var loaded = false;
    var routes = config.routes || {};
    var key = config.key || 'id';
    var items = [];
    var itemIndex = {};
    var pendingItems = {};
    var promises = {};
    var model = config.model || (function GenericModel(attrs) {
      var self = this;
      angular.forEach(attrs, function(value, key) {
        self[key] = value;
      });
    });

    // PRIVATE INTERFACE ------------------------------------------------

    var performRequest = function(routeName, item) {
      var collection = this;
      var route = routes[routeName];

      // Do some sanity checking to make sure required values exist.
      if (!route) throw "Unknown route named '"+routeName+"'";
      angular.forEach(['url', 'method'], function(key) {
        if (!route[key]) {
          throw "Route '"+routeName+"' does not have required parameter: "+key;
        }
      });

      // Convert plain a plain key item to an object so we support both query types
      if (typeof item !== 'object') {
        var obj = {};
        obj[key] = item;
        item = obj;
      }

      // Compose the URL we will be using.
      var url = route.url;
      if (typeof url == 'function') {
        url = route.url.call();
      }
      url = composeUrl(item, url, route.urlKeys);

      // If a request is already in process for this route, lets just
      // piggyback.  Instead of issuing another request, just return the
      // previous promise.
      var promiseKey = route.method+' '+url;
      if (promises[promiseKey]) {
        return promises[promiseKey];
      }

      // Transform the parameters if necessary.
      var params = angular.copy(item);
      if (route.transformRequestData) {
        params = route.transformRequestData(item);
      }
      if (route.requestPrefix) {
        var newParams = {};
        newParams[route.requestPrefix] = params;
        params = newParams;
      }

      var promise = $http[route.method](url, params)
        .then(function(response) {
          var data = response.data;
          if (route.responsePrefix) {
            data = data[route.responsePrefix];
          }
          if (route.transformResponseData) {
            data = route.transformResponseData(response.data, item)
          }

          // GET requests will set loaded to true.  This is just a convenience
          // way to know if items have been retrieved.
          if (route.method.toLowerCase() == 'get') {
            loaded = true;
          }

          if (route.responseType == 'array') {
            updateAllItems(data);
            return items;
          } else if (route.responseType == 'one') {
            updateOneItem(data);
            return items[data[key]];
          } else if (route.responseType == 'remove') {
            // Ignores the response from the API but removes the item from our
            // collection.
            removeItem(item);
            return items;
          } else if (route.responseType == 'ignore' || typeof response.routeType == 'undefined') {
            // By default we will ignore everything sent back from the API.
            return data;
          } else {
            throw "Unknown route responseType '"+route.responseType+"' for route "+routeName;
          }
        })
        .finally(function() {
          // clean up after ourselves -- since this request is complete, remove
          // our cached promise reference so future requests to this route will
          // generate a new request.
          delete promises[promiseKey];
        });

      promises[promiseKey] = promise;
      return promise;
    };

    var updateAllItems = function(data) {
      // Add new items and update existing items with new values
      var currentKeys = {};
      angular.forEach(data, function(item) {
        var model = updateOneItem(item);
        currentKeys[model[key]] = 1;
      });
      // Remove items from the array and index.
      for (var i=0; i < items.length; i++) {
        var currentItem = items[i]
        if (!currentKeys[currentItem[key]]) {
          items.splice(i, 1);
          delete itemIndex[currentItem[key]];
          i--; // decrement since we removed one value from the array
        }
      }
    };

    var updateOneItem = function(data) {
      var item = new model(data);
      injectItem(item);
      return item;
    };

    var removeItem = function(item) {
      for (var i=0; i < items.length; i++) {
        var currentItem = items[i];
        if (currentItem[key] == item[key]) {
          items.splice(i, 1);
          delete itemIndex[currentItem[key]]
          return;
        }
      }
    };

    var injectItem = function(item) {
      if (itemIndex[item[key]]) {
        angular.extend(itemIndex[item[key]], item);
      } else if (pendingItems[item[key]]) {
        itemIndex[item[key]] = angular.extend(pendingItems[item[key]], item);
        items.push(itemIndex[item[key]]);
        delete pendingItems[item[key]];
      } else {
        itemIndex[item[key]] = item;
        items.push(item);
      }
    };

    // Takes a url pattern and replaces variables with values from item as
    // mapped by the keys hash.  For example "/users/:id" becomes "/users/3".
    var composeUrl = function(item, url, keys) {
      var matches;
      while (matches = url.match(/:([^\/\?$]+)/)) {
        url = url.replace(matches[0], item[matches[1]]);
      }
      return url;
    };

    // PUBLIC INTERFACE ------------------------------------------------

    var SmartCollection = function() {};
    SmartCollection.prototype.items = function() { return items; };
    SmartCollection.prototype.item = function(keyValue) {
      var pendingObj = null;
      if (typeof keyValue == 'object') {
        pendingObj = keyValue;
        keyValue = pendingObj[key];
      }

      if (typeof itemIndex[keyValue] !== 'undefined') {
        return itemIndex[keyValue];
      } else if (typeof pendingItems[keyValue] !== 'undefined') {
        return pendingItems[keyValue];
      } else {
        var obj = pendingObj || {};
        obj[key] = keyValue;
        pendingItems[keyValue] = new model(obj);
        return pendingItems[keyValue];
      }
    };

    // Create a function for each route dynamically
    angular.forEach(routes, function(route, routeName) {
      if (SmartCollection.prototype[routeName])
        throw "Cannot create a route using reserved name '"+routeName+"'";
      SmartCollection.prototype[routeName] = function(item) {
        return performRequest(routeName, item);
      };
    });

    return new SmartCollection();
  };
});
<|endoftext|>


<commit_before>(function($) {
"use strict";

if (Echo.AppServer.Dashboard.isDefined("Echo.Apps.Spacer.Dashboard")) return;

var dashboard = Echo.AppServer.Dashboard.manifest("Echo.Apps.Spacer.Dashboard");

dashboard.inherits = Echo.Utils.getComponent("Echo.AppServer.Dashboards.AppSettings");

dashboard.config = {
	"ecl": [{
		"name": "height",
		"type": "string",
		"component": "Input",
		"default": "0",
		"config": {
			"title": "Height (in pixels)",
			"desc": "Specifies the height of the horizontal line"
		}
	}]
};

dashboard.init = function() {
	this.parent();
};

Echo.AppServer.Dashboard.create(dashboard);

})(Echo.jQuery);
<commit_msg>Default height according to spec<commit_after>(function($) {
"use strict";

if (Echo.AppServer.Dashboard.isDefined("Echo.Apps.Spacer.Dashboard")) return;

var dashboard = Echo.AppServer.Dashboard.manifest("Echo.Apps.Spacer.Dashboard");

dashboard.inherits = Echo.Utils.getComponent("Echo.AppServer.Dashboards.AppSettings");

dashboard.config = {
	"ecl": [{
		"name": "height",
		"type": "string",
		"component": "Input",
		"default": "30",
		"config": {
			"title": "Height (in pixels)",
			"desc": "Specifies the height of the horizontal line"
		}
	}]
};

dashboard.init = function() {
	this.parent();
};

Echo.AppServer.Dashboard.create(dashboard);

})(Echo.jQuery);
<|endoftext|>


<commit_before>// --------------------------------------------------------------------
// ----------------------      GitGraph         -----------------------
// --------------------------------------------------------------------

function GitGraph (options) {
  // Options
  options = options || {};

  this.elementId = options.elementId || "gitGraph";
  this.colors = options.colors || ["#6963FF", "#47E8D4", "#6BDB52", "#E84BA5", "#FFA657"];

  // Canvas init
  var canvas = document.getElementById(this.elementId);
  this.context = canvas.getContext('2d');

  // Navigations vars
  this.HEAD = null;
  this.branchs = [];
}

GitGraph.prototype.branch = function (options) {
  options = options || {};
  options.context = this.context;
  options.colors = this.colors;
  options.parentBranch = options.parentBranch || this.HEAD;
  options.parent = this;

  var branch = new Branch(options);
  this.branchs.push(branch);

  return branch;
}

// --------------------------------------------------------------------
// ----------------------        Branch         -----------------------
// --------------------------------------------------------------------

/**
 * Main Branch construtor
 *
 * @param {Object} options
 **/
function Branch(options) {
  // Options
  options = options || {};

  this.parent = options.parent;
  this.parentBranch = options.parentBranch;
  this.targetBranch = options.targetBranch;
  this.context = options.context;
  this.name = options.name || "no-name";
  this.origin = options.origin || 300;
  this.size = options.size || 10;
  this.lineWidth = options.lineWidth || 2;

  // Calcul column number for auto-color & auto-offset
  this.column = 0;
  this.calculColumn();

  // Options with auto value
  this.offsetX = options.offsetX || 20 + this.column * 20;
  this.color = options.color || options.colors[this.column];

  // Defaults values
  this.smoothOffset = 50; // Size of merge/fork portion
  this.commits = [];

  this.draw();
  this.checkout();
}

/**
 * Draw the branch
 **/
Branch.prototype.draw = function () {
  // Fork part
  if (this.parentBranch) {
    this.context.beginPath();
    this.context.moveTo(this.offsetX, this.origin);
    this.context.bezierCurveTo(
      this.offsetX, this.origin + this.smoothOffset / 2,
      this.parentBranch.offsetX, this.origin + this.smoothOffset / 2,
      this.parentBranch.offsetX, this.origin + this.smoothOffset);
    this.context.lineWidth = this.lineWidth;
    this.context.strokeStyle = this.color;
    this.context.stroke()
  }

  // Main part
  this.context.beginPath();
  this.context.moveTo(this.offsetX, this.origin);
  this.context.lineTo(this.offsetX, this.origin - this.size);
  this.context.lineWidth = this.lineWidth;
  this.context.strokeStyle = this.color;
  this.context.stroke();

  // Merge part
  if (this.targetBranch) {
    this.context.beginPath();
    this.context.moveTo(this.offsetX, this.origin - this.size);
    this.context.bezierCurveTo(
      this.offsetX, this.origin - this.size - this.smoothOffset / 2,
      this.targetBranch.offsetX, this.origin - this.size - this.smoothOffset / 2,
      this.targetBranch.offsetX, this.origin - this.size - this.smoothOffset);
    this.context.lineWidth = this.lineWidth;
    this.context.strokeStyle = this.color;
    this.context.stroke()
  }
}

/**
 * Checkout onto this branch
 **/
Branch.prototype.checkout = function () {
  this.parent.HEAD = this;
}

/**
 * Merge branch
 *
 * @param {Branch} target
 **/
Branch.prototype.merge = function (target) {
  this.targetBranch = target || this.parent.HEAD;
  this.draw();
}

/**
 * Calcul column
 **/
Branch.prototype.calculColumn = function () {
  for (var i = 0; i < this.parent.branchs.length; i++ ) {
    if (this.parent.branchs[i].origin - this.parent.branchs[i].size - this.parent.branchs[i].smoothOffset * 2 < this.origin)
      this.column++;
  }
  console.log('[' + this.name + '] column:' +this.column);
}<commit_msg>Space harmonization<commit_after>// --------------------------------------------------------------------
// ----------------------      GitGraph         -----------------------
// --------------------------------------------------------------------

function GitGraph(options) {
  // Options
  options = options || {};

  this.elementId = options.elementId || "gitGraph";
  this.colors = options.colors || ["#6963FF", "#47E8D4", "#6BDB52", "#E84BA5", "#FFA657"];

  // Canvas init
  var canvas = document.getElementById(this.elementId);
  this.context = canvas.getContext('2d');

  // Navigations vars
  this.HEAD = null;
  this.branchs = [];
}

GitGraph.prototype.branch = function (options) {
  options = options || {};
  options.context = this.context;
  options.colors = this.colors;
  options.parentBranch = options.parentBranch || this.HEAD;
  options.parent = this;

  var branch = new Branch(options);
  this.branchs.push(branch);

  return branch;
}

// --------------------------------------------------------------------
// ----------------------        Branch         -----------------------
// --------------------------------------------------------------------

/**
 * Main Branch construtor
 *
 * @param {Object} options
 **/
function Branch(options) {
  // Options
  options = options || {};

  this.parent = options.parent;
  this.parentBranch = options.parentBranch;
  this.targetBranch = options.targetBranch;
  this.context = options.context;
  this.name = options.name || "no-name";
  this.origin = options.origin || 300;
  this.size = options.size || 10;
  this.lineWidth = options.lineWidth || 2;

  // Calcul column number for auto-color & auto-offset
  this.column = 0;
  this.calculColumn();

  // Options with auto value
  this.offsetX = options.offsetX || 20 + this.column * 20;
  this.color = options.color || options.colors[this.column];

  // Defaults values
  this.smoothOffset = 50; // Size of merge/fork portion
  this.commits = [];

  this.draw();
  this.checkout();
}

/**
 * Draw the branch
 **/
Branch.prototype.draw = function () {
  // Fork part
  if (this.parentBranch) {
    this.context.beginPath();
    this.context.moveTo(this.offsetX, this.origin);
    this.context.bezierCurveTo(
      this.offsetX, this.origin + this.smoothOffset / 2,
      this.parentBranch.offsetX, this.origin + this.smoothOffset / 2,
      this.parentBranch.offsetX, this.origin + this.smoothOffset);
    this.context.lineWidth = this.lineWidth;
    this.context.strokeStyle = this.color;
    this.context.stroke()
  }

  // Main part
  this.context.beginPath();
  this.context.moveTo(this.offsetX, this.origin);
  this.context.lineTo(this.offsetX, this.origin - this.size);
  this.context.lineWidth = this.lineWidth;
  this.context.strokeStyle = this.color;
  this.context.stroke();

  // Merge part
  if (this.targetBranch) {
    this.context.beginPath();
    this.context.moveTo(this.offsetX, this.origin - this.size);
    this.context.bezierCurveTo(
      this.offsetX, this.origin - this.size - this.smoothOffset / 2,
      this.targetBranch.offsetX, this.origin - this.size - this.smoothOffset / 2,
      this.targetBranch.offsetX, this.origin - this.size - this.smoothOffset);
    this.context.lineWidth = this.lineWidth;
    this.context.strokeStyle = this.color;
    this.context.stroke()
  }
}

/**
 * Checkout onto this branch
 **/
Branch.prototype.checkout = function () {
  this.parent.HEAD = this;
}

/**
 * Merge branch
 *
 * @param {Branch} target
 **/
Branch.prototype.merge = function (target) {
  this.targetBranch = target || this.parent.HEAD;
  this.draw();
}

/**
 * Calcul column
 **/
Branch.prototype.calculColumn = function () {
  for (var i = 0; i < this.parent.branchs.length; i++) {
    if (this.parent.branchs[i].origin - this.parent.branchs[i].size - this.parent.branchs[i].smoothOffset * 2 < this.origin)
      this.column++;
  }
  console.log('[' + this.name + '] column:' + this.column);
}
<|endoftext|>


<commit_before>import * as d3Scale from 'd3-scale';
import * as d3Shape from "d3-shape";
import * as d3Hierarchy from "d3-hierarchy";

export default function() {

  var mode = "identity",
      modes = ["horizontal", "vertical", "central", "grid", "coordinate", "radial", "treemap", "identity"],
      layout = identity,
      size = [1, 1],
      cols,
      rows,
      r,
      padding = 1,
      sort = function(a, b) { return a - b; },
      value = function(d) { return d; },
      x = d3Scale.scaleLinear(),
      y = d3Scale.scaleLinear();

  function gridding(nodes) {

    nodes.sort(function(a, b) {
      return sort(value(a), value(b));
    });

    return layout(nodes);
  }

  function identity(nodes) {

    return nodes;
  }

  function horizontal(nodes) {

    y.domain([0, nodes.length]).range([0, size[1]]);

    nodes.forEach(function(n, i) {
      n.x = 0;
      n.y = n.cy = y(i);
      n.cx = size[0] / 2;
      n.width = size[0];
      n.height = size[1] / nodes.length;
    });

    return nodes;
  }

  function vertical(nodes) {

    x.domain([0, nodes.length]).range([0, size[0]]);

    nodes.forEach(function(n, i) {
      n.x = x(i);
      n.y = 0;
      n.cx = x(i) + (size[0] / nodes.length) / 2;
      n.cy = size[1] / 2;
      n.width = size[0] / nodes.length;
      n.height = size[1];
    });

    return nodes;
  }

  function central(nodes) {

    nodes.forEach(function(n, i) {
      n.x = 0;
      n.y = 0;
      n.cx = size[0] / 2;
      n.cy = size[1] / 2;
      n.width = size[0];
      n.height = size[1];
    });

    return nodes;
  }

  function grid(nodes) {

    cols = Math.ceil(Math.sqrt(nodes.length));
    rows = Math.ceil(nodes.length / cols);

    x.domain([0, cols]).range([0, size[0]]);
    y.domain([0, rows]).range([0, size[1]]);

    nodes.forEach(function(n, i) {

      var col = i % cols;
      var row = Math.floor(i / cols);

      n.x = x(col) + padding;
      n.y = y(row) + padding;
      n.width = size[0] / cols - 2 * padding;
      n.height = size[1] / rows - 2 * padding;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function coordinate(nodes) {

    x.domain([0, 1]).range([0, size[0]]);
    y.domain([0, 1]).range([0, size[1]]);

    nodes.forEach(function(n, i) {
      n.x = n.cx = x(Math.random());
      n.y = n.cy = y(Math.random());
      n.width = size[0] / nodes.length;
      n.height = size[1] / nodes.length;
    });

    return nodes;
  }

  function radial(nodes) {

    r = Math.min(size[0], size[1]) / 2;

    var arc = d3Shape.arc()
        .outerRadius(r)
        .innerRadius(0)

    var pie = d3Shape.pie()
        .sort(sort)
        .value(function(d) { return 1; });

    var arcs = pie(nodes);

    nodes.forEach(function(n, i) {
      n.x = n.cx = arc.centroid(arcs[i])[0] + r;
      n.y = n.cy = arc.centroid(arcs[i])[1] + r;
      n.width = size[0] / nodes.length;
      n.height = size[1] / nodes.length;
    });

    return nodes;
  }

  function treemap(nodes) {

    var treemap = d3.treemap()
        .size([width, height])
        .padding(padding);

    var tree = treemap(d3.stratify()
        .id(function(d, i) { return i; })
        .parentId(function(d, i) {
          return i === 0 ? "": 0;
        })
        ([{}].concat(nodes))
          .sum(function(d, i) { return 1; })
        );

    nodes.forEach(function(n, i) {

        n.x = n.cx = tree.children[i].x0;
        n.y = n.cy = tree.children[i].y0;
        n.width = tree.children[i].x1 - n.x;
        n.height = tree.children[i].y1 - n.y;

    });

    return nodes;
  }

  gridding.mode = function(value) {

    if (!arguments.length) return mode;
    mode = value;

    switch(mode) {
      case "horizontal":
        layout = horizontal;
      break;
      case "vertical":
        layout = vertical;
      break;
      case "central":
        layout = central;
      break;
      case "grid":
        layout = grid;
      break;
      case "coordinate":
        layout = coordinate;
      break;
      case "radial":
        layout = radial;
      break;
      case "treemap":
        layout = treemap;
      break;
      case "identity":
      default:
        layout = identity;
      break;
    }

    return gridding;
  }

  gridding.modes = function() {
    return modes;
  }

  gridding.size = function(value) {
    if(!arguments.length) return size;
    size = value;
    return gridding;
  }

  gridding.value = function(_value) {
    if(!arguments.length) return value;
    value = _value;
    return gridding;
  }

  gridding.sort = function(_sort) {
    if(!arguments.length) return _sort;
    sort = _sort;
    return gridding;
  }

  gridding.padding = function(_padding) {
    if(!arguments.length) return _padding;
    padding = _padding;
    return gridding;
  }

  return gridding;
};
<commit_msg>Simpler modes selection<commit_after>import * as d3Scale from 'd3-scale';
import * as d3Shape from "d3-shape";
import * as d3Hierarchy from "d3-hierarchy";

export default function() {

  var mode = "identity",
      modes = {"horizontal": horizontal, "vertical": vertical, "central": central, "grid": grid, "coordinate": coordinate, "radial": radial, "treemap": treemap, "identity": identity},
      layout = identity,
      size = [1, 1],
      cols,
      rows,
      r,
      padding = 1,
      sort = function(a, b) { return a - b; },
      value = function(d) { return d; },
      x = d3Scale.scaleLinear(),
      y = d3Scale.scaleLinear();

  function gridding(nodes) {

    nodes.sort(function(a, b) {
      return sort(value(a), value(b));
    });

    return layout(nodes);
  }

  function identity(nodes) {

    return nodes;
  }

  function horizontal(nodes) {

    y.domain([0, nodes.length]).range([0, size[1]]);

    nodes.forEach(function(n, i) {
      n.x = 0;
      n.y = n.cy = y(i);
      n.cx = size[0] / 2;
      n.width = size[0];
      n.height = size[1] / nodes.length;
    });

    return nodes;
  }

  function vertical(nodes) {

    x.domain([0, nodes.length]).range([0, size[0]]);

    nodes.forEach(function(n, i) {
      n.x = x(i);
      n.y = 0;
      n.cx = x(i) + (size[0] / nodes.length) / 2;
      n.cy = size[1] / 2;
      n.width = size[0] / nodes.length;
      n.height = size[1];
    });

    return nodes;
  }

  function central(nodes) {

    nodes.forEach(function(n, i) {
      n.x = 0;
      n.y = 0;
      n.cx = size[0] / 2;
      n.cy = size[1] / 2;
      n.width = size[0];
      n.height = size[1];
    });

    return nodes;
  }

  function grid(nodes) {

    cols = Math.ceil(Math.sqrt(nodes.length));
    rows = Math.ceil(nodes.length / cols);

    x.domain([0, cols]).range([0, size[0]]);
    y.domain([0, rows]).range([0, size[1]]);

    nodes.forEach(function(n, i) {

      var col = i % cols;
      var row = Math.floor(i / cols);

      n.x = x(col) + padding;
      n.y = y(row) + padding;
      n.width = size[0] / cols - 2 * padding;
      n.height = size[1] / rows - 2 * padding;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function coordinate(nodes) {

    x.domain([0, 1]).range([0, size[0]]);
    y.domain([0, 1]).range([0, size[1]]);

    nodes.forEach(function(n, i) {
      n.x = n.cx = x(Math.random());
      n.y = n.cy = y(Math.random());
      n.width = size[0] / nodes.length;
      n.height = size[1] / nodes.length;
    });

    return nodes;
  }

  function radial(nodes) {

    r = Math.min(size[0], size[1]) / 2;

    var arc = d3Shape.arc()
        .outerRadius(r)
        .innerRadius(0)

    var pie = d3Shape.pie()
        .sort(sort)
        .value(function(d) { return 1; });

    var arcs = pie(nodes);

    nodes.forEach(function(n, i) {
      n.x = n.cx = arc.centroid(arcs[i])[0] + r;
      n.y = n.cy = arc.centroid(arcs[i])[1] + r;
      n.width = size[0] / nodes.length;
      n.height = size[1] / nodes.length;
    });

    return nodes;
  }

  function treemap(nodes) {

    var treemap = d3.treemap()
        .size([width, height])
        .padding(padding);

    var tree = treemap(d3.stratify()
        .id(function(d, i) { return i; })
        .parentId(function(d, i) {
          return i === 0 ? "": 0;
        })
        ([{}].concat(nodes))
          .sum(function(d, i) { return 1; })
        );

    nodes.forEach(function(n, i) {

        n.x = n.cx = tree.children[i].x0;
        n.y = n.cy = tree.children[i].y0;
        n.width = tree.children[i].x1 - n.x;
        n.height = tree.children[i].y1 - n.y;

    });

    return nodes;
  }

  gridding.mode = function(value) {

    if (!arguments.length) return mode;
    mode = value;

    layout = modes[mode];

    return gridding;
  }

  gridding.modes = function() {
    return d3.keys(modes);
  }

  gridding.size = function(value) {
    if(!arguments.length) return size;
    size = value;
    return gridding;
  }

  gridding.value = function(_value) {
    if(!arguments.length) return value;
    value = _value;
    return gridding;
  }

  gridding.sort = function(_sort) {
    if(!arguments.length) return _sort;
    sort = _sort;
    return gridding;
  }

  gridding.padding = function(_padding) {
    if(!arguments.length) return _padding;
    padding = _padding;
    return gridding;
  }

  return gridding;
};
<|endoftext|>


<commit_before>import * as d3Scale from 'd3-scale';
import * as d3Shape from "d3-shape";
import * as d3Array from "d3-array";
import * as d3Hierarchy from "d3-hierarchy";

export default function() {

  var mode = "identity",
      modes = {
        "horizontal": horizontal,
        "vertical": vertical,
        "central": central,
        "grid": grid,
        "coordinate": coordinate,
        "radial": radial,
        "treemap": treemap,
        "pack": pack,
        "stack": stack,
        "diagonal": diagonal,
        "cascade": cascade,
        "pyramid": pyramid,
        "brick": brick
      },
      layout = identity,
      size = [1, 1],
      cellSize,
      offset = [0, 0],
      cols,
      rows,
      radius,
      padding = 1,
      sort = function(a, b) { return a - b; },
      value = function(d) { return d; },
      valueX,
      valueY,
      orient = "down",
      x = d3Scale.scaleLinear(),
      y = d3Scale.scaleLinear();

  function gridding(nodes) {

    if(typeof nodes[0] === "string") {
      nodes = Array.prototype.map.call(nodes, function(d) { return {"__value": d}; });
      value = function(d) { return d.__value.toLowerCase(); }
    } else if(typeof nodes[0] !== "object") {
      nodes = Array.apply(null, Array(nodes.length)).map(function() { return new Object(); });
    }

    nodes.sort(function(a, b) {
      return sort(value(a), value(b));
    });

    return layout(nodes);
  }

  function identity(nodes) {

    nodes.forEach(function(n) {
      n.x = n.x || 0;
      n.y = n.y || 0;
      n.width = n.width || size[0];
      n.height = n.height || size[1];
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function horizontal(nodes) {

    rows = nodes.length;
    y.domain([0, rows]).range([0, size[1]]);

    nodes.forEach(function(n, i) {
      n.x = 0 + offset[0];
      n.y = y(i) + offset[1];
      n.width = size[0];
      n.height = size[1] / rows;
      n.cx = n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function vertical(nodes) {

    cols = nodes.length;
    x.domain([0, cols]).range([0, size[0]]);

    nodes.forEach(function(n, i) {
      n.x = x(i) + offset[0];
      n.y = 0 + offset[1];
      n.width = size[0] / cols;
      n.height = size[1];
      n.cx = n.x + n.width / 2;
      n.cy = n.height / 2;
    });

    return nodes;
  }

  function central(nodes) {

    cols = rows = 1;

    nodes.forEach(function(n) {
      n.x = 0 + offset[0];
      n.y = 0 + offset[1];
      n.width = size[0];
      n.height = size[1];
      n.cx = n.width / 2;
      n.cy = n.height / 2;
    });

    return nodes;
  }

  function grid(nodes) {

    cols = Math.ceil(Math.sqrt(nodes.length));
    rows = Math.ceil(nodes.length / cols);

    if(typeof cellSize !== "undefined") {
      size[0] = cellSize[0] * cols;
      size[1] = cellSize[1] * rows;
    }

    x.domain([0, cols]).range([0, size[0]]);
    y.domain([0, rows]).range([0, size[1]]);

    nodes.forEach(function(n, i) {

      var col = i % cols;
      var row = Math.floor(i / cols);

      n.x = x(col) + padding + offset[0];
      n.y = y(row) + padding + offset[1];
      n.width = size[0] / cols - 2 * padding;
      n.height = size[1] / rows - 2 * padding;

      if(orient == "up") {
        n.y = size[1] - n.y - n.height;
      }

      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;

    });

    return nodes;
  }

  function coordinate(nodes) {

    // Create random data if no value function has been set
    if(!valueX) {
      valueX = function() { return Math.random(); }
      x.domain([0, 1]).range([0, size[0]]);
    } else {
      x.domain(d3Array.extent(nodes, valueX)).range([0, size[0]]);
    }

    if(!valueY) {
      valueY = function() { return Math.random(); }
      y.domain([0, 1]).range([0, size[1]]);
    } else {
      y.domain(d3Array.extent(nodes, valueY)).range([0, size[1]]);
    }

    nodes.forEach(function(n) {
      n.x = x(valueX(n)) + offset[0];
      n.y = y(valueY(n)) + offset[1];
      n.width = cellSize ? cellSize[0]: size[0] / nodes.length;
      n.height = cellSize ? cellSize[1]: size[1] / nodes.length;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function radial(nodes) {

    if(!radius) {
      radius = Math.min(size[0], size[1]) - 2 * (size[1] / nodes.length);
    }

    var arc = d3Shape.arc()
        .outerRadius(radius)
        .innerRadius(0);

    var pie = d3Shape.pie()
        .sort(sort)
        .value(function() { return 1; });

    var arcs = pie(nodes);

    nodes.forEach(function(n, i) {
      n.width = size[0] / nodes.length;
      n.height = size[1] / nodes.length;
      n.x = arc.centroid(arcs[i])[0] + size[0] / 2 + offset[0] - n.width / 2;
      n.y = arc.centroid(arcs[i])[1] + size[1] / 2 + offset[1] - n.height / 2;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function treemap(nodes) {

    var treemap = d3Hierarchy.treemap()
        .size([size[0], size[1]])
        .padding(padding);

    var tree = treemap(d3Hierarchy.stratify()
        .id(function(d, i) { return i; })
        .parentId(function(d, i) {
          return i === 0 ? "": 0;
        })([{}].concat(nodes))
          .sum(function() { return 1; })
        );

    nodes.forEach(function(n, i) {
      n.x = tree.children[i].x0 + offset[0];
      n.y = tree.children[i].y0 + offset[1];
      n.width = tree.children[i].x1 - tree.children[i].x0;
      n.height = tree.children[i].y1 - tree.children[i].y0;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function pack(nodes) {

    var pack = d3Hierarchy.pack()
        .size([size[0], size[1]])
        .padding(padding);

    var packed = pack(d3Hierarchy.stratify()
        .id(function(d, i) { return i; })
        .parentId(function(d, i) {
          return i === 0 ? "": 0;
        })([{}].concat(nodes))
          .sum(function() { return 1; })
        );

    nodes.forEach(function(n, i) {
      n.x = packed.children[i].x + offset[0];
      n.y = packed.children[i].y + offset[1];
      n.width = packed.children[i].r;
      n.height = packed.children[i].r;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function stack(nodes) {

    var stack = d3Hierarchy.stack()
        .keys(nodes.map(function(d, i) { return i + "_"; })) // Creates unique ids for nodes
        .value(function(d, key) { return nodes.indexOf(d[key]); });

    y.domain([0, d3Array.sum(d3Array.range(nodes.length)) + nodes.length]).range([0, size[1]]);

    var new_data = {};

    nodes.map(function(d, i) {
      new_data[i+"_"] = d;
    })

    var stacked = stack([new_data]);

    nodes.forEach(function(n, i) {
      var s = stacked[i][0];
      n.x = offset[0];
      n.y = y(s[1]) + offset[1];
      n.width = size[0];
      n.height = y(s[1]) - y(s[0]);
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function diagonal(nodes) {

    x.domain([0, nodes.length]).range([0, size[0]]);
    y.domain([0, nodes.length]).range([0, size[1]]);

    nodes.forEach(function(n, i) {

      if(orient == "up") {
        n.x = x(i) + offset[0];
        n.y = size[1] - (y(i) + offset[1]) - size[1] / nodes.length;
      } else {
        n.x = x(i) + offset[0];
        n.y = y(i) + offset[1];
      }

      n.width = size[0] / nodes.length;
      n.height = size[1] / nodes.length;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function cascade(nodes) {

    var spacing = size[0] * 2;

    x.domain([0, nodes.length]).range([0, spacing / nodes.length]);
    y.domain([0, nodes.length]).range([0, spacing / nodes.length]);

    nodes.forEach(function(n, i) {

      n.x = x(i) + offset[0];
      n.y = y(i) + offset[1];
      n.width = size[0] - spacing / nodes.length;
      n.height = size[1] - spacing / nodes.length;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;

    });

    return nodes;
  }

  function pyramid(nodes) {

    var shiftX = size[0] / (2 * nodes.length );
    var shiftY = size[1] / (2 * nodes.length );

    nodes.forEach(function(n, i) {

      n.x = 0 + offset[0] + shiftX * i;
      n.y = 0 + offset[1] + shiftY * i;
      n.width = size[0] - shiftX * i * 2;
      n.height = size[1] - shiftY * i * 2;
      n.cx = n.width / 2 + shiftX * i;
      n.cy = n.height / 2+ shiftY * i;

    });

    return nodes;
  }

  function brick(nodes) {

    cols = Math.ceil(Math.sqrt(nodes.length));
    rows = Math.ceil(nodes.length / cols);

    x.domain([0, cols + 1 / 2]).range([0, size[0]]);
    y.domain([0, rows]).range([0, size[1]]);

    nodes.forEach(function(n, i) {

      var col = i % cols;
      var row = Math.floor(i / cols);

      n.x = x(col) + padding + offset[0];
      n.y = y(row) + padding + offset[1];

      n.width = size[0] / (cols + 1 / 2) - 2 * padding;
      n.height = size[1] / rows - 2 * padding;

      if(orient === "left") {
        if(row % 2 === 1) {
          n.x += n.width / 2;
        }
      } else {
        if(row % 2 === 0) {
          n.x += n.width / 2;
        }
      }

      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;

    });

    return nodes;
  }

  gridding.mode = function(value) {

    if (!arguments.length) return mode;
    mode = value;

    if(mode === "identity") {
      layout = identity;
    } else if(Object.keys(modes).indexOf(value) >= 0) {
      layout = modes[mode];
    }

    return gridding;
  }

  gridding.modes = function() {
    return Object.keys(modes);
  }

  gridding.size = function(_size) {
    if(!arguments.length) return size;
    size = _size;
    return gridding;
  }

  gridding.cellSize = function(_cellSize) {
    if(!arguments.length) return cellSize;
    cellSize = _cellSize;
    return gridding;
  }

  gridding.value = function(_value) {
    if(!arguments.length) return value;
    value = _value;
    return gridding;
  }

  gridding.valueX = function(_valueX) {
    if(!arguments.length) return valueX;
    valueX = _valueX;
    return gridding;
  }

  gridding.valueY = function(_valueY) {
    if(!arguments.length) return valueY;
    valueY = _valueY;
    return gridding;
  }

  gridding.sort = function(_sort) {
    if(!arguments.length) return sort;
    sort = _sort;
    return gridding;
  }

  gridding.padding = function(_padding) {
    if(!arguments.length) return padding;
    padding = _padding;
    return gridding;
  }

  gridding.offset = function(_offset) {
    if(!arguments.length) return offset;
    offset = _offset;
    return gridding;
  }

  gridding.orient = function(_orient) {
    if(!arguments.length) return orient;
    orient = _orient;
    return gridding;
  }

  gridding.cols = function(_cols) {
    if(!arguments.length) return cols;
    cols = _cols;
    return gridding;
  }

  gridding.rows = function(_rows) {
    if(!arguments.length) return rows;
    rows = _rows;
    return gridding;
  }

  gridding.radius = function(_radius) {
    if(!arguments.length) return radius;
    radius = _radius;
    return gridding;
  }

  return gridding;
}
<commit_msg>Customizable valueY for horizontal layout<commit_after>import * as d3Scale from 'd3-scale';
import * as d3Shape from "d3-shape";
import * as d3Array from "d3-array";
import * as d3Hierarchy from "d3-hierarchy";

export default function() {

  var mode = "identity",
      modes = {
        "horizontal": horizontal,
        "vertical": vertical,
        "central": central,
        "grid": grid,
        "coordinate": coordinate,
        "radial": radial,
        "treemap": treemap,
        "pack": pack,
        "stack": stack,
        "diagonal": diagonal,
        "cascade": cascade,
        "pyramid": pyramid,
        "brick": brick
      },
      layout = identity,
      size = [1, 1],
      cellSize,
      offset = [0, 0],
      cols,
      rows,
      radius,
      padding = 1,
      sort = function(a, b) { return a - b; },
      value = function(d) { return d; },
      valueX,
      valueY,
      orient = "down",
      x = d3Scale.scaleLinear(),
      y = d3Scale.scaleLinear();

  function gridding(nodes) {

    if(typeof nodes[0] === "string") {
      nodes = Array.prototype.map.call(nodes, function(d) { return {"__value": d}; });
      value = function(d) { return d.__value.toLowerCase(); }
    } else if(typeof nodes[0] !== "object") {
      nodes = Array.apply(null, Array(nodes.length)).map(function() { return new Object(); });
    }

    nodes.sort(function(a, b) {
      return sort(value(a), value(b));
    });

    return layout(nodes);
  }

  function identity(nodes) {

    nodes.forEach(function(n) {
      n.x = n.x || 0;
      n.y = n.y || 0;
      n.width = n.width || size[0];
      n.height = n.height || size[1];
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function horizontal(nodes) {

    if(!valueY) {
      valueY = function() { return 1; }
      y.domain([0, nodes.length + 1]).range([0, size[1]]);
    } else {
      y.domain([0, d3.sum(nodes, valueY)]).range([0, size[1]]);
    }

    rows = nodes.length;

    nodes[0].y0 = 0 + offset[0];

    nodes.forEach(function(n, i) {
      n.x = 0 + offset[0];
      n.y = n.y0 + offset[1];
      n.width = size[0];
      n.height = y(valueY(n));

      if(i < nodes.length - 1) {
        nodes[i+1].y0 = n.y0 + n.height;
      }

      n.cx = n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function vertical(nodes) {

    cols = nodes.length;
    x.domain([0, cols]).range([0, size[0]]);

    nodes.forEach(function(n, i) {
      n.x = x(i) + offset[0];
      n.y = 0 + offset[1];
      n.width = size[0] / cols;
      n.height = size[1];
      n.cx = n.x + n.width / 2;
      n.cy = n.height / 2;
    });

    return nodes;
  }

  function central(nodes) {

    cols = rows = 1;

    nodes.forEach(function(n) {
      n.x = 0 + offset[0];
      n.y = 0 + offset[1];
      n.width = size[0];
      n.height = size[1];
      n.cx = n.width / 2;
      n.cy = n.height / 2;
    });

    return nodes;
  }

  function grid(nodes) {

    cols = Math.ceil(Math.sqrt(nodes.length));
    rows = Math.ceil(nodes.length / cols);

    if(typeof cellSize !== "undefined") {
      size[0] = cellSize[0] * cols;
      size[1] = cellSize[1] * rows;
    }

    x.domain([0, cols]).range([0, size[0]]);
    y.domain([0, rows]).range([0, size[1]]);

    nodes.forEach(function(n, i) {

      var col = i % cols;
      var row = Math.floor(i / cols);

      n.x = x(col) + padding + offset[0];
      n.y = y(row) + padding + offset[1];
      n.width = size[0] / cols - 2 * padding;
      n.height = size[1] / rows - 2 * padding;

      if(orient == "up") {
        n.y = size[1] - n.y - n.height;
      }

      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;

    });

    return nodes;
  }

  function coordinate(nodes) {

    // Create random data if no value function has been set
    if(!valueX) {
      valueX = function() { return Math.random(); }
      x.domain([0, 1]).range([0, size[0]]);
    } else {
      x.domain(d3Array.extent(nodes, valueX)).range([0, size[0]]);
    }

    if(!valueY) {
      valueY = function() { return Math.random(); }
      y.domain([0, 1]).range([0, size[1]]);
    } else {
      y.domain(d3Array.extent(nodes, valueY)).range([0, size[1]]);
    }

    nodes.forEach(function(n) {
      n.x = x(valueX(n)) + offset[0];
      n.y = y(valueY(n)) + offset[1];
      n.width = cellSize ? cellSize[0]: size[0] / nodes.length;
      n.height = cellSize ? cellSize[1]: size[1] / nodes.length;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function radial(nodes) {

    if(!radius) {
      radius = Math.min(size[0], size[1]) - 2 * (size[1] / nodes.length);
    }

    var arc = d3Shape.arc()
        .outerRadius(radius)
        .innerRadius(0);

    var pie = d3Shape.pie()
        .sort(sort)
        .value(function() { return 1; });

    var arcs = pie(nodes);

    nodes.forEach(function(n, i) {
      n.width = size[0] / nodes.length;
      n.height = size[1] / nodes.length;
      n.x = arc.centroid(arcs[i])[0] + size[0] / 2 + offset[0] - n.width / 2;
      n.y = arc.centroid(arcs[i])[1] + size[1] / 2 + offset[1] - n.height / 2;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function treemap(nodes) {

    var treemap = d3Hierarchy.treemap()
        .size([size[0], size[1]])
        .padding(padding);

    var tree = treemap(d3Hierarchy.stratify()
        .id(function(d, i) { return i; })
        .parentId(function(d, i) {
          return i === 0 ? "": 0;
        })([{}].concat(nodes))
          .sum(function() { return 1; })
        );

    nodes.forEach(function(n, i) {
      n.x = tree.children[i].x0 + offset[0];
      n.y = tree.children[i].y0 + offset[1];
      n.width = tree.children[i].x1 - tree.children[i].x0;
      n.height = tree.children[i].y1 - tree.children[i].y0;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function pack(nodes) {

    var pack = d3Hierarchy.pack()
        .size([size[0], size[1]])
        .padding(padding);

    var packed = pack(d3Hierarchy.stratify()
        .id(function(d, i) { return i; })
        .parentId(function(d, i) {
          return i === 0 ? "": 0;
        })([{}].concat(nodes))
          .sum(function() { return 1; })
        );

    nodes.forEach(function(n, i) {
      n.x = packed.children[i].x + offset[0];
      n.y = packed.children[i].y + offset[1];
      n.width = packed.children[i].r;
      n.height = packed.children[i].r;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function stack(nodes) {

    var stack = d3Hierarchy.stack()
        .keys(nodes.map(function(d, i) { return i + "_"; })) // Creates unique ids for nodes
        .value(function(d, key) { return nodes.indexOf(d[key]); });

    y.domain([0, d3Array.sum(d3Array.range(nodes.length)) + nodes.length]).range([0, size[1]]);

    var new_data = {};

    nodes.map(function(d, i) {
      new_data[i+"_"] = d;
    })

    var stacked = stack([new_data]);

    nodes.forEach(function(n, i) {
      var s = stacked[i][0];
      n.x = offset[0];
      n.y = y(s[1]) + offset[1];
      n.width = size[0];
      n.height = y(s[1]) - y(s[0]);
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function diagonal(nodes) {

    x.domain([0, nodes.length]).range([0, size[0]]);
    y.domain([0, nodes.length]).range([0, size[1]]);

    nodes.forEach(function(n, i) {

      if(orient == "up") {
        n.x = x(i) + offset[0];
        n.y = size[1] - (y(i) + offset[1]) - size[1] / nodes.length;
      } else {
        n.x = x(i) + offset[0];
        n.y = y(i) + offset[1];
      }

      n.width = size[0] / nodes.length;
      n.height = size[1] / nodes.length;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;
    });

    return nodes;
  }

  function cascade(nodes) {

    var spacing = size[0] * 2;

    x.domain([0, nodes.length]).range([0, spacing / nodes.length]);
    y.domain([0, nodes.length]).range([0, spacing / nodes.length]);

    nodes.forEach(function(n, i) {

      n.x = x(i) + offset[0];
      n.y = y(i) + offset[1];
      n.width = size[0] - spacing / nodes.length;
      n.height = size[1] - spacing / nodes.length;
      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;

    });

    return nodes;
  }

  function pyramid(nodes) {

    var shiftX = size[0] / (2 * nodes.length );
    var shiftY = size[1] / (2 * nodes.length );

    nodes.forEach(function(n, i) {

      n.x = 0 + offset[0] + shiftX * i;
      n.y = 0 + offset[1] + shiftY * i;
      n.width = size[0] - shiftX * i * 2;
      n.height = size[1] - shiftY * i * 2;
      n.cx = n.width / 2 + shiftX * i;
      n.cy = n.height / 2+ shiftY * i;

    });

    return nodes;
  }

  function brick(nodes) {

    cols = Math.ceil(Math.sqrt(nodes.length));
    rows = Math.ceil(nodes.length / cols);

    x.domain([0, cols + 1 / 2]).range([0, size[0]]);
    y.domain([0, rows]).range([0, size[1]]);

    nodes.forEach(function(n, i) {

      var col = i % cols;
      var row = Math.floor(i / cols);

      n.x = x(col) + padding + offset[0];
      n.y = y(row) + padding + offset[1];

      n.width = size[0] / (cols + 1 / 2) - 2 * padding;
      n.height = size[1] / rows - 2 * padding;

      if(orient === "left") {
        if(row % 2 === 1) {
          n.x += n.width / 2;
        }
      } else {
        if(row % 2 === 0) {
          n.x += n.width / 2;
        }
      }

      n.cx = n.x + n.width / 2;
      n.cy = n.y + n.height / 2;

    });

    return nodes;
  }

  gridding.mode = function(value) {

    if (!arguments.length) return mode;
    mode = value;

    if(mode === "identity") {
      layout = identity;
    } else if(Object.keys(modes).indexOf(value) >= 0) {
      layout = modes[mode];
    }

    return gridding;
  }

  gridding.modes = function() {
    return Object.keys(modes);
  }

  gridding.size = function(_size) {
    if(!arguments.length) return size;
    size = _size;
    return gridding;
  }

  gridding.cellSize = function(_cellSize) {
    if(!arguments.length) return cellSize;
    cellSize = _cellSize;
    return gridding;
  }

  gridding.value = function(_value) {
    if(!arguments.length) return value;
    value = _value;
    return gridding;
  }

  gridding.valueX = function(_valueX) {
    if(!arguments.length) return valueX;
    valueX = _valueX;
    return gridding;
  }

  gridding.valueY = function(_valueY) {
    if(!arguments.length) return valueY;
    if(typeof _valueY === "string") {
      valueY = function(d) { return d[_valueY]; }
    } else {
      valueY = _valueY;
    }
    return gridding;
  }

  gridding.sort = function(_sort) {
    if(!arguments.length) return sort;
    sort = _sort;
    return gridding;
  }

  gridding.padding = function(_padding) {
    if(!arguments.length) return padding;
    padding = _padding;
    return gridding;
  }

  gridding.offset = function(_offset) {
    if(!arguments.length) return offset;
    offset = _offset;
    return gridding;
  }

  gridding.orient = function(_orient) {
    if(!arguments.length) return orient;
    orient = _orient;
    return gridding;
  }

  gridding.cols = function(_cols) {
    if(!arguments.length) return cols;
    cols = _cols;
    return gridding;
  }

  gridding.rows = function(_rows) {
    if(!arguments.length) return rows;
    rows = _rows;
    return gridding;
  }

  gridding.radius = function(_radius) {
    if(!arguments.length) return radius;
    radius = _radius;
    return gridding;
  }

  return gridding;
}
<|endoftext|>


<commit_before>var extend = require('./extend.js')
	converter = require('./converter.js');

//g2svg as geojson2svg (shorthand)
var g2svg = function(options) {
  this.options = options || {};
  this.viewportSize = this.options.viewportSize ||
    {width: 256, height: 256};
  this.mapExtent = this.options.mapExtent ||
    {
      left: -20037508.342789244,
      right: 20037508.342789244,
      bottom: -20037508.342789244,
      top: 20037508.342789244
    };
  this.res = this.calResolution(this.mapExtent,this.viewportSize,
    this.options.fitTo);
};
g2svg.prototype.calResolution = function(extent,size,fitTo) {
  var xres = (extent.right - extent.left)/size.width;
  var yres = (extent.top - extent.bottom)/size.height;
  if (fitTo) {
    if (fitTo.toLowerCase() === 'width') {
      return xres;
    } else if (fitTo.toLowerCase() === 'height') {
      return yres;
    } else {
      throw new Error('"fitTo" option should be "width" or "height" ');
    }
  } else {
    return Math.max(xres,yres);
  }
};
g2svg.prototype.convert = function(geojson,options)  {
  var opt = extend(this.options, options || {});
  var multiGeometries = ['MultiPoint','MultiLineString','MultiPolygon'];
  var geometries = ['Point', 'LineString', 'Polygon'];
  var svgElements = [];
  if (geojson.type == 'FeatureCollection') {
    for(var i=0; i< geojson.features.length; i++) {
      svgElements = svgElements.concat(
        this.convertFeature(geojson.features[i],opt));
    }
  } else if (geojson.type == 'Feature') {
    svgElements = this.convertFeature(geojson,opt);
  } else if (geojson.type == 'GeometryCollection') {
    for(var i=0; i< geojson.geometries.length; i++) {
      svgElements = svgElements.concat(
        this.convertGeometry(geojson.geometries[i],opt));
    }
  } else if (converter[geojson.type]) {
    svgElements = this.convertGeometry(geojson,opt);
  } else {
    return;
  }
  if(opt.callback) opt.callback.call(this,svgElements);
  return svgElements;
};
g2svg.prototype.convertFeature = function(feature,options) {
  if(!feature && !feature.geometry) return;
  var opt = extend(this.options, options || {});
  if (opt.attributes && opt.attributes instanceof Array) {
    var arr = opt.attributes
    opt.attributes = arr.reduce(function(sum, property) {
      if (typeof(property) === 'string') {
        var val, key = property.split('.').pop()
        try {
          val = valueAt(feature, property)
        } catch(e) {
          val = false
        }
        if (val) sum[key] = val
      } else if (typeof(property) === 'object' && property.type
        && property.property)
      {
        if (property.type === 'dynamic') {
          var val, key = property.key ? property.key
            : property.property.split('.').pop()
          try {
            val = valueAt(feature, property.property)
          } catch(e) {
            val = false
          }
          if (val) sum[key] = val
        } else if (property.type === 'static'  && property.value) {
          sum[property.property] = property.value
        }
      }
      return sum
    }, {})
  } else {
    opt.attributes = opt.attributes || {};
  }
  var id = opt.attributes.id || feature.id ||
    (feature.properties && feature.properties.id
    ? feature.properties.id : null);
  if (id) opt.attributes.id = id
  return this.convertGeometry(feature.geometry,opt);
};
g2svg.prototype.convertGeometry = function(geom,options) {
  if(converter[geom.type]) {
    var opt = extend(this.options, options || {});
    var output = opt.output || 'svg';
    var paths = converter[geom.type].call(this,geom,
      this.res,
      {x:this.mapExtent.left,y:this.mapExtent.top},
      opt
    );
    var svgJsons,svgEles;
    if (output.toLowerCase() == 'svg') {
      svgJsons = paths.map(function(path) {
        return pathToSvgJson(path,geom.type,opt.attributes,opt);
      });
      svgEles = svgJsons.map(function(json) {
        return jsonToSvgElement(json,geom.type,opt);
      });
      return svgEles;
    } else {
      return paths;
    }
  } else {
    return;
  }
};

function pathToSvgJson(path,type,attributes,opt) {
  var svg = {};
  var pointAsCircle = opt && opt.hasOwnProperty('pointAsCircle')
    ? opt.pointAsCircle : false;
  if((type == 'Point' || type == 'MultiPoint') && pointAsCircle) {
    svg['cx'] = path.split(',')[0];
    svg['cy'] = path.split(',')[1];
    svg['r'] = opt && opt.r ? opt.r : '1';
  } else {
    svg = {d: path};
    if(type == 'Polygon' || type == 'MultiPolygon') {
      svg['fill-rule'] == 'evenodd';
    }
  }
  for (var key in attributes) {
    svg[key]= attributes[key];
  }
  return svg;
};

function jsonToSvgElement(json,type,opt) {
  var pointAsCircle = opt && opt.hasOwnProperty('pointAsCircle')
    ? opt.pointAsCircle : false;
  var ele ='<path';
  if((type == 'Point' || type == 'MultiPoint') && pointAsCircle) {
    ele = '<circle';
  }
  for(var key in json) {
    ele += ' ' + key +'="' + json[key] + '"';
  }
  ele += '/>';
  return ele;
}

function valueAt(obj,path) {
  //taken from http://stackoverflow.com/a/6394168/713573
  function index(prev,cur, i, arr) {
    if (prev.hasOwnProperty(cur)) {
      return prev[cur];
    } else {
      throw new Error(arr.slice(0,i+1).join('.') + ' is not a valid property path');
    }
  }
  return path.split('.').reduce(index, obj);
}
module.exports = g2svg;
<commit_msg>Fixed bug of variable declaration<commit_after>var extend = require('./extend.js');
var converter = require('./converter.js');

//g2svg as geojson2svg (shorthand)
var g2svg = function(options) {
  this.options = options || {};
  this.viewportSize = this.options.viewportSize ||
    {width: 256, height: 256};
  this.mapExtent = this.options.mapExtent ||
    {
      left: -20037508.342789244,
      right: 20037508.342789244,
      bottom: -20037508.342789244,
      top: 20037508.342789244
    };
  this.res = this.calResolution(this.mapExtent,this.viewportSize,
    this.options.fitTo);
};
g2svg.prototype.calResolution = function(extent,size,fitTo) {
  var xres = (extent.right - extent.left)/size.width;
  var yres = (extent.top - extent.bottom)/size.height;
  if (fitTo) {
    if (fitTo.toLowerCase() === 'width') {
      return xres;
    } else if (fitTo.toLowerCase() === 'height') {
      return yres;
    } else {
      throw new Error('"fitTo" option should be "width" or "height" ');
    }
  } else {
    return Math.max(xres,yres);
  }
};
g2svg.prototype.convert = function(geojson,options)  {
  var opt = extend(this.options, options || {});
  var multiGeometries = ['MultiPoint','MultiLineString','MultiPolygon'];
  var geometries = ['Point', 'LineString', 'Polygon'];
  var svgElements = [];
  if (geojson.type == 'FeatureCollection') {
    for(var i=0; i< geojson.features.length; i++) {
      svgElements = svgElements.concat(
        this.convertFeature(geojson.features[i],opt));
    }
  } else if (geojson.type == 'Feature') {
    svgElements = this.convertFeature(geojson,opt);
  } else if (geojson.type == 'GeometryCollection') {
    for(var i=0; i< geojson.geometries.length; i++) {
      svgElements = svgElements.concat(
        this.convertGeometry(geojson.geometries[i],opt));
    }
  } else if (converter[geojson.type]) {
    svgElements = this.convertGeometry(geojson,opt);
  } else {
    return;
  }
  if(opt.callback) opt.callback.call(this,svgElements);
  return svgElements;
};
g2svg.prototype.convertFeature = function(feature,options) {
  if(!feature && !feature.geometry) return;
  var opt = extend(this.options, options || {});
  if (opt.attributes && opt.attributes instanceof Array) {
    var arr = opt.attributes
    opt.attributes = arr.reduce(function(sum, property) {
      if (typeof(property) === 'string') {
        var val, key = property.split('.').pop()
        try {
          val = valueAt(feature, property)
        } catch(e) {
          val = false
        }
        if (val) sum[key] = val
      } else if (typeof(property) === 'object' && property.type
        && property.property)
      {
        if (property.type === 'dynamic') {
          var val, key = property.key ? property.key
            : property.property.split('.').pop()
          try {
            val = valueAt(feature, property.property)
          } catch(e) {
            val = false
          }
          if (val) sum[key] = val
        } else if (property.type === 'static'  && property.value) {
          sum[property.property] = property.value
        }
      }
      return sum
    }, {})
  } else {
    opt.attributes = opt.attributes || {};
  }
  var id = opt.attributes.id || feature.id ||
    (feature.properties && feature.properties.id
    ? feature.properties.id : null);
  if (id) opt.attributes.id = id
  return this.convertGeometry(feature.geometry,opt);
};
g2svg.prototype.convertGeometry = function(geom,options) {
  if(converter[geom.type]) {
    var opt = extend(this.options, options || {});
    var output = opt.output || 'svg';
    var paths = converter[geom.type].call(this,geom,
      this.res,
      {x:this.mapExtent.left,y:this.mapExtent.top},
      opt
    );
    var svgJsons,svgEles;
    if (output.toLowerCase() == 'svg') {
      svgJsons = paths.map(function(path) {
        return pathToSvgJson(path,geom.type,opt.attributes,opt);
      });
      svgEles = svgJsons.map(function(json) {
        return jsonToSvgElement(json,geom.type,opt);
      });
      return svgEles;
    } else {
      return paths;
    }
  } else {
    return;
  }
};

function pathToSvgJson(path,type,attributes,opt) {
  var svg = {};
  var pointAsCircle = opt && opt.hasOwnProperty('pointAsCircle')
    ? opt.pointAsCircle : false;
  if((type == 'Point' || type == 'MultiPoint') && pointAsCircle) {
    svg['cx'] = path.split(',')[0];
    svg['cy'] = path.split(',')[1];
    svg['r'] = opt && opt.r ? opt.r : '1';
  } else {
    svg = {d: path};
    if(type == 'Polygon' || type == 'MultiPolygon') {
      svg['fill-rule'] == 'evenodd';
    }
  }
  for (var key in attributes) {
    svg[key]= attributes[key];
  }
  return svg;
};

function jsonToSvgElement(json,type,opt) {
  var pointAsCircle = opt && opt.hasOwnProperty('pointAsCircle')
    ? opt.pointAsCircle : false;
  var ele ='<path';
  if((type == 'Point' || type == 'MultiPoint') && pointAsCircle) {
    ele = '<circle';
  }
  for(var key in json) {
    ele += ' ' + key +'="' + json[key] + '"';
  }
  ele += '/>';
  return ele;
}

function valueAt(obj,path) {
  //taken from http://stackoverflow.com/a/6394168/713573
  function index(prev,cur, i, arr) {
    if (prev.hasOwnProperty(cur)) {
      return prev[cur];
    } else {
      throw new Error(arr.slice(0,i+1).join('.') + ' is not a valid property path');
    }
  }
  return path.split('.').reduce(index, obj);
}
module.exports = g2svg;
<|endoftext|>