<commit_before>function isString(v) {
    return typeof v == "string"
}

function isNumber(v) {
    return typeof v == "number"
}

function isBoolean(v) {
    return typeof v == "boolean"
}

function isObject(v) {
    return typeof v == "object"
}

function isFunction(v) {
    return typeof v == "function"
}

function isArray(v) {
    return Array.isArray(v)
}

function isUndefined(v) {
    return v === undefined
}

function isNull(v) {
    return v === null
}

function isEmpty(v) {
    return isUndefined(v) || isNull(v)
}

function isType(v, t) {
    if (isString(t))
        return typeof v == t
    return v instanceof t
}

function extend(a, b) {
    a.__proto__ = new b();
    a.type = arguments.callee.caller.name;
}

function instanceOf(el, s) {
    if (el.type) {
        if (el.type == s)
            return true;
        return instanceOf(el.__proto__, s);
    }
    return false
}

function hasProperty(obj, n) {
    if (!isObject(obj))
        throw new TypeError("Parameter 1 must be Object");
    if (!isString(obj))
        throw new TypeError("Parameter 2 must be String");
    return (n in obj);
}

function query(s, t) {
    var p = t || document;
    return p.querySelector(s)
}

function queryAll(s, t) {
    var p = t || document;
    return p.querySelectorAll(s);
}

//Create Node from html string
function createNode(html) {
    var div = document.createElement("div");
    div.innerHTML = html;
    return div.childNodes[0];
}

function BaseObject() {
    var that = this;
    this.type = "BaseObject"

    var _data = {};
    this.defineProperty = function (n, value, readOnly) {
        _data[n] = value;
        this[n] = function (v) {
            if (!isEmpty(v) && !readOnly) {
                var e = {
                    name: n,
                    value: v,
                    cancel: false
                };
                that.trigger("beforeChange", [e]);
                if (!e.cancel) {
                    _data[n] = e.value;
                    that.trigger("change", [{ name: n, value: e.value }]);
                }
            }
            return _data[n]
        }
    }

    var _events = {};
    this.on = function (n, cb) {
        if (!isString(n))
            throw new TypeError("Parameter 1 must be String");
        if (!isFunction(cb))
            throw new TypeError("Parameter 2 must be Function");
        if (!(n in _events)) {
            _events[n] = []
        }
        _events[n].push(cb);
    }

    this.trigger = function (n, args) {
        if (n in _events) {
            for (var i in _events[n])
                _events[n][i].apply(this, args);
        }
    }

    this.off = function (n) {
        delete _events[n]
        return true;
    }

    this.applyOptions = function (options) {
        if (!isEmpty(options)) {
            if (!isObject(options))
                throw new TypeError("Parameter 1 must be Object");
            for (var i in options) {
                var prop = this[i];
                if (prop) {
                    if (isFunction(prop))
                        prop.call(this, options[i]);
                }

            }
        }
    }
}

//Collection
function Collection() {
    extend(this, BaseObject);

    var _items = {};
    this.items = function (index) {
        return _items[index];
    }

    this.length = function () {
        var res = Object.keys(_items).length;
        return res;
    }

    this.add = function (item) {
        var e = {
            value: item,
            cancel: false
        }
        this.trigger("beforeAdd", [e])
        if (!e.cancel) {
            var len = this.length();
            _items[len] = e.value;
            this.trigger("add", [{ value: e.value, index: this.length() }])
        }
    }

    function refreshIndexes(val) {
        var j = 0;
        for (var i in val) {
            val[j++] = val[i];
            if (i != j)
                delete val[i];
        }
    }

    this.removeAt = function (index) {
        var e = {
            value: item,
            cancel: false
        }
        this.trigger("beforeRemove", [e])
        if (!e.cancel) {
            delete _items[index];
            refreshIndexes(_items);
            this.trigger("remove", [e])
        }
    }
    function compareBase(el, val) {
        if (el.type) {
            if (el.type == val.type)
                return el == val;
            return compareBase(el.__proto__, val);
        }
        return false;
    }
    this.indexOf = function (val) {
        var res = -1;
        for (var i in _items)
            if (compareBase(_items[i], val)) {
                res = +i;
                break;
            }
        return res;
    }

    function init() {

    }
    init.apply(this, arguments);
}

//Element
function Element() {
    extend(this, BaseObject);
    var that = this;

    this.defineProperty("node");
    this.defineProperty("class");
    this.on("beforeChange", function (e) {
        switch (e.name) {
            case "class":
                if (!isString(e.value))
                    throw new TypeError("Value must be String");
                that.node().classList.remove(that.class());
                that.node().classList.add(e.value);
                break;
        }
    })

    this.create = function (s) {
        s = s || "div";
        var html = "<" + s + "/>";
        this.node(createNode(html));

        var that = this;
        this.node().addEventListener("click", function () {
            that.trigger("click", arguments);
        })
    }

    this.instanceOf = function (s) {
        return instanceOf(this, s);
    }

    this.query = function (s, t) {
        var p = t || document;
        return p.querySelector(s)
    }

    this.queryAll = function (s, t) {
        var p = t || document;
        return p.querySelectorAll(s);
    }

    this.appendTo = function (node) {
        if (instanceOf(node, "Element"))
            node.appendChild(this.node());
        else {
            var _node = node;
            if (isString(node))
                _node = this.query(node);
            _node.appendChild(this.node());
        }
    }

    this.addClass = function (s) {
        this.node().classList.add(s);
    }

    this.removeClass = function (s) {
        this.node().classList.remove(s);
    }

    this.hasClass = function (s) {
        return this.node().classList.contains(s);
    }

    this.attr = function (n, val) {
        if (isNull(val))
            this.node().removeAttribute(n);
        else if (isUndefined(val)) {
            return this.node().getAttribute(n);
        }
        else {
            this.node().setAttribute(n, val);
            return val;
        }
    }

    this.hasProperty = function (n) {
        return hasProperty(this, n);
    }

    this.text = function (s) {
        if (!isEmpty(s)) {
            if (!isString(s)) {
                throw new TypeError("Value must be String");
                this.node().textContent = s;
            }
        }
        return this.node().textContent;
    }

    this.html = function (s) {
        if (!isEmpty(s)) {
            if (!isString(s)) {
                throw new TypeError("Value must be String");
                this.node().innerHTML = s;
            }
        }
        return this.node().innerHTML;
    }

    this.show = function () {
        this.node().classList.remove("hidden");
    }

    this.hide = function () {
        this.node().classList.add("hidden");
    }

    this.append = function (node) {
        this.node().appendChild(node);
    }

    this.width = function (n) {
        if (n !== undefined)
            this.node().style.width = n;
        return this.node().clientWidth;
    }

    this.height = function (n) {
        if (n !== undefined)
            this.node().style.height = n;
        return this.node().clientHeight;
    }

    this.size = function (h, w) {
        if (arguments.length = 2) {
            this.width(w);
            this.height(h);
        }
        return { height: this.height(), width: this.width() }
    }

    this.x = this.left = function (n) {
        if (n !== undefined) {
            this.node().style.left = n;
            this.trigger("move");
        }
        return this.node().offsetLeft;
    }

    this.y = this.top = function (n) {
        if (n !== undefined) {
            this.node().style.top = n;
            this.trigger("move");
        }
        return this.node().offsetTop;
    }

    this.position = function (o) {
        if (o) {
            this.node().style.left = o.x || o.left;
            this.node().style.top = o.y || o.top;
            this.trigger("move");
        }
        return { x: this.x(), y: this.y() }
    }

    function init() {
    }

    init.apply(this, arguments);
}<commit_msg>Fix: Mozila, Explorer bugs<commit_after>function isString(v) {
    return typeof v == "string"
}

function isNumber(v) {
    return typeof v == "number"
}

function isBoolean(v) {
    return typeof v == "boolean"
}

function isObject(v) {
    return typeof v == "object"
}

function isFunction(v) {
    return typeof v == "function"
}

function isArray(v) {
    return Array.isArray(v)
}

function isUndefined(v) {
    return v === undefined
}

function isNull(v) {
    return v === null
}

function isEmpty(v) {
    return isUndefined(v) || isNull(v)
}

function isType(v, t) {
    if (isString(t))
        return typeof v == t
    return v instanceof t
}

function extend(a, b) {
    var reg = /function ([\w]+)/;
    var res = null;
    if (res = reg.exec(a.constructor.toString())){
        a.__type = res[1];
    }
    else{
        throw new Error("Error on get function name");
    }
    a.__proto__ = new b();
}

function instanceOf(el, s) {
    if (el.__type) {
        if (el.__type == s)
            return true;
        return instanceOf(el.__proto__, s);
    }
    return false
}

function hasProperty(obj, n) {
    if (!isObject(obj))
        throw new TypeError("Parameter 1 must be Object");
    if (!isString(n))
        throw new TypeError("Parameter 2 must be String");
    return (n in obj);
}

function query(s, t) {
    var p = t || document;
    return p.querySelector(s)
}

function queryAll(s, t) {
    var p = t || document;
    return p.querySelectorAll(s);
}

//Create Node from html string
function createNode(html) {
    var div = document.createElement("div");
    div.innerHTML = html;
    return div.childNodes[0];
}

function BaseObject() {
    var that = this;
    this.__type = "BaseObject"

    var _data = {};
    this.defineProperty = function (n, value, readOnly) {
        _data[n] = value;
        this[n] = function (v) {
            if (!isEmpty(v) && !readOnly) {
                var e = {
                    name: n,
                    value: v,
                    cancel: false
                };
                that.trigger("beforeChange", [e]);
                if (!e.cancel) {
                    _data[n] = e.value;
                    that.trigger("change", [{ name: n, value: e.value }]);
                }
            }
            return _data[n]
        }
    }

    this.hasProperty = function (n) {
        return hasProperty(this, n);
    }

    this.clearProperty = function (n) {
        if (this.hasProperty(n)) {
            _data[n] = null;
            return true;
        }
        return false;
    }

    var _events = {};
    this.on = function (n, cb) {
        if (!isString(n))
            throw new TypeError("Parameter 1 must be String");
        if (!isFunction(cb))
            throw new TypeError("Parameter 2 must be Function");
        if (!(n in _events)) {
            _events[n] = []
        }
        _events[n].push(cb);
    }

    this.trigger = function (n, args) {
        if (n in _events) {
            for (var i in _events[n])
                _events[n][i].apply(this, args);
        }
    }

    this.off = function (n) {
        delete _events[n]
        return true;
    }

    this.applyOptions = function (options) {
        if (!isEmpty(options)) {
            if (!isObject(options))
                throw new TypeError("Parameter 1 must be Object");
            for (var i in options) {
                var prop = this[i];
                if (prop) {
                    if (isFunction(prop))
                        prop.call(this, options[i]);
                }

            }
        }
    }
}

