<commit_before>'use strict';

/**
 * @ngdoc interface
 * @name angular.Module
 * @description
 *
 * Interface for configuring angular {@link angular.module modules}.
 */

function setupModuleLoader(window) {

  function ensure(obj, name, factory) {
    return obj[name] || (obj[name] = factory());
  }

  return ensure(ensure(window, 'angular', Object), 'module', function() {
    /** @type {Object.<string, angular.Module>} */
    var modules = {};

    /**
     * @ngdoc function
     * @name angular.module
     * @description
     *
     * The `angular.module` is a global place for creating and registering Angular modules. All
     * modules (angular core or 3rd party) that should be available to an application must be
     * registered using this mechanism.
     *
     *
     * # Module
     *
     * A module is a collocation of services, directives, filters, and configure information. Module
     * is used to configure the {@link AUTO.$injector $injector}.
     *
     *

     * // Create a new module
     * var myModule = angular.module('myModule', []);
     *
     * // register a new service
     * myModule.value('appName', 'MyCoolApp');
     *
     * // configure existing services inside initialization blocks.
     * myModule.config(function($locationProvider) {
     *   // Configure existing providers
     *   $locationProvider.hashPrefix('!');
     * });
     *

     *
     * Then you can create an injector and load your modules like this:
     *
     *

     * var injector = angular.injector(['ng', 'MyModule'])
     *

     *
     * However it's more likely that you'll just use
     * {@link ng.directive:ngApp ngApp} or
     * {@link angular.bootstrap} to simplify this process for you.
     *
     * @param {!string} name The name of the module to create or retrieve.
     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
     *        the module is being retrieved for further configuration.
     * @param {Function} configFn Option configuration function for the module. Same as
     *        {@link angular.Module#config Module#config()}.
     * @returns {module} new module with the {@link angular.Module} api.
     */
    return function module(name, requires, configFn) {
      if (requires && modules.hasOwnProperty(name)) {
        modules[name] = null;
      }
      return ensure(modules, name, function() {
        if (!requires) {
          throw Error('No module: ' + name);
        }

        /** @type {!Array.<Array.<*>>} */
        var invokeQueue = [];

        /** @type {!Array.<Function>} */
        var runBlocks = [];

        var config = invokeLater('$injector', 'invoke');

        /** @type {angular.Module} */
        var moduleInstance = {
          // Private state
          _invokeQueue: invokeQueue,
          _runBlocks: runBlocks,

          /**
           * @ngdoc property
           * @name angular.Module#requires
           * @propertyOf angular.Module
           * @returns {Array.<string>} List of module names which must be loaded before this module.
           * @description
           * Holds the list of modules which the injector will load before the current module is loaded.
           */
          requires: requires,

          /**
           * @ngdoc property
           * @name angular.Module#name
           * @propertyOf angular.Module
           * @returns {string} Name of the module.
           * @description
           */
          name: name,

          /**
           * @ngdoc method
           * @name angular.Module#provider
           * @methodOf angular.Module
           * @param {string} name service name
           * @param {Function} providerType Construction function for creating new instance of the service.
           * @description
           * See {@link AUTO.$provide#provider $provide.provider()}.
           */
          provider: invokeLater('$provide', 'provider'),

          /**
           * @ngdoc method
           * @name angular.Module#factory
           * @methodOf angular.Module
           * @param {string} name service name
           * @param {Function} providerFunction Function for creating new instance of the service.
           * @description
           * See {@link AUTO.$provide#factory $provide.factory()}.
           */
          factory: invokeLater('$provide', 'factory'),

          /**
           * @ngdoc method
           * @name angular.Module#service
           * @methodOf angular.Module
           * @param {string} name service name
           * @param {Function} constructor A constructor function that will be instantiated.
           * @description
           * See {@link AUTO.$provide#service $provide.service()}.
           */
          service: invokeLater('$provide', 'service'),

          /**
           * @ngdoc method
           * @name angular.Module#value
           * @methodOf angular.Module
           * @param {string} name service name
           * @param {*} object Service instance object.
           * @description
           * See {@link AUTO.$provide#value $provide.value()}.
           */
          value: invokeLater('$provide', 'value'),

          /**
           * @ngdoc method
           * @name angular.Module#constant
           * @methodOf angular.Module
           * @param {string} name constant name
           * @param {*} object Constant value.
           * @description
           * Because the constant are fixed, they get applied before other provide methods.
           * See {@link AUTO.$provide#constant $provide.constant()}.
           */
          constant: invokeLater('$provide', 'constant', 'unshift'),

          /**
           * @ngdoc method
           * @name angular.Module#filter
           * @methodOf angular.Module
           * @param {string} name Filter name.
           * @param {Function} filterFactory Factory function for creating new instance of filter.
           * @description
           * See {@link ng.$filterProvider#register $filterProvider.register()}.
           */
          filter: invokeLater('$filterProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#controller
           * @methodOf angular.Module
           * @param {string} name Controller name.
           * @param {Function} constructor Controller constructor function.
           * @description
           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
           */
          controller: invokeLater('$controllerProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#directive
           * @methodOf angular.Module
           * @param {string} name directive name
           * @param {Function} directiveFactory Factory function for creating new instance of
           * directives.
           * @description
           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
           */
          directive: invokeLater('$compileProvider', 'directive'),

          /**
           * @ngdoc method
           * @name angular.Module#config
           * @methodOf angular.Module
           * @param {Function} configFn Execute this function on module load. Useful for service
           *    configuration.
           * @description
           * Use this method to register work which needs to be performed on module loading.
           */
          config: config,

          /**
           * @ngdoc method
           * @name angular.Module#run
           * @methodOf angular.Module
           * @param {Function} initializationFn Execute this function after injector creation.
           *    Useful for application initialization.
           * @description
           * Use this method to register work which needs to be performed when the injector with
           * with the current module is finished loading.
           */
          run: function(block) {
            runBlocks.push(block);
            return this;
          }
        };

        if (configFn) {
          config(configFn);
        }

        return  moduleInstance;

        /**
         * @param {string} provider
         * @param {string} method
         * @param {String=} insertMethod
         * @returns {angular.Module}
         */
        function invokeLater(provider, method, insertMethod) {
          return function() {
            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
            return moduleInstance;
          }
        }
      });
    };
  });

}
<commit_msg>docs(angular.module): improve angular.Module#run docs<commit_after>'use strict';

/**
 * @ngdoc interface
 * @name angular.Module
 * @description
 *
 * Interface for configuring angular {@link angular.module modules}.
 */

function setupModuleLoader(window) {

  function ensure(obj, name, factory) {
    return obj[name] || (obj[name] = factory());
  }

  return ensure(ensure(window, 'angular', Object), 'module', function() {
    /** @type {Object.<string, angular.Module>} */
    var modules = {};

    /**
     * @ngdoc function
     * @name angular.module
     * @description
     *
     * The `angular.module` is a global place for creating and registering Angular modules. All
     * modules (angular core or 3rd party) that should be available to an application must be
     * registered using this mechanism.
     *
     *
     * # Module
     *
     * A module is a collocation of services, directives, filters, and configure information. Module
     * is used to configure the {@link AUTO.$injector $injector}.
     *
     *

     * // Create a new module
     * var myModule = angular.module('myModule', []);
     *
     * // register a new service
     * myModule.value('appName', 'MyCoolApp');
     *
     * // configure existing services inside initialization blocks.
     * myModule.config(function($locationProvider) {
     *   // Configure existing providers
     *   $locationProvider.hashPrefix('!');
     * });
     *

     *
     * Then you can create an injector and load your modules like this:
     *
     *

     * var injector = angular.injector(['ng', 'MyModule'])
     *

     *
     * However it's more likely that you'll just use
     * {@link ng.directive:ngApp ngApp} or
     * {@link angular.bootstrap} to simplify this process for you.
     *
     * @param {!string} name The name of the module to create or retrieve.
     * @param {Array.<string>=} requires If specified then new module is being created. If unspecified then the
     *        the module is being retrieved for further configuration.
     * @param {Function} configFn Option configuration function for the module. Same as
     *        {@link angular.Module#config Module#config()}.
     * @returns {module} new module with the {@link angular.Module} api.
     */
    return function module(name, requires, configFn) {
      if (requires && modules.hasOwnProperty(name)) {
        modules[name] = null;
      }
      return ensure(modules, name, function() {
        if (!requires) {
          throw Error('No module: ' + name);
        }

        /** @type {!Array.<Array.<*>>} */
        var invokeQueue = [];

        /** @type {!Array.<Function>} */
        var runBlocks = [];

        var config = invokeLater('$injector', 'invoke');

        /** @type {angular.Module} */
        var moduleInstance = {
          // Private state
          _invokeQueue: invokeQueue,
          _runBlocks: runBlocks,

          /**
           * @ngdoc property
           * @name angular.Module#requires
           * @propertyOf angular.Module
           * @returns {Array.<string>} List of module names which must be loaded before this module.
           * @description
           * Holds the list of modules which the injector will load before the current module is loaded.
           */
          requires: requires,

          /**
           * @ngdoc property
           * @name angular.Module#name
           * @propertyOf angular.Module
           * @returns {string} Name of the module.
           * @description
           */
          name: name,

          /**
           * @ngdoc method
           * @name angular.Module#provider
           * @methodOf angular.Module
           * @param {string} name service name
           * @param {Function} providerType Construction function for creating new instance of the service.
           * @description
           * See {@link AUTO.$provide#provider $provide.provider()}.
           */
          provider: invokeLater('$provide', 'provider'),

          /**
           * @ngdoc method
           * @name angular.Module#factory
           * @methodOf angular.Module
           * @param {string} name service name
           * @param {Function} providerFunction Function for creating new instance of the service.
           * @description
           * See {@link AUTO.$provide#factory $provide.factory()}.
           */
          factory: invokeLater('$provide', 'factory'),

          /**
           * @ngdoc method
           * @name angular.Module#service
           * @methodOf angular.Module
           * @param {string} name service name
           * @param {Function} constructor A constructor function that will be instantiated.
           * @description
           * See {@link AUTO.$provide#service $provide.service()}.
           */
          service: invokeLater('$provide', 'service'),

          /**
           * @ngdoc method
           * @name angular.Module#value
           * @methodOf angular.Module
           * @param {string} name service name
           * @param {*} object Service instance object.
           * @description
           * See {@link AUTO.$provide#value $provide.value()}.
           */
          value: invokeLater('$provide', 'value'),

          /**
           * @ngdoc method
           * @name angular.Module#constant
           * @methodOf angular.Module
           * @param {string} name constant name
           * @param {*} object Constant value.
           * @description
           * Because the constant are fixed, they get applied before other provide methods.
           * See {@link AUTO.$provide#constant $provide.constant()}.
           */
          constant: invokeLater('$provide', 'constant', 'unshift'),

          /**
           * @ngdoc method
           * @name angular.Module#filter
           * @methodOf angular.Module
           * @param {string} name Filter name.
           * @param {Function} filterFactory Factory function for creating new instance of filter.
           * @description
           * See {@link ng.$filterProvider#register $filterProvider.register()}.
           */
          filter: invokeLater('$filterProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#controller
           * @methodOf angular.Module
           * @param {string} name Controller name.
           * @param {Function} constructor Controller constructor function.
           * @description
           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
           */
          controller: invokeLater('$controllerProvider', 'register'),

          /**
           * @ngdoc method
           * @name angular.Module#directive
           * @methodOf angular.Module
           * @param {string} name directive name
           * @param {Function} directiveFactory Factory function for creating new instance of
           * directives.
           * @description
           * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
           */
          directive: invokeLater('$compileProvider', 'directive'),

          /**
           * @ngdoc method
           * @name angular.Module#config
           * @methodOf angular.Module
           * @param {Function} configFn Execute this function on module load. Useful for service
           *    configuration.
           * @description
           * Use this method to register work which needs to be performed on module loading.
           */
          config: config,

          /**
           * @ngdoc method
           * @name angular.Module#run
           * @methodOf angular.Module
           * @param {Function} initializationFn Execute this function after injector creation.
           *    Useful for application initialization.
           * @description
           * Use this method to register work which should be performed when the injector is done
           * loading all modules.
           */
          run: function(block) {
            runBlocks.push(block);
            return this;
          }
        };

        if (configFn) {
          config(configFn);
        }

        return  moduleInstance;

        /**
         * @param {string} provider
         * @param {string} method
         * @param {String=} insertMethod
         * @returns {angular.Module}
         */
        function invokeLater(provider, method, insertMethod) {
          return function() {
            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
            return moduleInstance;
          }
        }
      });
    };
  });

}
<|endoftext|>


<commit_before>import express from 'express';
import bodyParser from 'body-parser';
import winston from 'winston';
import session from 'express-session';
import router from './routes/index';

const port = process.env.PORT || 8081;
const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({ secret: 'secret', resave: false, saveUninitialized: true }));

app.use(router.user);
app.use(router.recipe);
app.use(router.review);
app.use(router.favorite);
app.use(router.vote);

app.listen(port, () => winston.info('We up!'));

export default app;
<commit_msg>create testing route for deployment<commit_after>import express from 'express';
import bodyParser from 'body-parser';
import winston from 'winston';
import router from './routes/index';

const port = process.env.PORT || 8081;
const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.get('/', (req, res) => {
  res.send('its working');
});
app.use(router.user);
app.use(router.recipe);
app.use(router.review);
app.use(router.favorite);
app.use(router.vote);

app.listen(port, () => winston.info('We up!'));

export default app;
<|endoftext|>


<commit_before>function getPasteEvent() {
    var el = document.createElement('input'),
        name = 'onpaste';
    el.setAttribute(name, '');
    return (typeof el[name] === 'function')?'paste':'input';
}

var pasteEventName = getPasteEvent() + ".mask",
	ua = navigator.userAgent,
	iPhone = /iphone/i.test(ua),
	chrome = /chrome/i.test(ua),
	android=/android/i.test(ua),
	caretTimeoutId;

$.mask = {
	//Predefined character definitions
	definitions: {
		'9': "[0-9]",
		'a': "[A-Za-z]",
		'*': "[A-Za-z0-9]"
	},
	dataName: "rawMaskFn",
	placeholder: '_'
};

$.fn.extend({
	//Helper Function for Caret positioning
	caret: function(begin, end) {
		var range;

		if (this.length === 0 || this.is(":hidden")) {
			return;
		}

		if (typeof begin == 'number') {
			end = (typeof end === 'number') ? end : begin;
			return this.each(function() {
				if (this.setSelectionRange) {
					this.setSelectionRange(begin, end);
				} else if (this.createTextRange) {
					range = this.createTextRange();
					range.collapse(true);
					range.moveEnd('character', end);
					range.moveStart('character', begin);
					range.select();
				}
			});
		} else {
			if (this[0].setSelectionRange) {
				begin = this[0].selectionStart;
				end = this[0].selectionEnd;
			} else if (document.selection && document.selection.createRange) {
				range = document.selection.createRange();
				begin = 0 - range.duplicate().moveStart('character', -100000);
				end = begin + range.text.length;
			}
			return { begin: begin, end: end };
		}
	},
	unmask: function() {
		return this.trigger("unmask");
	},
	mask: function(mask, settings) {
		var input,
			defs,
			tests,
			partialPosition,
			firstNonMaskPos,
			len;

		if (!mask && this.length > 0) {
			input = $(this[0]);
			return input.data($.mask.dataName)();
		}
		settings = $.extend({
			placeholder: $.mask.placeholder, // Load default placeholder
			completed: null
		}, settings);

		defs = $.mask.definitions;
		tests = [];
		partialPosition = len = mask.length;
		firstNonMaskPos = null;

		$.each(mask.split(""), function(i, c) {
			if (c == '?') {
				len--;
				partialPosition = i;
			} else if (defs[c]) {
				tests.push(new RegExp(defs[c]));
				if (firstNonMaskPos === null) {
					firstNonMaskPos = tests.length - 1;
				}
			} else {
				tests.push(null);
			}
		});

		return this.trigger("unmask").each(function() {
			var input = $(this),
				buffer = $.map(
				mask.split(""),
				function(c, i) {
					if (c != '?') {
						return defs[c] ? settings.placeholder : c;
					}
				}),
				focusText = input.val();

			function seekNext(pos) {
				while (++pos < len && !tests[pos]);
				return pos;
			}

			function seekPrev(pos) {
				while (--pos >= 0 && !tests[pos]);
				return pos;
			}

			function shiftL(begin,end) {
				var i,
					j;

				if (begin<0) {
					return;
				}

				for (i = begin, j = seekNext(end); i < len; i++) {
					if (tests[i]) {
						if (j < len && tests[i].test(buffer[j])) {
							buffer[i] = buffer[j];
							buffer[j] = settings.placeholder;
						} else {
							break;
						}

						j = seekNext(j);
					}
				}
				writeBuffer();
				input.caret(Math.max(firstNonMaskPos, begin));
			}

			function shiftR(pos) {
				var i,
					c,
					j,
					t;

				for (i = pos, c = settings.placeholder; i < len; i++) {
					if (tests[i]) {
						j = seekNext(i);
						t = buffer[i];
						buffer[i] = c;
						if (j < len && tests[j].test(t)) {
							c = t;
						} else {
							break;
						}
					}
				}
			}

			function keydownEvent(e) {
				var k = e.which,
					pos,
					begin,
					end;

				//backspace, delete, and escape get special treatment
				if (k === 8 || k === 46 || (iPhone && k === 127)) {
					pos = input.caret();
					begin = pos.begin;
					end = pos.end;

					if (end - begin === 0) {
						begin=k!==46?seekPrev(begin):(end=seekNext(begin-1));
						end=k===46?seekNext(end):end;
					}
					clearBuffer(begin, end);
					shiftL(begin, end - 1);

					e.preventDefault();
				} else if (k == 27) {//escape
					input.val(focusText);
					input.caret(0, checkVal());
					e.preventDefault();
				}
			}

			function keypressEvent(e) {
				var k = e.which,
					pos = input.caret(),
					p,
					c,
					next;

                    if (k == 0) {
                        // unable to detect key pressed. Grab it from pos and adjust
                        // this is a failsafe for mobile chrome
                        // which can't detect keypress events
                        // reliably
                        if (pos.begin >= len) {
                            input.val(input.val().substr(0, len));
                            e.preventDefault();
                            return false;
                        }
                        if (pos.begin == pos.end) {
                            k = input.val().charCodeAt(pos.begin - 1);
                            pos.begin--;
                            pos.end--;
                        }
                    }
				if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore
					return;
				} else if (k) {
					if (pos.end - pos.begin !== 0){
						clearBuffer(pos.begin, pos.end);
						shiftL(pos.begin, pos.end-1);
					}

					p = seekNext(pos.begin - 1);
					if (p < len) {
						c = String.fromCharCode(k);
						if (tests[p].test(c)) {
							shiftR(p);

							buffer[p] = c;
							writeBuffer();
							next = seekNext(p);

							if(android){
								setTimeout($.proxy($.fn.caret,input,next),0);
							}else{
								input.caret(next);
							}

							if (settings.completed && next >= len) {
								settings.completed.call(input);
							}
						}
					}
					e.preventDefault();
				}
			}

			function clearBuffer(start, end) {
				var i;
				for (i = start; i < end && i < len; i++) {
					if (tests[i]) {
						buffer[i] = settings.placeholder;
					}
				}
			}

			function writeBuffer() { input.val(buffer.join('')); }

			function checkVal(allow) {
				//try to place characters where they belong
				var test = input.val(),
					lastMatch = -1,
					i,
					c,
					pos;

				for (i = 0, pos = 0; i < len; i++) {
					if (tests[i]) {
						buffer[i] = settings.placeholder;
						while (pos++ < test.length) {
							c = test.charAt(pos - 1);
							if (tests[i].test(c)) {
								buffer[i] = c;
								lastMatch = i;
								break;
							}
						}
						if (pos > test.length) {
							break;
						}
					} else if (buffer[i] === test.charAt(pos) && i !== partialPosition) {
						pos++;
						lastMatch = i;
					}
				}
				if (allow) {
					writeBuffer();
				} else if (lastMatch + 1 < partialPosition) {
					input.val("");
					clearBuffer(0, len);
				} else {
					writeBuffer();
					input.val(input.val().substring(0, lastMatch + 1));
				}
				return (partialPosition ? i : firstNonMaskPos);
			}

			input.data($.mask.dataName,function(){
				return $.map(buffer, function(c, i) {
					return tests[i]&&c!=settings.placeholder ? c : null;
				}).join('');
			});

			if (!input.attr("readonly"))
				input
				.one("unmask", function() {
					input
						.unbind(".mask")
						.removeData($.mask.dataName);
				})
				.bind("focus.mask", function() {
					clearTimeout(caretTimeoutId);
					var pos;

					focusText = input.val();
					pos = checkVal();

					caretTimeoutId = setTimeout(function(){
						writeBuffer();
						if (pos == mask.length) {
							input.caret(0, pos);
						} else {
							input.caret(pos);
						}
					}, 10);
				})
				.bind("blur.mask", function() {
					checkVal();
					if (input.val() != focusText)
						input.change();
				})
				.bind("keydown.mask", keydownEvent)
				.bind("keypress.mask", keypressEvent)
				.bind(pasteEventName, function() {
					setTimeout(function() {
						var pos=checkVal(true);
						input.caret(pos);
						if (settings.completed && pos == input.val().length)
							settings.completed.call(input);
					}, 0);
				});
                if (chrome) {
                    input.bind("keyup.mask", keypressEvent);
                }
			checkVal(); //Perform initial check for existing values
		});
	}
});
<commit_msg>Add android to if statement<commit_after>function getPasteEvent() {
    var el = document.createElement('input'),
        name = 'onpaste';
    el.setAttribute(name, '');
    return (typeof el[name] === 'function')?'paste':'input';
}

var pasteEventName = getPasteEvent() + ".mask",
	ua = navigator.userAgent,
	iPhone = /iphone/i.test(ua),
	chrome = /chrome/i.test(ua),
	android=/android/i.test(ua),
	caretTimeoutId;

$.mask = {
	//Predefined character definitions
	definitions: {
		'9': "[0-9]",
		'a': "[A-Za-z]",
		'*': "[A-Za-z0-9]"
	},
	dataName: "rawMaskFn",
	placeholder: '_'
};

$.fn.extend({
	//Helper Function for Caret positioning
	caret: function(begin, end) {
		var range;

		if (this.length === 0 || this.is(":hidden")) {
			return;
		}

		if (typeof begin == 'number') {
			end = (typeof end === 'number') ? end : begin;
			return this.each(function() {
				if (this.setSelectionRange) {
					this.setSelectionRange(begin, end);
				} else if (this.createTextRange) {
					range = this.createTextRange();
					range.collapse(true);
					range.moveEnd('character', end);
					range.moveStart('character', begin);
					range.select();
				}
			});
		} else {
			if (this[0].setSelectionRange) {
				begin = this[0].selectionStart;
				end = this[0].selectionEnd;
			} else if (document.selection && document.selection.createRange) {
				range = document.selection.createRange();
				begin = 0 - range.duplicate().moveStart('character', -100000);
				end = begin + range.text.length;
			}
			return { begin: begin, end: end };
		}
	},
	unmask: function() {
		return this.trigger("unmask");
	},
	mask: function(mask, settings) {
		var input,
			defs,
			tests,
			partialPosition,
			firstNonMaskPos,
			len;

		if (!mask && this.length > 0) {
			input = $(this[0]);
			return input.data($.mask.dataName)();
		}
		settings = $.extend({
			placeholder: $.mask.placeholder, // Load default placeholder
			completed: null
		}, settings);

		defs = $.mask.definitions;
		tests = [];
		partialPosition = len = mask.length;
		firstNonMaskPos = null;

		$.each(mask.split(""), function(i, c) {
			if (c == '?') {
				len--;
				partialPosition = i;
			} else if (defs[c]) {
				tests.push(new RegExp(defs[c]));
				if (firstNonMaskPos === null) {
					firstNonMaskPos = tests.length - 1;
				}
			} else {
				tests.push(null);
			}
		});

		return this.trigger("unmask").each(function() {
			var input = $(this),
				buffer = $.map(
				mask.split(""),
				function(c, i) {
					if (c != '?') {
						return defs[c] ? settings.placeholder : c;
					}
				}),
				focusText = input.val();

			function seekNext(pos) {
				while (++pos < len && !tests[pos]);
				return pos;
			}

			function seekPrev(pos) {
				while (--pos >= 0 && !tests[pos]);
				return pos;
			}

			function shiftL(begin,end) {
				var i,
					j;

				if (begin<0) {
					return;
				}

				for (i = begin, j = seekNext(end); i < len; i++) {
					if (tests[i]) {
						if (j < len && tests[i].test(buffer[j])) {
							buffer[i] = buffer[j];
							buffer[j] = settings.placeholder;
						} else {
							break;
						}

						j = seekNext(j);
					}
				}
				writeBuffer();
				input.caret(Math.max(firstNonMaskPos, begin));
			}

			function shiftR(pos) {
				var i,
					c,
					j,
					t;

				for (i = pos, c = settings.placeholder; i < len; i++) {
					if (tests[i]) {
						j = seekNext(i);
						t = buffer[i];
						buffer[i] = c;
						if (j < len && tests[j].test(t)) {
							c = t;
						} else {
							break;
						}
					}
				}
			}

			function keydownEvent(e) {
				var k = e.which,
					pos,
					begin,
					end;

				//backspace, delete, and escape get special treatment
				if (k === 8 || k === 46 || (iPhone && k === 127)) {
					pos = input.caret();
					begin = pos.begin;
					end = pos.end;

					if (end - begin === 0) {
						begin=k!==46?seekPrev(begin):(end=seekNext(begin-1));
						end=k===46?seekNext(end):end;
					}
					clearBuffer(begin, end);
					shiftL(begin, end - 1);

					e.preventDefault();
				} else if (k == 27) {//escape
					input.val(focusText);
					input.caret(0, checkVal());
					e.preventDefault();
				}
			}

			function keypressEvent(e) {
				var k = e.which,
					pos = input.caret(),
					p,
					c,
					next;

                    if (k == 0) {
                        // unable to detect key pressed. Grab it from pos and adjust
                        // this is a failsafe for mobile chrome
                        // which can't detect keypress events
                        // reliably
                        if (pos.begin >= len) {
                            input.val(input.val().substr(0, len));
                            e.preventDefault();
                            return false;
                        }
                        if (pos.begin == pos.end) {
                            k = input.val().charCodeAt(pos.begin - 1);
                            pos.begin--;
                            pos.end--;
                        }
                    }
				if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore
					return;
				} else if (k) {
					if (pos.end - pos.begin !== 0){
						clearBuffer(pos.begin, pos.end);
						shiftL(pos.begin, pos.end-1);
					}

					p = seekNext(pos.begin - 1);
					if (p < len) {
						c = String.fromCharCode(k);
						if (tests[p].test(c)) {
							shiftR(p);

							buffer[p] = c;
							writeBuffer();
							next = seekNext(p);

							if(android){
								setTimeout($.proxy($.fn.caret,input,next),0);
							}else{
								input.caret(next);
							}

							if (settings.completed && next >= len) {
								settings.completed.call(input);
							}
						}
					}
					e.preventDefault();
				}
			}

			function clearBuffer(start, end) {
				var i;
				for (i = start; i < end && i < len; i++) {
					if (tests[i]) {
						buffer[i] = settings.placeholder;
					}
				}
			}

			function writeBuffer() { input.val(buffer.join('')); }

			function checkVal(allow) {
				//try to place characters where they belong
				var test = input.val(),
					lastMatch = -1,
					i,
					c,
					pos;

				for (i = 0, pos = 0; i < len; i++) {
					if (tests[i]) {
						buffer[i] = settings.placeholder;
						while (pos++ < test.length) {
							c = test.charAt(pos - 1);
							if (tests[i].test(c)) {
								buffer[i] = c;
								lastMatch = i;
								break;
							}
						}
						if (pos > test.length) {
							break;
						}
					} else if (buffer[i] === test.charAt(pos) && i !== partialPosition) {
						pos++;
						lastMatch = i;
					}
				}
				if (allow) {
					writeBuffer();
				} else if (lastMatch + 1 < partialPosition) {
					input.val("");
					clearBuffer(0, len);
				} else {
					writeBuffer();
					input.val(input.val().substring(0, lastMatch + 1));
				}
				return (partialPosition ? i : firstNonMaskPos);
			}

			input.data($.mask.dataName,function(){
				return $.map(buffer, function(c, i) {
					return tests[i]&&c!=settings.placeholder ? c : null;
				}).join('');
			});

			if (!input.attr("readonly"))
				input
				.one("unmask", function() {
					input
						.unbind(".mask")
						.removeData($.mask.dataName);
				})
				.bind("focus.mask", function() {
					clearTimeout(caretTimeoutId);
					var pos;

					focusText = input.val();
					pos = checkVal();

					caretTimeoutId = setTimeout(function(){
						writeBuffer();
						if (pos == mask.length) {
							input.caret(0, pos);
						} else {
							input.caret(pos);
						}
					}, 10);
				})
				.bind("blur.mask", function() {
					checkVal();
					if (input.val() != focusText)
						input.change();
				})
				.bind("keydown.mask", keydownEvent)
				.bind("keypress.mask", keypressEvent)
				.bind(pasteEventName, function() {
					setTimeout(function() {
						var pos=checkVal(true);
						input.caret(pos);
						if (settings.completed && pos == input.val().length)
							settings.completed.call(input);
					}, 0);
				});
                if (chrome && android) {
                    input.bind("keyup.mask", keypressEvent);
                }
			checkVal(); //Perform initial check for existing values
		});
	}
});
<|endoftext|>


