<commit_before>/**
 * Developer: Stepan Burguchev
 * Date: 12/2/2014
 * Copyright: 2009-2014 Comindware®
 *       All Rights Reserved
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Comindware
 *       The copyright notice above does not evidence any
 *       actual or intended publication of such source code.
 */

/* global define, require, Handlebars, Backbone, Marionette, $, _ */

/*
*
* Marionette-based Backbone.Form editor. MUST NOT be used directly. Use EditorBase*View base views instead while implementing Marionette editors.
*
* */

define([
        'module/lib'
    ],
    function () {
        'use strict';

        var classes = {
            disabled: 'l-field_disabled',
            readonly: 'l-field_readonly'
        };

        var onFocus = function () {
            this.trigger('focus', this);
        };

        var onBlur = function () {
            this.trigger('blur', this);
        };

        var onRender = function () {
            this.$el.attr('id', this.id);
            this.$el.attr('name', this.getName());
            this.setPermissions(this.enabled, this.readonly);
            //noinspection JSUnresolvedVariable
            if (this.schema.editorClass) {
                //noinspection JSUnresolvedVariable
                this.$el.addClass(this.schema.editorClass);
            }
            if (this.schema.editorAttrs) {
                this.$el.attr(this.schema.editorAttrs);
            }
            this.setValue(this.value, true);
            if (this.focusElement) {
                this.$el.on('focus', this.focusElement, onFocus.bind(this));
                this.$el.on('blur', this.focusElement, onBlur.bind(this));
            } else {
                this.$el.on('focus', onFocus.bind(this));
                this.$el.on('blur', onBlur.bind(this));
            }
        };

        return {
            create: function(viewClass) {
                return {
                    defaultValue: null,

                    hasFocus: false,

                    constructor: function (options) {
                        options = options || {};

                        //Set initial value
                        if (options.model) {
                            if (!options.key) {
                                throw new Error("Missing option: 'key'");
                            }

                            this.model = options.model;
                            this.value = this.model.get(options.key);
                        }
                        else if (options.value !== undefined) {
                            this.value = options.value;
                        }

                        if (this.value === undefined) {
                            this.value = this.defaultValue;
                        }

                        //Store important data
                        _.extend(this, _.pick(options, 'key', 'form'));

                        var schema = this.schema = options.schema || {};

                        this.validators = options.validators || schema.validators;

                        this.on('render', onRender.bind(this));

                        schema.autocommit = schema.autocommit || options.autocommit;
                        if (schema.autocommit) {
                            this.on('change', this.commit.bind(this, {}));
                        }

                        this.enabled = schema.enabled = schema.enabled || options.enabled || (schema.enabled === undefined && options.enabled === undefined);
                        this.readonly = schema.readonly = schema.readonly || options.readonly || (schema.readonly !== undefined && options.readonly !== undefined);
                        schema.forceCommit = options.forceCommit || schema.forceCommit;

                        viewClass.prototype.constructor.apply(this, arguments);
                        if (this.model) {
                            this.listenTo(this.model, 'change:' + this.key, this.updateValue);
                            this.listenTo(this.model, 'sync', this.updateValue);
                        }
                    },

                    updateValue: function () {
                        this.setValue(this.getModelValue());
                    },

                    getModelValue: function () {
                        return !this.model ? undefined : this.model.get(this.key);
                    },

                    __getFocusElement: function () {
                        if (this.focusElement) {
                            return this.$el.find(this.focusElement);
                        } else {
                            return this.$el;
                        }
                    },

                    __triggerChange: function () {
                        this.trigger.apply(this, [ 'change', this].concat(arguments));
                    },

                    /**
                     * Get the value for the form input 'name' attribute
                     *
                     * @return {String}
                     *
                     * @api private
                     */
                    getName: function() {
                        var key = this.key || '';

                        //Replace periods with underscores (e.g. for when using paths)
                        return key.replace(/\./g, '_');
                    },

                    /**
                     * Get editor value
                     * Extend and override this method to reflect changes in the DOM
                     *
                     * @return {Mixed}
                     */
                    getValue: function() {
                        return this.value;
                    },

                    /**
                     * Set editor value
                     * Extend and override this method to reflect changes in the DOM
                     *
                     * @param {Mixed} value
                     */
                    setValue: function(value) {
                        this.value = value;
                    },

                    setPermissions: function (enabled, readonly) {
                        this.__setEnabled(enabled);
                        this.__setReadonly(readonly);
                    },

                    setEnabled: function (enabled) {
                        var readonly = this.getReadonly();
                        this.setPermissions(enabled, readonly);
                    },

                    setReadonly: function (readonly) {
                        var enabled = this.getEnabled();
                        this.setPermissions(enabled, readonly);
                    },

                    __setEnabled: function (enabled) {
                        this.enabled = enabled;
                        this.trigger('enabled', enabled);
                        if (!this.enabled) {
                            this.$el.addClass(classes.disabled);
                        } else {
                            this.$el.removeClass(classes.disabled);
                        }
                    },

                    getEnabled: function () {
                        return this.enabled;
                    },

                    __setReadonly: function (readonly) {
                        this.readonly = readonly;
                        this.trigger('readonly', readonly);
                        if (this.readonly && this.getEnabled()) {
                            this.$el.addClass(classes.readonly);
                        } else {
                            this.$el.removeClass(classes.readonly);
                        }
                    },

                    getReadonly: function () {
                        return this.readonly;
                    },

                    /**
                     * Give the editor focus
                     * Extend and override this method
                     */
                    focus: function() {
                        if (this.hasFocus) {
                            return;
                        }
                        this.__getFocusElement().focus();
                    },

                    /**
                     * Remove focus from the editor
                     * Extend and override this method
                     */
                    blur: function() {
                        if (!this.hasFocus) {
                            return;
                        }
                        this.__getFocusElement().blur();
                    },

                    /**
                     * Update the model with the current value
                     *
                     * @param {Object} [options]              Options to pass to model.set()
                     * @param {Boolean} [options.validate]    Set to true to trigger built-in model validation
                     *
                     * @return {Mixed} error
                     */
                    commit: function(options) {
                        options = options || {};
                        var error = this.validate();
                        if (error && !this.schema.forceCommit) {
                            return error;
                        }

                        this.listenTo(this.model, 'invalid', function(model, e) {
                            error = e;
                        });

                        this.model.set(this.key, this.getValue(), {
                            silent: false,
                            validate: options.validate === true
                        });

                        if (error && !this.schema.forceCommit) {
                            return error;
                        }
                        this.trigger(this.key + ':committed', this, this.model, this.getValue());
                        this.trigger('value:committed', this, this.model, this.key, this.getValue());
                    },

                    /**
                     * Check validity
                     *
                     * @return {Object|Undefined}
                     */
                    validate: function() {
                        var $el = this.$el,
                            error = null,
                            value = this.getValue(),
                            formValues = this.form ? this.form.getValue() : {},
                            validators = this.validators,
                            getValidator = this.getValidator;

                        if (this.serverError) {
                            if (this.serverError.hasOwnProperty('type')) {
                                return this.serverError;
                            }
                        }

                        if (validators) {
                            //Run through validators until an error is found
                            _.every(validators, function(validator) {
                                error = getValidator(validator)(value, formValues);

                                return error ? false : true;
                            });
                        }

                        return error;
                    },

                    /**
                     * Set this.hasFocus, or call parent trigger()
                     *
                     * @param {String} event
                     */
                    trigger: function(event) {
                        if (event === 'focus') {
                            this.hasFocus = true;
                        }
                        else if (event === 'blur') {
                            this.hasFocus = false;
                        }

                        return Marionette.ItemView.prototype.trigger.apply(this, arguments);
                    },

                    /**
                     * Returns a validation function based on the type defined in the schema
                     *
                     * @param {RegExp|String|Function} validator
                     * @return {Function}
                     */
                    getValidator: function(validator) {
                        var validators = Backbone.Form.validators;

                        //Convert regular expressions to validators
                        if (_.isRegExp(validator)) {
                            return validators.regexp({ regexp: validator });
                        }

                        //Use a built-in validator if given a string
                        if (_.isString(validator)) {
                            if (!validators[validator]) {
                                throw new Error('Validator "' + validator + '" not found');
                            }

                            return validators[validator]();
                        }

                        //Functions can be used directly
                        if (_.isFunction(validator)) {
                            return validator;
                        }

                        //Use a customised built-in validator if given an object
                        //noinspection JSUnresolvedVariable
                        if (_.isObject(validator) && validator.type) {
                            var config = validator;

                            //noinspection JSUnresolvedVariable
                            return validators[config.type](config);
                        }

                        //Unknown validator type
                        throw new Error('Invalid validator: ' + validator);
                    }
                };
            }
        };
    });
<commit_msg>Review refactoring.<commit_after>/**
 * Developer: Stepan Burguchev
 * Date: 12/2/2014
 * Copyright: 2009-2014 Comindware®
 *       All Rights Reserved
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Comindware
 *       The copyright notice above does not evidence any
 *       actual or intended publication of such source code.
 */

/* global define, require, Handlebars, Backbone, Marionette, $, _ */

/*
*
* Marionette-based Backbone.Form editor. MUST NOT be used directly. Use EditorBase*View base views instead while implementing Marionette editors.
*
* */

