<commit_before>
moment.locale('zh-CN');

var socket = io('/');
var myname = localStorage.getItem('lucky_myname');

socket.on('connect', function () {
  // on connect
  if (myname) {
    init_socket();
  }
});
socket.on('status', function (data) {
  // list all
  if (data && data.me && data.me.value) {
    updateMyValue(data.me.value);
  } else {
    showGetter();
  }
  if (data && data.finished) {
    showFinished();
  }
});
socket.on('list', function (data) {
  // list all
  for (var i = data.length - 1; i >= 0; i--) {
    addToList(data[i]);
  }
});
socket.on('new', function (data) {
  // check if myself
  if (data && data.name === myname) {
    updateMyValue(data.value);
  }
  // add
  addToList(data);
});
socket.on('reset', function () {
  // remove all
  $('.posts-list').html('');
  showGetter();
});

function htmlEscape(str) {
  return String(str)
          .replace(/&/g, '&')
          .replace(/"/g, '"')
          .replace(/'/g, ''')
          .replace(/</g, '<')
          .replace(/>/g, '>');
}
function init_socket() {
  if (myname) {
    socket.emit('init', { name: myname });
  }
}
function updateMyName(name) {
  if (!myname) {
    localStorage.setItem('lucky_myname', name);
    myname = name;
    init_socket();
  }
}
function updateMyValue(value) {
  $('.controls > .control').hide();
  $('.valuer #myvalue').text(value);
  $('.valuer').show();
}
function showGetter() {
  $('.controls > .control').hide();
  $('.getter').show();
}
function showInputter() {
  $('.controls > .control').hide();
  $('.inputer').show();
}
function showFinished() {
  $('.controls > .control').hide();
  $('.finisher').show();
}
function addToList(data) {
  /*$('.posts-list').prepend('
'
    + '' + data.lid.toString() + ''
    + '' + htmlEscape(data.name) + ''
    + '' + data.value.toString() + ''
    + '
');*/
  var colors = ['#F44336', '#E91E63', '#2196F3', '#4CAF50', '#FF9800', '#FF5722', '#607D8B'];
  var lid = data.lid.toString();
  var selector = (data.name === myname ? '#my-value-list' : '#others-value-list');
  if ($(selector + '.posts-list li[data-lid=' + lid + ']').length > 0) {
    // exists
    return;
  }
  //'#e65100'
  var color = colors[data.name.charCodeAt(0) % colors.length];
  var name = htmlEscape(data.name);
  var html = ''
    + '
'
    + '
'
		+ '
'
	  + '   ' + lid + ''
    + '   ' + data.value.toString() + ''
		+ '
'
		+ '
'
		+ '		'
		+ '
' + name[0] + '
'
		+ '		'
		+ '
'
		+ '			' + name + '
'
		+ '			' + moment(data.updated_at).fromNow() + ''
		+ '
'
		+ '
'
		+ '
'
    + '
';
  $(selector + '.posts-list').prepend(html);
}

$(document).ready(function () {
  if (window.location.hash === '#reset') {
    $('.reseter').show();
  }
  $('.reseter #reset-btn').click(function () {
    var vals = $('.reseter #reset-data').val();
    if (vals) vals = vals.split(' ');
    if (vals && vals.length > 0) {
      var data = [];
      for (var i = 0; i < vals.length; i++) {
        var s = vals[i].trim();
        if (s) data.push(s);
      }
      if (data.length > 0) {
        var rkey = prompt('请输入重置密码：');
        socket.emit('reset', { reset_key: rkey, data: data });
      }
    }
  });
  $('.getter #get-btn').click(function () {
    if (confirm('准备好了么？')) {
      socket.emit('new');
    }
  });
  $('.inputer #myname-btn').click(function () {
    var name = $('.inputer #myname').val();
    if (name) {
      updateMyName(name);
    }
  });
  if (myname) {
    showGetter();
  } else {
    showInputter();
  }
});
<commit_msg>Fix admin reset btn not shown<commit_after>
moment.locale('zh-CN');

var socket = io('/');
var myname = localStorage.getItem('lucky_myname');

socket.on('connect', function () {
  // on connect
  if (myname) {
    init_socket();
  }
});
socket.on('status', function (data) {
  // list all
  if (data && data.me && data.me.value) {
    updateMyValue(data.me.value);
  } else {
    showGetter();
  }
  if (data && data.finished) {
    showFinished();
  }
});
socket.on('list', function (data) {
  // list all
  for (var i = data.length - 1; i >= 0; i--) {
    addToList(data[i]);
  }
});
socket.on('new', function (data) {
  // check if myself
  if (data && data.name === myname) {
    updateMyValue(data.value);
  }
  // add
  addToList(data);
});
socket.on('reset', function () {
  // remove all
  $('.posts-list').html('');
  showGetter();
});

function htmlEscape(str) {
  return String(str)
          .replace(/&/g, '&')
          .replace(/"/g, '"')
          .replace(/'/g, ''')
          .replace(/</g, '<')
          .replace(/>/g, '>');
}
function init_socket() {
  if (myname) {
    socket.emit('init', { name: myname });
  }
}
function updateMyName(name) {
  if (!myname) {
    localStorage.setItem('lucky_myname', name);
    myname = name;
    init_socket();
  }
}
function updateMyValue(value) {
  $('.controls > .control').hide();
  $('.valuer #myvalue').text(value);
  $('.valuer').show();
}
function showGetter() {
  $('.controls > .control').hide();
  $('.getter').show();
}
function showInputter() {
  $('.controls > .control').hide();
  $('.inputer').show();
}
function showFinished() {
  $('.controls > .control').hide();
  $('.finisher').show();
}
function addToList(data) {
  /*$('.posts-list').prepend('
'
    + '' + data.lid.toString() + ''
    + '' + htmlEscape(data.name) + ''
    + '' + data.value.toString() + ''
    + '
');*/
  var colors = ['#F44336', '#E91E63', '#2196F3', '#4CAF50', '#FF9800', '#FF5722', '#607D8B'];
  var lid = data.lid.toString();
  var selector = (data.name === myname ? '#my-value-list' : '#others-value-list');
  if ($(selector + '.posts-list li[data-lid=' + lid + ']').length > 0) {
    // exists
    return;
  }
  //'#e65100'
  var color = colors[data.name.charCodeAt(0) % colors.length];
  var name = htmlEscape(data.name);
  var html = ''
    + '
'
    + '
'
		+ '
'
	  + '   ' + lid + ''
    + '   ' + data.value.toString() + ''
		+ '
'
		+ '
'
		+ '		'
		+ '
' + name[0] + '
'
		+ '		'
		+ '
'
		+ '			' + name + '
'
		+ '			' + moment(data.updated_at).fromNow() + ''
		+ '
'
		+ '
'
		+ '
'
    + '
';
  $(selector + '.posts-list').prepend(html);
}

$(document).ready(function () {
  $('.reseter #reset-btn').click(function () {
    var vals = $('.reseter #reset-data').val();
    if (vals) vals = vals.split(' ');
    if (vals && vals.length > 0) {
      var data = [];
      for (var i = 0; i < vals.length; i++) {
        var s = vals[i].trim();
        if (s) data.push(s);
      }
      if (data.length > 0) {
        var rkey = prompt('请输入重置密码：');
        socket.emit('reset', { reset_key: rkey, data: data });
      }
    }
  });
  $('.getter #get-btn').click(function () {
    if (confirm('准备好了么？')) {
      socket.emit('new');
    }
  });
  $('.inputer #myname-btn').click(function () {
    var name = $('.inputer #myname').val();
    if (name) {
      updateMyName(name);
    }
  });
  if (myname) {
    showGetter();
  } else {
    showInputter();
  }
  // for admin
  if (window.location.hash === '#reset') {
    $('.reseter').show();
  }
});
<|endoftext|>


<commit_before>const path = require('path')

const hook = require('css-modules-require-hook')
const projectDir = path.resolve(__dirname)
hook({
  generateScopedName: '[name]_[local]__[hash:base64:5]',
  rootDir: projectDir
})

// We need to register the hook above first since ES2015 imports occur
// *before* statements are evaluated
require('./server')
<commit_msg>finishing up part 6, universal CSS<commit_after>const path = require('path')

const hook = require('css-modules-require-hook')
const projectDir = path.resolve(__dirname)
hook({
  generateScopedName: '[name]_[local]__[hash:base64:5]',
  rootDir: projectDir
})

// We need to register the hook above first since ES2015 imports
// occur *before* statements are evaluated
require('./server')
<|endoftext|>


<commit_before>'use strict';

require('dotenv').config();

const moment   = require('moment');
let   program  = require('commander');
const promptly = require('promptly');

const run    = require('./commands/run.js');
const update = require('./commands/update.js');
const setup  = require('./commands/setup.js');
const clean  = require('./commands/clean.js');

program
    .version('2.0.0')
    .option('-d, --dev', 'Development environment (set a custom date)');

program
    .command('run')
    .description('Run and post the fixtures happening in ' + process.env.TIMEFRAME + ' mins')
    .action(function(cmd) {
        if(cmd.parent.dev) {
            // set the date manually for dev purposes
            require('mockdate').set(moment.unix(1461419900));

            console.log('Running in development mode with custom date')
        }

        // find and post the matches that are happening within the given timeframe (in minutes)
        run();
    });

program
    .command('update')
    .description('Fetch the latest fixture list and update the local fixture list')
    .action(function() {
        // fetch the latest fixture list and update the local fixture list
        update();
    });

program
    .command('setup')
    .description('Fetch the latest fixture list and import into the local databse (first time setup)')
    .action(function() {
        // first time setup
        setup();
    });

program
    .command('clean')
    .description('Clean the local database')
    .action(function() {
        // clean the local database after confirmation from user
        promptly.confirm('This action will delete the local database, continue?', function(err, value) {
            if(value) {
                console.log('Cleaning...');
                clean();
            } else {
                console.log('Clean aborted');
            }
        });
    });

program.parse(process.argv);
<commit_msg>Add process.chdir to change the current working directory of the process upon run<commit_after>'use strict';

process.chdir(__dirname);

require('dotenv').config();

const moment   = require('moment');
let   program  = require('commander');
const promptly = require('promptly');

const run    = require('./commands/run.js');
const update = require('./commands/update.js');
const setup  = require('./commands/setup.js');
const clean  = require('./commands/clean.js');

program
    .version('2.0.0')
    .option('-d, --dev', 'Development environment (set a custom date)');

program
    .command('run')
    .description('Run and post the fixtures happening in ' + process.env.TIMEFRAME + ' mins')
    .action(function(cmd) {
        if(cmd.parent.dev) {
            // set the date manually for dev purposes
            require('mockdate').set(moment.unix(1461419900));

            console.log('Running in development mode with custom date')
        }

        // find and post the matches that are happening within the given timeframe (in minutes)
        run();
    });

program
    .command('update')
    .description('Fetch the latest fixture list and update the local fixture list')
    .action(function() {
        // fetch the latest fixture list and update the local fixture list
        update();
    });

program
    .command('setup')
    .description('Fetch the latest fixture list and import into the local databse (first time setup)')
    .action(function() {
        // first time setup
        setup();
    });

program
    .command('clean')
    .description('Clean the local database')
    .action(function() {
        // clean the local database after confirmation from user
        promptly.confirm('This action will delete the local database, continue?', function(err, value) {
            if(value) {
                console.log('Cleaning...');
                clean();
            } else {
                console.log('Clean aborted');
            }
        });
    });

program.parse(process.argv);
<|endoftext|>


<commit_before>/*jslint browser:true */
/*globals $, console */
var proxy = proxy || {};
var semtag = semtag || {};
proxy.get = function (url, callback) {
	"use strict";
	var data;
	$.getJSON('/proxy?q=' +  url, function (response) {
		data = response;
	}).success(function () {
		callback(null, data);
	}).error(function (data) {
		callback(data);
	});
};
(function () {
	'use strict';
	var getPage = function () {
		document.getElementById('content').innerHTML = '

Loading

';
		var url = $('#url').val();
		proxy.get(url, function (error, dom) {
			if (error) {
				document.getElementById('content').innerHTML = '

No such page found

';
			} else {
				semtag.dom = {};
				semtag.dom.URI = dom.URI || '';
				semtag.dom.head = dom.head || '';
				document.getElementById('content').innerHTML = dom.body;
				$(document.getElementById('content')).click(function (e) {
					e.preventDefault();
				});
			}

		});
	};
	$('#get').click(getPage);
	$('#url').keypress(function (e) {
		if (e.keyCode === 13) {
			getPage();
		}
	});
}());<commit_msg>Updated app object semtag -> madame<commit_after>/*jslint browser:true */
/*globals $, console */
var proxy = proxy || {};
var madame = madame || {};
proxy.get = function (url, callback) {
	"use strict";
	var data;
	$.getJSON('/proxy?q=' +  url, function (response) {
		data = response;
	}).success(function () {
		callback(null, data);
	}).error(function (data) {
		callback(data);
	});
};
(function () {
	'use strict';
	var getPage = function () {
		document.getElementById('content').innerHTML = '

Loading

';
		var url = $('#url').val();
		proxy.get(url, function (error, dom) {
			if (error) {
				document.getElementById('content').innerHTML = '

No such page found

';
			} else {
				madame.dom = {};
				madame.dom.URI = dom.URI || '';
				madame.dom.head = dom.head || '';
				document.getElementById('content').innerHTML = dom.body;
				$(document.getElementById('content')).click(function (e) {
					e.preventDefault();
				});
			}

		});
	};
	$('#get').click(getPage);
	$('#url').keypress(function (e) {
		if (e.keyCode === 13) {
			getPage();
		}
	});
}());<|endoftext|>


<commit_before>define(function(require, exports, module) {
    var kity = require('../core/kity');
    var utils = require('../core/utils');
    var MinderNode = require('../core/node');
    var Command = require('../core/command');
    var Module = require('../core/module');

    // 矩形的变形动画定义
    var MoveToParentCommand = kity.createClass('MoveToParentCommand', {
        base: Command,
        execute: function(minder, nodes, parent) {
            var node;
            for (var i = nodes.length - 1; i >= 0; i--) {
                node = nodes[i];
                if (node.parent) {
                    node.parent.removeChild(node);
                    parent.appendChild(node);
                    node.render();
                }
            }
            parent.expand();
            minder.select(nodes, true);
        }
    });

    var DropHinter = kity.createClass('DropHinter', {
        base: kity.Group,

        constructor: function() {
            this.callBase();
            this.rect = new kity.Rect();
            this.addShape(this.rect);
        },

        render: function(target) {
            this.setVisible(!!target);
            if (target) {
                this.rect
                    .setBox(target.getLayoutBox())
                    .setRadius(target.getStyle('radius') || 0)
                    .stroke(
                        target.getStyle('drop-hint-color') || 'yellow',
                        target.getStyle('drop-hint-width') || 2
                );
                this.bringTop();
            }
        }
    });

    var OrderHinter = kity.createClass('OrderHinter', {
        base: kity.Group,

        constructor: function() {
            this.callBase();
            this.area = new kity.Rect();
            this.path = new kity.Path();
            this.addShapes([this.area, this.path]);
        },

        render: function(hint) {
            this.setVisible(!!hint);
            if (hint) {
                this.area.setBox(hint.area);
                this.area.fill(hint.node.getStyle('order-hint-area-color') || 'rgba(0, 255, 0, .5)');
                this.path.setPathData(hint.path);
                this.path.stroke(
                    hint.node.getStyle('order-hint-path-color') || '#0f0',
                    hint.node.getStyle('order-hint-path-width') || 1);
            }
        }
    });

    // 对拖动对象的一个替代盒子，控制整个拖放的逻辑，包括：
    //    1. 从节点列表计算出拖动部分
    //    2. 计算可以 drop 的节点，产生 drop 交互提示
    var TreeDragger = kity.createClass('TreeDragger', {

        constructor: function(minder) {
            this._minder = minder;
            this._dropHinter = new DropHinter();
            this._orderHinter = new OrderHinter();
            minder.getRenderContainer().addShapes([this._dropHinter, this._orderHinter]);
        },

        dragStart: function(position) {
            // 只记录开始位置，不马上开启拖放模式
            // 这个位置同时是拖放范围收缩时的焦点位置（中心）
            this._startPosition = position;
        },

        dragMove: function(position) {
            // 启动拖放模式需要最小的移动距离
            var DRAG_MOVE_THRESHOLD = 10;

            if (!this._startPosition) return;

            var movement = kity.Vector.fromPoints(this._dragPosition || this._startPosition, position);
            var minder = this._minder;

            this._dragPosition = position;

            if (!this._dragMode) {
                // 判断拖放模式是否该启动
                if (kity.Vector.fromPoints(this._dragPosition, this._startPosition).length() < DRAG_MOVE_THRESHOLD) {
                    return;
                }
                if (!this._enterDragMode()) {
                    return;
                }
            }

            for (var i = 0; i < this._dragSources.length; i++) {
                this._dragSources[i].setLayoutOffset(this._dragSources[i].getLayoutOffset().offset(movement));
                minder.applyLayoutResult(this._dragSources[i]);
            }

            if (!this._dropTest()) {
                this._orderTest();
            } else {
                this._renderOrderHint(this._orderSucceedHint = null);
            }
        },

        dragEnd: function() {
            this._startPosition = null;
            this._dragPosition = null;

            if (!this._dragMode) {
                return;
            }

            this._fadeDragSources(1);

            if (this._dropSucceedTarget) {

                this._dragSources.forEach(function(source) {
                    source.setLayoutOffset(null);
                });

                this._minder.layout(-1);

                this._minder.execCommand('movetoparent', this._dragSources, this._dropSucceedTarget);

            } else if (this._orderSucceedHint) {

                var hint = this._orderSucceedHint;
                var index = hint.node.getIndex();

                var sourceIndexes = this._dragSources.map(function(source) {
                    // 顺便干掉布局偏移
                    source.setLayoutOffset(null);
                    return source.getIndex();
                });

                var maxIndex = Math.max.apply(Math, sourceIndexes);
                var minIndex = Math.min.apply(Math, sourceIndexes);

                if (index < minIndex && hint.type == 'down') index++;
                if (index > maxIndex && hint.type == 'up') index--;

                hint.node.setLayoutOffset(null);

                this._minder.execCommand('arrange', index);
                this._renderOrderHint(null);
            } else {
                this._minder.fire('savescene');
            }
            this._minder.layout(300);
            this._leaveDragMode();
            this._minder.fire('contentchange');
        },

        // 进入拖放模式：
        //    1. 计算拖放源和允许的拖放目标
        //    2. 标记已启动
        _enterDragMode: function() {
            this._calcDragSources();
            if (!this._dragSources.length) {
                this._startPosition = null;
                return false;
            }
            this._fadeDragSources(0.5);
            this._calcDropTargets();
            this._calcOrderHints();
            this._dragMode = true;
            this._minder.setStatus('dragtree');
            return true;
        },

        // 从选中的节点计算拖放源
        //    并不是所有选中的节点都作为拖放源，如果选中节点中存在 A 和 B，
        //    并且 A 是 B 的祖先，则 B 不作为拖放源
        //
        //    计算过程：
        //       1. 将节点按照树高排序，排序后只可能是前面节点是后面节点的祖先
        //       2. 从后往前枚举排序的结果，如果发现枚举目标之前存在其祖先，
        //          则排除枚举目标作为拖放源，否则加入拖放源
        _calcDragSources: function() {
            this._dragSources = this._minder.getSelectedAncestors();
        },

        _fadeDragSources: function(opacity) {
            var minder = this._minder;
            this._dragSources.forEach(function(source) {
                source.getRenderContainer().setOpacity(opacity, 200);
                source.traverse(function(node) {
                    if (opacity < 1) {
                        minder.detachNode(node);
                    } else {
                        minder.attachNode(node);
                    }
                }, true);
            });
        },

        // 计算拖放目标可以释放的节点列表（释放意味着成为其子树），存在这条限制规则：
        //    - 不能拖放到拖放目标的子树上（允许拖放到自身，因为多选的情况下可以把其它节点加入）
        //
        //    1. 加入当前节点（初始为根节点）到允许列表
        //    2. 对于当前节点的每一个子节点：
        //       (1) 如果是拖放目标的其中一个节点，忽略（整棵子树被剪枝）
        //       (2) 如果不是拖放目标之一，以当前子节点为当前节点，回到 1 计算
        //    3. 返回允许列表
        //
        _calcDropTargets: function() {

            function findAvailableParents(nodes, root) {
                var availables = [],
                    i;
                availables.push(root);
                root.getChildren().forEach(function(test) {
                    for (i = 0; i < nodes.length; i++) {
                        if (nodes[i] == test) return;
                    }
                    availables = availables.concat(findAvailableParents(nodes, test));
                });
                return availables;
            }

            this._dropTargets = findAvailableParents(this._dragSources, this._minder.getRoot());
            this._dropTargetBoxes = this._dropTargets.map(function(source) {
                return source.getLayoutBox();
            });
        },

        _calcOrderHints: function() {
            var sources = this._dragSources;
            var ancestor = MinderNode.getCommonAncestor(sources);

            // 只有一个元素选中，公共祖先是其父
            if (ancestor == sources[0]) ancestor = sources[0].parent;

            if (sources.length === 0 || ancestor != sources[0].parent) {
                this._orderHints = [];
                return;
            }

            var siblings = ancestor.children;

            this._orderHints = siblings.reduce(function(hint, sibling) {
                if (sources.indexOf(sibling) == -1) {
                    hint = hint.concat(sibling.getOrderHint());
                }
                return hint;
            }, []);
        },

        _leaveDragMode: function() {
            this._dragMode = false;
            this._dropSucceedTarget = null;
            this._orderSucceedHint = null;
            this._renderDropHint(null);
            this._renderOrderHint(null);
            this._minder.rollbackStatus();
        },

        _drawForDragMode: function() {
            this._text.setContent(this._dragSources.length + ' items');
            this._text.setPosition(this._startPosition.x, this._startPosition.y + 5);
            this._minder.getRenderContainer().addShape(this);
        },

        /**
         * 通过 judge 函数判断 targetBox 和 sourceBox 的位置交叉关系
         * @param targets -- 目标节点
         * @param targetBoxMapper -- 目标节点与对应 Box 的映射关系
         * @param judge -- 判断函数
         * @returns {*}
         * @private
         */
        _boxTest: function(targets, targetBoxMapper, judge) {
            var sourceBoxes = this._dragSources.map(function(source) {
                return source.getLayoutBox();
            });

            var i, j, target, sourceBox, targetBox;

            judge = judge || function(intersectBox, sourceBox, targetBox) {
                return intersectBox && !intersectBox.isEmpty();
            };

            for (i = 0; i < targets.length; i++) {

                target = targets[i];
                targetBox = targetBoxMapper.call(this, target, i);

                for (j = 0; j < sourceBoxes.length; j++) {
                    sourceBox = sourceBoxes[j];

                    var intersectBox = sourceBox.intersect(targetBox);
                    if (judge(intersectBox, sourceBox, targetBox)) {
                        return target;
                    }
                }
            }

            return null;
        },

        _dropTest: function() {
            this._dropSucceedTarget = this._boxTest(this._dropTargets, function(target, i) {
                return this._dropTargetBoxes[i];
            }, function(intersectBox, sourceBox, targetBox) {
                function area(box) {
                    return box.width * box.height;
                }
                if (!intersectBox) return false;
                /*
                * Added by zhangbobell, 2015.9.8
                *
                * 增加了下面一行判断，修复了循环比较中 targetBox 为折叠节点时，intersetBox 面积为 0，
                * 而 targetBox 的 width 和 height 均为 0
                * 此时造成了满足以下的第二个条件而返回 true
                * */
                if (!area(intersectBox)) return false;
                // 面积判断，交叉面积大于其中的一半
                if (area(intersectBox) > 0.5 * Math.min(area(sourceBox), area(targetBox))) return true;
                // 有一个边完全重合的情况，也认为两个是交叉的
                if (intersectBox.width + 1 >= Math.min(sourceBox.width, targetBox.width)) return true;
                if (intersectBox.height + 1 >= Math.min(sourceBox.height, targetBox.height)) return true;
                return false;
            });
            this._renderDropHint(this._dropSucceedTarget);
            return !!this._dropSucceedTarget;
        },

        _orderTest: function() {
            this._orderSucceedHint = this._boxTest(this._orderHints, function(hint) {
                return hint.area;
            });
            this._renderOrderHint(this._orderSucceedHint);
            return !!this._orderSucceedHint;
        },

        _renderDropHint: function(target) {
            this._dropHinter.render(target);
        },

        _renderOrderHint: function(hint) {
            this._orderHinter.render(hint);
        },
        preventDragMove: function() {
            this._startPosition = null;
        }
    });

    Module.register('DragTree', function() {
        var dragger;

        return {
            init: function() {
                dragger = new TreeDragger(this);
                window.addEventListener('mouseup', function() {
                    dragger.dragEnd();
                });
            },
            events: {
                'normal.mousedown inputready.mousedown': function(e) {
                    // 单选中根节点也不触发拖拽
                    if (e.originEvent.button) return;
                    if (e.getTargetNode() && e.getTargetNode() != this.getRoot()) {
                        dragger.dragStart(e.getPosition());
                    }
                },
                'normal.mousemove dragtree.mousemove': function(e) {
                    dragger.dragMove(e.getPosition());
                },
                'normal.mouseup dragtree.beforemouseup': function(e) {
                    dragger.dragEnd();
                    //e.stopPropagation();
                    e.preventDefault();
                },
                'statuschange': function(e) {
                    if (e.lastStatus == 'textedit' && e.currentStatus == 'normal') {
                        dragger.preventDragMove();
                    }
                }
            },
            commands: {
                'movetoparent': MoveToParentCommand
            }
        };
    });
});<commit_msg>ISSUE= fix(dragtree): fix bug of drag node reverse, close fex-team/kityminder-editor#118, fex-team/kityminder-editor#119, fex-team/kityminder-editor#220<commit_after>define(function(require, exports, module) {
    var kity = require('../core/kity');
    var utils = require('../core/utils');
    var MinderNode = require('../core/node');
    var Command = require('../core/command');
    var Module = require('../core/module');

    // 矩形的变形动画定义
    var MoveToParentCommand = kity.createClass('MoveToParentCommand', {
        base: Command,
        execute: function(minder, nodes, parent) {
            var node;
            for (var i = 0; i < nodes.length; i++) {
                node = nodes[i];
                if (node.parent) {
                    node.parent.removeChild(node);
                    parent.appendChild(node);
                    node.render();
                }
            }
            parent.expand();
            minder.select(nodes, true);
        }
    });

    var DropHinter = kity.createClass('DropHinter', {
        base: kity.Group,

        constructor: function() {
            this.callBase();
            this.rect = new kity.Rect();
            this.addShape(this.rect);
        },

        render: function(target) {
            this.setVisible(!!target);
            if (target) {
                this.rect
                    .setBox(target.getLayoutBox())
                    .setRadius(target.getStyle('radius') || 0)
                    .stroke(
                        target.getStyle('drop-hint-color') || 'yellow',
                        target.getStyle('drop-hint-width') || 2
                );
                this.bringTop();
            }
        }
    });

    var OrderHinter = kity.createClass('OrderHinter', {
        base: kity.Group,

        constructor: function() {
            this.callBase();
            this.area = new kity.Rect();
            this.path = new kity.Path();
            this.addShapes([this.area, this.path]);
        },

        render: function(hint) {
            this.setVisible(!!hint);
            if (hint) {
                this.area.setBox(hint.area);
                this.area.fill(hint.node.getStyle('order-hint-area-color') || 'rgba(0, 255, 0, .5)');
                this.path.setPathData(hint.path);
                this.path.stroke(
                    hint.node.getStyle('order-hint-path-color') || '#0f0',
                    hint.node.getStyle('order-hint-path-width') || 1);
            }
        }
    });

    // 对拖动对象的一个替代盒子，控制整个拖放的逻辑，包括：
    //    1. 从节点列表计算出拖动部分
    //    2. 计算可以 drop 的节点，产生 drop 交互提示
    var TreeDragger = kity.createClass('TreeDragger', {

        constructor: function(minder) {
            this._minder = minder;
            this._dropHinter = new DropHinter();
            this._orderHinter = new OrderHinter();
            minder.getRenderContainer().addShapes([this._dropHinter, this._orderHinter]);
        },

        dragStart: function(position) {
            // 只记录开始位置，不马上开启拖放模式
            // 这个位置同时是拖放范围收缩时的焦点位置（中心）
            this._startPosition = position;
        },

        dragMove: function(position) {
            // 启动拖放模式需要最小的移动距离
            var DRAG_MOVE_THRESHOLD = 10;

            if (!this._startPosition) return;

            var movement = kity.Vector.fromPoints(this._dragPosition || this._startPosition, position);
            var minder = this._minder;

            this._dragPosition = position;

            if (!this._dragMode) {
                // 判断拖放模式是否该启动
                if (kity.Vector.fromPoints(this._dragPosition, this._startPosition).length() < DRAG_MOVE_THRESHOLD) {
                    return;
                }
                if (!this._enterDragMode()) {
                    return;
                }
            }

            for (var i = 0; i < this._dragSources.length; i++) {
                this._dragSources[i].setLayoutOffset(this._dragSources[i].getLayoutOffset().offset(movement));
                minder.applyLayoutResult(this._dragSources[i]);
            }

            if (!this._dropTest()) {
                this._orderTest();
            } else {
                this._renderOrderHint(this._orderSucceedHint = null);
            }
        },

        dragEnd: function() {
            this._startPosition = null;
            this._dragPosition = null;

            if (!this._dragMode) {
                return;
            }

            this._fadeDragSources(1);

            if (this._dropSucceedTarget) {

                this._dragSources.forEach(function(source) {
                    source.setLayoutOffset(null);
                });

                this._minder.layout(-1);

                this._minder.execCommand('movetoparent', this._dragSources, this._dropSucceedTarget);

            } else if (this._orderSucceedHint) {

                var hint = this._orderSucceedHint;
                var index = hint.node.getIndex();

                var sourceIndexes = this._dragSources.map(function(source) {
                    // 顺便干掉布局偏移
                    source.setLayoutOffset(null);
                    return source.getIndex();
                });

                var maxIndex = Math.max.apply(Math, sourceIndexes);
                var minIndex = Math.min.apply(Math, sourceIndexes);

                if (index < minIndex && hint.type == 'down') index++;
                if (index > maxIndex && hint.type == 'up') index--;

                hint.node.setLayoutOffset(null);

                this._minder.execCommand('arrange', index);
                this._renderOrderHint(null);
            } else {
                this._minder.fire('savescene');
            }
            this._minder.layout(300);
            this._leaveDragMode();
            this._minder.fire('contentchange');
        },

        // 进入拖放模式：
        //    1. 计算拖放源和允许的拖放目标
        //    2. 标记已启动
        _enterDragMode: function() {
            this._calcDragSources();
            if (!this._dragSources.length) {
                this._startPosition = null;
                return false;
            }
            this._fadeDragSources(0.5);
            this._calcDropTargets();
            this._calcOrderHints();
            this._dragMode = true;
            this._minder.setStatus('dragtree');
            return true;
        },

        // 从选中的节点计算拖放源
        //    并不是所有选中的节点都作为拖放源，如果选中节点中存在 A 和 B，
        //    并且 A 是 B 的祖先，则 B 不作为拖放源
        //
        //    计算过程：
        //       1. 将节点按照树高排序，排序后只可能是前面节点是后面节点的祖先
        //       2. 从后往前枚举排序的结果，如果发现枚举目标之前存在其祖先，
        //          则排除枚举目标作为拖放源，否则加入拖放源
        _calcDragSources: function() {
            this._dragSources = this._minder.getSelectedAncestors();
        },

        _fadeDragSources: function(opacity) {
            var minder = this._minder;
            this._dragSources.forEach(function(source) {
                source.getRenderContainer().setOpacity(opacity, 200);
                source.traverse(function(node) {
                    if (opacity < 1) {
                        minder.detachNode(node);
                    } else {
                        minder.attachNode(node);
                    }
                }, true);
            });
        },

        // 计算拖放目标可以释放的节点列表（释放意味着成为其子树），存在这条限制规则：
        //    - 不能拖放到拖放目标的子树上（允许拖放到自身，因为多选的情况下可以把其它节点加入）
        //
        //    1. 加入当前节点（初始为根节点）到允许列表
        //    2. 对于当前节点的每一个子节点：
        //       (1) 如果是拖放目标的其中一个节点，忽略（整棵子树被剪枝）
        //       (2) 如果不是拖放目标之一，以当前子节点为当前节点，回到 1 计算
        //    3. 返回允许列表
        //
        _calcDropTargets: function() {

            function findAvailableParents(nodes, root) {
                var availables = [],
                    i;
                availables.push(root);
                root.getChildren().forEach(function(test) {
                    for (i = 0; i < nodes.length; i++) {
                        if (nodes[i] == test) return;
                    }
                    availables = availables.concat(findAvailableParents(nodes, test));
                });
                return availables;
            }

            this._dropTargets = findAvailableParents(this._dragSources, this._minder.getRoot());
            this._dropTargetBoxes = this._dropTargets.map(function(source) {
                return source.getLayoutBox();
            });
        },

        _calcOrderHints: function() {
            var sources = this._dragSources;
            var ancestor = MinderNode.getCommonAncestor(sources);

            // 只有一个元素选中，公共祖先是其父
            if (ancestor == sources[0]) ancestor = sources[0].parent;

            if (sources.length === 0 || ancestor != sources[0].parent) {
                this._orderHints = [];
                return;
            }

            var siblings = ancestor.children;

            this._orderHints = siblings.reduce(function(hint, sibling) {
                if (sources.indexOf(sibling) == -1) {
                    hint = hint.concat(sibling.getOrderHint());
                }
                return hint;
            }, []);
        },

        _leaveDragMode: function() {
            this._dragMode = false;
            this._dropSucceedTarget = null;
            this._orderSucceedHint = null;
            this._renderDropHint(null);
            this._renderOrderHint(null);
            this._minder.rollbackStatus();
        },

        _drawForDragMode: function() {
            this._text.setContent(this._dragSources.length + ' items');
            this._text.setPosition(this._startPosition.x, this._startPosition.y + 5);
            this._minder.getRenderContainer().addShape(this);
        },

        /**
         * 通过 judge 函数判断 targetBox 和 sourceBox 的位置交叉关系
         * @param targets -- 目标节点
         * @param targetBoxMapper -- 目标节点与对应 Box 的映射关系
         * @param judge -- 判断函数
         * @returns {*}
         * @private
         */
        _boxTest: function(targets, targetBoxMapper, judge) {
            var sourceBoxes = this._dragSources.map(function(source) {
                return source.getLayoutBox();
            });

            var i, j, target, sourceBox, targetBox;

            judge = judge || function(intersectBox, sourceBox, targetBox) {
                return intersectBox && !intersectBox.isEmpty();
            };

            for (i = 0; i < targets.length; i++) {

                target = targets[i];
                targetBox = targetBoxMapper.call(this, target, i);

                for (j = 0; j < sourceBoxes.length; j++) {
                    sourceBox = sourceBoxes[j];

                    var intersectBox = sourceBox.intersect(targetBox);
                    if (judge(intersectBox, sourceBox, targetBox)) {
                        return target;
                    }
                }
            }

            return null;
        },

        _dropTest: function() {
            this._dropSucceedTarget = this._boxTest(this._dropTargets, function(target, i) {
                return this._dropTargetBoxes[i];
            }, function(intersectBox, sourceBox, targetBox) {
                function area(box) {
                    return box.width * box.height;
                }
                if (!intersectBox) return false;
                /*
                * Added by zhangbobell, 2015.9.8
                *
                * 增加了下面一行判断，修复了循环比较中 targetBox 为折叠节点时，intersetBox 面积为 0，
                * 而 targetBox 的 width 和 height 均为 0
                * 此时造成了满足以下的第二个条件而返回 true
                * */
                if (!area(intersectBox)) return false;
                // 面积判断，交叉面积大于其中的一半
                if (area(intersectBox) > 0.5 * Math.min(area(sourceBox), area(targetBox))) return true;
                // 有一个边完全重合的情况，也认为两个是交叉的
                if (intersectBox.width + 1 >= Math.min(sourceBox.width, targetBox.width)) return true;
                if (intersectBox.height + 1 >= Math.min(sourceBox.height, targetBox.height)) return true;
                return false;
            });
            this._renderDropHint(this._dropSucceedTarget);
            return !!this._dropSucceedTarget;
        },

        _orderTest: function() {
            this._orderSucceedHint = this._boxTest(this._orderHints, function(hint) {
                return hint.area;
            });
            this._renderOrderHint(this._orderSucceedHint);
            return !!this._orderSucceedHint;
        },

        _renderDropHint: function(target) {
            this._dropHinter.render(target);
        },

        _renderOrderHint: function(hint) {
            this._orderHinter.render(hint);
        },
        preventDragMove: function() {
            this._startPosition = null;
        }
    });

    Module.register('DragTree', function() {
        var dragger;

        return {
            init: function() {
                dragger = new TreeDragger(this);
                window.addEventListener('mouseup', function() {
                    dragger.dragEnd();
                });
            },
            events: {
                'normal.mousedown inputready.mousedown': function(e) {
                    // 单选中根节点也不触发拖拽
                    if (e.originEvent.button) return;
                    if (e.getTargetNode() && e.getTargetNode() != this.getRoot()) {
                        dragger.dragStart(e.getPosition());
                    }
                },
                'normal.mousemove dragtree.mousemove': function(e) {
                    dragger.dragMove(e.getPosition());
                },
                'normal.mouseup dragtree.beforemouseup': function(e) {
                    dragger.dragEnd();
                    //e.stopPropagation();
                    e.preventDefault();
                },
                'statuschange': function(e) {
                    if (e.lastStatus == 'textedit' && e.currentStatus == 'normal') {
                        dragger.preventDragMove();
                    }
                }
            },
            commands: {
                'movetoparent': MoveToParentCommand
            }
        };
    });
});<|endoftext|>