<commit_before>angular
    .module('ngSharepoint')
    .factory('CamlBuilder', function(CamlTag) {
        var CamlBuilder = function() {
            this.caml = [];
        };
        CamlBuilder.prototype.push = function(tag, attr, value) {
            var camlTag;
            if (tag instanceof CamlTag) {
                camlTag = tag;
            }else {
                camlTag = new CamlTag(tag, attr, value);
            }
            this.caml.push(camlTag);
            return camlTag;
        };
        CamlBuilder.prototype.findByName = function(name) {
            var result = [];
            this.caml.forEach(function(tag) {
                if (tag.name === name) {
                    result.push(tag);
                }
            });
            return result;
        };
        CamlBuilder.prototype.isEmpty = function() {
            if (this.caml.length === 0) {
                return true;
            }else if (this.caml.length === 1) {
                var tag = this.caml[0];
                if (angular.isDefined(tag.value)) {
                    return false;
                }
                if (angular.isDefined(tag.caml) &&
                    angular.isArray(tag.caml) &&
                    tag.caml.length > 0) {
                    return false;
                }
                if (angular.isDefined(tag.attr) &&
                    angular.isObject(tag.attr) &&
                    Object.getOwnPropertyNames(tag.attr).length > 0) {
                    return false;
                }
                return true;
            }else {
                return false;
            }
        };
        CamlBuilder.prototype.build = function() {
            for (var i = 0; i < this.caml.length; i++) {
                this.caml[i] = this.caml[i].build();
            }
            return this.caml.join('');
        };
        CamlBuilder.prototype.buildFromJson = function(json) {
            var root = this.findByName('View');
            if (root.length === 0) {
                root = this.push('View');
            }else {
                root = root[0];
            }
            if (angular.isDefined(json.columns)) {
                this.__buildViewFields(json.columns, root);
            }
            if (angular.isDefined(json.query)) {
                this.__buildQuery(json.query, root);
            }
            if (angular.isDefined(json.limit)) {
                this.__buildLimit(json.limit, root);
            }
            if (angular.isDefined(json.order) && json.order.length > 0) {
                this.__buildOrder(json.order, root);
            }
        };
        CamlBuilder.prototype.__buildViewFields = function(columns, root) {
            var viewFields = root.push('ViewFields');
            columns.forEach(function(col) {
                viewFields.push('FieldRef', {Name: col});
            });
        };
        CamlBuilder.prototype.__buildQuery = function(query, root) {
            var builder = this;
            if (root.name === 'View') {
                root = root.push('Query').push('Where');
            }
            if (angular.isDefined(query.concat)) {
                var concatenator;
                if (query.concat === 'and') {
                    concatenator = root.push('And');
                }else if (query.concat === 'or') {
                    concatenator = root.push('Or');
                }else {
                    throw 'Invalid Query';
                }
                query.queries.forEach(function(sub) {
                    builder.__buildQuery(sub, concatenator);
                });
            }else if (angular.isDefined(query.comparator)) {
                query.comparator = query.comparator.toLowerCase();
                var comparator;
                switch (query.comparator) {
                    case 'beginswith':
                        comparator = root.push('BeginsWith');
                        break;
                    case 'contains':
                        comparator = root.push('Contains');
                        break;
                    case 'daterangesoverlap':
                        comparator = root.push('DateRangesOverlap');
                        break;
                    case '==':
                    case 'eq':
                    case 'equals':
                        comparator = root.push('Eq');
                        break;
                    case '>=':
                    case 'geq':
                    case 'greaterequals':
                        comparator = root.push('Geq');
                        break;
                    case '>':
                    case 'gt':
                    case 'greater':
                        comparator = root.push('Gt');
                        break;
                    case 'in':
                        comparator = root.push('In');
                        break;
                    case 'includes':
                        comparator = root.push('Includes');
                        break;
                    case 'isnotnull':
                        comparator = root.push('IsNotNull');
                        break;
                    case 'isnull':
                        comparator = root.push('IsNull');
                        break;
                    case '<=':
                    case 'leq':
                    case 'lessequals':
                        comparator = root.push('Leq');
                        break;
                    case '<':
                    case 'lt':
                    case 'less':
                        comparator = root.push('Lt');
                        break;
                    case '!=':
                    case 'neq':
                    case 'notequals':
                        comparator = root.push('Neq');
                        break;
                    case 'notincludes':
                        comparator = root.push('NotIncludes');
                        break;
                }
                comparator.push('FieldRef', {Name: query.column});
                if (angular.isDefined(query.value)) {
                    comparator.push('Value', {}, query.value);
                }
            }else {
                throw 'Invalid Query';
            }
        };
        CamlBuilder.prototype.__buildLimit = function(limit, root) {
            root.push('RowLimit', {}, limit);
        };
        CamlBuilder.prototype.__buildOrder = function(order, root) {
            var query = root.findByName('Query');
            if (query.length === 0) {
                query = root.push('Query');
            }else {
                query = query[0];
            }
            var orderTag = query.push('OrderBy');
            order.forEach(function(o) {
                if (angular.isDefined(o.column)) {
                    var asc = true;
                    if (angular.isDefined(o.asc)) {
                        asc = o.asc;
                    }
                    asc = asc.toString().toUpperCase();
                    orderTag.push('FieldRef', {Name: o.column, Ascending: asc});
                }else {
                    throw 'Invalid Order Query';
                }
            });
        };
        return (CamlBuilder);
    });
