<commit_before>/*    Copyright 2016 Firewalla LLC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
'use strict';

let instance = null;

const log = require('./logger.js')(__filename);

const request = require('request');
const SysManager = require('./SysManager.js');
const sysManager = new SysManager('info');

const rclient = require('../util/redis_manager.js').getRedisClient()

const bone = require("../lib/Bone.js");
const IntelTool = require('./IntelTool');
const intelTool = new IntelTool();

const A_WEEK = 3600 * 24 * 7;

/* malware, botnet, spam, phishing, malicious activity, blacklist, dnsbl */
const IGNORED_TAGS = ['dnsbl', 'spam'];

module.exports = class {
    constructor(loglevel) {
        if (instance == null) {
            instance = this;
        }
        return instance;
    }

    action(action, ip, callback) {
        if (action === "ignore") {
            rclient.hmset("intel:action:"+ip, {'ignore':true}, (err)=> {
                callback(err,null);
            });
        } else if (action === "unignore") {
            rclient.hmset("intel:action:"+ip, {'ignore':false}, (err)=> {
                callback(err,null);
            });
        } else if (action === "block") {
        } else if (action === "unblock") {
        } else if (action === "support") {
        }

      bone.intel(ip, "", action, {});
    }

    async cacheLookupAsync(dest, origin) {
        return await rclient.getAsync("cache.intel:" + origin + ":" + dest);
    }

    cachelookup(ip, origin, callback) {
        rclient.get("cache.intel:" + origin + ":" + ip, (err, result) => {
            callback(err, result);
        });
    }

    cacheAdd(ip, origin, value) {
        if (value == null) {
            value = "none";
        }
        rclient.set("cache.intel:" + origin + ":" + ip, value, (err, result) => {
          rclient.expireat("cache.intel:" + origin + ":" + ip, this.currentTime() + A_WEEK);
        });
    }

    currentTime() {
      return Math.round(Date.now() / 1000);
    }

    async lookupDomain(domain, ip, flowObj) {
      if (!domain || domain === "firewalla.com") {
        return;
      }

      if (await this.isIgnored(domain)) {
        log.info("Ignored domain:", domain, "skip...");
        return;
      }

      log.info("FlowObj:", flowObj);

      let intel = flowObj.intel;

      if (!intel.category) {
        log.info("No intel for domain", domain, "look up from cloud...");
        intel = await this._lookupDomain(domain, ip);
      } else {
        log.info("Intel for domain", domain, " exists in flowObj");
        if (intel.cc) {
          try {
            intel.cc = JSON.parse(intel.cc)[0];
          } catch (err) {
            log.warn("Error when parsing info.cc:", intel.cc, err);
          }
        }
      }
      log.info(`Intel for domain ${domain} is`, intel);

      return intel;
    }

    async isIgnored(target) {
      let data = await rclient.hgetallAsync("intel:action:" + target);
      log.info("Ignore check for domain:", target, " is", data);
      return data && data.ignore;
    }

    async _lookupDomain(domain, ip) {
      let cloudIntel;
      try {
        cloudIntel = await intelTool.checkIntelFromCloud([ip], [domain], 'out');
      } catch (err) {
        log.info("Error when check intel from cloud", err);
      }
      log.info("Cloud intel for ", domain, "is: ", cloudIntel);

      return this.processCloudIntel(cloudIntel[0]);
    }

  processCloudIntel(cloudIntel) {
    if (!cloudIntel) {
      return;
    }

    let intel = {};
    // check if the host matches the result from cloud
    // FIXME: ignore IP check because intel result from cloud does
    // NOT have "ip" all the time.
    if (cloudIntel.apps) {
      intel.apps = JSON.stringify(cloudIntel.apps);
      let keys = Object.keys(cloudIntel.apps);
      if (keys && keys[0]) {
        intel.app = keys[0];
      }
    }

    if (cloudIntel.c) {
      intel.category = cloudIntel.c;
    }

    if (cloudIntel.action && cloudIntel.action.block) {
      intel.action = "block"
    }

    if (cloudIntel.s) {
      intel.s = cloudIntel.s;
    }

    if (cloudIntel.t) {
      intel.t = cloudIntel.t;
    }

    if (cloudIntel.cc) {
      try {
        cloudIntel.cc = JSON.parse(cloudIntel.cc);
        intel.cc = cloudIntel.cc[0];
      } catch (err) {
        intel.cc = cloudIntel.cc;
        log.warn("Error when parsing info.cc:", cloudIntel.cc, err);
      }
    }
    return intel;
  }

  lookup(ip, intel, callback) {
        if (!ip || ip === "8.8.8.8" || sysManager.isLocalIP(ip)) {
            callback(null, null, null);
            return;
        }

        rclient.hgetall("intel:action:"+ip, (err,data) => {
            if (data && data.ignore) {
                log.info("Intel:Lookup:Ignored",ip);
                callback(null,null,null);
            }

            this.cachelookup(ip, "cymon", (err, result) => {
                if (result && result !== "none") {
                    this._location(ip, (err, lobj)=>{
                        let obj = JSON.parse(result);
                        if (!obj || obj.count === 0) {
                            obj = {}
                            obj.lobj = lobj;
                            obj = this._packageIntel(ip, obj, intel);
                            callback(null, obj);
                        } else {
                            obj.lobj = lobj;
                            log.info("Intel:Location",ip,obj.lobj);
                            this._packageCymon(ip, obj);
                            callback(err, obj);
                        }
                    });
                } else {
                    this._lookup(ip, intel, (err, obj)=>{
                        callback(err,obj);
                    });
                }
            });
        });
    }

    _packageIntel(ip, obj, intel) {
        let weburl = "https://intel.firewalla.com/";
        log.info("IntelManger:PackageIntel:",ip,JSON.stringify(intel,null,2));
        if (intel == null) {
            return null;
        }
        if (intel.t) {
            obj.count = Math.abs(intel.t/10);
        } else {
            obj.count = 4;
        }
        if (intel.s) {
            obj.severityscore = intel.s;
        } else {
            obj.severityscore = 20;
        }
        obj.summary = "";
        obj.weburl = weburl;
        if (intel.cc) {
            try {
                obj.tags = JSON.parse(intel.cc);
            } catch(e) {
            }
        }
        log.info("IntelManger:PackageIntel:Done",ip,JSON.stringify(intel,null,2),JSON.stringify(obj,null,2));
        return obj;
    }

    _packageCymon(ip, obj) {
        let weburl = "https://cymon.io/" + ip;
        log.info("INFO:------ Intel Information", obj.count);

        let results = obj.results.filter(x => !IGNORED_TAGS.includes(x.tag));
        obj.count = results.length;
        let summary = obj.count + " reported this IP.\n";

        let tags = {};
        for (let r of obj.results) {
            if (r.tag) {
                if (tags[r.tag] == null) {
                    tags[r.tag] = {
                        tag: r.tag,
                        count: 1
                    };
                } else {
                    tags[r.tag].count += 1;
                }
            }
        }

        let tagArray = [], tagCount = 0, severity = 0;
        for (let i in tags) {
            let tag = tags[i];
            tagArray.push(tag);
            if (i.includes("malicious")) {
              severity += tag.count * 3;
            } else if (i.includes("malware")) {
              severity += tag.count * 3;
            } else if (i == "blacklist") {
              severity += tag.count * 3;
            } else {
              severity += 1;
            }
            tagCount += tag.count;
        }

        tagArray.sort((a, b) => b.count - a.count);

        obj.severityscore = severity;
        obj.summary = summary;
        obj.weburl = weburl;
        obj.tags = tagArray;

        if (obj.tags && obj.tags.length > 0) {
          const reasonize = (tag) => `${tag.tag} - ${Math.round(tag.count / tagCount * 100)}%`;
          let reason = "Possibility: ";
            let first = true;
            for (let tag of obj.tags) {
                if (first) {
                    reason += reasonize(tag);
                    first = false;
                } else {
                    reason += ", " + reasonize(tag);
                }
            }
            obj.reason = reason;
        }
    }

    /* curl ipinfo.io/98.124.243.43/
{
  "ip": "98.124.243.43",
  "hostname": "No Hostname",
  "city": "Kirkland",
  "region": "Washington",
  "country": "US",
  "loc": "47.6727,-122.1873",
  "org": "AS21740 eNom, Incorporated",
  "postal": "98033"
 */
    _location(ip, callback) {
      log.info("Looking up location:",ip);
      this.cachelookup(ip, "ipinfo", (err,data)=>{
        if (data!=null) {
            callback(null, JSON.parse(data));
            return;
        }
        let weburl = "https://ipinfo.io/" + ip;

        var options = {
            uri: weburl,
            method: 'GET',
            family: 4
            // Authorization: 'Token dc30fcd03eddbd95b90bacaea5e5a44b1b60d2f5',
        };

        request(options, (err, resp, body) => {
            if (err) {
                log.warn(`Error while requesting ${weburl}`, err);
                callback(null, null);
                return;
            }
            if (!resp) {
                log.warn(`Error - null response from ${weburl}`);
                callback(null, null);
                return;
            }
            if (resp.statusCode < 200 || resp.statusCode > 299) {
                log.warn("Error in response code", resp.statusCode);
                callback(null, null);
                return;
            }
            if (body) {
              let obj;
              try {
                obj = JSON.parse(body);
              } catch (err) {
                log.error("Error when parse ip info:", body, err);
              }
              if (obj) {
                this.cacheAdd(ip, "ipinfo", body);
                callback(null, obj);
                return;
              }
            }
            callback(null, null);
        });
      });
    }

    _lookup(ip, intel, callback) {
        let url = "https://cymon.io/api/nexus/v1/ip/" + ip + "/events?limit=100";

        let options = {
            uri: url,
            method: 'GET',
            family: 4
        };

        this._location(ip, (err, lobj)=>{
            let obj = {lobj};
            log.info("Intel:Location",ip,lobj);
            obj = this._packageIntel(ip,obj,intel);
            request(options, (err, resp, body) => {
                if (err) {
                    log.info(`Error while requesting ${url}`, err);
                    callback(err, null, null);
                    return;
                }
                if (!resp) {
                    log.info("Error while response ", err);
                    callback(500, null, null);
                    return;
                }
                if (resp.statusCode < 200 || resp.statusCode > 299) {
                    log.error("**** Error while response HTTP ", resp.statusCode);
                    callback(resp.statusCode, null, null);
                    return;
                }
                if (body) {
                    this.cacheAdd(ip, "cymon", body);
                    let cobj = JSON.parse(body);
                    if (cobj) {
                        if (cobj.count === 0) {
                            log.info("INFO:====== No Intel Information!!", ip, obj);
                            callback(null,obj);
                        } else {
                            cobj.lobj = lobj;
                            this._packageCymon(ip, cobj);
                            callback(err, cobj, cobj.weburl);
                        }
                    } else {
                        callback(null,obj);
                    }
                } else {
                    callback(null,obj);
                }
            });
        });
    }
}
<commit_msg>remove attackpage from intel cc<commit_after>/*    Copyright 2016 Firewalla LLC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
'use strict';

let instance = null;

const log = require('./logger.js')(__filename);

const request = require('request');
const SysManager = require('./SysManager.js');
const sysManager = new SysManager('info');

const rclient = require('../util/redis_manager.js').getRedisClient()

const bone = require("../lib/Bone.js");
const IntelTool = require('./IntelTool');
const intelTool = new IntelTool();

const A_WEEK = 3600 * 24 * 7;

/* malware, botnet, spam, phishing, malicious activity, blacklist, dnsbl */
const IGNORED_TAGS = ['dnsbl', 'spam'];

