<commit_before>;(function(){

  var w, d;

  w = window;

  d = document;

  w.optly = w.optly || {};

  w.optly.mrkt = w.optly.mrkt || {};

  w.optly.mrkt.Oform = {};

  w.optly.mrkt.Oform.before = function(){

    d.getElementsByTagName('body')[0].classList.add('oform-processing');

    return true;

  };

  w.optly.mrkt.Oform.validationError = function(element){

    w.analytics.track(w.location.pathname, {

      category: 'form error',

      label: element.getAttribute('name')

    }, {

      Marketo: true

    });

  };

  w.optly.mrkt.Oform.done = function(){

    d.getElementsByTagName('body')[0].classList.remove('processing');

  };

  w.optly.mrkt.Oform.trackLead = function(data, XMLHttpRequest){

    var propertyName,
        reportingObject,
        source,
        token;

    source = w.optly.mrkt.source;

    token = JSON.parse(XMLHttpRequest.target.responseText);

    token = token.token || '';

    reportingObject = {

      token: token,
      utm_Campaign__c: source.utm.campaign,
      utm_Content__c: source.utm.content,
      utm_Medium__c: source.utm.medium,
      utm_Source__c: source.utm.source,
      utm_Keyword__c: source.utm.keyword,
      otm_Campaign__c: source.otm.campaign,
      otm_Content__c: source.otm.content,
      otm_Medium__c: source.otm.medium,
      otm_Source__c: source.otm.source,
      otm_Keyword__c: source.otm.keyword,
      GCLID__c: source.gclid,
      Signup_Platform__c: source.signupPlatform

    };

    for(propertyName in data){

      reportingObject['propertyName'] = data['propertyName']; //jshint ignore:line

    }

    if(typeof console === 'object'){
        console.log('reportingObject: ', reportingObject);
    }

    window.Munchkin.munchkinFunction('associateLead', reportingObject, token);

    w.analytics.identify(data.email, reportingObject, {
      integrations: {
        Marketo: true
      }
    });

    /* legacy reporting - to be deprecated */

    w.analytics.track('/account/create/success', {
      category: 'account',
      label: w.location.pathname
    }, {
      Marketo: true
    });
    w.analytics.track('/account/signin', {
      category: 'account',
      lable: w.location.pathname
    }, {
      Marketo: true
    });

    /* new reporting */

    w.analytics.track('account created', {
      category: 'account',
      label: w.location.pathname
    }, {
      Marketo: true
    });
    w.analytics.track('account signin', {
      category: 'account',
      lable: w.location.pathname
    }, {
      Marketo: true
    });

  };

  w.optly.mrkt.Oform.initContactForm = function(arg){

    new Oform({
      selector: arg.selector
    })
    .on('validationerror', w.optly.mrkt.Oform.validationError)
    .on('load', function(event){
      if(event.target.status === 200){
        //identify user
        $('body').addClass('oform-success');
        var response = JSON.parse(event.target.responseText),
            email = d.querySelector('[name="email"]').value,
            traffic = d.querySelector('#traffic');
        w.analytics.identify(email, {
          name: d.querySelector('[name="name"]').value,
          email: email,
          phone: d.querySelector('[name="phone"]').value || '',
          company: d.querySelector('[name="company"]').value || '',
          website: d.querySelector('[name="website"]').value || '',
          utm_Medium__c: window.optly.mrkt.source.utm.medium,
          otm_Medium__c: window.optly.mrkt.source.otm.medium,
          Demo_Request_Monthly_Traffic__c: traffic.options[traffic.selectedIndex].value || '',
          Inbound_Lead_Form_Type__c: d.querySelector('[name="inboundFormLeadType"]').value,
          token: response.token
        }, {
          integrations: {
            Marketo: true
          }
        });
        //track the event
        w.analytics.track('demo requested', {
          category: 'contact form',
          label: w.location.pathname
        }, {
          Marketo: true
        });
      }
    });

  };

})();
<commit_msg>set source cookie.<commit_after>;(function(){

  var w, d;

  w = window;

  d = document;

  w.optly = w.optly || {};

  w.optly.mrkt = w.optly.mrkt || {};

  w.optly.mrkt.Oform = {};

  w.optly.mrkt.Oform.before = function(){

    d.getElementsByTagName('body')[0].classList.add('oform-processing');

    return true;

  };

  w.optly.mrkt.Oform.validationError = function(element){

    w.analytics.track(w.location.pathname, {

      category: 'form error',

      label: element.getAttribute('name')

    }, {

      Marketo: true

    });

  };

  w.optly.mrkt.Oform.done = function(){

    d.getElementsByTagName('body')[0].classList.remove('processing');

  };

  w.optly.mrkt.Oform.trackLead = function(data, XMLHttpRequest){

    var propertyName,
        reportingObject,
        source,
        token;

    source = w.optly.mrkt.source;

    token = JSON.parse(XMLHttpRequest.target.responseText);

    token = token.token || '';

    reportingObject = {

      token: token,
      utm_Campaign__c: source.utm.campaign,
      utm_Content__c: source.utm.content,
      utm_Medium__c: source.utm.medium,
      utm_Source__c: source.utm.source,
      utm_Keyword__c: source.utm.keyword,
      otm_Campaign__c: source.otm.campaign,
      otm_Content__c: source.otm.content,
      otm_Medium__c: source.otm.medium,
      otm_Source__c: source.otm.source,
      otm_Keyword__c: source.otm.keyword,
      GCLID__c: source.gclid,
      Signup_Platform__c: source.signupPlatform

    };

    $.cookie('sourceCookie',
      source.utm.campaign + '|||' +
      source.utm.content + '|||' +
      source.utm.medium + '|||' +
      source.utm.source + '|||' +
      source.utm.keyword + '|||' +
      source.otm.campaign + '|||' +
      source.otm.content + '|||' +
      source.otm.medium + '|||' +
      source.otm.source + '|||' +
      source.otm.keyword + '|||' +
      source.signupPlatform + '|||'
    );

    for(propertyName in data){

      reportingObject['propertyName'] = data['propertyName']; //jshint ignore:line

    }

    if(typeof console === 'object'){
        console.log('reportingObject: ', reportingObject);
    }

    window.Munchkin.munchkinFunction('associateLead', reportingObject, token);

    w.analytics.identify(data.email, reportingObject, {
      integrations: {
        Marketo: true
      }
    });

    /* legacy reporting - to be deprecated */

    w.analytics.track('/account/create/success', {
      category: 'account',
      label: w.location.pathname
    }, {
      Marketo: true
    });
    w.analytics.track('/account/signin', {
      category: 'account',
      lable: w.location.pathname
    }, {
      Marketo: true
    });

    /* new reporting */

    w.analytics.track('account created', {
      category: 'account',
      label: w.location.pathname
    }, {
      Marketo: true
    });
    w.analytics.track('account signin', {
      category: 'account',
      lable: w.location.pathname
    }, {
      Marketo: true
    });

  };

  w.optly.mrkt.Oform.initContactForm = function(arg){

    new Oform({
      selector: arg.selector
    })
    .on('validationerror', w.optly.mrkt.Oform.validationError)
    .on('load', function(event){
      if(event.target.status === 200){
        //identify user
        $('body').addClass('oform-success');
        var response = JSON.parse(event.target.responseText),
            email = d.querySelector('[name="email"]').value,
            traffic = d.querySelector('#traffic');
        w.analytics.identify(email, {
          name: d.querySelector('[name="name"]').value,
          email: email,
          phone: d.querySelector('[name="phone"]').value || '',
          company: d.querySelector('[name="company"]').value || '',
          website: d.querySelector('[name="website"]').value || '',
          utm_Medium__c: window.optly.mrkt.source.utm.medium,
          otm_Medium__c: window.optly.mrkt.source.otm.medium,
          Demo_Request_Monthly_Traffic__c: traffic.options[traffic.selectedIndex].value || '',
          Inbound_Lead_Form_Type__c: d.querySelector('[name="inboundFormLeadType"]').value,
          token: response.token
        }, {
          integrations: {
            Marketo: true
          }
        });
        //track the event
        w.analytics.track('demo requested', {
          category: 'contact form',
          label: w.location.pathname
        }, {
          Marketo: true
        });
      }
    });

  };

})();
<|endoftext|>


<commit_before>import { lessPosition, eqPosition, minPosition, maxPosition } from "./position.js"
import { Range, defaultRange } from "./range.js";
import { TextAttribute } from "./attribute.js";
import config from "../config.js";
import { string, arr } from "lively.lang";
import { signal } from "lively.bindings";

var newline = "\n";

export class Selection {

  constructor(textMorph, range) {
    this.textMorph = textMorph;
    this._goalColumn = undefined;
    this._isReverse = false;

    var id = string.newUUID();
    this.startAnchor = textMorph.addAnchor("selection-start-" + id);
    this.endAnchor = textMorph.addAnchor("selection-end-" + id);

    this.range = Range.isValidLiteral(range) ? range : defaultRange;
    this._cursorVisible = true;
    this.cursorBlinkProcess = null;
  }

  get isSelection() { return true; }

  uninstall() {
    this.cursorBlinkStop();
    this.textMorph.removeAnchor(this.startAnchor);
    this.textMorph.removeAnchor(this.endAnchor);
  }

  mergeWith(otherSel) {
    if (!otherSel || !otherSel.isSelection)
        return false;
    if (Math.abs(Range.compare(this.range, otherSel.range)) > 4)
        return false;
    this.range = this.range.merge(otherSel.range);
    if (otherSel.isReverse() != this.isReverse())
      this.reverse();
    return true;
  }

  get range() { return this._range; }
  set range(range) {
    if (!range) return;
    let {start, end} = range;
    if (start === undefined || end === undefined) return;

    var d = this.textMorph.document;
    if (typeof start === "number") range.start = start = d.indexToPosition(start);
    if (typeof end === "number") range.end = end = d.indexToPosition(end);
    if (!Range.isValidLiteral(range)) return;

    start = d.clipPositionToLines(start);
    end = d.clipPositionToLines(end);

    var isReverse = this._isReverse = lessPosition(end, start);
    if (isReverse) [start, end] = [end, start];

    range.start = start;
    range.end = end;
    if (!range.isRange) range = new Range(range);

    if (range.equals(this._range)) return;

    this._range = range;
    this._goalColumn = this.textMorph.lineWrapping ?
      this.textMorph.toScreenPosition(this.lead).column :
      this.lead.column;

    this.startAnchor.position = range.start;
    this.endAnchor.position = range.end;

    this.textMorph.makeDirty();
    signal(this.textMorph, "selectionChange", this);
  }

  updateFromAnchors() {
    this.range = {start: this.startAnchor.position, end: this.endAnchor.position};
  }

  get start() { return this.range.start; }
  set start(val) { this.range = Range.fromPositions(val, this.end); }

  get end() { return this.range.end }
  set end(val) { this.range = Range.fromPositions(this.start, val); }

  get anchor() { return this.isReverse() ? this.range.end : this.range.start }
  set anchor(pos) {
    this.range = {start: pos, end: this.lead};
  }
  get lead() { return this.isReverse() ? this.range.start : this.range.end }
  set lead(pos) {
    this.range = {start: this.anchor, end: pos}
  }

  get text() { return this.textMorph.document.textInRange(this.range); }

  get selectedRows() {
    return {first: this.start.row, last: this.end.row}
  }

  set text(val) {
    let {range, textMorph} = this,
        reversed = this.isReverse();
    this.range = textMorph.replace(range, val);
    if (reversed) this.reverse();
  }

  reverse() { this._isReverse = !this.isEmpty() && !this._isReverse; return this; }
  isReverse() { return this._isReverse && !this.isEmpty(); }
  isEmpty() { return this.range.isEmpty(); }

  collapse(pos = this.start) { this.range = {start: pos, end: pos}; return this; }
  collapseToEnd() { this.collapse(this.end); return this; }

