<commit_before>import platform from '../util/platform'
import substanceGlobals from '../util/substanceGlobals'
import ClipboardImporter from '../model/ClipboardImporter'
import ClipboardExporter from '../model/ClipboardExporter'

export default class AbstractClipboard {
  constructor (configurator) {
    let schema = configurator.getSchema()
    let converterRegistry = configurator.converterRegistry
    let htmlConverters = []
    if (converterRegistry && converterRegistry.contains('html')) {
      htmlConverters = converterRegistry.get('html').values() || []
    }
    // Note: this config object is used for creating
    // ClipboardImporter and ClipboardExporter
    this._config = {
      schema: schema,
      DocumentClass: schema.getDocumentClass(),
      converters: htmlConverters,
      editorOptions: configurator.getEditorOptions()
    }
  }

  /*
    Called when copy event fired.

    @param {Event} event
  */
  onCopy (event) {
    // console.log("Clipboard.onCopy", arguments);
    let clipboardData = this._copy()
    substanceGlobals._clipboardData = event.clipboardData

    if (event.clipboardData && clipboardData.doc) {
      event.preventDefault()
      // store as plain text and html
      event.clipboardData.setData('text/plain', clipboardData.text)
      // WORKAROUND: under IE and Edge it is not permitted to set 'text/html'
      if (!platform.isIE && !platform.isEdge) {
        event.clipboardData.setData('text/html', clipboardData.html)
      }
    }
  }

  /*
    Called when cut event fired.

    @param {Event} event
  */
  onCut (event) {
    // preventing default behavior to avoid that contenteditable destroys our DOM
    event.preventDefault()
    // console.log("Clipboard.onCut", arguments);
    this.onCopy(event)
    this._cut()
  }

  /*
    Called when paste event fired.

    @param {Event} event
  */
  // Works on Safari/Chrome/FF
  onPaste (event) {
    let clipboardData = event.clipboardData

    let types = {}
    for (let i = 0; i < clipboardData.types.length; i++) {
      types[clipboardData.types[i]] = true
    }
    // console.log('onPaste(): received content types', types);

    event.preventDefault()
    event.stopPropagation()

    let plainText
    let html
    if (types['text/plain']) {
      plainText = clipboardData.getData('text/plain')
    }
    if (types['text/html']) {
      html = clipboardData.getData('text/html')
    }

    // HACK: to allow at least in app copy and paste under Edge (which blocks HTML)
    // we guess by comparing the old and new plain text
    if (platform.isEdge &&
        substanceGlobals.clipboardData &&
        substanceGlobals.clipboardData.text === plainText) {
      html = substanceGlobals.clipboardData.html
    } else {
      substanceGlobals.clipboardData = {
        text: plainText,
        html: html
      }
    }

    // console.log('onPaste(): html = ', html);

    // WORKAROUND: FF does not provide HTML coming in from other applications
    // so fall back to pasting plain text
    if (platform.isFF && !html) {
      this._pastePlainText(plainText)
      return
    }

    // if we have content given as HTML we let the importer assess the quality first
    // and fallback to plain text import if it's bad
    if (html) {
      if (!this._pasteHtml(html, plainText)) {
        this._pastePlainText(plainText)
      }
    } else {
      this._pastePlainText(plainText)
    }
  }

  _getImporter () {
    return new ClipboardImporter(this._config)
  }

  _getExporter () {
    return new ClipboardExporter(this._config)
  }

  /*
    Copies selected content from document returning a new document instance.
  */
  _copy () {
    throw new Error('This method is abstract.')
  }

  /*
    Removes the selected content from the document.
  */
  _cut () {
    throw new Error('This method is abstract.')
  }

  /*
    Pastes a given plain text into the editor.

    @param {String} plainText plain text
  */
  _pastePlainText(plainText) { // eslint-disable-line
    throw new Error('This method is abstract.')
  }

  /*
    Pastes a given parsed html document into the surface.

    @param {ui/DOMElement} docElement
    @param {String} text plain text representation used as a fallback
  */
  _pasteHtml(html, text) { // eslint-disable-line
    throw new Error('This method is abstract.')
  }
}
<commit_msg>Edge now allows for HTML clipboard content<commit_after>import platform from '../util/platform'
import substanceGlobals from '../util/substanceGlobals'
import ClipboardImporter from '../model/ClipboardImporter'
import ClipboardExporter from '../model/ClipboardExporter'

export default class AbstractClipboard {
  constructor (configurator) {
    let schema = configurator.getSchema()
    let converterRegistry = configurator.converterRegistry
    let htmlConverters = []
    if (converterRegistry && converterRegistry.contains('html')) {
      htmlConverters = converterRegistry.get('html').values() || []
    }
    // Note: this config object is used for creating
    // ClipboardImporter and ClipboardExporter
    this._config = {
      schema: schema,
      DocumentClass: schema.getDocumentClass(),
      converters: htmlConverters,
      editorOptions: configurator.getEditorOptions()
    }
  }

  /*
    Called when copy event fired.

    @param {Event} event
  */
  onCopy (event) {
    // console.log("Clipboard.onCopy", arguments);
    let clipboardData = this._copy()
    substanceGlobals._clipboardData = event.clipboardData

    if (event.clipboardData && clipboardData.doc) {
      event.preventDefault()
      // store as plain text and html
      event.clipboardData.setData('text/plain', clipboardData.text)
      event.clipboardData.setData('text/html', clipboardData.html)
    }
  }

  /*
    Called when cut event fired.

    @param {Event} event
  */
  onCut (event) {
    // preventing default behavior to avoid that contenteditable destroys our DOM
    event.preventDefault()
    // console.log("Clipboard.onCut", arguments);
    this.onCopy(event)
    this._cut()
  }

  /*
    Called when paste event fired.

    @param {Event} event
  */
  // Works on Safari/Chrome/FF
  onPaste (event) {
    let clipboardData = event.clipboardData

    let types = {}
    for (let i = 0; i < clipboardData.types.length; i++) {
      types[clipboardData.types[i]] = true
    }
    // console.log('onPaste(): received content types', types);

    event.preventDefault()
    event.stopPropagation()

    let plainText
    let html
    if (types['text/plain']) {
      plainText = clipboardData.getData('text/plain')
    }
    if (types['text/html']) {
      html = clipboardData.getData('text/html')
    }

    substanceGlobals.clipboardData = {
      text: plainText,
      html: html
    }

    // console.log('onPaste(): html = ', html);

    // WORKAROUND: FF does not provide HTML coming in from other applications
    // so fall back to pasting plain text
    if (platform.isFF && !html) {
      this._pastePlainText(plainText)
      return
    }

    // if we have content given as HTML we let the importer assess the quality first
    // and fallback to plain text import if it's bad
    if (html) {
      if (!this._pasteHtml(html, plainText)) {
        this._pastePlainText(plainText)
      }
    } else {
      this._pastePlainText(plainText)
    }
  }

  _getImporter () {
    return new ClipboardImporter(this._config)
  }

  _getExporter () {
    return new ClipboardExporter(this._config)
  }

  /*
    Copies selected content from document returning a new document instance.
  */
  _copy () {
    throw new Error('This method is abstract.')
  }

  /*
    Removes the selected content from the document.
  */
  _cut () {
    throw new Error('This method is abstract.')
  }

  /*
    Pastes a given plain text into the editor.

    @param {String} plainText plain text
  */
  _pastePlainText(plainText) { // eslint-disable-line
    throw new Error('This method is abstract.')
  }

  /*
    Pastes a given parsed html document into the surface.

    @param {ui/DOMElement} docElement
    @param {String} text plain text representation used as a fallback
  */
  _pasteHtml(html, text) { // eslint-disable-line
    throw new Error('This method is abstract.')
  }
}
<|endoftext|>


<commit_before>import "babel-polyfill";
import expect from 'expect.js';

import TelegramBotApi from './telegram-bot-methods';

const
token = process.env.TEST_TOKEN || '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
userId = process.env.TEST_USERID || 777000,

expectToBePromise = (obj) => {
  expect(obj).to.be.an('object');
  expect(obj).to.have.property('then');
  expect(obj.then).to.be.a('function');
}
;

