<commit_before>/**
 * Created by djarosz on 11/24/15.
 */
/**
 * The purpose of this file is to allow communication with the component database (CDB) used at the Advance Photon Source (APS).
 *
 * In order to integrate CDB into the traveler module the requirements below must be fullfilled:
 * Service.json file must include:
 *
 * "device_application": "cdb",
 * "cdb" : {
 *  "web_portal_url": "URL to home page of CDB",
 *  "web_service_url": "URL to the CDB web services"
 * }
 */

var config = require('./../../config/config.js');
var request = require('request');

var webServiceUrl = config.service.cdb.web_service_url;
var webPortalUrl = config.service.cdb.web_portal_url;

const PORTAL_PATH_FOR_ITEM = '/views/item/view.xhtml?id=REPLACE_ID';
const PORTAL_PATH_FOR_ITEM_ELEMENT =
  '/views/itemElement/view.xhtml?id=REPLACE_ID';

const ITEM_INVENTORY_DOMAIN_NAME = 'Inventory';
const ITEM_CATALOG_DOMAIN_NAME = 'Catalog';

/**
 * Performs a request to an external service and calls the call back function when the request is complete/incomplete.
 * @param {string} fullUrl - The full url of the web service request.
 * @param {requestCallback} cb - The function to be executed upon successful/unsuccessful completion of the request.
 * @returns {void}
 */
function performServiceRequest(fullUrl, cb) {
  console.log('Performing API Request: ' + fullUrl);
  request(
    {
      strictSSL: false,
      url: fullUrl,
    },
    function(error, response) {
      if (response !== undefined) {
        try {
          response = JSON.parse(response.body);
        } catch (e) {
          error = 'Response from server could not be parsed.';
        }
      }
      if (error !== null && error !== undefined) {
        console.error(error);
      }
      cb(response, error);
    }
  );
}

/**
 * Generates service url for entity type of item. Performs a request using the url.
 * @param {int} id - Unique identifier of the entity
 * @param {requestCallback} cb(resonse, error) - The function to be executed upon successful/unsuccessful completion of the request.
 * @returns {void}
 */
function getItemById(id, cb) {
  var fullUrl = webServiceUrl + '/items/' + id;
  performServiceRequest(fullUrl, cb);
}

function getItemElementById(id, cb) {
  var fullUrl = webServiceUrl + '/itemElements/' + id;
  performServiceRequest(fullUrl, cb);
}

/**
 * Gets the display value from web service for the specific entity from the Component Database(CDB) web service.
 * Generates an html  tag with target value to the entity in component database (CDB).
 * @param {String} valueOrig - value that is stored in the database, describes entity type and its id.
 * @param {requestCallback} cb - The function to be executed upon successful/unsuccessful completion of the request.
 * @returns {void}
 */
function getCDBEntityReference(valueOrig, cb) {
  var value = valueOrig.split(':');
  var id = value[1];
  var entityType = value[0];

  /**
   * Generates a proper displayValue depending on the data resulting from the request.
   * When connection/local error occurred, display value is db stored value.
   * When web service returns an error, the error from web service is display value.
   * When request was successful, display value is the value from web service.
   * @param {Object} data - response data from web service, may include error message.
   * @param {Object} error - An error that occurred on the local application server during the request.
   * @returns {Promise} - promise is returned once error checking is complete and display value is generated.
   */
  function performErrorChecking(data, error) {
    return new Promise(function(resolve) {
      var displayValue;
      if (error) {
        displayValue = valueOrig;
      } else if (data.errorMessage) {
        console.error(data.errorMessage);
        displayValue = 'Error: ' + data.errorMessage;
      }
      resolve(displayValue);
    });
  }

  /**
   * Using the generated display value and the configuration url path, it generates an  tag to display for device.
   * @param {String} urlPath - URL path stored in the configuration file for a specific entity.
   * @param {String} displayValue - The value to show on the url link that is generated to CDB.
   * @returns {void}
   */
  function constructFinalUrl(urlPath, displayValue) {
    urlPath = urlPath.replace('REPLACE_ID', id);
    var url = webPortalUrl + urlPath;
    var result = "";
    result += displayValue;
    result += '';
    cb(result);
  }

  /**
   * Function processes the response for a item entity type from CDB.
   * @param {Object} data - response data from web service, may include error message.
   * @param {Object} error - An error that occurred on the local application server during the request.
   * @returns {void}
   */
  function processItemResponse(data, error) {
    performErrorChecking(data, error).then(function(displayValue) {
      if (displayValue === undefined) {
        switch (data.domain.name) {
          case ITEM_CATALOG_DOMAIN_NAME:
            displayValue = 'Catalog Item: ' + data.name;
            finishItemResponse(displayValue);
            break;
          case ITEM_INVENTORY_DOMAIN_NAME:
            finishInventoryItemResponse(data);
            break;
          default:
            displayValue = 'Item: ' + data.name;
        }
      } else {
        finishItemResponse(displayValue);
      }
    });
  }

  function finishInventoryItemResponse(inventoryItem) {
    function addCatalogItemInformation(data, error) {
      performErrorChecking(data, error).then(function(displayValue) {
        if (displayValue === undefined) {
          catalogItem = data;
          displayValue = catalogItem.name + ' [' + inventoryItem.name + ']';
        } else {
          displayValue =
            displayValue + ' Inventory Item: ' + inventoryItem.name;
        }

        if (inventoryItem.qr_id) {
          displayValue += ' (QRID: ' + inventoryItem.qr_id + ')';
        }
        finishItemResponse(displayValue);
      });
    }
    catalogItemId = inventoryItem.derived_from_item_id;
    getItemById(catalogItemId, addCatalogItemInformation);
  }

  function finishItemResponse(displayValue) {
    constructFinalUrl(PORTAL_PATH_FOR_ITEM, displayValue);
  }

  function processItemElementResponse(data, error) {
    performErrorChecking(data, error).then(function(displayValue) {
      if (displayValue === undefined) {
        displayValue = 'Element';
        if (data.parentItem) {
          displayValue += ' of ' + data.parentItem.name;
        }
        if (data.name) {
          displayValue += ': ' + data.name;
        }
      }

      constructFinalUrl(PORTAL_PATH_FOR_ITEM_ELEMENT, displayValue);
    });
  }

  switch (entityType) {
    case 'item':
      getItemById(id, processItemResponse);
      break;
    case 'itemElement':
      getItemElementById(id, processItemElementResponse);
      break;
    default:
      cb(valueOrig);
  }
}

/*
function test() {
  function showResult(data, error) {
    console.log('error: ' + JSON.stringify(error));
    console.log('data: ' + data);
  }

  getCDBEntityReference('Component:263', showResult);
  getCDBEntityReference('ComponentInstance:108', showResult);
  getCDBEntityReference('Design:24', showResult);

}
test()
*/

module.exports = {
  getDeviceValue: getCDBEntityReference,
  devicesRemovalAllowed: false,
};
<commit_msg>Remove dependency on the cdb python API now use the java api.<commit_after>/**
 * Created by djarosz on 11/24/15.
 */
/**
 * The purpose of this file is to allow communication with the component database (CDB) used at the Advance Photon Source (APS).
 *
 * In order to integrate CDB into the traveler module the requirements below must be fullfilled:
 * Service.json file must include:
 *
 * "device_application": "cdb",
 * "cdb" : {
 *  "web_portal_url": "URL to home page of CDB. example: https://cdb.aps.anl.gov/cdb"
 * }
 */

var config = require('./../../config/config.js');
var request = require('request');

var webPortalUrl = config.service.cdb.web_portal_url;

const PORTAL_PATH_FOR_ITEM = '/views/item/view.xhtml?id=REPLACE_ID';

const ITEM_INVENTORY_DOMAIN_NAME = 'Inventory';

/**
 * Performs a request to an external service and calls the call back function when the request is complete/incomplete.
 * @param {string} fullUrl - The full url of the web service request.
 * @param {requestCallback} cb - The function to be executed upon successful/unsuccessful completion of the request.
 * @returns {void}
 */
function performServiceRequest(fullUrl, cb) {
  console.log('Performing API Request: ' + fullUrl);
  request(
    {
      strictSSL: false,
      url: fullUrl,
    },
    function(error, response) {
      if (response !== undefined) {
        try {
          response = JSON.parse(response.body);
        } catch (e) {
          error = 'Response from server could not be parsed.';
        }
      }
      if (error !== null && error !== undefined) {
        console.error(error);
      }
      cb(response, error);
    }
  );
}

/**
 * Generates service url for entity type of item. Performs a request using the url.
 * @param {int} id - Unique identifier of the entity
 * @param {requestCallback} cb(resonse, error) - The function to be executed upon successful/unsuccessful completion of the request.
 * @returns {void}
 */
function getItemById(id, cb) {
  var fullUrl = webPortalUrl + '/api/Items/ById/' + id;
  performServiceRequest(fullUrl, cb);
}

/**
 * Gets the display value from web service for the specific entity from the Component Database(CDB) web service.
 * Generates an html  tag with target value to the entity in component database (CDB).
 * @param {String} valueOrig - value that is stored in the database, describes entity type and its id.
 * @param {requestCallback} cb - The function to be executed upon successful/unsuccessful completion of the request.
 * @returns {void}
 */
function getCDBEntityReference(valueOrig, cb) {
  var value = valueOrig.split(':');
  var id = value[1];
  var entityType = value[0];

  /**
   * Generates a proper displayValue depending on the data resulting from the request.
   * When connection/local error occurred, display value is db stored value.
   * When web service returns an error, the error from web service is display value.
   * When request was successful, display value is the value from web service.
   * @param {Object} data - response data from web service, may include error message.
   * @param {Object} error - An error that occurred on the local application server during the request.
   * @returns {Promise} - promise is returned once error checking is complete and display value is generated.
   */
  function performErrorChecking(data, error) {
    return new Promise(function(resolve) {
      var displayValue;
      if (error) {
        displayValue = valueOrig;
      } else if (data.exception) {
        console.error(data.message);
        displayValue = 'Error: ' + data.message;
      }
      resolve(displayValue);
    });
  }

  /**
   * Using the generated display value and the configuration url path, it generates an  tag to display for device.
   * @param {String} urlPath - URL path stored in the configuration file for a specific entity.
   * @param {String} displayValue - The value to show on the url link that is generated to CDB.
   * @returns {void}
   */
  function constructFinalUrl(urlPath, displayValue) {
    urlPath = urlPath.replace('REPLACE_ID', id);
    var url = webPortalUrl + urlPath;
    var result = "";
    result += displayValue;
    result += '';
    cb(result);
  }

  /**
   * Function processes the response for a item entity type from CDB.
   * @param {Object} data - response data from web service, may include error message.
   * @param {Object} error - An error that occurred on the local application server during the request.
   * @returns {void}
   */
  function processItemResponse(data, error) {
    performErrorChecking(data, error).then(function(displayValue) {
      if (displayValue === undefined) {
        switch (data.domain.name) {
          case ITEM_INVENTORY_DOMAIN_NAME:
            let inventoryItem = data;
            let catalogItem = inventoryItem.catalogItem;
            displayValue = catalogItem.name + ' [' + inventoryItem.name + ']';

            if (inventoryItem.qrId) {
              displayValue += ' (QRID: ' + inventoryItem.qrId + ')';
            }

            finishItemResponse(displayValue);
            break;
          default:
            displayValue = 'Item: ' + data.name;
            finishItemResponse(displayValue);
        }
      } else {
        finishItemResponse(displayValue);
      }
    });
  }

  function finishItemResponse(displayValue) {
    constructFinalUrl(PORTAL_PATH_FOR_ITEM, displayValue);
  }

  switch (entityType) {
    case 'item':
      getItemById(id, processItemResponse);
      break;
    default:
      cb(valueOrig);
  }
}