<commit_msg>Check for a valid object before building a caml query<commit_after>angular
    .module('ngSharepoint')
    .factory('CamlBuilder', function(CamlTag) {
        var CamlBuilder = function() {
            this.caml = [];
        };
        CamlBuilder.prototype.push = function(tag, attr, value) {
            var camlTag;
            if (tag instanceof CamlTag) {
                camlTag = tag;
            }else {
                camlTag = new CamlTag(tag, attr, value);
            }
            this.caml.push(camlTag);
            return camlTag;
        };
        CamlBuilder.prototype.findByName = function(name) {
            var result = [];
            this.caml.forEach(function(tag) {
                if (tag.name === name) {
                    result.push(tag);
                }
            });
            return result;
        };
        CamlBuilder.prototype.isEmpty = function() {
            if (this.caml.length === 0) {
                return true;
            }else if (this.caml.length === 1) {
                var tag = this.caml[0];
                if (angular.isDefined(tag.value)) {
                    return false;
                }
                if (angular.isDefined(tag.caml) &&
                    angular.isArray(tag.caml) &&
                    tag.caml.length > 0) {
                    return false;
                }
                if (angular.isDefined(tag.attr) &&
                    angular.isObject(tag.attr) &&
                    Object.getOwnPropertyNames(tag.attr).length > 0) {
                    return false;
                }
                return true;
            }else {
                return false;
            }
        };
        CamlBuilder.prototype.build = function() {
            for (var i = 0; i < this.caml.length; i++) {
                this.caml[i] = this.caml[i].build();
            }
            return this.caml.join('');
        };
        CamlBuilder.prototype.buildFromJson = function(json) {
            if (angular.isDefined(json) && angular.isObject(json)) {
                var root = this.findByName('View');
                if (root.length === 0) {
                    root = this.push('View');
                }else {
                    root = root[0];
                }
                if (angular.isDefined(json.columns)) {
                    this.__buildViewFields(json.columns, root);
                }
                if (angular.isDefined(json.query)) {
                    this.__buildQuery(json.query, root);
                }
                if (angular.isDefined(json.limit)) {
                    this.__buildLimit(json.limit, root);
                }
                if (angular.isDefined(json.order) && json.order.length > 0) {
                    this.__buildOrder(json.order, root);
                }
            }
        };
        CamlBuilder.prototype.__buildViewFields = function(columns, root) {
            var viewFields = root.push('ViewFields');
            columns.forEach(function(col) {
                viewFields.push('FieldRef', {Name: col});
            });
        };
        CamlBuilder.prototype.__buildQuery = function(query, root) {
            var builder = this;
            if (root.name === 'View') {
                root = root.push('Query').push('Where');
            }
            if (angular.isDefined(query.concat)) {
                var concatenator;
                if (query.concat === 'and') {
                    concatenator = root.push('And');
                }else if (query.concat === 'or') {
                    concatenator = root.push('Or');
                }else {
                    throw 'Invalid Query';
                }
                query.queries.forEach(function(sub) {
                    builder.__buildQuery(sub, concatenator);
                });
            }else if (angular.isDefined(query.comparator)) {
                query.comparator = query.comparator.toLowerCase();
                var comparator;
                switch (query.comparator) {
                    case 'beginswith':
                        comparator = root.push('BeginsWith');
                        break;
                    case 'contains':
                        comparator = root.push('Contains');
                        break;
                    case 'daterangesoverlap':
                        comparator = root.push('DateRangesOverlap');
                        break;
                    case '==':
                    case 'eq':
                    case 'equals':
                        comparator = root.push('Eq');
                        break;
                    case '>=':
                    case 'geq':
                    case 'greaterequals':
                        comparator = root.push('Geq');
                        break;
                    case '>':
                    case 'gt':
                    case 'greater':
                        comparator = root.push('Gt');
                        break;
                    case 'in':
                        comparator = root.push('In');
                        break;
                    case 'includes':
                        comparator = root.push('Includes');
                        break;
                    case 'isnotnull':
                        comparator = root.push('IsNotNull');
                        break;
                    case 'isnull':
                        comparator = root.push('IsNull');
                        break;
                    case '<=':
                    case 'leq':
                    case 'lessequals':
                        comparator = root.push('Leq');
                        break;
                    case '<':
                    case 'lt':
                    case 'less':
                        comparator = root.push('Lt');
                        break;
                    case '!=':
                    case 'neq':
                    case 'notequals':
                        comparator = root.push('Neq');
                        break;
                    case 'notincludes':
                        comparator = root.push('NotIncludes');
                        break;
                }
                comparator.push('FieldRef', {Name: query.column});
                if (angular.isDefined(query.value)) {
                    comparator.push('Value', {}, query.value);
                }
            }else {
                throw 'Invalid Query';
            }
        };
        CamlBuilder.prototype.__buildLimit = function(limit, root) {
            root.push('RowLimit', {}, limit);
        };
        CamlBuilder.prototype.__buildOrder = function(order, root) {
            var query = root.findByName('Query');
            if (query.length === 0) {
                query = root.push('Query');
            }else {
                query = query[0];
            }
            var orderTag = query.push('OrderBy');
            order.forEach(function(o) {
                if (angular.isDefined(o.column)) {
                    var asc = true;
                    if (angular.isDefined(o.asc)) {
                        asc = o.asc;
                    }
                    asc = asc.toString().toUpperCase();
                    orderTag.push('FieldRef', {Name: o.column, Ascending: asc});
                }else {
                    throw 'Invalid Order Query';
                }
            });
        };
        return (CamlBuilder);
    });
