<commit_before>/*
 * Copyright (c) 2012 Peter Kuma

 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

var FileShack = new Class({
    Implements: Options,

    options: {
        updateInterval: 2000
    },

    initialize: function(options) {
        var this_ = this;

        this.setOptions(options);
        this.lastUpdate = undefined;

        this.items = new Collection();
        this.items.addEvent('add', function(view) {
            $('list').insertBefore(view.el, $('list').firstChild);
        });

        // Bootstrap items from JSON embedded in index.html.
        this.bootstrap($('bootstrap').get('text'))

        var dropbox = $('dropbox');
        var dropboxInput = $('dropbox-input');
        var iframe = $('iframe');

        // Drag & Drop.
        if (typeof dropbox.addEventListener != 'undefined' &&
            typeof dropbox.ondrop != 'undefined' &&
            typeof File != 'undefined')
        {
            // Register Drag & Drop events.
            dropbox.addEventListener("dragenter", function(e) { e.preventDefault(); }, false);
            dropbox.addEventListener("dragover", function(e) { e.preventDefault(); }, false);
            dropbox.addEventListener("drop", function(e) {
                e.preventDefault();
                if (e.dataTransfer.files)
                    Array.each(e.dataTransfer.files, function(f) { this_.upload(f); });
            }, false);
        } else {
            // Switch dropbox text, drag & drop is not supported.
            $('dropbox-text').setStyle('display', 'none');
            $('dropbox-text-nodragndrop').setStyle('display', 'block');
        }

        var clickDelegated = false;
        dropboxInput.onclick = function(e) {
            clickDelegated = true;
            if (e && e.stopPropagation) e.stopPropagation();
        };

        if (Browser.ie && Browser.version <= 7) {
            this.fallback();
        } else {
            // Delegate click on dropbox to the hidden input file element.
            dropbox.addEvent('click', function() {
                if (typeof File != 'undefined') {
                    dropboxInput.click();
                    window.setTimeout(function() { if (!clickDelegated) this_.fallback(); }, 100);
                } else { // Fallback to upload by the iframe hack (IE).
                    if (typeof iframe.contentDocument != 'undefined')
                        var form = iframe.contentDocument.forms[0];
                    else
                        var form = iframe.getDocument().forms[0];
                    form.file.onchange = function() {
                        var item = this_.upload(form);
                        iframe.onload = function() {
                            item.model.del();
                            this_.update();
                        };
                    };
                    form.file.click();
                }
            });
        }

        dropboxInput.addEvent('change', function() {
            this_.upload(dropbox);
            dropbox.reset();
        });

        //window.setInterval(function() { this_.update() }, this.options.updateInterval);
        window.uuid = uuid();
        //this.update();
    },

    bootstrap: function(json) {
        var this_ = this;
        items = JSON.decode(json);
        Array.each(items, function(item) {
            var view = new ItemView(new Item());
            view.model.update(item);
            this_.items.add(view);
        });
    },

    fallback: function() {
        var this_ = this;
        // Show the file upload input form.
        $('dropbox-text').setStyle('display', 'none');
        $('dropbox-text-nodragndrop').setStyle('display', 'none');
        $('dropbox-file').setStyle('visibility', 'visible');
    },

    update: function() {
        var xhr = new XMLHttpRequest();

        if (this.lastUpdate) xhr.open('GET', 'update/' + this.lastUpdate + '/');
        else xhr.open('GET', 'update/');

        var this_ = this;
        xhr.onreadystatechange = function(e) {
            if (this.readyState == 4) {
                json = JSON.decode(this.responseText);
                this_.removeStaleItems(json.item_ids);
                Array.each(json.items, function(item) {
                    if (this_.items.get(item.id)) { // Existing item.
                        // Do not update pending items.
                        if (this_.items.get(item.id).model.type != 'pending')
                            this_.items.get(item.id).model.update(item);
                    } else { // New item.
                        var view = new ItemView(new Item());
                        view.model.update(item);
                        this_.items.add(view);
                    }
                });
                this.lastUpdate = json.time;
            }
        };
        xhr.send();
    },

    upload: function(data) {
        var this_ = this;
        // If input[type="file"].files is supported, upload per parts.
        if (typeof HTMLFormElement != 'undefined' && data instanceof HTMLFormElement &&
            data.file && data.file.files)
        {
            Array.each(data.file.files, function(file) { this_.upload(file); });
            return null;
        }

        // Determine name and size of the file.
        if (typeof File != 'undefined' && data instanceof File) {
            // Older browsers.
            if (data.fileName) var name = data.fileName;
            if (data.fileSize) var size = data.fileSize;
            // Newer browsers.
            if (data.name) var name = data.name;
            if (data.size) var size = data.size;
        } else if (data.file) {
            var name = basename(data.file.value);
        } else {
            var name = '';
            var size = 0;
        }

        // Is there a stale item with the same size and name?
        var i = this.items.find(function(i) {
            if (!(i.model.type == 'stale' || i.model.type == 'pending' && i.isError()))
                return false;
            if (i.model.size_total != size) return false;
            if (i.model.name == name) return true;
            var n = i.model.name;
            // Django appends _#no to duplicate file names, account for that.
            if (n.contains('_')) {
                var index = n.lastIndexOf('_');
                var first = n.substring(0, index);
                var second = n.substring(index);
                n = first + second.substring(second.indexOf('.'));
            }
            if (n == name) return true;
            return false;
        });

        // If this is a File, ask the user about resume.
        if (i && data instanceof File) {
            var c = confirm('A stale file with the same name and size has been found.\nDo you want to resume uploading?');
            if (c) {
                item = i;
                item.clearError();
            }
        }

        if (!item) {
            var item = new ItemView(new Item({
                type: 'pending',
                'name': name,
                size: 0,
                size_total: size,
                status: 'UPLOADING'
            }));
            this.items.add(item);
        }

        if (ITEM_SIZE_LIMIT > 0 && size > ITEM_SIZE_LIMIT) {
            item.onError({
                label: ITEM_SIZE_LIMIT_ERROR_LABEL,
                message: ITEM_SIZE_LIMIT_ERROR_MESSAGE
	    });
            return null;
        }

        if (typeof File != 'undefined' && data instanceof File && typeof FileReader != 'undefined') {
            var reader = new FileReader()
            reader.onload = function(e) { item.model.upload(e.target.result); };
            reader.readAsBinaryString(data);
        } else if (typeof HTMLFormElement != 'undefined' && data instanceof HTMLFormElement && typeof FormData != 'undefined') {
            item.model.upload(new FormData(data));
        } else if (typeof File != 'undefined' && data instanceof File && typeof FormData != 'undefined') {
            var formData = new FormData();
            formData.append('file', data);
            item.model.upload(formData);
        } else if (typeof File != 'undefined' && data instanceof File) {
            item.model.upload(data.getAsBinary());
        } else {
            data.submit();
        }

        return item;
    },

    removeStaleItems: function(validIds) {
        Object.each(this.items.all(), function(item) {
            if (item.model.type != 'pending' && !validIds.contains(item.model.id))
                item.model.remove();
        });
    }
});

document.addEvent('domready', function() {
    var fs = new FileShack();
});

<commit_msg>When uploading via iframe, do not del() model.<commit_after>/*
 * Copyright (c) 2012 Peter Kuma

 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

var FileShack = new Class({
    Implements: Options,

    options: {
        updateInterval: 2000
    },

    initialize: function(options) {
        var this_ = this;

        this.setOptions(options);
        this.lastUpdate = undefined;

        this.items = new Collection();
        this.items.addEvent('add', function(view) {
            $('list').insertBefore(view.el, $('list').firstChild);
        });

        // Bootstrap items from JSON embedded in index.html.
        this.bootstrap($('bootstrap').get('text'))

        var dropbox = $('dropbox');
        var dropboxInput = $('dropbox-input');
        var iframe = $('iframe');

        // Drag & Drop.
        if (typeof dropbox.addEventListener != 'undefined' &&
            typeof dropbox.ondrop != 'undefined' &&
            typeof File != 'undefined')
        {
            // Register Drag & Drop events.
            dropbox.addEventListener("dragenter", function(e) { e.preventDefault(); }, false);
            dropbox.addEventListener("dragover", function(e) { e.preventDefault(); }, false);
            dropbox.addEventListener("drop", function(e) {
                e.preventDefault();
                if (e.dataTransfer.files)
                    Array.each(e.dataTransfer.files, function(f) { this_.upload(f); });
            }, false);
        } else {
            // Switch dropbox text, drag & drop is not supported.
            $('dropbox-text').setStyle('display', 'none');
            $('dropbox-text-nodragndrop').setStyle('display', 'block');
        }

        var clickDelegated = false;
        dropboxInput.onclick = function(e) {
            clickDelegated = true;
            if (e && e.stopPropagation) e.stopPropagation();
        };

        if (Browser.ie && Browser.version <= 7) {
            this.fallback();
        } else {
            // Delegate click on dropbox to the hidden input file element.
            dropbox.addEvent('click', function() {
                if (typeof File != 'undefined') {
                    dropboxInput.click();
                    window.setTimeout(function() { if (!clickDelegated) this_.fallback(); }, 100);
                } else { // Fallback to upload by the iframe hack (IE).
                    if (typeof iframe.contentDocument != 'undefined')
                        var form = iframe.contentDocument.forms[0];
                    else
                        var form = iframe.getDocument().forms[0];
                    form.file.onchange = function() {
                        var item = this_.upload(form);
                        iframe.onload = function() {
                            item.model.remove();
                            this_.update();
                        };
                    };
                    form.file.click();
                }
            });
        }

        dropboxInput.addEvent('change', function() {
            this_.upload(dropbox);
            dropbox.reset();
        });

        //window.setInterval(function() { this_.update() }, this.options.updateInterval);
        window.uuid = uuid();
        //this.update();
    },

    bootstrap: function(json) {
        var this_ = this;
        items = JSON.decode(json);
        Array.each(items, function(item) {
            var view = new ItemView(new Item());
            view.model.update(item);
            this_.items.add(view);
        });
    },

    fallback: function() {
        var this_ = this;
        // Show the file upload input form.
        $('dropbox-text').setStyle('display', 'none');
        $('dropbox-text-nodragndrop').setStyle('display', 'none');
        $('dropbox-file').setStyle('visibility', 'visible');
    },

    update: function() {
        var xhr = new XMLHttpRequest();

        if (this.lastUpdate) xhr.open('GET', 'update/' + this.lastUpdate + '/');
        else xhr.open('GET', 'update/');

        var this_ = this;
        xhr.onreadystatechange = function(e) {
            if (this.readyState == 4) {
                json = JSON.decode(this.responseText);
                this_.removeStaleItems(json.item_ids);
                Array.each(json.items, function(item) {
                    if (this_.items.get(item.id)) { // Existing item.
                        // Do not update pending items.
                        if (this_.items.get(item.id).model.type != 'pending')
                            this_.items.get(item.id).model.update(item);
                    } else { // New item.
                        var view = new ItemView(new Item());
                        view.model.update(item);
                        this_.items.add(view);
                    }
                });
                this.lastUpdate = json.time;
            }
        };
        xhr.send();
    },

    upload: function(data) {
        var this_ = this;
        // If input[type="file"].files is supported, upload per parts.
        if (typeof HTMLFormElement != 'undefined' && data instanceof HTMLFormElement &&
            data.file && data.file.files)
        {
            Array.each(data.file.files, function(file) { this_.upload(file); });
            return null;
        }

        // Determine name and size of the file.
        if (typeof File != 'undefined' && data instanceof File) {
            // Older browsers.
            if (data.fileName) var name = data.fileName;
            if (data.fileSize) var size = data.fileSize;
            // Newer browsers.
            if (data.name) var name = data.name;
            if (data.size) var size = data.size;
        } else if (data.file) {
            var name = basename(data.file.value);
        } else {
            var name = '';
            var size = 0;
        }

        // Is there a stale item with the same size and name?
        var i = this.items.find(function(i) {
            if (!(i.model.type == 'stale' || i.model.type == 'pending' && i.isError()))
                return false;
            if (i.model.size_total != size) return false;
            if (i.model.name == name) return true;
            var n = i.model.name;
            // Django appends _#no to duplicate file names, account for that.
            if (n.contains('_')) {
                var index = n.lastIndexOf('_');
                var first = n.substring(0, index);
                var second = n.substring(index);
                n = first + second.substring(second.indexOf('.'));
            }
            if (n == name) return true;
            return false;
        });

        // If this is a File, ask the user about resume.
        if (i && data instanceof File) {
            var c = confirm('A stale file with the same name and size has been found.\nDo you want to resume uploading?');
            if (c) {
                item = i;
                item.clearError();
            }
        }

        if (!item) {
            var item = new ItemView(new Item({
                type: 'pending',
                'name': name,
                size: 0,
                size_total: size,
                status: 'UPLOADING'
            }));
            this.items.add(item);
        }

        if (ITEM_SIZE_LIMIT > 0 && size > ITEM_SIZE_LIMIT) {
            item.onError({
                label: ITEM_SIZE_LIMIT_ERROR_LABEL,
                message: ITEM_SIZE_LIMIT_ERROR_MESSAGE
	    });
            return null;
        }

        if (typeof File != 'undefined' && data instanceof File && typeof FileReader != 'undefined') {
            var reader = new FileReader()
            reader.onload = function(e) { item.model.upload(e.target.result); };
            reader.readAsBinaryString(data);
        } else if (typeof HTMLFormElement != 'undefined' && data instanceof HTMLFormElement && typeof FormData != 'undefined') {
            item.model.upload(new FormData(data));
        } else if (typeof File != 'undefined' && data instanceof File && typeof FormData != 'undefined') {
            var formData = new FormData();
            formData.append('file', data);
            item.model.upload(formData);
        } else if (typeof File != 'undefined' && data instanceof File) {
            item.model.upload(data.getAsBinary());
        } else {
            data.submit();
        }

        return item;
    },

    removeStaleItems: function(validIds) {
        Object.each(this.items.all(), function(item) {
            if (item.model.type != 'pending' && !validIds.contains(item.model.id))
                item.model.remove();
        });
    }
});

document.addEvent('domready', function() {
    var fs = new FileShack();
});

<|endoftext|>


<commit_before>//= require jquery
//= require jquery_ujs
//= require jquery-ui-1.8.17.custom.min
//= require jquery.tagit
//= require jquery-ui-timepicker-addon
//= require jquery.purr
//= require best_in_place

//= require jquery.cookie

// visualizaciones y demas
//= require gmaps4rails/gmaps4rails.googlemaps.js.coffee
//= require timeline
// require timeline.es
//= require jwplayer
// require mercury

//= require bootstrap-alert
//= require bootstrap-modal
//= require bootstrap-typeahead
//= require bootstrap-dropdown

// for mind-map
// require jsplumb/jsBezier-0.3
// require jsplumb/jsPlumb-1.3.6-RC1
// require jsplumb/jsPlumb-defaults-1.3.6-RC1
// require jsplumb/jsPlumb-connectors-statemachine-1.3.6-RC1
// require jsplumb/jsPlumb-renderers-svg-1.3.6-RC1
// require jsplumb/jquery.jsPlumb-1.3.6-RC1
// require underscore
// require jquery.overscroll

//= require Markdown.Converter
//= require Markdown.Editor
//= require Markdown.Sanitizer
<commit_msg>assets: error en el gmaps4rails<commit_after>//= require jquery
//= require jquery_ujs
//= require jquery-ui-1.8.17.custom.min
//= require jquery.tagit
//= require jquery-ui-timepicker-addon
//= require jquery.purr
//= require best_in_place

//= require jquery.cookie

// visualizaciones y demas
//= require gmaps4rails/gmaps4rails.base.js.coffee
//= require gmaps4rails/gmaps4rails.googlemaps.js.coffee
//= require timeline
// require timeline.es
//= require jwplayer
// require mercury

//= require bootstrap-alert
//= require bootstrap-modal
//= require bootstrap-typeahead
//= require bootstrap-dropdown

// for mind-map
// require jsplumb/jsBezier-0.3
// require jsplumb/jsPlumb-1.3.6-RC1
// require jsplumb/jsPlumb-defaults-1.3.6-RC1
// require jsplumb/jsPlumb-connectors-statemachine-1.3.6-RC1
// require jsplumb/jsPlumb-renderers-svg-1.3.6-RC1
// require jsplumb/jquery.jsPlumb-1.3.6-RC1
// require underscore
// require jquery.overscroll

//= require Markdown.Converter
//= require Markdown.Editor
//= require Markdown.Sanitizer
<|endoftext|>


<commit_before>/* eslint-env mocha*/