describe('telegram-bot-methods', () => {
  var bot;

  describe('new instance', () => {

    it('should an constructor', () => {
      expect(TelegramBotApi).to.be.a('function');
      expect(new TelegramBotApi()).to.be.an('object');
    });

    it('should have token', () => {
      let bot = new TelegramBotApi(token);
      expect(bot.token).to.be.equal(token);
    });

    it('should have not token by default', () => {
      let bot = new TelegramBotApi();
      expect(bot.token).to.be.empty();
    });

    it('should not have any option', () => {
      let bot = new TelegramBotApi(token, {});
      expect(bot.options).to.be(undefined);
    });

  });

  describe('makeUrl', () => {

    it('should exist', () => {
      let bot = new TelegramBotApi('123456');
      expect(bot).to.have.property('makeUrl');
    });

    it('should return correct url', () => {
      let bot = new TelegramBotApi('123456');
      expect(bot.makeUrl('getMe')).to.be.equal('https://api.telegram.org/bot123456/getMe');
    });
  });

  before(() => {
    bot = new TelegramBotApi(token);
    return bot;
  });

  describe('query', () => {

    it('should exist', () => {
      expect(bot).to.have.property('query');
    });

    it('should a function', () => {
      expect(bot.query).to.be.a('function');
    });

    it('should return promise', () => {
      var queryRes = bot.query('getMe', {});
      expectToBePromise(queryRes);
    })

    it('should work with getMe', (done) => {
      bot.query('getMe', {})
      .then((data) => {
        expect(data).to.be.ok();
        done();
      }, done);
    });

    it('should return pased json', (done) => {
      bot.query('getMe', {})
      .then((data) => {
        expect(data).to.be.an('object');
        expect(data).to.have.property('ok');
        done();
      })
      .catch(done);
    });

    it('should send text message', (done) => {
      bot.query('sendMessage', {
        chat_id: userId,
        text: 'Test bot.js',
        disable_notification: true
      })
      .then((data) => {
        expect(data).to.be.an('object');
        expect(data).to.have.property('ok');
        done();
      }, done);
    });

  });

  describe('methods', () => {
    let methods = [
      'getMe',
      'sendMessage',
      'forwardMessage',
      'sendPhoto',
      'sendAudio',
      'sendDocument',
      'sendSticker',
      'sendVideo',
      'sendVoice',
      'sendLocation',
      'sendVenue',
      'sendContact',
      'sendChatAction',
      'getUserProfilePhotos',
      'getFile',
      'kickChatMember',
      'unbanChatMember',
      'answerCallbackQuery',
      'editMessageText',
      'editMessageCaption',
      'editMessageReplyMarkup',
      'answerInlineQuery'
    ];
    methods.forEach((method) => {
      it(`should ${method} exist.`, () => {
        expect(bot).to.have.property(method);
      })
    });

    it('should sendMessage work', (done) => {
      bot.sendMessage({
        chat_id: userId+'',
        text: 'Test2 bot.js',
        disable_notification: true
      })
      .then((data) => {
        expect(data).to.be.an('object');
        expect(data).to.have.property('ok');
        done();
      }, done);
    });

    it('should sendMessage with userId as a number', (done) => {
      bot.sendMessage({
        chat_id: parseInt(userId),
        text: 'Test3 bot.js',
        disable_notification: true
      })
      .then((data) => {
        expect(data).to.be.an('object');
        expect(data).to.have.property('ok');
        done();
      }, done);
    });
  });

});
<commit_msg>test(methods): add options test<commit_after>import "babel-polyfill";
import expect from 'expect.js';

import TelegramBotApi from './telegram-bot-methods';

const
token = process.env.TEST_TOKEN || '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
userId = process.env.TEST_USERID || 777000,

expectToBePromise = (obj) => {
  expect(obj).to.be.an('object');
  expect(obj).to.have.property('then');
  expect(obj.then).to.be.a('function');
}
;

describe('telegram-bot-methods', () => {
  var bot;

  describe('new instance', () => {

    it('should an constructor', () => {
      expect(TelegramBotApi).to.be.a('function');
      expect(new TelegramBotApi()).to.be.an('object');
    });

    it('should have token', () => {
      let bot = new TelegramBotApi(token);
      expect(bot.token).to.be.equal(token);
    });

    it('should have not token by default', () => {
      let bot = new TelegramBotApi();
      expect(bot.token).to.be.empty();
    });

    it('should can change super options like gzip', () => {
      let bot = new TelegramBotApi(token, {gzip: false});
      expect(bot.options.gzip).to.be.equal(false);
    });

    it('should can have option', () => {
      let bot = new TelegramBotApi(token, {junk: 10});
      expect(bot.options.junk).to.be(10);
    });

  });

  describe('makeUrl', () => {

    it('should exist', () => {
      let bot = new TelegramBotApi('123456');
      expect(bot).to.have.property('makeUrl');
    });

    it('should return correct url', () => {
      let bot = new TelegramBotApi('123456');
      expect(bot.makeUrl('getMe')).to.be.equal('https://api.telegram.org/bot123456/getMe');
    });
  });

  before(() => {
    bot = new TelegramBotApi(token);
    return bot;
  });

  describe('query', () => {

    it('should exist', () => {
      expect(bot).to.have.property('query');
    });

    it('should a function', () => {
      expect(bot.query).to.be.a('function');
    });

    it('should return promise', () => {
      var queryRes = bot.query('getMe', {});
      expectToBePromise(queryRes);
    })

    it('should work with getMe', (done) => {
      bot.query('getMe', {})
      .then((data) => {
        expect(data).to.be.ok();
        done();
      }, done);
    });

    it('should return pased json', (done) => {
      bot.query('getMe', {})
      .then((data) => {
        expect(data).to.be.an('object');
        expect(data).to.have.property('ok');
        done();
      })
      .catch(done);
    });

    it('should send text message', (done) => {
      bot.query('sendMessage', {
        chat_id: userId,
        text: 'Test bot.js',
        disable_notification: true
      })
      .then((data) => {
        expect(data).to.be.an('object');
        expect(data).to.have.property('ok');
        done();
      }, done);
    });

  });

  describe('methods', () => {
    let methods = [
      'getMe',
      'sendMessage',
      'forwardMessage',
      'sendPhoto',
      'sendAudio',
      'sendDocument',
      'sendSticker',
      'sendVideo',
      'sendVoice',
      'sendLocation',
      'sendVenue',
      'sendContact',
      'sendChatAction',
      'getUserProfilePhotos',
      'getFile',
      'kickChatMember',
      'unbanChatMember',
      'answerCallbackQuery',
      'editMessageText',
      'editMessageCaption',
      'editMessageReplyMarkup',
      'answerInlineQuery'
    ];
    methods.forEach((method) => {
      it(`should ${method} exist.`, () => {
        expect(bot).to.have.property(method);
      })
    });

    it('should sendMessage work', (done) => {
      bot.sendMessage({
        chat_id: userId+'',
        text: 'Test2 bot.js',
        disable_notification: true
      })
      .then((data) => {
        expect(data).to.be.an('object');
        expect(data).to.have.property('ok');
        done();
      }, done);
    });

    it('should sendMessage with userId as a number', (done) => {
      bot.sendMessage({
        chat_id: parseInt(userId),
        text: 'Test3 bot.js',
        disable_notification: true
      })
      .then((data) => {
        expect(data).to.be.an('object');
        expect(data).to.have.property('ok');
        done();
      }, done);
    });
  });

});
<|endoftext|>


<commit_before>/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
 * Use of this file is governed by the BSD 3-clause license that
 * can be found in the LICENSE.txt file in the project root.
 */

/*jslint smarttabs:true */

var Token = require('./Token').Token;

/* stop is not included! */
function Interval(start, stop) {
	this.start = start;
	this.stop = stop;
	return this;
}

Interval.prototype.contains = function(item) {
	return item >= this.start && item < this.stop;
};

Interval.prototype.toString = function() {
	if(this.start===this.stop-1) {
		return this.start.toString();
	} else {
		return this.start.toString() + ".." + (this.stop-1).toString();
	}
};

Object.defineProperty(Interval.prototype, "length", {
	get : function() {
		return this.stop - this.start;
	}
});

function IntervalSet() {
	this.intervals = null;
	this.readOnly = false;
}

IntervalSet.prototype.first = function(v) {
	if (this.intervals === null || this.intervals.length===0) {
		return Token.INVALID_TYPE;
	} else {
		return this.intervals[0].start;
	}
};

IntervalSet.prototype.addOne = function(v) {
	this.addInterval(new Interval(v, v + 1));
};

IntervalSet.prototype.addRange = function(l, h) {
	this.addInterval(new Interval(l, h + 1));
};

IntervalSet.prototype.addInterval = function(v) {
	if (this.intervals === null) {
		this.intervals = [];
		this.intervals.push(v);
	} else {
		// find insert pos
		for (var k = 0; k < this.intervals.length; k++) {
			var i = this.intervals[k];
			// distinct range -> insert
			if (v.stop < i.start) {
				this.intervals.splice(k, 0, v);
				return;
			}
			// contiguous range -> adjust
			else if (v.stop === i.start) {
				this.intervals[k].start = v.start;
				return;
			}
			// overlapping range -> adjust and reduce
			else if (v.start <= i.stop) {
				this.intervals[k] = new Interval(Math.min(i.start, v.start), Math.max(i.stop, v.stop));
				this.reduce(k);
				return;
			}
		}
		// greater than any existing
		this.intervals.push(v);
	}
};