<|endoftext|>


<commit_before>/*eslint-env browser */
/*global require: false, module: false */
'use strict';

var _ = require('./underscore_ext');
var Rx = require('rx');
var React = require('react');
var Legend = require('./views/Legend');
var {deepPureRenderMixin, rxEventsMixin} = require('./react-utils');
var widgets = require('./columnWidgets');
var util = require('./util');
var CanvasDrawing = require('./CanvasDrawing');
var {features, chromFromAlt, posFromAlt, structuralVariantClass} = require('./models/mutationVector');
var {drawMutations, radius, labelFont, toYPx} = require('./drawMutations');

// Since we don't set module.exports, but instead register ourselves
// with columWidgets, react-hot-loader can't handle the updates automatically.
// Accept hot loading here.
if (module.hot) {
	module.hot.accept();
	module.hot.accept('./models/mutationVector', () => {
		features = require('./models/mutationVector');
	});
}

// Since there are multiple components in the file we have to use makeHot
// explicitly.
function hotOrNot(component) {
	return module.makeHot ? module.makeHot(component) : component;
}

function drawLegend({column}) {
	var dataSubType = column.datasetMetadata[0].dataSubType,
		feature = _.getIn(column, ['sFeature']),
		{colors, labels, align} = features[feature].legend(dataSubType);

	return (
		<Legend
			colors={['rgb(255,255,255)', ...colors]}
			labels={['no variant', ...labels]}
			align={align}
			ellipsis='' />
	);
}

function closestNode(nodes, pixPerRow, index, count, x, y) {
	var cutoffX = radius,
		end = index + count,
		yPx = toYPx(pixPerRow, index),
		nearBy = _.filter(nodes, n => {
			if (!( n.y >= index && n.y < end &&
				(x > n.xStart - cutoffX) && (x < n.xEnd + cutoffX))) {
				return false;
			}
			var transformed = (pixPerRow > labelFont) && n.yTransformed,
				cutoffY = transformed ? n.svHeight / 2 :  pixPerRow / 2 ;
			return Math.abs(y - ( transformed ? n.yTransformed : yPx(n.y))) < cutoffY;
		});
	return nearBy.length > 0 ? _.min(nearBy, n => Math.abs(x - (n.xStart + n.xEnd) / 2.0)) : undefined;
}

function formatAf(af) {
	return (af === 'NA' || af === '' || af == null) ? null :
		Math.round(af * 100) + '%';
}

var fmtIf = (x, fmt, d = '' ) => x ? fmt(x) : d;
var dropNulls = rows => rows.map(row => row.filter(col => col != null)) // drop empty cols
	.filter(row => row.length > 0); // drop empty rows
var gbURL =  (assembly, pos) => `http://genome.ucsc.edu/cgi-bin/hgTracks?db=${encodeURIComponent(assembly)}&position=${encodeURIComponent(pos)}`;