module.exports = {
  getDeviceValue: getCDBEntityReference,
  devicesRemovalAllowed: false,
};
<|endoftext|>


<commit_before>Ext.define("UX.tinymce.WindowManager", {
	extend: tinymce.WindowManager,

	constructor: function(config)
	{
		tinymce.WindowManager.call(this, config.editor);
	},

	alert: function(txt, cb, s)
	{
		Ext.MessageBox.alert("", txt, function()
		{
			if(!Ext.isEmpty(cb))
			{
				cb.call(this);
			}
		}, s);
	},

	confirm: function(txt, cb, s)
	{
		Ext.MessageBox.confirm("", txt, function(btn)
		{
			if(!Ext.isEmpty(cb))
			{
				cb.call(this, btn == "yes");
			}
		}, s);
	},

	open: function(s, p)
	{
		s = s || {};
		p = p || {};
		if(!s.type)
		{
			this.bookmark = this.editor.selection.getBookmark('simple');
		}
		s.width = parseInt(s.width || 320);
		s.height = parseInt(s.height || 240) + (tinymce.isIE ? 8 : 0);
		s.min_width = parseInt(s.min_width || 150);
		s.min_height = parseInt(s.min_height || 100);
		s.max_width = parseInt(s.max_width || 2000);
		s.max_height = parseInt(s.max_height || 2000);
		s.movable = true;
		s.resizable = true;
		p.mce_width = s.width;
		p.mce_height = s.height;
		p.mce_inline = true;
		this.features = s;
		this.params = p;
		var win = Ext.create("Ext.window.Window", {
			title: s.name,
			width: s.width,
			height: s.height,
			minWidth: s.min_width,
			minHeight: s.min_height,
			resizable: true,
			maximizable: s.maximizable,
			minimizable: s.minimizable,
			modal: true,
			stateful: false,
			constrain: true,
			//border: false,
			layout: "fit",
			items: [Ext.create("Ext.Component", {
				autoEl: {
					tag: 'iframe',
					src: s.url || s.file
				},
				style: 'border-width: 0px;'
			})]
		});

		p.mce_window_id = win.getId();
		win.show(null, function()
		{
			if(s.left && s.top)
				win.setPagePosition(s.left, s.top);
			var pos = win.getPosition();
			s.left = pos[0];
			s.top = pos[1];
			this.onOpen.dispatch(this, s, p);
		}, this);

		return win;
	},

	close: function(win)
	{
		// Probably not inline
		if(!win.tinyMCEPopup || !win.tinyMCEPopup.id)
		{
			tinymce.WindowManager.prototype.close.call(this, win);
			return;
		}

		var w = Ext.getCmp(win.tinyMCEPopup.id);

		if(w)
		{
			this.onClose.dispatch(this);
			w.close();
		}
	},

	setTitle: function(win, ti)
	{
		if(!win.tinyMCEPopup || !win.tinyMCEPopup.id)
		{
			tinymce.WindowManager.prototype.setTitle.call(this, win, ti);
			return;
		}

		var w = Ext.getCmp(win.tinyMCEPopup.id);

		if(w)
			w.setTitle(ti);
	},

	resizeBy: function(dw, dh, id)
	{
		var w = Ext.getCmp(id);

		if(w)
		{
			var size = w.getSize();
			w.setSize(size.width + dw, size.height + dh);
		}
	},

	focus: function(id)
	{
		var w = Ext.getCmp(id);
		if(w)
			w.setActive(true);
	}
});

/**
 * @class Ext.ux.form.field.TinyMCE
 * @extends Ext.form.field.TextArea
 *
 * The Initial Developer of the Original Code is daanlib with some methods of
 * Fady Khalife (http://code.google.com/p/ext-js-4-tinymce-ux/source/browse/trunk/ux/form/TinyMCE.js)
 * @see http://www.sencha.com/forum/showthread.php?138436-TinyMCE-form-field
 *
 * @contributor Harald Hanek
 * @license MIT (http://www.opensource.org/licenses/mit-license.php)
 */
Ext.define("Ext.ux.form.field.TinyMCE",	{
	extend: 'Ext.form.field.TextArea',
	alias: 'widget.tinymcefield',

	config:
	{
		height: 170
	},

	/*
	fieldSubTpl: ['<textarea id="{id}" ',
			'<tpl if="name">name="{name}" </tpl>',
			'tabIndex="-1" ',
			'class="{fieldCls}" autocomplete="off" />',
			'</textarea>',
			{
				compiled: true,
				disableFormats: true
			}],
		*/

	statics: {
		tinyMCEInitialized: false,
		globalSettings: {
			accessibility_focus: false,
			language: "en",
			mode: "none",
			skin: "o2k7",
			theme: "advanced",
			plugins: 'autolink,lists,spellchecker,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template',
			theme_advanced_buttons1: 'newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect',
			theme_advanced_buttons2: 'cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor',
			theme_advanced_buttons3: 'tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen',
			theme_advanced_buttons4: 'insertlayer,moveforward,movebackward,absolute,|,styleprops,spellchecker,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,blockquote,pagebreak',
			// extended_valid_elements:
			// "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",
			// template_external_list_url:
			// "example_template_list.js"
			// content_css : "/lib/css/editor.css",
			theme_advanced_toolbar_location: 'top',
			theme_advanced_toolbar_align: 'left',
			theme_advanced_statusbar_location: 'bottom',
			theme_advanced_resize_horizontal: false,
			theme_advanced_resizing: false,
			width: '100%',
			height: '100%'
		},

		setGlobalSettings: function(settings)
		{
			Ext.apply(this.globalSettings, settings);
		}
	},

	constructor: function(config)
	{
		var me = this;

		config.height = (config.height && config.height >= me.config.height) ? config.height : me.config.height;

		Ext.applyIf(config.tinymceConfig, me.statics().globalSettings);

		// Init values we do not want changed
		config.tinymceConfig.mode = 'none';

		me.addEvents({
			"editorcreated": true
		});

		me.callParent([config]);
		//return me;
	},

	afterRender: function()
	{
		var me = this;
		me.callParent(arguments);
		me.tinymceConfig.height = me.height - 25;
		//me.tinymceConfig.height = me.height - 51;
		//console.log(me.tinymceConfig.height);
		me.editor = new tinymce.Editor(me.inputEl.id, me.tinymceConfig);

		// Validate value onKeyPress
        var validateContentTask = Ext.Function.createBuffered(me.validate, 250, this);
        me.editor.onKeyPress.add(validateContentTask);

		me.editor.onPostRender.add(Ext.Function.bind(function(editor, controlManager)
		{
			editor.windowManager = Ext.create("UX.tinymce.WindowManager", {
				editor: me.editor
			});
			me.tableEl = Ext.get(me.editor.id + "_tbl");
			me.iframeEl = Ext.get(me.editor.id + "_ifr");
		}, me));

		window.b = me.editor;
		me.on('resize', me.onResize, me);

		me.editor.render();
		tinyMCE.add(me.editor);
	},

	isDirty: function()
	{
		var me = this;
		if(me.disabled || !me.rendered)
		{
			return false;
		}
		return me.editor && me.editor.initialized && me.editor.isDirty();
	},

	getValue: function()
	{
		return this.editor.getContent();
	},

	setValue: function(value)
	{
		var me = this;
		me.value = value;
		if(me.rendered)
			me.withEd(function()
			{
				me.editor.undoManager.clear();
				me.editor.setContent(value === null || value === undefined ? '' : value);
				me.editor.startContent = me.editor.getContent({
					format: 'raw'
				});
				me.validate();
				// me.editor.resizeToContent();
			});
	},

	getSubmitData: function()
	{
		var ret = {};
		ret[this.getName()] = this.getValue();
		return ret;
	},

	insertValueAtCursor: function(value)
	{
		var me = this;

		if(me.editor && me.editor.initialized)
		{
			me.editor.execCommand('mceInsertContent', false, value);
		}
	},

	onDestroy: function()
	{
		var me = this;

		me.editor.remove();
		me.editor.destroy();
		me.callParent(arguments);
	},

	onResize: function(component, adjWidth, adjHeight)
	{
		var width,
			bodyWidth = component.bodyEl.getWidth();

		if(component.iframeEl)
		{
			width = bodyWidth - component.iframeEl.getBorderWidth('lr') - 2;
			component.iframeEl.setWidth(width);
		}

		if(component.tableEl)
		{
			width = bodyWidth - component.tableEl.getBorderWidth('lr') - 2;
			component.tableEl.setWidth(width);
		}
	},

	getEditor: function()
	{
		return this.editor;
	},

	getRawValue: function()
	{
		var me = this;
		if(!me.editor || !me.editor.initialized)
		{
			return Ext.valueFrom(me.value, '');
		}
		return me.editor.getContent();
	},

	disable: function()
	{
		this.withEd(function()
		{
			var bodyEl = this.editor.getBody();
			bodyEl = Ext.get(bodyEl);
			if(bodyEl.hasCls('mceContentBody'))
			{
				bodyEl.removeCls('mceContentBody');
				bodyEl.addCls('mceNonEditable');
			}
		});
	},

	enable: function()
	{
		this.withEd(function()
		{
			var bodyEl = this.editor.getBody();
			bodyEl = Ext.get(bodyEl);
			if(bodyEl.hasCls('mceNonEditable'))
			{
				bodyEl.removeCls('mceNonEditable');
				bodyEl.addCls('mceContentBody');
			}
		});
	},

	withEd: function(func)
	{
		// If editor is not created yet, reschedule this call.
		if(!this.editor)
			this.on("editorcreated", function()
			{
				this.withEd(func);
			}, this);
		// Else if editor is created and initialized
		else if(this.editor.initialized)
			func.call(this);
		// Else if editor is created but not initialized yet.
		else
			this.editor.onInit.add(Ext.Function.bind(function()
			{
				Ext.Function.defer(func, 10, this);
			}, this));
	},

    validateValue: function(value)
	{
		if(Ext.isFunction(this.validator))
		{
			var msg = this.validator(value);
			if(msg !== true)
			{
				this.markInvalid(msg);
				return false;
			}
		}
		if(value.length < 1 || value === this.emptyText)
		{ // if it's blank
			if(this.allowBlank)
			{
				this.clearInvalid();
				return true;
			}
			else
			{
				this.markInvalid(this.blankText);
				return false;
			}
		}
		if(value.length < this.minLength)
		{
			this.markInvalid(Ext.String.format(this.minLengthText, this.minLength));
			return false;
		}
		else
			this.clearInvalid();
		if(value.length > this.maxLength)
		{
			this.markInvalid(Ext.String.format(this.maxLengthText, this.maxLength));
			return false;
		}
		else
			this.clearInvalid();
		if(this.vtype)
		{
			var vt = Ext.form.field.VTypes;
			if(!vt[this.vtype](value, this))
			{
				this.markInvalid(this.vtypeText || vt[this.vtype + 'Text']);
				return false;
			}
		}
		if(this.regex && !this.regex.test(value))
		{
			this.markInvalid(this.regexText);
			return false;
		}
		return true;
	}
});<commit_msg>format<commit_after>Ext.define("UX.tinymce.WindowManager", {
	extend: tinymce.WindowManager,

	constructor: function(config)
	{
		tinymce.WindowManager.call(this, config.editor);
	},

	alert: function(txt, cb, s)
	{
		Ext.MessageBox.alert("", txt, function()
		{
			if(!Ext.isEmpty(cb))
			{
				cb.call(this);
			}
		}, s);
	},

	confirm: function(txt, cb, s)
	{
		Ext.MessageBox.confirm("", txt, function(btn)
		{
			if(!Ext.isEmpty(cb))
			{
				cb.call(this, btn == "yes");
			}
		}, s);
	},

	open: function(s, p)
	{
		s = s || {};
		p = p || {};
		if(!s.type)
		{
			this.bookmark = this.editor.selection.getBookmark('simple');
		}
		s.width = parseInt(s.width || 320);
		s.height = parseInt(s.height || 240) + (tinymce.isIE ? 8 : 0);
		s.min_width = parseInt(s.min_width || 150);
		s.min_height = parseInt(s.min_height || 100);
		s.max_width = parseInt(s.max_width || 2000);
		s.max_height = parseInt(s.max_height || 2000);
		s.movable = true;
		s.resizable = true;
		p.mce_width = s.width;
		p.mce_height = s.height;
		p.mce_inline = true;
		this.features = s;
		this.params = p;
		var win = Ext.create("Ext.window.Window", {
			title: s.name,
			width: s.width,
			height: s.height,
			minWidth: s.min_width,
			minHeight: s.min_height,
			resizable: true,
			maximizable: s.maximizable,
			minimizable: s.minimizable,
			modal: true,
			stateful: false,
			constrain: true,
			//border: false,
			layout: "fit",
			items: [Ext.create("Ext.Component", {
				autoEl: {
					tag: 'iframe',
					src: s.url || s.file
				},
				style: 'border-width: 0px;'
			})]
		});

		p.mce_window_id = win.getId();
		win.show(null, function()
		{
			if(s.left && s.top)
				win.setPagePosition(s.left, s.top);
			var pos = win.getPosition();
			s.left = pos[0];
			s.top = pos[1];
			this.onOpen.dispatch(this, s, p);
		}, this);

		return win;
	},

	close: function(win)
	{
		// Probably not inline
		if(!win.tinyMCEPopup || !win.tinyMCEPopup.id)
		{
			tinymce.WindowManager.prototype.close.call(this, win);
			return;
		}

		var w = Ext.getCmp(win.tinyMCEPopup.id);

		if(w)
		{
			this.onClose.dispatch(this);
			w.close();
		}
	},

	setTitle: function(win, ti)
	{
		if(!win.tinyMCEPopup || !win.tinyMCEPopup.id)
		{
			tinymce.WindowManager.prototype.setTitle.call(this, win, ti);
			return;
		}

		var w = Ext.getCmp(win.tinyMCEPopup.id);

		if(w)
			w.setTitle(ti);
	},

	resizeBy: function(dw, dh, id)
	{
		var w = Ext.getCmp(id);

		if(w)
		{
			var size = w.getSize();
			w.setSize(size.width + dw, size.height + dh);
		}
	},

	focus: function(id)
	{
		var w = Ext.getCmp(id);
		if(w)
			w.setActive(true);
	}
});

