<commit_before>/**
 * ------------------------------------------
 * 桌面接口实现文件
 * @version  1.0
 * @author   yuqijun(yuqijun@corp.netease.com)
 * ------------------------------------------
 */
var f = function() {
    // variable declaration
    var _   = NEJ.P,
        _o  = NEJ.O,
        _e  = _('nej.e'),
        _u  = _('nej.u'),
        _v  = _('nej.v'),
        _n  = _('nej.n'),
        _t  = _('nej.ut'),
        _p  = _('nej.cef'),
        _nt = _('nej.cef.ut'),
        _mcache = {};
    /**
     * 配置窗体信息
     * @see    {nej.cef._$configWindowPosition}
     * @see    {nej.cef._$configWindowSizeLimit}
     * @param  {Object} 配置信息，其他参数详情见@see指定接口配置信息
     * @return {Void}
     */
    _p._$configWindow = function(_options){
        _p._$configWindowSizeLimit(_options);
        _p._$configWindowPosition(_options);
        if (!!_options.icon)
            _p._$setWindowIcon(_options.icon);
        if (!!_options.title)
            _p._$setWindowTitle(_options.title);
    };
    /**
     * 配置窗体位置，对齐方式定义如下

     * 水平对齐方式：
     * [ntb]
     *   名称            |  描述
     *   ----------------------
     *   left   |  左侧对齐
     *   center |  中间对齐
     *   right  |  右侧对齐
     * [/ntb]
     *
     * 垂直对齐方式：
     * [ntb]
     *   名称              |  描述
     *   ---------------------
     *   top     |  顶部对齐
     *   center  |  中间对齐
     *   bottom  |  底部对齐
     * [/ntb]
     * @api    {nej.cef._$configWindowPosition}
     * @param  {Object} 配置信息
     * @config {String}  name     窗体名称
     * @config {Number}  width    窗体宽度
     * @config {Number}  height   窗体高度
     * @config {Boolean} topmost  窗体是否置顶
     * @config {String}  align    对齐方式，格式定义：水平对齐方式+空格+垂直对齐方式，如 left top
     * @config {Object}  area     区域位置，默认自动计算，格式如：{x:0,y:0,width:100,height:200}
     * @return {Void}
     */
    _p._$configWindowPosition = (function(){
        var _reg0 = /\s+/,
            _fmap = {
                left:function(_mbox,_total){
                    return 0;
                },
                center:function(_mbox,_total){
                    return Math.floor(Math.abs(_total-_mbox)/2);
                },
                right:function(_mbox,_total){
                    return Math.abs(_total);
                }
            };
        _fmap.top = _fmap.left;
        _fmap.bottom = _fmap.right;
        return function(_options){
            _options = _options||_o;
            // set window position
            var _aligns = (_options.align||'').trim().split(_reg0),
                _position = NEJ.EX({width:0,height:0,topmost:!1},_options),
                _wkarea = _options.area||(_n._$exec('os.getSystemInfo','monitor')||_o).workArea||_o;
            _position.x = _wkarea.x+(_fmap[_aligns[0]]||_fmap.center)(_position.width,_wkarea.width);
            _position.y = _wkarea.y+(_fmap[_aligns[1]]||_fmap.center)(_position.height,_wkarea.height);
            if (!_options.name){
                _n._$exec('winhelper.setWindowPosition',_position);
            }else{
                _position.name = _options.name;
                _n._$exec('winhelper.setNativeWindowRect',_position);
            }
        };
    })();
    /**
     * 配置窗体大小限制
     * @api    {nej.cef._$configWindowSizeLimit}
     * @param  {Object} 配置信息
     * @config {Number}  minWidth  窗体最小宽度
     * @config {Number}  maxWidth  窗体最大宽度
     * @config {Number}  minHeight 窗体最小高度
     * @config {Number}  maxHeight 窗体最大高度
     */
    _p._$configWindowSizeLimit = (function(){
        // parse min/max - width/height
        var _doParseBox = function(_width,_height){
            _width = parseInt(_width);
            _height = parseInt(_height);
            var _result;
            if (!isNaN(_width)){
                _result = _result||{};
                _result.x = _width;
            }
            if (!isNaN(_height)){
                _result = _result||{};
                _result.y = _height;
            }
            return _result;
        };
        return function(_options){
            _options = _options||_o;
            _n._$exec(
                'winhelper.setWindowSizeLimit',
                _doParseBox(_options.minWidth,_options.minHeight),
                _doParseBox(_options.maxWidth,_options.maxHeight)
            );
        };
    })();
    /**
     * 显示窗体,但窗体不会放在最上层
     * @api    {nej.cef._$showWindow}
     * @return {Void}
     */
    _p._$showWindow = function(_name){
        if (!_name){
            _n._$exec('winhelper.showWindow','show');
        }else{
            var _area = (_n._$exec('os.getSystemInfo','monitor')||_o).workArea||_o;
            _n._$exec('winhelper.setNativeWindowShow',_name,!0,_area);
        }
    };
    /**
     * 隐藏窗体
     * @api    {nej.cef._$hideWindow}
     * @return {Void}
     */
    _p._$hideWindow = function(_name){
        if (!_name){
            _n._$exec('winhelper.showWindow','hide');
        }else{
            var _area = (_n._$exec('os.getSystemInfo','monitor')||_o).workArea||_o;
            _n._$exec('winhelper.setNativeWindowShow',_name,!1,_area);
        }
    };
    /**
     * 关闭窗体，销毁窗体
     * @api    {nej.cef._$closeWindow}
     * @return {Void}
     */
    _p._$closeWindow = function(){
        _n._$exec('winhelper.destroyWindow');
    };
    /**
     * 窗口前置
     * @return {Void}
     */
    _p._$topWindow = function(_name){
        _p._$showWindow(_name);
        if (!_name){
            _n._$exec('winhelper.bringWindowToTop');
        }
    };
    /**
     * 设置窗口标题
     * @param  {String} 标题
     * @return {Void}
     */
    _p._$setWindowTitle = function(_title){
        _n._$exec('winhelper.setWindowTitle',_title||'应用名称');
    };
    /**
     * 设置窗口图标
     * @param  {String} 图标路径
     * @return {Void}
     */
    _p._$setWindowIcon = function(_url){
        if (!_url) return;
        _n._$exec('winhelper.setWindowIconFromLocalFile',_url);
    };
    /**
     * 打开新窗体
     * @param  {String} 新窗口地址，参数通过查询形式输入，如?width=1000&height=200
     * @return {Void}
     */
    _p._$open = (function(){
        var _doParseInt = function(_value,_key,_map){
            var _int = parseInt(_value);
            if (!isNaN(_int)){
                _map[_key] = _int;
            }else if(_value=='true'||_value=='false'){
                _map[_key] = _value=='true';
            }
        };
        return function(_url){
            // TODO parse param
            var _param = _u._$query2object(_url.split('?')[1]||'');
            _u._$forIn(_param,_doParseInt);
            _param.visible = _param.visible==null?!0:_param.visible;
            _n._$exec('winhelper.launchWindow',_url,_param,_param);
        };
    })();
    /**
     * 退出应用
     * @return {Void}
     */
    _p._$exit = function(_action){
        _nt._$$Tray._$getInstance()._$hide();
        _n._$exec('app.exit',_action||'');
    };
    /**
     * 打开外部链接
     * @param  {String} 链接地址
     * @return {Void}
     */
    _p._$external = function(_url){
        _n._$exec('os.navigateExternal',_url);
    };
    /**
     * 取菜单项
     * @param  {Object} 菜单配置
     * @return {Object} 菜单项信息
     */
    _p._$getMenuItem = function(_options){
        var _item = NEJ.X({
            text:'菜单项',menu:!0,
            menu_id:0,enable:!0,
            separator:!1,children:null
        },_options);
        // cache menu
        var _menu = _mcache[_item.menu_id];
        if (!!_menu){
            if (!_u._$isArray(_menu))
                _menu = [_menu];
            _menu.push(_item);
        }else{
            _menu = _item;
        }
        _mcache[_item.menu_id] = _menu;
        return _item;
    };
    /**
     * 根据ID取菜单项
     * @return {Void}
     */
    _p._$getMenuItemById = function(_id){
        return _mcache[_id];
    };
    /**
     * 弹出菜单
     * @param  {Array} 菜单项列表
     * @return {Void}
     */
    _p._$popMenu = (function(){
        var _reg0 = /\)$/;
        var _doCheckHotKey = function(_value,_id){
            var _item = _p._$getMenuItemById(_id);
            if (!!_item&&!_reg0.test(_item.text)){
                _item.text += '('+_value+')';
            }
        };
        var _doCompleteHotKey = function(_hotkey){
            _u._$forIn(_hotkey,_doCheckHotKey);
        };
        return function(_conf){
            _doCompleteHotKey(_conf.hotkey);
            _conf = NEJ.EX({
                content:null,
                hotkey:null
            },_conf);
            if (!_conf.menu_type) _conf.menu_type = 'normal';
            _conf.hotkey = JSON.stringify(_conf.hotkey||null);
            _conf.content = JSON.stringify(_conf.content||[]);
            _n._$exec('winhelper.popupMenu',_conf);
        };
    })();
    // init document.onmenuacton
    _('window.winhelper').onmenuclick = function(_id){
        _v._$dispatchEvent(
            document,'menuaction',{
                id:_id
            }
        );
    };
    _t._$$CustomEvent._$allocate({
        element:document,
        event:'menuaction'
    });
};
NEJ.define('{lib}native/cef/api.js',
          ['{lib}base/util.js'
          ,'{lib}base/element.js'
          ,'{lib}native/command.js'
          ,'{lib}util/event/event.js'
          ,'{lib}native/cef/util/tray.js'],f);<commit_msg>cef api<commit_after>/**
 * ------------------------------------------
 * 桌面接口实现文件
 * @version  1.0
 * @author   yuqijun(yuqijun@corp.netease.com)
 * ------------------------------------------
 */