//Collection
function Collection() {
    extend(this, BaseObject);

    var _items = {};
    this.items = function (index) {
        return _items[index];
    }

    this.length = function () {
        var res = Object.keys(_items).length;
        return res;
    }

    this.add = function (item) {
        var e = {
            value: item,
            cancel: false
        }
        this.trigger("beforeAdd", [e])
        if (!e.cancel) {
            var len = this.length();
            _items[len] = e.value;
            this.trigger("add", [{ value: e.value, index: this.length() }])
        }
    }

    function refreshIndexes(val) {
        var j = 0;
        for (var i in val) {
            val[j++] = val[i];
            if (i != j)
                delete val[i];
        }
    }

    this.removeAt = function (index) {
        var e = {
            value: item,
            cancel: false
        }
        this.trigger("beforeRemove", [e])
        if (!e.cancel) {
            delete _items[index];
            refreshIndexes(_items);
            this.trigger("remove", [e])
        }
    }
    function compareBase(el, val) {
        if (el.__type) {
            if (el.__type == val.__type)
                return el == val;
            return compareBase(el.__proto__, val);
        }
        return false;
    }
    this.indexOf = function (val) {
        var res = -1;
        for (var i in _items)
            if (compareBase(_items[i], val)) {
                res = +i;
                break;
            }
        return res;
    }

    function init() {

    }
    init.apply(this, arguments);
}

//Element
function Element() {
    extend(this, BaseObject);
    var that = this;

    this.defineProperty("node");
    this.defineProperty("class");
    this.defineProperty("visible");
    this.on("beforeChange", function (e) {
        switch (e.name) {
            case "class":
                if (!isString(e.value))
                    throw new TypeError("Value must be String");
                that.node().classList.remove(that.class());
                that.node().classList.add(e.value);
                break;
        }
    })

    this.on("change", function (e) {
        switch (e.name) {
            case "node":
                e.value.addEventListener("click", function () {
                    that.trigger("click", arguments);
                })
                break;
            case "visible":
                if (e.value)
                    that.node().style.display = "";
                else
                    that.node().style.display = "none";
                break;
        }
    })

    this.create = function (s) {
        s = s || "div";
        var html = "<" + s + "/>";
        this.node(createNode(html));
    }

    this.instanceOf = function (s) {
        return instanceOf(this, s);
    }

    this.query = function (s, t) {
        var p = t || document;
        return p.querySelector(s)
    }

    this.queryAll = function (s, t) {
        var p = t || document;
        return p.querySelectorAll(s);
    }

    this.appendTo = function (node) {
        if (instanceOf(node, "Element"))
            node.node().appendChild(this.node());
        else {
            var _node = node;
            if (isString(node))
                _node = query(node);
            _node.appendChild(this.node());
        }
    }

    this.addClass = function (s) {
        this.node().classList.add(s);
    }

    this.removeClass = function (s) {
        this.node().classList.remove(s);
    }

    this.hasClass = function (s) {
        return this.node().classList.contains(s);
    }

    this.attr = function (n, val) {
        if (isNull(val))
            this.node().removeAttribute(n);
        else if (isUndefined(val)) {
            return this.node().getAttribute(n);
        }
        else {
            this.node().setAttribute(n, val);
            return val;
        }
    }

    this.text = function (s) {
        if (!isEmpty(s)) {
            if (!isString(s))
                throw new TypeError("Value must be String");
            this.node().textContent = s;
        }
        return this.node().textContent;
    }

    this.html = function (s) {
        if (!isEmpty(s)) {
            if (!isString(s))
                throw new TypeError("Value must be String");
            this.node().innerHTML = s;
        }
        return this.node().innerHTML;
    }

    this.show = function () {
        this.node().classList.remove("hidden");
    }

    this.hide = function () {
        this.node().classList.add("hidden");
    }

    this.append = function (node) {
        if (instanceOf(node, "Element")) {
            node = node.node();
        }
        this.node().appendChild(node);
    }

    this.width = function (n) {
        if (n !== undefined)
            this.node().style.width = n;
        return this.node().clientWidth;
    }

    this.height = function (n) {
        if (n !== undefined)
            this.node().style.height = n;
        return this.node().clientHeight;
    }

    this.size = function (h, w) {
        if (arguments.length = 2) {
            this.width(w);
            this.height(h);
        }
        return { height: this.height(), width: this.width() }
    }

    this.x = this.left = function (n) {
        if (n !== undefined) {
            this.node().style.left = n;
            this.trigger("move");
        }
        return this.node().offsetLeft;
    }

    this.y = this.top = function (n) {
        if (n !== undefined) {
            this.node().style.top = n;
            this.trigger("move");
        }
        return this.node().offsetTop;
    }

    this.position = function (o) {
        if (o) {
            this.node().style.left = o.x || o.left;
            this.node().style.top = o.y || o.top;
            this.trigger("move");
        }
        return { x: this.x(), y: this.y() }
    }

    function init() {
    }

    init.apply(this, arguments);
}<|endoftext|>


<commit_before>var extractor = require('../extractor');

var map = {title:'title', links: 'a' };

extractor.Scrape('http://nodejs.org', map, function(err, data, url) {
	var i;
	if (err) {
		console.error("ERROR: " + err);
	}
	console.log("from -> "+ url);
	console.log("data -> " + JSON.stringify(data));
	for(i = 0; i < data.links.length; i += 1) {
		console.log("Link " + i + ": " + data.links[i].href);
	}
});
<commit_msg>Updated example for 0.0.8.<commit_after>var extractor = require('../extractor');

var map = {title:'title', links: 'a' };

extractor.Scrape('http://nodejs.org', map, function(err, data, env) {
	var i;
	if (err) {
		console.error("ERROR: " + err);
	}
	console.log("from -> "+ env.pathname);
	console.log("data -> " + JSON.stringify(data));
	for(i = 0; i < data.links.length; i += 1) {
		console.log("Link " + i + ": " + data.links[i].href);
	}
});
<|endoftext|>


<commit_before>var Html = require('./html');

function Fast(options) {

  this._format = 'xhtml';
  this._jsWrapper = 'cdata';
  this._attrQuote = '"';
  this._autoclose  = 'base basefont bgsound link meta area br embed img keygen wbr input menuitem param source track hr col frame'.split(/\s/);

  // We don't support options now
  //if (this._format !== 'xhtml') {
    //this._jsWrapper = 'comment';
  //}

  switch(this._jsWrapper) {
    case 'cdata':
      this._jsWrapper = ['\n//<![CDATA[\n', '\n//]]>\n'];
      break;
    case 'comment':
      this._jsWrapper = ['<!--\n', '\n//-->'];
      break;
    case 'both':
      this._jsWrapper = ['<!--\n//<![CDATA[\n', '\n//]]>\n//-->'];
  }
}

var FastProto = Fast.prototype = new Html();

FastProto.on_html_doctype = function(exps) {
  var type = exps[2];

  var XHTML_DOCTYPES = {
    '1.1'          : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
    '5'            : '<!DOCTYPE html>',
    'html'         : '<!DOCTYPE html>',
    'strict'       : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
    'frameset'     : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
    'basic'        : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
    'transitional' : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
    'svg'          : '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'
  };

  var HTML_DOCTYPES = {
    '5'            : '<!DOCTYPE html>',
    'html'         : '<!DOCTYPE html>',
    'strict'       : '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
    'frameset'     : '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
    'transitional' : '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
  };

  type = type.toString().toLowerCase();
  var m, str;

  m = /^xml(\s+(.+))?$/.exec(type);
  if (m) {
    if (this._format !== 'xhtml') {
      throw new Error('Invalid xml directive in html mode');
    }
    var w = this._attrQuote;
    str = '<?xml version=' + w + '1.0' + w + ' encoding=' + w + (m[2] || 'utf-8') + w + ' ?>';
  } else if (this._format !== 'xhtml') {
    str = HTML_DOCTYPES[type];
    if (!str) {
      throw new Error('Invalid html doctype ' + type);
    }
  } else {
    str = XHTML_DOCTYPES[type];
    if (!str) {
      throw new Error('Invalid xhtml doctype ' + type);
    }
  }

  return ['static', str];
};

FastProto.on_html_comment = function(exps) {
  return ['multi', ['static', '<!--'], this.compile(exps[2]), ['static', '-->']];
};

FastProto.on_html_condcomment = function(exps) {
  return this.on_html_comment(['html', 'comment', [
    'multi',
      ['static', '[' + exps[2] + ']>'], exps[3], ['static', '<![endif]']]]);
};

FastProto.on_html_tag = function(exps) {
  var name = exps[2].toString(), attrs = exps[3], content = exps[4];

  var closed = !content || (this._isEmptyExp(content) && this._autoclose.indexOf(name) !== -1);

  var res = [
    'multi',
      ['static', '<' + name],
      this.compile(attrs),
      ['static', (closed && this._format === 'xhtml' ? ' /' : '') + '>']
    ];

  if (content) {
    res.push(this.compile(content));
  }
  if (!closed) {
    res.push(['static', "</" + name + ">"]);
  }
  return res;
};

FastProto.on_html_attrs = FastProto._shiftAndCompileMulti;

FastProto.on_html_attr = function(exps) {
  var name = exps[2], value = exps[3];

  if (this._format !== 'xhtml' && this._isEmptyExp(value)) {
    return ['static', ' ' + name];
  }
  return ['multi',
    ['static', ' ' + name + '=' + this._attrQuote],
    this.compile(value),
    ['static', this._attrQuote]];
};

FastProto.on_html_js = function(exps) {
  var content = exps[2];

  return ['multi',
     ['static', this._jsWrapper[0]],
     this.compile(content),
     ['static', this._jsWrapper[1]]];
};

module.exports = Fast;
<commit_msg>Code cleanup<commit_after>var Html = require('./html');

function Fast() {

  // TODO: get format and js wrapper from options (constructor argument)
  this._format = 'xhtml';
  this._jsWrapper = 'cdata';
  this._attrQuote = '"';
  this._autoclose  = 'base basefont bgsound link meta area br embed img keygen wbr input menuitem param source track hr col frame'.split(/\s/);

  // We don't support options now
  //if (this._format !== 'xhtml') {
    //this._jsWrapper = 'comment';
  //}

  switch(this._jsWrapper) {
    case 'cdata':
      this._jsWrapper = ['\n//<![CDATA[\n', '\n//]]>\n'];
      break;
    case 'comment':
      this._jsWrapper = ['<!--\n', '\n//-->'];
      break;
    case 'both':
      this._jsWrapper = ['<!--\n//<![CDATA[\n', '\n//]]>\n//-->'];
  }
}

var FastProto = Fast.prototype = new Html();