function sampleTooltip(sampleFormat, data, gene, assembly) {
	var dnaVaf = data.dna_vaf == null ? null : ['labelValue',  'DNA variant allele freq', formatAf(data.dna_vaf)],
		rnaVaf = data.rna_vaf == null ? null : ['labelValue',  'RNA variant allele freq', formatAf(data.rna_vaf)],
		ref = data.reference && ['value', `${data.reference} to `],
		altPos = data.alt && structuralVariantClass(data.alt) &&
			`chr${chromFromAlt(data.alt)}:${posFromAlt(data.alt)}-${posFromAlt(data.alt)}`,
		alt = data.alt && (structuralVariantClass(data.alt) ?
							['url', `${data.alt}`, gbURL(assembly, altPos)] :
							['value', `${data.alt}`]),
		pos = data && `${data.chr}:${util.addCommas(data.start)}-${util.addCommas(data.end)}`,
		posDisplay = data && (data.start === data.end) ? `${data.chr}:${util.addCommas(data.start)}` : pos,
		posURL = ['url',  `${assembly} ${posDisplay}`, gbURL(assembly, pos)],
		effect = ['value', fmtIf(data.effect, x => `${x}, `) + //eslint-disable-line comma-spacing
					gene +
					fmtIf(data.amino_acid, x => ` (${x})`) +
					fmtIf(data.altGene, x => ` connect to ${x} `)
					];
	return {
		rows: dropNulls([
			[effect],
			[posURL, ref, alt],
			[dnaVaf],
			[rnaVaf]
		]),
		sampleID: sampleFormat(data.sample)
	};
}

function makeRow(fields, sampleGroup, row) {
	let fieldValue;
	if (_.isArray(sampleGroup) && sampleGroup.length === 0) {
		fieldValue = 'no variant';
	}
	if (_.isEmpty(sampleGroup)) {
		sampleGroup = [row];
	}
	return _.flatmap(sampleGroup, row =>
		_.map(fields, f => (row && row[f]) || fieldValue));
}

function tooltip(nodes, samples, sampleFormat, {height, count, index}, gene, assembly, ev) {
	var {x, y} = util.eventOffset(ev),
		pixPerRow = height / count,
		yIndex = Math.round((y - pixPerRow / 2) / pixPerRow + index),
		node = closestNode(nodes, pixPerRow, index, count, x, y);

	return node ?
		sampleTooltip(sampleFormat, node.data, gene, assembly) :
		{sampleID: sampleFormat(samples[yIndex])};
}

function getRowFields(rows, sampleGroups) {
	if (_.isEmpty(sampleGroups)) {
		return []; // When no samples exist
	} else if (!_.isEmpty(rows)) {
		return _.keys(rows[0]); // When samples have mutation(s)
	} else {
		return ['sample', 'result']; // default fields for mutation-less columns
	}
}

function formatSamples(sampleFormat, rows) {
	return _.map(rows, r => _.updateIn(r, ['sample'], sampleFormat));
}

var MutationColumn = hotOrNot(React.createClass({
	mixins: [rxEventsMixin, deepPureRenderMixin],
	componentWillMount: function () {
		this.events('mouseout', 'mousemove', 'mouseover');

		// Compute tooltip events from mouse events.
		this.ttevents = this.ev.mouseover
			.filter(ev => util.hasClass(ev.currentTarget, 'Tooltip-target'))
			.selectMany(() => {
				return this.ev.mousemove
					.takeUntil(this.ev.mouseout)
					.map(ev => ({
						data: this.tooltip(ev),
						open: true,
						point: {x: ev.clientX, y: ev.clientY}
					})) // look up current data
					.concat(Rx.Observable.return({open: false}));
			}).subscribe(this.props.tooltip);
	},
	componentWillUnmount: function () {
		this.ttevents.dispose();
	},
	download: function() {
		let {data: {req: {rows}}, samples, index, sampleFormat} = this.props,
			groupedSamples = _.getIn(index, ['bySample']) || [],
			rowFields = getRowFields(rows, groupedSamples),
			allRows = _.map(samples, (sId) => {
				let alternateRow = {sample: sampleFormat(sId)}; // only used for mutation-less samples
				return makeRow(rowFields, formatSamples(sampleFormat, groupedSamples[sId]),
					alternateRow);
			});
		return [rowFields, allRows];
	},
	tooltip: function (ev) {
		var {column: {nodes, fields, assembly}, samples, sampleFormat, zoom} = this.props;
		return tooltip(nodes, samples, sampleFormat, zoom, fields[0], assembly, ev);
	},
	render: function () {
		var {column, samples, zoom, data, index} = this.props,
			feature = _.getIn(column, ['sFeature']);

		// XXX Make plot a child instead of a prop? There's also legend.
		return (
			<CanvasDrawing
					ref='plot'
					draw={drawMutations}
					wrapperProps={{
						className: 'Tooltip-target',
						onMouseMove: this.ev.mousemove,
						onMouseOut: this.ev.mouseout,
						onMouseOver: this.ev.mouseover,
						onClick: this.props.onClick
					}}
					feature={feature}
					nodes={column.nodes}
					strand={column.strand}
					width={column.width}
					data={data}
					index={index}
					samples={samples}
					xzoom={column.zoom}
					zoom={zoom}/>);
	}
}));

var getColumn = props => <MutationColumn {...props} />;
widgets.column.add('mutation', getColumn);

widgets.legend.add('mutation', drawLegend);
<commit_msg>fix bug: in old bookmark and in the icgc chrome plugin generated "state", there is no datasetMetadata stored in the "column", but code expect datasetMetadata is there, which triggers the old bookmarks and, but code expect datasetMetadata is there, which triggers the old bookmarks and  chrome plugin generated states not be able to be loaded in the current browser. Fixed the bug<commit_after>/*eslint-env browser */
/*global require: false, module: false */
'use strict';

var _ = require('./underscore_ext');
var Rx = require('rx');
var React = require('react');
var Legend = require('./views/Legend');
var {deepPureRenderMixin, rxEventsMixin} = require('./react-utils');
var widgets = require('./columnWidgets');
var util = require('./util');
var CanvasDrawing = require('./CanvasDrawing');
var {features, chromFromAlt, posFromAlt, structuralVariantClass} = require('./models/mutationVector');
var {drawMutations, radius, labelFont, toYPx} = require('./drawMutations');

// Since we don't set module.exports, but instead register ourselves
// with columWidgets, react-hot-loader can't handle the updates automatically.
// Accept hot loading here.
if (module.hot) {
	module.hot.accept();
	module.hot.accept('./models/mutationVector', () => {
		features = require('./models/mutationVector');
	});
}

// Since there are multiple components in the file we have to use makeHot
// explicitly.
function hotOrNot(component) {
	return module.makeHot ? module.makeHot(component) : component;
}

function drawLegend({column}) {
	var allMetaData = _.getIn(column, ['datasetMetadata']),
		feature = _.getIn(column, ['sFeature']),
		dataSubType = (allMetaData && allMetaData[0]) ? allMetaData[0].dataSubType : undefined,
		{colors, labels, align} = features[feature].legend(dataSubType);

	return (
		<Legend
			colors={['rgb(255,255,255)', ...colors]}
			labels={['no variant', ...labels]}
			align={align}
			ellipsis='' />
	);
}

function closestNode(nodes, pixPerRow, index, count, x, y) {
	var cutoffX = radius,
		end = index + count,
		yPx = toYPx(pixPerRow, index),
		nearBy = _.filter(nodes, n => {
			if (!( n.y >= index && n.y < end &&
				(x > n.xStart - cutoffX) && (x < n.xEnd + cutoffX))) {
				return false;
			}
			var transformed = (pixPerRow > labelFont) && n.yTransformed,
				cutoffY = transformed ? n.svHeight / 2 :  pixPerRow / 2 ;
			return Math.abs(y - ( transformed ? n.yTransformed : yPx(n.y))) < cutoffY;
		});
	return nearBy.length > 0 ? _.min(nearBy, n => Math.abs(x - (n.xStart + n.xEnd) / 2.0)) : undefined;
}

function formatAf(af) {
	return (af === 'NA' || af === '' || af == null) ? null :
		Math.round(af * 100) + '%';
}

var fmtIf = (x, fmt, d = '' ) => x ? fmt(x) : d;
var dropNulls = rows => rows.map(row => row.filter(col => col != null)) // drop empty cols
	.filter(row => row.length > 0); // drop empty rows
var gbURL =  (assembly, pos) => `http://genome.ucsc.edu/cgi-bin/hgTracks?db=${encodeURIComponent(assembly)}&position=${encodeURIComponent(pos)}`;

function sampleTooltip(sampleFormat, data, gene, assembly) {
	var dnaVaf = data.dna_vaf == null ? null : ['labelValue',  'DNA variant allele freq', formatAf(data.dna_vaf)],
		rnaVaf = data.rna_vaf == null ? null : ['labelValue',  'RNA variant allele freq', formatAf(data.rna_vaf)],
		ref = data.reference && ['value', `${data.reference} to `],
		altPos = data.alt && structuralVariantClass(data.alt) &&
			`chr${chromFromAlt(data.alt)}:${posFromAlt(data.alt)}-${posFromAlt(data.alt)}`,
		alt = data.alt && (structuralVariantClass(data.alt) ?
							['url', `${data.alt}`, gbURL(assembly, altPos)] :
							['value', `${data.alt}`]),
		pos = data && `${data.chr}:${util.addCommas(data.start)}-${util.addCommas(data.end)}`,
		posDisplay = data && (data.start === data.end) ? `${data.chr}:${util.addCommas(data.start)}` : pos,
		posURL = ['url',  `${assembly} ${posDisplay}`, gbURL(assembly, pos)],
		effect = ['value', fmtIf(data.effect, x => `${x}, `) + //eslint-disable-line comma-spacing
					gene +
					fmtIf(data.amino_acid, x => ` (${x})`) +
					fmtIf(data.altGene, x => ` connect to ${x} `)
					];
	return {
		rows: dropNulls([
			[effect],
			[posURL, ref, alt],
			[dnaVaf],
			[rnaVaf]
		]),
		sampleID: sampleFormat(data.sample)
	};
}

function makeRow(fields, sampleGroup, row) {
	let fieldValue;
	if (_.isArray(sampleGroup) && sampleGroup.length === 0) {
		fieldValue = 'no variant';
	}
	if (_.isEmpty(sampleGroup)) {
		sampleGroup = [row];
	}
	return _.flatmap(sampleGroup, row =>
		_.map(fields, f => (row && row[f]) || fieldValue));
}

function tooltip(nodes, samples, sampleFormat, {height, count, index}, gene, assembly, ev) {
	var {x, y} = util.eventOffset(ev),
		pixPerRow = height / count,
		yIndex = Math.round((y - pixPerRow / 2) / pixPerRow + index),
		node = closestNode(nodes, pixPerRow, index, count, x, y);

	return node ?
		sampleTooltip(sampleFormat, node.data, gene, assembly) :
		{sampleID: sampleFormat(samples[yIndex])};
}