IntervalSet.prototype.addSet = function(other) {
	if (other.intervals !== null) {
		for (var k = 0; k < other.intervals.length; k++) {
			var i = other.intervals[k];
			this.addInterval(new Interval(i.start, i.stop));
		}
	}
	return this;
};

IntervalSet.prototype.reduce = function(k) {
	// only need to reduce if k is not the last
	if (k < this.intervalslength - 1) {
		var l = this.intervals[k];
		var r = this.intervals[k + 1];
		// if r contained in l
		if (l.stop >= r.stop) {
			this.intervals.pop(k + 1);
			this.reduce(k);
		} else if (l.stop >= r.start) {
			this.intervals[k] = new Interval(l.start, r.stop);
			this.intervals.pop(k + 1);
		}
	}
};

IntervalSet.prototype.complement = function(start, stop) {
    var result = new IntervalSet();
    result.addInterval(new Interval(start,stop+1));
    for(var i=0; i<this.intervals.length; i++) {
        result.removeRange(this.intervals[i]);
    }
    return result;
};

IntervalSet.prototype.contains = function(item) {
	if (this.intervals === null) {
		return false;
	} else {
		for (var k = 0; k < this.intervals.length; k++) {
			if(this.intervals[k].contains(item)) {
				return true;
			}
		}
		return false;
	}
};

Object.defineProperty(IntervalSet.prototype, "length", {
	get : function() {
		var len = 0;
		this.intervals.map(function(i) {len += i.length;});
		return len;
	}
});

IntervalSet.prototype.removeRange = function(v) {
    if(v.start===v.stop-1) {
        this.removeOne(v.start);
    } else if (this.intervals!==null) {
        var k = 0;
        for(var n=0; n<this.intervals.length; n++) {
            var i = this.intervals[k];
            // intervals are ordered
            if (v.stop<=i.start) {
                return;
            }
            // check for including range, split it
            else if(v.start>i.start && v.stop<i.stop) {
                this.intervals[k] = new Interval(i.start, v.start);
                var x = new Interval(v.stop, i.stop);
                this.intervals.splice(k, 0, x);
                return;
            }
            // check for included range, remove it
            else if(v.start<=i.start && v.stop>=i.stop) {
                this.intervals.splice(k, 1);
                k = k - 1; // need another pass
            }
            // check for lower boundary
            else if(v.start<i.stop) {
                this.intervals[k] = new Interval(i.start, v.start);
            }
            // check for upper boundary
            else if(v.stop<i.stop) {
                this.intervals[k] = new Interval(v.stop, i.stop);
            }
            k += 1;
        }
    }
};

IntervalSet.prototype.removeOne = function(v) {
	if (this.intervals !== null) {
		for (var k = 0; k < this.intervals.length; k++) {
			var i = this.intervals[k];
			// intervals is ordered
			if (v < i.start) {
				return;
			}
			// check for single value range
			else if (v === i.start && v === i.stop - 1) {
				this.intervals.splice(k, 1);
				return;
			}
			// check for lower boundary
			else if (v === i.start) {
				this.intervals[k] = new Interval(i.start + 1, i.stop);
				return;
			}
			// check for upper boundary
			else if (v === i.stop - 1) {
				this.intervals[k] = new Interval(i.start, i.stop - 1);
				return;
			}
			// split existing range
			else if (v < i.stop - 1) {
				var x = new Interval(i.start, v);
				i.start = v + 1;
				this.intervals.splice(k, 0, x);
				return;
			}
		}
	}
};

IntervalSet.prototype.toString = function(literalNames, symbolicNames, elemsAreChar) {
	literalNames = literalNames || null;
	symbolicNames = symbolicNames || null;
	elemsAreChar = elemsAreChar || false;
	if (this.intervals === null) {
		return "{}";
	} else if(literalNames!==null || symbolicNames!==null) {
		return this.toTokenString(literalNames, symbolicNames);
	} else if(elemsAreChar) {
		return this.toCharString();
	} else {
		return this.toIndexString();
	}
};

IntervalSet.prototype.toCharString = function() {
	var names = [];
	for (var i = 0; i < this.intervals.length; i++) {
		var v = this.intervals[i];
		if(v.stop===v.start+1) {
			if ( v.start===Token.EOF ) {
				names.push("<EOF>");
			} else {
				names.push("'" + String.fromCharCode(v.start) + "'");
			}
		} else {
			names.push("'" + String.fromCharCode(v.start) + "'..'" + String.fromCharCode(v.stop-1) + "'");
		}
	}
	if (names.length > 1) {
		return "{" + names.join(", ") + "}";
	} else {
		return names[0];
	}
};

IntervalSet.prototype.toIndexString = function() {
	var names = [];
	for (var i = 0; i < this.intervals.length; i++) {
		var v = this.intervals[i];
		if(v.stop===v.start+1) {
			if ( v.start===Token.EOF ) {
				names.push("<EOF>");
			} else {
				names.push(v.start.toString());
			}
		} else {
			names.push(v.start.toString() + ".." + (v.stop-1).toString());
		}
	}
	if (names.length > 1) {
		return "{" + names.join(", ") + "}";
	} else {
		return names[0];
	}
};

IntervalSet.prototype.toTokenString = function(literalNames, symbolicNames) {
	var names = [];
	for (var i = 0; i < this.intervals.length; i++) {
		var v = this.intervals[i];
		for (var j = v.start; j < v.stop; j++) {
			names.push(this.elementName(literalNames, symbolicNames, j));
		}
	}
	if (names.length > 1) {
		return "{" + names.join(", ") + "}";
	} else {
		return names[0];
	}
};

IntervalSet.prototype.elementName = function(literalNames, symbolicNames, a) {
	if (a === Token.EOF) {
		return "<EOF>";
	} else if (a === Token.EPSILON) {
		return "<EPSILON>";
	} else {
		return literalNames[a] || symbolicNames[a];
	}
};

exports.Interval = Interval;
exports.IntervalSet = IntervalSet;
<commit_msg>refactored IntervalSet.js to use es6 classes use const/let for better scoping<commit_after>/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
 * Use of this file is governed by the BSD 3-clause license that
 * can be found in the LICENSE.txt file in the project root.
 */

const {Token} = require('./Token');

/* stop is not included! */
class Interval {
	constructor(start, stop) {
		this.start = start;
		this.stop = stop;
	}

	contains(item) {
		return item >= this.start && item < this.stop;
	}

	toString() {
		if(this.start===this.stop-1) {
			return this.start.toString();
		} else {
			return this.start.toString() + ".." + (this.stop-1).toString();
		}
	}

	get length(){
		return this.stop - this.start;
	}
}

class IntervalSet {
	constructor() {
		this.intervals = null;
		this.readOnly = false;
	}

	first(v) {
		if (this.intervals === null || this.intervals.length===0) {
			return Token.INVALID_TYPE;
		} else {
			return this.intervals[0].start;
		}
	}

	addOne(v) {
		this.addInterval(new Interval(v, v + 1));
	}

	addRange(l, h) {
		this.addInterval(new Interval(l, h + 1));
	}

	addInterval(v) {
		if (this.intervals === null) {
			this.intervals = [];
			this.intervals.push(v);
		} else {
			// find insert pos
			for (let k = 0; k < this.intervals.length; k++) {
				const i = this.intervals[k];
				// distinct range -> insert
				if (v.stop < i.start) {
					this.intervals.splice(k, 0, v);
					return;
				}
				// contiguous range -> adjust
				else if (v.stop === i.start) {
					this.intervals[k].start = v.start;
					return;
				}
				// overlapping range -> adjust and reduce
				else if (v.start <= i.stop) {
					this.intervals[k] = new Interval(Math.min(i.start, v.start), Math.max(i.stop, v.stop));
					this.reduce(k);
					return;
				}
			}
			// greater than any existing
			this.intervals.push(v);
		}
	}

	addSet(other) {
		if (other.intervals !== null) {
			for (let k = 0; k < other.intervals.length; k++) {
				const i = other.intervals[k];
				this.addInterval(new Interval(i.start, i.stop));
			}
		}
		return this;
	}

	reduce(k) {
		// only need to reduce if k is not the last
		if (k < this.intervalslength - 1) {
			const l = this.intervals[k];
			const r = this.intervals[k + 1];
			// if r contained in l
			if (l.stop >= r.stop) {
				this.intervals.pop(k + 1);
				this.reduce(k);
			} else if (l.stop >= r.start) {
				this.intervals[k] = new Interval(l.start, r.stop);
				this.intervals.pop(k + 1);
			}
		}
	}

	complement(start, stop) {
		const result = new IntervalSet();
		result.addInterval(new Interval(start,stop+1));
		for(let i=0; i<this.intervals.length; i++) {
			result.removeRange(this.intervals[i]);
		}
		return result;
	}