/**
 * @class Ext.ux.form.field.TinyMCE
 * @extends Ext.form.field.TextArea
 *
 * The Initial Developer of the Original Code is daanlib with some methods of
 * Fady Khalife (http://code.google.com/p/ext-js-4-tinymce-ux/source/browse/trunk/ux/form/TinyMCE.js)
 * @see http://www.sencha.com/forum/showthread.php?138436-TinyMCE-form-field
 *
 * @contributor Harald Hanek
 * @license MIT (http://www.opensource.org/licenses/mit-license.php)
 */
Ext.define("Ext.ux.form.field.TinyMCE",	{
	extend: 'Ext.form.field.TextArea',
	alias: 'widget.tinymcefield',

	config:
	{
		height: 170
	},

	/*
	fieldSubTpl: ['<textarea id="{id}" ',
			'<tpl if="name">name="{name}" </tpl>',
			'tabIndex="-1" ',
			'class="{fieldCls}" autocomplete="off" />',
			'</textarea>',
			{
				compiled: true,
				disableFormats: true
			}],
		*/

	statics: {
		tinyMCEInitialized: false,
		globalSettings: {
			accessibility_focus: false,
			language: "en",
			mode: "none",
			skin: "o2k7",
			theme: "advanced",
			plugins: 'autolink,lists,spellchecker,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template',
			theme_advanced_buttons1: 'newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect',
			theme_advanced_buttons2: 'cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor',
			theme_advanced_buttons3: 'tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen',
			theme_advanced_buttons4: 'insertlayer,moveforward,movebackward,absolute,|,styleprops,spellchecker,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,blockquote,pagebreak',
			// extended_valid_elements:
			// "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",
			// template_external_list_url:
			// "example_template_list.js"
			// content_css : "/lib/css/editor.css",
			theme_advanced_toolbar_location: 'top',
			theme_advanced_toolbar_align: 'left',
			theme_advanced_statusbar_location: 'bottom',
			theme_advanced_resize_horizontal: false,
			theme_advanced_resizing: false,
			width: '100%',
			height: '100%'
		},

		setGlobalSettings: function(settings)
		{
			Ext.apply(this.globalSettings, settings);
		}
	},

	constructor: function(config)
	{
		var me = this;

		config.height = (config.height && config.height >= me.config.height) ? config.height : me.config.height;

		Ext.applyIf(config.tinymceConfig, me.statics().globalSettings);

		// Init values we do not want changed
		config.tinymceConfig.mode = 'none';

		me.addEvents({
			"editorcreated": true
		});

		me.callParent([config]);
		//return me;
	},

	afterRender: function()
	{
		var me = this;
		me.callParent(arguments);
		me.tinymceConfig.height = me.height - 25;
		//me.tinymceConfig.height = me.height - 51;
		//console.log(me.tinymceConfig.height);
		me.editor = new tinymce.Editor(me.inputEl.id, me.tinymceConfig);

		// Validate value onKeyPress
		var validateContentTask = Ext.Function.createBuffered(me.validate, 250, this);
		me.editor.onKeyPress.add(validateContentTask);

		me.editor.onPostRender.add(Ext.Function.bind(function(editor, controlManager)
		{
			editor.windowManager = Ext.create("UX.tinymce.WindowManager", {
				editor: me.editor
			});
			me.tableEl = Ext.get(me.editor.id + "_tbl");
			me.iframeEl = Ext.get(me.editor.id + "_ifr");
		}, me));

		window.b = me.editor;
		me.on('resize', me.onResize, me);

		me.editor.render();
		tinyMCE.add(me.editor);
	},

	isDirty: function()
	{
		var me = this;
		if(me.disabled || !me.rendered)
		{
			return false;
		}
		return me.editor && me.editor.initialized && me.editor.isDirty();
	},

	getValue: function()
	{
		return this.editor.getContent();
	},

	setValue: function(value)
	{
		var me = this;
		me.value = value;
		if(me.rendered)
			me.withEd(function()
			{
				me.editor.undoManager.clear();
				me.editor.setContent(value === null || value === undefined ? '' : value);
				me.editor.startContent = me.editor.getContent({
					format: 'raw'
				});
				me.validate();
				// me.editor.resizeToContent();
			});
	},

	getSubmitData: function()
	{
		var ret = {};
		ret[this.getName()] = this.getValue();
		return ret;
	},

	insertValueAtCursor: function(value)
	{
		var me = this;

		if(me.editor && me.editor.initialized)
		{
			me.editor.execCommand('mceInsertContent', false, value);
		}
	},

	onDestroy: function()
	{
		var me = this;

		me.editor.remove();
		me.editor.destroy();
		me.callParent(arguments);
	},

	onResize: function(component, adjWidth, adjHeight)
	{
		var width,
			bodyWidth = component.bodyEl.getWidth();

		if(component.iframeEl)
		{
			width = bodyWidth - component.iframeEl.getBorderWidth('lr') - 2;
			component.iframeEl.setWidth(width);
		}

		if(component.tableEl)
		{
			width = bodyWidth - component.tableEl.getBorderWidth('lr') - 2;
			component.tableEl.setWidth(width);
		}
	},

	getEditor: function()
	{
		return this.editor;
	},

	getRawValue: function()
	{
		var me = this;

		if(!me.editor || !me.editor.initialized)
		{
			return Ext.valueFrom(me.value, '');
		}
		return me.editor.getContent();
	},

	disable: function()
	{
		this.withEd(function()
		{
			var bodyEl = this.editor.getBody();
			bodyEl = Ext.get(bodyEl);
			if(bodyEl.hasCls('mceContentBody'))
			{
				bodyEl.removeCls('mceContentBody');
				bodyEl.addCls('mceNonEditable');
			}
		});
	},

	enable: function()
	{
		this.withEd(function()
		{
			var bodyEl = this.editor.getBody();
			bodyEl = Ext.get(bodyEl);
			if(bodyEl.hasCls('mceNonEditable'))
			{
				bodyEl.removeCls('mceNonEditable');
				bodyEl.addCls('mceContentBody');
			}
		});
	},

	withEd: function(func)
	{
		// If editor is not created yet, reschedule this call.
		if(!this.editor)
			this.on("editorcreated", function()
			{
				this.withEd(func);
			}, this);
		// Else if editor is created and initialized
		else if(this.editor.initialized)
			func.call(this);
		// Else if editor is created but not initialized yet.
		else
			this.editor.onInit.add(Ext.Function.bind(function()
			{
				Ext.Function.defer(func, 10, this);
			}, this));
	},

	validateValue: function(value)
	{
		var me = this;

		if(Ext.isFunction(me.validator))
		{
			var msg = me.validator(value);
			if(msg !== true)
			{
				me.markInvalid(msg);
				return false;
			}
		}

		if(value.length < 1 || value === me.emptyText)
		{ // if it's blank
			if(me.allowBlank)
			{
				me.clearInvalid();
				return true;
			}
			else
			{
				me.markInvalid(me.blankText);
				return false;
			}
		}

		if(value.length < me.minLength)
		{
			me.markInvalid(Ext.String.format(me.minLengthText, me.minLength));
			return false;
		}
		else
			me.clearInvalid();

		if(value.length > me.maxLength)
		{
			me.markInvalid(Ext.String.format(me.maxLengthText, me.maxLength));
			return false;
		}
		else
			me.clearInvalid();

		if(me.vtype)
		{
			var vt = Ext.form.field.VTypes;
			if(!vt[me.vtype](value, me))
			{
				me.markInvalid(me.vtypeText || vt[me.vtype + 'Text']);
				return false;
			}
		}

		if(me.regex && !me.regex.test(value))
		{
			me.markInvalid(me.regexText);
			return false;
		}
		return true;
	}
});<|endoftext|>