module.exports = class {
    constructor(loglevel) {
        if (instance == null) {
            instance = this;
        }
        return instance;
    }

    action(action, ip, callback) {
        if (action === "ignore") {
            rclient.hmset("intel:action:"+ip, {'ignore':true}, (err)=> {
                callback(err,null);
            });
        } else if (action === "unignore") {
            rclient.hmset("intel:action:"+ip, {'ignore':false}, (err)=> {
                callback(err,null);
            });
        } else if (action === "block") {
        } else if (action === "unblock") {
        } else if (action === "support") {
        }

      bone.intel(ip, "", action, {});
    }

    async cacheLookupAsync(dest, origin) {
        return await rclient.getAsync("cache.intel:" + origin + ":" + dest);
    }

    cachelookup(ip, origin, callback) {
        rclient.get("cache.intel:" + origin + ":" + ip, (err, result) => {
            callback(err, result);
        });
    }

    cacheAdd(ip, origin, value) {
        if (value == null) {
            value = "none";
        }
        rclient.set("cache.intel:" + origin + ":" + ip, value, (err, result) => {
          rclient.expireat("cache.intel:" + origin + ":" + ip, this.currentTime() + A_WEEK);
        });
    }

    currentTime() {
      return Math.round(Date.now() / 1000);
    }

    async lookupDomain(domain, ip, flowObj) {
      if (!domain || domain === "firewalla.com") {
        return;
      }

      if (await this.isIgnored(domain)) {
        log.info("Ignored domain:", domain, "skip...");
        return;
      }

      log.info("FlowObj:", flowObj);

      let intel = flowObj.intel;

      if (!intel.category) {
        log.info("No intel for domain", domain, "look up from cloud...");
        intel = await this._lookupDomain(domain, ip);
      } else {
        log.info("Intel for domain", domain, " exists in flowObj");
        if (intel.cc) {
          try {
            let json = JSON.parse(intel.cc)
            if(Array.isArray(json)) {
              // HACK, excluding attackpage
              json = json.filter((x) => x !== "attackpage")
              intel.cc = json[0]
            }
          } catch (err) {
            log.warn("Error when parsing info.cc:", intel.cc, err);
          }
        }
      }
      log.info(`Intel for domain ${domain} is`, intel);

      return intel;
    }

    async isIgnored(target) {
      let data = await rclient.hgetallAsync("intel:action:" + target);
      log.info("Ignore check for domain:", target, " is", data);
      return data && data.ignore;
    }

    async _lookupDomain(domain, ip) {
      let cloudIntel;
      try {
        cloudIntel = await intelTool.checkIntelFromCloud([ip], [domain], 'out');
      } catch (err) {
        log.info("Error when check intel from cloud", err);
      }
      log.info("Cloud intel for ", domain, "is: ", cloudIntel);

      return this.processCloudIntel(cloudIntel[0]);
    }

  processCloudIntel(cloudIntel) {
    if (!cloudIntel) {
      return;
    }

    let intel = {};
    // check if the host matches the result from cloud
    // FIXME: ignore IP check because intel result from cloud does
    // NOT have "ip" all the time.
    if (cloudIntel.apps) {
      intel.apps = JSON.stringify(cloudIntel.apps);
      let keys = Object.keys(cloudIntel.apps);
      if (keys && keys[0]) {
        intel.app = keys[0];
      }
    }

    if (cloudIntel.c) {
      intel.category = cloudIntel.c;
    }

    if (cloudIntel.action && cloudIntel.action.block) {
      intel.action = "block"
    }

    if (cloudIntel.s) {
      intel.s = cloudIntel.s;
    }

    if (cloudIntel.t) {
      intel.t = cloudIntel.t;
    }

    if (cloudIntel.cc) {
      try {
        cloudIntel.cc = JSON.parse(cloudIntel.cc);
        intel.cc = cloudIntel.cc[0];
      } catch (err) {
        intel.cc = cloudIntel.cc;
        log.warn("Error when parsing info.cc:", cloudIntel.cc, err);
      }
    }
    return intel;
  }

  lookup(ip, intel, callback) {
        if (!ip || ip === "8.8.8.8" || sysManager.isLocalIP(ip)) {
            callback(null, null, null);
            return;
        }

        rclient.hgetall("intel:action:"+ip, (err,data) => {
            if (data && data.ignore) {
                log.info("Intel:Lookup:Ignored",ip);
                callback(null,null,null);
            }

            this.cachelookup(ip, "cymon", (err, result) => {
                if (result && result !== "none") {
                    this._location(ip, (err, lobj)=>{
                        let obj = JSON.parse(result);
                        if (!obj || obj.count === 0) {
                            obj = {}
                            obj.lobj = lobj;
                            obj = this._packageIntel(ip, obj, intel);
                            callback(null, obj);
                        } else {
                            obj.lobj = lobj;
                            log.info("Intel:Location",ip,obj.lobj);
                            this._packageCymon(ip, obj);
                            callback(err, obj);
                        }
                    });
                } else {
                    this._lookup(ip, intel, (err, obj)=>{
                        callback(err,obj);
                    });
                }
            });
        });
    }

    _packageIntel(ip, obj, intel) {
        let weburl = "https://intel.firewalla.com/";
        log.info("IntelManger:PackageIntel:",ip,JSON.stringify(intel,null,2));
        if (intel == null) {
            return null;
        }
        if (intel.t) {
            obj.count = Math.abs(intel.t/10);
        } else {
            obj.count = 4;
        }
        if (intel.s) {
            obj.severityscore = intel.s;
        } else {
            obj.severityscore = 20;
        }
        obj.summary = "";
        obj.weburl = weburl;
        if (intel.cc) {
            try {
                obj.tags = JSON.parse(intel.cc);
            } catch(e) {
            }
        }
        log.info("IntelManger:PackageIntel:Done",ip,JSON.stringify(intel,null,2),JSON.stringify(obj,null,2));
        return obj;
    }

    _packageCymon(ip, obj) {
        let weburl = "https://cymon.io/" + ip;
        log.info("INFO:------ Intel Information", obj.count);

        let results = obj.results.filter(x => !IGNORED_TAGS.includes(x.tag));
        obj.count = results.length;
        let summary = obj.count + " reported this IP.\n";

        let tags = {};
        for (let r of obj.results) {
            if (r.tag) {
                if (tags[r.tag] == null) {
                    tags[r.tag] = {
                        tag: r.tag,
                        count: 1
                    };
                } else {
                    tags[r.tag].count += 1;
                }
            }
        }

        let tagArray = [], tagCount = 0, severity = 0;
        for (let i in tags) {
            let tag = tags[i];
            tagArray.push(tag);
            if (i.includes("malicious")) {
              severity += tag.count * 3;
            } else if (i.includes("malware")) {
              severity += tag.count * 3;
            } else if (i == "blacklist") {
              severity += tag.count * 3;
            } else {
              severity += 1;
            }
            tagCount += tag.count;
        }

        tagArray.sort((a, b) => b.count - a.count);

        obj.severityscore = severity;
        obj.summary = summary;
        obj.weburl = weburl;
        obj.tags = tagArray;

        if (obj.tags && obj.tags.length > 0) {
          const reasonize = (tag) => `${tag.tag} - ${Math.round(tag.count / tagCount * 100)}%`;
          let reason = "Possibility: ";
            let first = true;
            for (let tag of obj.tags) {
                if (first) {
                    reason += reasonize(tag);
                    first = false;
                } else {
                    reason += ", " + reasonize(tag);
                }
            }
            obj.reason = reason;
        }
    }

    /* curl ipinfo.io/98.124.243.43/
{
  "ip": "98.124.243.43",
  "hostname": "No Hostname",
  "city": "Kirkland",
  "region": "Washington",
  "country": "US",
  "loc": "47.6727,-122.1873",
  "org": "AS21740 eNom, Incorporated",
  "postal": "98033"
 */
    _location(ip, callback) {
      log.info("Looking up location:",ip);
      this.cachelookup(ip, "ipinfo", (err,data)=>{
        if (data!=null) {
            callback(null, JSON.parse(data));
            return;
        }
        let weburl = "https://ipinfo.io/" + ip;

        var options = {
            uri: weburl,
            method: 'GET',
            family: 4
            // Authorization: 'Token dc30fcd03eddbd95b90bacaea5e5a44b1b60d2f5',
        };

        request(options, (err, resp, body) => {
            if (err) {
                log.warn(`Error while requesting ${weburl}`, err);
                callback(null, null);
                return;
            }
            if (!resp) {
                log.warn(`Error - null response from ${weburl}`);
                callback(null, null);
                return;
            }
            if (resp.statusCode < 200 || resp.statusCode > 299) {
                log.warn("Error in response code", resp.statusCode);
                callback(null, null);
                return;
            }
            if (body) {
              let obj;
              try {
                obj = JSON.parse(body);
              } catch (err) {
                log.error("Error when parse ip info:", body, err);
              }
              if (obj) {
                this.cacheAdd(ip, "ipinfo", body);
                callback(null, obj);
                return;
              }
            }
            callback(null, null);
        });
      });
    }

    _lookup(ip, intel, callback) {
        let url = "https://cymon.io/api/nexus/v1/ip/" + ip + "/events?limit=100";

        let options = {
            uri: url,
            method: 'GET',
            family: 4
        };

        this._location(ip, (err, lobj)=>{
            let obj = {lobj};
            log.info("Intel:Location",ip,lobj);
            obj = this._packageIntel(ip,obj,intel);
            request(options, (err, resp, body) => {
                if (err) {
                    log.info(`Error while requesting ${url}`, err);
                    callback(err, null, null);
                    return;
                }
                if (!resp) {
                    log.info("Error while response ", err);
                    callback(500, null, null);
                    return;
                }
                if (resp.statusCode < 200 || resp.statusCode > 299) {
                    log.error("**** Error while response HTTP ", resp.statusCode);
                    callback(resp.statusCode, null, null);
                    return;
                }
                if (body) {
                    this.cacheAdd(ip, "cymon", body);
                    let cobj = JSON.parse(body);
                    if (cobj) {
                        if (cobj.count === 0) {
                            log.info("INFO:====== No Intel Information!!", ip, obj);
                            callback(null,obj);
                        } else {
                            cobj.lobj = lobj;
                            this._packageCymon(ip, cobj);
                            callback(err, cobj, cobj.weburl);
                        }
                    } else {
                        callback(null,obj);
                    }
                } else {
                    callback(null,obj);
                }
            });
        });
    }
}
<|endoftext|>