var f = function() {
    // variable declaration
    var _   = NEJ.P,
        _o  = NEJ.O,
        _e  = _('nej.e'),
        _u  = _('nej.u'),
        _v  = _('nej.v'),
        _n  = _('nej.n'),
        _t  = _('nej.ut'),
        _p  = _('nej.cef'),
        _nt = _('nej.cef.ut'),
        _mcache = {};
    /**
     * 配置窗体信息
     * @see    {nej.cef._$configWindowPosition}
     * @see    {nej.cef._$configWindowSizeLimit}
     * @param  {Object} 配置信息，其他参数详情见@see指定接口配置信息
     * @return {Void}
     */
    _p._$configWindow = function(_options){
        _p._$configWindowSizeLimit(_options);
        _p._$configWindowPosition(_options);
        if (!!_options.icon)
            _p._$setWindowIcon(_options.icon);
        if (!!_options.title)
            _p._$setWindowTitle(_options.title);
    };
    /**
     * 配置窗体位置，对齐方式定义如下

     * 水平对齐方式：
     * [ntb]
     *   名称            |  描述
     *   ----------------------
     *   left   |  左侧对齐
     *   center |  中间对齐
     *   right  |  右侧对齐
     * [/ntb]
     *
     * 垂直对齐方式：
     * [ntb]
     *   名称              |  描述
     *   ---------------------
     *   top     |  顶部对齐
     *   center  |  中间对齐
     *   bottom  |  底部对齐
     * [/ntb]
     * @api    {nej.cef._$configWindowPosition}
     * @param  {Object} 配置信息
     * @config {String}  name     窗体名称
     * @config {Number}  width    窗体宽度
     * @config {Number}  height   窗体高度
     * @config {Boolean} topmost  窗体是否置顶
     * @config {String}  align    对齐方式，格式定义：水平对齐方式+空格+垂直对齐方式，如 left top
     * @config {Object}  area     区域位置，默认自动计算，格式如：{x:0,y:0,width:100,height:200}
     * @return {Void}
     */
    _p._$configWindowPosition = (function(){
        var _reg0 = /\s+/,
            _fmap = {
                left:function(_mbox,_total){
                    return 0;
                },
                center:function(_mbox,_total){
                    return Math.floor(Math.abs(_total-_mbox)/2);
                },
                right:function(_mbox,_total){
                    return Math.abs(_total);
                }
            };
        _fmap.top = _fmap.left;
        _fmap.bottom = _fmap.right;
        return function(_options){
            _options = _options||_o;
            // set window position
            var _aligns = (_options.align||'').trim().split(_reg0),
                _position = NEJ.EX({width:0,height:0,topmost:!1},_options),
                _wkarea = _options.area||(_n._$exec('os.getSystemInfo','monitor')||_o).workArea||_o;
            _position.x = _wkarea.x+(_fmap[_aligns[0]]||_fmap.center)(_position.width,_wkarea.width);
            _position.y = _wkarea.y+(_fmap[_aligns[1]]||_fmap.center)(_position.height,_wkarea.height);
            if (!_options.name){
                _n._$exec('winhelper.setWindowPosition',_position);
            }else{
                _position.name = _options.name;
                _n._$exec('winhelper.setNativeWindowRect',_position);
            }
        };
    })();
    /**
     * 配置窗体大小限制
     * @api    {nej.cef._$configWindowSizeLimit}
     * @param  {Object} 配置信息
     * @config {Number}  minWidth  窗体最小宽度
     * @config {Number}  maxWidth  窗体最大宽度
     * @config {Number}  minHeight 窗体最小高度
     * @config {Number}  maxHeight 窗体最大高度
     */
    _p._$configWindowSizeLimit = (function(){
        // parse min/max - width/height
        var _doParseBox = function(_width,_height){
            _width = parseInt(_width);
            _height = parseInt(_height);
            var _result;
            if (!isNaN(_width)){
                _result = _result||{};
                _result.x = _width;
            }
            if (!isNaN(_height)){
                _result = _result||{};
                _result.y = _height;
            }
            return _result;
        };
        return function(_options){
            _options = _options||_o;
            _n._$exec(
                'winhelper.setWindowSizeLimit',
                _doParseBox(_options.minWidth,_options.minHeight),
                _doParseBox(_options.maxWidth,_options.maxHeight)
            );
        };
    })();
    /**
     * 显示窗体,但窗体不会放在最上层
     * @api    {nej.cef._$showWindow}
     * @return {Void}
     */
    _p._$showWindow = function(_name){
        if (!_name){
            _n._$exec('winhelper.showWindow','show');
        }else{
            var _area = (_n._$exec('os.getSystemInfo','monitor')||_o).workArea||_o;
            _n._$exec('winhelper.setNativeWindowShow',_name,!0,_area);
        }
    };
    /**
     * 隐藏窗体
     * @api    {nej.cef._$hideWindow}
     * @return {Void}
     */
    _p._$hideWindow = function(_name){
        if (!_name){
            _n._$exec('winhelper.showWindow','hide');
        }else{
            var _area = (_n._$exec('os.getSystemInfo','monitor')||_o).workArea||_o;
            _n._$exec('winhelper.setNativeWindowShow',_name,!1,_area);
        }
    };
    /**
     * 关闭窗体，销毁窗体
     * @api    {nej.cef._$closeWindow}
     * @return {Void}
     */
    _p._$closeWindow = function(){
        _n._$exec('winhelper.destroyWindow');
    };
    /**
     * 窗口前置
     * @return {Void}
     */
    _p._$topWindow = function(_name){
        _p._$showWindow(_name);
        if (!_name){
            _n._$exec('winhelper.bringWindowToTop');
        }
    };
    /**
     * 设置窗口标题
     * @param  {String} 标题
     * @return {Void}
     */
    _p._$setWindowTitle = function(_title){
        _n._$exec('winhelper.setWindowTitle',_title||'应用名称');
    };
    /**
     * 设置窗口图标
     * @param  {String} 图标路径
     * @return {Void}
     */
    _p._$setWindowIcon = function(_url){
        if (!_url) return;
        _n._$exec('winhelper.setWindowIconFromLocalFile',_url);
    };
    /**
     * 打开新窗体
     * @param  {String} 新窗口地址，参数通过查询形式输入，如?width=1000&height=200
     * @return {Void}
     */
    _p._$open = (function(){
        var _doParseInt = function(_value,_key,_map){
            var _int = parseInt(_value);
            if (!isNaN(_int)){
                _map[_key] = _int;
            }else if(_value=='true'||_value=='false'){
                _map[_key] = _value=='true';
            }
        };
        return function(_url){
            // TODO parse param
            var _param = _u._$query2object(_url.split('?')[1]||'');
            _u._$forIn(_param,_doParseInt);
            _param.visible = _param.visible==null?!0:_param.visible;
            _n._$exec('winhelper.launchWindow',_url,_param,_param);
        };
    })();
    /**
     * 退出应用
     * @return {Void}
     */
    _p._$exit = function(_action){
        _nt._$$Tray._$getInstance()._$hide();
        _n._$exec('app.exit',_action||'');
    };
    /**
     * 打开外部链接
     * @param  {String} 链接地址
     * @return {Void}
     */
    _p._$external = function(_url){
        _n._$exec('os.navigateExternal',_url);
    };
    /**
     * 取菜单项
     * @param  {Object} 菜单配置
     * @return {Object} 菜单项信息
     */
    _p._$getMenuItem = function(_options){
        var _item = NEJ.X({
            text:'菜单项',menu:!0,
            menu_id:0,enable:!0,
            separator:!1,children:null
        },_options);
        // cache menu
        var _menu = _mcache[_item.menu_id];
        if (!!_menu){
            if (!_u._$isArray(_menu))
                _menu = [_menu];
            _menu.push(_item);
        }else{
            _menu = _item;
        }
        _mcache[_item.menu_id] = _menu;
        return _item;
    };
    /**
     * 根据ID取菜单项
     * @return {Void}
     */
    _p._$getMenuItemById = function(_id){
        return _mcache[_id];
    };
    /**
     * 弹出菜单
     * @param  {Array} 菜单项列表
     * @return {Void}
     */
    _p._$popMenu = (function(){
        var _reg0 = /\)$/,
            _reg1 = /\s+/g;
        var _doCheckHotKey = function(_value,_id){
            var _item = _p._$getMenuItemById(_id);
            if (!!_item&&!_reg0.test(_item.text)){
                _item.text += '('+_value.replace(_reg1,'+')+')';
            }
        };
        var _doCompleteHotKey = function(_hotkey){
            _u._$forIn(_hotkey,_doCheckHotKey);
        };
        return function(_conf){
            _doCompleteHotKey(_conf.hotkey);
            _conf = NEJ.EX({
                content:null,
                hotkey:null
            },_conf);
            if (!_conf.menu_type) _conf.menu_type = 'normal';
            _conf.hotkey = JSON.stringify(_conf.hotkey||null);
            _conf.content = JSON.stringify(_conf.content||[]);
            _n._$exec('winhelper.popupMenu',_conf);
        };
    })();
    // init document.onmenuacton
    _('window.winhelper').onmenuclick = function(_id){
        _v._$dispatchEvent(
            document,'menuaction',{
                id:_id
            }
        );
    };
    _t._$$CustomEvent._$allocate({
        element:document,
        event:'menuaction'
    });
};
NEJ.define('{lib}native/cef/api.js',
          ['{lib}base/util.js'
          ,'{lib}base/element.js'
          ,'{lib}native/command.js'
          ,'{lib}util/event/event.js'
          ,'{lib}native/cef/util/tray.js'],f);<|endoftext|>


<commit_before><!--
var total=1;
var db = new Array();

// -- Enter Values Here --
// Format: dbAdd(parent[true|false] , description, URL [blank for nohref], level , TARGET [blank for "content"], image [1=yes])

// Get current cookie setting
var current=getCurrState()
function getCurrState() {
  var label = "currState="
  var labelLen = label.length
  var cLen = document.cookie.length
  var i = 0
  while (i < cLen) {
    var j = i + labelLen
    if (document.cookie.substring(i,j) == label) {
      var cEnd = document.cookie.indexOf(";",j)
      if (cEnd == -1) { cEnd = document.cookie.length }
      return unescape(document.cookie.substring(j,cEnd))
    }
    i++
  }
  return ""
}

// Record current settings in cookie
function setCurrState(setting) {
  var expire = new Date();
  expire.setTime(expire.getTime() + ( 60*60*1000 ) ); // expire in 1 hour
  document.cookie = "currState=" + escape(setting) + "; expires=" + expire.toGMTString();
  }

// Add an entry to the database
function dbAdd(mother,display,URL,indent,top,open,author,mailto,comment) {
  db[total] = new Object;
  db[total].mother = mother
  db[total].display = display
  db[total].URL = URL
  db[total].indent = indent
  db[total].top = top
  db[total].open = open
  db[total].image = ""
  db[total].author = author
  db[total].mailto = mailto
  db[total].comment = comment
  total++
  }

// toggles an outline mother entry, storing new value in the cookie
function toggle(n) {
  if (n != 0) {
    var newString = ""
    var expanded = current.substring(n-1,n) // of clicked item
    newString += current.substring(0,n-1)
    newString += expanded ^ 1 // Bitwise XOR clicked item
    newString += current.substring(n,current.length)
    setCurrState(newString) // write new state back to cookie
  }
}

// Reload page
function reload() {
  //   if (navigator.userAgent.toLowerCase().indexOf('opera') == -1) {
  //        history.go(0);
  //     } else {
      if (document.images) {
         location.replace(location.href);
      } else {
         location.href(location.href);
      }
  //     }
}

// returns padded spaces (in mulTIPles of 2) for indenting
function pad(n) {
  var result = ""
  for (var i = 1; i <= n; i++) { result += "    " }
  return result
}

// Expand everything
function explode() {
  current = "";
  initState="";
  for (var i = 1; i < db.length; i++) {
    initState += "1"
    current += "1"
    }
  setCurrState(initState);
  reload();
  }

// Collapse everything
function contract() {
  current = "";
  initState="";
  for (var i = 1; i < db.length; i++) {
    initState += "0"
    current += "0"
    }
  setCurrState(initState);
  reload();
  }

function tree_close() {
  window.parent.location = window.parent.content.location;
  }

//end -->
<commit_msg>BUG: Replacing XML tags by real char<commit_after><!--
var total=1;
var db = new Array();

// -- Enter Values Here --
// Format: dbAdd(parent[true|false] , description, URL [blank for nohref], level , TARGET [blank for "content"], image [1=yes])

// Get current cookie setting
var current=getCurrState()
function getCurrState() {
  var label = "currState="
  var labelLen = label.length
  var cLen = document.cookie.length
  var i = 0
  while (i < cLen) {
    var j = i + labelLen
    if (document.cookie.substring(i,j) == label) {
      var cEnd = document.cookie.indexOf(";",j)
      if (cEnd == -1) { cEnd = document.cookie.length }
      return unescape(document.cookie.substring(j,cEnd))
    }
    i++
  }
  return ""
}