<commit_before>/**
	Script loader for an actual plugin
*/
// load User Script
mw.loader.using( 'ext.visualEditor.desktopArticleTarget.init', function () {
	// Register plugins to VE. will be loaded once the user opens VE
	mw.libs.ve.addPlugin( function () {
		//return $.getScript('//pl.wikipedia.org/w/index.php?title=User:Nux/veCustomSearch.plugin.js&action=raw&ctype=text/javascript');
		return $.getScript('/_wiki_js/_przyciski%20edycji/veMyPlugins/veCustomSearch.plugin.js');
	} );
});
<commit_msg>localhost + logging<commit_after>/**
	Script loader for an actual plugin
*/
// load User Script
mw.loader.using('ext.visualEditor.desktopArticleTarget.init', function () {
	console.log('init');
	// Register plugins to VE. will be loaded once the user opens VE
	mw.libs.ve.addPlugin(function () {
		console.log('addPlugin');
		//return $.getScript('//pl.wikipedia.org/w/index.php?title=User:Nux/veCustomSearch.plugin.js&action=raw&ctype=text/javascript');
		return $.getScript('https://localhost/_wiki_js/_przyciski%20edycji/veMyPlugins/veCustomSearch.plugin.js');
	});
});
<|endoftext|>


<commit_before>const path = require('path');

module.exports = {
  entry: './front/app.js',
  output: {
    path: path.resolve(__dirname, 'public/build'),
    filename: 'app.js'
  },
  devtool: 'inline-source-map',
  module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      use: [
        'babel-loader'
      ]
    }, {
      test: /\.css$/,
      use: [
        'style-loader',
        'css-loader'
      ]
    }, {
      test: /\.less$/,
      use: [
        'style-loader',
        'css-loader',
        'less-loader'
      ]
    }]
  }
};
<commit_msg>Modify webpack config to seperate source map to another file<commit_after>const path = require('path');

module.exports = (env, argv) => ({
  entry: './front/app.js',
  output: {
    path: path.resolve(__dirname, 'public/build'),
    filename: 'app.js'
  },
  devtool: argv.mode === 'production' ? 'source-map' : 'eval',
  module: {
    rules: [{
      test: /\.js$/,
      exclude: /node_modules/,
      use: [
        'babel-loader'
      ]
    }, {
      test: /\.css$/,
      use: [
        'style-loader',
        'css-loader'
      ]
    }, {
      test: /\.less$/,
      use: [
        'style-loader',
        'css-loader',
        'less-loader'
      ]
    }]
  }
});
<|endoftext|>


<commit_before>'use strict';
var _ = require('underscore');
var React = require('react-native');
var {
  PropTypes,
  ScrollView,
  Text,
  TouchableHighlight,
  View,
} = React;

var allButtons = {
  alphanum: [
    {text: 'Done', action: 'dismissKeyboard', },
    {text: '123', action: 'numbersKeyboard', },
  ],
  none: [
    // {text: 'ABC', action: 'qwertyKeyboard', },
    {text: '123', action: 'numbersKeyboard', },
  ],
  numbers: [
    {text: 'Done', action: 'dismissKeyboard', },
    {text: 'ABC', action: 'qwertyKeyboard', },
  ],
};

var styles = require('../styles/editor-accessory');

var EditorAccessory = React.createClass({
  PropTypes: {
    onSuggestionPressed: PropTypes.func.required,
  },

  getInitialState: function () {
    return {
      completions: [],
      prefix: '',
      keyboardType: 'none',
    };
  },

  componentDidMount: function () {
    var actions = this.props.actions;
    if (!actions) {
      return;
    }
    actions.on('KeyboardWillShow', this._handleKeyboardChange);
    actions.on('SelectionDidChange', this._handleCursorChange);
  },

  componentWillUnmount: function () {
    var actions = this.props.actions;
    if (!actions) {
      return;
    }
    actions.unon('KeyboardWillShow', this._handleKeyboardChange);
    actions.unon('SelectionDidChange', this._handleCursorChange);
  },

  renderButton: function (b) {
      return (
        <TouchableHighlight
            key={b.text}
            activeOpacity={0.2}
            style={styles.button}
            onPress={() => this._handleStaticButton(b)} >
          <Text style={styles.buttonText}>{b.text}</Text>
        </TouchableHighlight>
      );
  },

  renderSuggestion: function(completion) {
      return (
        <TouchableHighlight
            key={completion}
            activeOpacity={0.2}
            style={styles.completion}
            onPress={() => this._handlePress(completion)} >
          <Text style={styles.text}>{completion}</Text>
        </TouchableHighlight>
      );
  },

  render: function () {
    var actions = this.props.actions;

    var {
      completions,
      prefix,
      keyboardType,
    } = this.state;

    if (completions.length > 10) {
      completions.length = 10;
    }

    let buttons = allButtons[keyboardType].map(this.renderButton, this)
    let suggestions = completions.map(this.renderSuggestion, this)
    if (completions.length > 0) {
      return (
        <View style={styles.container}>
            {buttons}
            <ScrollView horizontal={true} style={styles.scrollView}>
              {suggestions}
            </ScrollView>
        </View>
      )
    } else {
      return (
        <View style={styles.container}>
          {buttons}
        </View>
      )
    }
  },

  _handleCursorChange: function () {
    var actions = this.props.actions;
    this.setState(actions.tabCompletion);
  },

  _handleStaticButton: function (b) {
    var actions = this.props.actions;
    switch (b.action) {
      case 'dismissKeyboard':
        actions.emit('KeyboardWillShow', 'none');
        break;
      case 'numbersKeyboard':
        actions.emit('KeyboardWillShow', 'numbers');
        break;
      case 'qwertyKeyboard':
        actions.emit('KeyboardWillShow', 'alphanum');
        break;
      default:
        // NOP
    }
  },

  _handleKeyboardChange: function (keyboardType) {
    this.setState({keyboardType});
  },

  _handlePress: function (text) {
    var actions = this.props.actions;
    var prefix = this.state.prefix;
    if (prefix && text.indexOf(prefix) === 0) {
      text = text.substring(prefix.length);
    }
    // if the prefix == text, then we need
    // to move the text forward somehow.
    if (!text) {
      text = ' ';
    } else if (!prefix) {
      text = ' ' + text + ' ';
    }
    actions.insertText({ literal: text });
    return true;
  },
});

module.exports = EditorAccessory;
<commit_msg>Convert to use more efficient horizontal list view.<commit_after>'use strict';
var _ = require('underscore');
var React = require('react-native');
var {
  ListView,
  PropTypes,
  ScrollView,
  Text,
  TouchableHighlight,
  View,
} = React;

var allButtons = {
  alphanum: [
    {text: 'Done', action: 'dismissKeyboard', },
    {text: '123', action: 'numbersKeyboard', },
  ],
  none: [
    // {text: 'ABC', action: 'qwertyKeyboard', },
    {text: '123', action: 'numbersKeyboard', },
  ],
  numbers: [
    {text: 'Done', action: 'dismissKeyboard', },
    {text: 'ABC', action: 'qwertyKeyboard', },
  ],
};

var styles = require('../styles/editor-accessory');

var EditorAccessory = React.createClass({
  PropTypes: {
    onSuggestionPressed: PropTypes.func.required,
  },

  getInitialState: function () {
    return {
      completions: [],
      completionsDataSource: new ListView.DataSource({
        rowHasChanged (row1, row2) {
          return row1 !== row2
        }
      }),
      prefix: '',
      keyboardType: 'none',
    };
  },

  componentDidMount: function () {
    var actions = this.props.actions;
    if (!actions) {
      return;
    }
    actions.on('KeyboardWillShow', this._handleKeyboardChange);
    actions.on('SelectionDidChange', this._handleCursorChange);
  },

  componentWillUnmount: function () {
    var actions = this.props.actions;
    if (!actions) {
      return;
    }
    actions.unon('KeyboardWillShow', this._handleKeyboardChange);
    actions.unon('SelectionDidChange', this._handleCursorChange);
  },

  renderButton: function (b) {
      return (
        <TouchableHighlight
            key={b.text}
            activeOpacity={0.2}
            style={styles.button}
            onPress={() => this._handleStaticButton(b)} >
          <Text style={styles.buttonText}>{b.text}</Text>
        </TouchableHighlight>
      );
  },

  renderSuggestion: function(completion) {
      return (
        <TouchableHighlight
            key={completion}
            activeOpacity={0.2}
            style={styles.completion}
            onPress={() => this._handlePress(completion)} >
          <Text style={styles.text}>{completion}</Text>
        </TouchableHighlight>
      );
  },

  renderSuggestionItem (rowData: string, sectionID: number, rowID: number) {
      return this.renderSuggestion(rowData)
  },

  render: function () {
    var actions = this.props.actions;

    var {
      completions,
      completionsDataSource,
      prefix,
      keyboardType,
    } = this.state;

    let buttons = allButtons[keyboardType].map(this.renderButton, this)
    let suggestions = completions.map(this.renderSuggestion, this)

    return (
      <View style={styles.container}>
          {buttons}
          <ListView
            horizontal={true}
            dataSource={completionsDataSource}
            renderRow={this.renderSuggestionItem}
          />
      </View>
    )
  },

  _handleCursorChange: function () {
    let tabCompletion = this.props.actions.tabCompletion;
    let { completions, prefix } = tabCompletion
    tabCompletion.completionsDataSource = this.state.completionsDataSource.cloneWithRows(completions)
    this.setState(tabCompletion);
  },

  _handleStaticButton: function (b) {
    var actions = this.props.actions;
    switch (b.action) {
      case 'dismissKeyboard':
        actions.emit('KeyboardWillShow', 'none');
        break;
      case 'numbersKeyboard':
        actions.emit('KeyboardWillShow', 'numbers');
        break;
      case 'qwertyKeyboard':
        actions.emit('KeyboardWillShow', 'alphanum');
        break;
      default:
        // NOP
    }
  },

  _handleKeyboardChange: function (keyboardType) {
    this.setState({keyboardType});
  },

  _handlePress: function (text) {
    var actions = this.props.actions;
    var prefix = this.state.prefix;
    if (prefix && text.indexOf(prefix) === 0) {
      text = text.substring(prefix.length);
    }
    // if the prefix == text, then we need
    // to move the text forward somehow.
    if (!text) {
      text = ' ';
    } else if (!prefix) {
      text = ' ' + text + ' ';
    }
    actions.insertText({ literal: text });
    return true;
  },
});

module.exports = EditorAccessory;
<|endoftext|>


<commit_before>var detectionInterval = 33; // 33ms is fastest, 200ms is default
var faceboxColors = ['#e74c3c', '#3498db', '#2ecc71', '#f1c40f', '#9b59b6', '#e67e22']; // Hex color values for each facebox; will cycle if there are more faceboxes than colors
var minConfidence = 0.5; // Minimum confidence level for successful face authentication, range from 0 to 1
var faceThresholds = {
  width: 40
  , height: 100
}
var mirroring = true
var stabilizationTime = 1000; // in milliseconds
var maxDistance = 40;
var maxChange = 5;
var cycles = Math.floor(stabilizationTime / detectionInterval);
var stabilizationCounter = 0;
var prevX, prevY, prevWidth, prevHeight;

// State variables
var authenticating = false
var authenticated = false

// Initializations
var buttonAddFace, buttonReset, mediaCapture, video, message, prevMessage, snapshot, facesCanvas;