<commit_before>const Discord = require('discord.js');
const client = new Discord.Client();
const figlet = require('figlet');
const fs = require('fs');
const irc = require('irc');

//process.argv.forEach((t) => console.log(t));

token = process.argv[2];
//console.log('Using token: ' + token);

client.on('ready', () => {
        console.log("BOT IS READY");
});

serverText = fs.readFileSync('servers.json');
var servers = JSON.parse(serverText);

const ircClient = new irc.Client(servers.irc.hostname, servers.irc.nick, {
        channels: servers.irc.channels,
        secure: servers.irc.secure,
        port: servers.irc.port
});

executorsText = fs.readFileSync('executors.json');
const executors = JSON.parse(executorsText).list;

function getChannelFromID(server, id) {
        return server.channels.resolve(id);
}

client.on('message', (msg) => {

        const re = /\?(?<command>\w*)(?<args> (\w*)*)?( ?```(?<code>.*)```)?/gms;
        input = re.exec(msg.content);

        if(input) {

                command = input.groups.command;
                args = input.groups.args;
                code = input.groups.code;

                //console.dir(input);

                if (input.groups.command == "fig") {
                        if (input.groups.args == undefined) {
                                msg.channel.send("You need to give some text to figlet");
                                return;
                        }

                        figlet(args, (err, data) => {
                                if (err) {
                                        console.log("figlet broke?");
                                }
                                msg.channel.send("```" + data + "```")
                        });
                }

                if (command == "setdel") {
                        var channel = args;
                        if (!servers[msg.guild.id]) {
                                servers[msg.guild.id] = {}
                        }
                        servers[msg.guild.id]["deletes"] = channel;

                        let newServer = JSON.stringify(servers);

                        fs.writeFile('servers.json', newServer, (err) => {
                                if (err) throw err;
                                console.log("delete prefs updated for " + msg.guild.name);
                        });

                        msg.channel.send("Delete channel preference set.")
                }

                if (command == "execute") {
                        if (executors.includes(""+msg.author.id)) {
                                if(code != undefined) {
                                        try {
                                                msg.channel.send(eval(code.trim(/(javascript)|(js)/gm)));
                                        } catch (e) {
                                                msg.channel.send("Your code caused an error");
                                        }
                                } else {
                                        msg.channel.send("You have to send some code using ```[code]```");
                                }
                        } else {
                                msg.channel.send("You are not an approved executor");
                        }
                }

        }

        if (msg.channel.id == servers.irc.cid) {
                ircClient.say(servers.irc.channels[0], "<" + msg.member.displayName + ">: " + msg.content);
        }

});