	contains(item) {
		if (this.intervals === null) {
			return false;
		} else {
			for (let k = 0; k < this.intervals.length; k++) {
				if(this.intervals[k].contains(item)) {
					return true;
				}
			}
			return false;
		}
	}

	removeRange(v) {
		if(v.start===v.stop-1) {
			this.removeOne(v.start);
		} else if (this.intervals!==null) {
			let k = 0;
			for(let n=0; n<this.intervals.length; n++) {
				const i = this.intervals[k];
				// intervals are ordered
				if (v.stop<=i.start) {
					return;
				}
				// check for including range, split it
				else if(v.start>i.start && v.stop<i.stop) {
					this.intervals[k] = new Interval(i.start, v.start);
					const x = new Interval(v.stop, i.stop);
					this.intervals.splice(k, 0, x);
					return;
				}
				// check for included range, remove it
				else if(v.start<=i.start && v.stop>=i.stop) {
					this.intervals.splice(k, 1);
					k = k - 1; // need another pass
				}
				// check for lower boundary
				else if(v.start<i.stop) {
					this.intervals[k] = new Interval(i.start, v.start);
				}
				// check for upper boundary
				else if(v.stop<i.stop) {
					this.intervals[k] = new Interval(v.stop, i.stop);
				}
				k += 1;
			}
		}
	}

	removeOne(v) {
		if (this.intervals !== null) {
			for (let k = 0; k < this.intervals.length; k++) {
				const i = this.intervals[k];
				// intervals is ordered
				if (v < i.start) {
					return;
				}
				// check for single value range
				else if (v === i.start && v === i.stop - 1) {
					this.intervals.splice(k, 1);
					return;
				}
				// check for lower boundary
				else if (v === i.start) {
					this.intervals[k] = new Interval(i.start + 1, i.stop);
					return;
				}
				// check for upper boundary
				else if (v === i.stop - 1) {
					this.intervals[k] = new Interval(i.start, i.stop - 1);
					return;
				}
				// split existing range
				else if (v < i.stop - 1) {
					const x = new Interval(i.start, v);
					i.start = v + 1;
					this.intervals.splice(k, 0, x);
					return;
				}
			}
		}
	}

	toString(literalNames, symbolicNames, elemsAreChar) {
		literalNames = literalNames || null;
		symbolicNames = symbolicNames || null;
		elemsAreChar = elemsAreChar || false;
		if (this.intervals === null) {
			return "{}";
		} else if(literalNames!==null || symbolicNames!==null) {
			return this.toTokenString(literalNames, symbolicNames);
		} else if(elemsAreChar) {
			return this.toCharString();
		} else {
			return this.toIndexString();
		}
	}

	toCharString() {
		const names = [];
		for (let i = 0; i < this.intervals.length; i++) {
			const v = this.intervals[i];
			if(v.stop===v.start+1) {
				if ( v.start===Token.EOF ) {
					names.push("<EOF>");
				} else {
					names.push("'" + String.fromCharCode(v.start) + "'");
				}
			} else {
				names.push("'" + String.fromCharCode(v.start) + "'..'" + String.fromCharCode(v.stop-1) + "'");
			}
		}
		if (names.length > 1) {
			return "{" + names.join(", ") + "}";
		} else {
			return names[0];
		}
	}

	toIndexString() {
		const names = [];
		for (let i = 0; i < this.intervals.length; i++) {
			const v = this.intervals[i];
			if(v.stop===v.start+1) {
				if ( v.start===Token.EOF ) {
					names.push("<EOF>");
				} else {
					names.push(v.start.toString());
				}
			} else {
				names.push(v.start.toString() + ".." + (v.stop-1).toString());
			}
		}
		if (names.length > 1) {
			return "{" + names.join(", ") + "}";
		} else {
			return names[0];
		}
	}

	toTokenString(literalNames, symbolicNames) {
		const names = [];
		for (let i = 0; i < this.intervals.length; i++) {
			const v = this.intervals[i];
			for (let j = v.start; j < v.stop; j++) {
				names.push(this.elementName(literalNames, symbolicNames, j));
			}
		}
		if (names.length > 1) {
			return "{" + names.join(", ") + "}";
		} else {
			return names[0];
		}
	}

	elementName(literalNames, symbolicNames, a) {
		if (a === Token.EOF) {
			return "<EOF>";
		} else if (a === Token.EPSILON) {
			return "<EPSILON>";
		} else {
			return literalNames[a] || symbolicNames[a];
		}
	}

	get length(){
		let len = 0;
		this.intervals.map(function(i) {len += i.length;});
		return len;
	}
}

module.exports = {
	Interval,
	IntervalSet
};
<|endoftext|>


<commit_before>var version = require('./package.json').version;
var BowerWebpackPlugin = require("bower-webpack-plugin");

// Custom webpack loaders are generally the same for all webpack bundles, hence
// stored in a separate local variable.
var loaders = [
  { test: /\.json$/, loader: 'json-loader' },
  { test: /\.css$/, loader: "style-loader!css-loader" },
  { test: /\.jpe?g$|\.gif$|\.png$|\.svg$|\.woff(\?.*)$|\.eot(\?.*)$|\.woff2(\?.*)$|\.ttf(\?.*)$|\.wav$|\.mp3$/, loader: "file-loader" }
];

module.exports = [
  {// Notebook extension
    //
    // This bundle only contains the part of the JavaScript that is run on
    // load of the notebook. This section generally only performs
    // some configuration for requirejs, and provides the legacy
    // "load_ipython_extension" function which is required for any notebook
    // extension.
    //
    entry: './src/extension.js',
    output: {
      filename: 'extension.js',
      path: '../beakerx/static',
      libraryTarget: 'amd'
    },
    externals: [
      'services/config',
      'services/kernels/comm',
      'base/js/utils',
      'base/js/namespace',
      'base/js/events',
      'require'
    ]
  },
  {// Bundle for the notebook containing the custom widget views and models
    //
    // This bundle contains the implementation for the custom widget views and
    // custom widget.
    // It must be an amd module
    //
    entry: './src/index.js',
    output: {
      filename: 'index.js',
      path: '../beakerx/static',
      libraryTarget: 'amd'
    },
    devtool: 'source-map',
    module: {
      loaders: loaders
    },
    resolve: {
      modulesDirectories: ['web_modules', 'node_modules', 'bower_components'],
      extensions: ['.jsx','.js','.less','.css','']
    },
    plugins: [
      new BowerWebpackPlugin({
        modulesDirectories: ["bower_components"],
        manifestFiles:      "bower.json",
        includes:           /.*/,
        excludes:           [],
        searchResolveModulesDirectories: true
      })
    ],
    externals: ['jupyter-js-widgets']
  },
  {// Embeddable beakerx bundle
    //
    // This bundle is generally almost identical to the notebook bundle
    // containing the custom widget views and models.
    //
    // The only difference is in the configuration of the webpack public path
    // for the static assets.
    //
    // It will be automatically distributed by unpkg to work with the static
    // widget embedder.
    //
    // The target bundle is always `dist/index.js`, which is the path required
    // by the custom widget embedder.
    //
    entry: './src/embed.js',
    output: {
      filename: 'index.js',
      path: './dist/',
      libraryTarget: 'amd',
      publicPath: 'https://unpkg.com/beakerx@' + version + '/dist/'
    },
    devtool: 'source-map',
    module: {
      loaders: loaders
    },
    resolve: {
      modulesDirectories: ['web_modules', 'node_modules', 'bower_components'],
      extensions: ['.jsx','.js','.less','.css','']
    },
    plugins: [
      new BowerWebpackPlugin({
        modulesDirectories: ["bower_components"],
        manifestFiles:      "bower.json",
        includes:           /.*/,
        excludes:           [],
        searchResolveModulesDirectories: true
      })
    ],
    externals: ['jupyter-js-widgets']
  }
];
<commit_msg>add banner<commit_after>/*
 *  Copyright 2017 TWO SIGMA OPEN SOURCE, LLC
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

var version = require('./package.json').version;
var BowerWebpackPlugin = require("bower-webpack-plugin");

// Custom webpack loaders are generally the same for all webpack bundles, hence
// stored in a separate local variable.
var loaders = [
  { test: /\.json$/, loader: 'json-loader' },
  { test: /\.css$/, loader: "style-loader!css-loader" },
  { test: /\.jpe?g$|\.gif$|\.png$|\.svg$|\.woff(\?.*)$|\.eot(\?.*)$|\.woff2(\?.*)$|\.ttf(\?.*)$|\.wav$|\.mp3$/, loader: "file-loader" }
];

module.exports = [
  {// Notebook extension
    //
    // This bundle only contains the part of the JavaScript that is run on
    // load of the notebook. This section generally only performs
    // some configuration for requirejs, and provides the legacy
    // "load_ipython_extension" function which is required for any notebook
    // extension.
    //
    entry: './src/extension.js',
    output: {
      filename: 'extension.js',
      path: '../beakerx/static',
      libraryTarget: 'amd'
    },
    externals: [
      'services/config',
      'services/kernels/comm',
      'base/js/utils',
      'base/js/namespace',
      'base/js/events',
      'require'
    ]
  },
  {// Bundle for the notebook containing the custom widget views and models
    //
    // This bundle contains the implementation for the custom widget views and
    // custom widget.
    // It must be an amd module
    //
    entry: './src/index.js',
    output: {
      filename: 'index.js',
      path: '../beakerx/static',
      libraryTarget: 'amd'
    },
    devtool: 'source-map',
    module: {
      loaders: loaders
    },
    resolve: {
      modulesDirectories: ['web_modules', 'node_modules', 'bower_components'],
      extensions: ['.jsx','.js','.less','.css','']
    },
    plugins: [
      new BowerWebpackPlugin({
        modulesDirectories: ["bower_components"],
        manifestFiles:      "bower.json",
        includes:           /.*/,
        excludes:           [],
        searchResolveModulesDirectories: true
      })
    ],
    externals: ['jupyter-js-widgets']
  },
  {// Embeddable beakerx bundle
    //
    // This bundle is generally almost identical to the notebook bundle
    // containing the custom widget views and models.
    //
    // The only difference is in the configuration of the webpack public path
    // for the static assets.
    //
    // It will be automatically distributed by unpkg to work with the static
    // widget embedder.
    //
    // The target bundle is always `dist/index.js`, which is the path required
    // by the custom widget embedder.
    //
    entry: './src/embed.js',
    output: {
      filename: 'index.js',
      path: './dist/',
      libraryTarget: 'amd',
      publicPath: 'https://unpkg.com/beakerx@' + version + '/dist/'
    },
    devtool: 'source-map',
    module: {
      loaders: loaders
    },
    resolve: {
      modulesDirectories: ['web_modules', 'node_modules', 'bower_components'],
      extensions: ['.jsx','.js','.less','.css','']
    },
    plugins: [
      new BowerWebpackPlugin({
        modulesDirectories: ["bower_components"],
        manifestFiles:      "bower.json",
        includes:           /.*/,
        excludes:           [],
        searchResolveModulesDirectories: true
      })
    ],
    externals: ['jupyter-js-widgets']
  }
];
<|endoftext|>