var Capture = Windows.Media.Capture;
var captureSettings = new Capture.MediaCaptureInitializationSettings;
var DeviceEnumeration = Windows.Devices.Enumeration;
var displayRequest = new Windows.System.Display.DisplayRequest();
var effectDefinition = new Windows.Media.Core.FaceDetectionEffectDefinition();
var isAuthenticated = false;
var mediaStreamType = Capture.MediaStreamType.videoRecord;

function isStable(face) {
  if (stabilizationCounter == cycles) {
    prevX = prevY = prevWidth = prevHeight = null;
    stabilizationCounter = 0;
    return true;
  }

  var curX = face.x;
  var curY = face.y;
  var curWidth = face.width;
  var curHeight = face.height;

  stabilizationCounter++;

  if (prevX) {
    var distance = Math.sqrt(Math.pow(curX - prevX, 2) + Math.pow(curY - prevY, 2));
    if (distance > maxDistance || Math.abs(curWidth - prevWidth) > maxChange || Math.abs(curHeight - prevHeight) > maxChange) {
      console.log(`Reset! distance=${distance}, curWidth=${curWidth}, curHeight=${curHeight}, curX=${curX}, curY=${curY}`);
      stabilizationCounter = 0;
    }
  }

  prevX = curX;
  prevY = curY;
  prevWidth = curWidth;
  prevHeight = curHeight;

  return false;
}

var Authenticate = {}

Authenticate.findCameraDeviceByPanelAsync = function (panel) {
  var deviceInfo;
  return DeviceEnumeration.DeviceInformation.findAllAsync(DeviceEnumeration.DeviceClass.videoCapture).then(
    function(devices) {
      devices.forEach(function(cameraDeviceInfo) {
        if (cameraDeviceInfo.enclosureLocation != null && cameraDeviceInfo.enclosureLocation.panel === panel) {
          deviceInfo = cameraDeviceInfo;
          return;
        }
      });

      return !deviceInfo && devices.length > 0 ? devices.getAt(0) : deviceInfo;
    }
  );
}

Authenticate.takePhoto = function(addFace) {
  isAuthenticated = true;
  var Storage = Windows.Storage;
  var stream = new Storage.Streams.InMemoryRandomAccessStream();
  mediaCapture.capturePhotoToStreamAsync(Windows.Media.MediaProperties.ImageEncodingProperties.createJpeg(), stream)
  .then(function() {
    var buffer = new Storage.Streams.Buffer(stream.size);
    stream.seek(0);
    stream.readAsync(buffer, stream.size, 0).done(function() {
      var dataReader = Storage.Streams.DataReader.fromBuffer(buffer);
      var byteArray = new Uint8Array(buffer.length);
      dataReader.readBytes(byteArray);

      // Detect the face to get a face ID
      $.ajax({
        url: '/capture/authenticate',
        beforeSend: function(xhrObj) {
          xhrObj.setRequestHeader('Content-Type', 'application/octet-stream');
        },
        type: 'POST',
        data: byteArray,
        processData: false
      })
      .done(function(result) {
        var resultObj = JSON.parse(result)
        if(resultObj.authenticated){
          authenticated = true
          authenticating = false
          message.innerText = resultObj.message;
        } else {
          //If authenticated is false, then there was no match so start fresh
          authenticated = false
          authenticating = false
          message.innerText = ''
        }
      })
      .fail(function(e) {
        console.error(e);
      });

    });
  });
}

Authenticate.handleFaces = function(args) {
  var context = facesCanvas.getContext('2d');
  context.clearRect(0, 0, facesCanvas.width, facesCanvas.height);
  var detectedFaces = args.resultFrame.detectedFaces;
  var numFaces = detectedFaces.length;
  if (numFaces > 0) {
    var face;

    for (var i = 0; i < numFaces; i++) {
      face = detectedFaces.getAt(i).faceBox;
      context.beginPath();
      context.rect(face.x, face.y, face.width, face.height);
      context.lineWidth = 3;
      context.strokeStyle = faceboxColors[i % faceboxColors.length];
      context.stroke();
      context.closePath();

      if (mirroring) {
        facesCanvas.style.transform = 'scale(-1, 1)';
      }
      if(authenticated == false && authenticating == false && face.width > faceThresholds.width && face.height > faceThresholds.height){
        if (isStable(face)) {
          authenticating = true
          Authenticate.takePhoto()
        }
      }
    }
  }
}

Authenticate.mirrorPreview= function () {
  var props = mediaCapture.videoDeviceController.getMediaStreamProperties(Capture.MediaStreamType.videoPreview);
  props.properties.insert('C380465D-2271-428C-9B83-ECEA3B4A85C1', 0);
  return mediaCapture.setEncodingPropertiesAsync(Capture.MediaStreamType.videoPreview, props, null);
}

Authenticate.init = function() {
  if (typeof Windows == 'undefined') {
    console.log('Windows is not available');
    return;
  }
  buttonReset = document.getElementById('buttonReset')
  buttonReset.addEventListener('click', function() {
    message.innerText = '';
    authenticating = false
    authenticated = false
  })
  message = document.getElementById('message');
  facesCanvas = document.getElementById('facesCanvas');
  video = document.getElementById('video');
  facesCanvas.width = video.offsetWidth;
  facesCanvas.height = video.offsetHeight;
  Authenticate.findCameraDeviceByPanelAsync(DeviceEnumeration.Panel.back).then(
    function(camera) {
      if (!camera) {
        console.error('No camera device found!');
        return;
      }
      mediaCapture = new Capture.MediaCapture();
      captureSettings.videoDeviceId = camera.id;
      captureSettings.streamingCaptureMode = Capture.StreamingCaptureMode.video;
      mediaCapture.initializeAsync(captureSettings).then(
        function fulfilled(result) {
          mediaCapture.addVideoEffectAsync(effectDefinition, mediaStreamType).done(
            function complete(result) {
              result.desiredDetectionInterval = detectionInterval;
              result.addEventListener('facedetected', Authenticate.handleFaces);
            },
            function error(e) {
              console.error(e);
            }
          );
          displayRequest.requestActive();
          var preview = document.getElementById('cameraPreview');

          if (mirroring) {
            preview.style.transform = 'scale(-1, 1)';
            preview.addEventListener('playing', Authenticate.mirrorPreview);
          }
          var previewUrl = URL.createObjectURL(mediaCapture);
          preview.src = previewUrl;
          preview.play();
        },
        function error(e) {
          console.error(e);
        }
      );
    }
  );
}

window.Authenticate = Authenticate
<commit_msg>removing debug logs<commit_after>var detectionInterval = 33; // 33ms is fastest, 200ms is default
var faceboxColors = ['#e74c3c', '#3498db', '#2ecc71', '#f1c40f', '#9b59b6', '#e67e22']; // Hex color values for each facebox; will cycle if there are more faceboxes than colors
var minConfidence = 0.5; // Minimum confidence level for successful face authentication, range from 0 to 1
var faceThresholds = {
  width: 40
  , height: 100
}
var mirroring = true
var stabilizationTime = 1000; // in milliseconds
var maxDistance = 40;
var maxChange = 5;
var cycles = Math.floor(stabilizationTime / detectionInterval);
var stabilizationCounter = 0;
var prevX, prevY, prevWidth, prevHeight;

// State variables
var authenticating = false
var authenticated = false

// Initializations
var buttonAddFace, buttonReset, mediaCapture, video, message, prevMessage, snapshot, facesCanvas;

var Capture = Windows.Media.Capture;
var captureSettings = new Capture.MediaCaptureInitializationSettings;
var DeviceEnumeration = Windows.Devices.Enumeration;
var displayRequest = new Windows.System.Display.DisplayRequest();
var effectDefinition = new Windows.Media.Core.FaceDetectionEffectDefinition();
var isAuthenticated = false;
var mediaStreamType = Capture.MediaStreamType.videoRecord;

function isStable(face) {
  if (stabilizationCounter == cycles) {
    prevX = prevY = prevWidth = prevHeight = null;
    stabilizationCounter = 0;
    return true;
  }

  var curX = face.x;
  var curY = face.y;
  var curWidth = face.width;
  var curHeight = face.height;

  stabilizationCounter++;

  if (prevX) {
    var distance = Math.sqrt(Math.pow(curX - prevX, 2) + Math.pow(curY - prevY, 2));
    if (distance > maxDistance || Math.abs(curWidth - prevWidth) > maxChange || Math.abs(curHeight - prevHeight) > maxChange) {
      stabilizationCounter = 0;
    }
  }

  prevX = curX;
  prevY = curY;
  prevWidth = curWidth;
  prevHeight = curHeight;

  return false;
}

var Authenticate = {}

Authenticate.findCameraDeviceByPanelAsync = function (panel) {
  var deviceInfo;
  return DeviceEnumeration.DeviceInformation.findAllAsync(DeviceEnumeration.DeviceClass.videoCapture).then(
    function(devices) {
      devices.forEach(function(cameraDeviceInfo) {
        if (cameraDeviceInfo.enclosureLocation != null && cameraDeviceInfo.enclosureLocation.panel === panel) {
          deviceInfo = cameraDeviceInfo;
          return;
        }
      });

      return !deviceInfo && devices.length > 0 ? devices.getAt(0) : deviceInfo;
    }
  );
}

Authenticate.takePhoto = function(addFace) {
  isAuthenticated = true;
  var Storage = Windows.Storage;
  var stream = new Storage.Streams.InMemoryRandomAccessStream();
  mediaCapture.capturePhotoToStreamAsync(Windows.Media.MediaProperties.ImageEncodingProperties.createJpeg(), stream)
  .then(function() {
    var buffer = new Storage.Streams.Buffer(stream.size);
    stream.seek(0);
    stream.readAsync(buffer, stream.size, 0).done(function() {
      var dataReader = Storage.Streams.DataReader.fromBuffer(buffer);
      var byteArray = new Uint8Array(buffer.length);
      dataReader.readBytes(byteArray);

      // Detect the face to get a face ID
      $.ajax({
        url: '/capture/authenticate',
        beforeSend: function(xhrObj) {
          xhrObj.setRequestHeader('Content-Type', 'application/octet-stream');
        },
        type: 'POST',
        data: byteArray,
        processData: false
      })
      .done(function(result) {
        var resultObj = JSON.parse(result)
        if(resultObj.authenticated){
          authenticated = true
          authenticating = false
          message.innerText = resultObj.message;
        } else {
          //If authenticated is false, then there was no match so start fresh
          authenticated = false
          authenticating = false
          message.innerText = ''
        }
      })
      .fail(function(e) {
        console.error(e);
      });

    });
  });
}

Authenticate.handleFaces = function(args) {
  var context = facesCanvas.getContext('2d');
  context.clearRect(0, 0, facesCanvas.width, facesCanvas.height);
  var detectedFaces = args.resultFrame.detectedFaces;
  var numFaces = detectedFaces.length;
  if (numFaces > 0) {
    var face;

    for (var i = 0; i < numFaces; i++) {
      face = detectedFaces.getAt(i).faceBox;
      context.beginPath();
      context.rect(face.x, face.y, face.width, face.height);
      context.lineWidth = 3;
      context.strokeStyle = faceboxColors[i % faceboxColors.length];
      context.stroke();
      context.closePath();

      if (mirroring) {
        facesCanvas.style.transform = 'scale(-1, 1)';
      }
      if(authenticated == false && authenticating == false && face.width > faceThresholds.width && face.height > faceThresholds.height){
        if (isStable(face)) {
          authenticating = true
          Authenticate.takePhoto()
        }
      }
    }
  }
}