client.on('messageDelete', (msg) => {
        if (servers[msg.guild.id]) {
                if (servers[msg.guild.id]["deletes"]) {
                        chan = getChannelFromID(msg.guild, servers[msg.guild.id]["deletes"]);

                        let delEmbed = new Discord.MessageEmbed()
                                .setColor('#992020')
                                .setTitle("Deleted Message from " + msg.author.tag)
                                .addFields(
                                        {name: "Message", value: msg.content},
                                        {name: "Channel", value: msg.channel.name},
                                        {name: "Timestamp", value: msg.createdAt}
                                );
                        try {
                                chan.send(delEmbed);
                        } catch (e) {
                                console.log("error sending deleted message log");
                        }

                        console.log("sent deleted message log to " + msg.guild.name);

                }
        }

});

ircClient.addListener('message', (from, to, message) => {
        if (servers.irc.channels.includes(to)) {
                client.guild.resolve(servers.irc.sid).channels.resolve(servers.irc.cid).send(from + ": " + message);
        }
});

client.login(token);
<commit_msg>added irc error listener<commit_after>const Discord = require('discord.js');
const client = new Discord.Client();
const figlet = require('figlet');
const fs = require('fs');
const irc = require('irc');

//process.argv.forEach((t) => console.log(t));

token = process.argv[2];
//console.log('Using token: ' + token);