define([
        'module/lib'
    ],
    function () {
        'use strict';

        var classes = {
            disabled: 'l-field_disabled',
            readonly: 'l-field_readonly'
        };

        var onFocus = function () {
            this.trigger('focus', this);
        };

        var onBlur = function () {
            this.trigger('blur', this);
        };

        var onRender = function () {
            this.$el.attr('id', this.id);
            this.$el.attr('name', this.getName());
            this.setPermissions(this.enabled, this.readonly);
            //noinspection JSUnresolvedVariable
            if (this.schema.editorClass) {
                //noinspection JSUnresolvedVariable
                this.$el.addClass(this.schema.editorClass);
            }
            if (this.schema.editorAttrs) {
                this.$el.attr(this.schema.editorAttrs);
            }
            this.setValue(this.value, true);
            if (this.focusElement) {
                this.$el.on('focus', this.focusElement, onFocus.bind(this));
                this.$el.on('blur', this.focusElement, onBlur.bind(this));
            } else {
                this.$el.on('focus', onFocus.bind(this));
                this.$el.on('blur', onBlur.bind(this));
            }
        };

        return {
            create: function(viewClass) {
                return {
                    defaultValue: null,

                    hasFocus: false,

                    constructor: function (options) {
                        options = options || {};

                        //Set initial value
                        if (options.model) {
                            if (!options.key) {
                                throw new Error("Missing option: 'key'");
                            }

                            this.model = options.model;
                            this.value = this.model.get(options.key);
                        }
                        else if (options.value !== undefined) {
                            this.value = options.value;
                        }

                        if (this.value === undefined) {
                            this.value = this.defaultValue;
                        }

                        //Store important data
                        _.extend(this, _.pick(options, 'key', 'form'));

                        var schema = this.schema = options.schema || {};

                        this.validators = options.validators || schema.validators;

                        this.on('render', onRender.bind(this));

                        schema.autocommit = schema.autocommit || options.autocommit;
                        if (schema.autocommit) {
                            this.on('change', this.commit.bind(this, {}));
                        }

                        this.enabled = schema.enabled = schema.enabled || options.enabled || (schema.enabled === undefined && options.enabled === undefined);
                        this.readonly = schema.readonly = schema.readonly || options.readonly || (schema.readonly !== undefined && options.readonly !== undefined);
                        schema.forceCommit = options.forceCommit || schema.forceCommit;

                        viewClass.prototype.constructor.apply(this, arguments);
                        if (this.model) {
                            this.listenTo(this.model, 'change:' + this.key, this.updateValue);
                            this.listenTo(this.model, 'sync', this.updateValue);
                        }
                    },

                    updateValue: function () {
                        this.setValue(this.getModelValue());
                    },

                    getModelValue: function () {
                        return !this.model ? undefined : this.model.get(this.key);
                    },

                    __getFocusElement: function () {
                        if (this.focusElement) {
                            return this.$el.find(this.focusElement);
                        } else {
                            return this.$el;
                        }
                    },

                    __triggerChange: function () {
                        this.trigger.apply(this, [ 'change', this].concat(arguments));
                    },

                    /**
                     * Get the value for the form input 'name' attribute
                     *
                     * @return {String}
                     *
                     * @api private
                     */
                    getName: function() {
                        var key = this.key || '';

                        //Replace periods with underscores (e.g. for when using paths)
                        return key.replace(/\./g, '_');
                    },

                    /**
                     * Get editor value
                     * Extend and override this method to reflect changes in the DOM
                     *
                     * @return {Mixed}
                     */
                    getValue: function() {
                        return this.value;
                    },

                    /**
                     * Set editor value
                     * Extend and override this method to reflect changes in the DOM
                     *
                     * @param {Mixed} value
                     */
                    setValue: function(value) {
                        this.value = value;
                    },

                    setPermissions: function (enabled, readonly) {
                        this.__setEnabled(enabled);
                        this.__setReadonly(readonly);
                    },

                    setEnabled: function (enabled) {
                        var readonly = this.getReadonly();
                        this.setPermissions(enabled, readonly);
                    },

                    setReadonly: function (readonly) {
                        var enabled = this.getEnabled();
                        this.setPermissions(enabled, readonly);
                    },

                    __setEnabled: function (enabled) {
                        this.enabled = enabled;
                        this.trigger('enabled', enabled);
                        if (!this.enabled) {
                            this.$el.addClass(classes.disabled);
                        } else {
                            this.$el.removeClass(classes.disabled);
                        }
                    },

                    getEnabled: function () {
                        return this.enabled;
                    },

                    __setReadonly: function (readonly) {
                        this.readonly = readonly;
                        this.trigger('readonly', readonly);
                        if (this.readonly && this.getEnabled()) {
                            this.$el.addClass(classes.readonly);
                        } else {
                            this.$el.removeClass(classes.readonly);
                        }
                    },

                    getReadonly: function () {
                        return this.readonly;
                    },

                    /**
                     * Give the editor focus
                     * Extend and override this method
                     */
                    focus: function() {
                        if (this.hasFocus) {
                            return;
                        }
                        this.__getFocusElement().focus();
                    },

                    /**
                     * Remove focus from the editor
                     * Extend and override this method
                     */
                    blur: function() {
                        if (!this.hasFocus) {
                            return;
                        }
                        this.__getFocusElement().blur();
                    },

                    /**
                     * Update the model with the current value
                     *
                     * @param {Object} [options]              Options to pass to model.set()
                     * @param {Boolean} [options.validate]    Set to true to trigger built-in model validation
                     *
                     * @return {Mixed} error
                     */
                    commit: function(options) {
                        options = options || {};
                        var error = this.validate();
                        if (error && !this.schema.forceCommit) {
                            return error;
                        }

                        this.listenTo(this.model, 'invalid', function(model, e) {
                            error = e;
                        });

                        this.model.set(this.key, this.getValue(), {
                            silent: false,
                            validate: options.validate === true
                        });

                        if (error && !this.schema.forceCommit) {
                            return error;
                        }
                        this.trigger(this.key + ':committed', this, this.model, this.getValue());
                        this.trigger('value:committed', this, this.model, this.key, this.getValue());
                    },

                    /**
                     * Check validity
                     *
                     * @return {Object|Undefined}
                     */
                    validate: function() {
                        var $el = this.$el,
                            error = null,
                            value = this.getValue(),
                            formValues = this.form ? this.form.getValue() : {},
                            validators = this.validators,
                            getValidator = this.getValidator;

                        if (validators) {
                            //Run through validators until an error is found
                            _.every(validators, function(validator) {
                                error = getValidator(validator)(value, formValues);

                                return error ? false : true;
                            });
                        }

                        return error;
                    },

                    /**
                     * Set this.hasFocus, or call parent trigger()
                     *
                     * @param {String} event
                     */
                    trigger: function(event) {
                        if (event === 'focus') {
                            this.hasFocus = true;
                        }
                        else if (event === 'blur') {
                            this.hasFocus = false;
                        }

                        return Marionette.ItemView.prototype.trigger.apply(this, arguments);
                    },

                    /**
                     * Returns a validation function based on the type defined in the schema
                     *
                     * @param {RegExp|String|Function} validator
                     * @return {Function}
                     */
                    getValidator: function(validator) {
                        var validators = Backbone.Form.validators;

                        //Convert regular expressions to validators
                        if (_.isRegExp(validator)) {
                            return validators.regexp({ regexp: validator });
                        }

                        //Use a built-in validator if given a string
                        if (_.isString(validator)) {
                            if (!validators[validator]) {
                                throw new Error('Validator "' + validator + '" not found');
                            }

                            return validators[validator]();
                        }

                        //Functions can be used directly
                        if (_.isFunction(validator)) {
                            return validator;
                        }

                        //Use a customised built-in validator if given an object
                        //noinspection JSUnresolvedVariable
                        if (_.isObject(validator) && validator.type) {
                            var config = validator;

                            //noinspection JSUnresolvedVariable
                            return validators[config.type](config);
                        }

                        //Unknown validator type
                        throw new Error('Invalid validator: ' + validator);
                    }
                };
            }
        };
    });
<|endoftext|>


<commit_before>/**
 * @tag models, home
 * Wraps backend med services.  Enables
 * [SmartMedDisplay.Models.Med.static.findAll retrieving],
 */
SmartMedDisplay.Models.rdfObject.
extend('SmartMedDisplay.Models.MedDetails',
/* @Static */
{
	getDetails : function(med) {

	var ret = [];

	var r = med.Class.rdf
	.where(this.nodename+" ?p ?o")
	.where("?o ?f_field ?f_detail");

	for (var i = 0; i < r.length; i++)
	{
	var field = r[i].f_field.value._string;
	var value = r[i].f_detail.type=="bnode"? "" : r[i].f_detail.value._string || r[i].f_detail.value
	ret.push([field, value]);
	}

	if (med.cui._string == "http://link.informatics.stonybrook.edu/rxnorm/RXCUI/00000")
		return ret;

	var s = "<"+med.cui._string+"> "
	var r = med.Class.rdf
	 .where(s+ " ?p ?o");
	for (var i = 0; i < r.length; i++)
	{
		var field  = r[i].p.value._string;
		var value = r[i].o.value._string || r[i].o.value;
		ret.push([field, value]);
	}

	return ret;
	}
},
/* @Prototype */
{

});<commit_msg>handle blank or uri med nodes<commit_after>/**
 * @tag models, home
 * Wraps backend med services.  Enables
 * [SmartMedDisplay.Models.Med.static.findAll retrieving],
 */
SmartMedDisplay.Models.rdfObject.
extend('SmartMedDisplay.Models.MedDetails',
/* @Static */
{
	getDetails : function(med) {

	var ret = [];

	var r = med.Class.rdf
	.where(med.nodename+" ?p ?o")
	.where("?o ?f_field ?f_detail");

	for (var i = 0; i < r.length; i++)
	{
	var field = r[i].f_field.value._string;
	var value = r[i].f_detail.type=="bnode"? "" : r[i].f_detail.value._string || r[i].f_detail.value
	ret.push([field, value]);
	}

	if (med.cui._string == "http://link.informatics.stonybrook.edu/rxnorm/RXCUI/00000")
		return ret;

	var s = "<"+med.cui._string+"> "
	var r = med.Class.rdf
	 .where(s+ " ?p ?o");
	for (var i = 0; i < r.length; i++)
	{
		var field  = r[i].p.value._string;
		var value = r[i].o.value._string || r[i].o.value;
		ret.push([field, value]);
	}

	return ret;
	}
},
/* @Prototype */
{

});<|endoftext|>