  growLeft(n) {
    let {textMorph: {document: d}} = this,
        endIndex = d.positionToIndex(this.end),
        startIndex = Math.min(endIndex, d.positionToIndex(this.start) - n),
        r = this.isReverse();
    this.start = d.indexToPosition(startIndex);
    this._isReverse = r;
    return this;
  }

  growRight(n) {
    let {textMorph: {document: d}} = this,
        startIndex = d.positionToIndex(this.start),
        endIndex = Math.max(startIndex, d.positionToIndex(this.end) + n),
        r = this.isReverse();
    this.end = d.indexToPosition(endIndex);
    this._isReverse = r;
    return this;
  }

  selectAll() {
    this.range = {start: {row: 0, column: 0}, end: this.textMorph.document.endPosition};
    return this;
  }

  selectLine(row = this.lead.row, includingLineEnd = false) {
    this.range = {
    start: {row, column: 0},
    end: {row: includingLineEnd ? row + 1 : row, column: includingLineEnd ? 0 : this.textMorph.getLine(row).length}};
    return this;
  }

  gotoLineEnd(row = this.lead.row) {
    var pos = {row, column: this.textMorph.getLine(row).length};
    this.range = {start: pos, end: pos};
  }

  selectLeft(n = 1) {
    if (this.isEmpty()) { this.growLeft(n); this.reverse(); }
    else this.isReverse() ? this.growLeft(n) : this.growRight(-n);
    return this;
  }
  selectRight(n = 1) { this.isReverse() ? this.growLeft(-n) : this.growRight(n); return this; }
  selectUp(n = 1, useScreenPosition) { return this.goUp(n, useScreenPosition, true); }
  selectDown(n = 1, useScreenPosition) { return this.selectUp(-n, useScreenPosition); }

  goUp(n = 1, useScreenPosition = false, select = false) {
    if (n === 0) return this;
    var goalColumn = this._goalColumn;
    this.lead = this.textMorph.getPositionAboveOrBelow(n, this.lead, useScreenPosition, goalColumn);
    if (!select) this.anchor = this.lead;
    this._goalColumn = goalColumn;
    return this;
  }
  goDown(n = 1, useScreenPosition) { return this.goUp(-n, useScreenPosition); }

  goLeft(n = 1) {
    this.isEmpty() && this.growLeft(n);
    this.collapse();
    return this;
  }

  goRight(n = 1) {
    this.isEmpty() && this.growRight(n);
    this.collapseToEnd();
    return this;
  }

  get cursorVisible() {
    return this._cursorVisible
        && this.textMorph.isFocused()
        && !this.textMorph.rejectsInput()
  }

  cursorBlinkStart() {
    this.cursorBlinkStop();
    let timeout = config.text.cursorBlinkPeriod;
    if (timeout)
      this.cursorBlinkProcess = setInterval(() => {
        this._cursorVisible = !this._cursorVisible;
        this.textMorph.makeDirty();
      }, timeout*1000);
  }

  cursorBlinkStop() {
    if (this.cursorBlinkProcess)
      clearInterval(this.cursorBlinkProcess);
    this.cursorBlinkProcess = null;
    this._cursorVisible = true;
  }

  set style(style) {
    let {textMorph} = this,
        textAttribute = new TextAttribute(style, this);
    this.textMorph.addTextAttribute(textAttribute);
  }

  getTextAttributes() {
    let {textAttributes} = this.textMorph.document,
        result = [];
    textAttributes.map(ea => {
      let intersection = this.range.intersect(ea);
      if (!intersection.isEmpty()) {
        let textAttribute = new TextAttribute(ea.style, intersection);
        result.push(textAttribute);
      }
    });
    return result;
  }

  toString() {
    let {row, column} = this.anchor,
        {row: endRow, column: endColumn} = this.lead;
    return `Selection(${row}/${column} -> ${endRow}/${endColumn})`;
  }
}

export class MultiSelection extends Selection {

  constructor(textMorph, range) {
    this.textMorph = textMorph;
    this.selections = [new Selection(textMorph, range)];
  }

  get isMultiSelection() { return true; }

  uninstall() {
    this.selections.forEach(ea => ea.uninstall());
  }

  get defaultSelection() { return arr.last(this.selections); }
  removeSelections(startingAt = 1) {
    var toRemove = this.selections.slice(startingAt)
    toRemove.forEach(ea => ea.uninstall());
    this.selections = arr.withoutAll(this.selections, toRemove);
  }

  disableMultiSelect() {
    arr.without(this.selections, this.defaultSelection).forEach(ea => ea.uninstall());
    this.selections = [this.defaultSelection];
  }

  get range() { return this.defaultSelection.range; }
  set range(range) {
    this.disableMultiSelect();
    this.defaultSelection.range = range;
  }

  updateFromAnchors() {
    this.selections.forEach(ea => ea.updateFromAnchors());
  }

  get start() { return this.defaultSelection.start; }
  set start(val) { this.defaultSelection.start = val; }

  get end() { return this.defaultSelection.end }
  set end(val) { this.defaultSelection.end = val; }

  get anchor() { return this.defaultSelection.anchor; }
  set anchor(pos) { this.defaultSelection.anchor = pos; }
  get lead() { return this.defaultSelection.lead; }
  set lead(pos) { this.defaultSelection.lead = pos; }

  get text() { return this.selections.map(sel => sel.text).join("\n"); }
  set text(val) { this.selections.forEach(sel => sel.text = val); }

  get selectedRows() { return this.defaultSelection.selectedRows; }

  reverse() { this.defaultSelection.reverse(); }
  isReverse() { return this.defaultSelection.isReverse(); }
  isEmpty() { return this.defaultSelection.isEmpty(); }

  collapse(pos) { this.defaultSelection.collapse(pos); return this; }
  collapseToEnd() { this.defaultSelection.collapseToEnd(); return this; }

  growLeft(n) { this.defaultSelection.growLeft(n); return this; }

  growRight(n) { this.defaultSelection.growRight(n); return this; }

  selectAll() {
    this.disableMultiSelect();
    this.defaultSelection.selectAll();
    return this;
  }

  selectLine(row, includingLineEnd) {
    this.defaultSelection.selectLine(row, includingLineEnd);
    return this;
  }

  gotoLineEnd(row) { this.defaultSelection.gotoLineEnd(row); }

  selectLeft(n) { this.defaultSelection.selectLeft(n); return this; }
  selectRight(n) { this.defaultSelection.selectRight(n); return this; }
  selectUp(n, useScreenPosition) { this.defaultSelection.selectUp(n, useScreenPosition); return this; }
  selectDown(n, useScreenPosition) { this.defaultSelection.selectDown(n, useScreenPosition); return this; }

  goUp(n, useScreenPosition) { return this.defaultSelection.goUp(n, useScreenPosition); return this; }
  goDown(n, useScreenPosition) { return this.defaultSelection.goDown(n, useScreenPosition); return this; }
  goLeft(n) { return this.defaultSelection.goLeft(n); return this; }
  goRight(n) { return this.defaultSelection.goRight(n); return this; }

  get cursorVisible() { return this.defaultSelection.cursorVisible; }

  cursorBlinkStart() {
    this.cursorBlinkStop();
    let timeout = config.text.cursorBlinkPeriod;
    if (timeout)
      this.cursorBlinkProcess = setInterval(() => {
        this._cursorVisible = !this._cursorVisible;
        this.selections.forEach(sel => sel._cursorVisible = this._cursorVisible);
        this.textMorph.makeDirty();
      }, timeout*1000);
  }

  cursorBlinkStop() {
    super.cursorBlinkStop();
    this.selections.forEach(sel => sel._cursorVisible = true);
  }

  set style(style) { this.defaultSelection.style = style; }

  getTextAttributes() { return this.defaultSelection.getTextAttributes(); }

  toString() {
    return `MultiSelection(${this.selections.join(", ")})`;
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  mergeSelections() {
    var sels = this.selections.slice();
    for (var i = sels.length-1; i >= 0; i--) {
      for (var j = sels.length-1; j >= 0; j--) {
        if (i === j) continue;
        if (sels[j].mergeWith(sels[i])) {
          sels.splice(i, 1)
          break;
        }
      }
    }
    this.selections = sels;
  }

  get ranges() { return this.selections.map(ea => ea.range); }
  set ranges(ranges) {
    for (var i = 0; i < ranges.length; i++) {
      var sel = this.selections[i];
      if (sel) sel.range = ranges[i];
      else this.addRange(ranges[i]);
    }
    this.removeSelections(i);
    this.mergeSelections();
  }

  addRange(range) {
    this.selections.push(new Selection(this.textMorph, range));
    this.mergeSelections();
    return arr.last(this.selections).range;
  }
}
<commit_msg>text: selection cleanup<commit_after>import { lessPosition } from "./position.js"
import { Range, defaultRange } from "./range.js";
import config from "../config.js";
import { string, arr } from "lively.lang";
import { signal } from "lively.bindings";

export class Selection {

  constructor(textMorph, range) {
    this.textMorph = textMorph;
    this._goalColumn = undefined;
    this._isReverse = false;

    var id = string.newUUID();
    this.startAnchor = textMorph.addAnchor("selection-start-" + id);
    this.endAnchor = textMorph.addAnchor("selection-end-" + id);

    this.range = Range.isValidLiteral(range) ? range : defaultRange;
    this._cursorVisible = true;
    this.cursorBlinkProcess = null;
  }

  get isSelection() { return true; }

  uninstall() {
    this.cursorBlinkStop();
    this.textMorph.removeAnchor(this.startAnchor);
    this.textMorph.removeAnchor(this.endAnchor);
  }

  mergeWith(otherSel) {
    if (!otherSel || !otherSel.isSelection)
        return false;
    if (Math.abs(Range.compare(this.range, otherSel.range)) > 4)
        return false;
    this.range = this.range.merge(otherSel.range);
    if (otherSel.isReverse() != this.isReverse())
      this.reverse();
    return true;
  }

  get range() { return this._range; }
  set range(range) {
    if (!range) return;
    let {start, end} = range;
    if (start === undefined || end === undefined) return;

    var d = this.textMorph.document;
    if (typeof start === "number") range.start = start = d.indexToPosition(start);
    if (typeof end === "number") range.end = end = d.indexToPosition(end);
    if (!Range.isValidLiteral(range)) return;

    start = d.clipPositionToLines(start);
    end = d.clipPositionToLines(end);

    var isReverse = this._isReverse = lessPosition(end, start);
    if (isReverse) [start, end] = [end, start];

    range.start = start;
    range.end = end;
    if (!range.isRange) range = new Range(range);

    if (range.equals(this._range)) return;

    this._range = range;
    this._goalColumn = this.textMorph.lineWrapping ?
      this.textMorph.toScreenPosition(this.lead).column :
      this.lead.column;

    this.startAnchor.position = range.start;
    this.endAnchor.position = range.end;

    this.textMorph.makeDirty();
    signal(this.textMorph, "selectionChange", this);
  }

  updateFromAnchors() {
    this.range = {start: this.startAnchor.position, end: this.endAnchor.position};
  }

  get start() { return this.range.start; }
  set start(val) { this.range = Range.fromPositions(val, this.end); }

  get end() { return this.range.end }
  set end(val) { this.range = Range.fromPositions(this.start, val); }

  get anchor() { return this.isReverse() ? this.range.end : this.range.start }
  set anchor(pos) {
    this.range = {start: pos, end: this.lead};
  }
  get lead() { return this.isReverse() ? this.range.start : this.range.end }
  set lead(pos) {
    this.range = {start: this.anchor, end: pos}
  }

  get text() { return this.textMorph.document.textInRange(this.range); }

  get selectedRows() {
    return {first: this.start.row, last: this.end.row}
  }

  set text(val) {
    let {range, textMorph} = this,
        reversed = this.isReverse();
    this.range = textMorph.replace(range, val);
    if (reversed) this.reverse();
  }