// Record current settings in cookie
function setCurrState(setting) {
  var expire = new Date();
  expire.setTime(expire.getTime() + ( 60*60*1000 ) ); // expire in 1 hour
  document.cookie = "currState=" + escape(setting) + "; expires=" + expire.toGMTString();
  }

function XMLStrFormat(str)
{

  str = str.replace(/&apos;/,"\'");
  return str;
}

// Add an entry to the database
function dbAdd(mother,display,URL,indent,top,open,author,mailto,comment) {
  db[total] = new Object;
  db[total].mother = mother
  db[total].display = display
  db[total].URL = URL
  db[total].indent = indent
  db[total].top = top
  db[total].open = open
  db[total].image = ""
  db[total].author = author
  db[total].mailto = mailto
  db[total].comment = XMLStrFormat(comment)
  total++
  }

// toggles an outline mother entry, storing new value in the cookie
function toggle(n) {
  if (n != 0) {
    var newString = ""
    var expanded = current.substring(n-1,n) // of clicked item
    newString += current.substring(0,n-1)
    newString += expanded ^ 1 // Bitwise XOR clicked item
    newString += current.substring(n,current.length)
    setCurrState(newString) // write new state back to cookie
  }
}

// Reload page
function reload() {
  //   if (navigator.userAgent.toLowerCase().indexOf('opera') == -1) {
  //        history.go(0);
  //     } else {
      if (document.images) {
         location.replace(location.href);
      } else {
         location.href(location.href);
      }
  //     }
}

// returns padded spaces (in mulTIPles of 2) for indenting
function pad(n) {
  var result = ""
  for (var i = 1; i <= n; i++) { result += "    " }
  return result
}

// Expand everything
function explode() {
  current = "";
  initState="";
  for (var i = 1; i < db.length; i++) {
    initState += "1"
    current += "1"
    }
  setCurrState(initState);
  reload();
  }

// Collapse everything
function contract() {
  current = "";
  initState="";
  for (var i = 1; i < db.length; i++) {
    initState += "0"
    current += "0"
    }
  setCurrState(initState);
  reload();
  }

function tree_close() {
  window.parent.location = window.parent.content.location;
  }

//end -->
<|endoftext|>


<commit_before>var env = require('../env.js');
var gulp = require('gulp');
var browserSync = require('browser-sync');
var sourcemaps = require('gulp-sourcemaps');
var changed = require('gulp-changed');
var autoprefixer = require('gulp-autoprefixer');
var cssPrefix = require('gulp-css-prefix');
var gulpif = require('gulp-if');
var sass = require('gulp-sass');

module.exports = function() {
  return gulp.src(env.folder.src + '/styles/main.sass')
    .pipe(sourcemaps.init())
    .pipe(changed(env.folder.src + '/styles/**/*.sass'))
    .pipe(sass({
      includePaths: ['./node_modules/']
    }).on('error', sass.logError))
    .pipe(sass().on('error', sass.logError))
    .pipe(gulpif(
      env.namespaceCSS,
      cssPrefix({'parentClass': env.namespaceCSS})
    ))
    .pipe(autoprefixer({
      browsers: env.compatibility,
      cascade: true
    }))
    .pipe(sourcemaps.write('../sourcemaps'))
    .pipe(gulp.dest(env.folder.dev + '/styles/'))
    .pipe(browserSync.reload({stream:true}));
};
<commit_msg>gulp-util is uset for proper error handling<commit_after>var env = require('../env.js');
var gulp = require('gulp');
var browserSync = require('browser-sync');
var sourcemaps = require('gulp-sourcemaps');
var changed = require('gulp-changed');
var autoprefixer = require('gulp-autoprefixer');
var cssPrefix = require('gulp-css-prefix');
var gulpif = require('gulp-if');
var sass = require('gulp-sass');
var util = require('gulp-util');

module.exports = function() {
   return gulp.src(env.folder.src + '/styles/main.sass')
    .pipe(sourcemaps.init())
    .pipe(changed(env.folder.src + '/styles/**/*.sass'))
    .pipe(sass({
      includePaths: ['./node_modules/']
    }))
    .on('error', function (err) {
      util.log(err.message);
      this.emit('end');
    })
    .pipe(gulpif(
      env.namespaceCSS,
      cssPrefix({'parentClass': env.namespaceCSS})
    ))
    .pipe(autoprefixer({
      browsers: env.compatibility,
      cascade: true
    }))
    .pipe(sourcemaps.write('../sourcemaps'))
    .pipe(gulp.dest(env.folder.dev + '/styles/'))
    .pipe(browserSync.reload({stream:true}));
};
<|endoftext|>


<commit_before>// ==========================================================================
// Project:   MySystem.nodesController
// Copyright: ©2010 Concord Consortium
// ==========================================================================
/*globals MySystem */

/** @class

  The whole set of nodes in the system.

  @extends SC.Object
*/
MySystem.nodesController = SC.ArrayController.create( SC.CollectionViewDelegate,
/** @scope MySystem.nodesController.prototype */ {

  // the in-progress links originating and ending terminals
  dragLinkSrcTerminal:     null,
  dragLinkEndTerminal:     null,

  // FIXME dummy method for backward compatibility
  unselectAll: function() {
    this.deselectObjects(this.get('selection'));
  },

  collectionViewDeleteContent: function (view, content, indices) {
    // destroy the records
    var recordsToDestroy = indices.map( function (idx) {
      return this.objectAt(idx);
    }, this);

    recordsToDestroy.invoke('destroy');
  },

  collectionViewSelectionForProposedSelection: function(view, sel) {
    // Is this a shift-click?
    if (view.get('mouseDownInfo') && view.get('mouseDownInfo').event.shiftKey) {
      return null ; // No change to selection
    }
    else {
      return sel ; // Accept new selected set
    }
  },

  propertyEditing: function() {
    MySystem.statechart.sendEvent('diagramSelectionChanged', { });
  }.observes('selection'),

  // If the selection changes on nodes or links, grab the top layer and call focus().
  // This forces the browser focus back onto the application, which ensures that
  // keyboard and other events are properly directed here if we are embedding in an iframe.
  //
  // We need to focus again on every selection change, to account for an author who is
  // going back and forth between an author iframe and preview iframe.
  //
  // Having it here is a bit of a hack, and there might be some more stardard way of dealing
  // with this issue.
  focusMainPaneOnSelectionChange: function() {
    MySystem.mainPage.get('mainPane').get('layer').focus();
  }.observes('selection')
});
<commit_msg>Fix failing tests caused by mainPane not having a layer in tests<commit_after>// ==========================================================================
// Project:   MySystem.nodesController
// Copyright: ©2010 Concord Consortium
// ==========================================================================
/*globals MySystem */

/** @class

  The whole set of nodes in the system.

  @extends SC.Object
*/
MySystem.nodesController = SC.ArrayController.create( SC.CollectionViewDelegate,
/** @scope MySystem.nodesController.prototype */ {

  // the in-progress links originating and ending terminals
  dragLinkSrcTerminal:     null,
  dragLinkEndTerminal:     null,

  // FIXME dummy method for backward compatibility
  unselectAll: function() {
    this.deselectObjects(this.get('selection'));
  },

  collectionViewDeleteContent: function (view, content, indices) {
    // destroy the records
    var recordsToDestroy = indices.map( function (idx) {
      return this.objectAt(idx);
    }, this);

    recordsToDestroy.invoke('destroy');
  },

  collectionViewSelectionForProposedSelection: function(view, sel) {
    // Is this a shift-click?
    if (view.get('mouseDownInfo') && view.get('mouseDownInfo').event.shiftKey) {
      return null ; // No change to selection
    }
    else {
      return sel ; // Accept new selected set
    }
  },

  propertyEditing: function() {
    MySystem.statechart.sendEvent('diagramSelectionChanged', { });
  }.observes('selection'),

  // If the selection changes on nodes or links, grab the top layer and call focus().
  // This forces the browser focus back onto the application, which ensures that
  // keyboard and other events are properly directed here if we are embedding in an iframe.
  //
  // We need to focus again on every selection change, to account for an author who is
  // going back and forth between an author iframe and preview iframe.
  //
  // Having it here is a bit of a hack, and there might be some more stardard way of dealing
  // with this issue.
  focusMainPaneOnSelectionChange: function() {
    if (MySystem.mainPage.get('mainPane') && MySystem.mainPage.get('mainPane').get('layer')){
      MySystem.mainPage.get('mainPane').get('layer').focus();
    }
  }.observes('selection')
});
<|endoftext|>


<commit_before>var _ = require('underscore');
var Backbone = require('backbone');
var UserModel = require('../../../../../../javascripts/cartodb3/data/user-model');
var AnalysisDefinitionNodesCollection = require('../../../../../../javascripts/cartodb3/data/analysis-definition-nodes-collection');
var LayerDefinitionModel = require('../../../../../../javascripts/cartodb3/data/layer-definition-model');
var AnalysisFormsCollection = require('../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analysis-forms-collection');
var AnalysesContentView = require('../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analyses-content-view');
var ConfigModel = require('../../../../../../javascripts/cartodb3/data/config-model');
var LayerContentModel = require('../../../../../../javascripts/cartodb3/data/layer-content-model');
var analysisPlaceholderTemplate = require('../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analyses-placeholder.tpl');
var analysisSQLErrorTemplate = require('../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analyses-sql-error.tpl');
var actionErrorTemplate = require('../../../../../../javascripts/cartodb3/editor/layers/sql-error-action.tpl');
var ScrollView = require('../../../../../../javascripts/cartodb3/components/scroll/scroll-view');
var AnalysisControlsView = require('../../../../../../javascripts/cartodb3/components/scroll/scroll-view');
var Router = require('../../../../../../javascripts/cartodb3/routes/router');
var AnalysesService = require('../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analyses-service');