<commit_before>'use strict'

var Header = require('./Header')
var Footer = require('./Footer')
var Body = require('./Body')

var $ = window.jQuery

module.exports = HeaderFooterFactory

/**
 * HeaderFactory class. The aim of this class is to manage the document header and footer.
 * @constructor
 * @param {Editor} editor The current editor
 * @property {Editor} _editor The current editor
 * @property {Boolean} _hasHeader Tell if the document has a header or not
 * @property {Boolean} _hasBody Tell if the document has a body or not
 * @property {Boolean} _hasFooter Tell if the document has a fooer or not
 * @property {Header} header The current header if exists
 * @property {Footer} footer The current footer if exists
 */
function HeaderFooterFactory (editor) {
  this._editor = editor
  this._hasHeader = false
  this._hasBody = false
  this._hasFooter = false
}

/**
 * Load an existing header or footer depending of its nature, from its DOM element.
 * @method
 * @param {DOMElement} element
 * @returns void
 */
HeaderFooterFactory.prototype.loadElement = function (element) {
  var $el = $(element)
  if ($el.attr('data-headfoot-header')) {
    this._hasHeader = true
    this.header = new Header(this._editor, this._editor.getBody(), element)
  } else if ($el.attr('data-headfoot-footer')) {
    this._hasFooter = true
    this.footer = new Footer(this._editor, this._editor.getBody(), element)
  } else if ($el.attr('data-headfoot-body')) {
    this._hasBody = true
    this.body = new Body(this._editor, this._editor.getBody(), element, this.hasHeader(), this.hasFooter(), this.header)
  } else throw new Error('This element is not a header, footer neither a body element.')
}

/**
 * Insert a new header
 * @method
 * @returns void
 */
HeaderFooterFactory.prototype.insertHeader = function () {
  this.header = new Header(this._editor, this._editor.getBody())
  this._hasHeader = true
}

/**
 * Insert a new body
 * @method
 * @returns void
 */
HeaderFooterFactory.prototype.insertBody = function () {
  this.body = new Body(this._editor, this._editor.getBody(), this._hasHeader, this._hasFooter, this.header)
  this._hasBody = true
}

/**
 * Insert a new footer
 * @method
 * @returns void
 */
HeaderFooterFactory.prototype.insertFooter = function () {
  this.footer = new Footer(this._editor, this._editor.getBody())
  this._hasFooter = true
}

/**
 * Remove the current header
 * @method
 * @returns void
 */
HeaderFooterFactory.prototype.removeHeader = function () {
  // the header can be removed only if it exists
  if (!this.hasHeader()) throw new Error('No header available to remove')

  $(this.header.node).remove()
  this.header = null
  this._hasHeader = false
}

/**
 * Insert a new footer
 * @method
 * @returns void
 */
HeaderFooterFactory.prototype.removeFooter = function () {
  // the footer can be removed only if it exists
  if (!this.hasFooter()) throw new Error('No footer available to remove')

  $(this.footer.node).remove()
  this.footer = null
  this._hasFooter = false
}

/**
 * Check if the document has a header or not
 * @method
 * @returns {Boolean} true if the document has a header, false if not
 */
HeaderFooterFactory.prototype.hasHeader = function () {
  return this._hasHeader
}

/**
 * Check if the document has a body or not
 * @method
 * @returns {Boolean} true if the document has a body, false if not
 */
HeaderFooterFactory.prototype.hasBody = function () {
  return this._hasBody
}

/**
 * Check if the document has a footer or not
 * @method
 * @returns {Boolean} true if the document has a footer, false if not
 */
HeaderFooterFactory.prototype.hasFooter = function () {
  return this._hasFooter
}

HeaderFooterFactory.prototype.focusToEndOfBody = function () {
  var $body = $(this.body.node)
  var lastBodyChild = $body.children().last()[0]
  this.body.enterNode()
  this._editor.selection.setCursorLocation(lastBodyChild, lastBodyChild.childNodes.length)
}

HeaderFooterFactory.prototype.forceCursorToAllowedLocation = function (node, parents) {
  if (this.hasBody()) {
    if (!parents) {
      var $node = $(node)
      var allparents = $node.parents()
      parents = allparents.slice(0, -2)
    }

    var lastParent = parents[parents.length - 1]
    var allowedLocations = [this.body.node]

    if (this.hasHeader()) {
      allowedLocations.push(this.header.node)
    }
    if (this.hasFooter()) {
      allowedLocations.push(this.footer.node)
    }

    if (!~allowedLocations.indexOf(lastParent) && !~allowedLocations.indexOf(node)) {
      this.focusToEndOfBody()
    }
  }
}