  reverse() { this._isReverse = !this.isEmpty() && !this._isReverse; return this; }
  isReverse() { return this._isReverse && !this.isEmpty(); }
  isEmpty() { return this.range.isEmpty(); }

  collapse(pos = this.start) { this.range = {start: pos, end: pos}; return this; }
  collapseToEnd() { this.collapse(this.end); return this; }

  growLeft(n) {
    let {textMorph: {document: d}} = this,
        endIndex = d.positionToIndex(this.end),
        startIndex = Math.min(endIndex, d.positionToIndex(this.start) - n),
        r = this.isReverse();
    this.start = d.indexToPosition(startIndex);
    this._isReverse = r;
    return this;
  }

  growRight(n) {
    let {textMorph: {document: d}} = this,
        startIndex = d.positionToIndex(this.start),
        endIndex = Math.max(startIndex, d.positionToIndex(this.end) + n),
        r = this.isReverse();
    this.end = d.indexToPosition(endIndex);
    this._isReverse = r;
    return this;
  }

  selectAll() {
    this.range = {start: {row: 0, column: 0}, end: this.textMorph.document.endPosition};
    return this;
  }

  selectLine(row = this.lead.row, includingLineEnd = false) {
    this.range = {
    start: {row, column: 0},
    end: {row: includingLineEnd ? row + 1 : row, column: includingLineEnd ? 0 : this.textMorph.getLine(row).length}};
    return this;
  }

  gotoLineEnd(row = this.lead.row) {
    var pos = {row, column: this.textMorph.getLine(row).length};
    this.range = {start: pos, end: pos};
  }

  selectLeft(n = 1) {
    if (this.isEmpty()) { this.growLeft(n); this.reverse(); }
    else this.isReverse() ? this.growLeft(n) : this.growRight(-n);
    return this;
  }
  selectRight(n = 1) { this.isReverse() ? this.growLeft(-n) : this.growRight(n); return this; }
  selectUp(n = 1, useScreenPosition) { return this.goUp(n, useScreenPosition, true); }
  selectDown(n = 1, useScreenPosition) { return this.selectUp(-n, useScreenPosition); }

  goUp(n = 1, useScreenPosition = false, select = false) {
    if (n === 0) return this;
    var goalColumn = this._goalColumn;
    this.lead = this.textMorph.getPositionAboveOrBelow(n, this.lead, useScreenPosition, goalColumn);
    if (!select) this.anchor = this.lead;
    this._goalColumn = goalColumn;
    return this;
  }
  goDown(n = 1, useScreenPosition) { return this.goUp(-n, useScreenPosition); }

  goLeft(n = 1) {
    this.isEmpty() && this.growLeft(n);
    this.collapse();
    return this;
  }

  goRight(n = 1) {
    this.isEmpty() && this.growRight(n);
    this.collapseToEnd();
    return this;
  }

  get cursorVisible() {
    return this._cursorVisible
        && this.textMorph.isFocused()
        && !this.textMorph.rejectsInput()
  }

  cursorBlinkStart() {
    this.cursorBlinkStop();
    let timeout = config.text.cursorBlinkPeriod;
    if (timeout)
      this.cursorBlinkProcess = setInterval(() => {
        this._cursorVisible = !this._cursorVisible;
        this.textMorph.makeDirty();
      }, timeout*1000);
  }

  cursorBlinkStop() {
    if (this.cursorBlinkProcess)
      clearInterval(this.cursorBlinkProcess);
    this.cursorBlinkProcess = null;
    this._cursorVisible = true;
  }

  toString() {
    let {row, column} = this.anchor,
        {row: endRow, column: endColumn} = this.lead;
    return `Selection(${row}/${column} -> ${endRow}/${endColumn})`;
  }
}

export class MultiSelection extends Selection {

  constructor(textMorph, range) {
    this.textMorph = textMorph;
    this.selections = [new Selection(textMorph, range)];
  }

  get isMultiSelection() { return true; }

  uninstall() {
    this.selections.forEach(ea => ea.uninstall());
  }

  get defaultSelection() { return arr.last(this.selections); }
  removeSelections(startingAt = 1) {
    var toRemove = this.selections.slice(startingAt)
    toRemove.forEach(ea => ea.uninstall());
    this.selections = arr.withoutAll(this.selections, toRemove);
  }

  disableMultiSelect() {
    arr.without(this.selections, this.defaultSelection).forEach(ea => ea.uninstall());
    this.selections = [this.defaultSelection];
  }

  get range() { return this.defaultSelection.range; }
  set range(range) {
    this.disableMultiSelect();
    this.defaultSelection.range = range;
  }

  updateFromAnchors() {
    this.selections.forEach(ea => ea.updateFromAnchors());
  }

  get start() { return this.defaultSelection.start; }
  set start(val) { this.defaultSelection.start = val; }

  get end() { return this.defaultSelection.end }
  set end(val) { this.defaultSelection.end = val; }

  get anchor() { return this.defaultSelection.anchor; }
  set anchor(pos) { this.defaultSelection.anchor = pos; }
  get lead() { return this.defaultSelection.lead; }
  set lead(pos) { this.defaultSelection.lead = pos; }

  get text() { return this.selections.map(sel => sel.text).join("\n"); }
  set text(val) { this.selections.forEach(sel => sel.text = val); }

  get selectedRows() { return this.defaultSelection.selectedRows; }

  reverse() { this.defaultSelection.reverse(); }
  isReverse() { return this.defaultSelection.isReverse(); }
  isEmpty() { return this.defaultSelection.isEmpty(); }

  collapse(pos) { this.defaultSelection.collapse(pos); return this; }
  collapseToEnd() { this.defaultSelection.collapseToEnd(); return this; }

  growLeft(n) { this.defaultSelection.growLeft(n); return this; }

  growRight(n) { this.defaultSelection.growRight(n); return this; }

  selectAll() {
    this.disableMultiSelect();
    this.defaultSelection.selectAll();
    return this;
  }

  selectLine(row, includingLineEnd) {
    this.defaultSelection.selectLine(row, includingLineEnd);
    return this;
  }

  gotoLineEnd(row) { this.defaultSelection.gotoLineEnd(row); }

  selectLeft(n) { this.defaultSelection.selectLeft(n); return this; }
  selectRight(n) { this.defaultSelection.selectRight(n); return this; }
  selectUp(n, useScreenPosition) { this.defaultSelection.selectUp(n, useScreenPosition); return this; }
  selectDown(n, useScreenPosition) { this.defaultSelection.selectDown(n, useScreenPosition); return this; }

  goUp(n, useScreenPosition) { return this.defaultSelection.goUp(n, useScreenPosition); return this; }
  goDown(n, useScreenPosition) { return this.defaultSelection.goDown(n, useScreenPosition); return this; }
  goLeft(n) { return this.defaultSelection.goLeft(n); return this; }
  goRight(n) { return this.defaultSelection.goRight(n); return this; }

  get cursorVisible() { return this.defaultSelection.cursorVisible; }

  cursorBlinkStart() {
    this.cursorBlinkStop();
    let timeout = config.text.cursorBlinkPeriod;
    if (timeout)
      this.cursorBlinkProcess = setInterval(() => {
        this._cursorVisible = !this._cursorVisible;
        this.selections.forEach(sel => sel._cursorVisible = this._cursorVisible);
        this.textMorph.makeDirty();
      }, timeout*1000);
  }

  cursorBlinkStop() {
    super.cursorBlinkStop();
    this.selections.forEach(sel => sel._cursorVisible = true);
  }

  set style(style) { this.defaultSelection.style = style; }

  getTextAttributes() { return this.defaultSelection.getTextAttributes(); }