FastProto.on_html_doctype = function(exps) {
  var type = exps[2];

  var XHTML_DOCTYPES = {
    '1.1'          : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
    '5'            : '<!DOCTYPE html>',
    'html'         : '<!DOCTYPE html>',
    'strict'       : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
    'frameset'     : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
    'basic'        : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
    'transitional' : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
    'svg'          : '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'
  };

  var HTML_DOCTYPES = {
    '5'            : '<!DOCTYPE html>',
    'html'         : '<!DOCTYPE html>',
    'strict'       : '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
    'frameset'     : '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
    'transitional' : '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
  };

  type = type.toString().toLowerCase();
  var m, str;

  m = /^xml(\s+(.+))?$/.exec(type);
  if (m) {
    if (this._format !== 'xhtml') {
      throw new Error('Invalid xml directive in html mode');
    }
    var w = this._attrQuote;
    str = '<?xml version=' + w + '1.0' + w + ' encoding=' + w + (m[2] || 'utf-8') + w + ' ?>';
  } else if (this._format !== 'xhtml') {
    str = HTML_DOCTYPES[type];
    if (!str) {
      throw new Error('Invalid html doctype ' + type);
    }
  } else {
    str = XHTML_DOCTYPES[type];
    if (!str) {
      throw new Error('Invalid xhtml doctype ' + type);
    }
  }

  return ['static', str];
};

FastProto.on_html_comment = function(exps) {
  return ['multi', ['static', '<!--'], this.compile(exps[2]), ['static', '-->']];
};

FastProto.on_html_condcomment = function(exps) {
  return this.on_html_comment(['html', 'comment', [
    'multi',
      ['static', '[' + exps[2] + ']>'], exps[3], ['static', '<![endif]']]]);
};

FastProto.on_html_tag = function(exps) {
  var name = exps[2].toString(), attrs = exps[3], content = exps[4];

  var closed = !content || (this._isEmptyExp(content) && this._autoclose.indexOf(name) !== -1);

  var res = [
    'multi',
      ['static', '<' + name],
      this.compile(attrs),
      ['static', (closed && this._format === 'xhtml' ? ' /' : '') + '>']
    ];

  if (content) {
    res.push(this.compile(content));
  }
  if (!closed) {
    res.push(['static', "</" + name + ">"]);
  }
  return res;
};

FastProto.on_html_attrs = FastProto._shiftAndCompileMulti;

FastProto.on_html_attr = function(exps) {
  var name = exps[2], value = exps[3];

  if (this._format !== 'xhtml' && this._isEmptyExp(value)) {
    return ['static', ' ' + name];
  }
  return ['multi',
    ['static', ' ' + name + '=' + this._attrQuote],
    this.compile(value),
    ['static', this._attrQuote]];
};

FastProto.on_html_js = function(exps) {
  var content = exps[2];

  return ['multi',
     ['static', this._jsWrapper[0]],
     this.compile(content),
     ['static', this._jsWrapper[1]]];
};

module.exports = Fast;
<|endoftext|>