client.on('ready', () => {
        console.log("BOT IS READY");
});

serverText = fs.readFileSync('servers.json');
var servers = JSON.parse(serverText);

const ircClient = new irc.Client(servers.irc.hostname, servers.irc.nick, {
        channels: servers.irc.channels,
        secure: servers.irc.secure,
        port: servers.irc.port
});

executorsText = fs.readFileSync('executors.json');
const executors = JSON.parse(executorsText).list;

function getChannelFromID(server, id) {
        return server.channels.resolve(id);
}

client.on('message', (msg) => {

        const re = /\?(?<command>\w*)(?<args> (\w*)*)?( ?```(?<code>.*)```)?/gms;
        input = re.exec(msg.content);

        if(input) {

                command = input.groups.command;
                args = input.groups.args;
                code = input.groups.code;

                //console.dir(input);

                if (input.groups.command == "fig") {
                        if (input.groups.args == undefined) {
                                msg.channel.send("You need to give some text to figlet");
                                return;
                        }

                        figlet(args, (err, data) => {
                                if (err) {
                                        console.log("figlet broke?");
                                }
                                msg.channel.send("```" + data + "```")
                        });
                }

                if (command == "setdel") {
                        var channel = args;
                        if (!servers[msg.guild.id]) {
                                servers[msg.guild.id] = {}
                        }
                        servers[msg.guild.id]["deletes"] = channel;

                        let newServer = JSON.stringify(servers);

                        fs.writeFile('servers.json', newServer, (err) => {
                                if (err) throw err;
                                console.log("delete prefs updated for " + msg.guild.name);
                        });

                        msg.channel.send("Delete channel preference set.")
                }

                if (command == "execute") {
                        if (executors.includes(""+msg.author.id)) {
                                if(code != undefined) {
                                        try {
                                                msg.channel.send(eval(code.trim(/(javascript)|(js)/gm)));
                                        } catch (e) {
                                                msg.channel.send("Your code caused an error");
                                        }
                                } else {
                                        msg.channel.send("You have to send some code using ```[code]```");
                                }
                        } else {
                                msg.channel.send("You are not an approved executor");
                        }
                }

        }

        if (msg.channel.id == servers.irc.cid) {
                ircClient.say(servers.irc.channels[0], "<" + msg.member.displayName + ">: " + msg.content);
        }

});