HeaderFooterFactory.prototype.getActiveSection = function () {
  return [this.header, this.body, this.footer]
  .reduce(function (prev, section) {
    if (prev) {
      return prev
    } else {
      if (section.isActive) {
        return section
      }
    }
  }, null)
}
<commit_msg>enter into any just created section node<commit_after>'use strict'

var Header = require('./Header')
var Footer = require('./Footer')
var Body = require('./Body')

var $ = window.jQuery

module.exports = HeaderFooterFactory

/**
 * HeaderFactory class. The aim of this class is to manage the document header and footer.
 * @constructor
 * @param {Editor} editor The current editor
 * @property {Editor} _editor The current editor
 * @property {Boolean} _hasHeader Tell if the document has a header or not
 * @property {Boolean} _hasBody Tell if the document has a body or not
 * @property {Boolean} _hasFooter Tell if the document has a fooer or not
 * @property {Header} header The current header if exists
 * @property {Footer} footer The current footer if exists
 */
function HeaderFooterFactory (editor) {
  this._editor = editor
  this._hasHeader = false
  this._hasBody = false
  this._hasFooter = false
}

/**
 * Load an existing header or footer depending of its nature, from its DOM element.
 * @method
 * @param {DOMElement} element
 * @returns void
 */
HeaderFooterFactory.prototype.loadElement = function (element) {
  var $el = $(element)
  if ($el.attr('data-headfoot-header')) {
    this._hasHeader = true
    this.header = new Header(this._editor, this._editor.getBody(), element)
  } else if ($el.attr('data-headfoot-footer')) {
    this._hasFooter = true
    this.footer = new Footer(this._editor, this._editor.getBody(), element)
  } else if ($el.attr('data-headfoot-body')) {
    this._hasBody = true
    this.body = new Body(this._editor, this._editor.getBody(), element, this.hasHeader(), this.hasFooter(), this.header)
  } else throw new Error('This element is not a header, footer neither a body element.')
}

/**
 * Insert a new header
 * @method
 * @returns void
 */
HeaderFooterFactory.prototype.insertHeader = function () {
  this.header = new Header(this._editor, this._editor.getBody())
  this._hasHeader = true
  this.header.enterNode()
}

/**
 * Insert a new body
 * @method
 * @returns void
 */
HeaderFooterFactory.prototype.insertBody = function () {
  this.body = new Body(this._editor, this._editor.getBody(), this._hasHeader, this._hasFooter, this.header)
  this._hasBody = true
  this.body.enterNode()
}

/**
 * Insert a new footer
 * @method
 * @returns void
 */
HeaderFooterFactory.prototype.insertFooter = function () {
  this.footer = new Footer(this._editor, this._editor.getBody())
  this._hasFooter = true
  this.footer.enterNode()
}

/**
 * Remove the current header
 * @method
 * @returns void
 */
HeaderFooterFactory.prototype.removeHeader = function () {
  // the header can be removed only if it exists
  if (!this.hasHeader()) throw new Error('No header available to remove')

  $(this.header.node).remove()
  this.header = null
  this._hasHeader = false
}

/**
 * Insert a new footer
 * @method
 * @returns void
 */
HeaderFooterFactory.prototype.removeFooter = function () {
  // the footer can be removed only if it exists
  if (!this.hasFooter()) throw new Error('No footer available to remove')

  $(this.footer.node).remove()
  this.footer = null
  this._hasFooter = false
}

/**
 * Check if the document has a header or not
 * @method
 * @returns {Boolean} true if the document has a header, false if not
 */
HeaderFooterFactory.prototype.hasHeader = function () {
  return this._hasHeader
}

/**
 * Check if the document has a body or not
 * @method
 * @returns {Boolean} true if the document has a body, false if not
 */
HeaderFooterFactory.prototype.hasBody = function () {
  return this._hasBody
}

/**
 * Check if the document has a footer or not
 * @method
 * @returns {Boolean} true if the document has a footer, false if not
 */
HeaderFooterFactory.prototype.hasFooter = function () {
  return this._hasFooter
}

HeaderFooterFactory.prototype.focusToEndOfBody = function () {
  var $body = $(this.body.node)
  var lastBodyChild = $body.children().last()[0]
  this.body.enterNode()
  this._editor.selection.setCursorLocation(lastBodyChild, lastBodyChild.childNodes.length)
}

HeaderFooterFactory.prototype.forceCursorToAllowedLocation = function (node, parents) {
  if (this.hasBody()) {
    if (!parents) {
      var $node = $(node)
      var allparents = $node.parents()
      parents = allparents.slice(0, -2)
    }

    var lastParent = parents[parents.length - 1]
    var allowedLocations = [this.body.node]

    if (this.hasHeader()) {
      allowedLocations.push(this.header.node)
    }
    if (this.hasFooter()) {
      allowedLocations.push(this.footer.node)
    }

    if (!~allowedLocations.indexOf(lastParent) && !~allowedLocations.indexOf(node)) {
      this.focusToEndOfBody()
    }
  }
}

HeaderFooterFactory.prototype.getActiveSection = function () {
  return [this.header, this.body, this.footer]
  .reduce(function (prev, section) {
    if (prev) {
      return prev
    } else {
      if (section.isActive) {
        return section
      }
    }
  }, null)
}
<|endoftext|>


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

    var MongoClient = require('mongodb').MongoClient;
    var url = process.env.DOCDBCONNSTR_CosmosDB;

    var testObject = {
        "origin": "The Garage, Atlanta, GA",
        "departure_time": "1496779536115",
        "bags": 1,
        "oversized_bags": 0,
        "handicap_accessible": "false",
        "transport_mode": "driving",
        "risk_tolerance": 10,
        "segments": []
    };

    var updateObject = {
        "segments": [
            {
                "name": "Drive to airport",
                "duration_in_minutes": 10,
                "confidence_interval": 0.9
            },
            {
                "name": "Parking",
                "duration_in_minutes": 5,
                "confidence_interval": 1
            },
            {
                "name": "Security",
                "duration_in_minutes": 15,
                "confidence_interval": 0.5
            }
        ]
    };

    function addTrip(db, object) {
        return new Promise(function (resolve, reject) {
            db.collection('trips').insertOne(object, function(error, result) {
                if (error) {
                    reject(error);
                }

                resolve(result.ops[0]._id);
            });
        });
    }

    function findTrip(db, id) {
        return new Promise(function (resolve, reject) {
            db.collection('trips').findOne({_id: id}, function(error, data) {
                if (error) {
                    reject(error);
                }

                resolve(data);
            });
        });
    }

    function updateTrip(db, id, updateObject) {
        return new Promise(function (resolve, reject) {
            db.collection('trips').updateOne(
                { _id : id },
                {
                    $set: updateObject,
                    $currentDate: { "lastModified": true }
                },
                function(error, data) {
                    if (error) {
                        reject(error);
                    }

                    resolve(id);
            });
        });
    }

    module.exports = function(context, req) {
        var body = (req && req.query && req.body) || testObject,
            id = req && req.query && req.query.id,
            operation = req && req.query && req.query.operation;

        MongoClient.connect(url, function(error, db) {
            if (error) {
                console.log("Error (mongoClient): ", error);
            }

            switch(operation) {
                case "add":
                    addTrip(db, body).then(function (id) {
                        console.log({id: id});
                        context.log(id);
                        context.res = { body: id };
                    }).catch(function (error) {
                        console.log("Error (add): ", error);
                        context.error(error);
                    }).finally(function () {
                        db.close();
                        context.close();
                    });
                    break;
                case "find":
                    findTrip(db, id).then(function (data) {
                        console.log(data);
                        context.log(data);
                        context.res = { body: data };
                    }).catch(function (error) {
                        console.log("Error (find): ", error);
                        context.error(error);
                    }).finally(function () {
                        db.close();
                        context.close();
                    });
                    break;
                case "update":
                    updateTrip(db, id, updateObject).then(function (data) {
                        console.log({id: data});
                        context.log(data);
                        context.res = { body: data };
                    }).catch(function (error) {
                        console.log("Error (update): ", error);
                        context.error(error);
                    }).finally(function () {
                        db.close();
                        context.close();
                    });
                    break;
                default:
                    context.error("Operation not supported: ", operation);
                    db.close();
                    context.close();
            }

        });
    };
}());
<commit_msg>Update cosmoizer<commit_after>(function () {
    'use strict';

    var MongoClient = require('mongodb').MongoClient;
    var url = process.env.DOCDBCONNSTR_CosmosDB;

    var testObject = {
        "origin": "The Garage, Atlanta, GA",
        "departure_time": "1496779536115",
        "bags": 1,
        "oversized_bags": 0,
        "handicap_accessible": "false",
        "transport_mode": "driving",
        "risk_tolerance": 10,
        "segments": []
    };

    var updateObject = {
        "segments": [
            {
                "name": "Drive to airport",
                "duration_in_minutes": 10,
                "confidence_interval": 0.9
            },
            {
                "name": "Parking",
                "duration_in_minutes": 5,
                "confidence_interval": 1
            },
            {
                "name": "Security",
                "duration_in_minutes": 15,
                "confidence_interval": 0.5
            }
        ]
    };

    function addTrip(db, object) {
        return new Promise(function (resolve, reject) {
            db.collection('trips').insertOne(object, function(error, result) {
                if (error) {
                    reject(error);
                }

                resolve(result.ops[0]._id);
            });
        });
    }

    function findTrip(db, id) {
        return new Promise(function (resolve, reject) {
            db.collection('trips').findOne({_id: id}, function(error, data) {
                if (error) {
                    reject(error);
                }

                resolve(data);
            });
        });
    }

    function updateTrip(db, id, updateObject) {
        return new Promise(function (resolve, reject) {
            db.collection('trips').updateOne(
                { _id : id },
                {
                    $set: updateObject,
                    $currentDate: { "lastModified": true }
                },
                function(error, data) {
                    if (error) {
                        reject(error);
                    }

                    resolve(id);
            });
        });
    }

    module.exports = function(context, req) {
        var body = (req && req.body) || testObject,
            id = req && req.query && req.query.id,
            operation = req && req.query && req.query.operation;

        MongoClient.connect(url, function(error, db) {
            if (error) {
                console.log("Error (mongoClient): ", error);
            }

            switch(operation) {
                case "add":
                    addTrip(db, body).then(function (id) {
                        console.log({id: id});
                        context.log(id);
                        context.res = { body: id };
                    }).catch(function (error) {
                        console.log("Error (add): ", error);
                        context.log(error);
                    }).finally(function () {
                        db.close();
                        context.close();
                    });
                    break;
                case "find":
                    findTrip(db, id).then(function (data) {
                        console.log(data);
                        context.log(data);
                        context.res = { body: data };
                    }).catch(function (error) {
                        console.log("Error (find): ", error);
                        context.log(error);
                    }).finally(function () {
                        db.close();
                        context.close();
                    });
                    break;
                case "update":
                    updateTrip(db, id, updateObject).then(function (data) {
                        console.log({id: data});
                        context.log(data);
                        context.res = { body: data };
                    }).catch(function (error) {
                        console.log("Error (update): ", error);
                        context.log(error);
                    }).finally(function () {
                        db.close();
                        context.close();
                    });
                    break;
                default:
                    context.log("Operation not supported: ", operation);
                    db.close();
                    context.close();
            }

        });
    };
}());
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');