describe('editor/layers/layer-content-view/analyses-content-view', function () {
  var view;
  var userActions;
  var analysisFormsCollection;
  var layerDefinitionModel;
  var analysisDefinitionNodesCollection;
  var overlayModel;
  var layerContentModel;
  var renderTooltipSpy;
  var renderSpy;
  var onLayerDefSourceChangedSpy;
  var setDefaultSelectedNodeIdSpy;
  var toggleOverlaySpy;
  var removeUselessModelsSpy;
  var nodeA0;
  var nodeA1;
  var nodeB1;
  var formA0;
  var formA1;
  var formB1;

  var createViewFn = function (options) {
    var configModel = new ConfigModel({
      user_name: 'pepe'
    });

    var userModel = new UserModel({}, {
      configModel: configModel
    });
    spyOn(userModel, 'fetch');

    userActions = jasmine.createSpyObj('userActions', ['saveLayer']);

    overlayModel = new Backbone.Model({
      visible: false
    });

    analysisDefinitionNodesCollection = new AnalysisDefinitionNodesCollection(null, {
      configModel: configModel,
      userModel: userModel
    });

    nodeA0 = analysisDefinitionNodesCollection.add({
      id: 'a0',
      type: 'source',
      table_name: 'foo',
      query: 'SELECT * FROM table_name'
    });

    nodeA1 = analysisDefinitionNodesCollection.add({
      id: 'a1',
      type: 'buffer',
      radio: 300,
      source: 'a0'
    });

    nodeB1 = analysisDefinitionNodesCollection.add({
      id: 'b1',
      type: 'buffer',
      radio: 300,
      source: 'a1'
    });

    layerDefinitionModel = new LayerDefinitionModel({
      id: 'a0',
      letter: 'a',
      source: 'a0',
      options: {
        type: 'CartoDB',
        table_name: 'foo',
        cartocss: 'asd',
        source: 'a0'
      }
    }, {
      configModel: configModel,
      collection: new Backbone.Collection(),
      parse: true
    });
    layerDefinitionModel.findAnalysisDefinitionNodeModel = function (id) {
      switch (id) {
        case 'a0': return nodeA0;
        case 'a1': return nodeA1;
      }
    };

    analysisFormsCollection = new AnalysisFormsCollection(null, {
      configModel: configModel,
      userActions: userActions,
      layerDefinitionModel: layerDefinitionModel,
      analysisSourceOptionsModel: new Backbone.Model()
    });
    analysisFormsCollection.isEmpty = function () { return true; };

    layerContentModel = new LayerContentModel({}, {
      querySchemaModel: new Backbone.Model(),
      queryGeometryModel: new Backbone.Model(),
      queryRowsCollection: new Backbone.Collection()
    });
    layerContentModel.isErrored = function () { return false; };

    var defaultOptions = {
      userActions: userActions,
      analysisDefinitionNodesCollection: analysisDefinitionNodesCollection,
      analysisFormsCollection: analysisFormsCollection,
      layerDefinitionModel: layerDefinitionModel,
      userModel: userModel,
      configModel: configModel,
      stackLayoutModel: {},
      overlayModel: overlayModel,
      layerContentModel: layerContentModel
    };

    var view = new AnalysesContentView(_.extend(defaultOptions, options));

    renderTooltipSpy = spyOn(view, '_renderTooltip');

    return view;
  };

  beforeEach(function () {
    renderSpy = spyOn(AnalysesContentView.prototype, 'render');
    onLayerDefSourceChangedSpy = spyOn(AnalysesContentView.prototype, '_onLayerDefSourceChanged');
    setDefaultSelectedNodeIdSpy = spyOn(AnalysesContentView.prototype, '_setDefaultSelectedNodeId');
    toggleOverlaySpy = spyOn(AnalysesContentView.prototype, '_toggleOverlay');
    removeUselessModelsSpy = spyOn(AnalysisFormsCollection.prototype, 'removeUselessModels');

    view = createViewFn();
  });

  describe('.render', function () {
    it('should render properly', function () {
      renderSpy.and.callThrough();

      spyOn(view, '_initViews');

      view.render();

      expect(view._initViews).toHaveBeenCalled();
      expect(toggleOverlaySpy).toHaveBeenCalled();
    });

    it('should not have any leaks', function () {
      renderSpy.and.callThrough();

      view.render();

      expect(view).toHaveNoLeaks();
    });

    describe('is errored', function () {
      it('should render error', function () {
        renderSpy.and.callThrough();
        view._isErrored = function () { return true; };
        spyOn(view, '_renderError');

        view.render();

        expect(view._renderError).toHaveBeenCalled();
      });
    });
  });

  describe('._isErrored', function () {
    it('should return if layer content model is errored', function () {
      expect(view._isErrored()).toBe(false);

      layerContentModel.isErrored = function () { return true; };

      expect(view._isErrored()).toBe(true);
    });
  });

  describe('._renderError', function () {
    it('should render error', function () {
      var template = analysisSQLErrorTemplate({
        body: _t('editor.error-query.body', {
          action: actionErrorTemplate({
            label: _t('editor.error-query.label')
          })
        })
      });
      spyOn(view.$el, 'html');

      view._renderError();

      expect(view.$el.html).toHaveBeenCalledWith(template);
    });
  });

  describe('._initViews', function () {
    it('should init views', function () {
      var template = analysisPlaceholderTemplate();
      spyOn(view.$el, 'html');

      view._initViews();

      expect(view.$el.html).toHaveBeenCalledWith(template);
      expect(renderTooltipSpy).toHaveBeenCalled();
    });

    describe('analysis forms collection is not empty', function () {
      it('should init views', function () {
        analysisFormsCollection.isEmpty = function () { return false; };

        var formModel = 'wadus';

        spyOn(view, '_getFormModel').and.returnValue(formModel);
        spyOn(view, '_renderScrollableListView');
        spyOn(view, '_renderControlsView');

        view._initViews();

        expect(view._renderScrollableListView).toHaveBeenCalledWith(formModel);
        expect(view._renderControlsView).toHaveBeenCalledWith(formModel);
      });
    });
  });

  describe('._toggleOverlay', function () {
    it('should toggle overlay', function () {
      toggleOverlaySpy.and.callThrough();
      expect(view.$el.hasClass('is-disabled')).toBe(false);

      overlayModel.set('visible', true, { silent: true });
      view._toggleOverlay();

      expect(view.$el.hasClass('is-disabled')).toBe(true);
    });
  });

  describe('_renderTooltip', function () {
    it('should renderTooltip', function () {
      renderSpy.and.callThrough();

      view.render();

      expect(_.size(view._subviews)).toBe(0);

      renderTooltipSpy.and.callThrough();
      view._renderTooltip();

      expect(_.size(view._subviews)).toBe(1);
    });
  });

  describe('_initBinds', function () {
    it('should listen to layerDefinitionModel change source', function () {
      layerDefinitionModel.set('source', 'a1');

      expect(onLayerDefSourceChangedSpy).toHaveBeenCalled();
    });

    it('should listen to analysisFormsCollection destroyedModels', function () {
      analysisFormsCollection.trigger('destroyedModels');

      expect(setDefaultSelectedNodeIdSpy).toHaveBeenCalled();
    });

    it('should listen to analysisFormsCollection remove', function () {
      analysisFormsCollection.reset([{}]);
      analysisFormsCollection.remove(analysisFormsCollection.at(0));

      expect(setDefaultSelectedNodeIdSpy).toHaveBeenCalled();
    });

    it('should listen to overlayModel change visible', function () {
      overlayModel.set('visible', true);

      expect(toggleOverlaySpy).toHaveBeenCalled();
    });
  });

  describe('_renderScrollableListView', function () {
    it('should render scrollable list view', function () {
      spyOn(ScrollView.prototype, 'render').and.returnValue(this);

      view._renderScrollableListView();

      expect(_.size(view._subviews)).toBe(1); // ['ScrollView']
    });
  });

  describe('_renderControlsView', function () {
    it('should render constrols view', function () {
      spyOn(AnalysisControlsView.prototype, 'render').and.returnValue(this);

      var formModel = new Backbone.Model({
        id: 'wadus',
        type: 'type'
      });

      view._renderControlsView(formModel);

      expect(_.size(view._subviews)).toBe(1); // ['AnalysisControlsView']
    });
  });

  describe('_getFormModel', function () {
    afterEach(function () {
      analysisFormsCollection.reset([]);
    });

    it('should get form model', function () {
      formA0 = analysisFormsCollection.add(nodeA0.attributes);

      view = createViewFn({
        analysisFormsCollection: analysisFormsCollection
      });

      expect(view._getFormModel()).toBe(formA0);
    });

    describe('with selectedNodeId', function () {
      it('should get form model', function () {
        formA0 = analysisFormsCollection.add(nodeA0.attributes);
        formA1 = analysisFormsCollection.add(nodeA1.attributes);

        view = createViewFn({
          selectedNodeId: formA1.get('id'),
          analysisFormsCollection: analysisFormsCollection
        });

        expect(view._getFormModel()).toBe(formA1);
      });
    });
  });

  describe('_getQuerySchemaModelForEstimation', function () {
    afterEach(function () {
      analysisFormsCollection.reset([]);
    });

    it('should get QuerySchemaModel', function () {
      spyOn(layerDefinitionModel, 'getAnalysisDefinitionNodeModel').and.returnValue(nodeA0);

      view = createViewFn({
        analysisFormsCollection: analysisFormsCollection
      });

      expect(view._getQuerySchemaModelForEstimation()).toBe(nodeA0.querySchemaModel);
    });

    describe('with selectedNodeId', function () {
      it('should get form model', function () {
        formA0 = analysisFormsCollection.add(nodeA0.attributes);
        formA1 = analysisFormsCollection.add(nodeA1.attributes);
        formB1 = analysisFormsCollection.add(nodeB1.attributes);

        view = createViewFn({
          selectedNodeId: formB1.get('id'),
          analysisFormsCollection: analysisFormsCollection
        });

        expect(view._getQuerySchemaModelForEstimation()).toBe(nodeA1.querySchemaModel);
      });
    });
  });

  describe('_onLayerDefSourceChanged', function () {
    it('should remove models from the analysis forms collection', function () {
      onLayerDefSourceChangedSpy.and.callThrough();

      view._onLayerDefSourceChanged();

      expect(removeUselessModelsSpy).toHaveBeenCalled();
    });
  });

  describe('_setDefaultSelectedNodeId', function () {
    afterEach(function () {
      analysisFormsCollection.reset([]);
    });

    it('should call Route.goToAnalysisNode with selectedNodeId', function () {
      setDefaultSelectedNodeIdSpy.and.callThrough();
      spyOn(Router, 'goToAnalysisNode');
      spyOn(AnalysesService, 'clearNotAppliedAnalysis');
      formA0 = analysisFormsCollection.add(nodeA0.attributes);

      view._setDefaultSelectedNodeId();

      expect(AnalysesService.clearNotAppliedAnalysis).toHaveBeenCalledWith(nodeA0.get('id'));
      expect(Router.goToAnalysisNode).toHaveBeenCalledWith(layerDefinitionModel.get('id'), nodeA0.get('id'));
    });
  });
});
<commit_msg>Add missing test to analyses-content-view<commit_after>var _ = require('underscore');
var Backbone = require('backbone');
var UserModel = require('../../../../../../javascripts/cartodb3/data/user-model');
var AnalysisDefinitionNodesCollection = require('../../../../../../javascripts/cartodb3/data/analysis-definition-nodes-collection');
var LayerDefinitionModel = require('../../../../../../javascripts/cartodb3/data/layer-definition-model');
var AnalysisFormsCollection = require('../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analysis-forms-collection');
var AnalysesContentView = require('../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analyses-content-view');
var ConfigModel = require('../../../../../../javascripts/cartodb3/data/config-model');
var LayerContentModel = require('../../../../../../javascripts/cartodb3/data/layer-content-model');
var analysisPlaceholderTemplate = require('../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analyses-placeholder.tpl');
var analysisSQLErrorTemplate = require('../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analyses-sql-error.tpl');
var actionErrorTemplate = require('../../../../../../javascripts/cartodb3/editor/layers/sql-error-action.tpl');
var ScrollView = require('../../../../../../javascripts/cartodb3/components/scroll/scroll-view');
var AnalysisControlsView = require('../../../../../../javascripts/cartodb3/components/scroll/scroll-view');
var Router = require('../../../../../../javascripts/cartodb3/routes/router');
var AnalysesService = require('../../../../../../javascripts/cartodb3/editor/layers/layer-content-views/analyses/analyses-service');