client.on('messageDelete', (msg) => {
        if (servers[msg.guild.id]) {
                if (servers[msg.guild.id]["deletes"]) {
                        chan = getChannelFromID(msg.guild, servers[msg.guild.id]["deletes"]);

                        let delEmbed = new Discord.MessageEmbed()
                                .setColor('#992020')
                                .setTitle("Deleted Message from " + msg.author.tag)
                                .addFields(
                                        {name: "Message", value: msg.content},
                                        {name: "Channel", value: msg.channel.name},
                                        {name: "Timestamp", value: msg.createdAt}
                                );
                        try {
                                chan.send(delEmbed);
                        } catch (e) {
                                console.log("error sending deleted message log");
                        }

                        console.log("sent deleted message log to " + msg.guild.name);

                }
        }

});

ircClient.addListener('message', (from, to, message) => {
        if (servers.irc.channels.includes(to)) {
                client.guild.resolve(servers.irc.sid).channels.resolve(servers.irc.cid).send(from + ": " + message);
        }
});

ircClient.addListener('error', (msg) => {
        console.log("IRC Error: " + msg);
});

client.login(token);
<|endoftext|>


<commit_before>function integrate(tuples){
	var sum = 0;
	console.log(tuples);
	var boundB = tuples[tuples.length - 1].x;
	var boundA = tuples[0].x;
	for(var i=0;i<(tuples.length-1);i++){
		sum += ((tuples[i+1].x - tuples[i].x)*(tuples[i+1].y + tuples[i].y));
	}
	return (.5 * sum);
}
function xQuad(){
	var tempArr = [];
//	var boundA = $("#boundb").val();
//	var boundB = $("#bounda").val();
	var boundA_String = document.getElementById("bounda").innerHTML;
	var boundA_Int = parseInt(boundA_String);
	var boundB_String = document.getElementById("boundb").innerHTML;
	var boundB_Int = parseInt(boundB_String);

//	for(var i=boundA;i<=boundB;i++){
	for(var i=boundA_Int;i<=boundB_Int;i++){
		var tuple = {};
		tuple.x = i;
		tuple.y = Math.pow(i,2);
		tempArr.push(tuple);
	}
	return tempArr;
}
function xLin(){
	var tempArr = [];
//	var boundA = $("#boundb").val();
//	var boundB = $("#bounda").val();
	var boundA_String = document.getElementById("bounda").innerHTML;
	var boundA_Int = parseInt(boundA_String);
	var boundB_String = document.getElementById("boundb").innerHTML;
	var boundB_Int = parseInt(boundB_String);

//	for(var i=boundA;i<=boundB;i++){
	for(var i=boundA_Int;i<=boundB_Int;i++){
		var tuple = {};
		tuple.x = i;
		tuple.y = i;
		tempArr.push(tuple);
	}
	return tempArr;
}
//for testing, runs integrate() with xLin() as input
function integrateXLin(){
	document.getElementById("integral").innerHTML = integrate(xLin());
}
//for testing, runs integrate() with xQuad() as input
function integrateXQuad(){
	document.getElementById("integral").innerHTML = integrate(xQuad());
}
//final onpress function to run with parameters
function integrateFunc(){
	var func = document.getElementById("screen").innerHTML;
	console.log(func);
	//var boundA = $("#bounda").val(); //left
	//var boundB = $("#boundb").val(); //right
	var boundA_String = document.getElementById("bounda").innerHTML;
	var boundA_Int = parseInt(boundA_String);
	var boundB_String = document.getElementById("boundb").innerHTML;
	var boundB_Int = parseInt(boundB_String);

	//document.getElementById("integral").innerHTML = integrate(mapper(0,10,1));
	document.getElementById("integral").innerHTML = integrate(mapper(boundA_Int,boundB_Int,1));
}
//onpress function for integrating under function on screen
function drawIntegral(){
	refresh();
	var c = document.getElementById("graph");
	var ctext = c.getContext("2d");
	var tuples = mapper(-256,255,1);
	if(tuples.length < 1){
		tuples = deepCopy(defaultGraph);
	}
	scaleXCoords(tuples, xScaling);
	scaleYCoords(tuples, yScaling);
	//loops for each x
	for(var i=0;i<tuples.length;i++){
		//draws a rectangle with height y and width x at (x,y)
		ctext.fillRect((256+tuples[i].x),(256-tuples[i].y),(1*xScaling),tuples[i].y);
	}
	ctext.closePath();
	drawBorder();
}
<commit_msg>Add comments<commit_after>function integrate(tuples){
	var sum = 0;
	console.log(tuples);
	var boundB = tuples[tuples.length - 1].x;
	var boundA = tuples[0].x;
	for(var i=0;i<(tuples.length-1);i++){
		sum += ((tuples[i+1].x - tuples[i].x)*(tuples[i+1].y + tuples[i].y));
	}
	return (.5 * sum);
}
function xQuad(){
	var tempArr = [];
//	var boundA = $("#boundb").val();
//	var boundB = $("#bounda").val();
	//takes in the current left bound and converts it to type int
	var boundA_String = document.getElementById("bounda").innerHTML;
	var boundA_Int = parseInt(boundA_String);
	//takes in the current right bound and converts it to type int
	var boundB_String = document.getElementById("boundb").innerHTML;
	var boundB_Int = parseInt(boundB_String);

//	for(var i=boundA;i<=boundB;i++){
	for(var i=boundA_Int;i<=boundB_Int;i++){
		var tuple = {};
		tuple.x = i;
		tuple.y = Math.pow(i,2);
		tempArr.push(tuple);
	}
	return tempArr;
}
function xLin(){
	var tempArr = [];
//	var boundA = $("#boundb").val();
//	var boundB = $("#bounda").val();
	//takes in the current left bound and converts it to type int
	var boundA_String = document.getElementById("bounda").innerHTML;
	var boundA_Int = parseInt(boundA_String);
	//takes in the current right bound and converts it to type int
	var boundB_String = document.getElementById("boundb").innerHTML;
	var boundB_Int = parseInt(boundB_String);

//	for(var i=boundA;i<=boundB;i++){
	for(var i=boundA_Int;i<=boundB_Int;i++){
		var tuple = {};
		tuple.x = i;
		tuple.y = i;
		tempArr.push(tuple);
	}
	return tempArr;
}
//for testing, runs integrate() with xLin() as input
function integrateXLin(){
	document.getElementById("integral").innerHTML = integrate(xLin());
}
//for testing, runs integrate() with xQuad() as input
function integrateXQuad(){
	document.getElementById("integral").innerHTML = integrate(xQuad());
}
//final onpress function to run with parameters
function integrateFunc(){
	var func = document.getElementById("screen").innerHTML;
	console.log(func);
	//var boundA = $("#bounda").val(); //left
	//var boundB = $("#boundb").val(); //right
	//takes in the current left bound and converts it to type int
	var boundA_String = document.getElementById("bounda").innerHTML;
	var boundA_Int = parseInt(boundA_String);
	//takes in the current right bound and converts it to type int
	var boundB_String = document.getElementById("boundb").innerHTML;
	var boundB_Int = parseInt(boundB_String);

	//document.getElementById("integral").innerHTML = integrate(mapper(0,10,1));
	//passes in the bounds and step size into mapper which is passed into integrate and passes it to the screen
	document.getElementById("integral").innerHTML = integrate(mapper(boundA_Int,boundB_Int,1));
}
//onpress function for integrating under function on screen
function drawIntegral(){
	refresh();
	var c = document.getElementById("graph");
	var ctext = c.getContext("2d");
	var tuples = mapper(-256,255,1);
	if(tuples.length < 1){
		tuples = deepCopy(defaultGraph);
	}
	scaleXCoords(tuples, xScaling);
	scaleYCoords(tuples, yScaling);
	//loops for each x
	for(var i=0;i<tuples.length;i++){
		//draws a rectangle with height y and width x at (x,y)
		ctext.fillRect((256+tuples[i].x),(256-tuples[i].y),(1*xScaling),tuples[i].y);
	}
	ctext.closePath();
	drawBorder();
}
<|endoftext|>


<commit_before>/*global require, exports*/
var util = require('util'),
    _ = require('underscore'),
    extendWithGettersAndSetters = require('../util/extendWithGettersAndSetters'),
    Relation = require('./Relation');

function StaticUrlMapEntry(config) {
    Relation.call(this, config);
}

util.inherits(StaticUrlMapEntry, Relation);