function LineByLine(file, options) {
    options = options || {};

    if (!options.readChunk) {
        options.readChunk = 1024;
    }

    if (!options.newLineCharacter) {
        options.newLineCharacter = 0x0a; //linux line ending
    } else {
        options.newLineCharacter = options.newLineCharacter.charCodeAt(0);
    }

    if (typeof file === 'number') {
        this.fd = file;
    } else {
        this.fd = fs.openSync(file, 'r');
    }

    this.options = options;

    this.newLineCharacter = options.newLineCharacter;

    this.reset();
}

LineByLine.prototype.reset = function() {
    this.bufferData = null;
    this.bytesRead = 0;

    this.bufferPosition = 0;
    this.eofReached = false;

    this.line = '';

    this.linesCache = [];

    this.lastBytePosition = null;

    this.fdPosition = 0;
};

LineByLine.prototype._extractLines = function(buffer) {
    var line;
    var lines = [];
    var bufferPosition = 0;

    var lastNewLineBufferPosition = 0;
    while (true) {
        var bufferPositionValue = buffer[bufferPosition++];

        if (bufferPositionValue === this.newLineCharacter) {
            line = buffer.slice(lastNewLineBufferPosition, bufferPosition);
            lines.push(line);
            lastNewLineBufferPosition = bufferPosition;
        } else if (!bufferPositionValue) {
            break;
        }
    }

    var leftovers = buffer.slice(lastNewLineBufferPosition, bufferPosition);
    if (leftovers.length) {
        lines.push(leftovers);
    }

    return lines;
};

LineByLine.prototype._readChunk = function(lineLeftovers) {
    var bufferData = new Buffer(this.options.readChunk);

    var totalBytesRead = 0;

    var bytesRead = fs.readSync(this.fd, bufferData, 0, this.options.readChunk, this.fdPosition);

    totalBytesRead = totalBytesRead + bytesRead;

    this.fdPosition = this.fdPosition + bytesRead;

    var buffers = [];
    buffers.push(bufferData);

    var lastBuffer = buffers[buffers.length-1];

    while(buffers[buffers.length-1].indexOf(this.options.newLineCharacter) === -1) {
        //new line character doesn't exist in the readed data, so we must read
        //again
        var newBuffer = new Buffer(this.options.readChunk);

        var bytesRead = fs.readSync(this.fd, newBuffer, 0, this.options.readChunk, this.fdPosition);
        totalBytesRead = totalBytesRead + bytesRead;

        this.fdPosition = this.fdPosition + bytesRead;

        buffers.push(newBuffer);
    }

    bufferData = Buffer.concat(buffers);

    if (bytesRead < this.options.readChunk) {
        this.eofReached = true;
        bufferData = bufferData.slice(0, totalBytesRead);
    }

    if (bytesRead) {
        this.linesCache = this._extractLines(bufferData);

        if (lineLeftovers) {
            this.linesCache[0] = Buffer.concat([lineLeftovers, this.linesCache[0]]);
        }
    }

    return totalBytesRead;
};

LineByLine.prototype.next = function() {
    var line = false;

    if (this.eofReached && this.linesCache.length === 0) {
        return line;
    }

    var bytesRead;

    if (!this.linesCache.length) {
        bytesRead = this._readChunk();
    }

    if (this.linesCache.length) {
        line = this.linesCache.shift();

        var lastLineCharacter = line[line.length-1];

        if (lastLineCharacter !== 0x0a) {
            bytesRead = this._readChunk(line);

            if (bytesRead) {
                line = this.linesCache.shift();
            }
        }
    }

    if (this.eofReached && this.linesCache.length === 0) {
        fs.closeSync(this.fd);
        this.fd = null;
    }

    if (line && line[line.length-1] === this.newLineCharacter) {
        line = line.slice(0, line.length-1);
    }

    return line;
};

module.exports = LineByLine;
<commit_msg>replace indexOf method with internal<commit_after>'use strict';

var fs = require('fs');

function LineByLine(file, options) {
    options = options || {};

    if (!options.readChunk) {
        options.readChunk = 1024;
    }

    if (!options.newLineCharacter) {
        options.newLineCharacter = 0x0a; //linux line ending
    } else {
        options.newLineCharacter = options.newLineCharacter.charCodeAt(0);
    }

    if (typeof file === 'number') {
        this.fd = file;
    } else {
        this.fd = fs.openSync(file, 'r');
    }

    this.options = options;

    this.newLineCharacter = options.newLineCharacter;

    this.reset();
}

LineByLine.prototype._searchInBuffer = function(buffer, hexNeedle) {
    var found = -1;

    for (var i = 0; i <= buffer.length; i++) {
        var b_byte = buffer[i];
        if (b_byte === hexNeedle) {
            found = i;
            break;
        }
    }

    return found;
};

LineByLine.prototype.reset = function() {
    this.bufferData = null;
    this.bytesRead = 0;

    this.bufferPosition = 0;
    this.eofReached = false;

    this.line = '';

    this.linesCache = [];

    this.lastBytePosition = null;

    this.fdPosition = 0;
};

LineByLine.prototype._extractLines = function(buffer) {
    var line;
    var lines = [];
    var bufferPosition = 0;

    var lastNewLineBufferPosition = 0;
    while (true) {
        var bufferPositionValue = buffer[bufferPosition++];

        if (bufferPositionValue === this.newLineCharacter) {
            line = buffer.slice(lastNewLineBufferPosition, bufferPosition);
            lines.push(line);
            lastNewLineBufferPosition = bufferPosition;
        } else if (!bufferPositionValue) {
            break;
        }
    }

    var leftovers = buffer.slice(lastNewLineBufferPosition, bufferPosition);
    if (leftovers.length) {
        lines.push(leftovers);
    }

    return lines;
};

LineByLine.prototype._readChunk = function(lineLeftovers) {
    var bufferData = new Buffer(this.options.readChunk);

    var totalBytesRead = 0;

    var bytesRead = fs.readSync(this.fd, bufferData, 0, this.options.readChunk, this.fdPosition);

    totalBytesRead = totalBytesRead + bytesRead;

    this.fdPosition = this.fdPosition + bytesRead;

    var buffers = [];
    buffers.push(bufferData);

    var lastBuffer = buffers[buffers.length-1];

    while(this._searchInBuffer(buffers[buffers.length-1], this.options.newLineCharacter) === -1) {
        //new line character doesn't exist in the readed data, so we must read
        //again
        var newBuffer = new Buffer(this.options.readChunk);

        var bytesRead = fs.readSync(this.fd, newBuffer, 0, this.options.readChunk, this.fdPosition);
        totalBytesRead = totalBytesRead + bytesRead;

        this.fdPosition = this.fdPosition + bytesRead;

        buffers.push(newBuffer);
    }

    bufferData = Buffer.concat(buffers);

    if (bytesRead < this.options.readChunk) {
        this.eofReached = true;
        bufferData = bufferData.slice(0, totalBytesRead);
    }

    if (bytesRead) {
        this.linesCache = this._extractLines(bufferData);

        if (lineLeftovers) {
            this.linesCache[0] = Buffer.concat([lineLeftovers, this.linesCache[0]]);
        }
    }

    return totalBytesRead;
};