function getRowFields(rows, sampleGroups) {
	if (_.isEmpty(sampleGroups)) {
		return []; // When no samples exist
	} else if (!_.isEmpty(rows)) {
		return _.keys(rows[0]); // When samples have mutation(s)
	} else {
		return ['sample', 'result']; // default fields for mutation-less columns
	}
}

function formatSamples(sampleFormat, rows) {
	return _.map(rows, r => _.updateIn(r, ['sample'], sampleFormat));
}

var MutationColumn = hotOrNot(React.createClass({
	mixins: [rxEventsMixin, deepPureRenderMixin],
	componentWillMount: function () {
		this.events('mouseout', 'mousemove', 'mouseover');

		// Compute tooltip events from mouse events.
		this.ttevents = this.ev.mouseover
			.filter(ev => util.hasClass(ev.currentTarget, 'Tooltip-target'))
			.selectMany(() => {
				return this.ev.mousemove
					.takeUntil(this.ev.mouseout)
					.map(ev => ({
						data: this.tooltip(ev),
						open: true,
						point: {x: ev.clientX, y: ev.clientY}
					})) // look up current data
					.concat(Rx.Observable.return({open: false}));
			}).subscribe(this.props.tooltip);
	},
	componentWillUnmount: function () {
		this.ttevents.dispose();
	},
	download: function() {
		let {data: {req: {rows}}, samples, index, sampleFormat} = this.props,
			groupedSamples = _.getIn(index, ['bySample']) || [],
			rowFields = getRowFields(rows, groupedSamples),
			allRows = _.map(samples, (sId) => {
				let alternateRow = {sample: sampleFormat(sId)}; // only used for mutation-less samples
				return makeRow(rowFields, formatSamples(sampleFormat, groupedSamples[sId]),
					alternateRow);
			});
		return [rowFields, allRows];
	},
	tooltip: function (ev) {
		var {column: {nodes, fields, assembly}, samples, sampleFormat, zoom} = this.props;
		return tooltip(nodes, samples, sampleFormat, zoom, fields[0], assembly, ev);
	},
	render: function () {
		var {column, samples, zoom, data, index} = this.props,
			feature = _.getIn(column, ['sFeature']);

		// XXX Make plot a child instead of a prop? There's also legend.
		return (
			<CanvasDrawing
					ref='plot'
					draw={drawMutations}
					wrapperProps={{
						className: 'Tooltip-target',
						onMouseMove: this.ev.mousemove,
						onMouseOut: this.ev.mouseout,
						onMouseOver: this.ev.mouseover,
						onClick: this.props.onClick
					}}
					feature={feature}
					nodes={column.nodes}
					strand={column.strand}
					width={column.width}
					data={data}
					index={index}
					samples={samples}
					xzoom={column.zoom}
					zoom={zoom}/>);
	}
}));

var getColumn = props => <MutationColumn {...props} />;
widgets.column.add('mutation', getColumn);

widgets.legend.add('mutation', drawLegend);
<|endoftext|>


<commit_before>

function SpazPostPanel(opts) {

	this.container = opts.container || document.getElementById('entryform');
	this.textarea  = opts.textarea  || document.getElementById('entrybox');
	this.counter   = opts.counter   || document.getElementById('chars-left-count');
	this.counter_desc   = opts.counter_desc   || document.getElementById('chars-left-description');
	this.irt_container  = opts.irt_container  || document.getElementById('irt');
	this.$irt_container = jQuery(this.irt_container);
	this.irt_message    = opts.irt_message    || document.getElementById('irt-message');
	this.$irt_message   = jQuery(this.irt_message);
	this.irt_id_attr    = opts.irt_id_attr    || 'data-status-id';
	// this.menu      = opts.menu      || null;
	this.menus     = opts.menus     || {};
	this.maxlen    = opts.maxlen    || 140;
	this.on_over   = opts.on_over   || this.on_over_default;
	this.on_under  = opts.on_under  || this.on_under_default;
	this.on_submit = opts.on_submit || null;
	this.shortlink_service = opts.shortlink_service || SPAZCORE_SHORTURL_SERVICE_BITLY;

	this.irt_status = '';
	this.irt_status_id = 0;

	this.addListeners();
	this.buildShortenMenu();
}

SpazPostPanel.prototype.prepMessage = function() {
	this.clearPostIRT();
	this.textarea.focus();
	this.setMessageText('');
};

SpazPostPanel.prototype.prepReply = function(username, status_id, status_text) {

	this.clearPostIRT();

	this.textarea.focus();

	var text = '@';

    if (username) {
		text += username + ' ';
    }

	this.setPostIRT(status_id, status_text);

	this.setMessageText(text);

};

SpazPostPanel.prototype.prepRetweet = function(screenname, text) {
	this.clearPostIRT();
	this.textarea.focus();
	text = 'RT @' + screenname + ': '+text+'';
	this.setMessageText(text);
};

SpazPostPanel.prototype.prepDirectMessage = function(username) {
	this.clearPostIRT();
	this.textarea.focus();
	var text = 'd ';

    if (username) {
		text += (username + ' ');
    }
	this.setMessageText(text);
};

SpazPostPanel.prototype.prepPhotoPost = function(url) {

	this.clearPostIRT();
	this.textarea.focus();
	if (!url) {
		return false;
	}

	var text = url + ' ';

	this.setMessageText(text);
	return text;
};

SpazPostPanel.prototype.clearPostIRT = function() {
	this.irt_status = '';
	this.irt_status_id = 0;
	this.$irt_container.hide();
	this.$irt_message.attr(this.irt_id_attr, this.irt_status_id)
		.text(this.irt_status);
};

SpazPostPanel.prototype.shortenText = function() {
	var longtext  = this.getMessageText();
	var shorttext = this.shortener.shorten(longtext);
	this.setMessageText(shorttext);
};

SpazPostPanel.prototype.setPostIRT = function(status_id, status_text) {

	if (status_id) {
		this.irt_status_id = status_id;
		this.$irt_container.show();
		this.$irt_message.attr(this.irt_id_attr, this.irt_status_id)
			.text(this.irt_status_id);

	}

	if (status_text) {
		this.irt_status = status_text;
		this.$irt_message.text(this.irt_status);
	}

};

SpazPostPanel.prototype.setMessageText = function(text) {
	this.textarea.value = text;
	this.updateTextMetadata();
};

SpazPostPanel.prototype.getMessageText = function() {
	return this.textarea.value;
};

SpazPostPanel.prototype.addListeners = function() {
	var thisPP = this;

	jQuery(thisPP.textarea).
		keyup(function(e){ thisPP.updateTextMetadata(); }).
		focus(function(e){
			thisPP.updateTextMetadata();
			Spaz.UI.showEntryboxTip();
			$('#entrybox-popup').fadeIn('fast');
		}).
		blur(function(e){
			thisPP.updateTextMetadata();
			setTimeout(function(){
				// Hack: Brief delay to allow menus to appear, if any. A race condition
				// can occur here, where the menu only starts building after
				// #entrybox-popup has begun fading.
				if(!jQuery('#' + thisPP.menus.shorten.opts.base_id + ':visible')[0]){
					Spaz.UI.resetStatusBar();
					$("body").focus();
					$('#entrybox-popup').fadeOut('fast');
				}
			}, 100);
			return false;
		});
};

// SpazPostPanel.prototype.removeListeners = function() {
// 	sc.helpers.unlisten(this.textarea, 'keyup');
// 	sc.helpers.unlisten(this.textarea, 'focus');
// 	sc.helpers.unlisten(this.textarea, 'blur');
// };

SpazPostPanel.prototype.updateTextMetadata = function(){
	var thisPP = this;

	// Update character count
	(function(){
		var count = thisPP.textarea.value.length,
		    left  = thisPP.maxlen - count;
		thisPP.counter.innerText = left.toString();
		thisPP.counter_desc.innerText = 'left';

		var info = {
			entry_el:   thisPP.textarea,
			count_el:   thisPP.counter,
			curr_count: count,
			left:       left,
			max:        thisPP.maxlen
		};

		if (left < 0) {
			thisPP.on_over.call(thisPP.textarea, info);
		} else {
			thisPP.on_under.call(thisPP.textarea, info);
		}
	})();

	// Add styling hook for DMs
	(function(){
		var $textarea    = jQuery(thisPP.textarea),
		    text         = $textarea.val(),
		    textareaIsDM = $textarea.hasClass('dm'),
		    textIsDM     = text.match(/^d /);

		if(textIsDM && !textareaIsDM){
			$textarea.addClass('dm');
		}else if(!textIsDM && textareaIsDM){
			$textarea.removeClass('dm');
		}
	})();
};

SpazPostPanel.prototype.on_over_default = function(info) {
	jQuery(info.count_el).addClass('over').removeClass('under');
	jQuery(info.entry_el).addClass('over').removeClass('under');
};

SpazPostPanel.prototype.on_under_default = function(info) {
	jQuery(info.count_el).addClass('under').removeClass('over');
	jQuery(info.entry_el).addClass('under').removeClass('over');
};

SpazPostPanel.prototype.buildShortenMenu = function(){
	var thisPP  = this,
	    menuId  = 'entrybox-shorten-menu',
	    menu,
	    $toggle = $('#entrybox-shorten');

	// Build menu
	menu = this.menus.shorten = new SpazMenu({
		base_id:    menuId,
		base_class: 'spaz-menu',
		li_class:   'spaz-menu-item',
		items_func: function(){
			return [
				{
					label:   'Shorten URLs',
					handler: Spaz.UI.shortenPostPanelURLs
				},
				{
					label:   'Shorten text',
					handler: Spaz.UI.shortenPostPanelText
				}
			];
		}
	});
	menu.bindToggle($toggle.selector, {
		afterShow: function(e){
			jQuery(thisPP.textarea).focus();
		}
	});
};

SpazPostPanel.prototype.shortenText = function() {
	var stxt = new SpazShortText();
	var shorttext = stxt.shorten(this.getMessageText());
	this.setMessageText(shorttext);
	this.updateTextMetadata();
};