describe('editor/layers/layer-content-view/analyses-content-view', function () {
  var view;
  var userActions;
  var analysisFormsCollection;
  var layerDefinitionModel;
  var analysisDefinitionNodesCollection;
  var overlayModel;
  var layerContentModel;
  var renderTooltipSpy;
  var renderSpy;
  var onLayerDefSourceChangedSpy;
  var setDefaultSelectedNodeIdSpy;
  var toggleOverlaySpy;
  var removeUselessModelsSpy;
  var onAnalysisFormsCollectionSyncSpy;
  var nodeA0;
  var nodeA1;
  var nodeB1;
  var formA0;
  var formA1;
  var formB1;

  var createViewFn = function (options) {
    var configModel = new ConfigModel({
      user_name: 'pepe'
    });

    var userModel = new UserModel({}, {
      configModel: configModel
    });
    spyOn(userModel, 'fetch');

    userActions = jasmine.createSpyObj('userActions', ['saveLayer']);

    overlayModel = new Backbone.Model({
      visible: false
    });

    analysisDefinitionNodesCollection = new AnalysisDefinitionNodesCollection(null, {
      configModel: configModel,
      userModel: userModel
    });

    nodeA0 = analysisDefinitionNodesCollection.add({
      id: 'a0',
      type: 'source',
      table_name: 'foo',
      query: 'SELECT * FROM table_name'
    });

    nodeA1 = analysisDefinitionNodesCollection.add({
      id: 'a1',
      type: 'buffer',
      radio: 300,
      source: 'a0'
    });

    nodeB1 = analysisDefinitionNodesCollection.add({
      id: 'b1',
      type: 'buffer',
      radio: 300,
      source: 'a1'
    });

    layerDefinitionModel = new LayerDefinitionModel({
      id: 'a0',
      letter: 'a',
      source: 'a0',
      options: {
        type: 'CartoDB',
        table_name: 'foo',
        cartocss: 'asd',
        source: 'a0'
      }
    }, {
      configModel: configModel,
      collection: new Backbone.Collection(),
      parse: true
    });
    layerDefinitionModel.findAnalysisDefinitionNodeModel = function (id) {
      switch (id) {
        case 'a0': return nodeA0;
        case 'a1': return nodeA1;
      }
    };

    analysisFormsCollection = new AnalysisFormsCollection(null, {
      configModel: configModel,
      userActions: userActions,
      layerDefinitionModel: layerDefinitionModel,
      analysisSourceOptionsModel: new Backbone.Model()
    });
    analysisFormsCollection.isEmpty = function () { return true; };

    layerContentModel = new LayerContentModel({}, {
      querySchemaModel: new Backbone.Model(),
      queryGeometryModel: new Backbone.Model(),
      queryRowsCollection: new Backbone.Collection()
    });
    layerContentModel.isErrored = function () { return false; };

    var defaultOptions = {
      userActions: userActions,
      analysisDefinitionNodesCollection: analysisDefinitionNodesCollection,
      analysisFormsCollection: analysisFormsCollection,
      layerDefinitionModel: layerDefinitionModel,
      userModel: userModel,
      configModel: configModel,
      stackLayoutModel: {},
      overlayModel: overlayModel,
      layerContentModel: layerContentModel
    };

    var view = new AnalysesContentView(_.extend(defaultOptions, options));

    renderTooltipSpy = spyOn(view, '_renderTooltip');

    return view;
  };

  beforeEach(function () {
    renderSpy = spyOn(AnalysesContentView.prototype, 'render');
    onLayerDefSourceChangedSpy = spyOn(AnalysesContentView.prototype, '_onLayerDefSourceChanged');
    setDefaultSelectedNodeIdSpy = spyOn(AnalysesContentView.prototype, '_setDefaultSelectedNodeId');
    toggleOverlaySpy = spyOn(AnalysesContentView.prototype, '_toggleOverlay');
    onAnalysisFormsCollectionSyncSpy = spyOn(AnalysesContentView.prototype, '_onAnalysisFormsCollectionSync');
    removeUselessModelsSpy = spyOn(AnalysisFormsCollection.prototype, 'removeUselessModels');

    view = createViewFn();
  });

  describe('.render', function () {
    it('should render properly', function () {
      renderSpy.and.callThrough();

      spyOn(view, '_initViews');

      view.render();

      expect(view._initViews).toHaveBeenCalled();
      expect(toggleOverlaySpy).toHaveBeenCalled();
    });

    it('should not have any leaks', function () {
      renderSpy.and.callThrough();

      view.render();

      expect(view).toHaveNoLeaks();
    });

    describe('is errored', function () {
      it('should render error', function () {
        renderSpy.and.callThrough();
        view._isErrored = function () { return true; };
        spyOn(view, '_renderError');

        view.render();

        expect(view._renderError).toHaveBeenCalled();
      });
    });
  });

  describe('._isErrored', function () {
    it('should return if layer content model is errored', function () {
      expect(view._isErrored()).toBe(false);

      layerContentModel.isErrored = function () { return true; };

      expect(view._isErrored()).toBe(true);
    });
  });

  describe('._renderError', function () {
    it('should render error', function () {
      var template = analysisSQLErrorTemplate({
        body: _t('editor.error-query.body', {
          action: actionErrorTemplate({
            label: _t('editor.error-query.label')
          })
        })
      });
      spyOn(view.$el, 'html');

      view._renderError();

      expect(view.$el.html).toHaveBeenCalledWith(template);
    });
  });

  describe('._initViews', function () {
    it('should init views', function () {
      var template = analysisPlaceholderTemplate();
      spyOn(view.$el, 'html');

      view._initViews();

      expect(view.$el.html).toHaveBeenCalledWith(template);
      expect(renderTooltipSpy).toHaveBeenCalled();
    });

    describe('analysis forms collection is not empty', function () {
      it('should init views', function () {
        analysisFormsCollection.isEmpty = function () { return false; };

        var formModel = 'wadus';

        spyOn(view, '_getFormModel').and.returnValue(formModel);
        spyOn(view, '_renderScrollableListView');
        spyOn(view, '_renderControlsView');

        view._initViews();

        expect(view._renderScrollableListView).toHaveBeenCalledWith(formModel);
        expect(view._renderControlsView).toHaveBeenCalledWith(formModel);
      });
    });
  });

  describe('._toggleOverlay', function () {
    it('should toggle overlay', function () {
      toggleOverlaySpy.and.callThrough();
      expect(view.$el.hasClass('is-disabled')).toBe(false);

      overlayModel.set('visible', true, { silent: true });
      view._toggleOverlay();

      expect(view.$el.hasClass('is-disabled')).toBe(true);
    });
  });

  describe('_renderTooltip', function () {
    it('should renderTooltip', function () {
      renderSpy.and.callThrough();

      view.render();

      expect(_.size(view._subviews)).toBe(0);

      renderTooltipSpy.and.callThrough();
      view._renderTooltip();

      expect(_.size(view._subviews)).toBe(1);
    });
  });

  describe('_initBinds', function () {
    it('should listen to layerDefinitionModel change source', function () {
      layerDefinitionModel.set('source', 'a1');

      expect(onLayerDefSourceChangedSpy).toHaveBeenCalled();
    });

    it('should listen to analysisFormsCollection destroyedModels', function () {
      analysisFormsCollection.trigger('destroyedModels');

      expect(setDefaultSelectedNodeIdSpy).toHaveBeenCalled();
    });

    it('should listen to analysisFormsCollection remove', function () {
      analysisFormsCollection.reset([{}]);
      analysisFormsCollection.remove(analysisFormsCollection.at(0));

      expect(setDefaultSelectedNodeIdSpy).toHaveBeenCalled();
    });

    it('should listen to overlayModel change visible', function () {
      overlayModel.set('visible', true);

      expect(toggleOverlaySpy).toHaveBeenCalled();
    });

    it('should listen to analysisFormsCollection change persisted', function () {
      var analysisFormModel = analysisFormsCollection.add({ persisted: false });
      analysisFormModel.set('persisted', true);

      expect(onAnalysisFormsCollectionSyncSpy).toHaveBeenCalled();
    });
  });

  describe('_renderScrollableListView', function () {
    it('should render scrollable list view', function () {
      spyOn(ScrollView.prototype, 'render').and.returnValue(this);

      view._renderScrollableListView();

      expect(_.size(view._subviews)).toBe(1); // ['ScrollView']
    });
  });

  describe('_renderControlsView', function () {
    it('should render constrols view', function () {
      spyOn(AnalysisControlsView.prototype, 'render').and.returnValue(this);

      var formModel = new Backbone.Model({
        id: 'wadus',
        type: 'type'
      });

      view._renderControlsView(formModel);

      expect(_.size(view._subviews)).toBe(1); // ['AnalysisControlsView']
    });
  });

  describe('_getFormModel', function () {
    afterEach(function () {
      analysisFormsCollection.reset([]);
    });

    it('should get form model', function () {
      formA0 = analysisFormsCollection.add(nodeA0.attributes);

      view = createViewFn({
        analysisFormsCollection: analysisFormsCollection
      });

      expect(view._getFormModel()).toBe(formA0);
    });

    describe('with selectedNodeId', function () {
      it('should get form model', function () {
        formA0 = analysisFormsCollection.add(nodeA0.attributes);
        formA1 = analysisFormsCollection.add(nodeA1.attributes);

        view = createViewFn({
          selectedNodeId: formA1.get('id'),
          analysisFormsCollection: analysisFormsCollection
        });

        expect(view._getFormModel()).toBe(formA1);
      });
    });
  });

  describe('_getQuerySchemaModelForEstimation', function () {
    afterEach(function () {
      analysisFormsCollection.reset([]);
    });

    it('should get QuerySchemaModel', function () {
      spyOn(layerDefinitionModel, 'getAnalysisDefinitionNodeModel').and.returnValue(nodeA0);

      view = createViewFn({
        analysisFormsCollection: analysisFormsCollection
      });

      expect(view._getQuerySchemaModelForEstimation()).toBe(nodeA0.querySchemaModel);
    });

    describe('with selectedNodeId', function () {
      it('should get form model', function () {
        formA0 = analysisFormsCollection.add(nodeA0.attributes);
        formA1 = analysisFormsCollection.add(nodeA1.attributes);
        formB1 = analysisFormsCollection.add(nodeB1.attributes);

        view = createViewFn({
          selectedNodeId: formB1.get('id'),
          analysisFormsCollection: analysisFormsCollection
        });

        expect(view._getQuerySchemaModelForEstimation()).toBe(nodeA1.querySchemaModel);
      });
    });
  });

  describe('_onLayerDefSourceChanged', function () {
    it('should remove models from the analysis forms collection', function () {
      onLayerDefSourceChangedSpy.and.callThrough();

      view._onLayerDefSourceChanged();

      expect(removeUselessModelsSpy).toHaveBeenCalled();
    });
  });

  describe('_setDefaultSelectedNodeId', function () {
    afterEach(function () {
      analysisFormsCollection.reset([]);
    });

    it('should call Route.goToAnalysisNode with selectedNodeId', function () {
      setDefaultSelectedNodeIdSpy.and.callThrough();
      spyOn(Router, 'goToAnalysisNode');
      spyOn(AnalysesService, 'clearNotAppliedAnalysis');
      formA0 = analysisFormsCollection.add(nodeA0.attributes);

      view._setDefaultSelectedNodeId();

      expect(AnalysesService.clearNotAppliedAnalysis).toHaveBeenCalledWith(nodeA0.get('id'));
      expect(Router.goToAnalysisNode).toHaveBeenCalledWith(layerDefinitionModel.get('id'), nodeA0.get('id'));
    });
  });

  describe('_onAnalysisFormsCollectionSync', function () {
    it('should call AnalysesService.clearNotAppliedAnalysis', function () {
      onAnalysisFormsCollectionSyncSpy.and.callThrough();
      spyOn(AnalysesService, 'clearNotAppliedAnalysis');

      view._onAnalysisFormsCollectionSync(nodeA0);

      expect(AnalysesService.clearNotAppliedAnalysis).toHaveBeenCalledWith(nodeA0.get('id'));
    });
  });
});
<|endoftext|>