<commit_before>(function (angular) {
  "use strict";

  angular
    .module("Cerberus.TemplateEditor")
    .service("Cerberus.TemplateEditor.Helper.CSS", CSSHelperService);

  var propertiesWithUnits = {
    top: true,
    right: true,
    bottom: true,
    left: true,
    width: true,
    height: true,
    minHeight: true,
    minWidth: true,
    fontSize: true,
    paddingTop: true,
    paddingRight: true,
    paddingBottom: true,
    paddingLeft: true,
    borderTopLeftRadius: true,
    borderTopRightRadius: true,
    borderBottomLeftRadius: true,
    borderBottomRightRadius: true,
    borderTopWidth: true,
    borderRightWidth: true,
    borderBottomWidth: true,
    borderLeftWidth: true
  };

  function CSSHelperService() {
    //Creates a JSONP object from a CSS declaration
    this.fromCss = function (css) {
      var properties = css.split(";");
      var result = {};

      // Process any default CSS attributes
      _.forEach(properties, function (property) {
        var propertyName = property.split(":", 1)[0];

        if (propertyName && property.length > propertyName.length) {
          var propertyValue = property.substring(propertyName.length + 1).trim();
          //converts hyphenated properties into camelcaseproperties
          //  text-align => textAlign
          //  border-top-left-radius => borderTopLeftRadius
          propertyName = toCamelCase(propertyName);

          result[propertyName] = isUnitProperty(propertyName) ? toUnit(propertyValue) : propertyValue;
        }
      });

      //Special processing for background-image
      if (result["backgroundImage"] !== undefined) {
        var backgroundImage = result["backgroundImage"];
        backgroundImage = backgroundImage.replace(/^url\(/i, "");
        if (backgroundImage[backgroundImage.length - 1] === ')') {
          backgroundImage.length--;
        }

        result["backgroundImage"] = backgroundImage;
      }

      //Special processing for box shadow
      if (result["boxShadow"] !== undefined) {
        result.boxShadow = processShadowData(result["boxShadow"], "hShadow", "vShadow", "blurRadius", "spreadRadius");
      }

      //Special processing for text shadow
      if (result["textShadow"] !== undefined) {
        result.textShadow = processShadowData(result["textShadow"], "hShadow", "vShadow", "blurRadius");
      }

      //Special processing for transform
      if (result["transform"]) {
        var transforms = result["transform"];
        var rotateZ = transforms.match(/rotateZ\([^\)]+\)/i);
        if (rotateZ.length > 0) {
          rotateZ = rotateZ[0].toLowerCase().replace("rotatez(", "").replace(")", "");

          result.transform = {
            rotateZ: toUnit(rotateZ)
          };
        }
      }

      return result;
    };

    this.toCss = function (value) {
      var result = [];

      var propertyName = "";
      var propertyValue = "";
      var color;

      for (var i in value) {
        //Converts camelcase properties into hyphenated properties
        //textAlign => text-align
        //borderTopLeftRadius => border-top-left-radius
        propertyName = i.replace(/([A-Z])/g, "-$1").toLowerCase();

        propertyValue = "";

        //Custom preprocessing
        //TODO: Needs refactoring
        switch (propertyName) {
          case "box-shadow":
            color = value[i]["color"];

            if (color) {
              propertyValue = String.format("{0} {1} {2} {3} {4} {5}",
                color || "",
                value[i]["hShadow"] || "0px",
                value[i]["vShadow"] || "0px",
                value[i]["blurRadius"] || "0px",
                value[i]["spreadRadius"] || "0px",
                ~~value[i]["inset"] ? "inset" : "");
            }

            break;

          case "background-image":
            if (value[i].length > 0) {
              propertyValue = String.format("url({0})", value[i]);
            }
            break;

          case "text-shadow":
            color = value[i]["color"];

            if (color) {
              propertyValue = String.format("{0} {1} {2} {3}",
                color,
                value[i]["hShadow"] || "0px",
                value[i]["vShadow"] || "0px",
                value[i]["blurRadius"] || "0px");
            }
            break;

          case "transform":
            propertyValue = String.format("rotateZ({0})", [value[i].rotateZ.value, value[i].rotateZ.unitType].join(""));
            break;

          default:
            if (propertiesWithUnits[i]) {
              propertyValue = value[i].value;
              if (value[i].unitType) {
                propertyValue += value[i].unitType;
              }
            }
            else {
              propertyValue = value[i];
            }
        }

        if (propertyValue && propertyValue.length > 0) {
          result.push(String.format("{0}:{1}", propertyName, propertyValue));
        }
      }

      return result.join(";");
    };

    function processShadowData(shadowData) {
      var rgbaColorMatchPattern = /rgba?\([^\)]+\)/i,
        hexColorMatchPattern = /#[0-9a-f]{0,6}/i,
        namedColorMatchPattern = /\b[a-z]+/i,
        insetMatchPattern = /inset/i;

      var shadowLayers = shadowData.trim().split(/,(?![^\(]*\))/);
      var result;

      if (shadowLayers.length) {
        var shadow = shadowLayers[0];

        var color = shadow.match(rgbaColorMatchPattern) || shadow.match(hexColorMatchPattern) || shadow.match(namedColorMatchPattern);
        var inset = shadow.match(insetMatchPattern);

        var valuesExcludingColorAndInset = shadow
          .replace(color, "")
          .replace(inset, "")
          .trim()
          .split(" ");

        result = {
          color: color,
          inset: inset
        };

        for (var i = 1; i <= Math.min(arguments.length, valuesExcludingColorAndInset.length); i++) {
          result[arguments[i]] = valuesExcludingColorAndInset[i - 1] || "0";
        }
      }

      return result;
    }

    function toCamelCase(value) {
      return value
        .toLowerCase()
        .replace(/-([A-Z])/gi, function (v) {
          return v[1].toUpperCase();
        })
        .trim();
    }

    function isUnitProperty(propertyName) {
      return propertiesWithUnits[propertyName] !== undefined;
    }

    function toUnit(propertyValue) {
      var unit = {
        value: parseInt(propertyValue),
        unitType: undefined
      };

      if (isNaN(unit.value)) {
        unit.value = propertyValue;
      }
      else {
        unit.unitType = propertyValue.substring(unit.value.toString().length);
      }

      return unit;
    }
  }
})(window.angular);<commit_msg>Minor cleanup<commit_after>(function (angular, _) {
  "use strict";

  angular
    .module("Cerberus.TemplateEditor")
    .service("Cerberus.TemplateEditor.Helper.CSS", CSSHelperService);

  var propertiesWithUnits = {
    top: true,
    right: true,
    bottom: true,
    left: true,
    width: true,
    height: true,
    minHeight: true,
    minWidth: true,
    fontSize: true,
    paddingTop: true,
    paddingRight: true,
    paddingBottom: true,
    paddingLeft: true,
    borderTopLeftRadius: true,
    borderTopRightRadius: true,
    borderBottomLeftRadius: true,
    borderBottomRightRadius: true,
    borderTopWidth: true,
    borderRightWidth: true,
    borderBottomWidth: true,
    borderLeftWidth: true
  };

  function CSSHelperService() {
    //Creates a JSONP object from a CSS declaration
    this.fromCss = function (css) {
      var properties = css.split(";");
      var result = {};

      // Process any default CSS attributes
      _.forEach(properties, function (property) {
        var propertyName = property.split(":", 1)[0];

        if (propertyName && property.length > propertyName.length) {
          var propertyValue = property.substring(propertyName.length + 1).trim();
          //converts hyphenated properties into camelcaseproperties
          //  text-align => textAlign
          //  border-top-left-radius => borderTopLeftRadius
          propertyName = _.camelCase(propertyName);

          result[propertyName] = isUnitProperty(propertyName) ? toUnit(propertyValue) : propertyValue;
        }
      });

      //Special post-processing for background-image
      if (result.backgroundImage) {
        var backgroundImage = result["backgroundImage"];
        backgroundImage = backgroundImage.replace(/^url\(/i, "");
        if (backgroundImage[backgroundImage.length - 1] === ')') {
          backgroundImage.length--;
        }

        result.backgroundImage = backgroundImage;
      }

      //Special post-processing for box shadow
      if (result.boxShadow) {
        result.boxShadow = processShadowData(result["boxShadow"], "hShadow", "vShadow", "blurRadius", "spreadRadius");
      }

      //Special post-processing for text shadow
      if (result.textShadow) {
        result.textShadow = processShadowData(result["textShadow"], "hShadow", "vShadow", "blurRadius");
      }

      //Special post-processing for transform
      if (result.transform) {
        var transforms = result.transform;
        var rotateZ = transforms.match(/rotateZ\([^\)]+\)/i);
        if (rotateZ.length > 0) {
          rotateZ = rotateZ[0].toLowerCase().replace("rotatez(", "").replace(")", "");

          result.transform = {
            rotateZ: toUnit(rotateZ)
          };
        }
      }

      return result;
    };

    this.toCss = function (value) {
      var result = [];

      var propertyName = "";
      var propertyValue = "";
      var color;

      for (var i in value) {
        //Converts camelcase properties into hyphenated properties
        //textAlign => text-align
        //borderTopLeftRadius => border-top-left-radius
        propertyName = i.replace(/([A-Z])/g, "-$1").toLowerCase();

        propertyValue = "";

        //Custom preprocessing
        //TODO: Needs refactoring
        switch (propertyName) {
          case "box-shadow":
            color = value[i]["color"];

            if (color) {
              propertyValue = String.format("{0} {1} {2} {3} {4} {5}",
                color || "",
                value[i]["hShadow"] || "0px",
                value[i]["vShadow"] || "0px",
                value[i]["blurRadius"] || "0px",
                value[i]["spreadRadius"] || "0px",
                ~~value[i]["inset"] ? "inset" : "");
            }

            break;

          case "background-image":
            if (value[i].length > 0) {
              propertyValue = String.format("url({0})", value[i]);
            }
            break;

          case "text-shadow":
            color = value[i]["color"];

            if (color) {
              propertyValue = String.format("{0} {1} {2} {3}",
                color,
                value[i]["hShadow"] || "0px",
                value[i]["vShadow"] || "0px",
                value[i]["blurRadius"] || "0px");
            }
            break;

          case "transform":
            propertyValue = String.format("rotateZ({0})", [value[i].rotateZ.value, value[i].rotateZ.unitType].join(""));
            break;

          default:
            if (propertiesWithUnits[i]) {
              propertyValue = value[i].value;
              if (value[i].unitType) {
                propertyValue += value[i].unitType;
              }
            }
            else {
              propertyValue = value[i];
            }
        }

        if (propertyValue && propertyValue.length > 0) {
          result.push(String.format("{0}:{1}", propertyName, propertyValue));
        }
      }

      return result.join(";");
    };

    function processShadowData(shadowData) {
      var rgbaColorMatchPattern = /rgba?\([^\)]+\)/i,
        hexColorMatchPattern = /#[0-9a-f]{0,6}/i,
        namedColorMatchPattern = /\b[a-z]+/i,
        insetMatchPattern = /inset/i;

      var shadowLayers = shadowData.trim().split(/,(?![^\(]*\))/);
      var result;

      if (shadowLayers.length) {
        var shadow = shadowLayers[0];

        var color = shadow.match(rgbaColorMatchPattern) || shadow.match(hexColorMatchPattern) || shadow.match(namedColorMatchPattern);
        var inset = shadow.match(insetMatchPattern);

        var valuesExcludingColorAndInset = shadow
          .replace(color, "")
          .replace(inset, "")
          .trim()
          .split(" ");

        result = {
          color: color,
          inset: inset
        };

        for (var i = 1; i <= Math.min(arguments.length, valuesExcludingColorAndInset.length); i++) {
          result[arguments[i]] = valuesExcludingColorAndInset[i - 1] || "0";
        }
      }

      return result;
    }

    function isUnitProperty(propertyName) {
      return propertiesWithUnits[propertyName] !== undefined;
    }

    function toUnit(propertyValue) {
      var unit = {
        value: parseInt(propertyValue),
        unitType: undefined
      };

      if (isNaN(unit.value)) {
        unit.value = propertyValue;
      }
      else {
        unit.unitType = propertyValue.substring(unit.value.toString().length);
      }

      return unit;
    }
  }
})(window.angular, window._);<|endoftext|>


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