<commit_before>var shellView = Backbone.View.extend({
  el: '#content',
  events: {
    'click #editor-run' : 'submitEditor'
  },

  template: new EJS({url: '/_admin/html/js/templates/shellView.ejs'}),

  render: function() {
    $(this.el).html(this.template.text);
    this.replShell();
    this.editor();
    $("#shell_workspace").splitter({
      dock: true
    });
    $("#shell_workspace").trigger("resize", [ 200 ]);
    $('.vsplitbar').append('

');
    return this;
  },
  editor: function () {
    var editor = ace.edit("editor");
    editor.getSession().setMode("ace/mode/javascript");
  },
  submitEditor: function () {
    var editor = ace.edit("editor");
    var data = editor.getValue();
        try {
          if (window.eval(data) === undefined) {
          }
          else {
            jqconsole.Write('==> ' + window.eval(data) + '\n', 'jssuccess');
          }
        } catch (e) {
          jqconsole.Write('ReferenceError: ' + e.message + '\n', 'jserror');
      }
      jqconsole.Focus();
  },
  replShell: function () {
    // Creating the console.
    var header = 'Welcome to arangosh Copyright (c) 2012 triAGENS GmbH.\n';
    window.jqconsole = $('#replShell').jqconsole(header, 'JSH> ', "hehe");

    // Abort prompt on Ctrl+Z.
    jqconsole.RegisterShortcut('Z', function() {
      jqconsole.AbortPrompt();
      handler();
    });
    // Move to line end Ctrl+E.
    jqconsole.RegisterShortcut('E', function() {
      jqconsole.MoveToEnd();
      handler();
    });
    jqconsole.RegisterMatching('{', '}', 'brace');
    jqconsole.RegisterMatching('(', ')', 'paran');
    jqconsole.RegisterMatching('[', ']', 'bracket');
    // Handle a command.
    var handler = function(command) {
      if (command === 'help') {
        command = "require(\"arangosh\").HELP";
      }
      if (command === "exit") {
        location.reload();
      }
        try {
          if (window.eval(command) === undefined) {
          }
          else {
            jqconsole.Write('==> ' + window.eval(command) + '\n', 'jssuccess');
          }
        } catch (e) {
          jqconsole.Write('ReferenceError: ' + e.message + '\n', 'jserror');
      }
      jqconsole.Prompt(true, handler, function(command) {
        // Continue line if can't compile the command.
        try {
          Function(command);
        } catch (e) {
          if (/[\[\{\(]$/.test(command)) {
            return 1;
          } else {
            return 0;
          }
          }
          return false;
        });
      };

      // Initiate the first prompt.
      handler();
    },
    evaloutput: function (data) {
      try {
        var result = eval(data);
        if (result !== undefined) {
          print(result);
        }
      }
      catch(e) {
        $('#shellContent').append('
Error:' + e + '
');
      }
    }

  });
<commit_msg>jsshell resize event<commit_after>var shellView = Backbone.View.extend({
  el: '#content',
  events: {
    'click #editor-run'     : 'submitEditor',
    'mouseleave .vsplitbar' : 'renderEditor'
  },

  template: new EJS({url: '/_admin/html/js/templates/shellView.ejs'}),

  render: function() {
    $(this.el).html(this.template.text);
    this.replShell();
    this.editor();
    $("#shell_workspace").splitter({
      dock: true
    });
    $("#shell_workspace").trigger("resize", [ 200 ]);
    $('.vsplitbar').append('

');
    return this;
  },
  renderEditor: function () {
    var editor = ace.edit("editor");
    editor.resize()
  },
  editor: function () {
    var editor = ace.edit("editor");
    editor.getSession().setMode("ace/mode/javascript");
  },
  submitEditor: function () {
    var editor = ace.edit("editor");
    var data = editor.getValue();
        try {
          if (window.eval(data) === undefined) {
          }
          else {
            jqconsole.Write('==> ' + window.eval(data) + '\n', 'jssuccess');
          }
        } catch (e) {
          jqconsole.Write('ReferenceError: ' + e.message + '\n', 'jserror');
      }
      jqconsole.Focus();
  },
  replShell: function () {
    // Creating the console.
    var header = 'Welcome to arangosh Copyright (c) 2012 triAGENS GmbH.\n';
    window.jqconsole = $('#replShell').jqconsole(header, 'JSH> ', "hehe");

    // Abort prompt on Ctrl+Z.
    jqconsole.RegisterShortcut('Z', function() {
      jqconsole.AbortPrompt();
      handler();
    });
    // Move to line end Ctrl+E.
    jqconsole.RegisterShortcut('E', function() {
      jqconsole.MoveToEnd();
      handler();
    });
    jqconsole.RegisterMatching('{', '}', 'brace');
    jqconsole.RegisterMatching('(', ')', 'paran');
    jqconsole.RegisterMatching('[', ']', 'bracket');
    // Handle a command.
    var handler = function(command) {
      if (command === 'help') {
        command = "require(\"arangosh\").HELP";
      }
      if (command === "exit") {
        location.reload();
      }
        try {
          if (window.eval(command) === undefined) {
          }
          else {
            jqconsole.Write('==> ' + window.eval(command) + '\n', 'jssuccess');
          }
        } catch (e) {
          jqconsole.Write('ReferenceError: ' + e.message + '\n', 'jserror');
      }
      jqconsole.Prompt(true, handler, function(command) {
        // Continue line if can't compile the command.
        try {
          Function(command);
        } catch (e) {
          if (/[\[\{\(]$/.test(command)) {
            return 1;
          } else {
            return 0;
          }
          }
          return false;
        });
      };

      // Initiate the first prompt.
      handler();
    },
    evaloutput: function (data) {
      try {
        var result = eval(data);
        if (result !== undefined) {
          print(result);
        }
      }
      catch(e) {
        $('#shellContent').append('
Error:' + e + '
');
      }
    }

  });
<|endoftext|>


<commit_before>
var Observers = require("./observers");
var autoCancelPrevious = Observers.autoCancelPrevious;
var once = Observers.once;

exports.makePropertyBinder = makePropertyBinder;
function makePropertyBinder(observeObject, observeKey) {
    return function (observeValue, source, target, parameters, descriptor, trace) {
        return observeKey(autoCancelPrevious(function (key) {
            if (key == null) return;
            return observeObject(autoCancelPrevious(function (object) {
                if (object == null) return;
                if (object.bindProperty) {
                    return object.bindProperty(key, observeValue, source, parameters, descriptor, trace);
                } else {
                    return bindProperty(object, key, observeValue, source, parameters, descriptor, trace);
                }
            }), target, parameters);
        }), target, parameters);
    };
}

exports.bindProperty = bindProperty;
function bindProperty(object, key, observeValue, source, parameters, descriptor, trace) {
    return observeValue(autoCancelPrevious(function (value) {
        if (descriptor.isActive) {
            trace && console.log("IGNORED SET", trace.targetPath, "TO", value, "ON", object, "BECAUSE", trace.sourcePath, "ALREADY ACTIVE");
            return;
        }
        try {
            descriptor.isActive = true;
            trace && console.log("SET", trace.targetPath, "TO", value, "ON", object, "BECAUSE", trace.sourcePath);
            if (Array.isArray(object) && key >>> 0 === key) {
                // TODO spec this case
                object.set(key, value);
            } else {
                object[key] = value;
            }
        } finally {
            descriptor.isActive = false;
        }
    }), source, parameters);
}

exports.makeGetBinder = makeGetBinder;
function makeGetBinder(observeCollection, observeKey) {
    return function bindGet(observeValue, source, target, parameters, descriptor, trace) {
        return observeCollection(autoCancelPrevious(function replaceCollection(collection) {
            if (!collection) return;
            return observeKey(autoCancelPrevious(function replaceKey(key) {
                if (key == null) return;
                return bindKey(collection, key, observeValue, source, parameters, descriptor, trace);
            }), target, parameters);
        }), target, parameters);
    };
}

exports.bindKey = bindKey;
function bindKey(collection, key, observeValue, source, parameters, descriptor, trace) {
    return observeValue(autoCancelPrevious(function replaceValue(value) {
        if (descriptor.isActive) {
            trace && console.log("IGNORED SET FOR KEY", key, "OF", trace.targetPath, "TO", value, "ON", collection, "BECAUSE", trace.sourcePath, "ALREADY ACTIVE");
            return;
        }
        try {
            descriptor.isActive = true;
            trace && console.log("SET FOR KEY", key, "TO", value, "ON", collection, "BECAUSE", trace.sourcePath);
            collection.set(key, value);
        } finally {
            descriptor.isActive = false;
        }
    }), source, parameters);
}

exports.makeHasBinder = makeHasBinder;
function makeHasBinder(observeSet, observeValue) {
    return function (observeHas, source, target, parameters, descriptor, trace) {
        return observeSet(autoCancelPrevious(function (set) {
            if (!set) return;
            return observeValue(autoCancelPrevious(function (value) {
                return observeHas(autoCancelPrevious(function (has) {
                    // wait for the initial value to be updated by the
                    // other-way binding
                    if (has) { // should be in set
                        if (!(set.has || set.contains).call(set, value)) {
                            trace && console.log("ADD", value, "TO", trace.targetPath, "BECAUSE", trace.sourcePath);
                            set.add(value);
                        }
                    } else { // should not be in set
                        while ((set.has || set.contains).call(set, value)) {
                            trace && console.log("REMOVE", value, "FROM", trace.targetPath, "BECAUSE", trace.sourcePath);
                            (set.remove || set['delete']).call(set, value);
                        }
                    }
                }), source, parameters);
            }), target, parameters);
        }), target, parameters);
    };
}

// a == b <-> c
exports.makeEqualityBinder = makeEqualityBinder;
function makeEqualityBinder(bindLeft, observeRight) {
    return function (observeEquals, source, target, parameters, descriptor, trace) {
        // c
        return observeEquals(autoCancelPrevious(function (equals) {
            if (equals) {
                trace && console.log("BIND", trace.targetPath, "TO", trace.sourcePath);
                // a <-> b
                var cancel = bindLeft(observeRight, source, source, parameters, descriptor, trace);
                return function () {
                    trace && console.log("UNBIND", trace.targetPath, "FROM", trace.sourcePath);
                };
            }
        }), target, parameters);
    };
}

// (a ? b : c) <- d
exports.makeConditionalBinder = makeConditionalBinder;
function makeConditionalBinder(observeCondition, bindConsequent, bindAlternate) {
    return function (observeSource, source, target, parameters, descriptor, trace) {
        // a
        return observeCondition(autoCancelPrevious(function replaceCondition(condition) {
            if (condition == null) return;
            if (condition) {
                // b <- d
                return bindConsequent(observeSource, source, target, parameters, descriptor, trace);
            } else {
                // c <- d
                return bindAlternate(observeSource, source, target, parameters, descriptor, trace);
            }
        }), source, parameters);
    };
}

// a.* <- b.*
exports.makeRangeContentBinder = makeRangeContentBinder;
function makeRangeContentBinder(observeTarget) {
    return function (observeSource, source, target, parameters, descriptor, trace) {
        return observeTarget(autoCancelPrevious(function (target) {
            if (!target) return;
            return observeSource(autoCancelPrevious(function (source) {
                if (!source) {
                    target.clear();
                    return;
                }

                function rangeChange(plus, minus, index) {
                    if (isActive(target))
                        return;
                    if (trace) {
                        console.log("SWAPPING", minus, "FOR", plus, "AT", index);
                    }
                    if (target.swap) {
                        target.swap(index, minus.length, plus);
                    } else if (target.add && (target.remove || target["delete"])) {
                        plus.forEach(target.add, target);
                        minus.forEach(target.remove || target["delete"], target);
                    }
                }
                source.addRangeChangeListener(rangeChange);
                rangeChange(Array.from(source), Array.from(target), 0);
                return once(function () {
                    source.removeRangeChangeListener(rangeChange);
                });
            }), source, parameters);
        }), target, parameters);
    };
}

exports.makeMapContentBinder = makeMapContentBinder;
function makeMapContentBinder(observeTarget) {
    return function (observeSource, source, target, parameters, descriptor, trace) {
        return observeTarget(autoCancelPrevious(function (target) {
            if (!target) return;
            return observeSource(autoCancelPrevious(function (source) {
                if (!source) {
                    target.clear();
                    return;
                }

                function mapChange(value, key) {
                    if (descriptor.isActive) {
                        if (trace) {
                            console.log("IGNORED MAP CHANGE", trace.targetPath, "TO", value, "ON", target, "BECAUSE", trace.sourcePath, "ALREADY ACTIVE");
                        }
                        return;
                    }
                    try {
                        descriptor.isActive = true;
                        if (value === undefined) {
                            if (trace) {
                                trace && console.log("DELETED", trace.targetPath, "FOR KEY", key, "ON", target, "BECAUSE", trace.sourcePath);
                            }
                            if (Array.isArray(target)) {
                                target.splice(key, 1);
                            } else {
                                target["delete"](key);
                            }
                        } else {
                            if (trace) {
                                trace && console.log("SET", trace.targetPath, "FOR KEY", key, "TO", value, "ON", target, "BECAUSE", trace.sourcePath);
                            }
                            target.set(key, value);
                        }
                    } finally {
                        descriptor.isActive = false;
                    }
                }
                target.clear();
                source.forEach(mapChange);
                return source.addMapChangeListener(mapChange);
            }), source, parameters);
        }), target, parameters);
    };
}

// a.reversed() <-> b
exports.makeReversedBinder = makeReversedBinder;
function makeReversedBinder(observeTarget) {
    return function (observeSource, source, target, parameters, descriptor, trace) {
        return observeTarget(autoCancelPrevious(function (target) {
            if (!target) return;
            return observeSource(autoCancelPrevious(function (source) {
                if (!source) {
                    target.clear();
                    return;
                }

                function rangeChange(plus, minus, index) {
                    if (isActive(target))
                        return;
                    var reflected = target.length - index - minus.length;
                    target.swap(reflected, minus.length, plus.reversed());
                }
                source.addRangeChangeListener(rangeChange);
                rangeChange(source, target, 0);
                return once(function () {
                    source.removeRangeChangeListener(rangeChange);
                });
            }), source, parameters);
        }), target, parameters);
    };
}

function isActive(target) {
    return (
        target.getRangeChangeDescriptor &&
        target.getRangeChangeDescriptor().isActive
    );
}

<commit_msg>Ignore non-observable ranges in content binder<commit_after>
var Observers = require("./observers");
var autoCancelPrevious = Observers.autoCancelPrevious;
var once = Observers.once;

exports.makePropertyBinder = makePropertyBinder;
function makePropertyBinder(observeObject, observeKey) {
    return function (observeValue, source, target, parameters, descriptor, trace) {
        return observeKey(autoCancelPrevious(function (key) {
            if (key == null) return;
            return observeObject(autoCancelPrevious(function (object) {
                if (object == null) return;
                if (object.bindProperty) {
                    return object.bindProperty(key, observeValue, source, parameters, descriptor, trace);
                } else {
                    return bindProperty(object, key, observeValue, source, parameters, descriptor, trace);
                }
            }), target, parameters);
        }), target, parameters);
    };
}

exports.bindProperty = bindProperty;
function bindProperty(object, key, observeValue, source, parameters, descriptor, trace) {
    return observeValue(autoCancelPrevious(function (value) {
        if (descriptor.isActive) {
            trace && console.log("IGNORED SET", trace.targetPath, "TO", value, "ON", object, "BECAUSE", trace.sourcePath, "ALREADY ACTIVE");
            return;
        }
        try {
            descriptor.isActive = true;
            trace && console.log("SET", trace.targetPath, "TO", value, "ON", object, "BECAUSE", trace.sourcePath);
            if (Array.isArray(object) && key >>> 0 === key) {
                // TODO spec this case
                object.set(key, value);
            } else {
                object[key] = value;
            }
        } finally {
            descriptor.isActive = false;
        }
    }), source, parameters);
}

exports.makeGetBinder = makeGetBinder;
function makeGetBinder(observeCollection, observeKey) {
    return function bindGet(observeValue, source, target, parameters, descriptor, trace) {
        return observeCollection(autoCancelPrevious(function replaceCollection(collection) {
            if (!collection) return;
            return observeKey(autoCancelPrevious(function replaceKey(key) {
                if (key == null) return;
                return bindKey(collection, key, observeValue, source, parameters, descriptor, trace);
            }), target, parameters);
        }), target, parameters);
    };
}

exports.bindKey = bindKey;
function bindKey(collection, key, observeValue, source, parameters, descriptor, trace) {
    return observeValue(autoCancelPrevious(function replaceValue(value) {
        if (descriptor.isActive) {
            trace && console.log("IGNORED SET FOR KEY", key, "OF", trace.targetPath, "TO", value, "ON", collection, "BECAUSE", trace.sourcePath, "ALREADY ACTIVE");
            return;
        }
        try {
            descriptor.isActive = true;
            trace && console.log("SET FOR KEY", key, "TO", value, "ON", collection, "BECAUSE", trace.sourcePath);
            collection.set(key, value);
        } finally {
            descriptor.isActive = false;
        }
    }), source, parameters);
}

exports.makeHasBinder = makeHasBinder;
function makeHasBinder(observeSet, observeValue) {
    return function (observeHas, source, target, parameters, descriptor, trace) {
        return observeSet(autoCancelPrevious(function (set) {
            if (!set) return;
            return observeValue(autoCancelPrevious(function (value) {
                return observeHas(autoCancelPrevious(function (has) {
                    // wait for the initial value to be updated by the
                    // other-way binding
                    if (has) { // should be in set
                        if (!(set.has || set.contains).call(set, value)) {
                            trace && console.log("ADD", value, "TO", trace.targetPath, "BECAUSE", trace.sourcePath);
                            set.add(value);
                        }
                    } else { // should not be in set
                        while ((set.has || set.contains).call(set, value)) {
                            trace && console.log("REMOVE", value, "FROM", trace.targetPath, "BECAUSE", trace.sourcePath);
                            (set.remove || set['delete']).call(set, value);
                        }
                    }
                }), source, parameters);
            }), target, parameters);
        }), target, parameters);
    };
}

// a == b <-> c
exports.makeEqualityBinder = makeEqualityBinder;
function makeEqualityBinder(bindLeft, observeRight) {
    return function (observeEquals, source, target, parameters, descriptor, trace) {
        // c
        return observeEquals(autoCancelPrevious(function (equals) {
            if (equals) {
                trace && console.log("BIND", trace.targetPath, "TO", trace.sourcePath);
                // a <-> b
                var cancel = bindLeft(observeRight, source, source, parameters, descriptor, trace);
                return function () {
                    trace && console.log("UNBIND", trace.targetPath, "FROM", trace.sourcePath);
                };
            }
        }), target, parameters);
    };
}

// (a ? b : c) <- d
exports.makeConditionalBinder = makeConditionalBinder;
function makeConditionalBinder(observeCondition, bindConsequent, bindAlternate) {
    return function (observeSource, source, target, parameters, descriptor, trace) {
        // a
        return observeCondition(autoCancelPrevious(function replaceCondition(condition) {
            if (condition == null) return;
            if (condition) {
                // b <- d
                return bindConsequent(observeSource, source, target, parameters, descriptor, trace);
            } else {
                // c <- d
                return bindAlternate(observeSource, source, target, parameters, descriptor, trace);
            }
        }), source, parameters);
    };
}

// a.* <- b.*
exports.makeRangeContentBinder = makeRangeContentBinder;
function makeRangeContentBinder(observeTarget) {
    return function (observeSource, source, target, parameters, descriptor, trace) {
        return observeTarget(autoCancelPrevious(function (target) {
            if (!target) return;
            return observeSource(autoCancelPrevious(function (source) {
                if (!source || !source.addRangeChangeListener) {
                    target.clear();
                    return;
                }

                function rangeChange(plus, minus, index) {
                    if (isActive(target))
                        return;
                    if (trace) {
                        console.log("SWAPPING", minus, "FOR", plus, "AT", index);
                    }
                    if (target.swap) {
                        target.swap(index, minus.length, plus);
                    } else if (target.add && (target.remove || target["delete"])) {
                        plus.forEach(target.add, target);
                        minus.forEach(target.remove || target["delete"], target);
                    }
                }

                source.addRangeChangeListener(rangeChange);
                rangeChange(Array.from(source), Array.from(target), 0);
                return once(function () {
                    source.removeRangeChangeListener(rangeChange);
                });
            }), source, parameters);
        }), target, parameters);
    };
}

exports.makeMapContentBinder = makeMapContentBinder;
function makeMapContentBinder(observeTarget) {
    return function (observeSource, source, target, parameters, descriptor, trace) {
        return observeTarget(autoCancelPrevious(function (target) {
            if (!target) return;
            return observeSource(autoCancelPrevious(function (source) {
                if (!source) {
                    target.clear();
                    return;
                }

                function mapChange(value, key) {
                    if (descriptor.isActive) {
                        if (trace) {
                            console.log("IGNORED MAP CHANGE", trace.targetPath, "TO", value, "ON", target, "BECAUSE", trace.sourcePath, "ALREADY ACTIVE");
                        }
                        return;
                    }
                    try {
                        descriptor.isActive = true;
                        if (value === undefined) {
                            if (trace) {
                                trace && console.log("DELETED", trace.targetPath, "FOR KEY", key, "ON", target, "BECAUSE", trace.sourcePath);
                            }
                            if (Array.isArray(target)) {
                                target.splice(key, 1);
                            } else {
                                target["delete"](key);
                            }
                        } else {
                            if (trace) {
                                trace && console.log("SET", trace.targetPath, "FOR KEY", key, "TO", value, "ON", target, "BECAUSE", trace.sourcePath);
                            }
                            target.set(key, value);
                        }
                    } finally {
                        descriptor.isActive = false;
                    }
                }
                target.clear();
                source.forEach(mapChange);
                return source.addMapChangeListener(mapChange);
            }), source, parameters);
        }), target, parameters);
    };
}

// a.reversed() <-> b
exports.makeReversedBinder = makeReversedBinder;
function makeReversedBinder(observeTarget) {
    return function (observeSource, source, target, parameters, descriptor, trace) {
        return observeTarget(autoCancelPrevious(function (target) {
            if (!target) return;
            return observeSource(autoCancelPrevious(function (source) {
                if (!source) {
                    target.clear();
                    return;
                }

                function rangeChange(plus, minus, index) {
                    if (isActive(target))
                        return;
                    var reflected = target.length - index - minus.length;
                    target.swap(reflected, minus.length, plus.reversed());
                }
                source.addRangeChangeListener(rangeChange);
                rangeChange(source, target, 0);
                return once(function () {
                    source.removeRangeChangeListener(rangeChange);
                });
            }), source, parameters);
        }), target, parameters);
    };
}

function isActive(target) {
    return (
        target.getRangeChangeDescriptor &&
        target.getRangeChangeDescriptor().isActive
    );
}

<|endoftext|>


<commit_before>define(
  'ephox.darwin.keyboard.Retries',

  [
    'ephox.darwin.keyboard.Carets',
    'ephox.darwin.keyboard.Rectangles',
    'ephox.fussy.api.Point',
    'ephox.peanut.Fun',
    'ephox.perhaps.Option',
    'ephox.scullion.ADT',
    'global!Math'
  ],

  function (Carets, Rectangles, Point, Fun, Option, Adt, Math) {
    var JUMP_SIZE = 5;
    /*
     * This isn't right ... but let's just hook it up first.
     */

    var adt = Adt.generate([
      { 'none' : [] },
      { 'retry': [ 'caret' ] },
      { 'adjusted': [ 'caret' ] }
    ]);

    var adjustDown = function (guessBox, original, caret) {
      // We haven't dropped vertically, so we need to look down and try again.
      if (guessBox.bottom === original.bottom()) return adt.retry(Carets.moveDown(caret, JUMP_SIZE));
      // The returned guessBox based on the guess actually doesn't include the initial caret. So we search again
      // where we adjust the caret so that it is inside the returned guessBox. This means that the offset calculation
      // will be more accurate.
      else if (guessBox.top > caret.bottom()) return adt.adjusted(Carets.moveBottomTo(caret, guessBox.top + 1));
      else return adt.none();
    };

    var adjustUp = function (guessBox, original, caret) {
      // We haven't ascended vertically, so we need to look up and try again.
      if (guessBox.top === original.top()) return adt.retry(Carets.moveUp(caret, JUMP_SIZE));
      // The returned guessBox based on the guess actually doesn't include the initial caret. So we search again
      // where we adjust the caret so that it is inside the returned guessBox. This means that the offset calculation
      // will be more accurate.
      else if (guessBox.bottom < caret.top()) return adt.adjusted(Carets.moveTopTo(caret, guessBox.bottom - 1));
      else return adt.none();
    };

    var upMovement = {
      point: Carets.getTop,
      adjuster: adjustUp,
      move: Carets.moveUp
    };

    var downMovement = {
      point: Carets.getBottom,
      adjuster: adjustDown,
      move: Carets.moveDown
    };

    var adjustTil = function (win, direction, original, caret) {
      return Point.find(win, caret.left(), direction.point(caret)).bind(function (guess) {
        return guess.start().fold(Option.none, function (element, offset) {
          return Rectangles.getBox(win, element, offset).bind(function (guessBox) {
            return direction.adjuster(guessBox, original, caret).fold(Option.none, function (newCaret) {
              return adjustTil(win, direction, original, newCaret);
            }, function (newCaret) {
              return Option.some(newCaret);
            });
          });
        }, Option.none);
      });
    };

    var ieTryDown = function (win, caret) {
      return Point.find(win, caret.left, caret.bottom + JUMP_SIZE);
    };

    var ieTryUp = function (win, caret) {
      return Point.find(win, caret.left, caret.top - JUMP_SIZE);
    };

    var retry = function (direction, win, caret) {
      var c = Carets.nu(caret.left, caret.top, caret.right, caret.bottom);
      var moved = direction.move(c, JUMP_SIZE);
      var adjusted = adjustTil(win, direction, c, moved).getOr(moved);
      return Point.find(win, adjusted.left(), adjusted.bottom());
    };

    return {
      tryUp: Fun.curry(retry, upMovement),
      tryDown: Fun.curry(retry, downMovement),
      ieTryUp: ieTryUp,
      ieTryDown: ieTryDown
    };
  }
);<commit_msg>TBIO-2087: up sort of working<commit_after>define(
  'ephox.darwin.keyboard.Retries',

  [
    'ephox.darwin.keyboard.Carets',
    'ephox.darwin.keyboard.Rectangles',
    'ephox.fussy.api.Point',
    'ephox.peanut.Fun',
    'ephox.perhaps.Option',
    'ephox.scullion.ADT',
    'global!Math'
  ],

  function (Carets, Rectangles, Point, Fun, Option, Adt, Math) {
    var JUMP_SIZE = 5;
    /*
     * This isn't right ... but let's just hook it up first.
     */

    var adt = Adt.generate([
      { 'none' : [] },
      { 'retry': [ 'caret' ] },
      { 'adjusted': [ 'caret' ] }
    ]);

    var adjustDown = function (guessBox, original, caret) {
      // We haven't dropped vertically, so we need to look down and try again.
      if (guessBox.bottom === original.bottom()) return adt.retry(Carets.moveDown(caret, JUMP_SIZE));
      // The returned guessBox based on the guess actually doesn't include the initial caret. So we search again
      // where we adjust the caret so that it is inside the returned guessBox. This means that the offset calculation
      // will be more accurate.
      else if (guessBox.top > caret.bottom()) return adt.adjusted(Carets.moveBottomTo(caret, guessBox.top + 1));
      else return adt.none();
    };

    var adjustUp = function (guessBox, original, caret) {
      console.log('guessBox', guessBox.top, guessBox.bottom, 'original', original.top(), 'caret', caret.top());
      // We haven't ascended vertically, so we need to look up and try again.
      if (guessBox.top === original.top()) return adt.retry(Carets.moveUp(caret, JUMP_SIZE));
      // The returned guessBox based on the guess actually doesn't include the initial caret. So we search again
      // where we adjust the caret so that it is inside the returned guessBox. This means that the offset calculation
      // will be more accurate.
      else if (guessBox.bottom < caret.top()) return adt.adjusted(Carets.moveTopTo(caret, guessBox.bottom - 1));
      else return adt.none();
    };

    var upMovement = {
      point: Carets.getTop,
      adjuster: adjustUp,
      move: Carets.moveUp
    };

    var downMovement = {
      point: Carets.getBottom,
      adjuster: adjustDown,
      move: Carets.moveDown
    };

    var adjustTil = function (win, direction, original, caret) {
      return Point.find(win, caret.left(), direction.point(caret)).bind(function (guess) {
        return guess.start().fold(Option.none, function (element, offset) {
          return Rectangles.getBox(win, element, offset).bind(function (guessBox) {
            return direction.adjuster(guessBox, original, caret).fold(Option.none, function (newCaret) {
              console.log('still adjusting', newCaret.top());
              return adjustTil(win, direction, original, newCaret);
            }, function (newCaret) {
              console.log('finished at', newCaret, ' which is ', element.dom(), offset);
              return Option.some(newCaret);
            });
          });
        }, Option.none);
      });
    };

    var ieTryDown = function (win, caret) {
      return Point.find(win, caret.left, caret.bottom + JUMP_SIZE);
    };

    var ieTryUp = function (win, caret) {
      return Point.find(win, caret.left, caret.top - JUMP_SIZE);
    };

    var retry = function (direction, win, caret) {
      var c = Carets.nu(caret.left, caret.top, caret.right, caret.bottom);
      var moved = direction.move(c, JUMP_SIZE);
      var adjusted = adjustTil(win, direction, c, moved).getOr(moved);
      return Point.find(win, adjusted.left(), direction.point(adjusted));
    };

    return {
      tryUp: Fun.curry(retry, upMovement),
      tryDown: Fun.curry(retry, downMovement),
      ieTryUp: ieTryUp,
      ieTryDown: ieTryDown
    };
  }
);<|endoftext|>


<commit_before>/* Copyright 2013-2014 Extended Mind Technologies Oy
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 'use strict';

 function NoteEditorController($scope, NotesService, TagsService, UISessionService) {

  $scope.isNoteEdited = function() {
    if ($scope.noteTitlebarHasText()) {
      return NotesService.isNoteEdited($scope.note, UISessionService.getActiveUUID());
    }
  };

  // INITIALIZING

  if (angular.isFunction($scope.registerFeatureEditorAboutToCloseCallback))
    $scope.registerFeatureEditorAboutToCloseCallback(noteEditorAboutToClose, 'NoteEditorController');

  // SAVING, DELETING

  function saveNoteInEdit() {
    if ($scope.onboardingInProgress) $scope.turnOffListOnboardingLock('notes');

    // TODO: Keywords
    $scope.deferEdit().then(function() {
      $scope.saveNote($scope.note);
    });
  }

  $scope.deleteNoteInEdit = function() {
    // Unregister about to close callback, because delete is run after editor is closed
    // and about to close callback would try to save item in between close and delete.
    if (angular.isFunction($scope.unregisterEditorAboutToCloseCallback))
      $scope.unregisterEditorAboutToCloseCallback();

    $scope.closeNoteEditor();
    $scope.deferEdit().then(function() {
      UISessionService.allow('leaveAnimation', 200);
      $scope.deleteNote($scope.note);
    });
  };

  $scope.endNoteEdit = function() {
    $scope.closeNoteEditor();
  };

  function noteEditorAboutToClose() {
    if ($scope.isNoteEdited()) saveNoteInEdit();
    else NotesService.resetNote($scope.note, UISessionService.getActiveUUID());
  }

  $scope.clickFavorite = function() {
    if (!$scope.note.trans.favorited){
      $scope.favoriteNote($scope.note);
    }else{
      $scope.unfavoriteNote($scope.note);
    }
  };

  // MODES

  $scope.noteTitleFocused = function(){
    if ($scope.isFirstSlide()){
      $scope.mode = 'fullScreen';
    }
  };

  $scope.noteContentFocused = function(){
    if ($scope.isFirstSlide()){
      $scope.mode = 'fullScreen';
      $scope.hideNoteTitle = true;
    }
  };

  $scope.toggleNoteEditMode = function(){
    if ($scope.mode === 'fullScreen'){
      $scope.mode = undefined;
    }else if ($scope.mode === 'view'){
      $scope.mode = undefined;
    }else {
      $scope.mode = 'view';
    }
    $scope.hideNoteTitle = false;
  };

  $scope.isNoteFooterHidden = function() {
    return $scope.mode === 'fullScreen' || $scope.isTitleClamped();
  };

  // CONTENT

  var noteContentFocusCallback;
  $scope.registerNoteContentInputCallbacks = function(focus){
    noteContentFocusCallback = focus;
  };

  // TITLEBAR

  $scope.noteTitlebarHasText = function() {
    return $scope.note.trans.title && $scope.note.trans.title.length !== 0;
  };

  $scope.noteTitlebarTextKeyDown = function (keydownEvent) {
    $scope.handleBasicTitlebarKeydown(keydownEvent, $scope.note);
    // Return
    if (event.keyCode === 13 && $scope.noteTitlebarHasText()) {
      // TODO: Move focus to content field on enter!
      noteContentFocusCallback();
      event.preventDefault();
      event.stopPropagation();
    }
  };

  // KEYWORDS

  function clearKeyword() {
    $scope.newKeyword = TagsService.getNewTag({tagType: 'keyword'}, UISessionService.getActiveUUID());
  }
  clearKeyword(); // Initialize new keyword.

  $scope.addNewKeywordToNote = function(note, newKeyword) {
    if (!newKeyword || !newKeyword.title) return; // No text entered.
    if (note.trans && note.trans.keywords) {
      var noteKeyword = note.trans.keywords.findFirstObjectByKeyValue('title', newKeyword.title);

      if (noteKeyword !== undefined) {
        // Note's existing keyword. Do not re-add.
        clearKeyword();
        return;
      }
    }

    var keywordToAdd = $scope.keywords.findFirstObjectByKeyValue('title', newKeyword.title) || newKeyword;
    // Add already existing keyword or newly created keyword.
    $scope.addKeywordToNote(note, keywordToAdd);
  };

  $scope.addKeywordToNote = function(note, keyword) {
    if (!$scope.note.trans) $scope.note.trans = {};
    if (!$scope.note.trans.keywords) $scope.note.trans.keywords = [];
    $scope.note.trans.keywords.push(keyword);
    clearKeyword();
  };

  $scope.removeKeywordFromNote = function(note, keyword) {
    note.trans.keywords.splice(note.trans.keywords.indexOf(keyword), 1);
  };

}

NoteEditorController['$inject'] = ['$scope', 'NotesService', 'TagsService', 'UISessionService'];
angular.module('em.main').controller('NoteEditorController', NoteEditorController);
<commit_msg>Better ordering of functions.<commit_after>/* Copyright 2013-2014 Extended Mind Technologies Oy
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 'use strict';

 function NoteEditorController($scope, NotesService, TagsService, UISessionService) {

  // INITIALIZING

  if (angular.isFunction($scope.registerFeatureEditorAboutToCloseCallback))
    $scope.registerFeatureEditorAboutToCloseCallback(noteEditorAboutToClose, 'NoteEditorController');

  // SAVING, DELETING

  function saveNoteInEdit() {
    if ($scope.onboardingInProgress) $scope.turnOffListOnboardingLock('notes');

    // TODO: Keywords
    $scope.deferEdit().then(function() {
      $scope.saveNote($scope.note);
    });
  }

  $scope.deleteNoteInEdit = function() {
    // Unregister about to close callback, because delete is run after editor is closed
    // and about to close callback would try to save item in between close and delete.
    if (angular.isFunction($scope.unregisterEditorAboutToCloseCallback))
      $scope.unregisterEditorAboutToCloseCallback();

    $scope.closeNoteEditor();
    $scope.deferEdit().then(function() {
      UISessionService.allow('leaveAnimation', 200);
      $scope.deleteNote($scope.note);
    });
  };

  $scope.isNoteEdited = function() {
    // Note without title is unedited
    if ($scope.noteTitlebarHasText()) {
      return NotesService.isNoteEdited($scope.note, UISessionService.getActiveUUID());
    }
  };

  $scope.endNoteEdit = function() {
    $scope.closeNoteEditor();
  };

  function noteEditorAboutToClose() {
    if ($scope.isNoteEdited()) saveNoteInEdit();
    else NotesService.resetNote($scope.note, UISessionService.getActiveUUID());
  }

  $scope.clickFavorite = function() {
    if (!$scope.note.trans.favorited){
      $scope.favoriteNote($scope.note);
    }else{
      $scope.unfavoriteNote($scope.note);
    }
  };

  // MODES

  $scope.noteTitleFocused = function(){
    if ($scope.isFirstSlide()){
      $scope.mode = 'fullScreen';
    }
  };

  $scope.noteContentFocused = function(){
    if ($scope.isFirstSlide()){
      $scope.mode = 'fullScreen';
      $scope.hideNoteTitle = true;
    }
  };

  $scope.toggleNoteEditMode = function(){
    if ($scope.mode === 'fullScreen'){
      $scope.mode = undefined;
    }else if ($scope.mode === 'view'){
      $scope.mode = undefined;
    }else {
      $scope.mode = 'view';
    }
    $scope.hideNoteTitle = false;
  };

  $scope.isNoteFooterHidden = function() {
    return $scope.mode === 'fullScreen' || $scope.isTitleClamped();
  };

  // CONTENT

  var noteContentFocusCallback;
  $scope.registerNoteContentInputCallbacks = function(focus){
    noteContentFocusCallback = focus;
  };

  // TITLEBAR

  $scope.noteTitlebarHasText = function() {
    return $scope.note.trans.title && $scope.note.trans.title.length !== 0;
  };

  $scope.noteTitlebarTextKeyDown = function (keydownEvent) {
    $scope.handleBasicTitlebarKeydown(keydownEvent, $scope.note);
    // Return
    if (event.keyCode === 13 && $scope.noteTitlebarHasText()) {
      // TODO: Move focus to content field on enter!
      noteContentFocusCallback();
      event.preventDefault();
      event.stopPropagation();
    }
  };

  // KEYWORDS

  function clearKeyword() {
    $scope.newKeyword = TagsService.getNewTag({tagType: 'keyword'}, UISessionService.getActiveUUID());
  }
  clearKeyword(); // Initialize new keyword.

  $scope.addNewKeywordToNote = function(note, newKeyword) {
    if (!newKeyword || !newKeyword.title) return; // No text entered.
    if (note.trans && note.trans.keywords) {
      var noteKeyword = note.trans.keywords.findFirstObjectByKeyValue('title', newKeyword.title);

      if (noteKeyword !== undefined) {
        // Note's existing keyword. Do not re-add.
        clearKeyword();
        return;
      }
    }

    var keywordToAdd = $scope.keywords.findFirstObjectByKeyValue('title', newKeyword.title) || newKeyword;
    // Add already existing keyword or newly created keyword.
    $scope.addKeywordToNote(note, keywordToAdd);
  };

  $scope.addKeywordToNote = function(note, keyword) {
    if (!$scope.note.trans) $scope.note.trans = {};
    if (!$scope.note.trans.keywords) $scope.note.trans.keywords = [];
    $scope.note.trans.keywords.push(keyword);
    clearKeyword();
  };

  $scope.removeKeywordFromNote = function(note, keyword) {
    note.trans.keywords.splice(note.trans.keywords.indexOf(keyword), 1);
  };

}

NoteEditorController['$inject'] = ['$scope', 'NotesService', 'TagsService', 'UISessionService'];
angular.module('em.main').controller('NoteEditorController', NoteEditorController);
<|endoftext|>


<commit_before>const authors = [];
var warned = [];
var banned = [];
var messagelog = [];

/**
 * Add simple spam protection to your discord server.
 * @param  {Bot} bot - The discord.js CLient/bot
 * @param  {object} options - Optional (Custom configuarion options)
 * @return {[type]}         [description]
 */
module.exports = function (bot, options) {
  // Set options
  const warnBuffer = (options && options.prefix) || 7;
  const maxBuffer = (options && options.prefix) || 20;
  const interval = (options && options.interval) || 1000;
  const warningMessage = (options && options.warningMessage) || "stop spamming or I'll whack your head off.";
  const banMessage = (options && options.banMessage) || "has been banned for spamming, anyone else?";
  const maxDuplicatesWarning = (options && options.duplicates || 7);
  const maxDuplicatesBan = (options && options.duplicates || 20);

  bot.on('message', msg => {

    if(msg.author.id != bot.user.id){
      var now = Math.floor(Date.now());
      authors.push({
        "time": now,
        "author": msg.author.id
      });
      messagelog.push({
        "message": msg.content,
        "author": msg.author.id
      });

      // Check how many times the same message has been sent.
      var msgMatch = 0;
      for (var i = 0; i < messagelog.length; i++) {
        if (messagelog[i].message == msg.content && (messagelog[i].author == msg.author.id) && (msg.author.id !== bot.user.id)) {
          msgMatch++;
        }
      }
      // Check matched count
      if (msgMatch == maxDuplicatesWarning && !warned.includes(msg.author.id)) {
        warn(msg, msg.author.id);
      }
      if (msgMatch == maxDuplicatesBan && !banned.includes(msg.author.id)) {
        ban(msg, msg.author.id);
      }

      matched = 0;

      for (var i = 0; i < authors.length; i++) {
        if (authors[i].time > now - interval) {
          matched++;
          if (matched == warnBuffer && !warned.includes(msg.author.id)) {
            warn(msg, msg.author.id);
          }
          else if (matched == maxBuffer) {
            if (!banned.includes(msg.author.id)) {
              ban(msg, msg.author.id);
            }
          }
        }
        else if (authors[i].time < now - interval) {
          authors.splice(i);
          warned.splice(warned.indexOf(authors[i]));
          banned.splice(warned.indexOf(authors[i]));
        }
        if (messagelog.length >= 200) {
          messagelog.shift();
        }
      }
    }
  });

  /**
   * Warn a user
   * @param  {Object} msg
   * @param  {string} userid userid
   */
  function warn(msg, userid) {
    warned.push(msg.author.id);
    msg.channel.send("Stop spamming, " + msg.author + " continuing to spam will subsequently lead into a mute.");
  }

  /**
   * Ban a user by the user id
   * @param  {Object} msg
   * @param  {string} userid userid
   * @return {boolean} True or False
   */

  }

<commit_msg>Update anti_spam.js<commit_after>const authors = [];
var warned = [];
var banned = [];
var messagelog = [];

/**
 * Add simple spam protection to your discord server.
 * @param  {Bot} bot - The discord.js CLient/bot
 * @param  {object} options - Optional (Custom configuarion options)
 * @return {[type]}         [description]
 */
const Discord = require('discord.js');
module.exports = function (bot, options) {
  // Set options
  const warnBuffer = (options && options.prefix) || 7;
  const maxBuffer = (options && options.prefix) || 20;
  const interval = (options && options.interval) || 1000;
  const warningMessage = (options && options.warningMessage) || "stop spamming or I'll whack your head off.";
  const banMessage = (options && options.banMessage) || "has been banned for spamming, anyone else?";
  const maxDuplicatesWarning = (options && options.duplicates || 7);
  const maxDuplicatesBan = (options && options.duplicates || 20);
    const muteRole = client.guilds.get(message.guild.id).roles.find('name', `SendMessage`);
    const modlog = client.channels.find('name', 'mod-log');

  const embed = new Discord.RichEmbed()
  .setTimestamp()
  .setColor(0x00ff00)
  .setTitle("User Auto Muted")
  .setThumbnail(`${user.avatarURL}`)
  .setDescription(`\n`)
  .addField("Username:",`${msg.author} (${msg.author.username})`,true)
  .addField("Moderator:",`Pie Bot`, true)
  .addField("Reason:",`[Auto-Mute] Auto muted by system for spamming.`, false)
  .setFooter(`User: ${user.username}`,`${user.avatarURL}`);

  bot.on('message', msg => {

    if(msg.author.id != bot.user.id){
      var now = Math.floor(Date.now());
      authors.push({
        "time": now,
        "author": msg.author.id
      });
      messagelog.push({
        "message": msg.content,
        "author": msg.author.id
      });

      // Check how many times the same message has been sent.
      var msgMatch = 0;
      for (var i = 0; i < messagelog.length; i++) {
        if (messagelog[i].message == msg.content && (messagelog[i].author == msg.author.id) && (msg.author.id !== bot.user.id)) {
          msgMatch++;
        }
      }
      // Check matched count
      if (msgMatch == maxDuplicatesWarning && !warned.includes(msg.author.id)) {
        warn(msg, msg.author.id);
      }
      if (msgMatch == maxDuplicatesBan && !banned.includes(msg.author.id)) {
        message.guild.member(msg.author).removeRole(muteRole)
    client.channels.get(modlog.id).send({embed}).catch(console.error);
     message.channel.send({embed}).catch(console.error);
      }

      matched = 0;

      for (var i = 0; i < authors.length; i++) {
        if (authors[i].time > now - interval) {
          matched++;
          if (matched == warnBuffer && !warned.includes(msg.author.id)) {
            warn(msg, msg.author.id);
          }
          else if (matched == maxBuffer) {
            if (!banned.includes(msg.author.id)) {
              ban(msg, msg.author.id);
            }
          }
        }
        else if (authors[i].time < now - interval) {
          authors.splice(i);
          warned.splice(warned.indexOf(authors[i]));
          banned.splice(warned.indexOf(authors[i]));
        }
        if (messagelog.length >= 200) {
          messagelog.shift();
        }
      }
    }
  });

  /**
   * Warn a user
   * @param  {Object} msg
   * @param  {string} userid userid
   */
  function warn(msg, userid) {
    warned.push(msg.author.id);
    msg.channel.send("Stop spamming, " + msg.author + " continuing to spam will subsequently lead into a mute.");
  }

  /**
   * Ban a user by the user id
   * @param  {Object} msg
   * @param  {string} userid userid
   * @return {boolean} True or False
   */

  }

<|endoftext|>


<commit_before>Components.utils.import("resource://crownconstruction/modules/toolkit.js");
Components.utils.import("resource://crownconstruction/modules/db.js");

let Customer = null;
let People = [];
let Addresses = [];
let Phones = [];
let Emails = [];

const WARNING_PERSON_LASTNAME = "We can't save a person to a customer "+
  "file without a last name. If you don't intend to save this person, "+
  "then just erase the first name and try saving again.";

const WARN_NO_PEOPLE = "We can't save a customer file without any "+
  "people attached to it.  We'll need at least one last name to save.";

const WARNING_TRANSACTION_FAILED = "Well, this is embarassing, but there "+
  "has been an error while processing your save request. First, copy "+
  "all of your changes down to paper (or you can print this page), "+
  "because we will not be able to save them as they are. Then, go back "+
  "to the main menu, and press the refresh button before trying to "+
  "resubmit your changes.";

const OK_TRANSACTION = "Saved.";

function onWindowLoad(e)
{
  let uri = page.uriFromURL(window.location.href).uri;

  Customer = db.getKey(uri);
  customer = db.get(Customer);
  addPeople(customer.Person);
  if(customer.Address)
    addAddresses(customer.Address);
  if(customer.Phone)
    addPhones(customer.Phone);
  if(customer.Email)
    addEmails(customer.Email);

  return true;
}

function onCancel()
{
  // todo: fix this so it returns user to the menu
  window.close();
}

function onClose()
{
  // todo: fix this so it returns user to the menu
  window.close();
}

function onSave()
{
  let people = collectPeople();
  //tk.dump("people", tk.dumpObject(people));
  if(!people || !people.length)
    return true;

  function apply(ent) {
    let k = ent.key;
    for(let p in ent) {
      if(p != "key")
        db.setattr(k, p, ent[p]);
    }
    return k;
  }

  db.setattr(Customer, "Person", [apply(i) for each(i in people)]);

  let addresses = collectAddresses();
  //tk.dump("addresses", tk.dumpObject(addresses));
  db.setattr(Customer, "Address", [apply(i) for each(i in addresses)]);

  let phones = collectPhones();
  //tk.dump("phones", tk.dumpObject(phones));
  db.setattr(Customer, "Phone", [apply(i) for each(i in phones)]);

  let emails = collectEmails();
  //tk.dump("email", tk.dumpObject(emails));
  db.setattr(Customer, "Email", [apply(i) for each(i in emails)]);

  //tk.dump("catch", tk.dumpObject(db.cache));
  db.commit("testPilot", "save customer", function(r)
    {
      if(!r) {
        warnUser(WARNING_TRANSACTION_FAILED, function() {
            // todo: this should bring the user back to the menu
            window.close();
          });
        return true;
      }
      warnUser(OK_TRANSACTION, function() {
          // todo: this should bring the user back to the menu
          window.close();
        });
      //tk.dump("transaction", tk.dumpObject(r));
    });
  return true;
}

function onAddPerson()
{
  addPerson(null);
}

function onAddAddress()
{
  addAddress(null);
}

function onAddPhone()
{
  addPhone(null);
}

function onAddEmail()
{
  addEmail(null);
}

function addPeople(people)
{
  people = people || [null];
  people.forEach(addPerson);
}

function addAddresses(addresses)
{
  addresses = addresses || [null];
  addresses.forEach(addAddress);
}

function addPhones(phones)
{
  phones = phones || [null];
  phones.forEach(addPhones);
}

function addEmails(emails)
{
  emails = emails || [null];
  emails.forEach(addEmails);
}

function addPerson(person)
{
  person = person ? db.get(person) : db.get(db.createNew("Person"));
  let lastname = person.lastname || "";
  let firstname = person.firstname || "";

  let fn = INPUT({type: "text", value:firstname});
  let ln = INPUT({type: "text", value:lastname});
  $("people").appendChild(DIV(P([
        SPAN("Firstname: "),
        fn,
        SPAN("Lastname: "),
        ln
      ])));
  People.push({key: person.key(), firstname: fn, lastname: ln});
}

function addAddress(address)
{
  address = address ? db.get(address) : db.get(db.createNew("Address"));
  let label = address.label || "";
  let street = address.street || "";
  let addStreet = address.additional || "";
  let city = address.city || "";
  let state = address.state || "";
  let zip = address.zip || "";

  let l = INPUT({type: "text", value:label});
  let str = INPUT({type: "text", value:street});
  let ast = INPUT({type: "text", value:addStreet});
  let cty = INPUT({type: "text", value:city});
  let st = INPUT({type: "text", value:state});
  let z =  INPUT({type: "text", value:zip});

  $("addresses").appendChild(DIV(
    [
      P([SPAN("Description:"), l]),
      P([SPAN("Street:"), str]),
      P(ast),
      P([SPAN("City:"), cty, SPAN("State:"), st, SPAN("Zip:"), z]),
    ]));

  Addresses.push({
      key: address.key(),
      label: l,
      street: str,
      addStreet: ast,
      city: cty,
      state: st,
      zip: z
    });
}

function addPhone(phone)
{
  phone = phone ? db.get(phone) : db.get(db.createNew("Phone"));
  let label = phone.label || "";
  let num = phone.phonenumber || "";

  let l = INPUT({type: "text", value:label});
  let n = INPUT({type: "text", value:num});

  $("phones").appendChild(DIV(P([
      SPAN("Label: "),
      l,
      SPAN("Number: "),
      n
    ])));
  Phones.push({key: phone.key(), label: l, phonenumber: n});
}

function addEmail(email)
{
  email = email ? db.get(email) : db.get(db.createNew("Email"));
  let label = email.label || "";
  let link = email.link || "";

  let l = INPUT({type: "text", value:label});
  let lnk = INPUT({type: "text", value:link});

  $("emails").appendChild(DIV(P([
      SPAN("Label: "),
      l,
      SPAN("Email: "),
      lnk
    ])));
  Emails.push({key: email.key(), label: l, link: lnk});
}

function collectPeople()
{
  var warned = false;
  function validate(p) {
    if(p.lastname.value)
      return true;

    else if(!p.firstname.value)
      return false;

    warnUser(WARNING_PERSON_LASTNAME, function() {
        highlightError(p.lastname);
      });
    warned = true;
    return false;
  }

  function extract(person) {
    return {key: person.key,
      firstname: person.firstname.value,
      lastname: person.lastname.value};
  }

  let rv = [extract(p) for each(p in People) if(validate(p))];
  if(!rv || !rv.length) {
    warnUser(WARN_NO_PEOPLE, function() {
        highlightError(People[0].lastname);
      });
  }
  return rv;
}

function collectAddresses()
{
  function validate(a) {
    if(a.street.value || a.addStreet.value
        || a.city.value || a.state.value || a.zip.value)
    {
      return true;
    }
    return false;
  }

  function extract(address) {
    return {key: address.key,
      label: address.label.value,
      street: address.street.value,
      additional: address.addStreet.value,
      city: address.city.value,
      state: address.state.value,
      zip: address.zip.value
    };
  }

  return [extract(a) for each(a in Addresses) if(validate(a))];
}

function collectPhones()
{
  function validate(phone) {
    if(!phone.label.value && !phone.phonenumber.value)
      return false;
    return true;
  }

  function extract(phone) {
    return {key: phone.key,
      label: phone.label.value,
      phonenumber: phone.phonenumber.value};
  }

  return [extract(p) for each(p in Phones) if(validate(p))];
}

function collectEmails()
{
  function validate(email) {
    if(!email.label.value && !email.link.value)
      return false;
    return true;
  }

  function extract(email) {
    return {key: email.key,
      label: email.label.value,
      link: email.link.value};
  }

  return [extract(e) for each(e in Emails) if(validate(e))];
}

function warnUser(msg, callback)
{
  $("inner-message").innerHTML = msg;

  var box = $("warning");
  box.setAttribute("style", "display:block;");

  $("close-warning").onclick = function onCloseWarning(e) {
    box.setAttribute("style", "display:none;");
    if(callback)
      callback();
  };
}

function highlightError(e)
{
  e.select();
  e.focus();
}

window.addEventListener("load", onWindowLoad, false);
<commit_msg>bug: customer.js (page level)<commit_after>Components.utils.import("resource://crownconstruction/modules/toolkit.js");
Components.utils.import("resource://crownconstruction/modules/db.js");

let Customer = null;
let People = [];
let Addresses = [];
let Phones = [];
let Emails = [];

const WARNING_PERSON_LASTNAME = "We can't save a person to a customer "+
  "file without a last name. If you don't intend to save this person, "+
  "then just erase the first name and try saving again.";

const WARN_NO_PEOPLE = "We can't save a customer file without any "+
  "people attached to it.  We'll need at least one last name to save.";

const WARNING_TRANSACTION_FAILED = "Well, this is embarassing, but there "+
  "has been an error while processing your save request. First, copy "+
  "all of your changes down to paper (or you can print this page), "+
  "because we will not be able to save them as they are. Then, go back "+
  "to the main menu, and press the refresh button before trying to "+
  "resubmit your changes.";

const OK_TRANSACTION = "Saved.";

function onWindowLoad(e)
{
  let uri = page.uriFromURL(window.location.href).uri;

  Customer = db.getKey(uri);
  let customer = db.get(Customer);
  addPeople(customer.Person);
  if(customer.Address)
    addAddresses(customer.Address);
  if(customer.Phone)
    addPhones(customer.Phone);
  if(customer.Email)
    addEmails(customer.Email);

  return true;
}

function onCancel()
{
  // todo: fix this so it returns user to the menu
  window.close();
}

function onClose()
{
  // todo: fix this so it returns user to the menu
  window.close();
}

function onSave()
{
  let people = collectPeople();
  //tk.dump("people", tk.dumpObject(people));
  if(!people || !people.length)
    return true;

  function apply(ent) {
    let k = ent.key;
    for(let p in ent) {
      if(p != "key")
        db.setattr(k, p, ent[p]);
    }
    return k;
  }

  db.setattr(Customer, "Person", [apply(i) for each(i in people)]);

  let addresses = collectAddresses();
  //tk.dump("addresses", tk.dumpObject(addresses));
  db.setattr(Customer, "Address", [apply(i) for each(i in addresses)]);

  let phones = collectPhones();
  //tk.dump("phones", tk.dumpObject(phones));
  db.setattr(Customer, "Phone", [apply(i) for each(i in phones)]);

  let emails = collectEmails();
  //tk.dump("email", tk.dumpObject(emails));
  db.setattr(Customer, "Email", [apply(i) for each(i in emails)]);

  //tk.dump("catch", tk.dumpObject(db.cache));
  db.commit("testPilot", "save customer", function(r)
    {
      if(!r) {
        warnUser(WARNING_TRANSACTION_FAILED, function() {
            // todo: this should bring the user back to the menu
            window.close();
          });
        return true;
      }
      warnUser(OK_TRANSACTION, function() {
          // todo: this should bring the user back to the menu
          window.close();
        });
      //tk.dump("transaction", tk.dumpObject(r));
    });
  return true;
}

function onAddPerson()
{
  addPerson(null);
}

function onAddAddress()
{
  addAddress(null);
}

function onAddPhone()
{
  addPhone(null);
}

function onAddEmail()
{
  addEmail(null);
}

function addPeople(people)
{
  people = people || [null];
  people.forEach(addPerson);
}

function addAddresses(addresses)
{
  addresses = addresses || [null];
  addresses.forEach(addAddress);
}

function addPhones(phones)
{
  phones = phones || [null];
  phones.forEach(addPhones);
}

function addEmails(emails)
{
  emails = emails || [null];
  emails.forEach(addEmails);
}

function addPerson(person)
{
  person = person ? db.get(person) : db.get(db.createNew("Person"));
  let lastname = person.lastname || "";
  let firstname = person.firstname || "";

  let fn = INPUT({type: "text", value:firstname});
  let ln = INPUT({type: "text", value:lastname});
  $("people").appendChild(DIV(P([
        SPAN("Firstname: "),
        fn,
        SPAN("Lastname: "),
        ln
      ])));
  People.push({key: person.key(), firstname: fn, lastname: ln});
}

function addAddress(address)
{
  address = address ? db.get(address) : db.get(db.createNew("Address"));
  let label = address.label || "";
  let street = address.street || "";
  let addStreet = address.additional || "";
  let city = address.city || "";
  let state = address.state || "";
  let zip = address.zip || "";

  let l = INPUT({type: "text", value:label});
  let str = INPUT({type: "text", value:street});
  let ast = INPUT({type: "text", value:addStreet});
  let cty = INPUT({type: "text", value:city});
  let st = INPUT({type: "text", value:state});
  let z =  INPUT({type: "text", value:zip});

  $("addresses").appendChild(DIV(
    [
      P([SPAN("Description:"), l]),
      P([SPAN("Street:"), str]),
      P(ast),
      P([SPAN("City:"), cty, SPAN("State:"), st, SPAN("Zip:"), z]),
    ]));

  Addresses.push({
      key: address.key(),
      label: l,
      street: str,
      addStreet: ast,
      city: cty,
      state: st,
      zip: z
    });
}

function addPhone(phone)
{
  phone = phone ? db.get(phone) : db.get(db.createNew("Phone"));
  let label = phone.label || "";
  let num = phone.phonenumber || "";

  let l = INPUT({type: "text", value:label});
  let n = INPUT({type: "text", value:num});

  $("phones").appendChild(DIV(P([
      SPAN("Label: "),
      l,
      SPAN("Number: "),
      n
    ])));
  Phones.push({key: phone.key(), label: l, phonenumber: n});
}

function addEmail(email)
{
  email = email ? db.get(email) : db.get(db.createNew("Email"));
  let label = email.label || "";
  let link = email.link || "";

  let l = INPUT({type: "text", value:label});
  let lnk = INPUT({type: "text", value:link});

  $("emails").appendChild(DIV(P([
      SPAN("Label: "),
      l,
      SPAN("Email: "),
      lnk
    ])));
  Emails.push({key: email.key(), label: l, link: lnk});
}

function collectPeople()
{
  var warned = false;
  function validate(p) {
    if(p.lastname.value)
      return true;

    else if(!p.firstname.value)
      return false;

    warnUser(WARNING_PERSON_LASTNAME, function() {
        highlightError(p.lastname);
      });
    warned = true;
    return false;
  }

  function extract(person) {
    return {key: person.key,
      firstname: person.firstname.value,
      lastname: person.lastname.value};
  }

  let rv = [extract(p) for each(p in People) if(validate(p))];
  if(!rv || !rv.length) {
    warnUser(WARN_NO_PEOPLE, function() {
        highlightError(People[0].lastname);
      });
  }
  return rv;
}

function collectAddresses()
{
  function validate(a) {
    if(a.street.value || a.addStreet.value
        || a.city.value || a.state.value || a.zip.value)
    {
      return true;
    }
    return false;
  }

  function extract(address) {
    return {key: address.key,
      label: address.label.value,
      street: address.street.value,
      additional: address.addStreet.value,
      city: address.city.value,
      state: address.state.value,
      zip: address.zip.value
    };
  }

  return [extract(a) for each(a in Addresses) if(validate(a))];
}

function collectPhones()
{
  function validate(phone) {
    if(!phone.label.value && !phone.phonenumber.value)
      return false;
    return true;
  }

  function extract(phone) {
    return {key: phone.key,
      label: phone.label.value,
      phonenumber: phone.phonenumber.value};
  }

  return [extract(p) for each(p in Phones) if(validate(p))];
}

function collectEmails()
{
  function validate(email) {
    if(!email.label.value && !email.link.value)
      return false;
    return true;
  }

  function extract(email) {
    return {key: email.key,
      label: email.label.value,
      link: email.link.value};
  }

  return [extract(e) for each(e in Emails) if(validate(e))];
}

function warnUser(msg, callback)
{
  $("inner-message").innerHTML = msg;

  var box = $("warning");
  box.setAttribute("style", "display:block;");

  $("close-warning").onclick = function onCloseWarning(e) {
    box.setAttribute("style", "display:none;");
    if(callback)
      callback();
  };
}

function highlightError(e)
{
  e.select();
  e.focus();
}

window.addEventListener("load", onWindowLoad, false);
<|endoftext|>