extendWithGettersAndSetters(StaticUrlMapEntry.prototype, {
    baseAssetQuery: {type: 'Html', isInline: false},

    inline: function () {
        throw new Error("StaticUrlMapEntry.inline(): Not supported");
    },

    attach: function (asset, position, adjacentRelation) {
        position = position || 'last'; // FIXME?
        if (adjacentRelation && !this.wildCardValues) {
            // ? wildcards disabled because they're indistinguishable from GET parameters. This should work though (after the [\.\+] replace): .replace(/\?/g, '(.)')
            var wildCardValuesRegExp = new RegExp("^" + adjacentRelation.to.url.replace(/%7B/g, '{').replace(/%7D/g, '}').replace(/[\.\+]/g, "\\$&").replace(/\/\*\*\//g, '(?:\/(.+?))?\/').replace(/\*/g, '([^/]*?)').replace(/\{([^\}]*)\}/g, function ($0, $1) {
                    // {foo,bar} type wildcards
                    return '(' + $1.replace(/,/g, '|') + ')';
                }) + "$"),
                matchWildCardValues = this.to.url.match(wildCardValuesRegExp);
            if (matchWildCardValues) {
                // Map undefined to "" so ** that don't match anything get a sane value:
                this.wildCardValues = Array.prototype.slice.call(matchWildCardValues, 1).map(function (wildCardValue) {
                    return wildCardValue || '';
                });
            } else {
                throw new Error("relations.StaticUrlMapEntry.attach: Couldn't get wild card values");
            }
        }
        // This happens after wildcard expansion, adjacentRelation is the one with the wildcard
        if (this.wildCardValues) {
            if (this.wildCardValues.length !== asset.wildCardValueAsts.length) {
                throw new Error("relations.StaticUrlMapEntry.attach: Relation has the wrong number of wildcard values");
            }
            if (asset.wildCardValueAsts.length === 0) {
                if (asset.relationByWildCardValues) {
                    throw new Error("relations.StaticUrlMapEntry.attach: Cannot attach multiple relations to StaticUrlMap without wildcards.");
                }
                asset.relationByWildCardValues = this;
            } else {
                if (!asset.relationByWildCardValues) {
                    asset.relationByWildCardValues = {};
                } else if (asset.relationByWildCardValues.isRelation) {
                    if (this.relationByWildCardValues.href.indexOf('*') === -1) {
                        throw new Error("relations.StaticUrlMapEntry.attach: Cannot overwrite non-wildcard relation.");
                    }
                    this.relationByWildCardValues = {};
                }
                var cursor = asset.relationByWildCardValues;
                this.wildCardValues.forEach(function (wildCardValue, i) {
                    if (i === asset.wildCardValueAsts.length - 1) {
                        cursor[wildCardValue] = this;
                    } else {
                        if (!(wildCardValue in cursor)) {
                            cursor[wildCardValue] = {};
                        }
                        cursor = cursor[wildCardValue];
                    }
                }, this);
            }
        } else {
            throw new Error("relations.StaticUrlMapEntry.attach: The relation must have an adjacentRelation or a wildCardValues property");
        }
        return Relation.prototype.attach.call(this, asset, position, adjacentRelation);
    },

    detach: function () {
        if (this.wildCardValues) {
            var cursor = this.from.relationByWildCardValues;
            this.wildCardValues.forEach(function (wildCardValue, i) {
                if (i === this.from.wildCardValueAsts.length - 1) {
                    if (wildCardValue in cursor) {
                        delete cursor[wildCardValue];
                    } else {
                        throw new Error("relations.StaticUrlMapEntry.detach: The relation's set of wild card values aren't mapped.");
                    }
                } else {
                    if (!(wildCardValue in cursor)) {
                        throw new Error("relations.StaticUrlMapEntry.detach: The relation's set of wild card values aren't mapped.");
                    }
                    cursor = cursor[wildCardValue];
                }
            });
        } else if (this !== this.from.originalWildCardRelation) {
            throw new Error("relations.StaticUrlMapEntry.detach: Cannot detach relation without wildCardValues property or asterisks in its href");
        }
        return Relation.prototype.detach.call(this);
    }
});

module.exports = StaticUrlMapEntry;
<commit_msg>relations.StaticUrlMapEntry: Also escape ? when building a regexp out of the url.<commit_after>/*global require, exports*/
var util = require('util'),
    _ = require('underscore'),
    extendWithGettersAndSetters = require('../util/extendWithGettersAndSetters'),
    Relation = require('./Relation');

function StaticUrlMapEntry(config) {
    Relation.call(this, config);
}

util.inherits(StaticUrlMapEntry, Relation);

extendWithGettersAndSetters(StaticUrlMapEntry.prototype, {
    baseAssetQuery: {type: 'Html', isInline: false},

    inline: function () {
        throw new Error("StaticUrlMapEntry.inline(): Not supported");
    },

    attach: function (asset, position, adjacentRelation) {
        position = position || 'last'; // FIXME?
        if (adjacentRelation && !this.wildCardValues) {
            // ? wildcards disabled because they're indistinguishable from GET parameters. This should work though (after the [\.\+] replace): .replace(/\?/g, '(.)')
            var wildCardValuesRegExp = new RegExp("^" + adjacentRelation.to.url.replace(/%7B/g, '{').replace(/%7D/g, '}').replace(/[\.\+\?]/g, "\\$&").replace(/\/\*\*\//g, '(?:\/(.+?))?\/').replace(/\*/g, '([^/]*?)').replace(/\{([^\}]*)\}/g, function ($0, $1) {
                    // {foo,bar} type wildcards
                    return '(' + $1.replace(/,/g, '|') + ')';
                }) + "$"),
                matchWildCardValues = this.to.url.match(wildCardValuesRegExp);
            if (matchWildCardValues) {
                // Map undefined to "" so ** that don't match anything get a sane value:
                this.wildCardValues = Array.prototype.slice.call(matchWildCardValues, 1).map(function (wildCardValue) {
                    return wildCardValue || '';
                });
            } else {
                throw new Error("relations.StaticUrlMapEntry.attach: Couldn't get wild card values");
            }
        }
        // This happens after wildcard expansion, adjacentRelation is the one with the wildcard
        if (this.wildCardValues) {
            if (this.wildCardValues.length !== asset.wildCardValueAsts.length) {
                throw new Error("relations.StaticUrlMapEntry.attach: Relation has the wrong number of wildcard values");
            }
            if (asset.wildCardValueAsts.length === 0) {
                if (asset.relationByWildCardValues) {
                    throw new Error("relations.StaticUrlMapEntry.attach: Cannot attach multiple relations to StaticUrlMap without wildcards.");
                }
                asset.relationByWildCardValues = this;
            } else {
                if (!asset.relationByWildCardValues) {
                    asset.relationByWildCardValues = {};
                } else if (asset.relationByWildCardValues.isRelation) {
                    if (this.relationByWildCardValues.href.indexOf('*') === -1) {
                        throw new Error("relations.StaticUrlMapEntry.attach: Cannot overwrite non-wildcard relation.");
                    }
                    this.relationByWildCardValues = {};
                }
                var cursor = asset.relationByWildCardValues;
                this.wildCardValues.forEach(function (wildCardValue, i) {
                    if (i === asset.wildCardValueAsts.length - 1) {
                        cursor[wildCardValue] = this;
                    } else {
                        if (!(wildCardValue in cursor)) {
                            cursor[wildCardValue] = {};
                        }
                        cursor = cursor[wildCardValue];
                    }
                }, this);
            }
        } else {
            throw new Error("relations.StaticUrlMapEntry.attach: The relation must have an adjacentRelation or a wildCardValues property");
        }
        return Relation.prototype.attach.call(this, asset, position, adjacentRelation);
    },

    detach: function () {
        if (this.wildCardValues) {
            var cursor = this.from.relationByWildCardValues;
            this.wildCardValues.forEach(function (wildCardValue, i) {
                if (i === this.from.wildCardValueAsts.length - 1) {
                    if (wildCardValue in cursor) {
                        delete cursor[wildCardValue];
                    } else {
                        throw new Error("relations.StaticUrlMapEntry.detach: The relation's set of wild card values aren't mapped.");
                    }
                } else {
                    if (!(wildCardValue in cursor)) {
                        throw new Error("relations.StaticUrlMapEntry.detach: The relation's set of wild card values aren't mapped.");
                    }
                    cursor = cursor[wildCardValue];
                }
            });
        } else if (this !== this.from.originalWildCardRelation) {
            throw new Error("relations.StaticUrlMapEntry.detach: Cannot detach relation without wildCardValues property or asterisks in its href");
        }
        return Relation.prototype.detach.call(this);
    }
});

module.exports = StaticUrlMapEntry;
<|endoftext|>


<commit_before>    var Local = window.Local || {};

    Local.storageUnits = ['B', 'KB', 'MB', 'GB', 'TB'];
    Local.storageHex = 1024;

    Local.format = function(num, hex, units, dec, forTable) {
        num = num || 0;
        dec = dec || 0;
        forTable = forTable || false;
        var level = 0;

        // 详细报表中表格数据的最小单位为 KB 和 万次
        if (forTable) {
            num /= hex;
            level++;
        }
        while (num >= hex) {
            num /= hex;
            level++;
        }

        if (level === 0) {
            dec = 0;
        }

        return {
            'base': num.toFixed(dec),
            'unit': units[level],
            'format': function(sep) {
                sep = sep || '';
                return this.base + sep + this.unit;
            }
        };
    };

    Local.IE = (function() {
        var v = 4,
            div = document.createElement('div'),
            all = div.getElementsByTagName('i');
        while (
            div.innerHTML = '',
            all[0]
        ) {
            v++;
        }
        return v > 4 ? v : false;
    }());

    Local.uploaderRuntime = Local.IE && Local.IE < 10 ? 'flash' : 'html5,flash';
    console.log(Local.uploaderRuntime);

    var uploader = new plupload.Uploader({
        runtimes: 'html5,flash',
        browse_button: 'pickfiles',
        container: 'container',
        max_file_size: '40mb',
        url: 'http://up.qiniu.com',
        flash_swf_url: 'js/plupload/Moxie.swf',
        silverlight_xap_url: 'js/plupload/Moxie.xap',
        multipart_params: {
            "token": 'MX-bE11GUuO8WUqfv1kt69hNiJ2BeI3xeKYnZqMl:nyM055VliIdALnCy9vHhHsxnbyk=:eyJzY29wZSI6InFpbml1LXBsdXBsb2FkLWV4YW1wbGUiLCJkZWFkbGluZSI6MzkwOTYyNTkzN30='
        }
    });

    uploader.bind('Init', function(up, params) {
        //显示当前上传方式，调试用
        console.log('Current runtime:  ' + params.runtime);
    });
    uploader.init();

    uploader.bind('FilesAdded', function(up, files) {
        $.each(files, function(i, file) {
            var progress = new FileProgress(file, 'fsUploadProgress');
            progress.setStatus("等待...");
            progress.toggleCancel(true, uploader);
            up.start();
        });
        up.refresh(); // Reposition Flash/Silverlight
    });

    uploader.bind('BeforeUpload', function(up, file) {
        var progress = new FileProgress(file, 'fsUploadProgress');
        up.settings.multipart_params.key = file.name;
    });

    uploader.bind('UploadProgress', function(up, file) {
        var progress = new FileProgress(file, 'fsUploadProgress');
        progress.setProgress(file.percent + "%", up.total.bytesPerSec);
        progress.setStatus("上传中...", true);
    });

    uploader.bind('Error', function(up, err) {
        var file = err.file;
        var errTip = '';
        if (file) {
            var progress = new FileProgress(file, 'fsUploadProgress');
            progress.setError();
            switch (err.code) {
                case plupload.FAILED:
                    errTip = '上传失败';
                    break;
                case plupload.FILE_SIZE_ERROR:
                    errTip = '超过500M的文件请使用命令行或其他工具上传';
                    break;
                case plupload.FILE_EXTENSION_ERROR:
                    errTip = '非法的文件类型';
                    break;
                case plupload.HTTP_ERROR:
                    switch (err.status) {
                        case 400:
                            errTip = "请求参数错误";
                            break;
                        case 401:
                            errTip = "认证授权失败";
                            break;
                        case 405:
                            errTip = "请求方式错误，非预期的请求方式";
                            break;
                        case 579:
                            errTip = "文件上传成功，但是回调（callback app-server）失败";
                            break;
                        case 599:
                            errTip = "服务端操作失败";
                            break;
                        case 614:
                            errTip = "文件已存在";
                            break;
                        case 631:
                            errTip = "指定的存储空间（Bucket）不存在";
                            break;
                        default:
                            errTip = "其他HTTP_ERROR";
                            break;
                    }
                    break;
                case plupload.SECURITY_ERROR:
                    errTip = '安全错误';
                    break;
                case plupload.GENERIC_ERROR:
                    errTip = '通用错误';
                    break;
                case plupload.IO_ERROR:
                    errTip = '上传失败。请稍后重试';
                    break;
                case plupload.INIT_ERROR:
                    errTip = '配置错误';
                    uploader.destroy();
                    break;
                default:
                    errTip = err.message + err.details;
                    break;
            }
            progress.setStatus(errTip);
            progress.setCancelled();
        }
        up.refresh(); // Reposition Flash/Silverlight
    });

    uploader.bind('FileUploaded', function(up, file) {
        var progress = new FileProgress(file, 'fsUploadProgress');
        progress.setComplete();
        progress.setStatus("上传完成");
        progress.toggleCancel(false);
    });

    uploader.bind('UploadComplete', function(up, files) {

    });

    var cancelUpload = function() {
        uploader.destroy();
        model.manualCancel(true);
    };