Authenticate.mirrorPreview= function () {
  var props = mediaCapture.videoDeviceController.getMediaStreamProperties(Capture.MediaStreamType.videoPreview);
  props.properties.insert('C380465D-2271-428C-9B83-ECEA3B4A85C1', 0);
  return mediaCapture.setEncodingPropertiesAsync(Capture.MediaStreamType.videoPreview, props, null);
}

Authenticate.init = function() {
  if (typeof Windows == 'undefined') {
    console.log('Windows is not available');
    return;
  }
  buttonReset = document.getElementById('buttonReset')
  buttonReset.addEventListener('click', function() {
    message.innerText = '';
    authenticating = false
    authenticated = false
  })
  message = document.getElementById('message');
  facesCanvas = document.getElementById('facesCanvas');
  video = document.getElementById('video');
  facesCanvas.width = video.offsetWidth;
  facesCanvas.height = video.offsetHeight;
  Authenticate.findCameraDeviceByPanelAsync(DeviceEnumeration.Panel.back).then(
    function(camera) {
      if (!camera) {
        console.error('No camera device found!');
        return;
      }
      mediaCapture = new Capture.MediaCapture();
      captureSettings.videoDeviceId = camera.id;
      captureSettings.streamingCaptureMode = Capture.StreamingCaptureMode.video;
      mediaCapture.initializeAsync(captureSettings).then(
        function fulfilled(result) {
          mediaCapture.addVideoEffectAsync(effectDefinition, mediaStreamType).done(
            function complete(result) {
              result.desiredDetectionInterval = detectionInterval;
              result.addEventListener('facedetected', Authenticate.handleFaces);
            },
            function error(e) {
              console.error(e);
            }
          );
          displayRequest.requestActive();
          var preview = document.getElementById('cameraPreview');

          if (mirroring) {
            preview.style.transform = 'scale(-1, 1)';
            preview.addEventListener('playing', Authenticate.mirrorPreview);
          }
          var previewUrl = URL.createObjectURL(mediaCapture);
          preview.src = previewUrl;
          preview.play();
        },
        function error(e) {
          console.error(e);
        }
      );
    }
  );
}

window.Authenticate = Authenticate
<|endoftext|>


<commit_before>// ----------------------------------------------------------------------------
// File: Model.js
//
// Copyright (c) 2014 VoodooJs Authors
// ----------------------------------------------------------------------------

/**
 * Stores the id number to use for the next model created.
 *
 * @private
 *
 * @type {number}
 */
var nextModelId_ = 0;

/**
 * Default model organization when none is specified.
 *
 * @type {string}
 * @const
 * @private
 */
var defaultOrganization_ = '*';

/**
 * Base class for all models.
 *
 * A model is a single 3D object managed by the Voodoo engine. A model
 * stores the state of the object and a reference to its View. The
 * View is the renderable part of the 3D object. The user only interacts
 * with the model.
 *
 * All user models must extend Model via extend().
 *
 * @constructor
 * @extends {Extendable}
 */
var Model = Extendable['extend']();

/**
 * Cleans up resources before the model is destroyed.
 *
 * Derived classes may override this. This should never be called by the user.
 *
 * @this {Model}
 */
Model.prototype['cleanUp'] = function() {
  var func = this['base']['cleanUp'];
  if (typeof func === 'function')
    func();
};

/**
 * Constructs a new model.
 *
 * This is internal and must not be overridden or called by the user.
 *
 * @this {Model}
 * @ignore
 *
 * @param {Object} options User options.
 */
Model.prototype['construct'] = function(options) {
  log_.assert_(this['name'], 'Model type name cannot be undefined or null');
  log_.assert_(this['viewType'], 'Model view type cannot be undefined or null');
  if (!this['viewType'].prototype['above'] &&
      !this['viewType'].prototype['below'])
    log_.error_('View must exist on at least one layer');
  this['stencilViewType'] = this['stencilViewType'] || this['viewType'];

  this.setId_();
  log_.modelInformation_(this, 'Constructing');

  // If no engine has been created, create one with default options.
  if (typeof window['voodoo']['engine'] === 'undefined' ||
      window['voodoo']['engine'] === null) {
    window['voodoo']['engine'] = new Engine(new Options());
  }

  this.dispatcher_ = new Dispatcher_();

  this.setupCache_();
  if (typeof options === 'undefined' || !options)
    options = {};
  this['initialize'](options);

  this.createViews_();

  this.setupViewProperties_();
  this['setUpViews']();

  // Add this model to the engine to be updated
  window['voodoo']['engine'].addModel_(this);
};

/**
 * Destroys the model and all its views. This should not be overridden.
 *
 * @this {Model}
 */
Model.prototype['destroy'] = function() {
  log_.modelInformation_(this, 'Destroying');

  this.dispatchEvent_(new window['voodoo']['Event']('destroy', this));

  this['tearDownViews']();

  // Remove this model from the engine to stop being updated
  window['voodoo']['engine'].removeModel_(this);

  if (this.view_ && this.view_['destroy'])
    this.view_['destroy']();
  if (this.stencilView_ && this.stencilView_['destroy'])
    this.stencilView_['destroy']();

  this['cleanUp']();

  this.dispatcher_.destroy_();

  this.dispatcher_ = null;
  this.view_ = null;
  this.stencilView_ = null;
};

/**
 * Dispatches a custom event to all listeners registered on this model.
 *
 * @this {Model}
 *
 * @param {Event} event Event to fire.
 *
 * @return {Model} This.
 */
Model.prototype['dispatch'] = function(event) {
  event['model'] = this;
  this.dispatchEvent_(event);
  return this;
};

/**
 * Initialzes the model. This is the first method to be called when the
 * model is instantiated. Derived classes may override this. This should never
 * be called by the user. The options parameter is what the user passed to
 * the constructor when this Model was instantiated.
 *
 * @this {Model}
 *
 * @param {Object} options User options.
 */
Model.prototype['initialize'] = function(options) {
  var func = this['base']['initialize'];
  if (typeof func === 'function')
    func(options);
};

/**
 * Removes an event handler.
 *
 * @this {Model}
 *
 * @param {string} type Event type.
 * @param {function(Event)} listener Event listener.
 *
 * @return {Model} This.
 */
Model.prototype['off'] = function(type, listener) {
  this.dispatcher_.off_(type, listener);

  return this;
};

/**
 * Adds an event handler. Valid events are cameramove, destroy, mousedown,
 * mouseup, mouseover, mouseout, mousemove, click, and dblclick.
 *
 * @this {Model}
 *
 * @param {string} type Event type.
 * @param {function(Event)} listener Event listener.
 *
 * @return {Model} This.
 */
Model.prototype['on'] = function(type, listener) {
  this.dispatcher_.on_(type, listener);

  // Load is a special event since it can be dispatched before the user had time
  // to register for the event, so we call it anyway as soon as an event
  // listener is registered.
  if (type == 'load' && this.numViewsLoaded_ === this.numViewsToLoad_)
    listener.call(this, new window['voodoo']['Event']('load', this));

  return this;
};

/**
 * Initialize the view and stencilView. This is called after initialize() when
 * a model is instantiated. Derived classes may override this. This should never
 * be called by the user.
 *
 * @this {Model}
 */
Model.prototype['setUpViews'] = function() {
  var func = this['base']['setUpViews'];
  if (typeof func === 'function')
    func();
};

/**
 * Shuts down the views. This is called before cleanUp() when a model is
 * destroyed. Derived classes may override this. This should never be called by
 * the user.
 *
 * @this {Model}
 */
Model.prototype['tearDownViews'] = function() {
  var func = this['base']['tearDownViews'];
  if (typeof func === 'function')
    func();
};

/**
 * Each frame this is called to update and animate the model.
 *
 * Derived classes may override this. This should never be called by the user.
 *
 * @param {number} deltaTime The time difference between this frame and last in
 * seconds. This is often used for consistent animation.
 *
 * @this {Model}
 */
Model.prototype['update'] = function(deltaTime) {
  var func = this['base']['update'];
  if (typeof func === 'function')
    func(deltaTime);
};

/**
 * The storage cache for model objects.
 *
 * @type {Cache}
 */
Model.prototype['cache'] = null;

/**
 * Indicates whether all views have finished loading.
 *
 * @type {boolean}
 */
Model.prototype['loaded'] = false;

/**
 * The composite stencil view for this model.
 *
 * @type {Object}
 */
Model.prototype['stencilView'] = null;

/**
 * The composite regular view for this model.
 *
 * @type {Object}
 */
Model.prototype['view'] = null;

/**
 * Fires an event.
 *
 * @this {Model}
 * @private
 *
 * @param {Event} event Event description.
 */
Model.prototype.dispatchEvent_ = function(event) {
  this.dispatcher_.dispatchEvent_(this, event);
};

/**
 * Creates each view.
 *
 * @this {Model}
 * @private
 */
Model.prototype.createViews_ = function() {
  this.views_ = [];
  this.stencilViews_ = [];
  this.numViewsLoaded_ = 0;
  this.numViewsToLoad_ = 0;

  /** @type {Engine} */
  var engine = window['voodoo']['engine'];
  var layers = engine.renderer_.layers_;

  Object.defineProperty(this, 'loaded', {
    get: function() { return this.numViewsLoaded_ === this.numViewsToLoad_; },
    set: function() { log_.error_('loaded is read-only'); },
    writeable: false
  });

  // Create the views, one for each layer and one additional for the
  // stencil layer.
  var nonuniqueStencilView = this['stencilViewType'] == this['viewType'];
  for (var layerIndex = 0; layerIndex < layers.length; ++layerIndex) {
    var layer = layers[layerIndex];

    switch (layer.pass_) {
      case LayerPass_['Above']:
        if (this['viewType'].prototype['above'])
          this.views_.push(new this['viewType'](this, layer));
        break;
      case LayerPass_['Below']:
        if (this['viewType'].prototype['below'])
          this.views_.push(new this['viewType'](this, layer));
        break;
      case LayerPass_['Seam']:
        // If the model has content in the above layer, it MUST be added
        // to the seam layer to work with the stencil tests against other
        // models in the seam layer.
        if (this['viewType'].prototype['above'])
          this.views_.push(new this['viewType'](this, layer));
        break;
      case LayerPass_['BelowStencil']:
        if (this['viewType'].prototype['below']) {
          if (nonuniqueStencilView)
            this.views_.push(new this['viewType'](this, layer));
          else
            this.stencilViews_.push(new this['stencilViewType'](this, layer));
        }
        break;
      case LayerPass_['SeamStencil']:
        if (this['viewType'].prototype['below']) {
          if (nonuniqueStencilView)
            this.views_.push(new this['viewType'](this, layer));
          else
            this.stencilViews_.push(new this['stencilViewType'](this, layer));
        }
        break;
    }
  }

  // Create composite view and stencil views if there are more than one.
  this.view_ = this.views_.length > 1 ?
      new Composite_(this.views_) :
      this.views_[0];
  this.stencilView_ = this.stencilViews_.length > 1 ?
      new Composite_(this.stencilViews_) :
      this.stencilViews_[0];

  this.numViewsToLoad_ = this.views_.length + this.stencilViews_.length;
};

/**
 * Called from the view when it has loaded.
 *
 * @private
 *
 * @param {View} view View that loaded.
 */