<commit_before>transporter.module.create('projects/projects', function(requires) {}, function(thisModule) {

thisModule.addSlots(avocado, function(add) {

  add.creator('project', {}, {category: ['projects']});

});

thisModule.addSlots(avocado.project, function(add) {

  add.method('current', function () {
    return this._current || (this._current = this.create({ name: "This project" }));
  }, {category: ['current one']});

  add.method('setCurrent', function (p) {
    this._current = p;
  }, {category: ['current one']});

  add.method('create', function (info) {
    return Object.newChildOf(this, info);
  }, {category: ['creating']});

  add.method('initialize', function (info) {
    this.setName(info.name);
    this.setIsPrivate(info.isPrivate);
    if (info._id) {
      this.setID(info._id);
    } else {
      transporter.idTracker.createTemporaryIDFor(this);
    }
    this.markAsUnchanged();
  }, {category: ['creating']});

  add.method('name', function () { return this._name; }, {category: ['accessing']});

  add.method('setName', function (n) { this._name = n; this.markAsChanged(); }, {category: ['accessing']});

  add.method('id', function () { return this._projectID; }, {category: ['accessing']});

  add.method('setID', function (id) { this._projectID = id; }, {category: ['accessing']});

  add.method('isPrivate', function () { return this._isPrivate; }, {category: ['accessing']});

  add.method('setIsPrivate', function (b) { this._isPrivate = b; this.markAsChanged(); }, {category: ['accessing']});

  add.method('isInTrashCan', function () { return this._isInTrashCan; }, {category: ['accessing']});

  add.method('putInTrashCan', function () { this._isInTrashCan = true; this.markAsChanged(); }, {category: ['accessing']});

  add.method('module', function () { return modules.thisProject; }, {category: ['accessing']});

  add.method('inspect', function () { return this.name(); }, {category: ['printing']});

  add.method('toString', function () { return this.name(); }, {category: ['printing']});

  add.method('hasChangedSinceLastFileOut', function () {
    return this._hasChanged || this.module().haveIOrAnyOfMyRequirementsChangedSinceLastFileOut();
  }, {category: ['noticing changes']});

  add.method('markAsChanged', function () {
    this._hasChanged = true;
  }, {category: ['noticing changes']});

  add.method('markAsUnchanged', function () {
    this._hasChanged = false;
  }, {category: ['noticing changes']});

  add.method('togglePrivacy', function (evt) {
    this.setIsPrivate(! this.isPrivate());
  }, {category: ['commands']});

  add.method('grabRootModule', function (evt) {
    avocado.ui.grab(this.module(), evt);
  }, {category: ['commands']});

  add.method('rename', function (evt) {
    avocado.ui.prompt("New name?", function(n) { if (n) { this.setName(n); }}.bind(this), this.name(), evt);
  }, {category: ['commands']});

  add.method('save', function (evt) {
    var rootModule = this.module();
    var versionsToSave = {};
    var modulesNotToSave = {};
    var modulesLeftToLookAt = [this.module()];
    while (modulesLeftToLookAt.length > 0) {
      var m = modulesLeftToLookAt.pop();
      if (!modulesNotToSave[m.name()] && !versionsToSave[m.name()]) {
        // aaa - Could make this algorithm faster if each module knew who required him - just check
        // if m itself has changed, and if so then walk up the requirements chain making sure that
        // they're included.
        if (m === rootModule || m.haveIOrAnyOfMyRequirementsChangedSinceLastFileOut()) { // always save the root, just makes things simpler
          versionsToSave[m.name()] = m.createNewVersion();
          m.requirements().each(function(requiredModuleName) { modulesLeftToLookAt.push(modules[requiredModuleName])});
        } else {
          modulesNotToSave[m.name()] = m;
        }
      }
    }

    var moduleGraph = avocado.graphs.directed.create([this.module()], function(m) { return m.requiredModules(); });
    var sortedModules = moduleGraph.topologicalSort();
    var sortedVersionsToSave = [];
    sortedModules.each(function(m) {
      var v = versionsToSave[m.name()];
      if (v) { sortedVersionsToSave.push(v); }
    });

    var mockRepo = avocado.project.repository.create(this);
    mockRepo.setRoot(versionsToSave[this.module().name()]);
    var errors = transporter.fileOutPlural(sortedVersionsToSave.map(function(v) { return { moduleVersion: v }; }), evt, mockRepo, transporter.module.justBodyFilerOuter);
    if (errors.length === 0) {
      mockRepo.save(function() {
        this.markAsUnchanged();
        for (var moduleName in versionsToSave) {
          modules[moduleName].markAsUnchanged();
        }
      }.bind(this), function(failureReason) {
        console.log("Error saving " + this + ": " + failureReason);
      });
    } else {
      console.log("Not saving because there were transporter errors.");
    }
  }, {category: ['saving']});

  add.creator('repository', {}, {category: ['saving']});

  add.method('buttonCommands', function () {
    return avocado.command.list.create(this, [
      avocado.command.create('Save', this.save)
    ]);
  }, {category: ['user interface', 'commands']});

  add.method('commands', function () {
    return avocado.command.list.create(this, [
      avocado.command.create('save', this.save),
      avocado.command.create('rename', this.rename),
      avocado.command.create('get root module', this.grabRootModule),
      avocado.command.create(this.isPrivate() ? 'be public' : 'be private', this.togglePrivacy)
    ]);
  }, {category: ['user interface', 'commands']});

});

thisModule.addSlots(avocado.project.repository, function(add) {

  add.method('create', function (project) {
    return Object.newChildOf(this, project);
  }, {category: ['creating']});

  add.method('initialize', function (project) {
    this._project = project;
    this._projectData = {
      _id: project.id(),
      name: project.name(),
      isPrivate: project.isPrivate(),
      isInTrashCan: project.isInTrashCan(),
      modules: []
    };
  }, {category: ['creating']});

  add.method('setRoot', function (rootModuleVersion) {
    this._projectData.root = rootModuleVersion.versionID();
  }, {category: ['saving']});

  add.method('fileOutModuleVersion', function (moduleVersion, codeToFileOut, successBlock, failBlock) {
    this._projectData.modules.push({
      module: moduleVersion.module().name(),
      version: moduleVersion.versionID(),
      parents: moduleVersion.parentVersions().map(function(pv) { return pv.versionID(); }),
      reqs: moduleVersion.requiredModuleVersions().map(function(v) { return v.versionID(); }),
      code: codeToFileOut
    });
  }, {category: ['saving']});

  add.method('save', function (successBlock, failBlock) {
    var json = Object.toJSON(this._projectData);
    // aaa - I imagine it's possible to send the JSON without encoding it as a POST parameter, but let's not worry about it yet.
    var postBody = "projectDataJSON=" + encodeURIComponent(json);
    var url = "http://localhost:3000/project/save"; // aaa don't hard-code this
    console.log("About to save the project to URL " + url + ", sending JSON:\n" + json);
    var req = new Ajax.Request(url, {
      method: 'post',
      //postBody: postBody,
      //contentType: 'application/x-www-form-urlencoded',
      postBody: json,
      contentType: 'application/json',

      asynchronous: true,
      onSuccess:   function(transport) { this.onSuccessfulPost(JSON.parse(transport.responseText), successBlock, failBlock); }.bind(this),
      onFailure:   function(t        ) { failBlock("Failed to file out project " + this._project + " to repository " + this + "; HTTP status code was " + req.getStatus()); }.bind(this),
      onException: function(r,      e) { failBlock("Failed to file out project " + this._project + " to repository " + this + "; exception was " + e); }.bind(this)
    });
  }, {category: ['saving']});

  add.method('onSuccessfulPost', function (responseJSON, successBlock, failBlock) {
    if (responseJSON.error) {
      failBlock("Server responded with error: " + responseJSON.error);
    } else {
      var realIDsByTempID = responseJSON;
      for (var tempID in realIDsByTempID) {
        transporter.idTracker.recordRealID(tempID, realIDsByTempID[tempID]);
      }
      successBlock();
    }
  }, {category: ['saving']});

});

});
<commit_msg>Fixed the hard-coding of the server hostname.<commit_after>transporter.module.create('projects/projects', function(requires) {}, function(thisModule) {

thisModule.addSlots(avocado, function(add) {

  add.creator('project', {}, {category: ['projects']});

});

thisModule.addSlots(avocado.project, function(add) {

  add.method('current', function () {
    return this._current || (this._current = this.create({ name: "This project" }));
  }, {category: ['current one']});

  add.method('setCurrent', function (p) {
    this._current = p;
  }, {category: ['current one']});

  add.method('create', function (info) {
    return Object.newChildOf(this, info);
  }, {category: ['creating']});

  add.method('initialize', function (info) {
    this.setName(info.name);
    this.setIsPrivate(info.isPrivate);
    if (info._id) {
      this.setID(info._id);
    } else {
      transporter.idTracker.createTemporaryIDFor(this);
    }
    this.markAsUnchanged();
  }, {category: ['creating']});

  add.method('name', function () { return this._name; }, {category: ['accessing']});

  add.method('setName', function (n) { this._name = n; this.markAsChanged(); }, {category: ['accessing']});

  add.method('id', function () { return this._projectID; }, {category: ['accessing']});

  add.method('setID', function (id) { this._projectID = id; }, {category: ['accessing']});

  add.method('isPrivate', function () { return this._isPrivate; }, {category: ['accessing']});

  add.method('setIsPrivate', function (b) { this._isPrivate = b; this.markAsChanged(); }, {category: ['accessing']});

  add.method('isInTrashCan', function () { return this._isInTrashCan; }, {category: ['accessing']});

  add.method('putInTrashCan', function () { this._isInTrashCan = true; this.markAsChanged(); }, {category: ['accessing']});

  add.method('module', function () { return modules.thisProject; }, {category: ['accessing']});

  add.method('inspect', function () { return this.name(); }, {category: ['printing']});

  add.method('toString', function () { return this.name(); }, {category: ['printing']});

  add.method('hasChangedSinceLastFileOut', function () {
    return this._hasChanged || this.module().haveIOrAnyOfMyRequirementsChangedSinceLastFileOut();
  }, {category: ['noticing changes']});

  add.method('markAsChanged', function () {
    this._hasChanged = true;
  }, {category: ['noticing changes']});

  add.method('markAsUnchanged', function () {
    this._hasChanged = false;
  }, {category: ['noticing changes']});

  add.method('togglePrivacy', function (evt) {
    this.setIsPrivate(! this.isPrivate());
  }, {category: ['commands']});

  add.method('grabRootModule', function (evt) {
    avocado.ui.grab(this.module(), evt);
  }, {category: ['commands']});

  add.method('rename', function (evt) {
    avocado.ui.prompt("New name?", function(n) { if (n) { this.setName(n); }}.bind(this), this.name(), evt);
  }, {category: ['commands']});

  add.method('save', function (evt) {
    var rootModule = this.module();
    var versionsToSave = {};
    var modulesNotToSave = {};
    var modulesLeftToLookAt = [this.module()];
    while (modulesLeftToLookAt.length > 0) {
      var m = modulesLeftToLookAt.pop();
      if (!modulesNotToSave[m.name()] && !versionsToSave[m.name()]) {
        // aaa - Could make this algorithm faster if each module knew who required him - just check
        // if m itself has changed, and if so then walk up the requirements chain making sure that
        // they're included.
        if (m === rootModule || m.haveIOrAnyOfMyRequirementsChangedSinceLastFileOut()) { // always save the root, just makes things simpler
          versionsToSave[m.name()] = m.createNewVersion();
          m.requirements().each(function(requiredModuleName) { modulesLeftToLookAt.push(modules[requiredModuleName])});
        } else {
          modulesNotToSave[m.name()] = m;
        }
      }
    }

    var moduleGraph = avocado.graphs.directed.create([this.module()], function(m) { return m.requiredModules(); });
    var sortedModules = moduleGraph.topologicalSort();
    var sortedVersionsToSave = [];
    sortedModules.each(function(m) {
      var v = versionsToSave[m.name()];
      if (v) { sortedVersionsToSave.push(v); }
    });

    var mockRepo = avocado.project.repository.create(this);
    mockRepo.setRoot(versionsToSave[this.module().name()]);
    var errors = transporter.fileOutPlural(sortedVersionsToSave.map(function(v) { return { moduleVersion: v }; }), evt, mockRepo, transporter.module.justBodyFilerOuter);
    if (errors.length === 0) {
      mockRepo.save(function() {
        this.markAsUnchanged();
        for (var moduleName in versionsToSave) {
          modules[moduleName].markAsUnchanged();
        }
      }.bind(this), function(failureReason) {
        console.log("Error saving " + this + ": " + failureReason);
      });
    } else {
      console.log("Not saving because there were transporter errors.");
    }
  }, {category: ['saving']});

  add.creator('repository', {}, {category: ['saving']});

  add.method('buttonCommands', function () {
    return avocado.command.list.create(this, [
      avocado.command.create('Save', this.save)
    ]);
  }, {category: ['user interface', 'commands']});

  add.method('commands', function () {
    return avocado.command.list.create(this, [
      avocado.command.create('save', this.save),
      avocado.command.create('rename', this.rename),
      avocado.command.create('get root module', this.grabRootModule),
      avocado.command.create(this.isPrivate() ? 'be public' : 'be private', this.togglePrivacy)
    ]);
  }, {category: ['user interface', 'commands']});

});

thisModule.addSlots(avocado.project.repository, function(add) {

  add.method('create', function (project) {
    return Object.newChildOf(this, project);
  }, {category: ['creating']});

  add.method('initialize', function (project) {
    this._project = project;
    this._projectData = {
      _id: project.id(),
      name: project.name(),
      isPrivate: project.isPrivate(),
      isInTrashCan: project.isInTrashCan(),
      modules: []
    };
  }, {category: ['creating']});

  add.method('setRoot', function (rootModuleVersion) {
    this._projectData.root = rootModuleVersion.versionID();
  }, {category: ['saving']});

  add.method('fileOutModuleVersion', function (moduleVersion, codeToFileOut, successBlock, failBlock) {
    this._projectData.modules.push({
      module: moduleVersion.module().name(),
      version: moduleVersion.versionID(),
      parents: moduleVersion.parentVersions().map(function(pv) { return pv.versionID(); }),
      reqs: moduleVersion.requiredModuleVersions().map(function(v) { return v.versionID(); }),
      code: codeToFileOut
    });
  }, {category: ['saving']});

  add.method('save', function (successBlock, failBlock) {
    var json = Object.toJSON(this._projectData);
    // aaa - I imagine it's possible to send the JSON without encoding it as a POST parameter, but let's not worry about it yet.
    var postBody = "projectDataJSON=" + encodeURIComponent(json);
    var url = "http://" + window.location.host + "/project/save";
    console.log("About to save the project to URL " + url + ", sending JSON:\n" + json);
    var req = new Ajax.Request(url, {
      method: 'post',
      //postBody: postBody,
      //contentType: 'application/x-www-form-urlencoded',
      postBody: json,
      contentType: 'application/json',

      asynchronous: true,
      onSuccess:   function(transport) { this.onSuccessfulPost(JSON.parse(transport.responseText), successBlock, failBlock); }.bind(this),
      onFailure:   function(t        ) { failBlock("Failed to file out project " + this._project + " to repository " + this + "; HTTP status code was " + req.getStatus()); }.bind(this),
      onException: function(r,      e) { failBlock("Failed to file out project " + this._project + " to repository " + this + "; exception was " + e); }.bind(this)
    });
  }, {category: ['saving']});

  add.method('onSuccessfulPost', function (responseJSON, successBlock, failBlock) {
    if (responseJSON.error) {
      failBlock("Server responded with error: " + responseJSON.error);
    } else {
      var realIDsByTempID = responseJSON;
      for (var tempID in realIDsByTempID) {
        transporter.idTracker.recordRealID(tempID, realIDsByTempID[tempID]);
      }
      successBlock();
    }
  }, {category: ['saving']});

});

});
<|endoftext|>