LineByLine.prototype.next = function() {
    var line = false;

    if (this.eofReached && this.linesCache.length === 0) {
        return line;
    }

    var bytesRead;

    if (!this.linesCache.length) {
        bytesRead = this._readChunk();
    }

    if (this.linesCache.length) {
        line = this.linesCache.shift();

        var lastLineCharacter = line[line.length-1];

        if (lastLineCharacter !== 0x0a) {
            bytesRead = this._readChunk(line);

            if (bytesRead) {
                line = this.linesCache.shift();
            }
        }
    }

    if (this.eofReached && this.linesCache.length === 0) {
        fs.closeSync(this.fd);
        this.fd = null;
    }

    if (line && line[line.length-1] === this.newLineCharacter) {
        line = line.slice(0, line.length-1);
    }

    return line;
};

module.exports = LineByLine;
<|endoftext|>


<commit_before>'use strict'

module.exports = [
  {
    name: 'mc-web',
    script: 'node_modules/mc-core/src/server.js',
    node_args: '--optimize_for_size --max_old_space_size=920 --gc_interval=100',
    watch: 'node_modules/mc-core',
    ignore_watch: [
      '.git',
      '.idea',
      'node_modules/mc-core/.idea',
      'node_modules/mc-core/node_modules/mc-extension-validator/.idea',
      'node_modules/mc-core/.git',
      'node_modules/mc-core/node_modules'
    ]
  },
  {
    name: 'mc-worker-pipelines',
    script: 'node_modules/mc-core/src/worker-pipelines.js',
    watch: 'node_modules/mc-core',
    ignore_watch: [
      '.git',
      '.idea',
      'node_modules/mc-core/.idea',
      'node_modules/mc-core/node_modules/mc-extension-validator/.idea',
      'node_modules/mc-core/.git',
      'node_modules/mc-core/node_modules'
    ]
  },
  {
    name: 'mc-ui-gulp-watch',
    script: 'node_modules/mc-core/node_modules/.bin/gulp',
    args: ['watch'],
    cwd: 'node_modules/mc-core/'
  }
]
<commit_msg>Ignoring UI changes; Fixes #72<commit_after>'use strict'

module.exports = [
  {
    name: 'mc-web',
    script: 'node_modules/mc-core/src/server.js',
    node_args: '--optimize_for_size --max_old_space_size=920 --gc_interval=100',
    watch: 'node_modules/mc-core',
    ignore_watch: [
      '.git',
      '.idea',
      'node_modules/mc-core/.idea',
      'node_modules/mc-core/ui',
      'node_modules/mc-core/ui-build',
      'node_modules/mc-core/node_modules/mc-extension-validator/.idea',
      'node_modules/mc-core/.git',
      'node_modules/mc-core/node_modules'
    ]
  },
  {
    name: 'mc-worker-pipelines',
    script: 'node_modules/mc-core/src/worker-pipelines.js',
    watch: 'node_modules/mc-core',
    ignore_watch: [
      '.git',
      '.idea',
      'node_modules/mc-core/.idea',
      'node_modules/mc-core/ui',
      'node_modules/mc-core/ui-build',
      'node_modules/mc-core/node_modules/mc-extension-validator/.idea',
      'node_modules/mc-core/.git',
      'node_modules/mc-core/node_modules'
    ]
  },
  {
    name: 'mc-ui-gulp-watch',
    script: 'node_modules/mc-core/node_modules/.bin/gulp',
    args: ['watch'],
    cwd: 'node_modules/mc-core/'
  }
]
<|endoftext|>


<commit_before>(function(){

  var isIE = true; // /rv:11.0/i.test(navigator.userAgent) || /Edge\/12./i.test(navigator.userAgent);
  var queryRegExp = /query\((.+?(?=\)\s*query|\)$))/ig;
  var mediaRule = ' @media {rule} { [query-id="{id}"] { opacity: 1; } }';
  var baseRule = 'html, body { margin: 0; padding: 0 } div { -webkit-transition: opacity 0.01s; -ms-transition: opacity 0.01s; -o-transition: opacity 0.01s; transition: opacity 0.01s; opacity: 0; }';

  function attachObject(box){
    if (isIE) {
      var obj = document.createElement('iframe');
      obj.__querybox__ = box;
      obj.src = 'about:blank';
      box.appendChild(obj);
      return obj;
    } else {
      var obj = document.createElement('object');
      obj.__querybox__ = box;
      obj.type = 'text/html';
      obj.data = 'about:blank';
      return obj;
    }
  }

  function objectLoad(e){
    var box = e.target.__querybox__;
    var doc = box.__eq__.doc = e.target.contentDocument;
    doc.__querybox__ = box;
    setStyle(doc, baseRule);
    doc.addEventListener('transitionend', debounceMatching);
    doc.addEventListener('MSTransitionEnd', debounceMatching);
    doc.addEventListener('webkitTransitionEnd', debounceMatching);
    parseQueries(box);
    box.__eq__.loaded = true;
  }

  var requestFrame = window.requestAnimationFrame ||
                    window.mozRequestAnimationFrame ||
                    window.webkitRequestAnimationFrame ||
                    function(fn){ return window.setTimeout(fn, 20); };

  function debounceMatching(){
    var doc = this;
    if (!doc.__matching__) {
      doc.__matching__ = requestFrame(function(){
        getMatches(doc);
        doc.__matching__ = null;
      });
    };
  }

  function setStyle(doc, rules){
    var style = doc.createElement('style');
    style.innerHTML = rules;
    if (doc.head.firstChild) doc.head.removeChild(doc.head.firstChild);
    doc.head.appendChild(style);
  }

  function parseQueries(box){
    var media = box.getAttribute('data-media');
    if (media != null) {
      var rules = baseRule;
      var nodes = '';
      var matches = media.match(queryRegExp);
      box.setAttribute('matched-media', '');
      if (matches != null) matches.forEach(function(match){
        var values = match.replace('query(', '').split(',');
        var id = values.shift();
        nodes += '

';
        rules += mediaRule.replace('{rule}', values.join(',').trim()).replace('{id}', id);
      });
      var doc = box.__eq__.doc;
      setStyle(doc, rules);
      doc.body.innerHTML = nodes;
      getMatches(doc);
    }
  }

  function getMatches(doc){
    var matches = [];
    var box = doc.__querybox__;
    var nodes = doc.body.children;
    var index = nodes.length;
    while (index--) {
      // if you don't use the <object> defaultView's getComputedStyle, Firefox evaluates the query incorrectly
      if (doc.defaultView.getComputedStyle(nodes[index]).opacity == '1') {
        matches.push(nodes[index].getAttribute('query-id'));
      }
    }
    box.setAttribute('matched-media', matches.join(' '));
  }

  window.attachQuerySensor = function(box){
    if (!box.__eq__) {
      box.__eq__ = {};
      box.__eq__.object = attachObject(box);
    }
  };

  window.detachQuerySensor = function(box){
    if (box.__eq__) {
      box.removeChild(box.__eq__.object);
      delete box.__eq__;
    }
  };

  var setAttr = Element.prototype.setAttribute;
  Element.prototype.setAttribute = function(name){
    setAttr.apply(this, arguments);
    if (name == 'data-media') {
      if (this.__eq__) parseQueries(this);
      else attachQuerySensor(this);
    }
  }

  function initialize(){
    var nodes = document.body.querySelectorAll('body [data-media]:not(style)');
    var index = nodes.length;
    while (index--) attachQuerySensor(nodes[index]);
  }

  if (document.readyState == 'complete') initialize();
  else document.addEventListener('DOMContentLoaded', initialize);

  document.addSelectorListener("[data-media] > iframe, [data-media] > object", objectLoad);
})();<commit_msg>improve<commit_after>(function(){

  var isFrame = false;
  var queryRegExp = /query\((.+?(?=\)\s*query|\)$))/ig;
  var mediaRule = ' @media {rule} { [query-id="{id}"] { opacity: 1; } }';
  var baseRule = 'html, body { margin: 0; padding: 0 } div { -webkit-transition: opacity 0.01s; -ms-transition: opacity 0.01s; -o-transition: opacity 0.01s; transition: opacity 0.01s; opacity: 0; }';

  function attachObject(box){
    if (isFrame) {
      var obj = document.createElement('iframe');
      obj.src = 'about:blank';
    } else {
      var obj = document.createElement('object');
      obj.type = 'text/html';
      obj.data = 'about:blank';
    }
    obj.__querybox__ = box;
    box.appendChild(obj);
    return obj;
  }

  function objectLoad(e){
    var box = e.target.__querybox__;
    var doc = box.__eq__.doc = e.target.contentDocument;

    if (!doc) {
      isFrame = true;
      window.detachQuerySensor(box);
      window.attachQuerySensor(box);
      return;
    }

    doc.__querybox__ = box;
    setStyle(doc, baseRule);
    doc.addEventListener('transitionend', debounceMatching);
    doc.addEventListener('MSTransitionEnd', debounceMatching);
    doc.addEventListener('webkitTransitionEnd', debounceMatching);
    parseQueries(box);
    box.__eq__.loaded = true;
  }

  var requestFrame = window.requestAnimationFrame ||
                    window.mozRequestAnimationFrame ||
                    window.webkitRequestAnimationFrame ||
                    function(fn){ return window.setTimeout(fn, 20); };

  function debounceMatching(){
    var doc = this;
    if (!doc.__matching__) {
      doc.__matching__ = requestFrame(function(){
        getMatches(doc);
        doc.__matching__ = null;
      });
    };
  }

  function setStyle(doc, rules){
    var style = doc.createElement('style');
    style.innerHTML = rules;
    if (doc.head.firstChild) doc.head.removeChild(doc.head.firstChild);
    doc.head.appendChild(style);
  }

  function parseQueries(box){
    var media = box.getAttribute('data-media');
    if (media != null) {
      var rules = baseRule;
      var nodes = '';
      var matches = media.match(queryRegExp);
      box.setAttribute('matched-media', '');
      if (matches != null) matches.forEach(function(match){
        var values = match.replace('query(', '').split(',');
        var id = values.shift();
        nodes += '

';
        rules += mediaRule.replace('{rule}', values.join(',').trim()).replace('{id}', id);
      });
      var doc = box.__eq__.doc;
      setStyle(doc, rules);
      doc.body.innerHTML = nodes;
      getMatches(doc);
    }
  }

  function getMatches(doc){
    var matches = [];
    var box = doc.__querybox__;
    var nodes = doc.body.children;
    var index = nodes.length;
    while (index--) {
      // if you don't use the <object> defaultView's getComputedStyle, Firefox evaluates the query incorrectly
      if (doc.defaultView.getComputedStyle(nodes[index]).opacity == '1') {
        matches.push(nodes[index].getAttribute('query-id'));
      }
    }
    box.setAttribute('matched-media', matches.join(' '));
  }

  window.attachQuerySensor = function(box){
    if (!box.__eq__) {
      box.__eq__ = {};
      box.__eq__.object = attachObject(box);
    }
  };

  window.detachQuerySensor = function(box){
    if (box.__eq__) {
      box.removeChild(box.__eq__.object);
      delete box.__eq__;
    }
  };

  var setAttr = Element.prototype.setAttribute;
  Element.prototype.setAttribute = function(name){
    setAttr.apply(this, arguments);
    if (name == 'data-media') {
      if (this.__eq__) parseQueries(this);
      else attachQuerySensor(this);
    }
  }

  function initialize(){
    var nodes = document.body.querySelectorAll('body [data-media]:not(style)');
    var index = nodes.length;
    while (index--) attachQuerySensor(nodes[index]);
  }

  if (document.readyState == 'complete') initialize();
  else document.addEventListener('DOMContentLoaded', initialize);

  document.addSelectorListener("[data-media] > iframe, [data-media] > object", objectLoad);
})();<|endoftext|>