Model.prototype.onViewLoad_ = function(view) {
  this.numViewsLoaded_++;
  if (this.numViewsLoaded_ === this.numViewsToLoad_)
    this.dispatchEvent_(new window['voodoo']['Event']('load', this));
};

/**
 * Sets the identifier used for thei model in logging.
 *
 * @private
 */
Model.prototype.setId_ = function() {
  this.id_ = '<' + (++nextModelId_) + ',';

  // Only write the organization if it's not the default.
  if (this['organization'] !== defaultOrganization_)
    this.id_ += this['organization'] + '.';

  this.id_ += this['name'] + '>';
};

/**
 * Sets up the cache and the public property for it.
 *
 * @private
 */
Model.prototype.setupCache_ = function() {
  this.cache_ = window['voodoo']['engine'].modelCacheFactory_.createCache_(
      this);

  Object.defineProperty(this, 'cache', {
    get: function() { return this.cache_; },
    set: function() { log_.error_('cache is read-only'); },
    writeable: false
  });
};

/**
 * Creates the public properties for the views of the Model.
 *
 * @private
 */
Model.prototype.setupViewProperties_ = function() {
  Object.defineProperty(this, 'view', {
    get: function() { return this.view_; },
    set: function() { log_.error_('view is read-only'); },
    writeable: false
  });

  Object.defineProperty(this, 'stencilView', {
    get: function() { return this.stencilView_; },
    set: function() { log_.error_('stencilView is read-only'); },
    writeable: false
  });
};

/**
 * Friendly type name for this model.
 *
 * This must be set before creating any instances.
 *
 * @type {string}
 */
Model.prototype['name'] = null;

/**
 * Organization name for this model.
 *
 * This is optional and is used to differentiate between models with the same
 * name in the cache.
 *
 * @type {string}
 */
Model.prototype['organization'] = defaultOrganization_;

/**
 * The view type for this model.
 *
 * This must be set before creating any instances.
 *
 * @type {View}
 */
Model.prototype['viewType'] = null;

/**
 * The stencil view type for this model.
 *
 * If this is left undefined, voodoo uses the view.
 *
 * @type {View}
 */
Model.prototype['stencilViewType'] = null;

/**
 * Derives a new type from a base Model. The Model's views
 * are also automatically extended if they are defined.
 *
 * @param {Object=} opt_object Optional object to extend with.
 *
 * @return {?} Extended type.
 */
Model['extend'] = function(opt_object) {
  var newType = Extendable['extend'].call(this, opt_object);

  var viewType = this.prototype['viewType'];
  var newViewType = newType.prototype['viewType'];
  if (typeof viewType !== 'undefined' && viewType !== null &&
      typeof newViewType !== 'undefined' && newViewType !== null &&
      viewType != newViewType) {
    newType.prototype['viewType'] = viewType['extend'](newViewType);
  }

  var stencil = this.prototype['stencilViewType'];
  var newStencil = newType.prototype['stencilViewType'];
  if (typeof stencil !== 'undefined' && stencil != null &&
      typeof newStencil !== 'undefined' && newStencil != null &&
      stencil != newStencil) {
    newType.prototype['stencilViewType'] = stencil['extend'](newStencil);
  }

  var oldName = this.prototype['name'];
  var newName = newType.prototype['name'];
  if (typeof oldName !== 'undefined' && oldName !== null &&
      typeof newName !== 'undefined' && newName !== null &&
      newName !== oldName)
    newType.prototype['name'] = oldName + '.' + newName;

  return newType;
};

// Exports
this['Model'] = Model;
<commit_msg>Documentation fix for Model.loaded<commit_after>// ----------------------------------------------------------------------------
// File: Model.js
//
// Copyright (c) 2014 VoodooJs Authors
// ----------------------------------------------------------------------------

/**
 * Stores the id number to use for the next model created.
 *
 * @private
 *
 * @type {number}
 */
var nextModelId_ = 0;

/**
 * Default model organization when none is specified.
 *
 * @type {string}
 * @const
 * @private
 */
var defaultOrganization_ = '*';

/**
 * Base class for all models.
 *
 * A model is a single 3D object managed by the Voodoo engine. A model
 * stores the state of the object and a reference to its View. The
 * View is the renderable part of the 3D object. The user only interacts
 * with the model.
 *
 * All user models must extend Model via extend().
 *
 * @constructor
 * @extends {Extendable}
 */
var Model = Extendable['extend']();

/**
 * Cleans up resources before the model is destroyed.
 *
 * Derived classes may override this. This should never be called by the user.
 *
 * @this {Model}
 */
Model.prototype['cleanUp'] = function() {
  var func = this['base']['cleanUp'];
  if (typeof func === 'function')
    func();
};

/**
 * Constructs a new model.
 *
 * This is internal and must not be overridden or called by the user.
 *
 * @this {Model}
 * @ignore
 *
 * @param {Object} options User options.
 */
Model.prototype['construct'] = function(options) {
  log_.assert_(this['name'], 'Model type name cannot be undefined or null');
  log_.assert_(this['viewType'], 'Model view type cannot be undefined or null');
  if (!this['viewType'].prototype['above'] &&
      !this['viewType'].prototype['below'])
    log_.error_('View must exist on at least one layer');
  this['stencilViewType'] = this['stencilViewType'] || this['viewType'];

  this.setId_();
  log_.modelInformation_(this, 'Constructing');

  // If no engine has been created, create one with default options.
  if (typeof window['voodoo']['engine'] === 'undefined' ||
      window['voodoo']['engine'] === null) {
    window['voodoo']['engine'] = new Engine(new Options());
  }

  this.dispatcher_ = new Dispatcher_();

  this.setupCache_();
  if (typeof options === 'undefined' || !options)
    options = {};
  this['initialize'](options);

  this.createViews_();

  this.setupViewProperties_();
  this['setUpViews']();

  // Add this model to the engine to be updated
  window['voodoo']['engine'].addModel_(this);
};

/**
 * Destroys the model and all its views. This should not be overridden.
 *
 * @this {Model}
 */
Model.prototype['destroy'] = function() {
  log_.modelInformation_(this, 'Destroying');

  this.dispatchEvent_(new window['voodoo']['Event']('destroy', this));

  this['tearDownViews']();

  // Remove this model from the engine to stop being updated
  window['voodoo']['engine'].removeModel_(this);

  if (this.view_ && this.view_['destroy'])
    this.view_['destroy']();
  if (this.stencilView_ && this.stencilView_['destroy'])
    this.stencilView_['destroy']();

  this['cleanUp']();

  this.dispatcher_.destroy_();

  this.dispatcher_ = null;
  this.view_ = null;
  this.stencilView_ = null;
};

/**
 * Dispatches a custom event to all listeners registered on this model.
 *
 * @this {Model}
 *
 * @param {Event} event Event to fire.
 *
 * @return {Model} This.
 */
Model.prototype['dispatch'] = function(event) {
  event['model'] = this;
  this.dispatchEvent_(event);
  return this;
};

/**
 * Initialzes the model. This is the first method to be called when the
 * model is instantiated. Derived classes may override this. This should never
 * be called by the user. The options parameter is what the user passed to
 * the constructor when this Model was instantiated.
 *
 * @this {Model}
 *
 * @param {Object} options User options.
 */
Model.prototype['initialize'] = function(options) {
  var func = this['base']['initialize'];
  if (typeof func === 'function')
    func(options);
};

/**
 * Removes an event handler.
 *
 * @this {Model}
 *
 * @param {string} type Event type.
 * @param {function(Event)} listener Event listener.
 *
 * @return {Model} This.
 */
Model.prototype['off'] = function(type, listener) {
  this.dispatcher_.off_(type, listener);

  return this;
};

/**
 * Adds an event handler. Valid events are cameramove, destroy, mousedown,
 * mouseup, mouseover, mouseout, mousemove, click, and dblclick.
 *
 * @this {Model}
 *
 * @param {string} type Event type.
 * @param {function(Event)} listener Event listener.
 *
 * @return {Model} This.
 */
Model.prototype['on'] = function(type, listener) {
  this.dispatcher_.on_(type, listener);

  // Load is a special event since it can be dispatched before the user had time
  // to register for the event, so we call it anyway as soon as an event
  // listener is registered.
  if (type == 'load' && this.numViewsLoaded_ === this.numViewsToLoad_)
    listener.call(this, new window['voodoo']['Event']('load', this));

  return this;
};

/**
 * Initialize the view and stencilView. This is called after initialize() when
 * a model is instantiated. Derived classes may override this. This should never
 * be called by the user.
 *
 * @this {Model}
 */
Model.prototype['setUpViews'] = function() {
  var func = this['base']['setUpViews'];
  if (typeof func === 'function')
    func();
};

/**
 * Shuts down the views. This is called before cleanUp() when a model is
 * destroyed. Derived classes may override this. This should never be called by
 * the user.
 *
 * @this {Model}
 */
Model.prototype['tearDownViews'] = function() {
  var func = this['base']['tearDownViews'];
  if (typeof func === 'function')
    func();
};

/**
 * Each frame this is called to update and animate the model.
 *
 * Derived classes may override this. This should never be called by the user.
 *
 * @param {number} deltaTime The time difference between this frame and last in
 * seconds. This is often used for consistent animation.
 *
 * @this {Model}
 */
Model.prototype['update'] = function(deltaTime) {
  var func = this['base']['update'];
  if (typeof func === 'function')
    func(deltaTime);
};

/**
 * The storage cache for model objects.
 *
 * @type {Cache}
 */
Model.prototype['cache'] = null;

/**
 * Readonly property indicating whether all views have finished loading.
 *
 * @type {boolean}
 */
Model.prototype['loaded'] = false;

/**
 * The composite stencil view for this model.
 *
 * @type {Object}
 */
Model.prototype['stencilView'] = null;

/**
 * The composite regular view for this model.
 *
 * @type {Object}
 */
Model.prototype['view'] = null;

/**
 * Fires an event.
 *
 * @this {Model}
 * @private
 *
 * @param {Event} event Event description.
 */
Model.prototype.dispatchEvent_ = function(event) {
  this.dispatcher_.dispatchEvent_(this, event);
};

/**
 * Creates each view.
 *
 * @this {Model}
 * @private
 */