<commit_before>//藏干
var 藏干 = {
    子: {
        本氣: '癸',
        餘氣: '',
        雜氣: ''
    },
    丑: {
        本氣: '己',
        餘氣: '癸',
        雜氣: '辛'
    },
    寅: {
        本氣: '甲',
        餘氣: '戊',
        雜氣: '丙'
    },
    卯: {
        本氣: '乙',
        餘氣: '',
        雜氣: ''
    },
    辰: {
        本氣: '戊',
        餘氣: '乙',
        雜氣: '癸'
    },
    巳: {
        本氣: '丙',
        餘氣: '戊',
        雜氣: '庚'
    },
    午: {
        本氣: '丁',
        餘氣: '',
        雜氣: '己'
    },
    未: {
        本氣: '己',
        餘氣: '丁',
        雜氣: '乙'
    },
    申: {
        本氣: '庚',
        餘氣: '戊',
        雜氣: '壬'
    },
    酉: {
        本氣: '辛',
        餘氣: '',
        雜氣: ''
    },
    戌: {
        本氣: '戊',
        餘氣: '辛',
        雜氣: '丁'
    },
    亥: {
        本氣: '壬',
        餘氣: '',
        雜氣: '甲'
    },
};

<commit_msg>应该没什么问题吧<commit_after>//藏干
var 藏干 = {
    子: {
        本氣: '癸',
        餘氣: '',
        雜氣: ''
    },
    丑: {
        本氣: '己',
        餘氣: '癸',
        雜氣: '辛'
    },
    寅: {
        本氣: '甲',
        餘氣: '戊',
        雜氣: '丙'
    },
    卯: {
        本氣: '乙',
        餘氣: '',
        雜氣: ''
    },
    辰: {
        本氣: '戊',
        餘氣: '乙',
        雜氣: '癸'
    },
    巳: {
        本氣: '丙',
        餘氣: '戊',
        雜氣: '庚'
    },
    午: {
        本氣: '丁',
        餘氣: '',
        雜氣: '己'
    },
    未: {
        本氣: '己',
        餘氣: '丁',
        雜氣: '乙'
    },
    申: {
        本氣: '庚',
        餘氣: '戊',
        雜氣: '壬'
    },
    酉: {
        本氣: '辛',
        餘氣: '',
        雜氣: ''
    },
    戌: {
        本氣: '戊',
        餘氣: '辛',
        雜氣: '丁'
    },
    亥: {
        本氣: '壬',
        餘氣: '',
        雜氣: '甲'
    },
};

var 十神 = {
    甲{
        甲: '比肩',
        乙: '劫財',
        丙: '食神',
        丁: '傷官',
        戊: '偏財',
        己: '正財',
        庚: '七殺',
        辛: '正官',
        壬: '偏印',
        癸: '正印'
    };
    乙{
        甲: '劫財',
        乙: '比肩',
        丙: '傷官',
        丁: '食神',
        戊: '正財',
        己: '偏財',
        庚: '正官',
        辛: '七殺',
        壬: '正印',
        癸: '偏印'
    };
    丙{
        甲: '偏印',
        乙: '正印',
        丙: '比肩',
        丁: '劫財',
        戊: '食神',
        己: '傷官',
        庚: '偏財',
        辛: '正財',
        壬: '七殺',
        癸: '正官'
    };
    丁{
        甲: '正印',
        乙: '偏印',
        丙: '劫財',
        丁: '比肩',
        戊: '傷官',
        己: '食神',
        庚: '正財',
        辛: '偏財',
        壬: '正官',
        癸: '七殺'
    };
    戊{
        甲: '七殺',
        乙: '正官',
        丙: '偏印',
        丁: '正印',
        戊: '比肩',
        己: '劫財',
        庚: '食神',
        辛: '傷官',
        壬: '偏財',
        癸: '正財'
    };
    己{
        甲: '正官',
        乙: '七殺',
        丙: '正印',
        丁: '偏印',
        戊: '劫財',
        己: '比肩',
        庚: '傷官',
        辛: '食神',
        壬: '正財',
        癸: '偏財'
    };
    庚{
        甲: '偏財',
        乙: '正財',
        丙: '七殺',
        丁: '正官',
        戊: '偏印',
        己: '正印',
        庚: '比肩',
        辛: '劫財',
        壬: '食神',
        癸: '傷官'
    };
    辛{
        甲: '正財',
        乙: '偏財',
        丙: '正官',
        丁: '七殺',
        戊: '正印',
        己: '偏印',
        庚: '劫財',
        辛: '比肩',
        壬: '傷官',
        癸: '食神'
    };
    壬{
        甲: '食神',
        乙: '傷官',
        丙: '偏財',
        丁: '正財',
        戊: '七殺',
        己: '正官',
        庚: '偏印',
        辛: '正印',
        壬: '比肩',
        癸: '劫財'
    };
    癸{
        甲: '傷官',
        乙: '食神',
        丙: '正財',
        丁: '偏財',
        戊: '正官',
        己: '七殺',
        庚: '正印',
        辛: '偏印',
        壬: '劫財',
        癸: '比肩'
    };

};

var 十神逆 = {
    甲{
        比肩: '甲',
        劫財: '乙',
        食神: '丙',
        傷官: '丁',
        正財: '己',
        偏財: '戊',
        正官: '辛',
        七殺: '庚',
        正印: '癸',
        偏印: '壬'
    };
    乙{
        比肩: '乙',
        劫財: '甲',
        食神: '丁',
        傷官: '丙',
        正財: '戊',
        偏財: '己',
        正官: '庚',
        七殺: '辛',
        正印: '壬',
        偏印: '癸'
    };
    丙{
        比肩: '丙',
        劫財: '丁',
        食神: '己',
        傷官: '戊',
        正財: '辛',
        偏財: '庚',
        正官: '癸',
        七殺: '壬',
        正印: '乙',
        偏印: '甲'
    };
    丁{
        比肩: '丁',
        劫財: '丙',
        食神: '戊',
        傷官: '己',
        正財: '庚',
        偏財: '辛',
        正官: '壬',
        七殺: '癸',
        正印: '甲',
        偏印: '乙'
    };
    戊{
        比肩: '戊',
        劫財: '己',
        食神: '辛',
        傷官: '庚',
        正財: '癸',
        偏財: '壬',
        正官: '乙',
        七殺: '甲',
        正印: '丁',
        偏印: '丙'
    };
    己{
        比肩: '己',
        劫財: '戊',
        食神: '庚',
        傷官: '辛',
        正財: '壬',
        偏財: '癸',
        正官: '甲',
        七殺: '乙',
        正印: '丙',
        偏印: '丁'
    };
    庚{
        比肩: '庚',
        劫財: '辛',
        食神: '壬',
        傷官: '癸',
        正財: '乙',
        偏財: '甲',
        正官: '丁',
        七殺: '丙',
        正印: '己',
        偏印: '戊'
    };
    辛{
        比肩: '辛',
        劫財: '庚',
        食神: '癸',
        傷官: '壬',
        正財: '甲',
        偏財: '乙',
        正官: '丙',
        七殺: '丁',
        正印: '戊',
        偏印: '己'
    };
    壬{
        比肩: '壬',
        劫財: '癸',
        食神: '甲',
        傷官: '乙',
        正財: '丁',
        偏財: '丙',
        正官: '己',
        七殺: '戊',
        正印: '辛',
        偏印: '庚'
    };
    癸{
        比肩: '癸',
        劫財: '壬',
        食神: '甲',
        傷官: '乙',
        正財: '丙',
        偏財: '丁',
        正官: '戊',
        七殺: '己',
        正印: '庚',
        偏印: '辛'
    };

};