var rbush = function (maxFill) {
    if (!(this instanceof rbush)) {
        // jshint newcap: false
        return new rbush(maxFill);
    }
    this._maxFill = maxFill || 6;
};

rbush.prototype = {

    // redefine the next 3 methods to suit your data format

    // compare functions for sorting by x and y coordinate
    sortX: function (a, b) { return a[0] > b[0] ? 1 : -1; },
    sortY: function (a, b) { return a[1] > b[1] ? 1 : -1; },

    // get bounding box in the form of [minX, minY, maxX, maxY] given a data item
    toBBox: function (a) { return a; },

    // recursively search for objects in a given bbox
    search: function (bbox) {
        var result = [];
        this._search(bbox, this.data, result);
        return result;
    },

    // bulk load all data and recursively build the tree from stratch
    load: function (data) {
        this.data = {};
        this.data.children = [];

        this._buildFromTop(data);
        this._calcBBoxes(this.data);

        return this;
    },

    addOne: function (item) {
        var node = this._chooseSubtree(this.toBBox(item), this.data);
        // TODO reinsert, split (choose split axis, choose split index), insert
    },

    _chooseSubtree: function (bbox, node) {

        if (node.leaf) { return node; }

        var i, len, child, targetNode,
            area, enlargement, overlap, minArea, minEnlargement, minOverlap;

        minArea = minEnlargement = minOverlap = Infinity;

        for (var i = 0, len = node.children.length; i < len; i++) {
            child = node.children[i];

            area = this._area(child.bbox);
            enlargement = this._enlargedArea(bbox, child.bbox) - area;
            overlap = child.leaf && this._overlapArea(bbox, child);

            // choose the node with the least overlap
            if (overlap < minOverlap) {
                minOverlap = overlap;
                targetNode = child;

            } else if (!overlap || overlap === minOverlap) {
                // otherwise choose one with the least area enlargement
                if (enlargement < minEnlargement) {
                    minEnlargement = enlargement;
                    targetNode = child;

                } else if (enlargement === minEnlargement) {
                    // otherwise choose one with the smallest area
                    if (area < minArea) {
                        minArea = area;
                        targetNode = child;
                    }
                }
            }
        }

        return this._chooseSubtree(bbox, targetNode);
    },

    _area: function (bbox) {
        return (bbox[2] - bbox[0]) * (bbox[3] - bbox[1]);
    },

    _enlargedArea: function (bbox, bbox2) {
        return (Math.max(bbox2[2], bbox[2]) - Math.min(bbox2[0], bbox[0])) *
               (Math.max(bbox2[3], bbox[3]) - Math.min(bbox2[1], bbox[1]));
    },

    _overlapArea: function (bbox, node) {
        for (var i = 0, sum = 0, len = node.children.length; i < len; i++) {
            sum += this._intersectionArea(this.toBBox(node.children[i]), bbox);
        }
        return sum;
    },

    _intersectionArea: function (bbox, bbox2) {
        var minX = Math.max(bbox[0], bbox2[0]),
            maxX = Math.min(bbox[2], bbox2[2]),
            minY = Math.max(bbox[1], bbox2[1]),
            maxY = Math.min(bbox[3], bbox2[3]);

        return Math.max(maxX - minX, 0) *
               Math.max(maxY - minY, 0);
    },

    // bulk load data with the OMT algorithm
    _buildFromTop: function (data) {

        var N = data.length,           // number of items
            S = this._numTopSlices(N), // number of slices for levels 0 and 1
            N1 = Math.ceil(N / S),     // size of each root node
            N2 = Math.ceil(N1 / S),    // size of each node of the next level after root

            items = data.slice().sort(this.sortX),
            i, j, slice, node;

        // create S x S nodes for the root and build the rest recursively
        for (i = 0; i < N; i += N1) {
            slice = items.slice(i, i + N1).sort(this.sortY);

            for (j = 0; j < N1; j += N2) {
                node = this._build(slice.slice(j, j + N2), 1);
                this.data.children.push(node);
            }
        }
    },

    _build: function (items, level) {

        var node = {},
            len = items.length,
            k = Math.ceil(len / this._maxFill), // size of each child node
            i, childNode;

        if (k < 2) {
            node.children = items;
            node.leaf = true;
            return node;
        }

        // split by different plane each time - x, y, x, y, etc.
        items.sort(level % 2 ? this.sortX : this.sortY);

        node.children = [];

        for (i = 0; i < len; i += k) {
            childNode = this._build(items.slice(i, i + k), level + 1);
            node.children.push(childNode);
        }

        return node;
    },

    // recursively calculate all node bboxes in the tree
    _calcBBoxes: function (node) {

        node.bbox = [Infinity, Infinity, -Infinity, -Infinity];

        for (var i = 0, len = node.children.length, child; i < len; i++) {
            child = node.children[i];

            if (node.leaf) {
                this._extend(node.bbox, this.toBBox(child));
            } else {
                this._calcBBoxes(child);
                this._extend(node.bbox, child.bbox);
            }
        }
    },

    _numTopSlices: function (N) {

        var M = this._maxFill,                             // max number of branches in one node
            h = Math.ceil(Math.log(N) / Math.log(M)),      // target height of the tree
            Ns = Math.pow(M, h - 1),                       // max number of tree nodes
            S = Math.floor(Math.sqrt(Math.ceil(N / Ns)));  // target number of level 0-1 branches

        return Math.max(S, 2);
    },

    _search: function (bbox, node, result) {

        if (!this._intersects(bbox, node.bbox)) { return; }

        var i, child,
            len = node.children.length;

        for (i = 0; i < len; i++) {
            child = node.children[i];

            if (!node.leaf) {
                this._search(bbox, child, result);
            } else if (this._contains(bbox, this.toBBox(child))) {
                result.push(child);
            }
        }
    },

    _intersects: function (bbox, bbox2) {
        return bbox2[0] <= bbox[2] &&
               bbox2[1] <= bbox[3] &&
               bbox2[2] >= bbox[0] &&
               bbox2[3] >= bbox[1];
    },

    _contains: function (bbox, bbox2) {
        return bbox2[0] >= bbox[0] &&
               bbox2[1] >= bbox[1] &&
               bbox2[2] <= bbox[2] &&
               bbox2[3] <= bbox[3];
    },

    _extend: function (bbox, bbox2) {
        bbox[0] = Math.min(bbox[0], bbox2[0]);
        bbox[1] = Math.min(bbox[1], bbox2[1]);
        bbox[2] = Math.max(bbox[2], bbox2[2]);
        bbox[3] = Math.max(bbox[3], bbox2[3]);
    }
};