Model.prototype.createViews_ = function() {
  this.views_ = [];
  this.stencilViews_ = [];
  this.numViewsLoaded_ = 0;
  this.numViewsToLoad_ = 0;

  /** @type {Engine} */
  var engine = window['voodoo']['engine'];
  var layers = engine.renderer_.layers_;

  Object.defineProperty(this, 'loaded', {
    get: function() { return this.numViewsLoaded_ === this.numViewsToLoad_; },
    set: function() { log_.error_('loaded is read-only'); },
    writeable: false
  });

  // Create the views, one for each layer and one additional for the
  // stencil layer.
  var nonuniqueStencilView = this['stencilViewType'] == this['viewType'];
  for (var layerIndex = 0; layerIndex < layers.length; ++layerIndex) {
    var layer = layers[layerIndex];

    switch (layer.pass_) {
      case LayerPass_['Above']:
        if (this['viewType'].prototype['above'])
          this.views_.push(new this['viewType'](this, layer));
        break;
      case LayerPass_['Below']:
        if (this['viewType'].prototype['below'])
          this.views_.push(new this['viewType'](this, layer));
        break;
      case LayerPass_['Seam']:
        // If the model has content in the above layer, it MUST be added
        // to the seam layer to work with the stencil tests against other
        // models in the seam layer.
        if (this['viewType'].prototype['above'])
          this.views_.push(new this['viewType'](this, layer));
        break;
      case LayerPass_['BelowStencil']:
        if (this['viewType'].prototype['below']) {
          if (nonuniqueStencilView)
            this.views_.push(new this['viewType'](this, layer));
          else
            this.stencilViews_.push(new this['stencilViewType'](this, layer));
        }
        break;
      case LayerPass_['SeamStencil']:
        if (this['viewType'].prototype['below']) {
          if (nonuniqueStencilView)
            this.views_.push(new this['viewType'](this, layer));
          else
            this.stencilViews_.push(new this['stencilViewType'](this, layer));
        }
        break;
    }
  }

  // Create composite view and stencil views if there are more than one.
  this.view_ = this.views_.length > 1 ?
      new Composite_(this.views_) :
      this.views_[0];
  this.stencilView_ = this.stencilViews_.length > 1 ?
      new Composite_(this.stencilViews_) :
      this.stencilViews_[0];

  this.numViewsToLoad_ = this.views_.length + this.stencilViews_.length;
};

/**
 * Called from the view when it has loaded.
 *
 * @private
 *
 * @param {View} view View that loaded.
 */
Model.prototype.onViewLoad_ = function(view) {
  this.numViewsLoaded_++;
  if (this.numViewsLoaded_ === this.numViewsToLoad_)
    this.dispatchEvent_(new window['voodoo']['Event']('load', this));
};

/**
 * Sets the identifier used for thei model in logging.
 *
 * @private
 */
Model.prototype.setId_ = function() {
  this.id_ = '<' + (++nextModelId_) + ',';

  // Only write the organization if it's not the default.
  if (this['organization'] !== defaultOrganization_)
    this.id_ += this['organization'] + '.';

  this.id_ += this['name'] + '>';
};

/**
 * Sets up the cache and the public property for it.
 *
 * @private
 */
Model.prototype.setupCache_ = function() {
  this.cache_ = window['voodoo']['engine'].modelCacheFactory_.createCache_(
      this);

  Object.defineProperty(this, 'cache', {
    get: function() { return this.cache_; },
    set: function() { log_.error_('cache is read-only'); },
    writeable: false
  });
};

/**
 * Creates the public properties for the views of the Model.
 *
 * @private
 */
Model.prototype.setupViewProperties_ = function() {
  Object.defineProperty(this, 'view', {
    get: function() { return this.view_; },
    set: function() { log_.error_('view is read-only'); },
    writeable: false
  });

  Object.defineProperty(this, 'stencilView', {
    get: function() { return this.stencilView_; },
    set: function() { log_.error_('stencilView is read-only'); },
    writeable: false
  });
};

/**
 * Friendly type name for this model.
 *
 * This must be set before creating any instances.
 *
 * @type {string}
 */
Model.prototype['name'] = null;

/**
 * Organization name for this model.
 *
 * This is optional and is used to differentiate between models with the same
 * name in the cache.
 *
 * @type {string}
 */
Model.prototype['organization'] = defaultOrganization_;

/**
 * The view type for this model.
 *
 * This must be set before creating any instances.
 *
 * @type {View}
 */
Model.prototype['viewType'] = null;

/**
 * The stencil view type for this model.
 *
 * If this is left undefined, voodoo uses the view.
 *
 * @type {View}
 */
Model.prototype['stencilViewType'] = null;

/**
 * Derives a new type from a base Model. The Model's views
 * are also automatically extended if they are defined.
 *
 * @param {Object=} opt_object Optional object to extend with.
 *
 * @return {?} Extended type.
 */
Model['extend'] = function(opt_object) {
  var newType = Extendable['extend'].call(this, opt_object);

  var viewType = this.prototype['viewType'];
  var newViewType = newType.prototype['viewType'];
  if (typeof viewType !== 'undefined' && viewType !== null &&
      typeof newViewType !== 'undefined' && newViewType !== null &&
      viewType != newViewType) {
    newType.prototype['viewType'] = viewType['extend'](newViewType);
  }

  var stencil = this.prototype['stencilViewType'];
  var newStencil = newType.prototype['stencilViewType'];
  if (typeof stencil !== 'undefined' && stencil != null &&
      typeof newStencil !== 'undefined' && newStencil != null &&
      stencil != newStencil) {
    newType.prototype['stencilViewType'] = stencil['extend'](newStencil);
  }

  var oldName = this.prototype['name'];
  var newName = newType.prototype['name'];
  if (typeof oldName !== 'undefined' && oldName !== null &&
      typeof newName !== 'undefined' && newName !== null &&
      newName !== oldName)
    newType.prototype['name'] = oldName + '.' + newName;

  return newType;
};

// Exports
this['Model'] = Model;
<|endoftext|>


<commit_before>// @flow

import React from 'react'
import {SourceModel} from '../model/source'
import {AdminModel} from '../model/admin'
import {Link} from 'react-router'
import {sortBy} from 'lodash'

export class Sources extends React.Component {

  static load() {
    return {sources: SourceModel.findAll(), version: AdminModel.version()}
  }

  constructor(props) {
    super(props)
  }

  render() {
    var sources = this.props.sources || []

    var sorted = sortBy(sources, s => s.sourceDisabled)

    function renderRow(source) {
      var lastScan = source.lastScan || {}
      return

        <Link to="source" params={{id: source.id}}>{source.name}</Link>
        {source.url}
        {!source.disabled ? 'Active' : 'Disabled'}
        {lastScan.total}

    }

    return

Sources

      Add Source

          Image
          Name
          URL
          Active
          Chapters

        {sorted.map(renderRow)}

Version: {this.props.version}

Import Log

  }
}

<commit_msg>easier to see current version<commit_after>// @flow

import React from 'react'
import {SourceModel} from '../model/source'
import {AdminModel} from '../model/admin'
import {Link} from 'react-router'
import {sortBy} from 'lodash'

export class Sources extends React.Component {

  static load() {
    return {sources: SourceModel.findAll(), version: AdminModel.version()}
  }

  constructor(props) {
    super(props)
  }

  render() {
    var sources = this.props.sources || []

    var sorted = sortBy(sources, s => s.sourceDisabled)

    function renderRow(source) {
      var lastScan = source.lastScan || {}
      return

        <Link to="source" params={{id: source.id}}>{source.name}</Link>
        {source.url}
        {!source.disabled ? 'Active' : 'Disabled'}
        {lastScan.total}

    }

    return

Sources

      Add Source

          Image
          Name
          URL
          Active
          Chapters

        {sorted.map(renderRow)}

Import Log

Version: {this.props.version}

  }
}

<|endoftext|>


<commit_before>/*
 * Javascript Diff Algorithm
 *  By John Resig (http://ejohn.org/)
 *  Modified by Chu Alan "sprite"
 *
 * More Info:
 *  http://ejohn.org/projects/javascript-diff-algorithm/
 */

function escape(s) {
    var n = s;
    n = n.replace(/&/g, "&");
    n = n.replace(/</g, "<");
    n = n.replace(/>/g, ">");
    n = n.replace(/"/g, """);

    return n;
}

function diffString( o, n ) {
  o = o.replace(/\s+$/, '');
  n = n.replace(/\s+$/, '');

  var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );
  var str = "";

  var oSpace = o.match(/\s+/g);
  if (oSpace == null) {
    oSpace = ["\n"];
  } else {
    oSpace.push("\n");
  }
  var nSpace = n.match(/\s+/g);
  if (nSpace == null) {
    nSpace = ["\n"];
  } else {
    nSpace.push("\n");
  }

  if (out.n.length == 0) {
      for (var i = 0; i < out.o.length; i++) {
        str += '' + escape(out.o[i]) + oSpace[i] + "";
      }
  } else {
    if (out.n[0].text == null) {
      for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
        str += '' + escape(out.o[n]) + oSpace[n] + "";
      }
    }

    for ( var i = 0; i < out.n.length; i++ ) {
      if (out.n[i].text == null) {
        str += '' + escape(out.n[i]) + nSpace[i] + "";
      } else {
        var pre = "";

        for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
          pre += '' + escape(out.o[n]) + oSpace[n] + "";
        }
        str += " " + out.n[i].text + nSpace[i] + pre;
      }
    }
  }

  return str;
}

function randomColor() {
    return "rgb(" + (Math.random() * 100) + "%, " +
                    (Math.random() * 100) + "%, " +
                    (Math.random() * 100) + "%)";
}
function diffString2( o, n ) {
  o = o.replace(/\s+$/, '');
  n = n.replace(/\s+$/, '');

  var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/) );

  var oSpace = o.match(/\s+/g);
  if (oSpace == null) {
    oSpace = ["\n"];
  } else {
    oSpace.push("\n");
  }
  var nSpace = n.match(/\s+/g);
  if (nSpace == null) {
    nSpace = ["\n"];
  } else {
    nSpace.push("\n");
  }

  var os = "";
  var colors = new Array();
  for (var i = 0; i < out.o.length; i++) {
      colors[i] = randomColor();

      if (out.o[i].text != null) {
          os += '' +
                escape(out.o[i].text) + oSpace[i] + "";
      } else {
          os += "" + escape(out.o[i]) + oSpace[i] + "";
      }
  }

  var ns = "";
  for (var i = 0; i < out.n.length; i++) {
      if (out.n[i].text != null) {
          ns += '' +
                escape(out.n[i].text) + nSpace[i] + "";
      } else {
          ns += "" + escape(out.n[i]) + nSpace[i] + "";
      }
  }

  return { o : os , n : ns };
}

function diff( o, n ) {
  var ns = new Object();
  var os = new Object();

  for ( var i = 0; i < n.length; i++ ) {
    if ( ns[ n[i] ] == null )
      ns[ n[i] ] = { rows: new Array(), o: null };
    ns[ n[i] ].rows.push( i );
  }

  for ( var i = 0; i < o.length; i++ ) {
    if ( os[ o[i] ] == null )
      os[ o[i] ] = { rows: new Array(), n: null };
    os[ o[i] ].rows.push( i );
  }

  for ( var i in ns ) {
    if ( ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1 ) {
      n[ ns[i].rows[0] ] = { text: n[ ns[i].rows[0] ], row: os[i].rows[0] };
      o[ os[i].rows[0] ] = { text: o[ os[i].rows[0] ], row: ns[i].rows[0] };
    }
  }

  for ( var i = 0; i < n.length - 1; i++ ) {
    if ( n[i].text != null && n[i+1].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
         n[i+1] == o[ n[i].row + 1 ] ) {
      n[i+1] = { text: n[i+1], row: n[i].row + 1 };
      o[n[i].row+1] = { text: o[n[i].row+1], row: i + 1 };
    }
  }

  for ( var i = n.length - 1; i > 0; i-- ) {
    if ( n[i].text != null && n[i-1].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
         n[i-1] == o[ n[i].row - 1 ] ) {
      n[i-1] = { text: n[i-1], row: n[i].row - 1 };
      o[n[i].row-1] = { text: o[n[i].row-1], row: i - 1 };
    }
  }

  return { o: o, n: n };
}

<commit_msg>Remove jsdiff file that hasn't ever been used.<commit_after><|endoftext|>