const invRegLowGamma = require('./invRegLowGamma.js');
const expect = require('chai').expect;

describe('invRegLowGamma', function() {
	describe('smoke tests', function() {
		it('should exist', ()=>{
			expect(invRegLowGamma).to.exist;
		});

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

	describe('the function returns the lower regularized incomplete gamma function evaluated at (p,a)', function() {
		it('should return 228.60679774997897 for p=5 and a=5', ()=>{
			expect(invRegLowGamma(5, 5)).to.equal(228.60679774997897);
		});

		it('should return 6.475606702314749 for p=0.666 and a=5.75', ()=>{
			expect(invRegLowGamma(0.666, 5.75)).to.equal(6.475606702314749);
		});

		it('should return 100 for p=5 and a=0', ()=>{
			expect(invRegLowGamma(5, 0)).to.equal(100);
		});

        it('should return 1.67834699001666 for p=0.5 and a=2', ()=>{
			expect(invRegLowGamma(5, 0)).to.equal(1.67834699001666);
		});

        it('should return 0.3759413598815401 for p=0.5 and a=0.666', ()=>{
			expect(invRegLowGamma(5, 0)).to.equal(0.3759413598815401);
		});
	});

	describe('error tests', function() {
		it('should return a error for a NaN input in the parameter: p', ()=>{
			expect(()=>invRegLowGamma('Not a number', 6)).to.throw('The value in param "p" is not an number.');
		});

        it('should return a error for a NaN input in the parameter: a', ()=>{
			expect(()=>invRegLowGamma(6, 'Not a number')).to.throw('The value in param "a" is not an number.');
		});
	});
});
<commit_msg>fixes on values of invRegLowGamma spec<commit_after>/* eslint-env mocha*/

const invRegLowGamma = require('./invRegLowGamma.js');
const expect = require('chai').expect;

describe('invRegLowGamma', function() {
	describe('smoke tests', function() {
		it('should exist', ()=>{
			expect(invRegLowGamma).to.exist;
		});

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

	describe('the function returns the lower regularized incomplete gamma function evaluated at (p,a)', function() {
		it('should return 228.60679774997897 for p=5 and a=5', ()=>{
			expect(invRegLowGamma(5, 5)).to.equal(228.60679774997897);
		});

		it('should return 6.475606702314761 for p=0.666 and a=5.75', ()=>{
			expect(invRegLowGamma(0.666, 5.75)).to.equal(6.475606702314761);
		});

		it('should return 100 for p=5 and a=0', ()=>{
			expect(invRegLowGamma(5, 0)).to.equal(100);
		});

        it('should return 1.678346990016661 for p=0.5 and a=2', ()=>{
			expect(invRegLowGamma(0.5, 2)).to.equal(1.678346990016661);
		});

        it('should return 0.3759413598815398 for p=0.5 and a=0.666', ()=>{
			expect(invRegLowGamma(0.5, 0.666)).to.equal(0.3759413598815398);
		});

        it('should return 0 for p=-1(any negative number) and a=2', ()=>{
			expect(invRegLowGamma(-1, 2)).to.equal(0);
		});
	});

	describe('error tests', function() {
		it('should return a error for a NaN input in the parameter: p', ()=>{
			expect(()=>invRegLowGamma('Not a number', 6)).to.throw('The value in param "p" is not an number.');
		});

        it('should return a error for a NaN input in the parameter: a', ()=>{
			expect(()=>invRegLowGamma(6, 'Not a number')).to.throw('The value in param "a" is not an number.');
		});
	});
});
<|endoftext|>


<commit_before>import React from "react";
import TestRenderer from "react-test-renderer";
import { FluentBundle, FluentResource } from "@fluent/bundle";
import { ReactLocalization, LocalizationProvider, useLocalization } from "../esm/index";

function DummyComponent() {
  const { l10n } = useLocalization();

  return (

{l10n.getString('foo')}

  );
}

describe("useLocalization", () => {
  test("render inside of a LocalizationProvider", () => {
    const renderer = TestRenderer.create(
      <LocalizationProvider l10n={new ReactLocalization([])}>
        <DummyComponent />
      </LocalizationProvider>
    );
    expect(renderer.toJSON()).toMatchInlineSnapshot(`

        foo

    `);
  });

  test("render outside of a LocalizationProvider", () => {
    const renderer = TestRenderer.create(<DummyComponent />);
    expect(renderer.toJSON()).toMatchInlineSnapshot(`

        foo

    `);
  });

  test("useLocalization should exposes getString from ReactLocalization", () => {
    const bundle = new FluentBundle("en", { useIsolating: false });
    bundle.addResource(
      new FluentResource(`
foo = FOO
`)
    );

    const renderer = TestRenderer.create(
      <LocalizationProvider l10n={new ReactLocalization([bundle])}>
        <DummyComponent />
      </LocalizationProvider>
    );

    expect(renderer.toJSON()).toMatchInlineSnapshot(`

        FOO

    `);
  });
});
<commit_msg>Update fluent-react/test/use_localization.test.js<commit_after>import React from "react";
import TestRenderer from "react-test-renderer";
import { FluentBundle, FluentResource } from "@fluent/bundle";
import { ReactLocalization, LocalizationProvider, useLocalization } from "../esm/index";

function DummyComponent() {
  const { l10n } = useLocalization();

  return (

{l10n.getString('foo')}

  );
}

describe("useLocalization", () => {
  test("render inside of a LocalizationProvider", () => {
    const renderer = TestRenderer.create(
      <LocalizationProvider l10n={new ReactLocalization([])}>
        <DummyComponent />
      </LocalizationProvider>
    );
    expect(renderer.toJSON()).toMatchInlineSnapshot(`

        foo

    `);
  });

  test("render outside of a LocalizationProvider", () => {
    const renderer = TestRenderer.create(<DummyComponent />);
    expect(renderer.toJSON()).toMatchInlineSnapshot(`

        foo

    `);
  });

  test("useLocalization exposes getString from ReactLocalization", () => {
    const bundle = new FluentBundle("en", { useIsolating: false });
    bundle.addResource(
      new FluentResource(`
foo = FOO
`)
    );

    const renderer = TestRenderer.create(
      <LocalizationProvider l10n={new ReactLocalization([bundle])}>
        <DummyComponent />
      </LocalizationProvider>
    );

    expect(renderer.toJSON()).toMatchInlineSnapshot(`

        FOO

    `);
  });
});
<|endoftext|>


<commit_before>/*
 *  jQuery prioritize events
 *
 *  A jQuery plugin that adds controls to the selected jQuery
 *  elements with a simple call.
 *
 *  Example:
 *
 *      $("img").imageUpload();
 *
 *  Copyright (c) jillix GmbH
 *  License: MIT License
 *
 * */
(function ($) {

   /*
    * $("[jQuery selector]").imageUpload({...});
    * */
    $.fn.imageUpload = function(options) {

        // defaults
        var settings = $.extend( {

            wrapContent: "
",

            inputFileName: "inputFile",
            inputFileClass: "inputFile",

            uploadButtonValue: "Upload",
            uploadButtonClass: "uploadButton",

            browseButtonClass: "browseButton",
            browseButtonValue: "Browse",

            formClass: "controlForm",

            hideFileInput: true,

            uploadIframe: ".uploadIframe",

            hover: true,

            addClass: "jQuery-image-upload"
        }, options);

        // selected jQuery objects
        var $self = this;

        // return if no elements
        if (!$self.length) { return $self; }

        // call image upload for each element
        if ($self.length > 1) {
            $self.each(function () {
                $(this).imageUpload(settings);
            });
            return $self;
        }

        $self.addClass(settings.addClass);

        // form action not provided
        if (!settings.formAction) {
            throw new Error ("Form action was not provided. Please provide it: $(...).imageUpload({formAction: '...'})");
        }

        // wrap
        if (!settings.hover) {
            $self.wrap(settings.wrapContent)
        }

        // create the controls div
        var $controls       = $("
").addClass("controls")
          , $fileInput      = $("<input>")
                                .attr("type", "file")
                                .addClass(settings.inputFileClass)
                                .attr("name", settings.inputFileName)

          , $uploadButton   = $("<button>")
                                .attr("type", "submit")
                                .addClass(settings.uploadButtonClass)
                                .html(settings.uploadButtonValue)

          , $browseButton   = $("<button>")
                                .addClass(settings.browseButtonClass)
                                .html(settings.browseButtonValue)
                                .on("click", function () { $fileInput.click(); })

          , $uploadIframe   = $("")
                                .attr("id", "uploadIframe-" + Math.random().toString(36).substring(5, 20).toUpperCase())
                                .hide()

          , $uploadForm     = $("<form>")
                                .addClass(settings.formClass)
                                .attr("target", $uploadIframe.attr("id"))
                                .attr("enctype", "multipart/form-data")
                                .attr("method", "post")
                                .attr("action", settings.formAction);

        // append controls to form
        $uploadForm.append([$browseButton, $fileInput, $uploadButton, $uploadIframe]);

        // hide file input
        if (settings.hideFileInput) {
            $fileInput.hide();
        } else {
            // hide browse button
            $browseButton.hide();
        }

        // append $form to $controls
        $controls.append($uploadForm);

        // form on submit
        $uploadForm.on("submit", function () {

            // get submiited form
            var $form = $(this);

            // unset the load handler
            $uploadIframe.off("load");

            // set it again
            $uploadIframe.on("load", function () {

                // get text from the page
                var result = $(this.contentWindow.document).text();

                // if no result, return
                if (!result) { return; }

                // verify file input value
                if (!$fileInput.val()) {
                    return;
                }

                // try to parse result
                try {
                    result = JSON.parse(result);
                } catch (e) {
                    // nothing to do
                }

                // set src of iframe
                $uploadIframe.attr("src", "");

                // upadte the image source
                $self.attr("src", result);

                // trigger image changed event
                $self.trigger("imageChanged");

                // replace the file input
                $fileInput.replaceWith($fileInput.clone(true));
            });
        });

        // no hover
        if (!settings.hover) {

            // append controls to image wrapper
            $self.parent().append($controls);
        } else {

            // set absolute position to controls and set the offset
            $controls.css({ position: "absolute" });

            // add class to controls
            $controls.addClass("jQuery-image-upload-controls");

            // append controls to body
            $("body").append($controls.hide());

            // self on mouse enter
            $self.on("mouseenter", function () {

                // get the self offset
                var offset = $self.offset();

                // set control possition
                $controls.css({
                    top: offset.top,
                    left: offset.left
                });

                // show controls
                $controls.show();
            });

            // on mouse leave
            $("body").on("mouseleave", "." + settings.addClass, function (e) {

                // get position
                var o = $self.offset()

                    // width
                  , w = $self.width()

                    // and the hegiht
                  , h = $self.height();

                // hide controls
                if ((e.pageX < o.left || e.pageX > o.left + w) ||
                    (e.pageY < o.top || e.pageY > o.top + h)) {
                    $controls.hide();
                }
            });
        }

        // return selected element
        return $self;
    };
})($);
<commit_msg>Fixed #1. Set the defaults.<commit_after>/*
 *  jQuery prioritize events
 *
 *  A jQuery plugin that adds controls to the selected jQuery
 *  elements with a simple call.
 *
 *  Example:
 *
 *      $("img").imageUpload();
 *
 *  Copyright (c) jillix GmbH
 *  License: MIT License
 *
 * */
(function ($) {

    // defaults
    var defaults = {
            wrapContent: "
",

            inputFileName: "inputFile",
            inputFileClass: "inputFile",

            uploadButtonValue: "Upload",
            uploadButtonClass: "uploadButton",

            browseButtonClass: "browseButton",
            browseButtonValue: "Browse",

            formClass: "controlForm",

            hideFileInput: true,

            uploadIframe: ".uploadIframe",

            hover: true,

            addClass: "jQuery-image-upload"
    };

   /*
    * $("[jQuery selector]").imageUpload({...});
    * */
    $.fn.imageUpload = function(options) {

        // defaults
        var settings = $.extend(defaults, options);

        // selected jQuery objects
        var $self = this;

        // return if no elements
        if (!$self.length) { return $self; }

        // call image upload for each element
        if ($self.length > 1) {
            $self.each(function () {
                $(this).imageUpload(settings);
            });
            return $self;
        }

        $self.addClass(settings.addClass);

        // form action not provided
        if (!settings.formAction) {
            throw new Error ("Form action was not provided. Please provide it: $(...).imageUpload({formAction: '...'})");
        }

        // wrap
        if (!settings.hover) {
            $self.wrap(settings.wrapContent)
        }

        // create the controls div
        var $controls       = $("
").addClass("controls")
          , $fileInput      = $("<input>")
                                .attr("type", "file")
                                .addClass(settings.inputFileClass)
                                .attr("name", settings.inputFileName)

          , $uploadButton   = $("<button>")
                                .attr("type", "submit")
                                .addClass(settings.uploadButtonClass)
                                .html(settings.uploadButtonValue)

          , $browseButton   = $("<button>")
                                .addClass(settings.browseButtonClass)
                                .html(settings.browseButtonValue)
                                .on("click", function () { $fileInput.click(); })

          , $uploadIframe   = $("")
                                .attr("id", "uploadIframe-" + Math.random().toString(36).substring(5, 20).toUpperCase())
                                .hide()

          , $uploadForm     = $("<form>")
                                .addClass(settings.formClass)
                                .attr("target", $uploadIframe.attr("id"))
                                .attr("enctype", "multipart/form-data")
                                .attr("method", "post")
                                .attr("action", settings.formAction);

        // append controls to form
        $uploadForm.append([$browseButton, $fileInput, $uploadButton, $uploadIframe]);

        // hide file input
        if (settings.hideFileInput) {
            $fileInput.hide();
        } else {
            // hide browse button
            $browseButton.hide();
        }

        // append $form to $controls
        $controls.append($uploadForm);

        // form on submit
        $uploadForm.on("submit", function () {

            // get submiited form
            var $form = $(this);

            // unset the load handler
            $uploadIframe.off("load");

            // set it again
            $uploadIframe.on("load", function () {

                // get text from the page
                var result = $(this.contentWindow.document).text();

                // if no result, return
                if (!result) { return; }

                // verify file input value
                if (!$fileInput.val()) {
                    return;
                }

                // try to parse result
                try {
                    result = JSON.parse(result);
                } catch (e) {
                    // nothing to do
                }

                // set src of iframe
                $uploadIframe.attr("src", "");

                // upadte the image source
                $self.attr("src", result);

                // trigger image changed event
                $self.trigger("imageChanged");

                // replace the file input
                $fileInput.replaceWith($fileInput.clone(true));
            });
        });

        // no hover
        if (!settings.hover) {

            // append controls to image wrapper
            $self.parent().append($controls);
        } else {

            // set absolute position to controls and set the offset
            $controls.css({ position: "absolute" });

            // add class to controls
            $controls.addClass("jQuery-image-upload-controls");

            // append controls to body
            $("body").append($controls.hide());

            // self on mouse enter
            $self.on("mouseenter", function () {

                // get the self offset
                var offset = $self.offset();

                // set control possition
                $controls.css({
                    top: offset.top,
                    left: offset.left
                });

                // show controls
                $controls.show();
            });

            // on mouse leave
            $("body").on("mouseleave", "." + settings.addClass, function (e) {

                // get position
                var o = $self.offset()

                    // width
                  , w = $self.width()

                    // and the hegiht
                  , h = $self.height();

                // hide controls
                if ((e.pageX < o.left || e.pageX > o.left + w) ||
                    (e.pageY < o.top || e.pageY > o.top + h)) {
                    $controls.hide();
                }
            });
        }

        // return selected element
        return $self;
    };

    // defaults
    $.imageUpload = $.fn.imageUpload;
    $.imageUpload.defaults = defaults;
})($);
<|endoftext|>


<commit_before>/* global window */

import React                           from 'react';

import vtkOpenGLRenderWindow           from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow';
import vtkSynchronizableRenderWindow   from 'vtk.js/Sources/Rendering/Misc/SynchronizableRenderWindow';
import vtkRenderWindowInteractor       from 'vtk.js/Sources/Rendering/Core/RenderWindowInteractor';
import vtkInteractorStyleManipulator   from 'vtk.js/Sources/Interaction/Style/InteractorStyleManipulator';
import vtkTrackballPan                 from 'vtk.js/Sources/Interaction/Manipulators/TrackballPan';
import vtkTrackballZoom                from 'vtk.js/Sources/Interaction/Manipulators/TrackballZoom';
import vtkTrackballRotate              from 'vtk.js/Sources/Interaction/Manipulators/TrackballRotate';

const SYNCHRONIZATION_CONTEXT_NAME = 'pvwLocalRenderingContext';
const ACTIVE_VIEW_ID = '-1';

export default class VtkGeometryRenderer extends React.Component {
  constructor(props) {
    super(props);

    this.geometryTopicSubscription = null;

    // Set up initial state
    this.state = {
      viewId: props.viewId,
    };

    // Get our hands on the default synchronization context and tell how to fetch data arrays
    this.synchCtx = vtkSynchronizableRenderWindow.getSynchronizerContext(props.synchronizerContextName);
    this.synchCtx.setFetchArrayFunction(props.client.VtkGeometryDelivery.getArray);

    // VTK renderWindow/renderer
    const initialValues = { synchronizerContextName: props.synchronizerContextName };
    if (this.state.viewId !== ACTIVE_VIEW_ID) {
      initialValues.viewId = this.state.viewId;
    }

    this.renderWindow = vtkSynchronizableRenderWindow.newInstance(initialValues);

    // OpenGlRenderWindow
    this.openGlRenderWindow = vtkOpenGLRenderWindow.newInstance({ notifyImageReady: !!props.onImageReady });

    if (props.onImageReady) {
      this.imageReadySubscription = this.openGlRenderWindow.onImageReady(props.onImageReady);
    }
    this.renderWindow.addView(this.openGlRenderWindow);

    this.interactorStyle = vtkInteractorStyleManipulator.newInstance();

    const panManipulator = vtkTrackballPan.newInstance();
    panManipulator.setButton(1);
    panManipulator.setShift(false);
    panManipulator.setControl(true);
    this.interactorStyle.addManipulator(panManipulator);

    const zoomManipulator = vtkTrackballZoom.newInstance();
    zoomManipulator.setButton(1);
    zoomManipulator.setShift(true);
    zoomManipulator.setControl(false);
    this.interactorStyle.addManipulator(zoomManipulator);

    const rotateManipulator = vtkTrackballRotate.newInstance();
    rotateManipulator.setButton(1);
    rotateManipulator.setShift(false);
    rotateManipulator.setControl(false);
    this.interactorStyle.addManipulator(rotateManipulator);

    // Interactor
    this.interactor = vtkRenderWindowInteractor.newInstance();
    this.interactor.setView(this.openGlRenderWindow);
    this.interactor.setInteractorStyle(this.interactorStyle);
    this.interactor.initialize();

    // Method binding
    this.viewChanged = this.viewChanged.bind(this);
    this.addViewObserver = this.addViewObserver.bind(this);
    this.removeViewObserver = this.removeViewObserver.bind(this);
    this.subscribeViewChangeTopic = this.subscribeViewChangeTopic.bind(this);
    this.unsubscribeViewChangeTopic = this.unsubscribeViewChangeTopic.bind(this);
    this.updateRenderWindowSize = this.updateRenderWindowSize.bind(this);
  }

  componentDidMount() {
    this.openGlRenderWindow.setContainer(this.rootContainer);
    this.interactor.bindEvents(this.rootContainer);

    // Subscribe to pubsub topic and add view observer
    this.subscribeViewChangeTopic();
    this.addViewObserver(this.state.viewId);

    if (this.props.resizeOnWindowResize) {
      window.addEventListener('resize', this.updateRenderWindowSize);
    }

    this.updateRenderWindowSize();
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.viewId !== this.state.viewId && this.state.viewId !== '-1') {
      // Update observers for change in view id
      this.removeViewObserver(this.state.viewId);
      this.addViewObserver(nextProps.viewId);

      // dump the synchronizable render window and make a new one
      this.renderWindow.removeView(this.openGlRenderWindow);
      this.renderWindow.delete();
      const initialValues = { synchronizerContextName: this.props.synchronizerContextName };
      if (nextProps.viewId !== ACTIVE_VIEW_ID) {
        initialValues.viewId = nextProps.viewId;
      }
      this.renderWindow = vtkSynchronizableRenderWindow.newInstance(initialValues);
      this.renderWindow.addView(this.openGlRenderWindow);
    }

    if (nextProps.onImageReady !== this.props.onImageReady) {
      this.setNotifyImageReady(nextProps.onImageReady);
    }
  }

  componentWillUnmount() {
    this.interactor.unbindEvents(this.rootContainer);
    this.unsubscribeViewChangeTopic();
    this.removeViewObserver(this.state.viewId);

    if (this.props.clearOneTimeUpdatersOnUnmount) {
      this.renderWindow.clearOneTimeUpdaters();
    }

    if (this.props.clearInstanceCacheOnUnmount) {
      this.synchCtx.emptyCachedInstances();
    }

    if (this.props.clearArrayCacheOnUnmount) {
      this.synchCtx.emptyCachedArrays();
    }
  }

  setNotifyImageReady(onImageReady) {
    if (this.openGlRenderWindow) {
      const notify = !!onImageReady;
      this.openGlRenderWindow.setNotifyImageReady(notify);
      if (notify) {
        this.imageReadySubscription = this.openGlRenderWindow.onImageReady(onImageReady);
        this.renderWindow.render();
      } else if (this.imageReadySubscription) {
        this.imageReadySubscription.unsubscribe();
      }
    }
  }

  getCameraParameters() {
    // FIXME: find the proper way to get the renderer we care about
    // Calling getCurrentRenderer() on the interactorStyle seems to return null
    // const activeCamera = this.interactorStyle.getCurrentRenderer().getActiveCamera();
    const activeCamera = this.renderWindow.getRenderers()[0].getActiveCamera();
    const cameraParams = activeCamera.get('position', 'focalPoint', 'viewUp');
    return Object.assign({}, cameraParams, { centerOfRotation: this.interactorStyle.getCenterOfRotation() });
  }

  setCameraParameters({ position, focalPoint, viewUp, centerOfRotation }) {
    const activeCamera = this.renderWindow.getRenderers()[0].getActiveCamera();
    activeCamera.set({ position, focalPoint, viewUp });
    this.interactorStyle.setCenterOfRotation(centerOfRotation);
    this.renderWindow.render();
  }

  getRenderWindow() {
    return this.renderWindow;
  }

  getManipulatorInteractorStyle() {
    return this.interactorStyle;
  }

  resetCamera() {
    this.renderWindow.getRenderers().forEach(renderer => renderer.resetCamera());
  }

  updateRenderWindowSize() {
    const dims = this.rootContainer.getBoundingClientRect();
    this.openGlRenderWindow.setSize(dims.width, dims.height);
    this.renderWindow.render();
  }

  unsubscribeViewChangeTopic() {
    this.props.client.VtkGeometryDelivery.offViewChange(this.geometryTopicSubscription)
      .then((unsubSuccess) => {
        // console.log('Unsubscribe resolved ', unsubSuccess);
      }, (unsubFailure) => {
        console.log('Unsubscribe resolved ', unsubFailure);
      });
  }

  subscribeViewChangeTopic() {
    this.props.client.VtkGeometryDelivery.onViewChange(this.viewChanged).then((subscription) => {
      this.geometryTopicSubscription = subscription;
    }, (subError) => {
      console.log('Failed to subscribe to topic');
      console.log(subError);
    });
  }

  removeViewObserver(viewId) {
    this.props.client.VtkGeometryDelivery.removeViewObserver(viewId).then((successResult) => {
      // console.log(`Removed observer from view ${viewId} succeeded`);
      // console.log(successResult);
    }, (failureResult) => {
      console.log(`Failed to remove observer from view ${viewId}`);
      console.log(failureResult);
    });
  }

  addViewObserver(viewId) {
    this.props.client.VtkGeometryDelivery.addViewObserver(viewId).then((successResult) => {
      // console.log(`Successfully added observer to view ${viewId}`);
      // console.log(successResult);
      this.props.viewIdUpdated(successResult.viewId);
      this.setState({ viewId: successResult.viewId });
    }, (failureResult) => {
      console.log(`Failed to add observer to view ${viewId}`);
      console.log(failureResult);
    });
  }

  viewChanged(data) {
    const viewState = data[0];
    if (viewState.extra && viewState.extra.centerOfRotation) {
      this.interactorStyle.setCenterOfRotation(viewState.extra.centerOfRotation);
    }
    this.renderWindow.synchronize(viewState);
  }

  render() {
    return
 (this.rootContainer = c)} />;
  }
}

VtkGeometryRenderer.propTypes = {
  className: React.PropTypes.string,
  showFPS: React.PropTypes.bool,
  style: React.PropTypes.object,
  viewId: React.PropTypes.string,
  interactionTimout: React.PropTypes.number,
  synchronizerContextName: React.PropTypes.string,
  resizeOnWindowResize: React.PropTypes.bool,
  clearOneTimeUpdatersOnUnmount: React.PropTypes.bool,
  clearInstanceCacheOnUnmount: React.PropTypes.bool,
  clearArrayCacheOnUnmount: React.PropTypes.bool,
  onImageReady: React.PropTypes.func,
  viewIdUpdated: React.PropTypes.func,
  client: React.PropTypes.object,
  connection: React.PropTypes.object,
};

VtkGeometryRenderer.defaultProps = {
  className: '',
  showFPS: false,
  style: {},
  viewId: ACTIVE_VIEW_ID,
  interactionTimout: 500,
  synchronizerContextName: SYNCHRONIZATION_CONTEXT_NAME,
  resizeOnWindowResize: false,
  clearOneTimeUpdatersOnUnmount: false,
  clearInstanceCacheOnUnmount: false,
  clearArrayCacheOnUnmount: false,
};
<commit_msg>fix(VtkGeometryRenderer): Handle active camera if provided<commit_after>/* global window */

import React                           from 'react';

import vtkOpenGLRenderWindow           from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow';
import vtkSynchronizableRenderWindow   from 'vtk.js/Sources/Rendering/Misc/SynchronizableRenderWindow';
import vtkRenderWindowInteractor       from 'vtk.js/Sources/Rendering/Core/RenderWindowInteractor';
import vtkInteractorStyleManipulator   from 'vtk.js/Sources/Interaction/Style/InteractorStyleManipulator';
import vtkTrackballPan                 from 'vtk.js/Sources/Interaction/Manipulators/TrackballPan';
import vtkTrackballZoom                from 'vtk.js/Sources/Interaction/Manipulators/TrackballZoom';
import vtkTrackballRotate              from 'vtk.js/Sources/Interaction/Manipulators/TrackballRotate';

const SYNCHRONIZATION_CONTEXT_NAME = 'pvwLocalRenderingContext';
const ACTIVE_VIEW_ID = '-1';

export default class VtkGeometryRenderer extends React.Component {
  constructor(props) {
    super(props);

    this.geometryTopicSubscription = null;

    // Set up initial state
    this.state = {
      viewId: props.viewId,
    };

    // Get our hands on the default synchronization context and tell how to fetch data arrays
    this.synchCtx = vtkSynchronizableRenderWindow.getSynchronizerContext(props.synchronizerContextName);
    this.synchCtx.setFetchArrayFunction(props.client.VtkGeometryDelivery.getArray);

    // VTK renderWindow/renderer
    const initialValues = { synchronizerContextName: props.synchronizerContextName };
    if (this.state.viewId !== ACTIVE_VIEW_ID) {
      initialValues.viewId = this.state.viewId;
    }

    this.renderWindow = vtkSynchronizableRenderWindow.newInstance(initialValues);

    // OpenGlRenderWindow
    this.openGlRenderWindow = vtkOpenGLRenderWindow.newInstance({ notifyImageReady: !!props.onImageReady });

    if (props.onImageReady) {
      this.imageReadySubscription = this.openGlRenderWindow.onImageReady(props.onImageReady);
    }
    this.renderWindow.addView(this.openGlRenderWindow);

    this.interactorStyle = vtkInteractorStyleManipulator.newInstance();

    const panManipulator = vtkTrackballPan.newInstance();
    panManipulator.setButton(1);
    panManipulator.setShift(false);
    panManipulator.setControl(true);
    this.interactorStyle.addManipulator(panManipulator);

    const zoomManipulator = vtkTrackballZoom.newInstance();
    zoomManipulator.setButton(1);
    zoomManipulator.setShift(true);
    zoomManipulator.setControl(false);
    this.interactorStyle.addManipulator(zoomManipulator);

    const rotateManipulator = vtkTrackballRotate.newInstance();
    rotateManipulator.setButton(1);
    rotateManipulator.setShift(false);
    rotateManipulator.setControl(false);
    this.interactorStyle.addManipulator(rotateManipulator);

    // Interactor
    this.interactor = vtkRenderWindowInteractor.newInstance();
    this.interactor.setView(this.openGlRenderWindow);
    this.interactor.setInteractorStyle(this.interactorStyle);
    this.interactor.initialize();

    // Method binding
    this.viewChanged = this.viewChanged.bind(this);
    this.addViewObserver = this.addViewObserver.bind(this);
    this.removeViewObserver = this.removeViewObserver.bind(this);
    this.subscribeViewChangeTopic = this.subscribeViewChangeTopic.bind(this);
    this.unsubscribeViewChangeTopic = this.unsubscribeViewChangeTopic.bind(this);
    this.updateRenderWindowSize = this.updateRenderWindowSize.bind(this);
  }

  componentDidMount() {
    this.openGlRenderWindow.setContainer(this.rootContainer);
    this.interactor.bindEvents(this.rootContainer);

    // Subscribe to pubsub topic and add view observer
    this.subscribeViewChangeTopic();
    this.addViewObserver(this.state.viewId);

    if (this.props.resizeOnWindowResize) {
      window.addEventListener('resize', this.updateRenderWindowSize);
    }

    this.updateRenderWindowSize();
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.viewId !== this.state.viewId && this.state.viewId !== '-1') {
      // Update observers for change in view id
      this.removeViewObserver(this.state.viewId);
      this.addViewObserver(nextProps.viewId);

      // dump the synchronizable render window and make a new one
      this.renderWindow.removeView(this.openGlRenderWindow);
      this.renderWindow.delete();
      const initialValues = { synchronizerContextName: this.props.synchronizerContextName };
      if (nextProps.viewId !== ACTIVE_VIEW_ID) {
        initialValues.viewId = nextProps.viewId;
      }
      this.renderWindow = vtkSynchronizableRenderWindow.newInstance(initialValues);
      this.renderWindow.addView(this.openGlRenderWindow);
    }

    if (nextProps.onImageReady !== this.props.onImageReady) {
      this.setNotifyImageReady(nextProps.onImageReady);
    }
  }

  componentWillUnmount() {
    this.interactor.unbindEvents(this.rootContainer);
    this.unsubscribeViewChangeTopic();
    this.removeViewObserver(this.state.viewId);

    if (this.props.clearOneTimeUpdatersOnUnmount) {
      this.renderWindow.clearOneTimeUpdaters();
    }

    if (this.props.clearInstanceCacheOnUnmount) {
      this.synchCtx.emptyCachedInstances();
    }

    if (this.props.clearArrayCacheOnUnmount) {
      this.synchCtx.emptyCachedArrays();
    }
  }

  setNotifyImageReady(onImageReady) {
    if (this.openGlRenderWindow) {
      const notify = !!onImageReady;
      this.openGlRenderWindow.setNotifyImageReady(notify);
      if (notify) {
        this.imageReadySubscription = this.openGlRenderWindow.onImageReady(onImageReady);
        this.renderWindow.render();
      } else if (this.imageReadySubscription) {
        this.imageReadySubscription.unsubscribe();
      }
    }
  }

  getCameraParameters() {
    // FIXME: find the proper way to get the renderer we care about
    // Calling getCurrentRenderer() on the interactorStyle seems to return null
    // const activeCamera = this.interactorStyle.getCurrentRenderer().getActiveCamera();
    const activeCamera = this.activeCamera || this.renderWindow.getRenderers()[0].getActiveCamera();
    const cameraParams = activeCamera.get('position', 'focalPoint', 'viewUp');
    return Object.assign({}, cameraParams, { centerOfRotation: this.interactorStyle.getCenterOfRotation() });
  }

  setCameraParameters({ position, focalPoint, viewUp, centerOfRotation }) {
    const activeCamera = this.activeCamera || this.renderWindow.getRenderers()[0].getActiveCamera();
    activeCamera.set({ position, focalPoint, viewUp });
    this.interactorStyle.setCenterOfRotation(centerOfRotation);
    this.renderWindow.render();
  }

  getRenderWindow() {
    return this.renderWindow;
  }

  getManipulatorInteractorStyle() {
    return this.interactorStyle;
  }

  resetCamera() {
    this.renderWindow.getRenderers().forEach(renderer => renderer.resetCamera());
  }

  updateRenderWindowSize() {
    const dims = this.rootContainer.getBoundingClientRect();
    this.openGlRenderWindow.setSize(dims.width, dims.height);
    this.renderWindow.render();
  }

  unsubscribeViewChangeTopic() {
    this.props.client.VtkGeometryDelivery.offViewChange(this.geometryTopicSubscription)
      .then((unsubSuccess) => {
        // console.log('Unsubscribe resolved ', unsubSuccess);
      }, (unsubFailure) => {
        console.log('Unsubscribe resolved ', unsubFailure);
      });
  }

  subscribeViewChangeTopic() {
    this.props.client.VtkGeometryDelivery.onViewChange(this.viewChanged).then((subscription) => {
      this.geometryTopicSubscription = subscription;
    }, (subError) => {
      console.log('Failed to subscribe to topic');
      console.log(subError);
    });
  }

  removeViewObserver(viewId) {
    this.props.client.VtkGeometryDelivery.removeViewObserver(viewId).then((successResult) => {
      // console.log(`Removed observer from view ${viewId} succeeded`);
      // console.log(successResult);
    }, (failureResult) => {
      console.log(`Failed to remove observer from view ${viewId}`);
      console.log(failureResult);
    });
  }

  addViewObserver(viewId) {
    this.props.client.VtkGeometryDelivery.addViewObserver(viewId).then((successResult) => {
      // console.log(`Successfully added observer to view ${viewId}`);
      // console.log(successResult);
      this.props.viewIdUpdated(successResult.viewId);
      this.setState({ viewId: successResult.viewId });
    }, (failureResult) => {
      console.log(`Failed to add observer to view ${viewId}`);
      console.log(failureResult);
    });
  }

  viewChanged(data) {
    const viewState = data[0];
    if (viewState.extra && viewState.extra.centerOfRotation) {
      this.interactorStyle.setCenterOfRotation(viewState.extra.centerOfRotation);
    }
    this.renderWindow.synchronize(viewState);
    if (viewState.extra && viewState.extra.camera) {
      this.activeCamera = this.synchCtx.getInstance(viewState.extra.camera);
    }
  }

  render() {
    return
 (this.rootContainer = c)} />;
  }
}

VtkGeometryRenderer.propTypes = {
  className: React.PropTypes.string,
  showFPS: React.PropTypes.bool,
  style: React.PropTypes.object,
  viewId: React.PropTypes.string,
  interactionTimout: React.PropTypes.number,
  synchronizerContextName: React.PropTypes.string,
  resizeOnWindowResize: React.PropTypes.bool,
  clearOneTimeUpdatersOnUnmount: React.PropTypes.bool,
  clearInstanceCacheOnUnmount: React.PropTypes.bool,
  clearArrayCacheOnUnmount: React.PropTypes.bool,
  onImageReady: React.PropTypes.func,
  viewIdUpdated: React.PropTypes.func,
  client: React.PropTypes.object,
  connection: React.PropTypes.object,
};

VtkGeometryRenderer.defaultProps = {
  className: '',
  showFPS: false,
  style: {},
  viewId: ACTIVE_VIEW_ID,
  interactionTimout: 500,
  synchronizerContextName: SYNCHRONIZATION_CONTEXT_NAME,
  resizeOnWindowResize: false,
  clearOneTimeUpdatersOnUnmount: false,
  clearInstanceCacheOnUnmount: false,
  clearArrayCacheOnUnmount: false,
};
<|endoftext|>


<commit_before>
import API from 'src/util/api';
import UI from 'src/util/ui';
import OCLE from './libs/OCLE';
import CCE from './libs/CCE';

class MF {
    constructor(sample) {
        this.sample = sample;
        // if no mf we calculate from molfile
        if (!this.getMF()) {
            this.fromMolfile();
        } else {
            const mf = this.getMF();
            if (mf) {
                var chemcalc = CCE.analyseMF(this.getMF());
                if (chemcalc) {
                    this.previousEMMF = chemcalc.em;
                }
            }
        }
    }

    fromMolfile() {
        var chemcalc = this._chemcalcFromMolfile();
        if (chemcalc && this.previousEMMolfile !== chemcalc.em) {
            this.previousEMMolfile = chemcalc.em;
            this.setMF(chemcalc.mf);
        } else {
            // why should we suppress the molecular formula if it changed ???
            // this.setMF('');
        }
        API.createData('mfBGColor', 'white');
    }

    _chemcalcFromMolfile() {
        var molfile = this.getMolfile();
        if (molfile) {
            var molecule = OCLE.Molecule.fromMolfile(molfile);
            var mf = molecule.getMolecularFormula().formula;
            try {
                return CCE.analyseMF(mf);
            } catch (e) {
                if (mf !== '') {
                    UI.showNotification('Could not calculate molecular formula: ' + e);
                }
            }
        }
        return null;
    }

    getMF() {
        return String(this.sample.getChildSync(['$content', 'general', 'mf']) || '');
    }

    getMolfile() {
        return String(this.sample.getChildSync(['$content', 'general', 'molfile']));
    }

    setMF(mf) {
        this.sample.setChildSync(['$content', 'general', 'mf'], mf);
    }

    setMW(mw) {
        this.sample.setChildSync(['$content', 'general', 'mw'], mw);
    }

    setEM(em) {
        this.sample.setChildSync(['$content', 'general', 'em'], em);
    }

    fromMF() {
        if (!this.getMF()) {
            this.previousEMMF = 0;
            this.setMW(0);
            this.setEM(0);
            return;
        }
        var chemcalc = CCE.analyseMF(this.getMF());
        if (chemcalc && this.previousEMMF !== chemcalc.em) {
            this.previousEMMF = chemcalc.em;
            this.setMW(chemcalc.mw);
            this.setEM(chemcalc.em);
        }
    }

    _mfColor() {
        var existingMF = this.getMF();
        var molfile = this.getMolfile();
        if (molfile) {
            var molecule = OCLE.Molecule.fromMolfile(molfile);
            var mf = molecule.getMolecularFormula().formula;
            var existingMW = existingMF ? CCE.analyseMF(existingMF).mw : 0;
            var newMW = mf ? CCE.analyseMF(mf).mw : 0;
            if (newMW !== existingMW) {
                API.createData('mfBGColor', 'pink');
            } else {
                API.createData('mfBGColor', 'white');
            }
        } else {
            API.createData('mfBGColor', 'white');
        }
    }
}

module.exports = MF;
<commit_msg>add empty MF if undefined<commit_after>
import API from 'src/util/api';
import UI from 'src/util/ui';
import OCLE from './libs/OCLE';
import CCE from './libs/CCE';

class MF {
    constructor(sample) {
        this.sample = sample;
        // if no mf we calculate from molfile
        if (!this.getMF()) {
            this.fromMolfile();
            if (!this.getMF()) {
                this.setMF('');
            }
        } else {
            const mf = this.getMF();
            if (mf) {
                var chemcalc = CCE.analyseMF(this.getMF());
                if (chemcalc) {
                    this.previousEMMF = chemcalc.em;
                }
            }
        }
    }

    fromMolfile() {
        var chemcalc = this._chemcalcFromMolfile();
        if (chemcalc && this.previousEMMolfile !== chemcalc.em) {
            this.previousEMMolfile = chemcalc.em;
            this.setMF(chemcalc.mf);
        } else {
            // why should we suppress the molecular formula if it changed ???
            // this.setMF('');
        }
        API.createData('mfBGColor', 'white');
    }

    _chemcalcFromMolfile() {
        var molfile = this.getMolfile();
        if (molfile) {
            var molecule = OCLE.Molecule.fromMolfile(molfile);
            var mf = molecule.getMolecularFormula().formula;
            try {
                return CCE.analyseMF(mf);
            } catch (e) {
                if (mf !== '') {
                    UI.showNotification('Could not calculate molecular formula: ' + e);
                }
            }
        }
        return null;
    }

    getMF() {
        return String(this.sample.getChildSync(['$content', 'general', 'mf']) || '');
    }

    getMolfile() {
        return String(this.sample.getChildSync(['$content', 'general', 'molfile']));
    }

    setMF(mf) {
        this.sample.setChildSync(['$content', 'general', 'mf'], mf);
    }

    setMW(mw) {
        this.sample.setChildSync(['$content', 'general', 'mw'], mw);
    }

    setEM(em) {
        this.sample.setChildSync(['$content', 'general', 'em'], em);
    }

    fromMF() {
        if (!this.getMF()) {
            this.previousEMMF = 0;
            this.setMW(0);
            this.setEM(0);
            return;
        }
        var chemcalc = CCE.analyseMF(this.getMF());
        if (chemcalc && this.previousEMMF !== chemcalc.em) {
            this.previousEMMF = chemcalc.em;
            this.setMW(chemcalc.mw);
            this.setEM(chemcalc.em);
        }
    }

    _mfColor() {
        var existingMF = this.getMF();
        var molfile = this.getMolfile();
        if (molfile) {
            var molecule = OCLE.Molecule.fromMolfile(molfile);
            var mf = molecule.getMolecularFormula().formula;
            var existingMW = existingMF ? CCE.analyseMF(existingMF).mw : 0;
            var newMW = mf ? CCE.analyseMF(mf).mw : 0;
            if (newMW !== existingMW) {
                API.createData('mfBGColor', 'pink');
            } else {
                API.createData('mfBGColor', 'white');
            }
        } else {
            API.createData('mfBGColor', 'white');
        }
    }
}

module.exports = MF;
<|endoftext|>


<commit_before>/**
*  Ajax Autocomplete for jQuery, version 1.1.5
*  (c) 2012 Tomas Kirda, Vytautas Pranskunas
*
*  Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
*  For details, see the web site: http://www.devbridge.com/projects/autocomplete/jquery/
*
*  Last Review: 11/08/2012
*/

/*jslint  browser: true, white: true, plusplus: true */
/*global window: true, document: true, clearInterval: true, setInterval: true, jQuery: true */

(function ($) {
    'use strict';

    var reEscape = new RegExp('(\\' + ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'].join('|\\') + ')', 'g');

    function fnFormatResult(value, data, currentValue) {
        var pattern = '(' + currentValue.replace(reEscape, '\\$1') + ')';
        return value.replace(new RegExp(pattern, 'gi'), '$1<\/strong>');
    }

    function Autocomplete(el, options) {
        this.el = $(el);
        this.el.attr('autocomplete', 'off');
        this.suggestions = [];
        this.data = [];
        this.badQueries = [];
        this.selectedIndex = -1;
        this.currentValue = this.el.val();
        this.intervalId = 0;
        this.cachedResponse = [];
        this.onChangeInterval = null;
        this.onChange = null;
        this.ignoreValueChange = false;
        this.serviceUrl = options.serviceUrl;
        this.isLocal = false;
        this.options = {
            autoSubmit: false,
            minChars: 1,
            maxHeight: 300,
            deferRequestBy: 0,
            width: 0,
            highlight: true,
            params: {},
            fnFormatResult: fnFormatResult,
            delimiter: null,
            zIndex: 9999
        };
        this.initialize();
        this.setOptions(options);
        this.el.data('autocomplete', this);
    }

    $.fn.autocomplete = function (options, args) {
        var instance;

        if (typeof options === 'string') {
            instance = this.data('autocomplete');
            if (typeof instance[options] === 'function') {
                instance[options](args);
            }
        } else {
            instance = new Autocomplete(this.get(0) || $('<input />'), options);
        }

        return instance;
    };

    Autocomplete.prototype = {

        killerFn: null,

        initialize: function () {
            var me = this,
                uid = Math.floor(Math.random() * 0x100000).toString(16),
                autocompleteElId = 'Autocomplete_' + uid,
                onKeyPress = function (e) {
                    me.onKeyPress(e);
                };

            this.killerFn = function (e) {
                if ($(e.target).parents('.autocomplete').size() === 0) {
                    me.killSuggestions();
                    me.disableKillerFn();
                }
            };

            if (!this.options.width) {
                this.options.width = this.el.width();
            }

            this.mainContainerId = 'AutocompleteContainter_' + uid;

            $('

').appendTo('body');

            this.container = $('#' + autocompleteElId);
            this.fixPosition();

            if (window.opera) {
                this.el.keypress(onKeyPress);
            } else {
                this.el.keydown(onKeyPress);
            }

            this.el.keyup(function (e) { me.onKeyUp(e); });
            this.el.blur(function () { me.enableKillerFn(); });
            this.el.focus(function () { me.fixPosition(); });
            this.el.change(function () { me.onValueChanged(); });
        },

        extendOptions: function (options) {
            $.extend(this.options, options);
        },

        setOptions: function (options) {
            var o = this.options;

            this.extendOptions(options);

            if (o.lookup || o.isLocal) {
                this.isLocal = true;
                if ($.isArray(o.lookup)) { o.lookup = { suggestions: o.lookup, data: [] }; }
            }

            $('#' + this.mainContainerId).css({ zIndex: o.zIndex });

            this.container.css({ maxHeight: o.maxHeight + 'px', width: o.width });
        },

        clearCache: function () {
            this.cachedResponse = [];
            this.badQueries = [];
        },

        disable: function () {
            this.disabled = true;
        },

        enable: function () {
            this.disabled = false;
        },

        fixPosition: function () {
            var offset = this.el.offset();
            $('#' + this.mainContainerId).css({ top: (offset.top + this.el.innerHeight()) + 'px', left: offset.left + 'px' });
        },

        enableKillerFn: function () {
            var me = this;
            $(document).bind('click', me.killerFn);
        },

        disableKillerFn: function () {
            var me = this;
            $(document).unbind('click', me.killerFn);
        },

        killSuggestions: function () {
            var me = this;
            me.stopKillSuggestions();
            me.intervalId = window.setInterval(function () {
                me.hide();
                me.stopKillSuggestions();
            }, 300);
        },

        stopKillSuggestions: function () {
            window.clearInterval(this.intervalId);
        },

        onValueChanged: function () {
            this.change(this.selectedIndex);
        },

        onKeyPress: function (e) {
            if (this.disabled || !this.enabled) {
                return;
            }

            switch (e.keyCode) {
                case 27: //KEY_ESC:
                    this.el.val(this.currentValue);
                    this.hide();
                    break;
                case 9: //KEY_TAB:
                case 13: //KEY_RETURN:
                    if (this.selectedIndex === -1) {
                        this.hide();
                        return;
                    }
                    this.select(this.selectedIndex);
                    if (e.keyCode === 9) {
                        return;
                    }
                    break;
                case 38: //KEY_UP:
                    this.moveUp();
                    break;
                case 40: //KEY_DOWN:
                    this.moveDown();
                    break;
                default:
                    return;
            }

            // Cancel event if function did not return:
            e.stopImmediatePropagation();
            e.preventDefault();
        },

        onKeyUp: function (e) {
            if (this.disabled) {
                return;
            }

            switch (e.keyCode) {
                case 38: //KEY_UP:
                case 40: //KEY_DOWN:
                    return;
            }

            clearInterval(this.onChangeInterval);

            if (this.currentValue !== this.el.val()) {
                if (this.options.deferRequestBy > 0) {
                    // Defer lookup in case when value changes very quickly:
                    var me = this;
                    this.onChangeInterval = setInterval(function () { me.onValueChange(); }, this.options.deferRequestBy);
                } else {
                    this.onValueChange();
                }
            }
        },

        onValueChange: function () {
            clearInterval(this.onChangeInterval);
            this.currentValue = this.el.val();
            var q = this.getQuery(this.currentValue);
            this.selectedIndex = -1;

            if (this.ignoreValueChange) {
                this.ignoreValueChange = false;
                return;
            }

            if (q === '' || q.length < this.options.minChars) {
                this.hide();
            } else {
                this.getSuggestions(q);
            }
        },

        getQuery: function (val) {
            var d, arr;
            d = this.options.delimiter;
            if (!d) {
                return $.trim(val);
            }
            arr = val.split(d);
            return $.trim(arr[arr.length - 1]);
        },

        getSuggestionsLocal: function (q) {
            var ret, arr, len, val, i;

            arr = this.options.lookup;
            len = arr.suggestions.length;
            ret = { suggestions: [], data: [] };
            q = q.toLowerCase();

            for (i = 0; i < len; i++) {
                val = arr.suggestions[i];
                if (val.toLowerCase().indexOf(q) === 0) {
                    ret.suggestions.push(val);
                    ret.data.push(arr.data[i]);
                }
            }

            return ret;
        },

        getSuggestions: function (q) {
            var cr, me;

            cr = this.isLocal ? this.getSuggestionsLocal(q) : this.cachedResponse[q];

            if (cr && $.isArray(cr.suggestions)) {
                this.suggestions = cr.suggestions;
                this.data = cr.data;
                this.suggest();
            } else if (!this.isBadQuery(q)) {
                me = this;
                me.options.params.query = q;
                $.get(this.serviceUrl, me.options.params, function (txt) {
                    me.processResponse(txt);
                }, 'text');
            }
        },

        isBadQuery: function (q) {
            var i = this.badQueries.length;

            while (i--) {
                if (q.indexOf(this.badQueries[i]) === 0) {
                    return true;
                }
            }

            return false;
        },

        hide: function () {
            this.enabled = false;
            this.selectedIndex = -1;
            this.container.hide();
        },

        suggest: function () {
            if (this.suggestions.length === 0) {
                this.hide();
                return;
            }

            var me, len, div, f, v, i, s, mOver, mClick;

            me = this;
            len = this.suggestions.length;
            f = this.options.fnFormatResult;
            v = this.getQuery(this.currentValue);

            mOver = function (xi) {
                return function () {
                    me.activate(xi);
                };
            };

            mClick = function (xi) {
                return function () {
                    me.select(xi);
                };
            };

            this.container.hide().empty();

            for (i = 0; i < len; i++) {
                s = this.suggestions[i];
                div = $((me.selectedIndex === i ? '<div class="selected"' : '
' + f(s, this.data[i], v) + '
');
                div.mouseover(mOver(i));
                div.click(mClick(i));
                this.container.append(div);
            }

            this.enabled = true;
            this.container.show();
        },

        processResponse: function (text) {
            /*jslint evil: true */
            var response;

            try {
                response = eval('(' + text + ')');
            } catch (err) {
                return;
            }

            if (!$.isArray(response.data)) {
                response.data = [];
            }

            if (!this.options.noCache) {
                this.cachedResponse[response.query] = response;
                if (response.suggestions.length === 0) {
                    this.badQueries.push(response.query);
                }
            }

            if (response.query === this.getQuery(this.currentValue)) {
                this.suggestions = response.suggestions;
                this.data = response.data;
                this.suggest();
            }
        },

        activate: function (index) {
            var divs, activeItem;

            divs = this.container.children();
            // Clear previous selection:
            if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
                $(divs.get(this.selectedIndex)).removeClass();
            }

            this.selectedIndex = index;

            if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
                activeItem = divs.get(this.selectedIndex);
                $(activeItem).addClass('selected');
                return activeItem;
            }

            return null;
        },

        deactivate: function (div, index) {
            div.className = '';
            if (this.selectedIndex === index) {
                this.selectedIndex = -1;
            }
        },

        select: function (i) {
            var selectedValue, f;

            selectedValue = this.suggestions[i];

            if (selectedValue) {
                this.el.val(selectedValue);
                if (this.options.autoSubmit) {
                    f = this.el.parents('form');
                    if (f.length > 0) {
                        f.get(0).submit();
                    }
                }
                this.ignoreValueChange = true;
                this.hide();
                this.onSelect(i);
            }
        },

        change: function (i) {
            var selectedValue, onChange, me, s, d;

            me = this;
            selectedValue = this.suggestions[i];

            if (selectedValue) {
                s = me.suggestions[i];
                d = me.data[i];
                me.el.val(me.getValue(s));
            } else {
                s = '';
                d = -1;
            }

            onChange = me.options.onChange;
            if ($.isFunction(onChange)) {
                onChange(s, d, me.el);
            }
        },

        moveUp: function () {
            if (this.selectedIndex === -1) {
                return;
            }

            if (this.selectedIndex === 0) {
                this.container.children().get(0).className = '';
                this.selectedIndex = -1;
                this.el.val(this.currentValue);
                return;
            }

            this.adjustScroll(this.selectedIndex - 1);
        },

        moveDown: function () {
            if (this.selectedIndex === (this.suggestions.length - 1)) {
                return;
            }

            this.adjustScroll(this.selectedIndex + 1);
        },

        adjustScroll: function (i) {
            var activeItem, offsetTop, upperBound, lowerBound;

            activeItem = this.activate(i);
            offsetTop = activeItem.offsetTop;
            upperBound = this.container.scrollTop();
            lowerBound = upperBound + this.options.maxHeight - 25;

            if (offsetTop < upperBound) {
                this.container.scrollTop(offsetTop);
            } else if (offsetTop > lowerBound) {
                this.container.scrollTop(offsetTop - this.options.maxHeight + 25);
            }

            this.el.val(this.getValue(this.suggestions[i]));
        },

        onSelect: function (i) {
            var me = this,
                callback = me.options.onSelect,
                sugestion = me.suggestions[i],
                data = me.data[i];

            me.el.val(me.getValue(sugestion));

            if ($.isFunction(callback)) {
                callback(sugestion, data, me.el);
            }
        },

        getValue: function (value) {
            var me = this,
                separator = me.options.delimiter,
                currentValue,
                array;

            if (!separator) {
                return value;
            }

            currentValue = me.currentValue;
            array = currentValue.split(separator);

            if (array.length === 1) {
                return value;
            }

            return currentValue.substr(0, currentValue.length - array[array.length - 1].length) + value;
        }
    };
}(jQuery));
<commit_msg>Use outerHeight instead of innerHeight<commit_after>/**
*  Ajax Autocomplete for jQuery, version 1.1.5
*  (c) 2012 Tomas Kirda, Vytautas Pranskunas
*
*  Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
*  For details, see the web site: http://www.devbridge.com/projects/autocomplete/jquery/
*
*  Last Review: 11/08/2012
*/

/*jslint  browser: true, white: true, plusplus: true */
/*global window: true, document: true, clearInterval: true, setInterval: true, jQuery: true */

(function ($) {
    'use strict';

    var reEscape = new RegExp('(\\' + ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'].join('|\\') + ')', 'g');

    function fnFormatResult(value, data, currentValue) {
        var pattern = '(' + currentValue.replace(reEscape, '\\$1') + ')';
        return value.replace(new RegExp(pattern, 'gi'), '$1<\/strong>');
    }

    function Autocomplete(el, options) {
        this.el = $(el);
        this.el.attr('autocomplete', 'off');
        this.suggestions = [];
        this.data = [];
        this.badQueries = [];
        this.selectedIndex = -1;
        this.currentValue = this.el.val();
        this.intervalId = 0;
        this.cachedResponse = [];
        this.onChangeInterval = null;
        this.onChange = null;
        this.ignoreValueChange = false;
        this.serviceUrl = options.serviceUrl;
        this.isLocal = false;
        this.options = {
            autoSubmit: false,
            minChars: 1,
            maxHeight: 300,
            deferRequestBy: 0,
            width: 0,
            highlight: true,
            params: {},
            fnFormatResult: fnFormatResult,
            delimiter: null,
            zIndex: 9999
        };
        this.initialize();
        this.setOptions(options);
        this.el.data('autocomplete', this);
    }

    $.fn.autocomplete = function (options, args) {
        var instance;

        if (typeof options === 'string') {
            instance = this.data('autocomplete');
            if (typeof instance[options] === 'function') {
                instance[options](args);
            }
        } else {
            instance = new Autocomplete(this.get(0) || $('<input />'), options);
        }

        return instance;
    };

    Autocomplete.prototype = {

        killerFn: null,

        initialize: function () {
            var me = this,
                uid = Math.floor(Math.random() * 0x100000).toString(16),
                autocompleteElId = 'Autocomplete_' + uid,
                onKeyPress = function (e) {
                    me.onKeyPress(e);
                };

            this.killerFn = function (e) {
                if ($(e.target).parents('.autocomplete').size() === 0) {
                    me.killSuggestions();
                    me.disableKillerFn();
                }
            };

            if (!this.options.width) {
                this.options.width = this.el.outerWidth();
            }

            this.mainContainerId = 'AutocompleteContainter_' + uid;

            $('

').appendTo('body');

            this.container = $('#' + autocompleteElId);
            this.fixPosition();

            if (window.opera) {
                this.el.keypress(onKeyPress);
            } else {
                this.el.keydown(onKeyPress);
            }

            this.el.keyup(function (e) { me.onKeyUp(e); });
            this.el.blur(function () { me.enableKillerFn(); });
            this.el.focus(function () { me.fixPosition(); });
            this.el.change(function () { me.onValueChanged(); });
        },

        extendOptions: function (options) {
            $.extend(this.options, options);
        },

        setOptions: function (options) {
            var o = this.options;

            this.extendOptions(options);

            if (o.lookup || o.isLocal) {
                this.isLocal = true;
                if ($.isArray(o.lookup)) { o.lookup = { suggestions: o.lookup, data: [] }; }
            }

            $('#' + this.mainContainerId).css({ zIndex: o.zIndex });

            this.container.css({ maxHeight: o.maxHeight + 'px', width: o.width });
        },

        clearCache: function () {
            this.cachedResponse = [];
            this.badQueries = [];
        },

        disable: function () {
            this.disabled = true;
        },

        enable: function () {
            this.disabled = false;
        },

        fixPosition: function () {
            var offset = this.el.offset();
            $('#' + this.mainContainerId).css({ top: (offset.top + this.el.outerHeight()) + 'px', left: offset.left + 'px' });
        },

        enableKillerFn: function () {
            var me = this;
            $(document).bind('click', me.killerFn);
        },

        disableKillerFn: function () {
            var me = this;
            $(document).unbind('click', me.killerFn);
        },

        killSuggestions: function () {
            var me = this;
            me.stopKillSuggestions();
            me.intervalId = window.setInterval(function () {
                me.hide();
                me.stopKillSuggestions();
            }, 300);
        },

        stopKillSuggestions: function () {
            window.clearInterval(this.intervalId);
        },

        onValueChanged: function () {
            this.change(this.selectedIndex);
        },

        onKeyPress: function (e) {
            if (this.disabled || !this.enabled) {
                return;
            }

            switch (e.keyCode) {
                case 27: //KEY_ESC:
                    this.el.val(this.currentValue);
                    this.hide();
                    break;
                case 9: //KEY_TAB:
                case 13: //KEY_RETURN:
                    if (this.selectedIndex === -1) {
                        this.hide();
                        return;
                    }
                    this.select(this.selectedIndex);
                    if (e.keyCode === 9) {
                        return;
                    }
                    break;
                case 38: //KEY_UP:
                    this.moveUp();
                    break;
                case 40: //KEY_DOWN:
                    this.moveDown();
                    break;
                default:
                    return;
            }

            // Cancel event if function did not return:
            e.stopImmediatePropagation();
            e.preventDefault();
        },

        onKeyUp: function (e) {
            if (this.disabled) {
                return;
            }

            switch (e.keyCode) {
                case 38: //KEY_UP:
                case 40: //KEY_DOWN:
                    return;
            }

            clearInterval(this.onChangeInterval);

            if (this.currentValue !== this.el.val()) {
                if (this.options.deferRequestBy > 0) {
                    // Defer lookup in case when value changes very quickly:
                    var me = this;
                    this.onChangeInterval = setInterval(function () { me.onValueChange(); }, this.options.deferRequestBy);
                } else {
                    this.onValueChange();
                }
            }
        },

        onValueChange: function () {
            clearInterval(this.onChangeInterval);
            this.currentValue = this.el.val();
            var q = this.getQuery(this.currentValue);
            this.selectedIndex = -1;

            if (this.ignoreValueChange) {
                this.ignoreValueChange = false;
                return;
            }

            if (q === '' || q.length < this.options.minChars) {
                this.hide();
            } else {
                this.getSuggestions(q);
            }
        },

        getQuery: function (val) {
            var d, arr;
            d = this.options.delimiter;
            if (!d) {
                return $.trim(val);
            }
            arr = val.split(d);
            return $.trim(arr[arr.length - 1]);
        },

        getSuggestionsLocal: function (q) {
            var ret, arr, len, val, i;

            arr = this.options.lookup;
            len = arr.suggestions.length;
            ret = { suggestions: [], data: [] };
            q = q.toLowerCase();

            for (i = 0; i < len; i++) {
                val = arr.suggestions[i];
                if (val.toLowerCase().indexOf(q) === 0) {
                    ret.suggestions.push(val);
                    ret.data.push(arr.data[i]);
                }
            }

            return ret;
        },

        getSuggestions: function (q) {
            var cr, me;

            cr = this.isLocal ? this.getSuggestionsLocal(q) : this.cachedResponse[q];

            if (cr && $.isArray(cr.suggestions)) {
                this.suggestions = cr.suggestions;
                this.data = cr.data;
                this.suggest();
            } else if (!this.isBadQuery(q)) {
                me = this;
                me.options.params.query = q;
                $.get(this.serviceUrl, me.options.params, function (txt) {
                    me.processResponse(txt);
                }, 'text');
            }
        },

        isBadQuery: function (q) {
            var i = this.badQueries.length;

            while (i--) {
                if (q.indexOf(this.badQueries[i]) === 0) {
                    return true;
                }
            }

            return false;
        },

        hide: function () {
            this.enabled = false;
            this.selectedIndex = -1;
            this.container.hide();
        },

        suggest: function () {
            if (this.suggestions.length === 0) {
                this.hide();
                return;
            }

            var me, len, div, f, v, i, s, mOver, mClick;

            me = this;
            len = this.suggestions.length;
            f = this.options.fnFormatResult;
            v = this.getQuery(this.currentValue);

            mOver = function (xi) {
                return function () {
                    me.activate(xi);
                };
            };

            mClick = function (xi) {
                return function () {
                    me.select(xi);
                };
            };

            this.container.hide().empty();

            for (i = 0; i < len; i++) {
                s = this.suggestions[i];
                div = $((me.selectedIndex === i ? '<div class="selected"' : '
' + f(s, this.data[i], v) + '
');
                div.mouseover(mOver(i));
                div.click(mClick(i));
                this.container.append(div);
            }

            this.enabled = true;
            this.container.show();
        },

        processResponse: function (text) {
            /*jslint evil: true */
            var response;

            try {
                response = eval('(' + text + ')');
            } catch (err) {
                return;
            }

            if (!$.isArray(response.data)) {
                response.data = [];
            }

            if (!this.options.noCache) {
                this.cachedResponse[response.query] = response;
                if (response.suggestions.length === 0) {
                    this.badQueries.push(response.query);
                }
            }

            if (response.query === this.getQuery(this.currentValue)) {
                this.suggestions = response.suggestions;
                this.data = response.data;
                this.suggest();
            }
        },

        activate: function (index) {
            var divs, activeItem;

            divs = this.container.children();
            // Clear previous selection:
            if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
                $(divs.get(this.selectedIndex)).removeClass();
            }

            this.selectedIndex = index;

            if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
                activeItem = divs.get(this.selectedIndex);
                $(activeItem).addClass('selected');
                return activeItem;
            }

            return null;
        },

        deactivate: function (div, index) {
            div.className = '';
            if (this.selectedIndex === index) {
                this.selectedIndex = -1;
            }
        },

        select: function (i) {
            var selectedValue, f;

            selectedValue = this.suggestions[i];

            if (selectedValue) {
                this.el.val(selectedValue);
                if (this.options.autoSubmit) {
                    f = this.el.parents('form');
                    if (f.length > 0) {
                        f.get(0).submit();
                    }
                }
                this.ignoreValueChange = true;
                this.hide();
                this.onSelect(i);
            }
        },

        change: function (i) {
            var selectedValue, onChange, me, s, d;

            me = this;
            selectedValue = this.suggestions[i];

            if (selectedValue) {
                s = me.suggestions[i];
                d = me.data[i];
                me.el.val(me.getValue(s));
            } else {
                s = '';
                d = -1;
            }

            onChange = me.options.onChange;
            if ($.isFunction(onChange)) {
                onChange(s, d, me.el);
            }
        },

        moveUp: function () {
            if (this.selectedIndex === -1) {
                return;
            }

            if (this.selectedIndex === 0) {
                this.container.children().get(0).className = '';
                this.selectedIndex = -1;
                this.el.val(this.currentValue);
                return;
            }

            this.adjustScroll(this.selectedIndex - 1);
        },

        moveDown: function () {
            if (this.selectedIndex === (this.suggestions.length - 1)) {
                return;
            }

            this.adjustScroll(this.selectedIndex + 1);
        },

        adjustScroll: function (i) {
            var activeItem, offsetTop, upperBound, lowerBound;

            activeItem = this.activate(i);
            offsetTop = activeItem.offsetTop;
            upperBound = this.container.scrollTop();
            lowerBound = upperBound + this.options.maxHeight - 25;

            if (offsetTop < upperBound) {
                this.container.scrollTop(offsetTop);
            } else if (offsetTop > lowerBound) {
                this.container.scrollTop(offsetTop - this.options.maxHeight + 25);
            }

            this.el.val(this.getValue(this.suggestions[i]));
        },

        onSelect: function (i) {
            var me = this,
                callback = me.options.onSelect,
                sugestion = me.suggestions[i],
                data = me.data[i];

            me.el.val(me.getValue(sugestion));

            if ($.isFunction(callback)) {
                callback(sugestion, data, me.el);
            }
        },

        getValue: function (value) {
            var me = this,
                separator = me.options.delimiter,
                currentValue,
                array;

            if (!separator) {
                return value;
            }

            currentValue = me.currentValue;
            array = currentValue.split(separator);

            if (array.length === 1) {
                return value;
            }

            return currentValue.substr(0, currentValue.length - array[array.length - 1].length) + value;
        }
    };
}(jQuery));
<|endoftext|>