SpazPostPanel.prototype.shortenURLs = function() {

	var thisPP = this;

	var event_target = this.textarea;

	var surl = new SpazShortURL(this.shortlink_service);

	var longurls = sc.helpers.extractURLs(this.getMessageText());

    sch.error(this.getMessageText());
    sch.error(longurls);

	/*
		check URL lengths
	*/
	var reallylongurls = [];
	for (var i=0; i<longurls.length; i++) {
		if (longurls[i].length > 25) { // only shorten links longer than 25chars
			reallylongurls.push(longurls[i]);
		}
	}

	/*
		drop out if we don't have any URLs
	*/
	if (reallylongurls.length < 1) {
		return;
	}

	function onShortURLSuccess(e, data) {
		Spaz.UI.statusBar('URLs shortened');
		Spaz.UI.hideLoading();

		var newtext = sc.helpers.replaceMultiple(thisPP.getMessageText(), data);
		thisPP.setMessageText(newtext);
		thisPP.updateTextMetadata();
		sch.unlisten(event_target, sc.events.newShortURLSuccess, onShortURLSuccess);
		sch.unlisten(event_target, sc.events.newShortURLFailure, onShortURLFailure);
	}
	function onShortURLFailure(e) {
		Spaz.UI.statusBar('URL shortening failed');
		Spaz.UI.hideLoading();

		thisPP.updateTextMetadata();
		sch.unlisten(event_target, sc.events.newShortURLSuccess, onShortURLSuccess);
		sch.unlisten(event_target, sc.events.newShortURLFailure, onShortURLFailure);
	}

	sch.listen(event_target, sc.events.newShortURLSuccess, onShortURLSuccess);
	sch.listen(event_target, sc.events.newShortURLFailure, onShortURLFailure);

	Spaz.UI.statusBar('Shortening URLs in message');
	Spaz.UI.showLoading();

	surl.shorten(reallylongurls, {
		'event_target':event_target,
		'apiopts': {
			'version':'2.0.1',
			'format':'json',
			'login':Spaz.Prefs.get('services-bitly-login') || 'spazcore',
			'apiKey':Spaz.Prefs.get('services-bitly-apikey') || 'R_f3b86681a63a6bbefc7d8949fd915f1d'
		}
	});
};

SpazPostPanel.prototype.submit = function() {

	if (this.on_submit) {
		this.on_submit.call(this);
	}
};

SpazPostPanel.prototype.disable = function() {
	this.disabled = true;
	this.textarea.setAttribute("disabled","disabled");
};

SpazPostPanel.prototype.enable = function() {
	this.disabled = false;
	this.textarea.removeAttribute("disabled");
};

SpazPostPanel.prototype.reset = function() {
	this.clearPostIRT();
	this.setMessageText('');
	this.updateTextMetadata();
};
<commit_msg>Made blurring of PostPanel smarter so it doesn't blur when the panel is clicked on. Also converted spaces to tabs.<commit_after>

function SpazPostPanel(opts) {

	this.container = opts.container || document.getElementById('entryform');
	this.textarea  = opts.textarea	|| document.getElementById('entrybox');
	this.counter   = opts.counter	|| document.getElementById('chars-left-count');
	this.counter_desc	= opts.counter_desc	  || document.getElementById('chars-left-description');
	this.irt_container	= opts.irt_container  || document.getElementById('irt');
	this.$irt_container = jQuery(this.irt_container);
	this.irt_message	= opts.irt_message	  || document.getElementById('irt-message');
	this.$irt_message	= jQuery(this.irt_message);
	this.irt_id_attr	= opts.irt_id_attr	  || 'data-status-id';
	// this.menu	  = opts.menu	   || null;
	this.menus	   = opts.menus		|| {};
	this.maxlen	   = opts.maxlen	|| 140;
	this.on_over   = opts.on_over	|| this.on_over_default;
	this.on_under  = opts.on_under	|| this.on_under_default;
	this.on_submit = opts.on_submit || null;
	this.shortlink_service = opts.shortlink_service || SPAZCORE_SHORTURL_SERVICE_BITLY;

	this.irt_status = '';
	this.irt_status_id = 0;

	this.addListeners();
	this.buildShortenMenu();
}

SpazPostPanel.prototype.prepMessage = function() {
	this.clearPostIRT();
	this.textarea.focus();
	this.setMessageText('');
};

SpazPostPanel.prototype.prepReply = function(username, status_id, status_text) {

	this.clearPostIRT();

	this.textarea.focus();

	var text = '@';

	if (username) {
		text += username + ' ';
	}

	this.setPostIRT(status_id, status_text);

	this.setMessageText(text);

};

SpazPostPanel.prototype.prepRetweet = function(screenname, text) {
	this.clearPostIRT();
	this.textarea.focus();
	text = 'RT @' + screenname + ': '+text+'';
	this.setMessageText(text);
};

SpazPostPanel.prototype.prepDirectMessage = function(username) {
	this.clearPostIRT();
	this.textarea.focus();
	var text = 'd ';

	if (username) {
		text += (username + ' ');
	}
	this.setMessageText(text);
};

SpazPostPanel.prototype.prepPhotoPost = function(url) {

	this.clearPostIRT();
	this.textarea.focus();
	if (!url) {
		return false;
	}

	var text = url + ' ';

	this.setMessageText(text);
	return text;
};

SpazPostPanel.prototype.clearPostIRT = function() {
	this.irt_status = '';
	this.irt_status_id = 0;
	this.$irt_container.hide();
	this.$irt_message.attr(this.irt_id_attr, this.irt_status_id)
		.text(this.irt_status);
};

SpazPostPanel.prototype.shortenText = function() {
	var longtext  = this.getMessageText();
	var shorttext = this.shortener.shorten(longtext);
	this.setMessageText(shorttext);
};

SpazPostPanel.prototype.setPostIRT = function(status_id, status_text) {

	if (status_id) {
		this.irt_status_id = status_id;
		this.$irt_container.show();
		this.$irt_message.attr(this.irt_id_attr, this.irt_status_id)
			.text(this.irt_status_id);

	}

	if (status_text) {
		this.irt_status = status_text;
		this.$irt_message.text(this.irt_status);
	}

};

SpazPostPanel.prototype.setMessageText = function(text) {
	this.textarea.value = text;
	this.updateTextMetadata();
};

SpazPostPanel.prototype.getMessageText = function() {
	return this.textarea.value;
};

SpazPostPanel.prototype.addListeners = function() {
	var thisPP = this;

	jQuery('#entrybox-popup')
		.mousedown(function(e) {
			thisPP.panelClicked = true;
		})
		.mouseup(function(e) {
			thisPP.panelClicked = false;
			thisPP.textarea.focus();
		});

	jQuery(thisPP.textarea).
		keyup(function(e){ thisPP.updateTextMetadata(); }).
		focus(function(e){
			thisPP.updateTextMetadata();
			Spaz.UI.showEntryboxTip();
			jQuery('#entrybox-popup').fadeIn('fast');
		}).
		blur(function(e){
			thisPP.updateTextMetadata();
			if (!thisPP.panelClicked) {
				sch.error('panel NOT clicked, blur-ing');
				Spaz.UI.resetStatusBar();
				jQuery("body").focus();
				jQuery('#entrybox-popup').fadeOut('fast');
				thisPP.panelClicked = false;
			} else {
				sch.error('panel clicked, blocking blur');
			}
			return false;
		});
};

// SpazPostPanel.prototype.removeListeners = function() {
//	sc.helpers.unlisten(this.textarea, 'keyup');
//	sc.helpers.unlisten(this.textarea, 'focus');
//	sc.helpers.unlisten(this.textarea, 'blur');
// };

SpazPostPanel.prototype.updateTextMetadata = function(){
	var thisPP = this;

	// Update character count
	(function(){
		var count = thisPP.textarea.value.length,
			left  = thisPP.maxlen - count;
		thisPP.counter.innerText = left.toString();
		thisPP.counter_desc.innerText = 'left';

		var info = {
			entry_el:	thisPP.textarea,
			count_el:	thisPP.counter,
			curr_count: count,
			left:		left,
			max:		thisPP.maxlen
		};

		if (left < 0) {
			thisPP.on_over.call(thisPP.textarea, info);
		} else {
			thisPP.on_under.call(thisPP.textarea, info);
		}
	})();

	// Add styling hook for DMs
	(function(){
		var $textarea	 = jQuery(thisPP.textarea),
			text		 = $textarea.val(),
			textareaIsDM = $textarea.hasClass('dm'),
			textIsDM	 = text.match(/^d /);

		if(textIsDM && !textareaIsDM){
			$textarea.addClass('dm');
		}else if(!textIsDM && textareaIsDM){
			$textarea.removeClass('dm');
		}
	})();
};

SpazPostPanel.prototype.on_over_default = function(info) {
	jQuery(info.count_el).addClass('over').removeClass('under');
	jQuery(info.entry_el).addClass('over').removeClass('under');
};

SpazPostPanel.prototype.on_under_default = function(info) {
	jQuery(info.count_el).addClass('under').removeClass('over');
	jQuery(info.entry_el).addClass('under').removeClass('over');
};

SpazPostPanel.prototype.buildShortenMenu = function(){
	var thisPP	= this,
		menuId	= 'entrybox-shorten-menu',
		menu,
		$toggle = $('#entrybox-shorten');

	// Build menu
	menu = this.menus.shorten = new SpazMenu({
		base_id:	menuId,
		base_class: 'spaz-menu',
		li_class:	'spaz-menu-item',
		items_func: function(){
			return [
				{
					label:	 'Shorten URLs',
					handler: Spaz.UI.shortenPostPanelURLs
				},
				{
					label:	 'Shorten text',
					handler: Spaz.UI.shortenPostPanelText
				}
			];
		}
	});
	menu.bindToggle($toggle.selector, {
		afterShow: function(e){
			jQuery(thisPP.textarea).focus();
		}
	});
};

SpazPostPanel.prototype.shortenText = function() {
	var stxt = new SpazShortText();
	var shorttext = stxt.shorten(this.getMessageText());
	this.setMessageText(shorttext);
	this.updateTextMetadata();
};

SpazPostPanel.prototype.shortenURLs = function() {

	var thisPP = this;

	var event_target = this.textarea;

	var surl = new SpazShortURL(this.shortlink_service);

	var longurls = sc.helpers.extractURLs(this.getMessageText());

	sch.error(this.getMessageText());
	sch.error(longurls);

	/*
		check URL lengths
	*/
	var reallylongurls = [];
	for (var i=0; i<longurls.length; i++) {
		if (longurls[i].length > 25) { // only shorten links longer than 25chars
			reallylongurls.push(longurls[i]);
		}
	}

	/*
		drop out if we don't have any URLs
	*/
	if (reallylongurls.length < 1) {
		return;
	}

	function onShortURLSuccess(e, data) {
		Spaz.UI.statusBar('URLs shortened');
		Spaz.UI.hideLoading();

		var newtext = sc.helpers.replaceMultiple(thisPP.getMessageText(), data);
		thisPP.setMessageText(newtext);
		thisPP.updateTextMetadata();
		sch.unlisten(event_target, sc.events.newShortURLSuccess, onShortURLSuccess);
		sch.unlisten(event_target, sc.events.newShortURLFailure, onShortURLFailure);
	}
	function onShortURLFailure(e) {
		Spaz.UI.statusBar('URL shortening failed');
		Spaz.UI.hideLoading();

		thisPP.updateTextMetadata();
		sch.unlisten(event_target, sc.events.newShortURLSuccess, onShortURLSuccess);
		sch.unlisten(event_target, sc.events.newShortURLFailure, onShortURLFailure);
	}

	sch.listen(event_target, sc.events.newShortURLSuccess, onShortURLSuccess);
	sch.listen(event_target, sc.events.newShortURLFailure, onShortURLFailure);

	Spaz.UI.statusBar('Shortening URLs in message');
	Spaz.UI.showLoading();

	surl.shorten(reallylongurls, {
		'event_target':event_target,
		'apiopts': {
			'version':'2.0.1',
			'format':'json',
			'login':Spaz.Prefs.get('services-bitly-login') || 'spazcore',
			'apiKey':Spaz.Prefs.get('services-bitly-apikey') || 'R_f3b86681a63a6bbefc7d8949fd915f1d'
		}
	});
};