<commit_before>( function( $ ) {
	$( document )
		.ready( function() {
			$( ".clickable" )
				.click( function() {
					window.document.location = $( this )
						.data( "href" );
				} );

			$( "#updatecheck" )
				.click( function() {
					var checked = $( '#leader_radio input[type=radio]:checked' );
					if ( checked.size() > 0 ) {
						$( ".modal .modal-body" )
							.html( "
Your choice is " + checked.val() + ".
" );
						$( ".modal .modal-footer" )
							.html( "<button type='button' class='btn btn-default' data-dismiss='modal'>Reselect</button>" +
									'<input type="submit" class="btn btn-primary" form="leader_radio" name="change_leader" value="Confirm">' );
					} else {
						$( ".modal .modal-body" )
							.html( "
Please select one memeber as next club leader!
" );
						$( ".modal .modal-footer" )
							.html( "<button type='button' class='btn btn-default' data-dismiss='modal'>Close</button>" );
					}
				} );

			$( "#updatequit" )
				.click( function() {
					var selected = $( '.form-group select option:selected' );
					if ( selected.size() > 0 ) {
						$( ".modal .modal-body" )
							.html( "
Your choice is " + selected.text() + ".
" );
					} else {
						$( ".modal .modal-body" )
							.html( "
Please choose the club you want to quit.
" );
					}
				} );

			$( ".updatehm" )
				.click( function() {
					var date = $( "#date" ).val();
					var contents = $( "#contents" ).val();
					if ( date !== '' && contents !== '' ) {
						$( "#schedule tbody" )
							.append( "
" + date + "	" + contents + "	<button class='btn btn-primary' id='" + contents + "'>Delete</button>
");
						$( "#" + contents )
							.click( function() {$( this ).parents("tr").eq(0).remove();});
					}
				} );

			$( '.refresh' )
				.click( function() {
					location.reload();
				} );

			$( '.drag' )
				.draggable( {
					handle:'.drag-point',
					containment: '.homepage_image',
					stack: '.drag',
					revert: true
				} );

			$( '.edit a' )
				.click( function() {
					var parent = $(this).parents('td').eq(0);
					var content = parent.find('.content p').html();
					parent.find('.content').html('<input type="text" class="input_content" name="content" value="' + content + '">');
					parent.find('.content .input_content').focus();
					parent.find('.edit').html('<button class="btn btn-success check"></button>' +
						'<button class="btn btn-danger cross"></button>');
					parent.find('.edit .cross').bind('click', function() {
						var parent = $(this).parents('td').eq(0);
						var content = parent.find('.content input').value();
						parent.find('.content').html('
' + content + '
');
						parent.find('.edit').html('Edit');
					});
				} );

		} );
} )( jQuery );

var menuYloc = null;
	$(document).ready(function(){
		document.querySelector('#floatmenu').style.left = (window.innerWidth -75) + "px";
		document.querySelector('#floatmenu').style.top = (window.innerHeight -125) + "px";
		menuYloc = parseInt($('#floatmenu').css("top").substring(0,$('#floatmenu').css("top").indexOf("p")));
			$(window).scroll(function () {
				if(window.innerWidth<=500){
					document.querySelector('#floatmenu').style.top = menuYloc+$(document).scrollTop()+"px";
				}
			});
			$(window).resize(function () {
				if(window.innerWidth<=500){
					document.querySelector('#floatmenu').style.left = (window.innerWidth -75) + "px";
					document.querySelector('#floatmenu').style.top = (window.innerHeight -125) + "px";
				}
			});
	});<commit_msg>oclubs.js: modified<commit_after>( function( $ ) {
	$( document )
		.ready( function() {
			$( ".clickable" )
				.click( function() {
					window.document.location = $( this )
						.data( "href" );
				} );

			$( "#updatecheck" )
				.click( function() {
					var checked = $( '#leader_radio input[type=radio]:checked' );
					if ( checked.size() > 0 ) {
						$( ".modal .modal-body" )
							.html( "
Your choice is " + checked.val() + ".
" );
						$( ".modal .modal-footer" )
							.html( "<button type='button' class='btn btn-default' data-dismiss='modal'>Reselect</button>" +
									'<input type="submit" class="btn btn-primary" form="leader_radio" name="change_leader" value="Confirm">' );
					} else {
						$( ".modal .modal-body" )
							.html( "
Please select one memeber as next club leader!
" );
						$( ".modal .modal-footer" )
							.html( "<button type='button' class='btn btn-default' data-dismiss='modal'>Close</button>" );
					}
				} );

			$( "#updatequit" )
				.click( function() {
					var selected = $( '.form-group select option:selected' );
					if ( selected.size() > 0 ) {
						$( ".modal .modal-body" )
							.html( "
Your choice is " + selected.text() + ".
" );
					} else {
						$( ".modal .modal-body" )
							.html( "
Please choose the club you want to quit.
" );
					}
				} );

			$( ".updatehm" )
				.click( function() {
					var date = $( "#date" ).val();
					var contents = $( "#contents" ).val();
					if ( date !== '' && contents !== '' ) {
						$( "#schedule tbody" )
							.append( "
" + date + "	" + contents + "	<button class='btn btn-primary' id='" + contents + "'>Delete</button>
");
						$( "#" + contents )
							.click( function() {$( this ).parents("tr").eq(0).remove();});
					}
				} );

			$( '.refresh' )
				.click( function() {
					location.reload();
				} );

			$( '.drag' )
				.draggable( {
					handle:'.drag-point',
					containment: '.homepage_image',
					stack: '.drag',
					revert: true
				} );

			edit_user_info = function() {
				var item = $(this).parents('td').eq(0);
				var content = item.find('.content p').text();
				item.find('.content p').replaceWith($('<input type="text" class="input_content" name="content">').attr('value', content));
				item.find('.content .input_content').focus();
				item.find('.edit').empty()
					.append($('<button class="btn btn-success"></button>'))
					.append($('<button class="btn btn-danger"></button>'));

			};

			edit_user_info_undo = function() {
				var item = $(this).parents('td').eq(0);
				item.find('.content input').replaceWith($('
'));
				$('Edit').replaceAll(item.find('.edit button'));
			};

		} );
} )( jQuery );

var menuYloc = null;
	$(document).ready(function(){
		document.querySelector('#floatmenu').style.left = (window.innerWidth -75) + "px";
		document.querySelector('#floatmenu').style.top = (window.innerHeight -125) + "px";
		menuYloc = parseInt($('#floatmenu').css("top").substring(0,$('#floatmenu').css("top").indexOf("p")));
			$(window).scroll(function () {
				if(window.innerWidth<=500){
					document.querySelector('#floatmenu').style.top = menuYloc+$(document).scrollTop()+"px";
				}
			});
			$(window).resize(function () {
				if(window.innerWidth<=500){
					document.querySelector('#floatmenu').style.left = (window.innerWidth -75) + "px";
					document.querySelector('#floatmenu').style.top = (window.innerHeight -125) + "px";
				}
			});
	});<|endoftext|>


<commit_before>var http    = require('http'),
    express = require('express'),
    app     = express(),
    libxmljs= require('libxmljs');

var zwid = 'X1-ZWz1dp4jgzyih7_axb7v';

app.configure(function() {

    // simple logger
    app.use(function(req, res, next){
    	console.log('%s %s', req.method, req.url);
	    next();
    });

    app.use(express.compress());
    // app.use(express.cookieParser('xxx secret'));
    // app.use(express.cookieSession());
    // app.use(express.bodyParser());
    // app.use(app.router);

});

app.get('/propertySearch', function(req, client) {
	var ec = encodeURIComponent;
	var q = "?zws-id="+ec(zwid)+"&address="+ec(req.query.address)+
								"&citystatezip="+ec(req.query.citystatezip);
	var options = {
	  host: 'www.zillow.com',
	  path: '/webservice/GetSearchResults.htm' + q
	};

	var req = http.get(options, function(res) {
	  console.log('STATUS: ' + res.statusCode);
	  console.log('HEADERS: ' + JSON.stringify(res.headers));

	  // Buffer the body entirely for processing as a whole.
	  var bodyChunks = [];
	  res.on('data', function(chunk) {
	    // You can process streamed parts here...
	    bodyChunks.push(chunk);
	  }).on('end', function() {
	    var body = Buffer.concat(bodyChunks);
	    console.log('BODY: ' + body);

	    var xmlDoc = libxmljs.parseXml(body);
	    var out = JSON.stringify(xmlDoc);

	    client.status(200).set('Content-Type', 'text/html').send(out);

	    // ...and/or process the entire body here.
	  })
	});

	req.on('error', function(e) {
	  console.log('ERROR: ' + e.message);
	  client.status(200).set('Content-Type', 'text/html').send('fail');
	});
});

app.get('/propertyDetail', function(req, res) {
	var uri = "http://www.zillow.com/webservice/GetZestimate.htm?zws-id="+zwid+"&zpid="+req.query.zpid;

	http.get(encodeURIComponent(uri), function(res){
		console.log(res);
	    res.status(200).set('Content-Type', 'text/html').send('ok');
	});
});

var server = http.createServer(app);
server.listen(8080);
module.exports = server;

<commit_msg>udpates client output<commit_after>var http    = require('http'),
    express = require('express'),
    app     = express(),
    libxmljs= require('libxmljs');

var zwid = 'X1-ZWz1dp4jgzyih7_axb7v';

app.configure(function() {

    // simple logger
    app.use(function(req, res, next){
    	console.log('%s %s', req.method, req.url);
	    next();
    });

    app.use(express.compress());
    // app.use(express.cookieParser('xxx secret'));
    // app.use(express.cookieSession());
    // app.use(express.bodyParser());
    // app.use(app.router);

});

app.get('/propertySearch', function(req, client) {
	var ec = encodeURIComponent;
	var q = "?zws-id="+ec(zwid)+"&address="+ec(req.query.address)+
								"&citystatezip="+ec(req.query.citystatezip);
	var options = {
	  host: 'www.zillow.com',
	  path: '/webservice/GetSearchResults.htm' + q
	};

	var req = http.get(options, function(res) {
	  // console.log('STATUS: ' + res.statusCode);
	  // console.log('HEADERS: ' + JSON.stringify(res.headers));

	  // Buffer the body entirely for processing as a whole.
	  var bodyChunks = [];
	  res.on('data', function(chunk) {
	    // You can process streamed parts here...
	    bodyChunks.push(chunk);
	  }).on('end', function() {
	    var body = Buffer.concat(bodyChunks);
	    // console.log('BODY: ' + body);

	    var xmlDoc = libxmljs.parseXml(body);
	    var out = JSON.stringify(xmlDoc);

	    console.log(out);
	    client.status(200).set('Content-Type', 'text/html').send(out);

	    // ...and/or process the entire body here.
	  })
	});

	req.on('error', function(e) {
	  console.log('ERROR: ' + e.message);
	  client.status(200).set('Content-Type', 'text/html').send('fail');
	});
});

app.get('/propertyDetail', function(req, res) {
	var uri = "http://www.zillow.com/webservice/GetZestimate.htm?zws-id="+zwid+"&zpid="+req.query.zpid;

	http.get(encodeURIComponent(uri), function(res){
		console.log(res);
	    res.status(200).set('Content-Type', 'text/html').send('ok');
	});
});

var server = http.createServer(app);
server.listen(8080);
module.exports = server;

<|endoftext|>


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

*/

import globalstore from "./globalstore";
import keys from "./keys";
import base from "../base";
import PubSub from "PubSub";
import androidEventHandler from "./androidEventHandler";
const PSTOPIC="remote.";
export const COMMANDS={
    setPage:'CP', //str page
    key:'K', //str key
    setChart: 'CM', //json chartEntry
    setCenter: 'CC', //json lat,lon
    setZoom: 'CZ', //float zoom
    lock: 'CL', //str true|false
    courseUp: 'CU', //str true|false
    gpsNum: 'CN', //num number gpspage number
    addOn: 'CA' //the add on number
};
class RemoteChannel{
    constructor(props) {
        this.timerCall=this.timerCall.bind(this);
        this.timer=undefined;
        this.websocket=undefined;
        this.pubsub=new PubSub();
        this.channel=globalstore.getData(keys.properties.remoteChannelName,'0');
        this.channelChanged=this.channelChanged.bind(this);
        this.android=window.avnavAndroid;
        if (this.android){
            this.token=androidEventHandler.subscribe('remoteMessage',(ev)=>{
                window.setTimeout(()=>{
                    while (true) {
                        let msg = this.android.readChannelMessage(this.websocket);
                        if (msg) {
                            this.onMessage(msg);
                        }
                        else{
                            break;
                        }
                    }
                },0);
            })
            this.closeToken=androidEventHandler.subscribe('channelClose',(ev)=>{
               if (ev.id === this.websocket){
                   this.close();
               }
            });
        }
        this.id=0;
    }
    close(){
        if (this.websocket !== undefined){
            if (this.android){
                try{
                    this.android.channelClose(this.websocket);
                }catch (e){}
                this.websocket=undefined;
                return;
            }
            try{
                this.websocket.close();
            }catch (e){}
            this.websocket=undefined;
        }
    }
    channelChanged(){
       let nc=globalstore.getData(keys.properties.remoteChannelName,'0');
       if (nc !== this.channel){
           this.channel=nc;
           this.close();
           this.openWebSocket();
       }

    }
    timerCall(){
        if (this.websocket === undefined){
            this.openWebSocket();
        }
        else{
            if (!globalstore.getData(keys.gui.capabilities.remoteChannel)){
                this.close();
            }
        }
        globalstore.storeData(keys.gui.global.remoteChannelState,{
            connected: this.websocket !== undefined,
            channel: this.channel
        })
    }
    start(){
        if (window.WebSocket === undefined) return;
        globalstore.register(this.channelChanged,[keys.properties.remoteChannelName]);
        this.channel=globalstore.getData(keys.properties.remoteChannelName,'0');
        this.openWebSocket();
        this.timer=window.setInterval(this.timerCall,1000);
    }
    onMessage(data){
        base.log("message",data);
        if (! globalstore.getData(keys.properties.remoteChannelRead,false)) return;
        if (! globalstore.getData(keys.properties.connectedMode,false)) return;
        let parts=data.split(/  */);
        if (parts.length < 2) return;
        if (! parts[0] in COMMANDS) return;
        data=data.replace(/^[^ ]* */,'');
        window.setTimeout(()=> {
            this.pubsub.publish(PSTOPIC + parts[0], data);
        },0);
    }
    openWebSocket(){
        if (! globalstore.getData(keys.gui.capabilities.remoteChannel)) return;
        this.close();
        if (this.android){
            this.websocket=this.android.channelOpen("/remotechannels/"+this.channel);
            if (this.websocket < 0) this.websocket=undefined;
            return;
        }
        this.id++;
        let connectionId=this.id;
        let url='ws://'+window.location.host+
            "/remotechannels/"+this.channel;
        try{
            console.log("opening websocket to ",url);
            this.websocket=new WebSocket(url);
            this.websocket.addEventListener('message',(msg)=>{
                if (connectionId === this.id) {
                    this.onMessage(msg.data);
                }
            });
            this.websocket.addEventListener('close',()=>{
                console.log("websocket closed");
                if (connectionId !== this.id) {
                    return;
                }
                this.websocket = undefined;
            })
            this.websocket.addEventListener('error',()=>{
                console.log("websocket error");
                if (connectionId !== this.id){
                    return;
                }
                try{
                    this.websocket.close();
                }catch (e){}
                this.websocket=undefined;
            })
        }catch (e){
            base.log("error opening websocket channel")
        }
    }
    stop(){
        globalstore.deregister(this.channelChanged);
        if (this.timer !== undefined) {
            window.clearInterval(this.timer);
            this.timer=undefined;
        }
        this.close();
    }
    sendMessage(msg,param){
        if (! this.websocket) return;
        if (! globalstore.getData(keys.properties.remoteChannelWrite,false)) return;
        if (! globalstore.getData(keys.properties.connectedMode,false)) return;
        try {
            if (param !== undefined) msg+=" "+param;
            if (this.android){
                this.android.sendChannelMessage(this.websocket,msg);
            }
            else {
                this.websocket.send(msg);
            }
        }catch (e){

        }
    }
    sendJsonMessage(command,data){
        let p=JSON.stringify(data);
        this.sendMessage(command,p);
    }
    subscribe(type,callback){
        return this.pubsub.subscribe(PSTOPIC+type,callback);
    }
    unsubscribe(token){
        return this.pubsub.unsubscribe(token);
    }
}

export default new RemoteChannel()<commit_msg>get me out of dim mode when receiving a remote command<commit_after>/*
# vim: ts=2 sw=2 et
###############################################################################
# Copyright (c) 2014-2021, Andreas Vogel andreas@wellenvogel.net
#
#  Permission is hereby granted, free of charge, to any person obtaining a
#  copy of this software and associated documentation files (the "Software"),
#  to deal in the Software without restriction, including without limitation
#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
#  and/or sell copies of the Software, and to permit persons to whom the
#  Software is furnished to do so, subject to the following conditions:
    #
#  The above copyright notice and this permission notice shall be included
#  in all copies or substantial portions of the Software.
    #
#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#  DEALINGS IN THE SOFTWARE.
    ###############################################################################

*/

import globalstore from "./globalstore";
import keys from "./keys";
import base from "../base";
import PubSub from "PubSub";
import androidEventHandler from "./androidEventHandler";
import dimhandler from "./dimhandler";
const PSTOPIC="remote.";
export const COMMANDS={
    setPage:'CP', //str page
    key:'K', //str key
    setChart: 'CM', //json chartEntry
    setCenter: 'CC', //json lat,lon
    setZoom: 'CZ', //float zoom
    lock: 'CL', //str true|false
    courseUp: 'CU', //str true|false
    gpsNum: 'CN', //num number gpspage number
    addOn: 'CA' //the add on number
};
class RemoteChannel{
    constructor(props) {
        this.timerCall=this.timerCall.bind(this);
        this.timer=undefined;
        this.websocket=undefined;
        this.pubsub=new PubSub();
        this.channel=globalstore.getData(keys.properties.remoteChannelName,'0');
        this.channelChanged=this.channelChanged.bind(this);
        this.android=window.avnavAndroid;
        if (this.android){
            this.token=androidEventHandler.subscribe('remoteMessage',(ev)=>{
                window.setTimeout(()=>{
                    while (true) {
                        let msg = this.android.readChannelMessage(this.websocket);
                        if (msg) {
                            this.onMessage(msg);
                        }
                        else{
                            break;
                        }
                    }
                },0);
            })
            this.closeToken=androidEventHandler.subscribe('channelClose',(ev)=>{
               if (ev.id === this.websocket){
                   this.close();
               }
            });
        }
        this.id=0;
    }
    close(){
        if (this.websocket !== undefined){
            if (this.android){
                try{
                    this.android.channelClose(this.websocket);
                }catch (e){}
                this.websocket=undefined;
                return;
            }
            try{
                this.websocket.close();
            }catch (e){}
            this.websocket=undefined;
        }
    }
    channelChanged(){
       let nc=globalstore.getData(keys.properties.remoteChannelName,'0');
       if (nc !== this.channel){
           this.channel=nc;
           this.close();
           this.openWebSocket();
       }

    }
    timerCall(){
        if (this.websocket === undefined){
            this.openWebSocket();
        }
        else{
            if (!globalstore.getData(keys.gui.capabilities.remoteChannel)){
                this.close();
            }
        }
        globalstore.storeData(keys.gui.global.remoteChannelState,{
            connected: this.websocket !== undefined,
            channel: this.channel
        })
    }
    start(){
        if (window.WebSocket === undefined) return;
        globalstore.register(this.channelChanged,[keys.properties.remoteChannelName]);
        this.channel=globalstore.getData(keys.properties.remoteChannelName,'0');
        this.openWebSocket();
        this.timer=window.setInterval(this.timerCall,1000);
    }
    onMessage(data){
        base.log("message",data);
        if (! globalstore.getData(keys.properties.remoteChannelRead,false)) return;
        if (! globalstore.getData(keys.properties.connectedMode,false)) return;
        let parts=data.split(/  */);
        if (parts.length < 2) return;
        if (! parts[0] in COMMANDS) return;
        data=data.replace(/^[^ ]* */,'');
        window.setTimeout(()=> {
            dimhandler.trigger(); //get us out of dim mode
            this.pubsub.publish(PSTOPIC + parts[0], data);
        },0);
    }
    openWebSocket(){
        if (! globalstore.getData(keys.gui.capabilities.remoteChannel)) return;
        this.close();
        if (this.android){
            this.websocket=this.android.channelOpen("/remotechannels/"+this.channel);
            if (this.websocket < 0) this.websocket=undefined;
            return;
        }
        this.id++;
        let connectionId=this.id;
        let url='ws://'+window.location.host+
            "/remotechannels/"+this.channel;
        try{
            console.log("opening websocket to ",url);
            this.websocket=new WebSocket(url);
            this.websocket.addEventListener('message',(msg)=>{
                if (connectionId === this.id) {
                    this.onMessage(msg.data);
                }
            });
            this.websocket.addEventListener('close',()=>{
                console.log("websocket closed");
                if (connectionId !== this.id) {
                    return;
                }
                this.websocket = undefined;
            })
            this.websocket.addEventListener('error',()=>{
                console.log("websocket error");
                if (connectionId !== this.id){
                    return;
                }
                try{
                    this.websocket.close();
                }catch (e){}
                this.websocket=undefined;
            })
        }catch (e){
            base.log("error opening websocket channel")
        }
    }
    stop(){
        globalstore.deregister(this.channelChanged);
        if (this.timer !== undefined) {
            window.clearInterval(this.timer);
            this.timer=undefined;
        }
        this.close();
    }
    sendMessage(msg,param){
        if (! this.websocket) return;
        if (! globalstore.getData(keys.properties.remoteChannelWrite,false)) return;
        if (! globalstore.getData(keys.properties.connectedMode,false)) return;
        try {
            if (param !== undefined) msg+=" "+param;
            if (this.android){
                this.android.sendChannelMessage(this.websocket,msg);
            }
            else {
                this.websocket.send(msg);
            }
        }catch (e){

        }
    }
    sendJsonMessage(command,data){
        let p=JSON.stringify(data);
        this.sendMessage(command,p);
    }
    subscribe(type,callback){
        return this.pubsub.subscribe(PSTOPIC+type,callback);
    }
    unsubscribe(token){
        return this.pubsub.unsubscribe(token);
    }
}

export default new RemoteChannel()<|endoftext|>


<commit_before>var appConfig = require('./passport-config'),
    passport = require('passport'),
    passportOauth = require('passport-oauth'),
    OAuthStrategy = passportOauth.OAuthStrategy,
    OAuth2Strategy = passportOauth.OAuth2Strategy,
    request = require('request');

var passportPlugin = {};

var logins = [];
var users = [];

var hasApi = function(apiName) {
  return appConfig[apiName] != undefined;
};
passportPlugin.hasApi = hasApi;

var findUser = function(apiName,req) {

  if(req.session.user == undefined
     || logins[req.session.user.id] == undefined) {
    return undefined;
  }

  return users[logins[req.session.user.id][apiName]];
};
passportPlugin.findUser = findUser;

var init = function(app) {

  app.use(passport.initialize());
  app.use(passport.session());

  // store user in persistent storage for passport
  passport.serializeUser(function(user, done) {
    //console.log('serialize user ' + user._id);
    users[user._id] = user;

    if(logins[user._login] == undefined) {
      logins[user._login] = [];
      logins[user._login][user._api] = user._id;
    }
    else {
      logins[user._login][user._api] = user._id;
    }

    done(null, user._id);
});

  // retrieve user from persistent store for passport
  passport.deserializeUser(function(id, done) {
    //console.log('deserialize user ' + id);
    var user = users[id];
    done(null, user);
  });

  // load all app configs
  for(var apiName in appConfig) {
    console.log('register = ' + apiName);
    register(apiName);
  }

};
passportPlugin.init = init;

var register = function(apiName) {

   var strategyCallback = function(req, token, tokenSecret, profile, done) {
    var fakeUser = { 'token' : token,
                     'tokenSecret' : tokenSecret };
    var options =  { 'method' : 'GET',
                     'uri' : appConfig[apiName].defaultLoadUrl };
    var callback = function(user, data) {
      var fullUser = null;

      //var profileUser = appConfig[apiName].userElementName?data[appConfig[apiName].userElementName]:data;
      var profileUserId = null;
      if(data) {
        var userIdPath = appConfig[apiName].userIdPath.split('.');
        var profileUser = data;
        for(var i=0;i<userIdPath.length;i++) {
          if(i==userIdPath.length-1) {
            profileUserId = profileUser[userIdPath[i]];
          }
          else {
            profileUser = profileUser[userIdPath[i]];
          }
        }
      }

      if(profileUserId) {
        fullUser = {};
        fullUser.profile = data;
        fullUser._id = apiName + "~" + profileUserId;
        fullUser.token = fakeUser.token;
        fullUser.tokenSecret = fakeUser.tokenSecret;
        fullUser._login = req.session.user.id;
        fullUser._api = apiName;
      }
      done(null, fullUser);
    };
    handleRequest(apiName,fakeUser,options,callback);
  };

  if(appConfig[apiName].type == 'oauth-1.0') {
    // setup oauth1 through passport
    passport.use(apiName,
      new OAuthStrategy({
          userAuthorizationURL: appConfig[apiName].authorizationUrl,
          requestTokenURL: appConfig[apiName].requestTokenUrl,
          accessTokenURL: appConfig[apiName].accessTokenUrl,
          consumerKey: appConfig[apiName].clientId,
          consumerSecret: appConfig[apiName].clientSecret,
          callbackURL: appConfig[apiName].callbackUrl,
          passReqToCallback: true
      }, strategyCallback
    ));
  }
  else if(appConfig[apiName].type == 'oauth-2.0') {
    // setup oauth2 through passport
    passport.use(apiName,
      new OAuth2Strategy({
          authorizationURL: appConfig[apiName].authorizationUrl,
          tokenURL: appConfig[apiName].accessTokenUrl,
          clientID: appConfig[apiName].clientId,
          clientSecret: appConfig[apiName].clientSecret,
          callbackURL: appConfig[apiName].callbackUrl,
          passReqToCallback: true
      }, strategyCallback
    ));
  }
  else {
    console.log(apiName + " has unknown auth type of " + appConfig[apiName].type);
  }
};
passportPlugin.register = register;

// simplified request handling
var handleRequest = function(apiName, user, options, callback) {
  console.log('handling request to ' + options.uri);

  var _oauth = undefined;
  if(appConfig[apiName].type == 'oauth-1.0') {
    _oauth =passport._strategy(apiName)._oauth;
  }
  else if(appConfig[apiName].type == 'oauth-2.0') {
    _oauth =passport._strategy(apiName)._oauth2;
  }
  else {
    console.log('No request handling for ' + appConfig[apiName].type]);
    return;
  }

  _oauth.get(appConfig[apiName].baseUrl+options.uri, user.token, user.tokenSecret, function (error, body, response) {
    if(error) {
      console.log('handle request error ' + JSON.stringify(error));
      callback(user,null);
      return;
    }

    if (response.statusCode === 200) {
      //console.log("RESULT=" + body);
      callback(user,JSON.parse(body));
    } else {
      console.log('handle request error ' + response.statusCode);
      callback(user,response.statusCode);
    }
  });
};
passportPlugin.handleRequest = handleRequest;

var auth = function(apiName,streams) {
  //console.log('auth attempt');
  passport.authenticate(apiName)(streams.req,streams.res,streams.next);
}
passportPlugin.auth = auth;

var authCallback = function(apiName,urls,streams) {
  //console.log('authCallback attempt');
  passport.authenticate(apiName,
                          {
                            'successRedirect' : urls.successUrl,
                            'failureRedirect' : urls.failureUrl
                          }
                       )(streams.req,streams.res,streams.next);
}
passportPlugin.authCallback = authCallback;

module.exports = passportPlugin;
<commit_msg>fixed oauth2 request handling again<commit_after>var appConfig = require('./passport-config'),
    passport = require('passport'),
    passportOauth = require('passport-oauth'),
    OAuthStrategy = passportOauth.OAuthStrategy,
    OAuth2Strategy = passportOauth.OAuth2Strategy,
    request = require('request');

var passportPlugin = {};

var logins = [];
var users = [];

var hasApi = function(apiName) {
  return appConfig[apiName] != undefined;
};
passportPlugin.hasApi = hasApi;

var findUser = function(apiName,req) {

  if(req.session.user == undefined
     || logins[req.session.user.id] == undefined) {
    return undefined;
  }

  return users[logins[req.session.user.id][apiName]];
};
passportPlugin.findUser = findUser;

var init = function(app) {

  app.use(passport.initialize());
  app.use(passport.session());

  // store user in persistent storage for passport
  passport.serializeUser(function(user, done) {
    //console.log('serialize user ' + user._id);
    users[user._id] = user;

    if(logins[user._login] == undefined) {
      logins[user._login] = [];
      logins[user._login][user._api] = user._id;
    }
    else {
      logins[user._login][user._api] = user._id;
    }

    done(null, user._id);
});

  // retrieve user from persistent store for passport
  passport.deserializeUser(function(id, done) {
    //console.log('deserialize user ' + id);
    var user = users[id];
    done(null, user);
  });

  // load all app configs
  for(var apiName in appConfig) {
    console.log('register = ' + apiName);
    register(apiName);
  }

};
passportPlugin.init = init;

var register = function(apiName) {

   var strategyCallback = function(req, token, tokenSecret, profile, done) {
    var fakeUser = { 'token' : token,
                     'tokenSecret' : tokenSecret };
    var options =  { 'method' : 'GET',
                     'uri' : appConfig[apiName].defaultLoadUrl };
    var callback = function(user, data) {
      var fullUser = null;

      //var profileUser = appConfig[apiName].userElementName?data[appConfig[apiName].userElementName]:data;
      var profileUserId = null;
      if(data) {
        var userIdPath = appConfig[apiName].userIdPath.split('.');
        var profileUser = data;
        for(var i=0;i<userIdPath.length;i++) {
          if(i==userIdPath.length-1) {
            profileUserId = profileUser[userIdPath[i]];
          }
          else {
            profileUser = profileUser[userIdPath[i]];
          }
        }
      }

      if(profileUserId) {
        fullUser = {};
        fullUser.profile = data;
        fullUser._id = apiName + "~" + profileUserId;
        fullUser.token = fakeUser.token;
        fullUser.tokenSecret = fakeUser.tokenSecret;
        fullUser._login = req.session.user.id;
        fullUser._api = apiName;
      }
      done(null, fullUser);
    };
    handleRequest(apiName,fakeUser,options,callback);
  };

  if(appConfig[apiName].type == 'oauth-1.0') {
    // setup oauth1 through passport
    passport.use(apiName,
      new OAuthStrategy({
          userAuthorizationURL: appConfig[apiName].authorizationUrl,
          requestTokenURL: appConfig[apiName].requestTokenUrl,
          accessTokenURL: appConfig[apiName].accessTokenUrl,
          consumerKey: appConfig[apiName].clientId,
          consumerSecret: appConfig[apiName].clientSecret,
          callbackURL: appConfig[apiName].callbackUrl,
          passReqToCallback: true
      }, strategyCallback
    ));
  }
  else if(appConfig[apiName].type == 'oauth-2.0') {
    // setup oauth2 through passport
    passport.use(apiName,
      new OAuth2Strategy({
          authorizationURL: appConfig[apiName].authorizationUrl,
          tokenURL: appConfig[apiName].accessTokenUrl,
          clientID: appConfig[apiName].clientId,
          clientSecret: appConfig[apiName].clientSecret,
          callbackURL: appConfig[apiName].callbackUrl,
          passReqToCallback: true
      }, strategyCallback
    ));
  }
  else {
    console.log(apiName + " has unknown auth type of " + appConfig[apiName].type);
  }
};
passportPlugin.register = register;

// simplified request handling
var handleRequest = function(apiName, user, options, callback) {
  console.log('handling request to ' + options.uri);

  var _oauth = undefined;
  if(appConfig[apiName].type == 'oauth-1.0') {
    _oauth =passport._strategy(apiName)._oauth;
  }
  else if(appConfig[apiName].type == 'oauth-2.0') {
    _oauth =passport._strategy(apiName)._oauth2;
  }
  else {
    console.log('No request handling for ' + appConfig[apiName].type);
    return;
  }

  _oauth.get(appConfig[apiName].baseUrl+options.uri, user.token, user.tokenSecret, function (error, body, response) {
    if(error) {
      console.log('handle request error ' + JSON.stringify(error));
      callback(user,null);
      return;
    }

    if (response.statusCode === 200) {
      //console.log("RESULT=" + body);
      callback(user,JSON.parse(body));
    } else {
      console.log('handle request error ' + response.statusCode);
      callback(user,response.statusCode);
    }
  });
};
passportPlugin.handleRequest = handleRequest;

var auth = function(apiName,streams) {
  //console.log('auth attempt');
  passport.authenticate(apiName)(streams.req,streams.res,streams.next);
}
passportPlugin.auth = auth;

var authCallback = function(apiName,urls,streams) {
  //console.log('authCallback attempt');
  passport.authenticate(apiName,
                          {
                            'successRedirect' : urls.successUrl,
                            'failureRedirect' : urls.failureUrl
                          }
                       )(streams.req,streams.res,streams.next);
}
passportPlugin.authCallback = authCallback;

module.exports = passportPlugin;
<|endoftext|>


<commit_before>/* global Dropzone*/
import Ember from 'ember';

export default Ember.Component.extend({
  classNames: ['dropzone'],

  myDropzone: document.body || undefined,

  dropzoneOptions: null,

  // Configuration Options

  url: '#',
  withCredentials: null,
  method: null,
  parallelUploads: null,
  maxFilesize: null,
  filesizeBase: null,
  paramName: null,
  uploadMultiple: null,
  headers: null,
  addRemoveLinks: null,
  previewsContainer: null,
  clickable: null,
  maxThumbnailFilesize: null,
  thumbnailWidth: null,
  thumbnailHeight: null,
  maxFiles: null,
  createImageThumbnails: null,

  // resize: not available
  acceptedFiles: null,
  autoProcessQueue: null,
  forceFallback: null,
  previewTemplate: null,

  // Dropzone translations
  dictDefaultMessage: null,
  dictFallbackMessage: null,
  dictFallbackText: null,
  dictInvalidFileType: null,
  dictFileTooBig: null,
  dictResponseError: null,
  dictCancelUpload: null,
  dictCancelUploadConfirmation: null,
  dictRemoveFile: null,
  dictMaxFilesExceeded: null,

  // Bonus for full screen zones
  maxDropRegion: null,

  // Events

  // All of these receive the event as first parameter:
  drop: null,
  dragstart: null,
  dragend: null,
  dragenter: null,
  dragover: null,
  dragleave: null,

  // All of these receive the file as first parameter:
  addedfile: null,
  removedfile: null,
  thumbnail: null,
  error: null,
  processing: null,
  uploadprogress: null,
  sending: null,
  success: null,
  complete: null,
  canceled: null,
  maxfilesreached: null,
  maxfilesexceeded: null,

  // All of these receive a list of files as first parameter and are only called if the uploadMultiple option is true:
  processingmultiple: null,
  sendingmultiple: null,
  successmultiple: null,
  completemultiple: null,
  canceledmultiple: null,

  // Special events:
  totaluploadprogress: null,
  reset: null,
  queuecomplete: null,
  files: null,

  // Callback functions
  accept: null,

  setEvents() {
    let myDropzone = this.get('myDropzone');
    let events = {
      drop: this.drop,
      dragstart: this.dragstart,
      dragend: this.dragend,
      dragenter: this.dragenter,
      dragover: this.dragover,
      dragleave: this.dragleave,
      addedfile: this.addedfile,
      removedfile: this.removedfile,
      thumbnail: this.thumbnail,
      error: this.error,
      processing: this.processing,
      uploadprogress: this.uploadprogress,
      sending: this.sending,
      success: this.success,
      complete: this.complete,
      canceled: this.canceled,
      maxfilesreached: this.maxfilesreached,
      maxfilesexceeded: this.maxfilesexceeded,
      processingmultiple: this.processingmultiple,
      sendingmultiple: this.sendingmultiple,
      successmultiple: this.successmultiple,
      completemultiple: this.completemultiple,
      canceledmultiple: this.canceledmultiple,
      totaluploadprogress: this.totaluploadprogress,
      reset: this.reset,
      queuecomplete: this.queuecomplete,
      files: this.files,
      accept: this.accept,
    };

    for (let e in events) {
      if (events[e] !== null) {
        myDropzone.on(e, events[e]);
      }
    }
  },

  getDropzoneOptions() {
    let dropzoneOptions = {};
    let dropzoneConfig = {
      url: this.url,
      withCredentials: this.withCredentials,
      method: this.method,
      parallelUploads: this.parallelUploads,
      maxFilesize: this.maxFilesize,
      filesizeBase: this.filesizeBase,
      paramName: this.paramName,
      uploadMultiple: this.uploadMultiple,
      headers: this.headers,
      addRemoveLinks: this.addRemoveLinks,
      previewsContainer: this.previewsContainer,
      clickable: this.clickable,
      maxThumbnailFilesize: this.maxThumbnailFilesize,
      thumbnailWidth: this.thumbnailWidth,
      thumbnailHeight: this.thumbnailHeight,
      maxFiles: this.maxFiles,
      createImageThumbnails: this.createImageThumbnails,

      // resize: not available
      acceptedFiles: this.acceptedFiles,
      autoProcessQueue: this.autoProcessQueue,
      forceFallback: this.forceFallback,
      previewTemplate: this.previewTemplate,

      // Dropzone translations
      dictDefaultMessage: this.dictDefaultMessage,
      dictFallbackMessage: this.dictFallbackMessage,
      dictFallbackText: this.dictFallbackText,
      dictInvalidFileType: this.dictInvalidFileType,
      dictFileTooBig: this.dictFileTooBig,
      dictResponseError: this.dictResponseError,
      dictCancelUpload: this.dictCancelUpload,
      dictCancelUploadConfirmation: this.dictCancelUploadConfirmation,
      dictRemoveFile: this.dictRemoveFile,
      dictMaxFilesExceeded: this.dictMaxFilesExceeded,

      // Fix flickering dragging over child elements: https://github.com/enyo/dropzone/issues/438
      init: function() {
        this.dragEnteredEls = new Array();
      },
      dragenter: function(e) {
        this.dragEnteredEls.push(e.target);
        Ember.$(this.element).addClass('dz-drag-hover');
      },
      dragleave: function(e) {
        this.dragEnteredEls = $(this.dragEnteredEls).not(e.target);
        if (this.dragEnteredEls.length === 0) {
          Ember.$(this.element).removeClass('dz-drag-hover');
        }
      },
    };

    for (let option in dropzoneConfig) {
      let data = dropzoneConfig[option];
      if (data !== null) {
        dropzoneOptions[option] = data;
      } else if (option === 'thumbnailHeight' || option === 'thumbnailWidth') {
        dropzoneOptions[option] = data;
      }
    }

    this.set('dropzoneOptions', dropzoneOptions);
  },

  createDropzone(element) {
    let region = this.get('maxDropRegion') ? document.body : element;
    this.set('myDropzone', new Dropzone(region, this.dropzoneOptions));
  },

  destroyDropzone: Ember.on('willDestroyElement', function() {
    this.get('myDropzone').destroy();
  }),

  insertDropzone: Ember.on('didInsertElement', function() {
    let _this = this;
    this.getDropzoneOptions();
    Dropzone.autoDiscover = false;
    this.createDropzone(this.element);
    //make sure events are set before any files are added
    this.setEvents();

    //this condition requires a fully resolved array to work
    //will not work with model.get('files') as it returns promise not array hence length condition is failed
    if (this.files && this.files.length > 0) {
      this.files.map(function(file) {
        let dropfile = {
          name: file.get('name'),
          type: file.get('type'),
          size: file.get('size'),
          status: Dropzone.ADDED,
          //add support for id  in files object so that it can be access in addedFile,removedFile callbacks for files identified by id
          id: file.get('id')
        };
        let thumbnail = file.get('thumbnail');

        if (typeof (thumbnail) === 'string') {
          dropfile.thumbnail = thumbnail;
        }

        _this.myDropzone.emit('addedfile', dropfile);

        if (typeof (thumbnail) === 'string') {

          _this.myDropzone.emit('thumbnail', dropfile, thumbnail);
        }

        _this.myDropzone.emit('complete', dropfile);
        _this.myDropzone.files.push(file);
      });
    }

    return this.myDropzone;
  }),
});
<commit_msg>Fix jQuery dependency<commit_after>/* global Dropzone*/
import Ember from 'ember';

export default Ember.Component.extend({
  classNames: ['dropzone'],

  myDropzone: document.body || undefined,

  dropzoneOptions: null,

  // Configuration Options

  url: '#',
  withCredentials: null,
  method: null,
  parallelUploads: null,
  maxFilesize: null,
  filesizeBase: null,
  paramName: null,
  uploadMultiple: null,
  headers: null,
  addRemoveLinks: null,
  previewsContainer: null,
  clickable: null,
  maxThumbnailFilesize: null,
  thumbnailWidth: null,
  thumbnailHeight: null,
  maxFiles: null,
  createImageThumbnails: null,

  // resize: not available
  acceptedFiles: null,
  autoProcessQueue: null,
  forceFallback: null,
  previewTemplate: null,

  // Dropzone translations
  dictDefaultMessage: null,
  dictFallbackMessage: null,
  dictFallbackText: null,
  dictInvalidFileType: null,
  dictFileTooBig: null,
  dictResponseError: null,
  dictCancelUpload: null,
  dictCancelUploadConfirmation: null,
  dictRemoveFile: null,
  dictMaxFilesExceeded: null,

  // Bonus for full screen zones
  maxDropRegion: null,

  // Events

  // All of these receive the event as first parameter:
  drop: null,
  dragstart: null,
  dragend: null,
  dragenter: null,
  dragover: null,
  dragleave: null,

  // All of these receive the file as first parameter:
  addedfile: null,
  removedfile: null,
  thumbnail: null,
  error: null,
  processing: null,
  uploadprogress: null,
  sending: null,
  success: null,
  complete: null,
  canceled: null,
  maxfilesreached: null,
  maxfilesexceeded: null,

  // All of these receive a list of files as first parameter and are only called if the uploadMultiple option is true:
  processingmultiple: null,
  sendingmultiple: null,
  successmultiple: null,
  completemultiple: null,
  canceledmultiple: null,

  // Special events:
  totaluploadprogress: null,
  reset: null,
  queuecomplete: null,
  files: null,

  // Callback functions
  accept: null,

  setEvents() {
    let myDropzone = this.get('myDropzone');
    let events = {
      drop: this.drop,
      dragstart: this.dragstart,
      dragend: this.dragend,
      dragenter: this.dragenter,
      dragover: this.dragover,
      dragleave: this.dragleave,
      addedfile: this.addedfile,
      removedfile: this.removedfile,
      thumbnail: this.thumbnail,
      error: this.error,
      processing: this.processing,
      uploadprogress: this.uploadprogress,
      sending: this.sending,
      success: this.success,
      complete: this.complete,
      canceled: this.canceled,
      maxfilesreached: this.maxfilesreached,
      maxfilesexceeded: this.maxfilesexceeded,
      processingmultiple: this.processingmultiple,
      sendingmultiple: this.sendingmultiple,
      successmultiple: this.successmultiple,
      completemultiple: this.completemultiple,
      canceledmultiple: this.canceledmultiple,
      totaluploadprogress: this.totaluploadprogress,
      reset: this.reset,
      queuecomplete: this.queuecomplete,
      files: this.files,
      accept: this.accept,
    };

    for (let e in events) {
      if (events[e] !== null) {
        myDropzone.on(e, events[e]);
      }
    }
  },

  getDropzoneOptions() {
    let dropzoneOptions = {};
    let dropzoneConfig = {
      url: this.url,
      withCredentials: this.withCredentials,
      method: this.method,
      parallelUploads: this.parallelUploads,
      maxFilesize: this.maxFilesize,
      filesizeBase: this.filesizeBase,
      paramName: this.paramName,
      uploadMultiple: this.uploadMultiple,
      headers: this.headers,
      addRemoveLinks: this.addRemoveLinks,
      previewsContainer: this.previewsContainer,
      clickable: this.clickable,
      maxThumbnailFilesize: this.maxThumbnailFilesize,
      thumbnailWidth: this.thumbnailWidth,
      thumbnailHeight: this.thumbnailHeight,
      maxFiles: this.maxFiles,
      createImageThumbnails: this.createImageThumbnails,

      // resize: not available
      acceptedFiles: this.acceptedFiles,
      autoProcessQueue: this.autoProcessQueue,
      forceFallback: this.forceFallback,
      previewTemplate: this.previewTemplate,

      // Dropzone translations
      dictDefaultMessage: this.dictDefaultMessage,
      dictFallbackMessage: this.dictFallbackMessage,
      dictFallbackText: this.dictFallbackText,
      dictInvalidFileType: this.dictInvalidFileType,
      dictFileTooBig: this.dictFileTooBig,
      dictResponseError: this.dictResponseError,
      dictCancelUpload: this.dictCancelUpload,
      dictCancelUploadConfirmation: this.dictCancelUploadConfirmation,
      dictRemoveFile: this.dictRemoveFile,
      dictMaxFilesExceeded: this.dictMaxFilesExceeded,

      // Fix flickering dragging over child elements: https://github.com/enyo/dropzone/issues/438
      init: function() {
        this.dragEnteredEls = new Array();
      },
      dragenter: function(e) {
        this.dragEnteredEls.push(e.target);
        Ember.$(this.element).addClass('dz-drag-hover');
      },
      dragleave: function(e) {
        this.dragEnteredEls = Ember.$(this.dragEnteredEls).not(e.target);
        if (this.dragEnteredEls.length === 0) {
          Ember.$(this.element).removeClass('dz-drag-hover');
        }
      },
    };

    for (let option in dropzoneConfig) {
      let data = dropzoneConfig[option];
      if (data !== null) {
        dropzoneOptions[option] = data;
      } else if (option === 'thumbnailHeight' || option === 'thumbnailWidth') {
        dropzoneOptions[option] = data;
      }
    }

    this.set('dropzoneOptions', dropzoneOptions);
  },

  createDropzone(element) {
    let region = this.get('maxDropRegion') ? document.body : element;
    this.set('myDropzone', new Dropzone(region, this.dropzoneOptions));
  },

  destroyDropzone: Ember.on('willDestroyElement', function() {
    this.get('myDropzone').destroy();
  }),

  insertDropzone: Ember.on('didInsertElement', function() {
    let _this = this;
    this.getDropzoneOptions();
    Dropzone.autoDiscover = false;
    this.createDropzone(this.element);
    //make sure events are set before any files are added
    this.setEvents();

    //this condition requires a fully resolved array to work
    //will not work with model.get('files') as it returns promise not array hence length condition is failed
    if (this.files && this.files.length > 0) {
      this.files.map(function(file) {
        let dropfile = {
          name: file.get('name'),
          type: file.get('type'),
          size: file.get('size'),
          status: Dropzone.ADDED,
          //add support for id  in files object so that it can be access in addedFile,removedFile callbacks for files identified by id
          id: file.get('id')
        };
        let thumbnail = file.get('thumbnail');

        if (typeof (thumbnail) === 'string') {
          dropfile.thumbnail = thumbnail;
        }

        _this.myDropzone.emit('addedfile', dropfile);

        if (typeof (thumbnail) === 'string') {

          _this.myDropzone.emit('thumbnail', dropfile, thumbnail);
        }

        _this.myDropzone.emit('complete', dropfile);
        _this.myDropzone.files.push(file);
      });
    }

    return this.myDropzone;
  }),
});
<|endoftext|>


<commit_before>define(
    [
        'service/serviceBase'
    ],
    function (ServiceBase) {
      'use strict';

        function OntologyService() {
            ServiceBase.call(this);

            var toMemoize = [
                'propertiesByConceptId',
                'propertiesByRelationshipLabel',
                'conceptToConceptRelationships'
            ];

            var self = this;
            toMemoize.forEach(function(f) {
                self[f] = _.memoize(self[f].bind(self), self[f].memoizeHashFunction);
            });
            return this;
        }

        OntologyService.prototype = Object.create(ServiceBase.prototype);

        OntologyService.prototype.clearCaches = function () {
            cachedConcepts = null;
            cachedRelationships = null;
            cachedProperties = null;
        };

        var cachedConcepts;
        OntologyService.prototype.concepts = function (refresh, callback) {
            if (typeof refresh === 'function') {
                callback = refresh;
                refresh = false;
            }
            if (!callback) callback = function() { };

            if (!refresh && cachedConcepts) {
                cachedConcepts.done(function(v) {callback(null, v); });
                return cachedConcepts;
            }

            cachedConcepts = this._ajaxGet({
                url: 'ontology/concept'
            }).then(function(response) {
                var entityConcept = findConceptByTitle(response, 'entity');
                return {
                    tree: response,
                    entityConcept: entityConcept,
                    byId: buildConceptMapById(response, {}),
                    byTitle: flattenConcepts(entityConcept)
                };
            }).always(function(data) {callback(null, data); });

            return cachedConcepts;

            function findConceptByTitle(concept, title) {
                if (concept.title == title) {
                    return concept;
                }
                if (concept.children) {
                    for (var i = 0; i < concept.children.length; i++) {
                        var child = concept.children[i];
                        var c = findConceptByTitle(child, title);
                        if (c) {
                            return c;
                        }
                    }
                }
                return null;
            }

            function buildConceptMapById(concept, map, parentId) {
                map[concept.id] = concept;
                if (parentId) {
                    concept.parentId = parentId;
                }
                if (concept.children) {
                    for (var i = 0; i < concept.children.length; i++) {
                        buildConceptMapById(concept.children[i], map, concept.id);
                    }
                }
                return map;
            }

            function flattenConcepts(concept) {
                var childIdx, child, grandChildIdx;
                var flattenedConcepts = [];
                for (childIdx in concept.children) {
                    child = concept.children[childIdx];
                    if (concept.flattenedTitle) {
                        child.flattenedTitle = concept.flattenedTitle + "/" + child.title;
                        child.flattenedDisplayName = concept.flattenedDisplayName + "/" + child.displayName;
                    } else {
                        child.flattenedTitle = child.title;
                        child.flattenedDisplayName = child.displayName;
                    }
                    flattenedConcepts.push(child);
                    var grandChildren = flattenConcepts(child);
                    for (grandChildIdx in grandChildren) {
                        flattenedConcepts.push(grandChildren[grandChildIdx]);
                    }
                }
                return _.sortBy(flattenedConcepts, 'flattenedDisplayName');
            }
        };

        var cachedRelationships;
        OntologyService.prototype.relationships = function (refresh, callback) {
            if (typeof refresh === 'function') {
                callback = refresh;
                refresh = false;
            }
            if (!callback) callback = function() { };

            if (!refresh && cachedRelationships) {
                cachedRelationships.done(function(v) {callback(null, v); });
                return cachedRelationships;
            }

            cachedRelationships = this._ajaxGet({
                url: 'ontology/relationship'
            }).then(function(response) {
                return {
                    list: response.relationships,
                    byTitle: buildRelationshipsByTitle(response.relationships),
                    byId: buildRelationshipsById(response.relationships)
                };
            }).always(function(data) {callback(null, data); });

            return cachedRelationships;

            function buildRelationshipsByTitle(relationships) {
                var result = {};
                relationships.forEach(function (relationship) {
                    result[relationship.title] = relationship;
                });
                return result;
            }

            function buildRelationshipsById(relationships) {
                var result = {};
                relationships.forEach(function (relationship) {
                    result[relationship.id] = relationship;
                });
                return result;
            }
        };

        OntologyService.prototype.conceptToConceptRelationships = function(sourceConceptTypeId, destConceptTypeId) {
            return this._ajaxGet({
                url: 'ontology/relationship',
                data: {
                    sourceConceptTypeId: sourceConceptTypeId,
                    destConceptTypeId: destConceptTypeId
                }
            });
        };
        OntologyService.prototype.conceptToConceptRelationships.memoizeHashFunction = function(s,d) {
            return s+d;
        };

        var cachedProperties;
        OntologyService.prototype.properties = function (refresh, callback) {
            if (typeof refresh === 'function') {
                callback = refresh;
                refresh = false;
            }
            if (!callback) callback = function() { };

            if (!refresh && cachedProperties) {
                cachedProperties.done(function(v) {callback(null, v); });
                return cachedProperties;
            }

            cachedProperties = this._ajaxGet({
                url: 'ontology/property'
            }).then(function(response) {
                return {
                    list: response.properties,
                    byTitle: buildPropertiesByTitle(response.properties)
                };
            }).always(function(data) {callback(null, data); });

            return cachedProperties;
        };

        OntologyService.prototype.propertiesByConceptId = function (conceptId) {
            return this._ajaxGet({
                url: 'ontology/concept/' + conceptId + '/properties'
            }).then(function(response) {
                return {
                    list: response.properties,
                    byTitle: buildPropertiesByTitle(response.properties)
                };
            });
        };

        OntologyService.prototype.propertiesByRelationshipLabel = function (relationshipLabel) {
            return this._ajaxGet({
                url: 'ontology/' + relationshipLabel + '/properties'
            }).then(function(response) {
                return {
                    list: response.properties,
                    byTitle: buildPropertiesByTitle(response.properties)
                };
            });
        };

        function buildPropertiesByTitle(properties) {
            var result = {};
            properties.forEach(function (property) {
                result[property.title] = property;
            });
            return result;
        }

        return OntologyService;
    });

<commit_msg>Fix issue where caching certain ajax requests would also cache failures or aborts<commit_after>define(
    [
        'service/serviceBase'
    ],
    function (ServiceBase) {
      'use strict';

        var memoizedMap = {};

        function OntologyService() {
            ServiceBase.call(this);

            var toMemoize = [
                'propertiesByConceptId',
                'propertiesByRelationshipLabel',
                'conceptToConceptRelationships'
            ];

            var self = this;
            toMemoize.forEach(function(f) {
                var cachedFunction = self[f],
                    hashFunction = self[f].memoizeHashFunction;
                self[f] = function() {
                    var key = hashFunction.apply(self, arguments),
                        result = memoizedMap[key];

                    if (result && result.statusText != 'abort') {
                        return result;
                    }
                    result = cachedFunction.apply(self, arguments);
                    if (result.fail) {
                        result.fail(function() {
                            delete memoizedMap[key];
                        })
                    }
                    memoizedMap[key] = result;
                    return result;
                }
            });
            return this;
        }

        OntologyService.prototype = Object.create(ServiceBase.prototype);

        OntologyService.prototype.clearCaches = function () {
            cachedConcepts = null;
            cachedRelationships = null;
            cachedProperties = null;
        };

        var cachedConcepts;
        OntologyService.prototype.concepts = function (refresh, callback) {
            if (typeof refresh === 'function') {
                callback = refresh;
                refresh = false;
            }
            if (!callback) callback = function() { };

            if (!refresh && cachedConcepts) {
                cachedConcepts.done(function(v) {callback(null, v); });
                return cachedConcepts;
            }

            cachedConcepts = this._ajaxGet({
                url: 'ontology/concept'
            }).then(function(response) {
                var entityConcept = findConceptByTitle(response, 'entity');
                return {
                    tree: response,
                    entityConcept: entityConcept,
                    byId: buildConceptMapById(response, {}),
                    byTitle: flattenConcepts(entityConcept)
                };
            }).always(function(data) {callback(null, data); });

            return cachedConcepts;

            function findConceptByTitle(concept, title) {
                if (concept.title == title) {
                    return concept;
                }
                if (concept.children) {
                    for (var i = 0; i < concept.children.length; i++) {
                        var child = concept.children[i];
                        var c = findConceptByTitle(child, title);
                        if (c) {
                            return c;
                        }
                    }
                }
                return null;
            }

            function buildConceptMapById(concept, map, parentId) {
                map[concept.id] = concept;
                if (parentId) {
                    concept.parentId = parentId;
                }
                if (concept.children) {
                    for (var i = 0; i < concept.children.length; i++) {
                        buildConceptMapById(concept.children[i], map, concept.id);
                    }
                }
                return map;
            }

            function flattenConcepts(concept) {
                var childIdx, child, grandChildIdx;
                var flattenedConcepts = [];
                for (childIdx in concept.children) {
                    child = concept.children[childIdx];
                    if (concept.flattenedTitle) {
                        child.flattenedTitle = concept.flattenedTitle + "/" + child.title;
                        child.flattenedDisplayName = concept.flattenedDisplayName + "/" + child.displayName;
                    } else {
                        child.flattenedTitle = child.title;
                        child.flattenedDisplayName = child.displayName;
                    }
                    flattenedConcepts.push(child);
                    var grandChildren = flattenConcepts(child);
                    for (grandChildIdx in grandChildren) {
                        flattenedConcepts.push(grandChildren[grandChildIdx]);
                    }
                }
                return _.sortBy(flattenedConcepts, 'flattenedDisplayName');
            }
        };

        var cachedRelationships;
        OntologyService.prototype.relationships = function (refresh, callback) {
            if (typeof refresh === 'function') {
                callback = refresh;
                refresh = false;
            }
            if (!callback) callback = function() { };

            if (!refresh && cachedRelationships) {
                cachedRelationships.done(function(v) {callback(null, v); });
                return cachedRelationships;
            }

            cachedRelationships = this._ajaxGet({
                url: 'ontology/relationship'
            }).then(function(response) {
                return {
                    list: response.relationships,
                    byTitle: buildRelationshipsByTitle(response.relationships),
                    byId: buildRelationshipsById(response.relationships)
                };
            }).always(function(data) {callback(null, data); });

            return cachedRelationships;

            function buildRelationshipsByTitle(relationships) {
                var result = {};
                relationships.forEach(function (relationship) {
                    result[relationship.title] = relationship;
                });
                return result;
            }

            function buildRelationshipsById(relationships) {
                var result = {};
                relationships.forEach(function (relationship) {
                    result[relationship.id] = relationship;
                });
                return result;
            }
        };

        OntologyService.prototype.conceptToConceptRelationships = function(sourceConceptTypeId, destConceptTypeId) {
            return this._ajaxGet({
                url: 'ontology/relationship',
                data: {
                    sourceConceptTypeId: sourceConceptTypeId,
                    destConceptTypeId: destConceptTypeId
                }
            });
        };
        OntologyService.prototype.conceptToConceptRelationships.memoizeHashFunction = function(s,d) {
            return s+d;
        };

        var cachedProperties;
        OntologyService.prototype.properties = function (refresh, callback) {
            if (typeof refresh === 'function') {
                callback = refresh;
                refresh = false;
            }
            if (!callback) callback = function() { };

            if (!refresh && cachedProperties) {
                cachedProperties.done(function(v) {callback(null, v); });
                return cachedProperties;
            }

            cachedProperties = this._ajaxGet({
                url: 'ontology/property'
            }).then(function(response) {
                return {
                    list: response.properties,
                    byTitle: buildPropertiesByTitle(response.properties)
                };
            }).always(function(data) {callback(null, data); });

            return cachedProperties;
        };

        OntologyService.prototype.propertiesByConceptId = function (conceptId) {
            return this._ajaxGet({
                url: 'ontology/concept/' + conceptId + '/properties'
            }).then(function(response) {
                return {
                    list: response.properties,
                    byTitle: buildPropertiesByTitle(response.properties)
                };
            });
        };

        OntologyService.prototype.propertiesByRelationshipLabel = function (relationshipLabel) {
            return this._ajaxGet({
                url: 'ontology/' + relationshipLabel + '/properties'
            }).then(function(response) {
                return {
                    list: response.properties,
                    byTitle: buildPropertiesByTitle(response.properties)
                };
            });
        };

        function buildPropertiesByTitle(properties) {
            var result = {};
            properties.forEach(function (property) {
                result[property.title] = property;
            });
            return result;
        }

        return OntologyService;
    });

<|endoftext|>