<commit_msg>update qiniu.js<commit_after>    var Local = window.Local || {};

    Local.storageUnits = ['B', 'KB', 'MB', 'GB', 'TB'];
    Local.storageHex = 1024;

    Local.format = function(num, hex, units, dec, forTable) {
        num = num || 0;
        dec = dec || 0;
        forTable = forTable || false;
        var level = 0;

        // 详细报表中表格数据的最小单位为 KB 和 万次
        if (forTable) {
            num /= hex;
            level++;
        }
        while (num >= hex) {
            num /= hex;
            level++;
        }

        if (level === 0) {
            dec = 0;
        }

        return {
            'base': num.toFixed(dec),
            'unit': units[level],
            'format': function(sep) {
                sep = sep || '';
                return this.base + sep + this.unit;
            }
        };
    };

    // Local.IE = (function() {
    //     var v = 4,
    //         div = document.createElement('div'),
    //         all = div.getElementsByTagName('i');
    //     while (
    //         div.innerHTML = '',
    //         all[0]
    //     ) {
    //         v++;
    //     }
    //     return v > 4 ? v : false;
    // }());

    // Local.uploaderRuntime = Local.IE && Local.IE < 10 ? 'flash' : 'html5,flash';
    // console.log(Local.uploaderRuntime);

    var uploader = new plupload.Uploader({
        runtimes: 'html5,flash',
        browse_button: 'pickfiles',
        container: 'container',
        max_file_size: '40mb',
        url: 'http://up.qiniu.com',
        flash_swf_url: 'js/plupload/Moxie.swf',
        silverlight_xap_url: 'js/plupload/Moxie.xap',
        multipart_params: {
            "token": ''
        }
    });

    uploader.bind('Init', function(up, params) {
        //显示当前上传方式，调试用
        console.log('Current runtime:  ' + params.runtime);
        console.log(up.settings.multipart_params.token);
        $.ajax({
            url: '/token',
            type: 'GET',
            success: function(data) {
                if (data && data.uptoken) {
                    console.log(data.uptoken);
                    up.settings.multipart_params.token = data.uptoken;
                }
            },
            error: function(error) {
                console.log(error);
            }
        });
    });
    uploader.init();

    uploader.bind('FilesAdded', function(up, files) {

        $.each(files, function(i, file) {
            var progress = new FileProgress(file, 'fsUploadProgress');
            progress.setStatus("等待...");
            progress.toggleCancel(true, uploader);
            up.start();
        });
        up.refresh(); // Reposition Flash/Silverlight
    });

    uploader.bind('BeforeUpload', function(up, file) {
        var progress = new FileProgress(file, 'fsUploadProgress');
        up.settings.multipart_params.key = file.name;
    });

    uploader.bind('UploadProgress', function(up, file) {
        var progress = new FileProgress(file, 'fsUploadProgress');
        progress.setProgress(file.percent + "%", up.total.bytesPerSec);
        progress.setStatus("上传中...", true);
    });

    uploader.bind('Error', function(up, err) {
        var file = err.file;
        var errTip = '';
        if (file) {
            var progress = new FileProgress(file, 'fsUploadProgress');
            progress.setError();
            switch (err.code) {
                case plupload.FAILED:
                    errTip = '上传失败';
                    break;
                case plupload.FILE_SIZE_ERROR:
                    errTip = '超过500M的文件请使用命令行或其他工具上传';
                    break;
                case plupload.FILE_EXTENSION_ERROR:
                    errTip = '非法的文件类型';
                    break;
                case plupload.HTTP_ERROR:
                    switch (err.status) {
                        case 400:
                            errTip = "请求参数错误";
                            break;
                        case 401:
                            errTip = "认证授权失败";
                            break;
                        case 405:
                            errTip = "请求方式错误，非预期的请求方式";
                            break;
                        case 579:
                            errTip = "文件上传成功，但是回调（callback app-server）失败";
                            break;
                        case 599:
                            errTip = "服务端操作失败";
                            break;
                        case 614:
                            errTip = "文件已存在";
                            break;
                        case 631:
                            errTip = "指定的存储空间（Bucket）不存在";
                            break;
                        default:
                            errTip = "其他HTTP_ERROR";
                            break;
                    }
                    break;
                case plupload.SECURITY_ERROR:
                    errTip = '安全错误';
                    break;
                case plupload.GENERIC_ERROR:
                    errTip = '通用错误';
                    break;
                case plupload.IO_ERROR:
                    errTip = '上传失败。请稍后重试';
                    break;
                case plupload.INIT_ERROR:
                    errTip = '配置错误';
                    uploader.destroy();
                    break;
                default:
                    errTip = err.message + err.details;
                    break;
            }
            progress.setStatus(errTip);
            progress.setCancelled();
        }
        up.refresh(); // Reposition Flash/Silverlight
    });

    uploader.bind('FileUploaded', function(up, file) {
        var progress = new FileProgress(file, 'fsUploadProgress');
        progress.setComplete();
        progress.setStatus("上传完成");
        progress.toggleCancel(false);
    });

    uploader.bind('UploadComplete', function(up, files) {

    });

    var cancelUpload = function() {
        uploader.destroy();
        model.manualCancel(true);
    };

    $('#pickfiles').on('click', function() {

    });
<|endoftext|>