SpazPostPanel.prototype.submit = function() {

	if (this.on_submit) {
		this.on_submit.call(this);
	}
};

SpazPostPanel.prototype.disable = function() {
	this.disabled = true;
	this.textarea.setAttribute("disabled","disabled");
};

SpazPostPanel.prototype.enable = function() {
	this.disabled = false;
	this.textarea.removeAttribute("disabled");
};

SpazPostPanel.prototype.reset = function() {
	this.clearPostIRT();
	this.setMessageText('');
	this.updateTextMetadata();
};
<|endoftext|>


<commit_before>'use strict';

angular.module('subutai.kurjun.service', [])
	.factory('kurjunSrv', kurjunService);

kurjunService.$inject = ['$http', 'Upload', 'SettingsKurjunSrv'];

function kurjunService($http, Upload, SettingsKurjunSrv)
{
	var BASE_URL = GLOBAL_KURJUN_URL + "/";
	var TEMPLATE_URL = BASE_URL + "template/";
	var DEB_URL = BASE_URL + "deb/";
	var RAW_URL = BASE_URL + "file/";

	var LOCAL_BASE_URL = SERVER_URL + "rest/kurjun/";
	var LOCAL_TEMPLATE_URL = LOCAL_BASE_URL + "template/";
	var LOCAL_DEB_URL = LOCAL_BASE_URL + "deb/";
	var LOCAL_RAW_URL = LOCAL_BASE_URL + "file/";

	var REPOSITORY_URL = LOCAL_BASE_URL + "templates/repositories";

	var kurjunService = {
		getRepositories: getRepositories,
		getTemplates: getTemplates,
		getAPTList: getAPTList,
		addTemplate: addTemplate,
		shareTemplate: shareTemplate,
		addApt: addApt,
		deleteTemplate: deleteTemplate,
		deleteAPT: deleteAPT,
		isUploadAllowed: isUploadAllowed,
		getShared: getShared,
		getRawFiles: getRawFiles,
		addFile:addFile,
		uploadFile: uploadFile
	};

	return kurjunService;

	function setUrlsValues() {
		BASE_URL = GLOBAL_KURJUN_URL + "/";
		TEMPLATE_URL = BASE_URL + "template/";
		// REPOSITORY_URL = BASE_URL + "repository/";
		DEB_URL = BASE_URL + "deb/";
		RAW_URL = BASE_URL + "file/";
	}

	function getRepositories() {
		setUrlsValues();
		return $http.get(REPOSITORY_URL, {withCredentials: false, headers: {'Content-Type': 'application/json'}});
	}

	function getTemplates(repository) {
		setUrlsValues();
		return $http.get(TEMPLATE_URL + 'list?repository=all', {
			withCredentials: false,
			headers: {'Content-Type': 'application/json'}
		});
	}

	function getAPTList() {
		setUrlsValues();
		return $http.get(DEB_URL + "list?repository=all", {
			withCredentials: false,
			headers: {'Content-Type': 'application/json'}
		});
	}

	function getRawFiles() {
		setUrlsValues();
		return $http.get(RAW_URL + "list?repository=all", {
			withCredentials: false,
			headers: {'Content-Type': 'application/json'}
		});
	}

	function addFile(file) {
		return uploadFile(file, LOCAL_RAW_URL + 'upload');
	}

	function addTemplate(file) {
		//setUrlsValues();
		//@todo repository=
		return uploadTemplate(file, LOCAL_TEMPLATE_URL + 'upload');
	}

	function addApt(file) {
		return uploadApt(file, LOCAL_DEB_URL + 'upload');
	}

	function deleteTemplate(id) {
		setUrlsValues();
		return $http.delete(LOCAL_TEMPLATE_URL + 'delete', {params: {id: id}}, {
			withCredentials: false,
			headers: {'Content-Type': 'application/json'}
		});
	}

	function shareTemplate(users, templateId) {
		setUrlsValues();
		// TODO: doesn't work properly
		var postData = "users=" + users + "&templateId=" + templateId;
		return $http.post(
			BASE_URL + "share",
			postData,
			{withCredentials: false, headers: {'Content-Type': 'application/x-www-form-urlencoded'}}
		);
	}

	function deleteAPT(md5) {
		setUrlsValues();
		return $http.delete(LOCAL_DEB_URL + 'delete', {params: {md5: md5}}, {
			withCredentials: false,
			headers: {withCredentials: false, 'Content-Type': 'application/json'}
		});
	}

	function isUploadAllowed(repository) {
		setUrlsValues();
		return $http.get(LOCAL_TEMPLATE_URL + repository + '/can-upload', {
			withCredentials: false,
			headers: {withCredentials: false, 'Content-Type': 'application/json'}
		});
	}

	function getShared(templateId) {
		// TODO: doesn't work properly
		return $http.get (BASE_URL + "shared/users/" + templateId);
	}

	function uploadTemplate(file, url) {
		return Upload.upload({
			url: url,
			data: {package: file},
			headers: {withCredentials: false, 'Content-Type': undefined},
			transformRequest: angular.identity
		});
	}

	function uploadApt(file, url) {
		return Upload.upload({
			url: url,
			data: {file: file},
			headers: {withCredentials: false, 'Content-Type': undefined},
			transformRequest: angular.identity
		});
	}

	function uploadFile(file, url) {
		return Upload.upload({
			url: url,
			data: {file: file},
			headers: {withCredentials: false, 'Content-Type': undefined},
			transformRequest: angular.identity
		});
	}
}
<commit_msg>kurjun changed to local urls<commit_after>'use strict';

angular.module('subutai.kurjun.service', [])
	.factory('kurjunSrv', kurjunService);

kurjunService.$inject = ['$http', 'Upload', 'SettingsKurjunSrv'];

function kurjunService($http, Upload, SettingsKurjunSrv)
{
	var BASE_URL = GLOBAL_KURJUN_URL + "/";
	var TEMPLATE_URL = BASE_URL + "template/";
	var DEB_URL = BASE_URL + "deb/";
	var RAW_URL = BASE_URL + "file/";

	var LOCAL_BASE_URL = SERVER_URL + "rest/kurjun/";
	var LOCAL_TEMPLATE_URL = LOCAL_BASE_URL + "template/";
	var LOCAL_DEB_URL = LOCAL_BASE_URL + "deb/";
	var LOCAL_RAW_URL = LOCAL_BASE_URL + "file/";

	var REPOSITORY_URL = LOCAL_BASE_URL + "templates/repositories";

	var kurjunService = {
		getRepositories: getRepositories,
		getTemplates: getTemplates,
		getAPTList: getAPTList,
		addTemplate: addTemplate,
		shareTemplate: shareTemplate,
		addApt: addApt,
		deleteTemplate: deleteTemplate,
		deleteAPT: deleteAPT,
		isUploadAllowed: isUploadAllowed,
		getShared: getShared,
		getRawFiles: getRawFiles,
		addFile:addFile,
		uploadFile: uploadFile
	};

	return kurjunService;

	function setUrlsValues() {
		BASE_URL = GLOBAL_KURJUN_URL + "/";
		TEMPLATE_URL = BASE_URL + "template/";
		// REPOSITORY_URL = BASE_URL + "repository/";
		DEB_URL = BASE_URL + "deb/";
		RAW_URL = BASE_URL + "file/";
	}

	function getRepositories() {
		setUrlsValues();
		return $http.get(REPOSITORY_URL, {withCredentials: false, headers: {'Content-Type': 'application/json'}});
	}

	function getTemplates(repository) {
		setUrlsValues();
		return $http.get(LOCAL_TEMPLATE_URL + 'list?repository=all', {
			withCredentials: false,
			headers: {'Content-Type': 'application/json'}
		});
	}

	function getAPTList() {
		setUrlsValues();
		return $http.get(LOCAL_DEB_URL + "list?repository=all", {
			withCredentials: false,
			headers: {'Content-Type': 'application/json'}
		});
	}

	function getRawFiles() {
		setUrlsValues();
		return $http.get(LOCAL_RAW_URL + "list?repository=all", {
			withCredentials: false,
			headers: {'Content-Type': 'application/json'}
		});
	}

	function addFile(file) {
		return uploadFile(file, LOCAL_RAW_URL + 'upload');
	}

	function addTemplate(file) {
		//setUrlsValues();
		//@todo repository=
		return uploadTemplate(file, LOCAL_TEMPLATE_URL + 'upload');
	}

	function addApt(file) {
		return uploadApt(file, LOCAL_DEB_URL + 'upload');
	}

	function deleteTemplate(id) {
		setUrlsValues();
		return $http.delete(LOCAL_TEMPLATE_URL + 'delete', {params: {id: id}}, {
			withCredentials: false,
			headers: {'Content-Type': 'application/json'}
		});
	}

	function shareTemplate(users, templateId) {
		setUrlsValues();
		// TODO: doesn't work properly
		var postData = "users=" + users + "&templateId=" + templateId;
		return $http.post(
			BASE_URL + "share",
			postData,
			{withCredentials: false, headers: {'Content-Type': 'application/x-www-form-urlencoded'}}
		);
	}

	function deleteAPT(md5) {
		setUrlsValues();
		return $http.delete(LOCAL_DEB_URL + 'delete', {params: {md5: md5}}, {
			withCredentials: false,
			headers: {withCredentials: false, 'Content-Type': 'application/json'}
		});
	}

	function isUploadAllowed(repository) {
		setUrlsValues();
		return $http.get(LOCAL_TEMPLATE_URL + repository + '/can-upload', {
			withCredentials: false,
			headers: {withCredentials: false, 'Content-Type': 'application/json'}
		});
	}

	function getShared(templateId) {
		// TODO: doesn't work properly
		return $http.get (BASE_URL + "shared/users/" + templateId);
	}

	function uploadTemplate(file, url) {
		return Upload.upload({
			url: url,
			data: {package: file},
			headers: {withCredentials: false, 'Content-Type': undefined},
			transformRequest: angular.identity
		});
	}

	function uploadApt(file, url) {
		return Upload.upload({
			url: url,
			data: {file: file},
			headers: {withCredentials: false, 'Content-Type': undefined},
			transformRequest: angular.identity
		});
	}

	function uploadFile(file, url) {
		return Upload.upload({
			url: url,
			data: {file: file},
			headers: {withCredentials: false, 'Content-Type': undefined},
			transformRequest: angular.identity
		});
	}
}
<|endoftext|>