<|endoftext|>


<commit_before>parse = [
  // Simple spacing - paragraphs and line breaks.

  {
    'name'    : "A single bare line will be formatted as a paragraph.",
    'textile' : "One solitary line.",
    'html'    : "
One solitary line.
"
  },
  {
    'name'    : "A line break will be converted to an HTML break.",
    'textile' : "The first of a doublet.\nThe second of the doublet.",
    'html'    : "
The first of a doublet.
\nThe second of the doublet.
"
  },
  {
    'name'    : "Two blocks will be formatted as separate paragraphs.",
    'textile' : "The first paragraph.\n\nThe second paragraph.",
    'html'    : "
The first paragraph.
\n
The second paragraph.
"
  },
  {
    'name'    : "Two blocks with a space on the blank line will be formatted as separate paragraphs.",
    'textile' : "The first paragraph.\n \nThe second paragraph.",
    'html'    : "
The first paragraph.
\n
The second paragraph.
"
  },
  {
    'name'    : "Two blocks with a tab on the blank line will be formatted as separate paragraphs.",
    'textile' : "The first paragraph.\n\t\nThe second paragraph.",
    'html'    : "
The first paragraph.
\n
The second paragraph.
"
  },

  // Headers.

  {
    'name'    : "A line can be marked as a header.",
    'textile' : "h1. Big Picture\n\nBlah Blah Blah.\n\nh3. Slightly Smaller Picture\n\nTra la la.",
    'html'    : "
Big Picture
\n
Blah Blah Blah.
\n
Slightly Smaller Picture
\n
Tra la la.
"
  },

  // Horizontal rules.

  {
    'name'    : "A horizontal rule can be defined between paragraphs with a line of three asterisks.",
    'textile' : "A normal paragraph *** is unaffected.\n\n***\n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph * is unaffected.
\n
\n
And here is another paragraph.
"
  },
  {
    'name'    : "Or it can be more than three asterisks.",
    'textile' : "A normal paragraph **** is unaffected.\n\n****\n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph ** is unaffected.
\n
\n
And here is another paragraph.
"
  },
  {
    'name'    : "It can't be less than three, though.",
    'textile' : "A normal paragraph *** is unaffected.\n\n**\n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph * is unaffected.
\n
**
\n
And here is another paragraph.
"
  },
  {
    'name'    : "The line also can't have any other text on it.",
    'textile' : "A normal paragraph *** is unaffected.\n\n***blah\n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph * is unaffected.
\n
*blah
\n
And here is another paragraph.
"
  },
  {
    'name'    : "Though whitespace doesn't count.",
    'textile' : "A normal paragraph *** is unaffected.\n\n  ***  \n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph * is unaffected.
\n
\n
And here is another paragraph.
"
  },
  {
    'name'    : "It can also be done with three dashes.",
    'textile' : "A normal paragraph --- is unaffected.\n\n---\n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph —- is unaffected.
\n
\n
And here is another paragraph.
"
  },
  {
    'name'    : "Or three underscores.",
    'textile' : "A normal paragraph ___ is unaffected.\n\n___\n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph _ is unaffected.
\n
\n
And here is another paragraph.
"
  }
]
<commit_msg>Just leave on trailing commas in the test cases. Chrome doesn't seem to mind.<commit_after>parse = [
  // Simple spacing - paragraphs and line breaks.

  {
    'name'    : "A single bare line will be formatted as a paragraph.",
    'textile' : "One solitary line.",
    'html'    : "
One solitary line.
"
  },
  {
    'name'    : "A line break will be converted to an HTML break.",
    'textile' : "The first of a doublet.\nThe second of the doublet.",
    'html'    : "
The first of a doublet.
\nThe second of the doublet.
"
  },
  {
    'name'    : "Two blocks will be formatted as separate paragraphs.",
    'textile' : "The first paragraph.\n\nThe second paragraph.",
    'html'    : "
The first paragraph.
\n
The second paragraph.
"
  },
  {
    'name'    : "Two blocks with a space on the blank line will be formatted as separate paragraphs.",
    'textile' : "The first paragraph.\n \nThe second paragraph.",
    'html'    : "
The first paragraph.
\n
The second paragraph.
"
  },
  {
    'name'    : "Two blocks with a tab on the blank line will be formatted as separate paragraphs.",
    'textile' : "The first paragraph.\n\t\nThe second paragraph.",
    'html'    : "
The first paragraph.
\n
The second paragraph.
"
  },

  // Headers.

  {
    'name'    : "A line can be marked as a header.",
    'textile' : "h1. Big Picture\n\nBlah Blah Blah.\n\nh3. Slightly Smaller Picture\n\nTra la la.",
    'html'    : "
Big Picture
\n
Blah Blah Blah.
\n
Slightly Smaller Picture
\n
Tra la la.
"
  },

  // Horizontal rules.

  {
    'name'    : "A horizontal rule can be defined between paragraphs with a line of three asterisks.",
    'textile' : "A normal paragraph *** is unaffected.\n\n***\n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph * is unaffected.
\n
\n
And here is another paragraph.
"
  },
  {
    'name'    : "Or it can be more than three asterisks.",
    'textile' : "A normal paragraph **** is unaffected.\n\n****\n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph ** is unaffected.
\n
\n
And here is another paragraph.
"
  },
  {
    'name'    : "It can't be less than three, though.",
    'textile' : "A normal paragraph *** is unaffected.\n\n**\n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph * is unaffected.
\n
**
\n
And here is another paragraph.
"
  },
  {
    'name'    : "The line also can't have any other text on it.",
    'textile' : "A normal paragraph *** is unaffected.\n\n***blah\n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph * is unaffected.
\n
*blah
\n
And here is another paragraph.
"
  },
  {
    'name'    : "Though whitespace doesn't count.",
    'textile' : "A normal paragraph *** is unaffected.\n\n  ***  \n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph * is unaffected.
\n
\n
And here is another paragraph.
"
  },
  {
    'name'    : "It can also be done with three dashes.",
    'textile' : "A normal paragraph --- is unaffected.\n\n---\n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph —- is unaffected.
\n
\n
And here is another paragraph.
"
  },
  {
    'name'    : "Or three underscores.",
    'textile' : "A normal paragraph ___ is unaffected.\n\n___\n\nAnd here is another paragraph.",
    'html'    : "
A normal paragraph _ is unaffected.
\n
\n
And here is another paragraph.
"
  },
]
<|endoftext|>


<commit_before>cdb.geo.ui.Share = cdb.core.View.extend({

  className: "cartodb-share",

  events: {
    "click a": "_onClick"
  },
  default_options: { },

  initialize: function() {

    _.bindAll(this, "_onClick");

    _.defaults(this.options, this.default_options);

    this.template = this.options.template;

  },

  _applyStyle: function() { },

  _onClick: function(e) {

    e.preventDefault();
    e.stopPropagation();

    this.dialog.show();

  },

  createDialog: function() {

    var data = this.options;
    data.template = "";

    // Add the complete url for facebook and twitter
    if (location.href) {
      data.share_url = encodeURIComponent(location.href);
    } else {
      data.share_url = data.url;
    }

    var template = cdb.core.Template.compile(
      data.template || '\

\

\
      x\

\

Share this map
\

\

\

\

Social
\

\

Share on Facebook
\

Share on Twitter
\

Link to this map
\

\

\

Embed this map
\
      <textarea id="" name="" cols="30" rows="10">{{ code }}</textarea>\

\

\

\

\
      ',
      data.templateType || 'mustache'
    );

    var url = location.href;

    url = url.replace("public_map", "embed_map");

    var public_map_url = url.replace("embed_map", "public_map"); // TODO: get real URL

    var code = "";

    this.dialog = new cdb.ui.common.ShareDialog({
      title: data.map.get("title"),
      description: data.map.get("description"),
      model: this.options.vis.map,
      code: code,
      url: data.url,
      public_map_url: public_map_url,
      share_url: data.share_url,
      template: template,
      target: $(".cartodb-share a"),
      size: $(document).width() > 400 ? "" : "small",
      width: $(document).width() > 400 ? 430 : 216
    });

    $(".cartodb-map-wrapper").append(this.dialog.render().$el);

  },

  render: function() {

    this.$el.html(this.template(_.extend(this.model.attributes)));

    return this;

  }

});
<commit_msg>Clean view after removing the parent<commit_after>cdb.geo.ui.Share = cdb.core.View.extend({

  className: "cartodb-share",

  events: {
    "click a": "_onClick"
  },
  default_options: { },

  initialize: function() {

    _.bindAll(this, "_onClick");

    _.defaults(this.options, this.default_options);

    this.template = this.options.template;

  },

  _applyStyle: function() { },

  _onClick: function(e) {

    e.preventDefault();
    e.stopPropagation();

    this.dialog.show();

  },

  createDialog: function() {

    var data = this.options;
    data.template = "";

    // Add the complete url for facebook and twitter
    if (location.href) {
      data.share_url = encodeURIComponent(location.href);
    } else {
      data.share_url = data.url;
    }

    var template = cdb.core.Template.compile(
      data.template || '\

\

\
      x\

\

Share this map
\

\

\

\

Social
\

\

Share on Facebook
\

Share on Twitter
\

Link to this map
\

\

\

Embed this map
\
      <textarea id="" name="" cols="30" rows="10">{{ code }}</textarea>\

\

\

\

\
      ',
      data.templateType || 'mustache'
    );

    var url = location.href;

    url = url.replace("public_map", "embed_map");

    var public_map_url = url.replace("embed_map", "public_map"); // TODO: get real URL

    var code = "";

    this.dialog = new cdb.ui.common.ShareDialog({
      title: data.map.get("title"),
      description: data.map.get("description"),
      model: this.options.vis.map,
      code: code,
      url: data.url,
      public_map_url: public_map_url,
      share_url: data.share_url,
      template: template,
      target: $(".cartodb-share a"),
      size: $(document).width() > 400 ? "" : "small",
      width: $(document).width() > 400 ? 430 : 216
    });

    $(".cartodb-map-wrapper").append(this.dialog.render().$el);

    this.addView(this.dialog);

  },

  render: function() {

    this.$el.html(this.template(_.extend(this.model.attributes)));

    return this;

  }

});
<|endoftext|>