<commit_before>(function(){
    var objectHistoryDebugger = {
        trackAllObjects: true,
        _specificallyTrackedObjects: [],
        trackObject(obj){
            this._specificallyTrackedObjects.push(obj)
        },
        untrackObject(objToUntrack){
            this._specificallyTrackedObjects = this._specificallyTrackedObjects.filter(function(obj){
                return obj !== objToUntrack
            })
        },
        _isTrackingObject: function(obj){
            if (this.trackAllObjects) {
                return true;
            }

            return this._specificallyTrackedObjects.indexOf(obj) !== -1
        }
    }

    function PropertyHistory(propertyName){
        Object.defineProperties(this, {
            propertyName: {
                value: propertyName,
                enumerable: false
            },
            fullHistory: {
                value: [],
                enumerable: false
            }
        })
    }
    PropertyHistory.prototype.clone = function(){
        return {
            fullHistory: this.fullHistory.slice().map(assignment => {
                return {
                    value: assignment.value,
                    stack: assignment.stack.slice()
                }
            })
        }
    }
    PropertyHistory.prototype.prettyPrint = function(){
        console.info("Pretty print is asynchronous, so if you're paused in the debugger you first need to continue execution.")

        var fullHistory = this.clone().fullHistory;
        var self = this;

        var framesLeftToResolve = 0;

        fullHistory.forEach(function(assignment, assignmentIndex){
            assignment.stack.forEach(function(frameString, frameIndex){
                framesLeftToResolve++;

                codePreprocessor.resolveFrame(frameString, function(err, resolvedFrame){
                    framesLeftToResolve--;

                    fullHistory[assignmentIndex].stack[frameIndex] = resolvedFrame

                    if (framesLeftToResolve===0){
                        console.log("done")
                        self._log(fullHistory)
                    }
                })
            })
        })
    }
    PropertyHistory.prototype.prettyPrintSynchronously = function(){
        var hist = this;

        console.info("Pretty print synchronously will display history right away, but it won't apply source maps to show your original code.")

        this._log(hist.fullHistory)
    }
    PropertyHistory.prototype._log = function(fullHistory){
        console.group("%c Most recent '" + this.propertyName + "' assignments:", "color: red; text-transform: uppercase; font-weight: bold; font-size: 10px")
        fullHistory.forEach((assignment, i) => {
            var frame = assignment.stack[0]
            if (typeof frame === "string"){
                console.log("[" + i + "] Set to ", assignment.value, frame)
            } else {
                console.log("[" + i + "] Set to ", assignment.value)
                logFrameObject(frame, false)
            }

            console.groupCollapsed("%c MORE", "font-weight: bold; font-size: 7px;color: #777")
            assignment.stack.forEach(function(frame){
                if (typeof frame === "string") {
                    console.log(frame)
                } else if (typeof frame === "object") {
                    logFrameObject(frame, true)
                }
            })
            console.groupEnd()
        })
        console.groupEnd()

        function logFrameObject(frame, isDetailed){
            var path = frame.fileName.replace(".dontprocess", "")
            var parts = path.split("/")
            var fileName = parts[parts.length - 1]
            console.log("Original location:", fileName + ":" + frame.lineNumber + ":" + frame.columnNumber)
            if (isDetailed){
                var previousLine = frame.prevLines[frame.prevLines.length - 1]
                var nextLine = frame.nextLines[0]
                if (previousLine){
                    console.log("###", previousLine)
                }
                console.log(">>>", frame.line)
                if (nextLine) {
                    console.log("###", nextLine)
                }
            } else {
                console.log(frame.line)
            }
        }
    }
    Object.defineProperty(PropertyHistory.prototype, "clickDotsToPrettyPrintSynchronously", {
        get: function(){
            this.prettyPrintSynchronously()
            return "Printed to console"
        },
        enumerable: true
    })
    Object.defineProperty(PropertyHistory.prototype, "clickDotsToPrettyPrint", {
        get: function(){
            this.prettyPrint()
            return "See console, note pretty print is asynchronous"
        },
        enumerable: true
    })

    var nativeObjectGetOwnPropertyNames = Object.getOwnPropertyNames
    Object.getOwnPropertyNames = function(){
        // If DevTools calls it we want to show all names because
        // the __history__ properties should be visible to developer
        // We are checking stack to do that... works but possibly slow
        // and could break in future if DevTools/Chrome code changes
        var stack = Error().stack
        var calledFromDevTools = stack.indexOf("_propertyDescriptors.next") !== -1 &&
            stack.indexOf("InjectedScript") !== -1

        var names = nativeObjectGetOwnPropertyNames.apply(this, arguments)
        if (calledFromDevTools) {
            return names
        } else {
            return names.filter(removeHistoryPropertyNames)
        }

        function removeHistoryPropertyNames(name){
            return name.indexOf("__history__") === -1
        }
    }

    var nativeObjectGetOwnPropertyDescriptors = Object.getOwnPropertyDescriptors
    Object.getOwnPropertyDescriptors = function(){
        var descriptors = nativeObjectGetOwnPropertyDescriptors.apply(this, arguments)
        var ret = {}
        for (key in descriptors) {
            if (key.indexOf("__history__") === -1) {
                ret[key] = descriptors[key]
            }
        }

        return ret
    }

    window.__ohdAssign = function(object, propertyName, value){
        if (objectHistoryDebugger._isTrackingObject(object)) {
            var propertyNameString = propertyName.toString()

            var propertyNameType = typeof propertyName;
            // Either Symbol() or Object(Symbol())
            var propertyNameIsSymbol = propertyNameType === "symbol" || propertyNameString === "Symbol()"
            if (!propertyNameIsSymbol) {
                if (propertyName === null
                    || propertyName === undefined
                    || (propertyNameType !== "string")) {
                    propertyName = propertyNameString;
                }
            }

            addToHistory(object, propertyName, value)
        }

        return object[propertyName] = value
    }

    window.__ohdMakeObject = function(properties){
        var obj = {}
        var methodProperties = {};
        for (var i=0; i< properties.length ;i++){
            var property =  properties[i]
            var propertyType = property[0]
            var propertyKey = property[1]
            if (propertyType === "ObjectProperty") {
                __ohdAssign(obj, property[1], property[2])
            } else if (propertyType === "ObjectMethod") {
                var propertyKind = property[2]
                var fn = property[3]
                if (!methodProperties[propertyKey]){
                    methodProperties[propertyKey] = {
                        enumerable: true,
                        configurable: true
                    }
                }
                methodProperties[propertyKey][propertyKind] = fn

            }
        }
        Object.defineProperties(obj, methodProperties)
        return obj
    }

    window.__ohdDeleteProperty = function(object, propertyName){
        addToHistory(object, propertyName, undefined)
        return delete object[propertyName]
    }

    function addToHistory(object, propertyName, value){
        var propertyNameString = propertyName.toString();
        var storagePropName = propertyNameString + "__history__";

        if (object[storagePropName] === undefined){
            Object.defineProperty(object, storagePropName, {
                value: new PropertyHistory(propertyNameString),
                enumerable: false,
                writable: true
            })
        }

        Error.stackTraceLimit = 100
        var stack = Error().stack.split("\n")
        stack = stack.filter(frameString => {
            if (frameString === "Error") {
                return false;
            }
            if (frameString.indexOf("__ohd") !== -1) {
                return false;
            }
            if (frameString.indexOf("<anonymous>:") !== -1){
                return false;
            }
            if (frameString.indexOf("/ohd.js") !== -1) {
                return false;
            }
            return true;
        })

        object[storagePropName].fullHistory.unshift({
            stack,
            value
        })

        if (object[storagePropName].fullHistory.length > 20) {
            object[storagePropName].fullHistory = object[storagePropName].fullHistory.slice(0, 20)
        }
    }

    window.objectHistoryDebugger = objectHistoryDebugger

    if (typeof module !== "undefined"){
        module.exports = objectHistoryDebugger;
    }

})()
<commit_msg>Explain why objectHistoryDebugger is global for now.<commit_after>(function(){
    var objectHistoryDebugger = {
        trackAllObjects: true,
        _specificallyTrackedObjects: [],
        trackObject(obj){
            this._specificallyTrackedObjects.push(obj)
        },
        untrackObject(objToUntrack){
            this._specificallyTrackedObjects = this._specificallyTrackedObjects.filter(function(obj){
                return obj !== objToUntrack
            })
        },
        _isTrackingObject: function(obj){
            if (this.trackAllObjects) {
                return true;
            }

            return this._specificallyTrackedObjects.indexOf(obj) !== -1
        }
    }

    function PropertyHistory(propertyName){
        Object.defineProperties(this, {
            propertyName: {
                value: propertyName,
                enumerable: false
            },
            fullHistory: {
                value: [],
                enumerable: false
            }
        })
    }
    PropertyHistory.prototype.clone = function(){
        return {
            fullHistory: this.fullHistory.slice().map(assignment => {
                return {
                    value: assignment.value,
                    stack: assignment.stack.slice()
                }
            })
        }
    }
    PropertyHistory.prototype.prettyPrint = function(){
        console.info("Pretty print is asynchronous, so if you're paused in the debugger you first need to continue execution.")

        var fullHistory = this.clone().fullHistory;
        var self = this;

        var framesLeftToResolve = 0;

        fullHistory.forEach(function(assignment, assignmentIndex){
            assignment.stack.forEach(function(frameString, frameIndex){
                framesLeftToResolve++;

                codePreprocessor.resolveFrame(frameString, function(err, resolvedFrame){
                    framesLeftToResolve--;

                    fullHistory[assignmentIndex].stack[frameIndex] = resolvedFrame

                    if (framesLeftToResolve===0){
                        console.log("done")
                        self._log(fullHistory)
                    }
                })
            })
        })
    }
    PropertyHistory.prototype.prettyPrintSynchronously = function(){
        var hist = this;

        console.info("Pretty print synchronously will display history right away, but it won't apply source maps to show your original code.")

        this._log(hist.fullHistory)
    }
    PropertyHistory.prototype._log = function(fullHistory){
        console.group("%c Most recent '" + this.propertyName + "' assignments:", "color: red; text-transform: uppercase; font-weight: bold; font-size: 10px")
        fullHistory.forEach((assignment, i) => {
            var frame = assignment.stack[0]
            if (typeof frame === "string"){
                console.log("[" + i + "] Set to ", assignment.value, frame)
            } else {
                console.log("[" + i + "] Set to ", assignment.value)
                logFrameObject(frame, false)
            }

            console.groupCollapsed("%c MORE", "font-weight: bold; font-size: 7px;color: #777")
            assignment.stack.forEach(function(frame){
                if (typeof frame === "string") {
                    console.log(frame)
                } else if (typeof frame === "object") {
                    logFrameObject(frame, true)
                }
            })
            console.groupEnd()
        })
        console.groupEnd()

        function logFrameObject(frame, isDetailed){
            var path = frame.fileName.replace(".dontprocess", "")
            var parts = path.split("/")
            var fileName = parts[parts.length - 1]
            console.log("Original location:", fileName + ":" + frame.lineNumber + ":" + frame.columnNumber)
            if (isDetailed){
                var previousLine = frame.prevLines[frame.prevLines.length - 1]
                var nextLine = frame.nextLines[0]
                if (previousLine){
                    console.log("###", previousLine)
                }
                console.log(">>>", frame.line)
                if (nextLine) {
                    console.log("###", nextLine)
                }
            } else {
                console.log(frame.line)
            }
        }
    }
    Object.defineProperty(PropertyHistory.prototype, "clickDotsToPrettyPrintSynchronously", {
        get: function(){
            this.prettyPrintSynchronously()
            return "Printed to console"
        },
        enumerable: true
    })
    Object.defineProperty(PropertyHistory.prototype, "clickDotsToPrettyPrint", {
        get: function(){
            this.prettyPrint()
            return "See console, note pretty print is asynchronous"
        },
        enumerable: true
    })

    var nativeObjectGetOwnPropertyNames = Object.getOwnPropertyNames
    Object.getOwnPropertyNames = function(){
        // If DevTools calls it we want to show all names because
        // the __history__ properties should be visible to developer
        // We are checking stack to do that... works but possibly slow
        // and could break in future if DevTools/Chrome code changes
        var stack = Error().stack
        var calledFromDevTools = stack.indexOf("_propertyDescriptors.next") !== -1 &&
            stack.indexOf("InjectedScript") !== -1

        var names = nativeObjectGetOwnPropertyNames.apply(this, arguments)
        if (calledFromDevTools) {
            return names
        } else {
            return names.filter(removeHistoryPropertyNames)
        }

        function removeHistoryPropertyNames(name){
            return name.indexOf("__history__") === -1
        }
    }

    var nativeObjectGetOwnPropertyDescriptors = Object.getOwnPropertyDescriptors
    Object.getOwnPropertyDescriptors = function(){
        var descriptors = nativeObjectGetOwnPropertyDescriptors.apply(this, arguments)
        var ret = {}
        for (key in descriptors) {
            if (key.indexOf("__history__") === -1) {
                ret[key] = descriptors[key]
            }
        }

        return ret
    }

    window.__ohdAssign = function(object, propertyName, value){
        if (objectHistoryDebugger._isTrackingObject(object)) {
            var propertyNameString = propertyName.toString()

            var propertyNameType = typeof propertyName;
            // Either Symbol() or Object(Symbol())
            var propertyNameIsSymbol = propertyNameType === "symbol" || propertyNameString === "Symbol()"
            if (!propertyNameIsSymbol) {
                if (propertyName === null
                    || propertyName === undefined
                    || (propertyNameType !== "string")) {
                    propertyName = propertyNameString;
                }
            }

            addToHistory(object, propertyName, value)
        }

        return object[propertyName] = value
    }

    window.__ohdMakeObject = function(properties){
        var obj = {}
        var methodProperties = {};
        for (var i=0; i< properties.length ;i++){
            var property =  properties[i]
            var propertyType = property[0]
            var propertyKey = property[1]
            if (propertyType === "ObjectProperty") {
                __ohdAssign(obj, property[1], property[2])
            } else if (propertyType === "ObjectMethod") {
                var propertyKind = property[2]
                var fn = property[3]
                if (!methodProperties[propertyKey]){
                    methodProperties[propertyKey] = {
                        enumerable: true,
                        configurable: true
                    }
                }
                methodProperties[propertyKey][propertyKind] = fn

            }
        }
        Object.defineProperties(obj, methodProperties)
        return obj
    }

    window.__ohdDeleteProperty = function(object, propertyName){
        addToHistory(object, propertyName, undefined)
        return delete object[propertyName]
    }

    function addToHistory(object, propertyName, value){
        var propertyNameString = propertyName.toString();
        var storagePropName = propertyNameString + "__history__";

        if (object[storagePropName] === undefined){
            Object.defineProperty(object, storagePropName, {
                value: new PropertyHistory(propertyNameString),
                enumerable: false,
                writable: true
            })
        }

        Error.stackTraceLimit = 100
        var stack = Error().stack.split("\n")
        stack = stack.filter(frameString => {
            if (frameString === "Error") {
                return false;
            }
            if (frameString.indexOf("__ohd") !== -1) {
                return false;
            }
            if (frameString.indexOf("<anonymous>:") !== -1){
                return false;
            }
            if (frameString.indexOf("/ohd.js") !== -1) {
                return false;
            }
            return true;
        })

        object[storagePropName].fullHistory.unshift({
            stack,
            value
        })

        if (object[storagePropName].fullHistory.length > 20) {
            object[storagePropName].fullHistory = object[storagePropName].fullHistory.slice(0, 20)
        }
    }

    // Only needed for tests I think... we can get rid of it once we have
    // some kind of loader for Karma
    window.objectHistoryDebugger = objectHistoryDebugger

    if (typeof module !== "undefined"){
        module.exports = objectHistoryDebugger;
    }

})()
<|endoftext|>