  toString() {
    return `MultiSelection(${this.selections.join(", ")})`;
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  mergeSelections() {
    var sels = this.selections.slice();
    for (var i = sels.length-1; i >= 0; i--) {
      for (var j = sels.length-1; j >= 0; j--) {
        if (i === j) continue;
        if (sels[j].mergeWith(sels[i])) {
          sels.splice(i, 1)
          break;
        }
      }
    }
    this.selections = sels;
  }

  get ranges() { return this.selections.map(ea => ea.range); }
  set ranges(ranges) {
    for (var i = 0; i < ranges.length; i++) {
      var sel = this.selections[i];
      if (sel) sel.range = ranges[i];
      else this.addRange(ranges[i]);
    }
    this.removeSelections(i);
    this.mergeSelections();
  }

  addRange(range) {
    this.selections.push(new Selection(this.textMorph, range));
    this.mergeSelections();
    return arr.last(this.selections).range;
  }
}
<|endoftext|>


<commit_before>var log = require('czagenda-log').from(__filename);
var statusCodes = require('../statusCodes');
var errors = require('../../models').errors;
var async = require('async');

exports.populateModelUrls = function () {
	this._urls.get[this._urlPrefix] = { middleware : [], fn : this.list};
	this._urls.get[this._urlPrefix + '/_count'] =  { middleware : [],  fn :this.count};
	this._urls.get[this._urlPrefix + '/:id'] =  { middleware : [], fn :this.read};

	this._urls.post[this._urlPrefix] =  { middleware : [], fn :this.create};

	this._urls.put[this._urlPrefix + '/:id'] =  { middleware : [], fn :this.update};
	this._urls.del[this._urlPrefix + '/:id'] =  { middleware : [], fn :this.del};
}

/**
 * populate an object with other object attributes
 */
exports._populateObject = function(obj, data, req, res) {

	log.notice("[TODO] exports._populateObject Supprimer oauthKeys");

	var oauthKeys = ['oauth_nonce', 'oauth_timestamp', 'oauth_consumer_key', 'oauth_signature_method', 'oauth_version', 'oauth_token', 'oauth_signature'];

	var allowedKeys = obj.constructor.publicWriteAttributes;
	var wrongKeys = [];

	for(k in data) {
		if(allowedKeys.indexOf(k) === -1 && oauthKeys.indexOf(k) === -1) {
			wrongKeys.push(k);
		} else {
			obj[k] = data[k];
		}
	}

	if(wrongKeys.length === 0) {
		return true;
	} else {
		res.statusCode = statusCodes.BAD_REQUEST;
		res.end(JSON.stringify({
			error : "Readonly attributes",
			attributes : wrongKeys
		}))
		return false;
	}

}
/**
 * Return a serializable object that contains only attributes listed in keys
 */
exports._serializeObject = function(obj) {
	return obj.serialize(obj.constructor.publicAttributes);
}

exports._getQueryFromRequest = function(req, callback) {
	callback(null, {
		query : {
			match_all : {}
		}
	});
}

exports.list = function(req, res) {

	var query = req.query;

	if( typeof (query.skip) !== 'undefined') {
		query.skip = parseInt(query.skip);
	}

	if( typeof (query.limit) !== 'undefined') {
		query.limit = parseInt(query.limit);
	}

	this._getQueryFromRequest(req, function(err, query) {

		if(err !== null) {

			if( err instanceof restError.BadRequest) {
				res.statusCode = statusCodes.BAD_REQUEST;
				res.end(err.message)
			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}

		} else {
			this._search(req, res, query);
		}
	}.bind(this));
}

exports.count = function(req, res) {

	var query = {
		match_all : { }
	}

	this._count(req, res, query);

}

exports.read = function(req, res) {

	this._clazz.get({
		id : req.url.split('?')[0]
	}, function(err, obj) {

		if(err !== null) {
			if( err instanceof errors.ObjectDoesNotExist) {
				res.statusCode = statusCodes.NOT_FOUND;
				res.end('Not found')
			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}
		} else {
			res.statusCode = statusCodes.ALL_OK;
			res.end(this._renderJson(req, res, this._serializeObject(obj)));
		}

	}.bind(this));
}

exports.create = function(req, res) {

	var data = req.body;

	var obj = new this._clazz;
	if(this._populateObject(obj, data, req, res) === true) {

		obj.save( function(err, obj) {

			if(err === null) {
				res.statusCode = statusCodes.CREATED;
				res.end(this._renderJson(req, res, this._serializeObject(obj)));
			} else {

				if( err instanceof errors.ObjectAlreadyExists) {
					res.statusCode = statusCodes.DUPLICATE_ENTRY;
					res.end(err.message);

				} else if( err instanceof errors.ValidationError) {
					res.statusCode = statusCodes.BAD_REQUEST;
					res.end(this._renderJson(req, res, obj.validationErrors));

				} else {
					res.statusCode = statusCodes.INTERNAL_ERROR;
					res.end('Internal error')
				}

			}

		}.bind(this));
	}
}

exports.update = function(req, res) {
	// load object...

	console.log(req.url);
	console.log(req.url.split('?')[0]);

	this._clazz.get({
		id : req.url.split('?')[0]
	}, function(err, obj) {

		if(err !== null) {

			if( err instanceof errors.ObjectDoesNotExist) {
				res.statusCode = statusCodes.NOT_FOUND;
				res.end('Not found')
			} else if( err instanceof errors.ValidationError) {
				res.statusCode = statusCodes.BAD_REQUEST;
				res.end(this._renderJson(req, res, obj.validationErrors));

			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}

		} else {
			if(this._populateObject(obj, req.body, req, res) === true) {

				obj.save( function(err, obj) {

					if(err !== null) {
						if( err instanceof errors.ObjectDoesNotExist) {
							res.statusCode = statusCodes.NOT_FOUND;
							res.end('Not found')
						} else if( err instanceof errors.ValidationError) {
							res.statusCode = statusCodes.BAD_REQUEST;
							res.end(this._renderJson(req, res, obj.validationErrors));

						} else {
							res.statusCode = statusCodes.INTERNAL_ERROR;
							res.end('Internal error')
						}

					} else {
						res.statusCode = statusCodes.ALL_OK;
						res.end(this._renderJson(req, res, this._serializeObject(obj)));
					}

				}.bind(this));
			}

		}

	}.bind(this))
}

exports.del = function(req, res) {

	// load object...
	this._clazz.get({
		id : req.url.split('?')[0]
	}, function(err, obj) {

		if(err !== null) {
			if( err instanceof errors.ObjectDoesNotExist) {
				res.statusCode = statusCodes.NOT_FOUND;
				res.end('Not found')
			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}

		} else {

			// and delete it...
			obj.del( function(err, obj) {

				if(err !== null) {
					res.statusCode = statusCodes.INTERNAL_ERROR;
					res.end('Internal error')
				} else {

					res.statusCode = statusCodes.DELETED;
					res.end()
				}

			}.bind(this))
		}

	}.bind(this))
}

exports._search = function(req, res, query) {

	var qs = req.query;

	if( typeof (qs.limit) !== 'undefined') {
		query.size = qs.limit;
	} else {
		query.size = 10;
	}

	if( typeof (qs.skip) !== 'undefined') {
		query.from = qs.skip;
	} else {
		query.from = 0;
	}

	if( typeof (qs['sort']) !== 'undefined') {
		query['sort'] = [{}];
		query['sort'][0][qs['sort']] = {};
	}

	var attrs = this._clazz.publicAttributes;

	this._clazz.search(query, attrs, function(err, result) {
		if(err !== null) {
			if( err instanceof errors.IndexDoesNotExist) {
				res.statusCode = statusCodes.NOT_FOUND;
				res.end('Not found');
			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}
		} else {
			res.end(this._renderJson(req, res, result));
		}

	}.bind(this));
}

exports._count = function(req, res, query) {

	this._clazz.count(query, function(err, result) {
		if(err !== null) {
			if( err instanceof errors.IndexDoesNotExist) {
				res.statusCode = statusCodes.NOT_FOUND;
				res.end('Not found');
			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}
		} else {
			res.end(this._renderJson(req, res, result));
		}

	}.bind(this));
}

exports._perms = function(req, res, permClass, grantToClass) {

	var q = {
		query : {
			term : {
				applyOn : '/' + this._type + '/' + req.params.id
			}
		}
	};

	var tasks = [

	function(callback) {
		permClass.search(q, ["grantTo", "createDate", "updateDate"], function(err, result) {

			if(err !== null) {
				callback(err)
			} else {
				callback(null, result);
			}

		});
	}];

	if(req.query.include_docs == true || ( typeof (req.query.include_docs) !== 'undefined' && req.query.include_docs.toLowerCase() == 'true')) {
		tasks.push(function(result, callback) {

			var ids = [];
			var byGrantTo = {};

			for(var i = 0, l = result.rows.length; i < l; i++) {
				ids.push(result.rows[i].grantTo)
				byGrantTo[result.rows[i].grantTo] = result.rows[i];
			}

			var q = {
				size : 10000,
				query : {
					ids : {
						values : ids
					}
				}
			}

			grantToClass.search(q, grantToClass.publicAttributes, function(err, objects) {

				if(err !== null) {
					callback(err);
				} else {

					for(var i = 0, l = objects.rows.length; i < l; i++) {
						byGrantTo[objects.rows[i].id].grantTo = objects.rows[i];
					}
					callback(null, result);
				}
			});
		});
	}

	async.waterfall(tasks, function(err, result) {
		if(err !== null) {
			if( err instanceof errors.IndexDoesNotExist) {
				res.statusCode = statusCodes.NOT_FOUND;
				res.end('Not found');
			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}
		} else {
			res.end(this._renderJson(req, res, result));
		}
	}.bind(this));
}<commit_msg>bugfix in libs/rest/mModelUrls due to prefixing urls api<commit_after>var log = require('czagenda-log').from(__filename);
var statusCodes = require('../statusCodes');
var errors = require('../../models').errors;
var async = require('async');

exports.populateModelUrls = function () {
	this._urls.get[this._urlPrefix] = { middleware : [], fn : this.list};
	this._urls.get[this._urlPrefix + '/_count'] =  { middleware : [],  fn :this.count};
	this._urls.get[this._urlPrefix + '/:id'] =  { middleware : [], fn :this.read};

	this._urls.post[this._urlPrefix] =  { middleware : [], fn :this.create};

	this._urls.put[this._urlPrefix + '/:id'] =  { middleware : [], fn :this.update};
	this._urls.del[this._urlPrefix + '/:id'] =  { middleware : [], fn :this.del};
}

/**
 * populate an object with other object attributes
 */
exports._populateObject = function(obj, data, req, res) {

	log.notice("[TODO] exports._populateObject Supprimer oauthKeys");

	var oauthKeys = ['oauth_nonce', 'oauth_timestamp', 'oauth_consumer_key', 'oauth_signature_method', 'oauth_version', 'oauth_token', 'oauth_signature'];

	var allowedKeys = obj.constructor.publicWriteAttributes;
	var wrongKeys = [];

	for(k in data) {
		if(allowedKeys.indexOf(k) === -1 && oauthKeys.indexOf(k) === -1) {
			wrongKeys.push(k);
		} else {
			obj[k] = data[k];
		}
	}

	if(wrongKeys.length === 0) {
		return true;
	} else {
		res.statusCode = statusCodes.BAD_REQUEST;
		res.end(JSON.stringify({
			error : "Readonly attributes",
			attributes : wrongKeys
		}))
		return false;
	}

}
/**
 * Return a serializable object that contains only attributes listed in keys
 */
exports._serializeObject = function(obj) {
	return obj.serialize(obj.constructor.publicAttributes);
}

exports._getQueryFromRequest = function(req, callback) {
	callback(null, {
		query : {
			match_all : {}
		}
	});
}

exports.list = function(req, res) {

	var query = req.query;

	if( typeof (query.skip) !== 'undefined') {
		query.skip = parseInt(query.skip);
	}

	if( typeof (query.limit) !== 'undefined') {
		query.limit = parseInt(query.limit);
	}

	this._getQueryFromRequest(req, function(err, query) {

		if(err !== null) {

			if( err instanceof restError.BadRequest) {
				res.statusCode = statusCodes.BAD_REQUEST;
				res.end(err.message)
			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}

		} else {
			this._search(req, res, query);
		}
	}.bind(this));
}

exports.count = function(req, res) {

	var query = {
		match_all : { }
	}

	this._count(req, res, query);

}

exports.read = function(req, res) {

	this._clazz.get({
		id : this._urlPrefix + "/" + req.params.id
	}, function(err, obj) {

		if(err !== null) {
			if( err instanceof errors.ObjectDoesNotExist) {
				res.statusCode = statusCodes.NOT_FOUND;
				res.end('Not found')
			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}
		} else {
			res.statusCode = statusCodes.ALL_OK;
			res.end(this._renderJson(req, res, this._serializeObject(obj)));
		}

	}.bind(this));
}

exports.create = function(req, res) {

	var data = req.body;

	var obj = new this._clazz;
	if(this._populateObject(obj, data, req, res) === true) {

		obj.save( function(err, obj) {

			if(err === null) {
				res.statusCode = statusCodes.CREATED;
				res.end(this._renderJson(req, res, this._serializeObject(obj)));
			} else {

				if( err instanceof errors.ObjectAlreadyExists) {
					res.statusCode = statusCodes.DUPLICATE_ENTRY;
					res.end(err.message);

				} else if( err instanceof errors.ValidationError) {
					res.statusCode = statusCodes.BAD_REQUEST;
					res.end(this._renderJson(req, res, obj.validationErrors));

				} else {
					res.statusCode = statusCodes.INTERNAL_ERROR;
					res.end('Internal error')
				}

			}

		}.bind(this));
	}
}

exports.update = function(req, res) {
	// load object...

	this._clazz.get({
		id : this._urlPrefix + "/" + req.params.id
	}, function(err, obj) {

		if(err !== null) {

			if( err instanceof errors.ObjectDoesNotExist) {
				res.statusCode = statusCodes.NOT_FOUND;
				res.end('Not found')
			} else if( err instanceof errors.ValidationError) {
				res.statusCode = statusCodes.BAD_REQUEST;
				res.end(this._renderJson(req, res, obj.validationErrors));

			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}

		} else {
			if(this._populateObject(obj, req.body, req, res) === true) {

				obj.save( function(err, obj) {

					if(err !== null) {
						if( err instanceof errors.ObjectDoesNotExist) {
							res.statusCode = statusCodes.NOT_FOUND;
							res.end('Not found')
						} else if( err instanceof errors.ValidationError) {
							res.statusCode = statusCodes.BAD_REQUEST;
							res.end(this._renderJson(req, res, obj.validationErrors));

						} else {
							res.statusCode = statusCodes.INTERNAL_ERROR;
							res.end('Internal error')
						}

					} else {
						res.statusCode = statusCodes.ALL_OK;
						res.end(this._renderJson(req, res, this._serializeObject(obj)));
					}

				}.bind(this));
			}

		}

	}.bind(this))
}

exports.del = function(req, res) {

	// load object...
	this._clazz.get({
		id : this._urlPrefix + "/" + req.params.id
	}, function(err, obj) {

		if(err !== null) {
			if( err instanceof errors.ObjectDoesNotExist) {
				res.statusCode = statusCodes.NOT_FOUND;
				res.end('Not found')
			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}

		} else {

			// and delete it...
			obj.del( function(err, obj) {

				if(err !== null) {
					res.statusCode = statusCodes.INTERNAL_ERROR;
					res.end('Internal error')
				} else {

					res.statusCode = statusCodes.DELETED;
					res.end()
				}

			}.bind(this))
		}

	}.bind(this))
}

exports._search = function(req, res, query) {

	var qs = req.query;

	if( typeof (qs.limit) !== 'undefined') {
		query.size = qs.limit;
	} else {
		query.size = 10;
	}

	if( typeof (qs.skip) !== 'undefined') {
		query.from = qs.skip;
	} else {
		query.from = 0;
	}

	if( typeof (qs['sort']) !== 'undefined') {
		query['sort'] = [{}];
		query['sort'][0][qs['sort']] = {};
	}

	var attrs = this._clazz.publicAttributes;

	this._clazz.search(query, attrs, function(err, result) {
		if(err !== null) {
			if( err instanceof errors.IndexDoesNotExist) {
				res.statusCode = statusCodes.NOT_FOUND;
				res.end('Not found');
			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}
		} else {
			res.end(this._renderJson(req, res, result));
		}

	}.bind(this));
}

exports._count = function(req, res, query) {

	this._clazz.count(query, function(err, result) {
		if(err !== null) {
			if( err instanceof errors.IndexDoesNotExist) {
				res.statusCode = statusCodes.NOT_FOUND;
				res.end('Not found');
			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}
		} else {
			res.end(this._renderJson(req, res, result));
		}

	}.bind(this));
}

exports._perms = function(req, res, permClass, grantToClass) {

	var q = {
		query : {
			term : {
				applyOn : '/' + this._type + '/' + req.params.id
			}
		}
	};

	var tasks = [

	function(callback) {
		permClass.search(q, ["grantTo", "createDate", "updateDate"], function(err, result) {

			if(err !== null) {
				callback(err)
			} else {
				callback(null, result);
			}

		});
	}];

	if(req.query.include_docs == true || ( typeof (req.query.include_docs) !== 'undefined' && req.query.include_docs.toLowerCase() == 'true')) {
		tasks.push(function(result, callback) {

			var ids = [];
			var byGrantTo = {};

			for(var i = 0, l = result.rows.length; i < l; i++) {
				ids.push(result.rows[i].grantTo)
				byGrantTo[result.rows[i].grantTo] = result.rows[i];
			}

			var q = {
				size : 10000,
				query : {
					ids : {
						values : ids
					}
				}
			}

			grantToClass.search(q, grantToClass.publicAttributes, function(err, objects) {

				if(err !== null) {
					callback(err);
				} else {

					for(var i = 0, l = objects.rows.length; i < l; i++) {
						byGrantTo[objects.rows[i].id].grantTo = objects.rows[i];
					}
					callback(null, result);
				}
			});
		});
	}

	async.waterfall(tasks, function(err, result) {
		if(err !== null) {
			if( err instanceof errors.IndexDoesNotExist) {
				res.statusCode = statusCodes.NOT_FOUND;
				res.end('Not found');
			} else {
				res.statusCode = statusCodes.INTERNAL_ERROR;
				res.end('Internal error')
			}
		} else {
			res.end(this._renderJson(req, res, result));
		}
	}.bind(this));
}<|endoftext|>


<commit_before>goog.provide('lime.audio.Audio');

goog.require('goog.events');

// Notice. Real problems for audio in iOS. Works only for one sound
// and needs to be initialized from user event. No solutions found.

/**
 * Audio stream object
 * @constructor
 * @param {string} filePath Path to audio file.
 */
lime.audio.Audio = function(filePath) {

    if(filePath && goog.isFunction(filePath.data)){
        filePath = filePath.data();
    }

    /**
     * @type bBoolean}
     * @private
     */
    this.loaded_ = false;

    /**
     * @type {boolean}
     * @private
     */
    this.playing_ = false;

    /**
     * Internal audio element
     * @type {audio}
     */
    this.baseElement = document.createElement('audio');
    this.baseElement.preload = true;
    this.baseElement.loop = false;

    if (goog.userAgent.GECKO && (/\.mp3$/).test(filePath)) {
        filePath = filePath.replace(/\.mp3$/, '.ogg');
    }

    this.baseElement.src = filePath;
    this.baseElement.load();

    this.loadInterval = setInterval(goog.bind(this.loadHandler_, this), 10);

    this.loaded_ = false;
};

/**
 * Handle loading the audio file. Event handlers seem to fail
 * on lot of browsers.
 * @private
 */
lime.audio.Audio.prototype.loadHandler_ = function() {
    if (this.baseElement.readyState > 2) {
        this.loaded_ = true;
        clearTimeout(this.loadInterval);
    }
    if (this.baseElement.error)clearTimeout(this.loadInterval);

    if (lime.userAgent.IOS && this.baseElement.readyState == 0) {
        //ios hack do not work any more after 4.2.1 updates
        // no good solutions that i know
        this.loaded_ = true;
        clearTimeout(this.loadInterval);
        // this means that ios audio anly works if called from user action
    }
};

/**
 * Returns true if audio file has been loaded
 * @return {boolean} Audio has been loaded.
 */
lime.audio.Audio.prototype.isLoaded = function() {
    return this.loaded_;
};

/**
 * Returns true if audio file is playing
 * @return {boolean} Audio is playing.
 */
lime.audio.Audio.prototype.isPlaying = function() {
    return this.playing_;
};

/**
 * Start playing the audio
 */
lime.audio.Audio.prototype.play = function() {
    if (this.isLoaded() && !this.isPlaying() && !lime.audio.getMute()) {
        this.baseElement.play();
        this.playing_ = true;
        if (lime.audio._playQueue.indexOf(this) == -1) {
          lime.audio._playQueue.push(this);
        }
    }
};

/**
 * Stop playing the audio
 */
lime.audio.Audio.prototype.stop = function() {
    if (this.isPlaying()) {
        this.baseElement.pause();
        this.playing_ = false;
    }
};

lime.audio._isMute = false;
lime.audio._playQueue = [];

lime.audio.getMute = function() {
  return lime.audio._isMute;
};

lime.audio.setMute = function(bool) {
  if (bool && !lime.audio._isMute) {
    for (var i = 0; i < lime.audio._playQueue.length; i++) {
      lime.audio._playQueue[i].stop();
    }
    lime.audio._playQueue = [];
  }
  lime.audio._isMute = bool;
};
<commit_msg>Web Audio API version of Audio player<commit_after>goog.provide('lime.audio.Audio');

goog.require('goog.events');

// Notice. Real problems for audio in iOS. Works only for one sound
// and needs to be initialized from user event. No solutions found.

/**
 * Audio stream object
 * @constructor
 * @param {string} filePath Path to audio file.
 */
lime.audio.Audio = function(filePath) {

    if(filePath && goog.isFunction(filePath.data)){
        filePath = filePath.data();
    }

    /**
     * @type bBoolean}
     * @private
     */
    this.loaded_ = false;

    /**
     * @type {boolean}
     * @private
     */
    this.playing_ = false;

    if (goog.userAgent.GECKO && (/\.mp3$/).test(filePath)) {
        filePath = filePath.replace(/\.mp3$/, '.ogg');
    }

    if (lime.audio.AudioContext) {
        this.prepareContext_();
        this.loadBuffer(filePath, goog.bind(this.bufferLoadedHandler_, this));
    }
    else {
        /**
         * Internal audio element
         * @type {audio}
         */
        this.baseElement = document.createElement('audio');
        this.baseElement.preload = true;
        this.baseElement.loop = false;

        this.baseElement.src = filePath;
        this.baseElement.load();
        var self = this;
        this.baseElement.addEventListener('ended', function() {
            self.playing_ = false;
        });
        this.loadInterval = setInterval(goog.bind(this.loadHandler_, this), 10);

        this.loaded_ = false;
    }
};

lime.audio.AudioContext = goog.global['AudioContext'] || goog.global['webkitAudioContext'];
lime.audio._buffers = {};

lime.audio.Audio.prototype.prepareContext_ = function() {
    if (lime.audio.context) return;
    var context = lime.audio.context = new lime.audio.AudioContext();
    var gain = lime.audio.masterGain = context.createGainNode();
    gain.connect(context.destination);
};

lime.audio.Audio.prototype.loadBuffer = function (path, cb) {
    var buffers = lime.audio._buffers;
    if (buffers[path] && buffers[path].buffer) {
        cb(buffers[path].buffer, path);
    }
    else if (buffers[path]) {
        buffers[path].push(cb);
    }
    else {
        buffers[path] = [cb];
        var req = new XMLHttpRequest();
        req.open('GET', path, true);
        req.responseType = 'arraybuffer';
        req.onload = function() {
            lime.audio.context.decodeAudioData(req.response, function(buffer) {
               if (!buffer) {
                   return console.error('Error decoding file:', path);
               }
               var cbArray = buffers[path];
               buffers[path] = buffer;
               for (var i=0; i < cbArray.length; i++) {
                   cbArray[i](buffer, path);
               }
            });
        };
        req.onerror = function() {
          console.error('XHR error loading file:', path);
        };
        req.send();
    }
};

lime.audio.Audio.prototype.bufferLoadedHandler_ = function (buffer, path) {
    this.buffer = buffer;
    this.loaded_ = true;
    console.log(this.buffer.duration, lime.audio.context.currentTime);
};

/**
 * Handle loading the audio file. Event handlers seem to fail
 * on lot of browsers.
 * @private
 */
lime.audio.Audio.prototype.loadHandler_ = function() {
    if (this.baseElement.readyState > 2) {
        this.loaded_ = true;
        clearTimeout(this.loadInterval);
    }
    if (this.baseElement.error)clearTimeout(this.loadInterval);

    if (lime.userAgent.IOS && this.baseElement.readyState == 0) {
        //ios hack do not work any more after 4.2.1 updates
        // no good solutions that i know
        this.loaded_ = true;
        clearTimeout(this.loadInterval);
        // this means that ios audio anly works if called from user action
    }
};

/**
 * Returns true if audio file has been loaded
 * @return {boolean} Audio has been loaded.
 */
lime.audio.Audio.prototype.isLoaded = function() {
    return this.loaded_;
};

/**
 * Returns true if audio file is playing
 * @return {boolean} Audio is playing.
 */
lime.audio.Audio.prototype.isPlaying = function() {
    return lime.audio.AudioContext && this.source ? this.source.playbackState == this.source.PLAYING_STATE : this.playing_;
};

/**
 * Start playing the audio
 */
lime.audio.Audio.prototype.play = function() {
    if (this.isLoaded() && !this.isPlaying() && !lime.audio.getMute()) {
        if (lime.audio.AudioContext) {
            if (this.source && this.source.playbackState == this.source.FINISHED_STATE) {
                this.playPosition_ = 0;
            }
            this.source = lime.audio.context.createBufferSource();
            this.source.buffer = this.buffer;
            this.source.connect(lime.audio.masterGain);
            this.playTime_ = lime.audio.context.currentTime;
            if (this.playPosition_ > 0) {
                this.source.noteGrainOn(0, this.playPosition_, this.buffer.duration - this.playPosition_);
            }
            else {
                this.source.noteOn(0);
            }
        }
        else {
            this.baseElement.play();
        }
        this.playing_ = true;
        if (lime.audio._playQueue.indexOf(this) == -1) {
          lime.audio._playQueue.push(this);
        }
    }
};

/**
 * Stop playing the audio
 */
lime.audio.Audio.prototype.stop = function() {
    if (this.isPlaying()) {
        if (lime.audio.AudioContext) {
            this.playPosition_ = lime.audio.context.currentTime - this.playTime_ + (this.playPosition_ || 0);
            if (this.playPosition_ > this.buffer.duration) {
                this.playPosition_ = 0;
            }
            this.source.noteOff(0);
            this.source = null;
        }
        else {
            this.baseElement.pause();
        }
        this.playing_ = false;
    }
};

lime.audio._isMute = false;
lime.audio._playQueue = [];

lime.audio.getMute = function() {
  return lime.audio._isMute;
};

lime.audio.setMute = function(bool) {
  if (bool && !lime.audio._isMute) {
    for (var i = 0; i < lime.audio._playQueue.length; i++) {
      lime.audio._playQueue[i].stop();
    }
    lime.audio._playQueue = [];
  }
  lime.audio._isMute = bool;
};

<|endoftext|>


<commit_before>'use strict';

var MongoClient = require('mongodb').MongoClient
var cheerio = require('cheerio');
var Q = require('q');
var _ = require('lodash');

var mongoUri = process.env.MONGOLAB_URI ||
    process.env.MONGOHQ_URL ||
    'mongodb://localhost/prerender';

var db = Q.denodeify(MongoClient.connect)(mongoUri);
var table = function(domain){
    return db.then(function (db) {
        return Q.denodeify(db.collection.bind(db))(domain);
    });
};

module.exports = {
    beforePhantomRequest: function(req, res, next) {
        var uri = uriFromPath(req.url);
        if (req.method === 'DELETE') {
            console.log('DELETE :', uri);
            del(uri).then(function () {
                res.send(200, uri + ' deleted.');
            }).catch(reportAndProceed(next));
        } else if (req.method === 'PUT' || req.method === 'POST') {
            // Just pass through so that Phantom will render the page
            console.log('PUT :', uri);
            next();
        } else if (req.method === 'GET') {
            console.log('GET :', uri);
            get(uri).then(function (document) {
                console.log('Serving from cache:', uri);

                _.each(document.headers, function (value, key) {
                    res.setHeader(key, value);
                });

                res.send(document.statusCode, document.content);
            }).catch(reportAndProceed(next));
        } else {
            res.send(400, 'Only GET, POST, PUT and DELETE methods are supported.');
        }
    },

    afterPhantomRequest: function(req, res, next) {
        var uri = uriFromPath(req.url);

        var original = originalHead(req);
        var overrides = headOverrides(req);
        var head = _.merge({}, original, overrides);

        var document = {
            content: req.prerender.documentHTML,
            statusCode: head.statusCode,
            headers: head.headers,
            originalHead: original,
            overrides: overrides
        };

        set(uri, document).then(function () {
            console.log('Saved:', uri);

            _.each(document.headers, function (value, key) {
                res.setHeader(key, value);
            });

            res.send(document.statusCode, document.content);
        }).catch(reportAndProceed(next));
    }
};

function uriFromPath (path) {
    return path.replace(/^\//, '');
}

function domainFromPath (uri) {
    return uri.replace('http://','').replace('https://','').split(/[/?#]/)[0];
}

function originalHead (req) {
    return {
        statusCode: req.prerender.statusCode,
        headers: req.prerender.headers.reduce(function (headers, header) {
            headers[header.name] = header.value;
            return headers;
        }, {})
    };
}

function headOverrides (req) {
    var $ = cheerio.load(req.prerender.documentHTML);

    var headersOverride = {};

    $('meta[name="prerender-header"][content]').each(function (i, el) {
        var content = el.attribs.content.match(/([^:]+):\s*(.*)\s*/);
        var name = content[1];
        var value = content[2];
        headersOverride[name] = value;
    });

    var overriden = {
        headers: headersOverride
    };

    var statusCodeOverride = $('meta[name="prerender-status-code"][content]')
        .last()
        .attr('content');

    if (statusCodeOverride) {
        overriden.statusCode = parseInt(statusCodeOverride, 10);
    }

    return overriden;
}

function get (uri) {
    return table(domainFromPath(uri)).then(function (collection) {
        var findOne = Q.denodeify(collection.findOne.bind(collection));

        return findOne({ uri: uri }).then(function (item) {
            return item || Q.reject(uri + ' not found');
        });
    });
}

function set (uri, value) {
    return table(domainFromPath(uri)).then(function (collection) {
        var update = Q.denodeify(collection.update.bind(collection));

        var query = { uri: uri };
        var options = { upsert: true };

        var document = _.merge({
            uri: uri,
            date: new Date()
        }, value);

        return update(query, document, options);
    });
}

function del (uri) {
    return table(domainFromPath(uri)).then(function (collection) {
        var findAndRemove = Q.denodeify(collection.findAndRemove.bind(collection));

        return findAndRemove({ uri: uri });
    });
}

function reportAndProceed (next) {
    return function (error) {
        console.error(error.stack || error);
        next();
    };
}
<commit_msg>Removed console.log<commit_after>'use strict';

var MongoClient = require('mongodb').MongoClient
var cheerio = require('cheerio');
var Q = require('q');
var _ = require('lodash');

var mongoUri = process.env.MONGOLAB_URI ||
    process.env.MONGOHQ_URL ||
    'mongodb://localhost/prerender';

var db = Q.denodeify(MongoClient.connect)(mongoUri);
var table = function(domain){
    return db.then(function (db) {
        return Q.denodeify(db.collection.bind(db))(domain);
    });
};

module.exports = {
    beforePhantomRequest: function(req, res, next) {
        var uri = uriFromPath(req.url);
        if (req.method === 'DELETE') {
            del(uri).then(function () {
                res.send(200, uri + ' deleted.');
            }).catch(reportAndProceed(next));
        } else if (req.method === 'PUT' || req.method === 'POST') {
            // Just pass through so that Phantom will render the page
            next();
        } else if (req.method === 'GET') {
            get(uri).then(function (document) {
                console.log('Serving from cache:', uri);

                _.each(document.headers, function (value, key) {
                    res.setHeader(key, value);
                });

                res.send(document.statusCode, document.content);
            }).catch(reportAndProceed(next));
        } else {
            res.send(400, 'Only GET, POST, PUT and DELETE methods are supported.');
        }
    },

    afterPhantomRequest: function(req, res, next) {
        var uri = uriFromPath(req.url);

        var original = originalHead(req);
        var overrides = headOverrides(req);
        var head = _.merge({}, original, overrides);

        var document = {
            content: req.prerender.documentHTML,
            statusCode: head.statusCode,
            headers: head.headers,
            originalHead: original,
            overrides: overrides
        };

        set(uri, document).then(function () {
            console.log('Saved:', uri);

            _.each(document.headers, function (value, key) {
                res.setHeader(key, value);
            });

            res.send(document.statusCode, document.content);
        }).catch(reportAndProceed(next));
    }
};

function uriFromPath (path) {
    return path.replace(/^\//, '');
}

function domainFromPath (uri) {
    return uri.replace('http://','').replace('https://','').split(/[/?#]/)[0];
}

function originalHead (req) {
    return {
        statusCode: req.prerender.statusCode,
        headers: req.prerender.headers.reduce(function (headers, header) {
            headers[header.name] = header.value;
            return headers;
        }, {})
    };
}

function headOverrides (req) {
    var $ = cheerio.load(req.prerender.documentHTML);

    var headersOverride = {};

    $('meta[name="prerender-header"][content]').each(function (i, el) {
        var content = el.attribs.content.match(/([^:]+):\s*(.*)\s*/);
        var name = content[1];
        var value = content[2];
        headersOverride[name] = value;
    });

    var overriden = {
        headers: headersOverride
    };

    var statusCodeOverride = $('meta[name="prerender-status-code"][content]')
        .last()
        .attr('content');

    if (statusCodeOverride) {
        overriden.statusCode = parseInt(statusCodeOverride, 10);
    }

    return overriden;
}

function get (uri) {
    return table(domainFromPath(uri)).then(function (collection) {
        var findOne = Q.denodeify(collection.findOne.bind(collection));

        return findOne({ uri: uri }).then(function (item) {
            return item || Q.reject(uri + ' not found');
        });
    });
}

function set (uri, value) {
    return table(domainFromPath(uri)).then(function (collection) {
        var update = Q.denodeify(collection.update.bind(collection));

        var query = { uri: uri };
        var options = { upsert: true };

        var document = _.merge({
            uri: uri,
            date: new Date()
        }, value);

        return update(query, document, options);
    });
}

function del (uri) {
    return table(domainFromPath(uri)).then(function (collection) {
        var findAndRemove = Q.denodeify(collection.findAndRemove.bind(collection));

        return findAndRemove({ uri: uri });
    });
}

function reportAndProceed (next) {
    return function (error) {
        console.error(error.stack || error);
        next();
    };
}
<|endoftext|>


<commit_before>// When an error occurs
function errorFn(msg, trace) {
  // Log the error and trace
  console.error(msg);
  trace.forEach(function(item) {
      console.error('  ', item.file, ':', item.line);
  });

  // Leave with a bad exit code
  phantom.exit(1);
}
phantom.onError = errorFn;

// Load in dependencies
var system = require('system'),
    webpage = require('webpage');

// Create a webpage
var page = webpage.create();
page.onError = errorFn;

// Grab the arguments
var args = system.args,
    username = args[1];

// If there is no image, throw an error
if (!username) {
  throw new Error('No username was specified.');
}

// Load the screenshot page
var __dirname = phantom.libraryPath;
page.open(__dirname + '/index.html?' + username, function (status) {
  // Wait until the canvas has rendered
  function checkCanvas() {
    // Determine if the canvas is rendered
    var canvasRendered = page.evaluate(function () {
          return window.canvasHasRendered;
        });

    console.log('checking', canvasRendered);
    // If it has not, check again in 100ms
    if (!canvasRendered) {
      return setTimeout(checkCanvas, 100);
    }

    // Grab the canvas contents and echo
    var png = page.evaluate(function () {
          var canvas = document.getElementById('canvas');
          return canvas.toDataURL();
        });
    console.log(png);

    // Leave gracefully
    phantom.exit(0);
  }
  checkCanvas();
});

// Set up a timeout to autokill
setTimeout(function () {
  console.error('Timeout occurred at 2 seconds.');
  phantom.exit(1);
}, 2000);<commit_msg>One typo out of the way and back on track!<commit_after>// When an error occurs
function errorFn(msg, trace) {
  // Log the error and trace
  console.error(msg);
  trace.forEach(function(item) {
      console.error('  ', item.file, ':', item.line);
  });

  // Leave with a bad exit code
  phantom.exit(1);
}
phantom.onError = errorFn;

// Load in dependencies
var system = require('system'),
    webpage = require('webpage');

// Create a webpage
var page = webpage.create();
page.onError = errorFn;

// Grab the arguments
var args = system.args,
    username = args[1];

// If there is no image, throw an error
if (!username) {
  throw new Error('No username was specified.');
}

// Load the screenshot page
var __dirname = phantom.libraryPath;
page.open(__dirname + '/index.html?' + username, function (status) {
  // Wait until the canvas has rendered
  function checkCanvas() {
    // Determine if the canvas is rendered
    var canvasRendered = page.evaluate(function () {
          return window.canvasRendered;
        });

    // console.log('checking', canvasRendered);
    // If it has not, check again in 100ms
    if (!canvasRendered) {
      return setTimeout(checkCanvas, 100);
    }

    // Grab the canvas contents and echo
    var dataPng = page.evaluate(function () {
          var canvas = document.getElementById('canvas');
          return canvas.toDataURL();
        }),
        // 'data:image/png;base64,iVBORw0KGgoAAAANS...'
        // 'data:image/png;base64,'.length === 22
        png = dataPng.slice(22);
    console.log(png);

    // Leave gracefully
    phantom.exit(0);
  }
  checkCanvas();
});

// Set up a timeout to autokill
setTimeout(function () {
  console.error('Timeout occurred at 2 seconds.');
  phantom.exit(1);
}, 2000);<|endoftext|>


<commit_before>var request = require('request');
var funkit = require('funkit');
var is = require('is-js');

function api(url, cb) {
    getMeta(url, function(err, d) {
        if(err) cb(err);
        else cb(null, constructAPI(url, d));
    });
}
exports.api = api;

function getMeta(url, cb) {
    request.get(url, function(err, d) {
        if(err || d.statusCode != 200) cb(err || d.body);
        else cb(null, JSON.parse(d.body));
    });
}
exports.getMeta = getMeta;

function constructAPI(url, d) {
    var ret = {};
    var parts = url.split('?');
    url = funkit.string.rtrim('/', parts[0]) + '/';
    var q = QtoOb(parts[1]);

    for(var k in d) {
        var v = d[k];
        var r = url + k;

        // TODO: collection ops (ie. boards(id).columns.<op>)
        ret[k] = {};
        ret[k].get = op('get', r, q);
        ret[k].count = op('get', r + '/count', q);
        ret[k].create = op('post', r, q);
        ret[k].update = op('put', r, q);
        ret[k]['delete'] = op('delete', r, q);
    }

    return ret;
}

function op(method, r, q) {
    return function(o, cb) {
        if(is.fn(o)) {
            request.get({url: r, qs: funkit.common.merge({method: method}, q)},
                handle(o));
        }
        else if(is.object(o) && !is.array(o) && o.length) {
            o.method = method;
            var id = o.id || o._id || '';
            delete o.id;

            request.get({url: r + '/' + id, qs: funkit.common.merge(o, q)},
                handle(cb));
        }
        else {
            o = o? o: '';
            o = o.length? o: '';
            request.get({url: r + o, qs: funkit.common.merge({method: method}, q)},
                handle(cb));
        }
    };
}

function handle(cb) {
    return function(err, d) {
        if(err || d.statusCode != 200) cb(err || d.body);
        else cb(null, JSON.parse(d.body));
    };
}

function QtoOb(q) {
    q = q? q.split('&'): [];
    return funkit.functional.ziptoo(q.map(funkit.partial(funkit.string.split, '=')));
}
exports.QtoOb = QtoOb;

function toQ(o) {
    var fields = o.fields? o.fields.join(','): '';
    delete o.fields;

    return fields + funkit.functional.otozip(o).map(function(v) {
        return v[0] + '=' + v[1].split(' ').join('+');
    }).join('&');
}

<commit_msg>Make create work again<commit_after>var request = require('request');
var funkit = require('funkit');
var is = require('is-js');

function api(url, cb) {
    getMeta(url, function(err, d) {
        if(err) cb(err);
        else cb(null, constructAPI(url, d));
    });
}
exports.api = api;

function getMeta(url, cb) {
    request.get(url, function(err, d) {
        if(err || d.statusCode != 200) cb(err || d.body);
        else cb(null, JSON.parse(d.body));
    });
}
exports.getMeta = getMeta;

function constructAPI(url, d) {
    var ret = {};
    var parts = url.split('?');
    url = funkit.string.rtrim('/', parts[0]) + '/';
    var q = QtoOb(parts[1]);

    for(var k in d) {
        var v = d[k];
        var r = url + k;

        // TODO: collection ops (ie. boards(id).columns.<op>)
        ret[k] = {};
        ret[k].get = op('get', r, q);
        ret[k].count = op('get', r + '/count', q);
        ret[k].create = op('post', r, q);
        ret[k].update = op('put', r, q);
        ret[k]['delete'] = op('delete', r, q);
    }

    return ret;
}

function op(method, r, q) {
    return function(o, cb) {
        if(is.fn(o)) {
            request.get({url: r, qs: funkit.common.merge({method: method}, q)},
                handle(o));
        }
        else if(is.object(o) && !is.array(o) && Object.keys(o).length) {
            o.method = method;
            var id = o.id || o._id || '';
            delete o.id;

            request.get({url: r + '/' + id, qs: funkit.common.merge(o, q)},
                handle(cb));
        }
        else {
            o = o? o: '';
            o = o.length? o: '';
            request.get({url: r + o, qs: funkit.common.merge({method: method}, q)},
                handle(cb));
        }
    };
}

function handle(cb) {
    return function(err, d) {
        if(err || d.statusCode != 200) cb(err || d.body);
        else cb(null, JSON.parse(d.body));
    };
}

function QtoOb(q) {
    q = q? q.split('&'): [];
    return funkit.functional.ziptoo(q.map(funkit.partial(funkit.string.split, '=')));
}
exports.QtoOb = QtoOb;

function toQ(o) {
    var fields = o.fields? o.fields.join(','): '';
    delete o.fields;

    return fields + funkit.functional.otozip(o).map(function(v) {
        return v[0] + '=' + v[1].split(' ').join('+');
    }).join('&');
}

<|endoftext|>


<commit_before>/**
 * Breadcrumb handlers
 */

module.exports = {
  /**
   * Middleware for select the breadcrumb middleware handler
   */
  middleware: function metatagMiddleware(req, res, next) {
    if (res.locals.breadcrumbHandler) {
      if (typeof res.locals.breadcrumbHandler === 'function') {
        return res.locals.breadcrumbHandler(req, res, next);
      } else if (req.we.router.breadcrumb.middlewares[res.locals.breadcrumbHandler]) {
        return req.we.router.breadcrumb.middlewares[res.locals.breadcrumbHandler](req, res, next);
      }
    }

    next();
  },

  /**
   * Middleware handlers
   *
   * @type {Object}
   */
  middlewares: {
    /**
     * Default create breadcrumb function
     * @return {Array} Links array with href and text
     */
    create: function createBreadcrumb(req, res, next) {
      res.locals.breadcrumb =
        '
'+
          '
'+res.locals.__('Home')+'
'+
          '
'+res.locals.__(res.locals.resourceName + '.find')+'
'+
          '
'+res.locals.__(res.locals.resourceName + '.create')+'
'+
        '
';

      next();
    },

    /**
     * Default find breadcrumb function
     * @return {Array} Links array with href and text
     */
    find: function findBreadcrumb(req, res, next) {
      res.locals.breadcrumb =
        '
'+
          '
'+res.locals.__('Home')+'
'+
          '
'+res.locals.__(res.locals.resourceName + '.find')+'
'+
        '
';

      next();
    },

    /**
     * Default findOne breadcrumb function
     * @return {Array} Links array with href and text
     */
    findOne: function findOneBreadcrumb(req, res, next) {
      res.locals.breadcrumb =
        '
'+
          '
'+res.locals.__('Home')+'
'+
          '
'+res.locals.__(res.locals.resourceName + '.find')+'
'+
          '
'+req.we.utils.string(res.locals.title).truncate(25).s+'
'+
        '
';

      next();
    },

    /**
     * Default edit / update breadcrumb function
     * @return {Array} Links array with href and text
     */
    edit: function editBreadcrumb(req, res, next) {
      res.locals.breadcrumb =
        '
'+
          '
'+res.locals.__('Home')+'
'+
          '
'+res.locals.__(res.locals.resourceName + '.find')+'
'+
          '
'+
            req.we.utils.string(res.locals.title).truncate(25).s+
          '
'+
          '
'+res.locals.__('edit')+'
'+
        '
';

      next();
    },

    /**
     * Default delete breadcrumb function
     * @return {Array} Links array with href and text
     */
    delete: function deleteBreadcrumb(req, res, next) {
      res.locals.breadcrumb =
        '
'+
          '
'+res.locals.__('Home')+'
'+
          '
'+res.locals.__(res.locals.resourceName + '.find')+'
'+
          '
'+
            req.we.utils.string(res.locals.title).truncate(25).s+
          '
'+
          '
'+res.locals.__('delete')+'
'+
        '
';

      next();
    }
  }
}<commit_msg>fix error if title is null<commit_after>/**
 * Breadcrumb handlers
 */

module.exports = {
  /**
   * Middleware for select the breadcrumb middleware handler
   */
  middleware: function metatagMiddleware(req, res, next) {
    if (res.locals.breadcrumbHandler) {
      if (typeof res.locals.breadcrumbHandler === 'function') {
        return res.locals.breadcrumbHandler(req, res, next);
      } else if (req.we.router.breadcrumb.middlewares[res.locals.breadcrumbHandler]) {
        return req.we.router.breadcrumb.middlewares[res.locals.breadcrumbHandler](req, res, next);
      }
    }

    next();
  },

  /**
   * Middleware handlers
   *
   * @type {Object}
   */
  middlewares: {
    /**
     * Default create breadcrumb function
     * @return {Array} Links array with href and text
     */
    create: function createBreadcrumb(req, res, next) {
      res.locals.breadcrumb =
        '
'+
          '
'+res.locals.__('Home')+'
'+
          '
'+res.locals.__(res.locals.resourceName + '.find')+'
'+
          '
'+res.locals.__(res.locals.resourceName + '.create')+'
'+
        '
';

      next();
    },

    /**
     * Default find breadcrumb function
     * @return {Array} Links array with href and text
     */
    find: function findBreadcrumb(req, res, next) {
      res.locals.breadcrumb =
        '
'+
          '
'+res.locals.__('Home')+'
'+
          '
'+res.locals.__(res.locals.resourceName + '.find')+'
'+
        '
';

      next();
    },

    /**
     * Default findOne breadcrumb function
     * @return {Array} Links array with href and text
     */
    findOne: function findOneBreadcrumb(req, res, next) {
      res.locals.breadcrumb =
        '
'+
          '
'+res.locals.__('Home')+'
'+
          '
'+res.locals.__(res.locals.resourceName + '.find')+'
'+
          '
'+req.we.utils.string(res.locals.title || '').truncate(25).s+'
'+
        '
';

      next();
    },

    /**
     * Default edit / update breadcrumb function
     * @return {Array} Links array with href and text
     */
    edit: function editBreadcrumb(req, res, next) {
      res.locals.breadcrumb =
        '
'+
          '
'+res.locals.__('Home')+'
'+
          '
'+res.locals.__(res.locals.resourceName + '.find')+'
'+
          '
'+
            req.we.utils.string(res.locals.title || '').truncate(25).s+
          '
'+
          '
'+res.locals.__('edit')+'
'+
        '
';

      next();
    },

    /**
     * Default delete breadcrumb function
     * @return {Array} Links array with href and text
     */
    delete: function deleteBreadcrumb(req, res, next) {
      res.locals.breadcrumb =
        '
'+
          '
'+res.locals.__('Home')+'
'+
          '
'+res.locals.__(res.locals.resourceName + '.find')+'
'+
          '
'+
            req.we.utils.string(res.locals.title || '').truncate(25).s+
          '
'+
          '
'+res.locals.__('delete')+'
'+
        '
';

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


<commit_before>
module.exports = function(app){

    app.use(function(req, res, next){
        //Look for the cookie
        if(!app.sdk || !app.sdk.Account){
            return next();
        }
        var access_token = req.headers.access_token || req.cookies['access_token'];
        if(!access_token){
            if(req.session.access_token){
                req.session.access_token = null;
            }
            return next();
        }
        if(req.session.user && req.session.access_token == access_token){
            //No change of user => No need to load... hopefully
            res.bootstrap('access_token', access_token);
            res.bootstrap('user', new app.sdk.Account(req.session.user));

            return next();
        }
        app.sdk.Account.findByAccessToken(
            access_token,
            { client_id: app.njax.config.core.app, client_secret:null },
            function(err, account){
                if(err) return next(err);

                req.session.access_token = access_token;
                res.bootstrap('access_token', access_token);
                req.session.user = account.toObject();
                res.bootstrap('user',  account);
                return next();
            }
        );

    });
    app.use(function(req, res, next){
        var api_url = req.api_url.replace('http://', '').replace('https://', '');;
        var www_url = req.www_url.replace('http://', '').replace('https://', '');;

        var allow_origin = null;
        var raw_origin = req.get('Origin');
		if(raw_origin){
			var origin = raw_origin.replace('http://', '').replace('https://', '');
			req.njax.origin = origin;
			if(raw_origin.indexOf('://') != -1){
				req.njax.origin_protocal = raw_origin.split('://')[0];
			}else{
				req.njax.origin_protocal = null;
			}
		}
		/*console.log("!!!!!!!!!!!!!!!!MAAATTTTT REMOVE THIs");
		allow_origin = origin;*/
        if(!origin){
            allow_origin = api_url;
        }else if(origin == api_url){
            allow_origin = api_url;
        }else if(origin == www_url){
            allow_origin = www_url;
        }else if(origin == app.njax.config.core.api.host){
            allow_origin = app.njax.config.core.api.host;
        }else if(origin == app.njax.config.core.host){
            allow_origin = app.njax.config.core.host;
        }else if(origin == app.njax.config.api.host){
            allow_origin = app.njax.config.api.host;
        }if(origin == app.njax.config.core.host){
            allow_origin = app.njax.config.core.host;
        }/*else if (origin == app.njax.config.core.api.host.substr('api.'.length)){
            //TODO: Allow core app to get in this bad boy
            allow_origin =  app.njax.config.core.api.host.substr('api.'.length);
        }*/
		res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
		res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,access_token,client_id,client_secret');
		res.setHeader('Access-Control-Allow-Credentials', true);
		res.bootstrap('allow_origin', allow_origin);
		function finish(err){
			if(err){
				return next(err);
			}
			if(origin){
				/*console.log('Protocol:', req.njax.origin_protocal + '://' + origin);*/
				res.setHeader('Access-Control-Allow-Origin', req.njax.origin_protocal + '://' + origin);

			}

			if(req.method == 'OPTIONS'){
				return res.send("Your Origin is allowed by our 'Access-Control-Allow-Credentials'");
			}
			return next();
		}
		if(!allow_origin){
			return app.njax.routes.origin_middleware(req, res, finish);
		}
		return finish();

    });
}<commit_msg>middleware update<commit_after>
module.exports = function(app){

    app.use(function(req, res, next){
        var api_url = req.api_url.replace('http://', '').replace('https://', '');;
        var www_url = req.www_url.replace('http://', '').replace('https://', '');;

        var allow_origin = null;
        var raw_origin = req.get('Origin');
		if(raw_origin){
			var origin = raw_origin.replace('http://', '').replace('https://', '');
			req.njax.origin = origin;
			if(raw_origin.indexOf('://') != -1){
				req.njax.origin_protocal = raw_origin.split('://')[0];
			}else{
				req.njax.origin_protocal = null;
			}
		}
		/*console.log("!!!!!!!!!!!!!!!!MAAATTTTT REMOVE THIs");
		allow_origin = origin;*/
        if(!origin){
            allow_origin = api_url;
        }else if(origin == api_url){
            allow_origin = api_url;
        }else if(origin == www_url){
            allow_origin = www_url;
        }else if(origin == app.njax.config.core.api.host){
            allow_origin = app.njax.config.core.api.host;
        }else if(origin == app.njax.config.core.host){
            allow_origin = app.njax.config.core.host;
        }else if(origin == app.njax.config.api.host){
            allow_origin = app.njax.config.api.host;
        }if(origin == app.njax.config.core.host){
            allow_origin = app.njax.config.core.host;
        }/*else if (origin == app.njax.config.core.api.host.substr('api.'.length)){
            //TODO: Allow core app to get in this bad boy
            allow_origin =  app.njax.config.core.api.host.substr('api.'.length);
        }*/
		res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
		res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,access_token,client_id,client_secret');
		res.setHeader('Access-Control-Allow-Credentials', true);
		res.bootstrap('allow_origin', allow_origin);
		function finish(err){
			if(err){
				return next(err);
			}
			if(origin){
				/*console.log('Protocol:', req.njax.origin_protocal + '://' + origin);*/
				res.setHeader('Access-Control-Allow-Origin', req.njax.origin_protocal + '://' + origin);

			}

			if(req.method == 'OPTIONS'){
				return res.send("Your Origin is allowed by our 'Access-Control-Allow-Credentials'");
			}
			return next();
		}
		if(!allow_origin){
			return app.njax.routes.origin_middleware(req, res, finish);
		}
		return finish();

    });
	app.use(function(req, res, next){
		//Look for the cookie
		if(!app.sdk || !app.sdk.Account){
			return next();
		}
		var access_token = req.headers.access_token || req.cookies['access_token'];
		if(!access_token){
			if(req.session.access_token){
				req.session.access_token = null;
			}
			return next();
		}
		if(req.session.user && req.session.access_token == access_token){
			//No change of user => No need to load... hopefully
			res.bootstrap('access_token', access_token);
			res.bootstrap('user', new app.sdk.Account(req.session.user));

			return next();
		}
		app.sdk.Account.findByAccessToken(
			access_token,
			{ client_id: app.njax.config.core.app, client_secret:null },
			function(err, account){
				if(err) return next(err);

				req.session.access_token = access_token;
				res.bootstrap('access_token', access_token);
				req.session.user = account.toObject();
				res.bootstrap('user',  account);
				return next();
			}
		);

	});
}<|endoftext|>


<commit_before>var $$ = React.createElement;

var _ = require("substance/helpers");

// Tree Node Component
// ---------------

var TreeNode = React.createClass({
  displayName: "TreeNode",

  handleToggle: function(e) {
    var node = this.props.node;
    node.handleToggle(node.id);
    e.preventDefault();
  },

  render: function() {
    var node = this.props.node;
    var treeComp = this.props.treeComp;
    var tree = treeComp.props.tree;
    var childNodes = tree.getChildren(node.id);

    var childrenEls = [];

    childrenEls = childNodes.map(function(node) {
      return $$(TreeNode, {
        treeComp: treeComp,
        key: node.id,
        node: node
      });
    }.bind(this));

    _.each(this.props.children, function(childNode) {
      childrenEls($$(TreeNode, {
        node: childNode
      }));
    });

    return $$("div", {className: 'tree-node'+ (node.active ? ' selected' : '')},
      $$('a', {
        href: "#",
        className: 'name',
        "data-id": node.id,
        onClick: this.handleToggle,
      }, node.name),
      $$('div', {className: 'children'}, childrenEls)
    );
  }
});

// Tree Component
// ---------------

var Tree = React.createClass({
  displayName: "Tree",

  componentWillMount: function() {
    this._prepare();
  },

  _prepare: function() {
    var tree = this.props.tree;

    this.state = {
      tree: tree
    };
  },

  getInitialState: function() {
    return {
      tree: null
    };
  },

  render: function() {
    var tree = this.state.tree;
    var childNodes = tree.getChildren("root");

    var childEls = childNodes.map(function(node) {
      return $$(TreeNode, {
        treeComp: this,
        key: node.id,
        node: node
      });
    }.bind(this));
    return $$("div", {className: 'tree-list-component'}, childEls);
  }
});

module.exports = Tree;<commit_msg>use subjects work names inside writer's to<commit_after>var $$ = React.createElement;

var _ = require("substance/helpers");

// Tree Node Component
// ---------------

var TreeNode = React.createClass({
  displayName: "TreeNode",

  handleToggle: function(e) {
    var node = this.props.node;
    node.handleToggle(node.id);
    e.preventDefault();
  },

  render: function() {
    var node = this.props.node;
    var treeComp = this.props.treeComp;
    var tree = treeComp.props.tree;
    var childNodes = tree.getChildren(node.id);

    var childrenEls = [];

    childrenEls = childNodes.map(function(node) {
      return $$(TreeNode, {
        treeComp: treeComp,
        key: node.id,
        node: node
      });
    }.bind(this));

    _.each(this.props.children, function(childNode) {
      childrenEls($$(TreeNode, {
        node: childNode
      }));
    });

    return $$("div", {className: 'tree-node'+ (node.active ? ' selected' : '')},
      $$('a', {
        href: "#",
        className: 'name',
        "data-id": node.id,
        onClick: this.handleToggle,
      }, node.workname),
      $$('div', {className: 'children'}, childrenEls)
    );
  }
});

// Tree Component
// ---------------

var Tree = React.createClass({
  displayName: "Tree",

  componentWillMount: function() {
    this._prepare();
  },

  _prepare: function() {
    var tree = this.props.tree;

    this.state = {
      tree: tree
    };
  },

  getInitialState: function() {
    return {
      tree: null
    };
  },

  render: function() {
    var tree = this.state.tree;
    var childNodes = tree.getChildren("root");

    var childEls = childNodes.map(function(node) {
      return $$(TreeNode, {
        treeComp: this,
        key: node.id,
        node: node
      });
    }.bind(this));
    return $$("div", {className: 'tree-list-component'}, childEls);
  }
});

module.exports = Tree;<|endoftext|>


<commit_before>const KabaScss = require("kaba-scss");
const kleur = require("kleur");
const Logger = require("../Logger");
const path = require("path");

class SassRunner
{
    /**
     * Constructs a new runner
     * @param {KabaBuildConfig} fullBuildConfig
     * @param {CliConfig} cliConfig
     */
    constructor (fullBuildConfig, cliConfig)
    {
        /**
         * @private
         * @type {SassBuildConfig}
         */
        this.buildConfig = fullBuildConfig.sass;

        /**
         * @private
         * @type {CliConfig}
         */
        this.cliConfig = cliConfig;

        /**
         * @private
         * @type {Logger}
         */
        this.logger = new Logger(kleur.bgMagenta.black(" Sass "));

        /**
         * @private
         * @type {?KabaScss}
         */
        this.compiler = null;
    }

    /**
     * Runs the actual runner
     *
     * @return {Promise<boolean>} whether the build was successful and error-free
     */
    async run ()
    {
        const entries = Object.keys(this.buildConfig.entries);

        // skip if no entries set
        if (entries.length === 0)
        {
            return true;
        }

        this.compiler = new KabaScss({
            isDebug: this.cliConfig.isDebug(),
            includeSourceMaps: this.cliConfig.includeSourceMaps(),
            isWatch: this.cliConfig.isWatch(),
            lint: this.cliConfig.isLint(),
            analyze: this.cliConfig.isAnalyze(),
            cwd: this.buildConfig.cwd,
            browserList: this.buildConfig.browserList,
            fix: this.cliConfig.isFix(),
        }, this.logger);

        entries.forEach(
            name =>
            {
                const src = this.buildConfig.entries[name];
                const outputPath = `${this.buildConfig.outputPath}/${name}.css`;

                this.compiler.addEntry(src, path.dirname(outputPath), path.basename(outputPath));
            }
        );

        return this.compiler.run();
    }

    /**
     * Stops the runner
     */
    stop ()
    {
        if (this.compiler !== null)
        {
            this.compiler.stop();
        }
    }
}

module.exports = SassRunner;
<commit_msg>Lazy load kaba-scss<commit_after>const kleur = require("kleur");
const Logger = require("../Logger");
const path = require("path");

class SassRunner
{
    /**
     * Constructs a new runner
     * @param {KabaBuildConfig} fullBuildConfig
     * @param {CliConfig} cliConfig
     */
    constructor (fullBuildConfig, cliConfig)
    {
        /**
         * @private
         * @type {SassBuildConfig}
         */
        this.buildConfig = fullBuildConfig.sass;

        /**
         * @private
         * @type {CliConfig}
         */
        this.cliConfig = cliConfig;

        /**
         * @private
         * @type {Logger}
         */
        this.logger = new Logger(kleur.bgMagenta.black(" Sass "));

        /**
         * @private
         * @type {?KabaScss}
         */
        this.compiler = null;
    }

    /**
     * Runs the actual runner
     *
     * @return {Promise<boolean>} whether the build was successful and error-free
     */
    async run ()
    {
        const entries = Object.keys(this.buildConfig.entries);
        // lazy load it as it is optional
        const KabaScss = require("kaba-scss");

        // skip if no entries set
        if (entries.length === 0)
        {
            return true;
        }

        this.compiler = new KabaScss({
            isDebug: this.cliConfig.isDebug(),
            includeSourceMaps: this.cliConfig.includeSourceMaps(),
            isWatch: this.cliConfig.isWatch(),
            lint: this.cliConfig.isLint(),
            analyze: this.cliConfig.isAnalyze(),
            cwd: this.buildConfig.cwd,
            browserList: this.buildConfig.browserList,
            fix: this.cliConfig.isFix(),
        }, this.logger);

        entries.forEach(
            name =>
            {
                const src = this.buildConfig.entries[name];
                const outputPath = `${this.buildConfig.outputPath}/${name}.css`;

                this.compiler.addEntry(src, path.dirname(outputPath), path.basename(outputPath));
            }
        );

        return this.compiler.run();
    }

    /**
     * Stops the runner
     */
    stop ()
    {
        if (this.compiler !== null)
        {
            this.compiler.stop();
        }
    }
}

module.exports = SassRunner;
<|endoftext|>