if (typeof module !== 'undefined') {
    module.exports = rbush;
} else {
    window.rbush = rbush;
}

})();
<commit_msg>autogess maxFill if not provided<commit_after>(function () { 'use strict';

var rbush = function (maxFill) {
    if (!(this instanceof rbush)) {
        // jshint newcap: false
        return new rbush(maxFill);
    }
    this._maxFill = maxFill;
};

rbush.prototype = {

    // redefine the next 3 methods to suit your data format

    // compare functions for sorting by x and y coordinate
    sortX: function (a, b) { return a[0] > b[0] ? 1 : -1; },
    sortY: function (a, b) { return a[1] > b[1] ? 1 : -1; },

    // get bounding box in the form of [minX, minY, maxX, maxY] given a data item
    toBBox: function (a) { return a; },

    // recursively search for objects in a given bbox
    search: function (bbox) {
        var result = [];
        this._search(bbox, this.data, result);
        return result;
    },

    // bulk load all data and recursively build the tree from stratch
    load: function (data) {
        this.data = {};
        this.data.children = [];

        if (!this._maxFill) {
            this._maxFill = Math.max(Math.ceil(data.length / 1000), 6);
        }

        this._buildFromTop(data);
        this._calcBBoxes(this.data);

        return this;
    },

    addOne: function (item) {
        var node = this._chooseSubtree(this.toBBox(item), this.data);
        // TODO reinsert, split (choose split axis, choose split index), insert
    },

    _chooseSubtree: function (bbox, node) {

        if (node.leaf) { return node; }

        var i, len, child, targetNode,
            area, enlargement, overlap, minArea, minEnlargement, minOverlap;

        minArea = minEnlargement = minOverlap = Infinity;

        for (var i = 0, len = node.children.length; i < len; i++) {
            child = node.children[i];

            area = this._area(child.bbox);
            enlargement = this._enlargedArea(bbox, child.bbox) - area;
            overlap = child.leaf && this._overlapArea(bbox, child);

            // choose the node with the least overlap
            if (overlap < minOverlap) {
                minOverlap = overlap;
                targetNode = child;

            } else if (!overlap || overlap === minOverlap) {
                // otherwise choose one with the least area enlargement
                if (enlargement < minEnlargement) {
                    minEnlargement = enlargement;
                    targetNode = child;

                } else if (enlargement === minEnlargement) {
                    // otherwise choose one with the smallest area
                    if (area < minArea) {
                        minArea = area;
                        targetNode = child;
                    }
                }
            }
        }

        return this._chooseSubtree(bbox, targetNode);
    },

    _area: function (bbox) {
        return (bbox[2] - bbox[0]) * (bbox[3] - bbox[1]);
    },

    _enlargedArea: function (bbox, bbox2) {
        return (Math.max(bbox2[2], bbox[2]) - Math.min(bbox2[0], bbox[0])) *
               (Math.max(bbox2[3], bbox[3]) - Math.min(bbox2[1], bbox[1]));
    },

    _overlapArea: function (bbox, node) {
        for (var i = 0, sum = 0, len = node.children.length; i < len; i++) {
            sum += this._intersectionArea(this.toBBox(node.children[i]), bbox);
        }
        return sum;
    },

    _intersectionArea: function (bbox, bbox2) {
        var minX = Math.max(bbox[0], bbox2[0]),
            maxX = Math.min(bbox[2], bbox2[2]),
            minY = Math.max(bbox[1], bbox2[1]),
            maxY = Math.min(bbox[3], bbox2[3]);

        return Math.max(maxX - minX, 0) *
               Math.max(maxY - minY, 0);
    },

    // bulk load data with the OMT algorithm
    _buildFromTop: function (data) {

        var N = data.length,           // number of items
            S = this._numTopSlices(N), // number of slices for levels 0 and 1
            N1 = Math.ceil(N / S),     // size of each root node
            N2 = Math.ceil(N1 / S),    // size of each node of the next level after root

            items = data.slice().sort(this.sortX),
            i, j, slice, node;

        // create S x S nodes for the root and build the rest recursively
        for (i = 0; i < N; i += N1) {
            slice = items.slice(i, i + N1).sort(this.sortY);

            for (j = 0; j < N1; j += N2) {
                node = this._build(slice.slice(j, j + N2), 1);
                this.data.children.push(node);
            }
        }
    },

    _build: function (items, level) {

        var node = {},
            len = items.length,
            k = Math.ceil(len / this._maxFill), // size of each child node
            i, childNode;

        if (k < 2) {
            node.children = items;
            node.leaf = true;
            return node;
        }

        // split by different plane each time - x, y, x, y, etc.
        items.sort(level % 2 ? this.sortX : this.sortY);

        node.children = [];

        for (i = 0; i < len; i += k) {
            childNode = this._build(items.slice(i, i + k), level + 1);
            node.children.push(childNode);
        }

        return node;
    },

    // recursively calculate all node bboxes in the tree
    _calcBBoxes: function (node) {

        node.bbox = [Infinity, Infinity, -Infinity, -Infinity];

        for (var i = 0, len = node.children.length, child; i < len; i++) {
            child = node.children[i];

            if (node.leaf) {
                this._extend(node.bbox, this.toBBox(child));
            } else {
                this._calcBBoxes(child);
                this._extend(node.bbox, child.bbox);
            }
        }
    },

    _numTopSlices: function (N) {

        var M = this._maxFill,                             // max number of branches in one node
            h = Math.ceil(Math.log(N) / Math.log(M)),      // target height of the tree
            Ns = Math.pow(M, h - 1),                       // max number of tree nodes
            S = Math.floor(Math.sqrt(Math.ceil(N / Ns)));  // target number of level 0-1 branches

        return Math.max(S, 2);
    },

    _search: function (bbox, node, result) {

        if (!this._intersects(bbox, node.bbox)) { return; }

        var i, child,
            len = node.children.length;

        for (i = 0; i < len; i++) {
            child = node.children[i];

            if (!node.leaf) {
                this._search(bbox, child, result);
            } else if (this._contains(bbox, this.toBBox(child))) {
                result.push(child);
            }
        }
    },

    _intersects: function (bbox, bbox2) {
        return bbox2[0] <= bbox[2] &&
               bbox2[1] <= bbox[3] &&
               bbox2[2] >= bbox[0] &&
               bbox2[3] >= bbox[1];
    },

    _contains: function (bbox, bbox2) {
        return bbox2[0] >= bbox[0] &&
               bbox2[1] >= bbox[1] &&
               bbox2[2] <= bbox[2] &&
               bbox2[3] <= bbox[3];
    },

    _extend: function (bbox, bbox2) {
        bbox[0] = Math.min(bbox[0], bbox2[0]);
        bbox[1] = Math.min(bbox[1], bbox2[1]);
        bbox[2] = Math.max(bbox[2], bbox2[2]);
        bbox[3] = Math.max(bbox[3], bbox2[3]);
    }
};

if (typeof module !== 'undefined') {
    module.exports = rbush;
} else {
    window.rbush = rbush;
}

})();
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2013 by Animatron.
 * All rights are reserved.
 *
 * Animatron Player is licensed under the MIT License, see LICENSE.
 *
 * @VERSION
 */