<commit_before>define([
  'jquery',
  'underscore',
  'mockup-patterns-structure-url/js/views/tablerow',
  'text!mockup-patterns-structure-url/templates/table.xml',
  'mockup-ui-url/views/base',
  'mockup-patterns-datatables',
  'mockup-patterns-sortable',
  'mockup-patterns-moment',
  'mockup-patterns-structure-url/js/models/result',
  'mockup-patterns-structure-url/js/views/actionmenu',
  'translate',
  'pat-registry',
  'bootstrap-alert'
], function($, _, TableRowView, TableTemplate, BaseView, patDataTables,
            Sortable, patMoment, Result, ActionMenuView, _t, registry) {
  'use strict';

  var TableView = BaseView.extend({
    tagName: 'div',
    template: _.template(TableTemplate),
    initialize: function(options) {
      var self = this;
      BaseView.prototype.initialize.apply(self, [options]);
      self.collection = self.app.collection;
      self.selectedCollection = self.app.selectedCollection;
      self.listenTo(self.collection, 'sync', self.render);
      self.listenTo(self.selectedCollection, 'remove', self.render);
      self.listenTo(self.selectedCollection, 'reset', self.render);
      self.collection.pager();
      self.subsetIds = [];
      self.contextInfo = null;

      $('body').on('context-info-loaded', function(event, data) {
        self.contextInfo = data;
        /* set default page info */
        self.setContextInfo();
      });

      self.dateColumns = [
        'ModificationDate',
        'EffectiveDate',
        'CreationDate',
        'ExpirationDate',
        'start',
        'end',
        'last_comment_date'
      ];
    },
    events: {
      'click .fc-breadcrumbs a': 'breadcrumbClicked',
      'change .select-all': 'selectAll',
    },
    setContextInfo: function() {
      var self = this;
      var data = self.contextInfo;
      var $defaultPage = self.$('[data-id="' + data.defaultPage + '"]');
      if ($defaultPage.length > 0) {
        $defaultPage.addClass('default-page');
      }
      /* set breadcrumb title info */
      var crumbs = data.breadcrumbs;
      if (crumbs && crumbs.length) {
        var $crumbs = self.$('.fc-breadcrumbs a.crumb');
        _.each(crumbs, function(crumb, idx) {
          $crumbs.eq(idx).html(crumb.title);
        });
      }
    },
    render: function() {
      var self = this;

      // By default do not start sorted by any column
      // Ignore first column and the last one (activeColumns.length + 2)
      // Do not show paginator, search or information, we only want column sorting
      var datatables_options = {
        "aaSorting": [],
        "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ 0, self.app.activeColumns.length + 2 ] }
        ],
        "paging": false,
        "searching": false,
        "info": false
      };

      // If options were passed from the pattern, override these ones
      $.extend(
        datatables_options, self.app.options.datatables_options
      );

      self.$el.html(self.template({
        _t: _t,
        pathParts: _.filter(
          self.app.getCurrentPath().split('/').slice(1),
          function(val) {
            return val.length > 0;
          }
        ),
        status: self.app.status,
        activeColumns: self.app.activeColumns,
        availableColumns: self.app.availableColumns,
        datatables_options: JSON.stringify(datatables_options)
      }));

      if (self.collection.length) {
        var container = self.$('tbody');
        self.collection.each(function(result) {
          self.dateColumns.map(function (col) {
            // empty column instead of displaying "None".
            if (result.attributes.hasOwnProperty(col) && (result.attributes[col] === 'None' || !result.attributes[col] )) {
              result.attributes[col] = '';
            }
          });

          var view = (new TableRowView({
            model: result,
            app: self.app,
            table: self
          })).render();
          container.append(view.el);
        });
      }
      self.moment = new patMoment(self.$el, {
        selector: '.' + self.dateColumns.join(',.'),
        format: self.options.app.momentFormat
      });

      if (self.app.options.moveUrl) {
        self.addReordering();
      }

      self.storeOrder();

      registry.scan(self.$el);

      self.$el.find("table").on( 'order.dt', function (e, settings, details) {
        var btn = $('<button type="button" class="btn btn-danger btn-xs"></button>')
                  .text(_t('Reset column sorting'))
                  .on('click', function(e) {
                    // Use column 0 to restore ordering and then empty list so it doesn't
                    // show the icon in the column header
                    self.$el.find("table.pat-datatables").data('patternDatatables').table
                        .order([ 0, "asc" ]).draw()
                        .order([]).draw();
                    // Restore reordering by drag and drop
                    self.addReordering();
                    // Clear the status message
                    self.app.setStatus();
                  });
        self.app.setStatus(_t('Cannot drag and drop items to reorder while manually sorting a column'), 'warning', btn = btn);
        $(".pat-datatables tbody").find('tr').off("drag")
        self.$el.removeClass('order-support');
      } );

      return this;
    },
    breadcrumbClicked: function(e) {
      e.preventDefault();
      var $el = $(e.target);
      if ($el[0].tagName !== 'A') {
        $el = $el.parent('a');
      }
      var path = '';
      $($el.prevAll('a').get().reverse()).each(function() {
        var part = $(this).attr('data-path');
        path += part;
        if (part !== '/') {
          path += '/';
        }
      });
      path += $el.attr('data-path');
      this.app.setCurrentPath(path);
      this.collection.currentPage = 1;
      this.collection.pager();
    },
    selectAll: function(e) {
      if ($(e.target).is(':checked')) {
        $('input[type="checkbox"]', this.$('tbody')).prop('checked', true).change();
      } else {
        /* delaying the re-rendering is much faster in this case */
        this.selectedCollection.remove(this.collection.models, { silent: true });
        this.selectedCollection.trigger('remove');
      }
      this.setContextInfo();
    },
    toggleSelectAll: function(e) {
      var $el = $(e.target);
      if (!$el.is(':checked')) {
        this.$('.select-all').prop('checked', false);
      }
    },
    addReordering: function() {
      var self = this;
      // if we have a custom query going on, we do not allow sorting.
      if (self.app.inQueryMode()) {
        self.app.setStatus({text: _t('Cannot order items while querying'), type: 'warning'});
        self.$el.removeClass('order-support');
        return;
      }
      self.$el.addClass('order-support');
      var dd = new Sortable(self.$('tbody'), {
        selector: 'tr',
        createDragItem: function(pattern, $el) {
          var $tr = $el.clone();
          var $table = $('

');
          $('tbody', $table).append($tr);
          $table.addClass('structure-dragging')
            .css({opacity: 0.85, position: 'absolute'});
          $table.width($el.width());
          $table.height($el.height());
          $table.appendTo(document.body);
          return $table;
        },
        drop: function($el, delta) {
          if (delta !== 0){
            self.app.moveItem($el.attr('data-id'), delta, self.subsetIds);
            self.storeOrder();
          }
        }
      });
    },
    storeOrder: function() {
      var self = this;
      var subsetIds = [];
      self.$('tbody tr.itemRow').each(function() {
        subsetIds.push($(this).attr('data-id'));
      });
      self.subsetIds = subsetIds;
    }
  });

  return TableView;
});
<commit_msg>fix column count for datatable initialization<commit_after>define([
  'jquery',
  'underscore',
  'mockup-patterns-structure-url/js/views/tablerow',
  'text!mockup-patterns-structure-url/templates/table.xml',
  'mockup-ui-url/views/base',
  'mockup-patterns-datatables',
  'mockup-patterns-sortable',
  'mockup-patterns-moment',
  'mockup-patterns-structure-url/js/models/result',
  'mockup-patterns-structure-url/js/views/actionmenu',
  'translate',
  'pat-registry',
  'bootstrap-alert'
], function($, _, TableRowView, TableTemplate, BaseView, patDataTables,
            Sortable, patMoment, Result, ActionMenuView, _t, registry) {
  'use strict';

  var TableView = BaseView.extend({
    tagName: 'div',
    template: _.template(TableTemplate),
    initialize: function(options) {
      var self = this;
      BaseView.prototype.initialize.apply(self, [options]);
      self.collection = self.app.collection;
      self.selectedCollection = self.app.selectedCollection;
      self.listenTo(self.collection, 'sync', self.render);
      self.listenTo(self.selectedCollection, 'remove', self.render);
      self.listenTo(self.selectedCollection, 'reset', self.render);
      self.collection.pager();
      self.subsetIds = [];
      self.contextInfo = null;

      $('body').on('context-info-loaded', function(event, data) {
        self.contextInfo = data;
        /* set default page info */
        self.setContextInfo();
      });

      self.dateColumns = [
        'ModificationDate',
        'EffectiveDate',
        'CreationDate',
        'ExpirationDate',
        'start',
        'end',
        'last_comment_date'
      ];
    },
    events: {
      'click .fc-breadcrumbs a': 'breadcrumbClicked',
      'change .select-all': 'selectAll',
    },
    setContextInfo: function() {
      var self = this;
      var data = self.contextInfo;
      var $defaultPage = self.$('[data-id="' + data.defaultPage + '"]');
      if ($defaultPage.length > 0) {
        $defaultPage.addClass('default-page');
      }
      /* set breadcrumb title info */
      var crumbs = data.breadcrumbs;
      if (crumbs && crumbs.length) {
        var $crumbs = self.$('.fc-breadcrumbs a.crumb');
        _.each(crumbs, function(crumb, idx) {
          $crumbs.eq(idx).html(crumb.title);
        });
      }
    },
    render: function() {
      var self = this;

      // By default do not start sorted by any column
      // Ignore first column and the last one (activeColumns.length + 1)
      // Do not show paginator, search or information, we only want column sorting
      var datatables_options = {
        "aaSorting": [],
        "aoColumnDefs": [
          { "bSortable": false, "aTargets": [ 0, self.app.activeColumns.length + 1 ] }
        ],
        "paging": false,
        "searching": false,
        "info": false
      };

      // If options were passed from the pattern, override these ones
      $.extend(
        datatables_options, self.app.options.datatables_options
      );

      self.$el.html(self.template({
        _t: _t,
        pathParts: _.filter(
          self.app.getCurrentPath().split('/').slice(1),
          function(val) {
            return val.length > 0;
          }
        ),
        status: self.app.status,
        activeColumns: self.app.activeColumns,
        availableColumns: self.app.availableColumns,
        datatables_options: JSON.stringify(datatables_options)
      }));

      if (self.collection.length) {
        var container = self.$('tbody');
        self.collection.each(function(result) {
          self.dateColumns.map(function (col) {
            // empty column instead of displaying "None".
            if (result.attributes.hasOwnProperty(col) && (result.attributes[col] === 'None' || !result.attributes[col] )) {
              result.attributes[col] = '';
            }
          });

          var view = (new TableRowView({
            model: result,
            app: self.app,
            table: self
          })).render();
          container.append(view.el);
        });
      }
      self.moment = new patMoment(self.$el, {
        selector: '.' + self.dateColumns.join(',.'),
        format: self.options.app.momentFormat
      });

      if (self.app.options.moveUrl) {
        self.addReordering();
      }

      self.storeOrder();

      registry.scan(self.$el);

      self.$el.find("table").on( 'order.dt', function (e, settings, details) {
        var btn = $('<button type="button" class="btn btn-danger btn-xs"></button>')
                  .text(_t('Reset column sorting'))
                  .on('click', function(e) {
                    // Use column 0 to restore ordering and then empty list so it doesn't
                    // show the icon in the column header
                    self.$el.find("table.pat-datatables").data('patternDatatables').table
                        .order([ 0, "asc" ]).draw()
                        .order([]).draw();
                    // Restore reordering by drag and drop
                    self.addReordering();
                    // Clear the status message
                    self.app.setStatus();
                  });
        self.app.setStatus(_t('Cannot drag and drop items to reorder while manually sorting a column'), 'warning', btn = btn);
        $(".pat-datatables tbody").find('tr').off("drag")
        self.$el.removeClass('order-support');
      } );

      return this;
    },
    breadcrumbClicked: function(e) {
      e.preventDefault();
      var $el = $(e.target);
      if ($el[0].tagName !== 'A') {
        $el = $el.parent('a');
      }
      var path = '';
      $($el.prevAll('a').get().reverse()).each(function() {
        var part = $(this).attr('data-path');
        path += part;
        if (part !== '/') {
          path += '/';
        }
      });
      path += $el.attr('data-path');
      this.app.setCurrentPath(path);
      this.collection.currentPage = 1;
      this.collection.pager();
    },
    selectAll: function(e) {
      if ($(e.target).is(':checked')) {
        $('input[type="checkbox"]', this.$('tbody')).prop('checked', true).change();
      } else {
        /* delaying the re-rendering is much faster in this case */
        this.selectedCollection.remove(this.collection.models, { silent: true });
        this.selectedCollection.trigger('remove');
      }
      this.setContextInfo();
    },
    toggleSelectAll: function(e) {
      var $el = $(e.target);
      if (!$el.is(':checked')) {
        this.$('.select-all').prop('checked', false);
      }
    },
    addReordering: function() {
      var self = this;
      // if we have a custom query going on, we do not allow sorting.
      if (self.app.inQueryMode()) {
        self.app.setStatus({text: _t('Cannot order items while querying'), type: 'warning'});
        self.$el.removeClass('order-support');
        return;
      }
      self.$el.addClass('order-support');
      var dd = new Sortable(self.$('tbody'), {
        selector: 'tr',
        createDragItem: function(pattern, $el) {
          var $tr = $el.clone();
          var $table = $('

');
          $('tbody', $table).append($tr);
          $table.addClass('structure-dragging')
            .css({opacity: 0.85, position: 'absolute'});
          $table.width($el.width());
          $table.height($el.height());
          $table.appendTo(document.body);
          return $table;
        },
        drop: function($el, delta) {
          if (delta !== 0){
            self.app.moveItem($el.attr('data-id'), delta, self.subsetIds);
            self.storeOrder();
          }
        }
      });
    },
    storeOrder: function() {
      var self = this;
      var subsetIds = [];
      self.$('tbody tr.itemRow').each(function() {
        subsetIds.push($(this).attr('data-id'));
      });
      self.subsetIds = subsetIds;
    }
  });

  return TableView;
});
<|endoftext|>