(function() { // anonymous wrapper to exclude global context clash
  var C = anm.C,
      is = __anm.is;
  var _ResMan = __anm.resource_manager;
  var Player = anm.Player;

  C.MOD_SCRIPTING = 'scripting';
  if (anm.M[C.MOD_SCRIPTING]) throw new Error('SCRIPTING module already enabled');

  anm.M[C.MOD_SCRIPTING] = {};

  var E = anm.Element;

  var handler_map = {
    'click': C.X_MCLICK
  }, wrappers_map = {
    'click': [
      '(function(ctx) { ' +
         'return function(evt, t) { ' +
           'if (this.$.contains(evt.pos)) { ' +
             '(function(ctx, evt, t) { ',
                /* content */
             '}).call(this.$.bstate, ctx, evt, t);' +
           '}' +
         '}' +
      '})(____user_ctx)'
    ]
  };

  var ____user_ctx = { 'foo': 'bar' };

  var last_scene_is_dynamic;

  E._customImporters.push(function(source, type, importer) {
    if ((type === 255) && source[8]) { // type === 255 is TYPE_LAYER, see animatron-importer.js
      var handlers = source[8];
      for (var handler_type in handlers) {
        var handler_code = wrappers_map[handler_type][0] +
                           handlers[handler_type] + wrappers_map[handler_type][1];

        last_scene_is_dynamic = true;
        eval('this.m_on(handler_map[handler_type], ' +
             handler_code + ');');
      }
    }
  });

  var prev_forSnapshot = Player.forSnapshot;
  Player.forSnapshot = function(canvasId, snapshotUrl, importer, callback) {
    last_scene_is_dynamic = false;
    var player = prev_forSnapshot.call(this, canvasId, snapshotUrl, importer, function() {
      if (last_scene_is_dynamic) {
          player.mode = C.M_DYNAMIC;
          player._checkMode();
          player.play();
      }
      last_scene_is_dynamic = false;
      if (callback) callback();
    });
    return player;
  }

})();<commit_msg>more actions<commit_after>/*
 * Copyright (c) 2011-2013 by Animatron.
 * All rights are reserved.
 *
 * Animatron Player is licensed under the MIT License, see LICENSE.
 *
 * @VERSION
 */

(function() { // anonymous wrapper to exclude global context clash
  var C = anm.C,
      is = __anm.is;
  var _ResMan = __anm.resource_manager;
  var Player = anm.Player;

  C.MOD_SCRIPTING = 'scripting';
  if (anm.M[C.MOD_SCRIPTING]) throw new Error('SCRIPTING module already enabled');

  anm.M[C.MOD_SCRIPTING] = {};

  var E = anm.Element;

  var MOUSE_PAIR = [
      '(function(ctx) { ' +
        'return function(evt, t) { ' +
          'if (this.$.contains(evt.pos)) { ' +
            '(function(ctx, evt, t) { ',
                /* content */
            '}).call(this.$.bstate, ctx, evt, t);' +
          '}' +
        '}' +
      '})(____user_ctx)'];

  var KBD_PAIR = [
      '(function(ctx) { ' +
        'return function(evt, t) { ' +
          '(function(ctx, evt, t) { ',
                /* content */
          '}).call(this.$.bstate, ctx, evt, t);' +
        '}' +
      '})(____user_ctx)'];

  var handler_map = {
    'click': C.X_MCLICK,
    'dclick': C.X_MDCLICK, /* who need this? */
    'm_up': C.X_MUP,
    'm_down': C.X_MDOWN,
    'm_enter': C.X_MMOVE,
    'm_leave': C.X_MMOVE,
    'm_penter': C.X_MOVER, /* enter the player canvas */
    'm_pleave': C.X_MOUT, /* out of the player canvas */
    'm_move': C.X_MMOVE,
    'k_up': C.X_KUP,
    'k_down': C.X_KDOWN,
    'k_press': C.X_KPRESS
  }, wrappers_map = {
    'click': MOUSE_PAIR,
    'dclick': MOUSE_PAIR,
    'mup': MOUSE_PAIR,
    'm_up': MOUSE_PAIR,
    'm_down': MOUSE_PAIR,
    'm_enter': [
      '(function(ctx) { ' +
        'return function(evt, t) { ' +
          'if ((this.$.__last_p == undefined || !this.$.contains(this.$.__last_p)) && this.$.contains(evt.pos)) { ' +
            '(function(ctx, evt, t) { ',
                /* content */
            '}).call(this.$.bstate, ctx, evt, t);' +
          '}' +
          'this.$.__last_p = evt.pos;' +
        '}' +
      '})(____user_ctx)'],
    'm_leave': [
      '(function(ctx) { ' +
        'return function(evt, t) { ' +
          'if (this.$.__last_p != undefined && this.$.contains(this.$.__last_p) && !this.$.contains(evt.pos)) { ' +
            '(function(ctx, evt, t) { ',
                /* content */
            '}).call(this.$.bstate, ctx, evt, t);' +
          '}' +
          'this.$.__last_p = evt.pos;' +
        '}' +
      '})(____user_ctx)'],
    'm_penter': MOUSE_PAIR,
    'm_pleave': MOUSE_PAIR,
    'm_move': KBD_PAIR, /* no boundaries check so MOVE is handled at the whole player canvas! */
    'k_up': KBD_PAIR,
    'k_down': KBD_PAIR,
    'k_press': KBD_PAIR
  };

  var ____user_ctx = { 'foo': 'bar' };

  var last_scene_is_dynamic;

  E._customImporters.push(function(source, type, importer) {
    if ((type === 255) && source[8]) { // type === 255 is TYPE_LAYER, see animatron-importer.js
      var handlers = source[8];
      for (var handler_type in handlers) {
        var handler_code = wrappers_map[handler_type][0] +
                           handlers[handler_type] + wrappers_map[handler_type][1];

        last_scene_is_dynamic = true;
        eval('this.m_on(handler_map[handler_type], ' +
             handler_code + ');');
      }
    }
  });

  var prev_forSnapshot = Player.forSnapshot;
  Player.forSnapshot = function(canvasId, snapshotUrl, importer, callback) {
    last_scene_is_dynamic = false;
    var player = prev_forSnapshot.call(this, canvasId, snapshotUrl, importer, function() {
      if (last_scene_is_dynamic) {
          player.mode = C.M_DYNAMIC;
          player._checkMode();
          player.play();
      }
      last_scene_is_dynamic = false;
      if (callback) callback();
    });
    return player;
  }

})();<|endoftext|>