<commit_before>const Effect = require('./Effect');

/**
 * Affect the volume of an effect chain.
 */
class VolumeEffect extends Effect {
    /**
     * Default value to set the Effect to when constructed and when clear'ed.
     * @const {number}
     */
    get DEFAULT_VALUE () {
        return 100;
    }

    /**
     * Return the name of the effect.
     * @type {string}
     */
    get name () {
        return 'volume';
    }

    /**
     * Initialize the Effect.
     * Effects start out uninitialized. Then initialize when they are first set
     * with some value.
     * @throws {Error} throws when left unimplemented
     */
    initialize () {
        this.inputNode = this.audioEngine.audioContext.createGain();
        this.outputNode = this.inputNode;

        this.initialized = true;
    }

    /**
     * Set the effects value.
     * @private
     * @param {number} value - new value to set effect to
     */
    _set (value) {
        this.value = value;

        const {gain} = this.outputNode;
        const {currentTime, DECAY_WAIT, DECAY_DURATION} = this.audioEngine;
        gain.setValueAtTime(gain.value, currentTime + DECAY_WAIT);
        gain.linearRampToValueAtTime(value / 100, currentTime + DECAY_WAIT + DECAY_DURATION);
    }

    /**
     * Clean up and disconnect audio nodes.
     */
    dispose () {
        if (!this.initialized) {
            return;
        }

        this.outputNode.disconnect();

        this.inputNode = null;
        this.outputNode = null;
        this.target = null;

        this.initialized = false;
    }
}

module.exports = VolumeEffect;
<commit_msg>Don't setValueAtTime in volume effect<commit_after>const Effect = require('./Effect');

/**
 * Affect the volume of an effect chain.
 */
class VolumeEffect extends Effect {
    /**
     * Default value to set the Effect to when constructed and when clear'ed.
     * @const {number}
     */
    get DEFAULT_VALUE () {
        return 100;
    }

    /**
     * Return the name of the effect.
     * @type {string}
     */
    get name () {
        return 'volume';
    }

    /**
     * Initialize the Effect.
     * Effects start out uninitialized. Then initialize when they are first set
     * with some value.
     * @throws {Error} throws when left unimplemented
     */
    initialize () {
        this.inputNode = this.audioEngine.audioContext.createGain();
        this.outputNode = this.inputNode;

        this.initialized = true;
    }

    /**
     * Set the effects value.
     * @private
     * @param {number} value - new value to set effect to
     */
    _set (value) {
        this.value = value;

        const {gain} = this.outputNode;
        const {currentTime, DECAY_WAIT, DECAY_DURATION} = this.audioEngine;
        gain.linearRampToValueAtTime(value / 100, currentTime + DECAY_WAIT + DECAY_DURATION);
    }

    /**
     * Clean up and disconnect audio nodes.
     */
    dispose () {
        if (!this.initialized) {
            return;
        }

        this.outputNode.disconnect();

        this.inputNode = null;
        this.outputNode = null;
        this.target = null;

        this.initialized = false;
    }
}

module.exports = VolumeEffect;
<|endoftext|>


<commit_before><commit_msg>make fillColor work<commit_after><|endoftext|>


<commit_before>/*!
 * Copyright (c) 2015-2019 Cisco Systems, Inc. See LICENSE file.
 */

import '@webex/internal-plugin-wdm';

import {registerInternalPlugin} from '@webex/webex-core';
import Metrics from './metrics';
import config from './config';

registerInternalPlugin('metrics', Metrics, {
  config
});

export {default} from './metrics';
export {config};
<commit_msg>refactor(internal-plugin-metrics): migrate to device<commit_after>/*!
 * Copyright (c) 2015-2019 Cisco Systems, Inc. See LICENSE file.
 */

import '@webex/internal-plugin-device';

import {registerInternalPlugin} from '@webex/webex-core';

import Metrics from './metrics';
import config from './config';

registerInternalPlugin('metrics', Metrics, {
  config
});

export {default} from './metrics';
export {config};
<|endoftext|>


<commit_before>/*!
 * jQuery UI Selectmenu @VERSION
 *
 * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Selectmenu
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.position.js
 *	jquery.ui.menu.js
 */
(function( $, undefined ) {

$.widget( "ui.selectmenu", {
	version: "@VERSION",
	defaultElement: "<select>",
	options: {
		dropdown: true,
		appendTo: "body",
		position: {
			my: "left top",
			at: "left bottom",
			collision: "none"
		},
		// callbacks
		open: null,
		focus: null,
		select: null,
		close: null,
		change: null
	},

	_create: function() {
		// get / make unique id
		var selectmenuId = this.element.attr( 'id' ) || 'ui-selectmenu-' + Math.random().toString( 16 ).slice( 2, 10 );

		// array of button and menu id's
		this.ids = { id: selectmenuId, button: selectmenuId + '-button', menu: selectmenuId + '-menu' };

		// catch click event of the label
		this._bind({
			'click':  function( event ) {
				this.button.focus();
				event.preventDefault();
			}
		});

		this._drawButton();
		this._bind( this.button, this._buttonEvents );
		this._hoverable( this.button );
		this._focusable( this.button );

		this._drawMenu();

		// document click closes menu
		this._bind( document, {
			click: function( event ) {
				if ( this.isOpen && !$( event.target ).closest( "li.ui-state-disabled, li.ui-selectmenu-optgroup, #" + this.ids.button ).length ) {
					this.close( event );
				}
			}
		});

		if ( this.options.disabled ) {
			this.disable();
		}
	},

	_drawButton: function() {
		var tabindex = this.element.attr( 'tabindex' );

		// hide original select tag
		this.element.hide();

		// create button
		this.button = $( '', {
			'class': 'ui-button ui-widget ui-state-default ui-corner-all',
			href: '#' + this.ids.id,
			tabindex: ( tabindex ? tabindex : this.options.disabled ? -1 : 0 ),
			id: this.ids.button,
			width: this.element.outerWidth(),
			role: 'combobox',
			'aria-expanded': false,
			'aria-autocomplete': 'list',
			'aria-owns': this.ids.menu,
			'aria-haspopup': true
		});

		this.button.prepend( $( '' ) );

		this.buttonText = $( '', {
				'class': 'ui-selectmenu-text' ,
				html: this.element.find( "option:selected" ).text() || ' '
			})
			.appendTo( this.button );

		// wrap and insert new button
		this.buttonWrap = $( '', {
				'class': 'ui-selectmenu-button'
			})
			.append( this.button )
			.insertAfter( this.element );
	},

	_drawMenu: function() {
		var that = this;

		// create menu portion, append to body
		this.menu = $( '
', {
			'aria-hidden': true,
			'aria-labelledby': this.ids.button,
			id: this.ids.menu
		});

		// wrap menu
		this.menuWrap = $( '
', {
				'class': 'ui-selectmenu-menu',
				width: ( this.options.dropdown ) ? this.button.outerWidth() : this.buttonText.width() + parseFloat( this.buttonText.css( "padding-left" ) ) || 0 + parseFloat( this.buttonText.css( "margin-left" ) ) || 0
			})
			.append( this.menu )
			.appendTo( this.options.appendTo );

		// init menu widget
		this.menu.menu({
			select: function( event, ui ) {
				var item = ui.item.data( "item.selectmenu" );

				that._select( item, event );

				if ( that.isOpen ) {
					event.preventDefault();
					that.close( event );
				}
			},
			focus: function( event, ui ) {
				var item = ui.item.data( "item.selectmenu" );

				if ( that.focus !== undefined ) {
					if ( item.index !== that.focus ) {
						that._trigger( "focus", event, { item: item } );
						if ( !that.isOpen ) {
							that._select( item, event );
						}
					}
				}
				that.focus = item.index;
			}
		})
		// change ARIA role
		.attr( 'role', 'listbox' );

		// change menu styles?
		if ( this.options.dropdown ) {
			this.menu.addClass( 'ui-corner-bottom' ).removeClass( 'ui-corner-all' );
		}

		// unbind uneeded Menu events
		this.menu.unbind ( "mouseleave.menu" );
		$( document ).unbind( "click.menu" );
	},

	refresh: function() {
		this.menu.empty();

		var options = this.element.find( 'option' );
		if ( options.length ) {
			this._readOptions( options );
			this._renderMenu( this.menu, this.items );

			this.menu.menu( "refresh" );
			this.menuItems = this.menu.find( "li" ).not( '.ui-selectmenu-optgroup' );

			// adjust ARIA
			this.menuItems.find( 'a' ).attr( 'role', 'option' );

			// select current item
			var item = this._getSelectedItem();
			this.menu.menu( "focus", null, item );
			this._setSelected( item.data( "item.selectmenu" ) );

			// set disabled state
			this._setOption( "disabled", this._getCreateOptions()[ 'disabled' ] );
		}
	},

	open: function( event ) {
		if ( !this.options.disabled ) {
			// make sure menu is refreshed on first init (needed at least for IE9)
			if ( this.isOpen === undefined ) {
				this.button.trigger( "focus" );
			}

			this.isOpen = true;
			this._toggleAttr();

			if ( this.items && !this.options.dropdown ) {
				var currentItem = this._getSelectedItem();
				// center current item
				if ( this.menu.outerHeight() < this.menu.prop( "scrollHeight" ) ) {
					this.menuWrap.css( "left" , -10000 );
					this.menu.scrollTop( this.menu.scrollTop() + currentItem.position().top - this.menu.outerHeight() / 2 + currentItem.outerHeight() / 2 );
					this.menuWrap.css( "left" , "auto" );
				}

				$.extend( this.options.position, {
					my: "left top",
					at: "left top",
					// calculate offset
					offset: "0 " + ( this.menu.offset().top  - currentItem.offset().top + ( this.button.outerHeight() - currentItem.outerHeight() ) / 2 )
				});
			}

			this.options.position.of = this.button;
			this.menuWrap
				.zIndex( this.element.zIndex() + 1 )
				.position( this.options.position );

			this._trigger( "open", event );
		}
	},

	close: function( event ) {
		if ( this.isOpen ) {
			this.isOpen = false;
			this._toggleAttr();
			this._trigger( "close", event );
		}
	},

	widget: function() {
		return this.button;
	},

	menuWidget: function() {
		return this.menu;
	},

	_renderMenu: function( ul, items ) {
		var that = this,
			currentOptgroup = "";

		$.each( items, function( index, item ) {
			if ( item.optgroup != currentOptgroup ) {
				$( '
', {
					'class': 'ui-selectmenu-optgroup' + ( item.element.parent( "optgroup" ).attr( "disabled" ) ? ' ui-state-disabled' : '' ),
					html: item.optgroup
				}).appendTo( ul );
				currentOptgroup = item.optgroup;
			}
			that._renderItem( ul, item );
		});
	},

	_renderItem: function( ul, item) {
		var li = $( "
" ).data( "item.selectmenu", item );
		if ( item.disabled ) {
			li.addClass( 'ui-state-disabled' );
		}
		li.append( $( "", {
				html: item.label,
				href: '#'
			})
		);

		return li.appendTo( ul );
	},

	_move: function( direction, event ) {
		if ( direction == "first" || direction == "last" ) {
			// set focus manually for first or last item
			this.menu.menu( "focus", event, this.menuItems[ direction ]() );
		} else {
			// move to and focus next or prev item
			this.menu.menu( direction, event );
		}
	},

	_getSelectedItem: function() {
		return this.menuItems.eq( this.element[ 0 ].selectedIndex );
	},

	_toggle: function( event ) {
		if ( this.isOpen ) {
			this.close( event );
		} else {
			this.open( event );
		}
	},

	_buttonEvents: {
		focus: function( event ) {
			// init Menu on first focus
			this.refresh();
			this.button.unbind( "focus." + this.widgetName );
		},
		click: function( event ) {
			this._toggle( event );
			event.preventDefault();
		},
		keydown: function( event ) {
			var prevDef = true;
			switch ( event.keyCode ) {
				case $.ui.keyCode.TAB:
				case $.ui.keyCode.ESCAPE:
					if ( this.isOpen ) {
						this.close( event );
					}
					prevDef = false;
					break;
				case $.ui.keyCode.ENTER:
					if ( this.isOpen ) {
						this.menu.menu( "select", event );
					}
					break;
				case $.ui.keyCode.UP:
					if ( event.altKey ) {
						this._toggle( event );
					} else {
						this._move( "previous", event );
					}
					break;
				case $.ui.keyCode.DOWN:
					if ( event.altKey ) {
						this._toggle( event );
					} else {
						this._move( "next", event );
					}
					break;
				case $.ui.keyCode.LEFT:
					this._move( "previous", event );
					break;
				case $.ui.keyCode.RIGHT:
					this._move( "next", event );
					break;
				case $.ui.keyCode.HOME:
				case $.ui.keyCode.PAGE_UP:
					this._move( "first", event );
					break;
				case $.ui.keyCode.END:
				case $.ui.keyCode.PAGE_DOWN:
					this._move( "last", event );
					break;
				default:
					this.menu.trigger( event );
					prevDef = false;
			}
			if ( prevDef ) {
				event.preventDefault();
			}
		}
	},

	_select: function( item, event ) {
		var oldIndex = this.element[ 0 ].selectedIndex;
		// change native select element
		this.element[ 0 ].selectedIndex = item.index;
		this._setSelected( item );
		this._trigger( "select", event, { item: item } );

		if ( item.index != oldIndex ) {
			this._trigger( "change", event, { item: item } );
		}
	},

	_setSelected: function( item ) {
		// update button text
		this.buttonText.html( item.label );
		// change ARIA attr
		this.menuItems.find( "a" ).attr( "aria-selected", false );
		this._getSelectedItem().find( "a" ).attr( "aria-selected", true );
	},

	_setOption: function( key, value ) {
		this._super( key, value );

		if ( key === "appendTo" ) {
			this.menuWrap.appendTo( $( value || "body", this.element[ 0 ].ownerDocument )[ 0 ] );
		}
		if ( key === "disabled" ) {
			this.menu.menu( "option", "disabled", value );
			if ( value ) {
				this.element.attr( "disabled", "disabled" );
				this.button.attr( "tabindex", -1 );
				this.close();
			} else {
				this.element.removeAttr( "disabled" );
				this.button.attr( "tabindex", 0 );
			}
		}
	},

	_toggleAttr: function(){
		if ( this.options.dropdown ) {
			this.button.toggleClass( 'ui-corner-top', this.isOpen ).toggleClass( 'ui-corner-all', !this.isOpen );
		}
		this.menuWrap.toggleClass( 'ui-selectmenu-open', this.isOpen );
		this.menu.attr("aria-hidden", !this.isOpen);
		this.button.attr("aria-expanded", this.isOpen);
	},

	_getCreateOptions: function() {
		return { disabled: !!this.element.attr( 'disabled' ) };
	},

	_readOptions: function( options ) {
		var data = [];
		$.each( options, function( index, item ) {
			var option = $( item ),
				optgroup = option.parent( "optgroup" );
			data.push({
				element: option,
				index: index,
				value: option.attr( 'value' ),
				label: option.text() || ' ',
				optgroup: optgroup.attr( "label" ) || false,
				disabled: optgroup.attr( "disabled" ) || option.attr( "disabled" )
			});
		});
		this.items = data;
	},

	_destroy: function() {
		this.menuWrap.remove();
		this.buttonWrap.remove();
		this.element.show();
	}
});

}( jQuery ));
<commit_msg>Selectmenu: small fixes for lint tests<commit_after>/*!
 * jQuery UI Selectmenu @VERSION
 *
 * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Selectmenu
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.position.js
 *	jquery.ui.menu.js
 */
(function( $, undefined ) {

$.widget( "ui.selectmenu", {
	version: "@VERSION",
	defaultElement: "<select>",
	options: {
		dropdown: true,
		appendTo: "body",
		position: {
			my: "left top",
			at: "left bottom",
			collision: "none"
		},
		// callbacks
		open: null,
		focus: null,
		select: null,
		close: null,
		change: null
	},

	_create: function() {
		// get / make unique id
		var selectmenuId = this.element.attr( 'id' ) || 'ui-selectmenu-' + Math.random().toString( 16 ).slice( 2, 10 );

		// array of button and menu id's
		this.ids = { id: selectmenuId, button: selectmenuId + '-button', menu: selectmenuId + '-menu' };

		// catch click event of the label
		this._bind({
			'click':  function( event ) {
				this.button.focus();
				event.preventDefault();
			}
		});

		this._drawButton();
		this._bind( this.button, this._buttonEvents );
		this._hoverable( this.button );
		this._focusable( this.button );

		this._drawMenu();

		// document click closes menu
		this._bind( document, {
			click: function( event ) {
				if ( this.isOpen && !$( event.target ).closest( "li.ui-state-disabled, li.ui-selectmenu-optgroup, #" + this.ids.button ).length ) {
					this.close( event );
				}
			}
		});

		if ( this.options.disabled ) {
			this.disable();
		}
	},

	_drawButton: function() {
		var tabindex = this.element.attr( 'tabindex' );

		// hide original select tag
		this.element.hide();

		// create button
		this.button = $( '', {
			'class': 'ui-button ui-widget ui-state-default ui-corner-all',
			href: '#' + this.ids.id,
			tabindex: ( tabindex ? tabindex : this.options.disabled ? -1 : 0 ),
			id: this.ids.button,
			width: this.element.outerWidth(),
			role: 'combobox',
			'aria-expanded': false,
			'aria-autocomplete': 'list',
			'aria-owns': this.ids.menu,
			'aria-haspopup': true
		});

		this.button.prepend( $( '' ) );

		this.buttonText = $( '', {
				'class': 'ui-selectmenu-text' ,
				html: this.element.find( "option:selected" ).text() || ' '
			})
			.appendTo( this.button );

		// wrap and insert new button
		this.buttonWrap = $( '', {
				'class': 'ui-selectmenu-button'
			})
			.append( this.button )
			.insertAfter( this.element );
	},

	_drawMenu: function() {
		var that = this;

		// create menu portion, append to body
		this.menu = $( '
', {
			'aria-hidden': true,
			'aria-labelledby': this.ids.button,
			id: this.ids.menu
		});

		// wrap menu
		this.menuWrap = $( '
', {
				'class': 'ui-selectmenu-menu',
				width: ( this.options.dropdown ) ? this.button.outerWidth() : this.buttonText.width() + parseFloat( this.buttonText.css( "padding-left" ) ) || 0 + parseFloat( this.buttonText.css( "margin-left" ) ) || 0
			})
			.append( this.menu )
			.appendTo( this.options.appendTo );

		// init menu widget
		this.menu.menu({
			select: function( event, ui ) {
				var item = ui.item.data( "item.selectmenu" );

				that._select( item, event );

				if ( that.isOpen ) {
					event.preventDefault();
					that.close( event );
				}
			},
			focus: function( event, ui ) {
				var item = ui.item.data( "item.selectmenu" );

				if ( that.focus !== undefined ) {
					if ( item.index !== that.focus ) {
						that._trigger( "focus", event, { item: item } );
						if ( !that.isOpen ) {
							that._select( item, event );
						}
					}
				}
				that.focus = item.index;
			}
		})
		// change ARIA role
		.attr( 'role', 'listbox' );

		// change menu styles?
		if ( this.options.dropdown ) {
			this.menu.addClass( 'ui-corner-bottom' ).removeClass( 'ui-corner-all' );
		}

		// unbind uneeded Menu events
		this.menu.unbind ( "mouseleave.menu" );
		$( document ).unbind( "click.menu" );
	},

	refresh: function() {
		this.menu.empty();

		var options = this.element.find( 'option' );
		if ( options.length ) {
			this._readOptions( options );
			this._renderMenu( this.menu, this.items );

			this.menu.menu( "refresh" );
			this.menuItems = this.menu.find( "li" ).not( '.ui-selectmenu-optgroup' );

			// adjust ARIA
			this.menuItems.find( 'a' ).attr( 'role', 'option' );

			// select current item
			var item = this._getSelectedItem();
			this.menu.menu( "focus", null, item );
			this._setSelected( item.data( "item.selectmenu" ) );

			// set disabled state
			this._setOption( "disabled", this._getCreateOptions().disabled );
		}
	},

	open: function( event ) {
		if ( !this.options.disabled ) {
			// make sure menu is refreshed on first init (needed at least for IE9)
			if ( this.isOpen === undefined ) {
				this.button.trigger( "focus" );
			}

			this.isOpen = true;
			this._toggleAttr();

			if ( this.items && !this.options.dropdown ) {
				var currentItem = this._getSelectedItem();
				// center current item
				if ( this.menu.outerHeight() < this.menu.prop( "scrollHeight" ) ) {
					this.menuWrap.css( "left" , -10000 );
					this.menu.scrollTop( this.menu.scrollTop() + currentItem.position().top - this.menu.outerHeight() / 2 + currentItem.outerHeight() / 2 );
					this.menuWrap.css( "left" , "auto" );
				}

				$.extend( this.options.position, {
					my: "left top",
					at: "left top",
					// calculate offset
					offset: "0 " + ( this.menu.offset().top  - currentItem.offset().top + ( this.button.outerHeight() - currentItem.outerHeight() ) / 2 )
				});
			}

			this.options.position.of = this.button;
			this.menuWrap
				.zIndex( this.element.zIndex() + 1 )
				.position( this.options.position );

			this._trigger( "open", event );
		}
	},

	close: function( event ) {
		if ( this.isOpen ) {
			this.isOpen = false;
			this._toggleAttr();
			this._trigger( "close", event );
		}
	},

	widget: function() {
		return this.button;
	},

	menuWidget: function() {
		return this.menu;
	},

	_renderMenu: function( ul, items ) {
		var that = this,
			currentOptgroup = "";

		$.each( items, function( index, item ) {
			if ( item.optgroup != currentOptgroup ) {
				$( '
', {
					'class': 'ui-selectmenu-optgroup' + ( item.element.parent( "optgroup" ).attr( "disabled" ) ? ' ui-state-disabled' : '' ),
					html: item.optgroup
				}).appendTo( ul );
				currentOptgroup = item.optgroup;
			}
			that._renderItem( ul, item );
		});
	},

	_renderItem: function( ul, item) {
		var li = $( "
" ).data( "item.selectmenu", item );
		if ( item.disabled ) {
			li.addClass( 'ui-state-disabled' );
		}
		li.append( $( "", {
				html: item.label,
				href: '#'
			})
		);

		return li.appendTo( ul );
	},

	_move: function( direction, event ) {
		if ( direction === "first" || direction === "last" ) {
			// set focus manually for first or last item
			this.menu.menu( "focus", event, this.menuItems[ direction ]() );
		} else {
			// move to and focus next or prev item
			this.menu.menu( direction, event );
		}
	},

	_getSelectedItem: function() {
		return this.menuItems.eq( this.element[ 0 ].selectedIndex );
	},

	_toggle: function( event ) {
		if ( this.isOpen ) {
			this.close( event );
		} else {
			this.open( event );
		}
	},

	_buttonEvents: {
		focus: function( event ) {
			// init Menu on first focus
			this.refresh();
			this.button.unbind( "focus." + this.widgetName );
		},
		click: function( event ) {
			this._toggle( event );
			event.preventDefault();
		},
		keydown: function( event ) {
			var prevDef = true;
			switch ( event.keyCode ) {
				case $.ui.keyCode.TAB:
				case $.ui.keyCode.ESCAPE:
					if ( this.isOpen ) {
						this.close( event );
					}
					prevDef = false;
					break;
				case $.ui.keyCode.ENTER:
					if ( this.isOpen ) {
						this.menu.menu( "select", event );
					}
					break;
				case $.ui.keyCode.UP:
					if ( event.altKey ) {
						this._toggle( event );
					} else {
						this._move( "previous", event );
					}
					break;
				case $.ui.keyCode.DOWN:
					if ( event.altKey ) {
						this._toggle( event );
					} else {
						this._move( "next", event );
					}
					break;
				case $.ui.keyCode.LEFT:
					this._move( "previous", event );
					break;
				case $.ui.keyCode.RIGHT:
					this._move( "next", event );
					break;
				case $.ui.keyCode.HOME:
				case $.ui.keyCode.PAGE_UP:
					this._move( "first", event );
					break;
				case $.ui.keyCode.END:
				case $.ui.keyCode.PAGE_DOWN:
					this._move( "last", event );
					break;
				default:
					this.menu.trigger( event );
					prevDef = false;
			}
			if ( prevDef ) {
				event.preventDefault();
			}
		}
	},

	_select: function( item, event ) {
		var oldIndex = this.element[ 0 ].selectedIndex;
		// change native select element
		this.element[ 0 ].selectedIndex = item.index;
		this._setSelected( item );
		this._trigger( "select", event, { item: item } );

		if ( item.index !== oldIndex ) {
			this._trigger( "change", event, { item: item } );
		}
	},

	_setSelected: function( item ) {
		// update button text
		this.buttonText.html( item.label );
		// change ARIA attr
		this.menuItems.find( "a" ).attr( "aria-selected", false );
		this._getSelectedItem().find( "a" ).attr( "aria-selected", true );
	},

	_setOption: function( key, value ) {
		this._super( key, value );

		if ( key === "appendTo" ) {
			this.menuWrap.appendTo( $( value || "body", this.element[ 0 ].ownerDocument )[ 0 ] );
		}
		if ( key === "disabled" ) {
			this.menu.menu( "option", "disabled", value );
			if ( value ) {
				this.element.attr( "disabled", "disabled" );
				this.button.attr( "tabindex", -1 );
				this.close();
			} else {
				this.element.removeAttr( "disabled" );
				this.button.attr( "tabindex", 0 );
			}
		}
	},

	_toggleAttr: function(){
		if ( this.options.dropdown ) {
			this.button.toggleClass( 'ui-corner-top', this.isOpen ).toggleClass( 'ui-corner-all', !this.isOpen );
		}
		this.menuWrap.toggleClass( 'ui-selectmenu-open', this.isOpen );
		this.menu.attr("aria-hidden", !this.isOpen);
		this.button.attr("aria-expanded", this.isOpen);
	},

	_getCreateOptions: function() {
		return { disabled: !!this.element.attr( 'disabled' ) };
	},

	_readOptions: function( options ) {
		var data = [];
		$.each( options, function( index, item ) {
			var option = $( item ),
				optgroup = option.parent( "optgroup" );
			data.push({
				element: option,
				index: index,
				value: option.attr( 'value' ),
				label: option.text() || ' ',
				optgroup: optgroup.attr( "label" ) || false,
				disabled: optgroup.attr( "disabled" ) || option.attr( "disabled" )
			});
		});
		this.items = data;
	},

	_destroy: function() {
		this.menuWrap.remove();
		this.buttonWrap.remove();
		this.element.show();
	}
});

}( jQuery ));
<|endoftext|>


<commit_before>"use strict";
var colors = require("colors");
var readline = require('readline');
var Promise = require('bluebird');
var REPL = readline.createInterface(process.stdin, process.stdout);
var core = require("./chat_modules/core");

var properties = {
    say: {
        domain: {
            description: colors.magenta("Chat Domain (abbreviated)"),
            pattern: /^[mse|so|se]/i,
            message: "Please enter either ".bold.red +
                "MSE".bold.white +
                ", ".bold.red + "SO".bold.white +
                " or ".bold.red + "SE".bold.white +
                " as an abbreviated chat domain".bold.red
        },
        "room_id": {
            description: colors.magenta("Room ID"),
            pattern: /^[0-9]+$/,
            message: colors.red("Room ID must be only numbers")
        },
        message: {
            description: colors.magenta("The message")
        }
    },
    edit: {
        domain: {
            description: colors.magenta("Chat Domain (abbreviated)"),
            pattern: /[mse|so|se]/i,
            message: "Please enter either ".bold.red +
                "MSE".bold.white +
                ", ".bold.red + "SO".bold.white +
                " or ".bold.red + "SE".bold.white +
                " as an abbreviated chat domain".bold.red
        },
        "message_id": {
            description: colors.magenta("Message ID"),
            pattern: /^[0-9]+$/,
            message: colors.red("Message ID must be only numbers")
        },
        message: {
            description: colors.magenta("The message")
        }
    },
    join: {
        domain: {
            description: colors.magenta("Chat Domain (abbreviated)"),
            pattern: /[mse|so|se]/i,
            message: "Please enter either ".bold.red +
                "MSE".bold.white +
                ", ".bold.red + "SO".bold.white +
                " or ".bold.red + "SE".bold.white +
                "as an abbreviated chat domain".bold.red
        },
        "room_id": {
            description: colors.magenta("Room ID"),
            pattern: /^[0-9]+$/,
            message: colors.bold.red("Room ID must be only numbers")
        }
    },
    pingable: {
        domain: {
            description: colors.magenta("Chat Domain (abbreviated)"),
            pattern: /[mse|so|se]/i,
            message: "Please enter either ".bold.red +
                "MSE".bold.white +
                ", ".bold.red + "SO".bold.white +
                " or ".bold.red + "SE".bold.white +
                "as an abbreviated chat domain".bold.red
        },
        "room_id": {
            description: colors.magenta("Room ID"),
            pattern: /^[0-9]+$/,
            message: colors.bold.red("Room ID must be only numbers")
        }
    },
    star: {
        domain: {
            description: colors.magenta("Chat Domain (abbreviated)"),
            pattern: /[mse|so|se]/i,
            message: "Please enter either ".bold.red +
                "MSE".bold.white +
                ", ".bold.red + "SO".bold.white +
                " or ".bold.red + "SE".bold.white +
                "as an abbreviated chat domain".bold.red
        },
        "message_id": {
            description: "Message id",
            pattern: /^[0-9]+$/,
            message: colors.bold.red("Message ID must be only numbers")
        }
    },
    commands: {
        command: {
            description: "Command name (do /help for a list of commands)",
            message: colors.bold.red(
                "Command unrecognised. " +
                "If this command shows up in /help, " +
                "please leave an issue on the GitHub repo"
            )
        }
    }
};
properties.leave = properties.join;
properties.delete = properties.star;

var formattedCommandInstructions = [
    "/help".bold.white + " to get a list of commands".yellow,
    "/say".bold.white + " to send a message".yellow,
    "/join".bold.white + " to join a room".yellow,
    "/leave".bold.white + " to leave a room".yellow,
    "/star".bold.white + " to star a message".yellow,
    "/delete".bold.white + " to delete a message".yellow,
    "/edit".bold.white + " to edit a message".yellow
];
var commands = {
    say: function(chatDomainUnfixed, roomId, message) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.send(chatDomain, roomId, message);
    },
    join: function(chatDomainUnfixed, roomId) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.join(chatDomain, roomId);
    },
    star: function(chatDomainUnfixed, messageId) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.star(chatDomain, messageId);
    },
    edit: function(chatDomainUnfixed, messageId, message) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.edit(chatDomain, message_id, message);
    },
    delete: function(chatDomainUnfixed, messageId) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.delete(chatDomain, messageId);
    },
    leave: function(chatDomainUnfixed, roomId) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.leave(chatDomain, roomId);
    },
    pingable: function(chatDomainUnfixed, roomId) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.pingable(chatDomain, roomId).then(function(response){
            try {
                var users = JSON.parse(response).map(function(user){
                    console.log(user[1]);
                });
            } catch (e) {
                return false;
            }

        });
    }
};

var handleInput = function(STDIN){
    var input = STDIN.replace('/', '');
    var storedValues = {};
    var previousPromise = Promise.resolve();
    if (Object.keys(properties).indexOf(input) !== -1){
        var commandPropertyPromises = [];
        Object.keys(properties[input]).map(function(subCommandName){
            var subCommand = properties[input][subCommandName];
            previousPromise = previousPromise.then(function(){
                return new Promise(function(resolve, reject){
                    REPL.question(subCommand.description + '> '.green.bold, function(response){
                        if (response.match(subCommand.pattern) != null){
                            storedValues[subCommandName] = response;
                            resolve(response);
                        } else {
                            console.log(subCommand.message);
                            reject(response);
                        }
                    });
                });
            });
        });
        previousPromise.then(function(){
            // The null needs to be used here so the scope of the function isn't defined.
            // Read here for more info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
            commands[input].apply(null, Object.keys(storedValues).map(function(valueName){
                return storedValues[valueName];
            }));
        });
    } else {
        switch (input) {
            case "help":
                formattedCommandInstructions.forEach(function(commandInstruction) {
                    console.log(commandInstruction);
                });
                break;
            default:
                console.log(
                    colors.bold.red(
                        "Command unrecognised. " +
                        "If this command shows up in /help, " +
                        "please leave an issue on the GitHub repo"
                    )
                );
        }
    }
    return new Promise(function(resolve){
        resolve()
    });
}

var start = function(){
    REPL.prompt();

    REPL.on('line', function(STDIN) {
        handleInput(STDIN).then(function(){
            REPL.prompt();
        });
    })
    .on('close', function(){ process.exit(0) });
}
// From here: http://stackoverflow.com/a/24519813/3296811
var fixedPrint = function(type, args) {
    var indent = Math.ceil((REPL.line.length + 3) / process.stdout.columns);
    var text = require('util').format.apply(console, args);
    REPL.output.write("\n\x1B[" + indent + "A\x1B[0J"); // No idea at all....
    REPL.output.write(text + "\n");
    REPL.output.write(Array(indent).join("\n\x1B[E"));
    REPL._refreshLine();
};

console.log = function() {
    fixedPrint("log", arguments);
};
console.warn = function() {
    fixedPrint("warn", arguments);
};
console.info = function() {
    fixedPrint("info", arguments);
};
console.error = function() {
    fixedPrint("error", arguments);
};
var HTMLtoMarkdown = function(string){
    if (string.indexOf('<') !== -1){
        var dom = cheerio.load(string);
        var post = dom(".ob-post-title");
        if (post != null){
            return "[" + post.text + "](" + post.attr("href") + ")";
        }
        post = dom(".ob-image a");
        if (post != null){
            return "![" + post.attr('alt') + "](" + post.attr("href") + ")";
        }
    }
    return string;
}
var messageFormatting = {
    room: function(event) {
        return colors.green("[") +
            colors.bold.white(event.room_id) +
            colors.green(": ") +
            colors.bold.white(event.room_name) +
            colors.green("]");
    },
    user: function(event) {
        return colors.bold.yellow(event.user_name);
    },
    activity: function(string) {
        return colors.blue(string);
    },
    content: function(event) {
        return colors.green(HTMLtoMarkdown(event.content));
    },
    edited: function(event) {
        var maxStringLength = 25;
        var editedStringLength = Math.ceil(maxStringLength / 2);
        return colors.green(event.content.length > maxStringLength ? event.content.substring(0, editedStringLength) + "..." : event.content);
    },
    changedRoomName: function(event) {
        var name = event.content.substring(0, event.content.lastIndexOf(" /"));
        return colors.green("[") +
            colors.bold.white(event.room_id) +
            colors.green(": ") +
            colors.bold.white(name) +
            colors.green("]");
    },
    messageId: function(event) {
        return colors.green(event.message_id);
    },
    connection: function(event) {
        return colors.green("Connecting to ") + colors.bold.white(event.name);
    },
};
core.setMessageFormatting(messageFormatting);
module.exports = {
    properties: properties,
    commands: commands,
    start: start
};
<commit_msg>Fixed pingable<commit_after>"use strict";
var colors = require("colors");
var cheerio = require("cheerio");
var readline = require('readline');
var Promise = require('bluebird');
var REPL = readline.createInterface(process.stdin, process.stdout);
var core = require("./chat_modules/core");

var properties = {
    say: {
        domain: {
            description: colors.magenta("Chat Domain (abbreviated)"),
            pattern: /^[mse|so|se]/i,
            message: "Please enter either ".bold.red +
                "MSE".bold.white +
                ", ".bold.red + "SO".bold.white +
                " or ".bold.red + "SE".bold.white +
                " as an abbreviated chat domain".bold.red
        },
        "room_id": {
            description: colors.magenta("Room ID"),
            pattern: /^[0-9]+$/,
            message: colors.red("Room ID must be only numbers")
        },
        message: {
            description: colors.magenta("The message")
        }
    },
    edit: {
        domain: {
            description: colors.magenta("Chat Domain (abbreviated)"),
            pattern: /[mse|so|se]/i,
            message: "Please enter either ".bold.red +
                "MSE".bold.white +
                ", ".bold.red + "SO".bold.white +
                " or ".bold.red + "SE".bold.white +
                " as an abbreviated chat domain".bold.red
        },
        "message_id": {
            description: colors.magenta("Message ID"),
            pattern: /^[0-9]+$/,
            message: colors.red("Message ID must be only numbers")
        },
        message: {
            description: colors.magenta("The message")
        }
    },
    join: {
        domain: {
            description: colors.magenta("Chat Domain (abbreviated)"),
            pattern: /[mse|so|se]/i,
            message: "Please enter either ".bold.red +
                "MSE".bold.white +
                ", ".bold.red + "SO".bold.white +
                " or ".bold.red + "SE".bold.white +
                "as an abbreviated chat domain".bold.red
        },
        "room_id": {
            description: colors.magenta("Room ID"),
            pattern: /^[0-9]+$/,
            message: colors.bold.red("Room ID must be only numbers")
        }
    },
    pingable: {
        domain: {
            description: colors.magenta("Chat Domain (abbreviated)"),
            pattern: /[mse|so|se]/i,
            message: "Please enter either ".bold.red +
                "MSE".bold.white +
                ", ".bold.red + "SO".bold.white +
                " or ".bold.red + "SE".bold.white +
                "as an abbreviated chat domain".bold.red
        },
        "room_id": {
            description: colors.magenta("Room ID"),
            pattern: /^[0-9]+$/,
            message: colors.bold.red("Room ID must be only numbers")
        }
    },
    star: {
        domain: {
            description: colors.magenta("Chat Domain (abbreviated)"),
            pattern: /[mse|so|se]/i,
            message: "Please enter either ".bold.red +
                "MSE".bold.white +
                ", ".bold.red + "SO".bold.white +
                " or ".bold.red + "SE".bold.white +
                "as an abbreviated chat domain".bold.red
        },
        "message_id": {
            description: "Message id",
            pattern: /^[0-9]+$/,
            message: colors.bold.red("Message ID must be only numbers")
        }
    },
    commands: {
        command: {
            description: "Command name (do /help for a list of commands)",
            message: colors.bold.red(
                "Command unrecognised. " +
                "If this command shows up in /help, " +
                "please leave an issue on the GitHub repo"
            )
        }
    }
};
properties.leave = properties.join;
properties.delete = properties.star;

var formattedCommandInstructions = [
    "/help".bold.white + " to get a list of commands".yellow,
    "/say".bold.white + " to send a message".yellow,
    "/join".bold.white + " to join a room".yellow,
    "/leave".bold.white + " to leave a room".yellow,
    "/star".bold.white + " to star a message".yellow,
    "/delete".bold.white + " to delete a message".yellow,
    "/edit".bold.white + " to edit a message".yellow
];
var commands = {
    say: function(chatDomainUnfixed, roomId, message) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.send(chatDomain, roomId, message);
    },
    join: function(chatDomainUnfixed, roomId) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.join(chatDomain, roomId);
    },
    star: function(chatDomainUnfixed, messageId) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.star(chatDomain, messageId);
    },
    edit: function(chatDomainUnfixed, messageId, message) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.edit(chatDomain, message_id, message);
    },
    delete: function(chatDomainUnfixed, messageId) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.delete(chatDomain, messageId);
    },
    leave: function(chatDomainUnfixed, roomId) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.leave(chatDomain, roomId);
    },
    pingable: function(chatDomainUnfixed, roomId) {
        var chatDomain = core.chatAbbreviationToFull(chatDomainUnfixed);
        core.actions.pingable(chatDomain, roomId).then(function(response){
            try {
                var rows = [];
                var currentRow = [];
                var users = JSON.parse(response.body).map(function(user){
                    var name = user[1];
                    if (currentRow.length !== 6){
                        currentRow.push(name);
                    } else {
                        rows.push(currentRow);
                        currentRow = [name];
                    }
                });
                console.log('Current users are: ');
                rows.forEach(function(row){
                    console.log(row.join(', '));
                });
            } catch (e) {
                return false;
            }

        });
    }
};

var handleInput = function(STDIN){
    var input = STDIN.replace('/', '');
    var storedValues = {};
    var previousPromise = Promise.resolve();
    if (Object.keys(properties).indexOf(input) !== -1){
        var commandPropertyPromises = [];
        Object.keys(properties[input]).map(function(subCommandName){
            var subCommand = properties[input][subCommandName];
            previousPromise = previousPromise.then(function(){
                return new Promise(function(resolve, reject){
                    REPL.question(subCommand.description + '> '.green.bold, function(response){
                        if (response.match(subCommand.pattern) != null){
                            storedValues[subCommandName] = response;
                            resolve(response);
                        } else {
                            console.log(subCommand.message);
                            reject(response);
                        }
                    });
                });
            });
        });
        previousPromise.then(function(){
            // The null needs to be used here so the scope of the function isn't defined.
            // Read here for more info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
            commands[input].apply(null, Object.keys(storedValues).map(function(valueName){
                return storedValues[valueName];
            }));
        });
    } else {
        switch (input) {
            case "help":
                formattedCommandInstructions.forEach(function(commandInstruction) {
                    console.log(commandInstruction);
                });
                break;
            default:
                console.log(
                    colors.bold.red(
                        "Command unrecognised. " +
                        "If this command shows up in /help, " +
                        "please leave an issue on the GitHub repo"
                    )
                );
        }
    }
    return new Promise(function(resolve){
        resolve()
    });
}

var start = function(){
    REPL.prompt();

    REPL.on('line', function(STDIN) {
        handleInput(STDIN).then(function(){
            REPL.prompt();
        });
    })
    .on('close', function(){ process.exit(0) });
}
// From here: http://stackoverflow.com/a/24519813/3296811
var fixedPrint = function(type, args) {
    var indent = Math.ceil((REPL.line.length + 3) / process.stdout.columns);
    var text = require('util').format.apply(console, args);
    REPL.output.write("\n\x1B[" + indent + "A\x1B[0J"); // No idea at all....
    REPL.output.write(text + "\n");
    REPL.output.write(Array(indent).join("\n\x1B[E"));
    REPL._refreshLine();
};

console.log = function() {
    fixedPrint("log", arguments);
};
console.warn = function() {
    fixedPrint("warn", arguments);
};
console.info = function() {
    fixedPrint("info", arguments);
};
console.error = function() {
    fixedPrint("error", arguments);
};
var HTMLtoMarkdown = function(string){
    if (string.indexOf('<') !== -1){
        var dom = cheerio.load(string);
        var post = dom(".ob-post-title");
        if (post != null){
            return "[" + post.text + "](" + post.attr("href") + ")";
        }
        post = dom(".ob-image a");
        if (post != null){
            return "![" + post.attr('alt') + "](" + post.attr("href") + ")";
        }
    }
    return string;
}
var messageFormatting = {
    room: function(event) {
        return colors.green("[") +
            colors.bold.white(event.room_id) +
            colors.green(": ") +
            colors.bold.white(event.room_name) +
            colors.green("]");
    },
    user: function(event) {
        return colors.bold.yellow(event.user_name);
    },
    activity: function(string) {
        return colors.blue(string);
    },
    content: function(event) {
        return colors.green(HTMLtoMarkdown(event.content));
    },
    edited: function(event) {
        var maxStringLength = 25;
        var editedStringLength = Math.ceil(maxStringLength / 2);
        return colors.green(event.content.length > maxStringLength ? event.content.substring(0, editedStringLength) + "..." : event.content);
    },
    changedRoomName: function(event) {
        var name = event.content.substring(0, event.content.lastIndexOf(" /"));
        return colors.green("[") +
            colors.bold.white(event.room_id) +
            colors.green(": ") +
            colors.bold.white(name) +
            colors.green("]");
    },
    messageId: function(event) {
        return colors.green(event.message_id);
    },
    connection: function(event) {
        return colors.green("Connecting to ") + colors.bold.white(event.name);
    },
};
core.setMessageFormatting(messageFormatting);
module.exports = {
    properties: properties,
    commands: commands,
    start: start
};
<|endoftext|>


<commit_before>import classNames from 'classnames';
import React from 'react';

import FormGroupHeadingContent from './FormGroupHeadingContent';

function getChildren(children, required) {
  if (!required) {
    return children;
  }

  // We add the required field indicator after the first child.
  return React.Children.toArray(children).reduce(
    function (accumulator, child, index) {
      accumulator.push(child);

      if (index === 0) {
        accumulator.push(
          <FormGroupHeadingContent
            className="text-danger"
            key={`${index}-asterisk`}>
            *
          </FormGroupHeadingContent>
        );
      }

      return accumulator;
    },
    []
  );
}

function FormGroupHeading({className, children, required}) {
  const classes = classNames('form-group-heading', className);

  return (

      {getChildren(children, required)}

  );
}

FormGroupHeading.defaultProps = {
  required: false
};

FormGroupHeading.propTypes = {
  children: React.PropTypes.node.isRequired,
  className: React.PropTypes.oneOfType([
    React.PropTypes.array,
    React.PropTypes.object,
    React.PropTypes.string
  ]),
  required: React.PropTypes.bool
};

module.exports = FormGroupHeading;
<commit_msg>Adjust child modification logic<commit_after>import classNames from 'classnames';
import React from 'react';

import FormGroupHeadingContent from './FormGroupHeadingContent';

function getModifiedChildren(children) {
  const asteriskNode = (
    <FormGroupHeadingContent className="text-danger" key="asterisk">
      *
    </FormGroupHeadingContent>
  );
  const nextChildren = React.Children.toArray(children);

  nextChildren.splice(1, 0, asteriskNode);

  return nextChildren;
}

function FormGroupHeading({className, children, required}) {
  const classes = classNames('form-group-heading', className);

  return (

      {required ? getModifiedChildren(children) : children}

  );
}

FormGroupHeading.defaultProps = {
  required: false
};

FormGroupHeading.propTypes = {
  children: React.PropTypes.node.isRequired,
  className: React.PropTypes.oneOfType([
    React.PropTypes.array,
    React.PropTypes.object,
    React.PropTypes.string
  ]),
  required: React.PropTypes.bool
};

module.exports = FormGroupHeading;
<|endoftext|>


<commit_before>/**
 * @constructor
 */
function ContextMenu() {
  if (ContextMenu._instance)
  {
    return ContextMenu._instance;
  }
  ContextMenu._instance = this;

  /**
   * All registered context menus.
   */
  this._registered_menus = {};
  this._current_items = null;

  this._broker = ActionBroker.get_instance();

  /**
   * Registers a new context menu.
   *
   * @param {String} menu_id An id corresponding to an id specified with a data-menu
   *                         attribute in the markup. May be an already existing
   *                         menu, in which case the items are added.
   * @param {Array} item_list An array of objects with 'label' and 'handler'
   *                          (function). Optionally it may have 'checked' (boolean)
   *                          for showing a checkbox before the item, or 'selected'
   *                          (boolean) for showing the selected item in a group.
   */
  this.register = function(menu_id, item_list, extend)
  {
    if (item_list)
    {
      if (this._registered_menus[menu_id] && extend)
      {
        item_list.extend(this._registered_menus[menu_id]);
      }
      this._registered_menus[menu_id] = item_list;
    }
  };

  /**
   * Global context menu event handler.
   */
  this.oncontextmenu = function(event)
  {

    var parents = [];
    var cur = event.target;
    while (cur)
      parents.push(cur = cur.parentNode);

    // Hide the currently visible context menu, if any
    this.dismiss();

    Tooltips.handle_contextmenu_event(event);

    CstSelectBase.close_opened_select();

    if (/*!window.getSelection().isCollapsed ||*/ event.shiftKey) // Shift key overrides for debugging
    {
      return;
    }

    // Prevent the normal context menu from showing up
    event.preventDefault();

    var ele = event.target;
    // The previous calls could have removed the event.target from the DOM.
    // In this case we re-dispatch the event if any element in
    // the parent node chain is still in the DOM.
    // (It would be better to get the new target with elementFromPoint
    //  but that is currently broken in XML documents.)
    if (!document.documentElement.contains(ele))
    {
      var new_target = null;
      while (new_target = parents.shift())
      {
        if (document.documentElement.contains(new_target))
          break;
      }

      if (new_target)
      {
        var new_event = document.createEvent("MouseEvent");
        new_event.initMouseEvent(event.type,
                                 event.bubbles,
                                 event.cancelable,
                                 event.view,
                                 event.detail,
                                 event.screenX,
                                 event.screenY,
                                 event.clientX,
                                 event.clientY,
                                 event.ctrlKey,
                                 event.altKey,
                                 event.shiftKey,
                                 event.metaKey,
                                 event.button,
                                 event.relatedTarget);
        new_target.dispatchEvent(new_event);
      }
      return;
    }

    var all_items = [];
    var menu_id = null;
    var last_found_menu_id = '';
    var collected_menus = [];
    var items = null;
    // This traverses up the tree and collects all menus it finds, and
    // concatenates them with a separator between each menu. It stops if it
    // finds a data-menu attribute with a blank value.
    while (ele && ele != document && (menu_id = ele.getAttribute("data-menu")) !== "")
    {
      items = null;
      if (menu_id)
      {
        last_found_menu_id = menu_id;
      }
      // Make sure the same menu is never collected twice
      if (collected_menus.indexOf(menu_id) == -1) {
        collected_menus.push(menu_id);

        var items = this._registered_menus[menu_id];
        if (items && items.length)
        {
          if (all_items.length)
          {
            all_items.push(ContextMenu.separator);
          }

          all_items = all_items.concat(this._expand_all_items(items, event, menu_id));
        }
      }
      ele = ele.parentNode;
    }

    // This should preferably not be done inside ContextMenu.
    var spec = event.target.get_attr("parent-node-chain", "data-spec");
    if (spec)
    {
      var speclinks = SpecLinks.get_instance();
      var specs = speclinks.get_spec_links(spec);
      if (specs.length)
      {
        items = specs.map(function(spec)
        {
          return {
            label: ui_strings.M_CONTEXTMENU_SPEC_LINK.replace("%s", spec.prop),
            handler: function(event, target) {
              speclinks.open_spec_link(spec.url);
            },
            id: spec.prop,
            menu_id: "spec"
          };
        });
        this.register("spec", items);

        if (all_items.length)
        {
          all_items.push(ContextMenu.separator);
        }
      }

      if (items)
      {
        all_items = all_items.concat(items);
      }
    }

    var res_id_or_url = event.target.get_attr("parent-node-chain", "data-resource-id") ||
                        event.target.get_attr("parent-node-chain", "data-resource-url");
    var line_number = event.target.get_attr('parent-node-chain', 'data-resource-line-number');
    if (res_id_or_url)
    {
      if (last_found_menu_id == "dom")
      {
        var rt_id = event.target.get_attr('parent-node-chain', 'rt-id');
        res_id_or_url = helpers.resolveURLS(runtimes.getURI(rt_id), res_id_or_url);
      }
      var broker = cls.ResourceDisplayBroker.get_instance();
      var rid = parseInt(res_id_or_url, 10);
      if (rid)
      {
        // data-resource-line-number
        var fun = function()
        {
          broker.show_resource_for_id(rid, line_number);
        }
      }
      else
      {
        var fun = function()
        {
          broker.show_resource_for_url(res_id_or_url, line_number);
        }
      }

      if (all_items.length)
      {
        all_items.push(ContextMenu.separator);
      }

      all_items.push(
        {
          label: ui_strings.M_CONTEXTMENU_SHOW_RESOURCE,
          handler: fun,
          id: res_id_or_url,
          menu_id: "resource"
        }
      )
    }

    this._current_items = all_items;

    if (all_items.length)
    {
      // Prevent scrolling by mouse wheel when menu is visible
      window.onmousewheel = function(event) { event.preventDefault(); }

      this._current_event = event;
      this.show(all_items, event.clientX, event.clientY);
      this.is_visible = true;
    }
  };

  /**
   * Show and position a context menu.
   *
   * @param {Array} items The items to show, see ContextMenu.register for how to
   *                      specify items.
   * @param {Int} x The left position of the menu, relative to the viewport.
   * @param {Int} y The top position of the menu, relative to the viewport.
   */
  this.show = function(items, x, y)
  {
    if (items)
    {
      var contextmenu = document.documentElement.render(window.templates.contextmenu(items));

      const DEFAULT_MARGIN = 2;
      var max_height = 0;
      var box = contextmenu.getBoundingClientRect();

      // Check if the menu height fits within the window
      if (box.height + (DEFAULT_MARGIN * 2) > window.innerHeight)
      {
        // It doesn't fit, apply max-height to make it scroll
        y = DEFAULT_MARGIN;
        max_height = window.innerHeight - (DEFAULT_MARGIN * 2) - 2; // 2 = border-width (top+bottom)
      }
      // It fits within the window, check if it fits downwards or not. If it
      // doesn't, we have to adjust the position.
      else if (y + box.height + DEFAULT_MARGIN > window.innerHeight)
      {
        // Check if we can just flip it upwards
        if (box.height + DEFAULT_MARGIN < y)
        {
          y -= box.height;
        }
        // It doesn't fit upwards, reposition it upwards as much as needed
        else
        {
          var overflow = window.innerHeight - y - box.height;
          y += overflow - DEFAULT_MARGIN;
        }
      }

      // It doesn't fit to the right, flip it
      if (x + box.width + DEFAULT_MARGIN > window.innerWidth)
      {
        x -= box.width;
      }

      contextmenu.style.cssText = [
        "left:" + x + "px",
        "top:" + y + "px",
        "max-height:" + (max_height ? max_height + "px" : "100%"),
        "visibility:visible"
      ].join(";");
    }
  };

  /**
   * Hides the context menu.
   */
  this.dismiss = function()
  {
    var contextmenu = document.getElementById("contextmenu");
    if (contextmenu)
    {
      contextmenu.parentElement.removeChild(contextmenu);
    }
    this.is_visible = false;
  };

  this._expand_all_items = function(items, event, menu_id)
  {
    var all_items = [];

    for (var i = 0, item; item = items[i]; i++)
    {
      if (typeof item.callback == "function")
      {
        var callback_items = item.callback(event, event.target);
        if (callback_items)
        {
          all_items = all_items.concat(callback_items);
        }
      }
      else
      {
        all_items.push(item);
      }
    }

    for (var i = 0, item; item = all_items[i]; i++)
    {
      item.id = "item_" + i;
      if (menu_id)
      {
        item.menu_id = menu_id;
      }
    }

    return all_items;
  };

  this.modal_click_handler = function(event)
  {
    var target = event.target;
    var contextmenu = document.getElementById("contextmenu");

    window.onmousewheel = null;

    event.stopPropagation();
    event.preventDefault();

    while (target != contextmenu && target != document)
    {
      var handler_id = target.getAttribute("data-handler-id");
      if (handler_id)
      {
        var menu_id = target.getAttribute("data-menu-id");
        var items = this._current_items;
        for (var i = 0, item; item = items[i]; i++)
        {
          if (item.id == handler_id && item.menu_id == menu_id)
          {
            if (item.disabled)
            {
              return;
            }

            var current_target = this._current_event.target;
            while (current_target)
            {
              if (menu_id == "spec" && current_target.getAttribute("data-spec")) { break }
              else if (menu_id == "resource" && current_target.getAttribute("data-resource-url")) { break }
              else if (menu_id == "resource" && current_target.getAttribute("data-resource-id")) { break }
              else if (current_target.getAttribute("data-menu") == menu_id) { break }
              current_target = current_target.parentNode;
            }
            item.handler(this._current_event, current_target);
            break;
          }
        }
      }
      target = target.parentNode;
    }

    this.dismiss();

    this._broker.clear_setter_click_handler(this);
  }.bind(this);
};

ContextMenu.get_instance = function()
{
  return this._instance || new ContextMenu();
};

ContextMenu.separator = {separator: true};
<commit_msg>remove contextual menu to 'show resource'<commit_after>/**
 * @constructor
 */
function ContextMenu() {
  if (ContextMenu._instance)
  {
    return ContextMenu._instance;
  }
  ContextMenu._instance = this;

  /**
   * All registered context menus.
   */
  this._registered_menus = {};
  this._current_items = null;

  this._broker = ActionBroker.get_instance();

  /**
   * Registers a new context menu.
   *
   * @param {String} menu_id An id corresponding to an id specified with a data-menu
   *                         attribute in the markup. May be an already existing
   *                         menu, in which case the items are added.
   * @param {Array} item_list An array of objects with 'label' and 'handler'
   *                          (function). Optionally it may have 'checked' (boolean)
   *                          for showing a checkbox before the item, or 'selected'
   *                          (boolean) for showing the selected item in a group.
   */
  this.register = function(menu_id, item_list, extend)
  {
    if (item_list)
    {
      if (this._registered_menus[menu_id] && extend)
      {
        item_list.extend(this._registered_menus[menu_id]);
      }
      this._registered_menus[menu_id] = item_list;
    }
  };

  /**
   * Global context menu event handler.
   */
  this.oncontextmenu = function(event)
  {

    var parents = [];
    var cur = event.target;
    while (cur)
      parents.push(cur = cur.parentNode);

    // Hide the currently visible context menu, if any
    this.dismiss();

    Tooltips.handle_contextmenu_event(event);

    CstSelectBase.close_opened_select();

    if (/*!window.getSelection().isCollapsed ||*/ event.shiftKey) // Shift key overrides for debugging
    {
      return;
    }

    // Prevent the normal context menu from showing up
    event.preventDefault();

    var ele = event.target;
    // The previous calls could have removed the event.target from the DOM.
    // In this case we re-dispatch the event if any element in
    // the parent node chain is still in the DOM.
    // (It would be better to get the new target with elementFromPoint
    //  but that is currently broken in XML documents.)
    if (!document.documentElement.contains(ele))
    {
      var new_target = null;
      while (new_target = parents.shift())
      {
        if (document.documentElement.contains(new_target))
          break;
      }

      if (new_target)
      {
        var new_event = document.createEvent("MouseEvent");
        new_event.initMouseEvent(event.type,
                                 event.bubbles,
                                 event.cancelable,
                                 event.view,
                                 event.detail,
                                 event.screenX,
                                 event.screenY,
                                 event.clientX,
                                 event.clientY,
                                 event.ctrlKey,
                                 event.altKey,
                                 event.shiftKey,
                                 event.metaKey,
                                 event.button,
                                 event.relatedTarget);
        new_target.dispatchEvent(new_event);
      }
      return;
    }

    var all_items = [];
    var menu_id = null;
    var last_found_menu_id = '';
    var collected_menus = [];
    var items = null;
    // This traverses up the tree and collects all menus it finds, and
    // concatenates them with a separator between each menu. It stops if it
    // finds a data-menu attribute with a blank value.
    while (ele && ele != document && (menu_id = ele.getAttribute("data-menu")) !== "")
    {
      items = null;
      if (menu_id)
      {
        last_found_menu_id = menu_id;
      }
      // Make sure the same menu is never collected twice
      if (collected_menus.indexOf(menu_id) == -1) {
        collected_menus.push(menu_id);

        var items = this._registered_menus[menu_id];
        if (items && items.length)
        {
          if (all_items.length)
          {
            all_items.push(ContextMenu.separator);
          }

          all_items = all_items.concat(this._expand_all_items(items, event, menu_id));
        }
      }
      ele = ele.parentNode;
    }

    // This should preferably not be done inside ContextMenu.
    var spec = event.target.get_attr("parent-node-chain", "data-spec");
    if (spec)
    {
      var speclinks = SpecLinks.get_instance();
      var specs = speclinks.get_spec_links(spec);
      if (specs.length)
      {
        items = specs.map(function(spec)
        {
          return {
            label: ui_strings.M_CONTEXTMENU_SPEC_LINK.replace("%s", spec.prop),
            handler: function(event, target) {
              speclinks.open_spec_link(spec.url);
            },
            id: spec.prop,
            menu_id: "spec"
          };
        });
        this.register("spec", items);

        if (all_items.length)
        {
          all_items.push(ContextMenu.separator);
        }
      }

      if (items)
      {
        all_items = all_items.concat(items);
      }
    }
/*
    var res_id_or_url = event.target.get_attr("parent-node-chain", "data-resource-id") ||
                        event.target.get_attr("parent-node-chain", "data-resource-url");
    var line_number = event.target.get_attr('parent-node-chain', 'data-resource-line-number');
    if (res_id_or_url)
    {
      if (last_found_menu_id == "dom")
      {
        var rt_id = event.target.get_attr('parent-node-chain', 'rt-id');
        res_id_or_url = helpers.resolveURLS(runtimes.getURI(rt_id), res_id_or_url);
      }
      var broker = cls.ResourceDisplayBroker.get_instance();
      var rid = parseInt(res_id_or_url, 10);
      if (rid)
      {
        // data-resource-line-number
        var fun = function()
        {
          broker.show_resource_for_id(rid, line_number);
        }
      }
      else
      {
        var fun = function()
        {
          broker.show_resource_for_url(res_id_or_url, line_number);
        }
      }

      if (all_items.length)
      {
        all_items.push(ContextMenu.separator);
      }

      all_items.push(
        {
          label: ui_strings.M_CONTEXTMENU_SHOW_RESOURCE,
          handler: fun,
          id: res_id_or_url,
          menu_id: "resource"
        }
      )
    }
*/
    this._current_items = all_items;

    if (all_items.length)
    {
      // Prevent scrolling by mouse wheel when menu is visible
      window.onmousewheel = function(event) { event.preventDefault(); }

      this._current_event = event;
      this.show(all_items, event.clientX, event.clientY);
      this.is_visible = true;
    }
  };

  /**
   * Show and position a context menu.
   *
   * @param {Array} items The items to show, see ContextMenu.register for how to
   *                      specify items.
   * @param {Int} x The left position of the menu, relative to the viewport.
   * @param {Int} y The top position of the menu, relative to the viewport.
   */
  this.show = function(items, x, y)
  {
    if (items)
    {
      var contextmenu = document.documentElement.render(window.templates.contextmenu(items));

      const DEFAULT_MARGIN = 2;
      var max_height = 0;
      var box = contextmenu.getBoundingClientRect();

      // Check if the menu height fits within the window
      if (box.height + (DEFAULT_MARGIN * 2) > window.innerHeight)
      {
        // It doesn't fit, apply max-height to make it scroll
        y = DEFAULT_MARGIN;
        max_height = window.innerHeight - (DEFAULT_MARGIN * 2) - 2; // 2 = border-width (top+bottom)
      }
      // It fits within the window, check if it fits downwards or not. If it
      // doesn't, we have to adjust the position.
      else if (y + box.height + DEFAULT_MARGIN > window.innerHeight)
      {
        // Check if we can just flip it upwards
        if (box.height + DEFAULT_MARGIN < y)
        {
          y -= box.height;
        }
        // It doesn't fit upwards, reposition it upwards as much as needed
        else
        {
          var overflow = window.innerHeight - y - box.height;
          y += overflow - DEFAULT_MARGIN;
        }
      }

      // It doesn't fit to the right, flip it
      if (x + box.width + DEFAULT_MARGIN > window.innerWidth)
      {
        x -= box.width;
      }

      contextmenu.style.cssText = [
        "left:" + x + "px",
        "top:" + y + "px",
        "max-height:" + (max_height ? max_height + "px" : "100%"),
        "visibility:visible"
      ].join(";");
    }
  };

  /**
   * Hides the context menu.
   */
  this.dismiss = function()
  {
    var contextmenu = document.getElementById("contextmenu");
    if (contextmenu)
    {
      contextmenu.parentElement.removeChild(contextmenu);
    }
    this.is_visible = false;
  };

  this._expand_all_items = function(items, event, menu_id)
  {
    var all_items = [];

    for (var i = 0, item; item = items[i]; i++)
    {
      if (typeof item.callback == "function")
      {
        var callback_items = item.callback(event, event.target);
        if (callback_items)
        {
          all_items = all_items.concat(callback_items);
        }
      }
      else
      {
        all_items.push(item);
      }
    }

    for (var i = 0, item; item = all_items[i]; i++)
    {
      item.id = "item_" + i;
      if (menu_id)
      {
        item.menu_id = menu_id;
      }
    }

    return all_items;
  };

  this.modal_click_handler = function(event)
  {
    var target = event.target;
    var contextmenu = document.getElementById("contextmenu");

    window.onmousewheel = null;

    event.stopPropagation();
    event.preventDefault();

    while (target != contextmenu && target != document)
    {
      var handler_id = target.getAttribute("data-handler-id");
      if (handler_id)
      {
        var menu_id = target.getAttribute("data-menu-id");
        var items = this._current_items;
        for (var i = 0, item; item = items[i]; i++)
        {
          if (item.id == handler_id && item.menu_id == menu_id)
          {
            if (item.disabled)
            {
              return;
            }

            var current_target = this._current_event.target;
            while (current_target)
            {
              if (menu_id == "spec" && current_target.getAttribute("data-spec")) { break }
              else if (menu_id == "resource" && current_target.getAttribute("data-resource-url")) { break }
              else if (menu_id == "resource" && current_target.getAttribute("data-resource-id")) { break }
              else if (current_target.getAttribute("data-menu") == menu_id) { break }
              current_target = current_target.parentNode;
            }
            item.handler(this._current_event, current_target);
            break;
          }
        }
      }
      target = target.parentNode;
    }

    this.dismiss();

    this._broker.clear_setter_click_handler(this);
  }.bind(this);
};

ContextMenu.get_instance = function()
{
  return this._instance || new ContextMenu();
};

ContextMenu.separator = {separator: true};
<|endoftext|>


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

    var jsPlumb = require('jsplumb');
    var _ = require('underscore');
    var JsPlumbManager = require('./jsplumb-manager');

    function Smartline(params) {
        this.type = 'Smartline';
        this.idPrefix = 'smartline-connector-';
        params = params || {};
        params.stub = params.stub === null || params.stub === void 0 ? 30 : params.stub;
        var segments;
        var _super = jsPlumb.Connectors.AbstractConnector.apply(this, arguments);
        this.smartlineManager = JsPlumbManager.getJsPlumbSmartlineManager(params._jsPlumb);
        var midpoint = params.midpoint === null || params.midpoint === void 0 ? 0.5 : params.midpoint;
        var alwaysRespectStubs = params.alwaysRespectStubs === true;
        var userSuppliedSegments = null;
        var lastx = null;
        var lasty = null;
        var lastOrientation;
        var cornerRadius = params.cornerRadius !== null && params.midpoint !== void 0 ? params.cornerRadius : 0;
        var showLoopback = params.showLoopback !== false;
        var sgn = function(n) {
            return n < 0 ? -1 : n === 0 ? 0 : 1;
        };
        /**
         * helper method to add a segment.
         */
        var addSegment = function(segments, x, y, paintInfo) {
            if (lastx === x && lasty === y) {
                return;
            }
            var lx = lastx === null ? paintInfo.sx : lastx;
            var ly = lasty === null ? paintInfo.sy : lasty;
            var o = lx === x ? 'v' : 'h';
            var sgnx = sgn(x - lx);
            var sgny = sgn(y - ly);

            lastx = x;
            lasty = y;
            segments.push([lx, ly, x, y, o, sgnx, sgny]);
        };
        var segLength = function(s) {
            return Math.sqrt(Math.pow(s[0] - s[2], 2) + Math.pow(s[1] - s[3], 2));
        };
        var _cloneArray = function(a) {
            var _a = [];
            _a.push.apply(_a, a);
            return _a;
        };
        var writeSegments = function(conn, segments, paintInfo) {
            var current = null;
            var next;
            for (var i = 0; i < segments.length - 1; i++) {

                current = current || _cloneArray(segments[i]);
                next = _cloneArray(segments[i + 1]);
                if (cornerRadius > 0 && current[4] !== next[4]) {
                    var radiusToUse = Math.min(cornerRadius, segLength(current), segLength(next));
                    // right angle. adjust current segment's end point, and next segment's start point.
                    current[2] -= current[5] * radiusToUse;
                    current[3] -= current[6] * radiusToUse;
                    next[0] += next[5] * radiusToUse;
                    next[1] += next[6] * radiusToUse;
                    var ac = (current[6] === next[5] && next[5] === 1) ||
                            ((current[6] === next[5] && next[5] === 0) && current[5] !== next[6]) ||
                            (current[6] === next[5] && next[5] === -1);
                    var sgny = next[1] > current[3] ? 1 : -1;
                    var sgnx = next[0] > current[2] ? 1 : -1;
                    var sgnEqual = sgny === sgnx;
                    var cx = (sgnEqual && ac || (!sgnEqual && !ac)) ? next[0] : current[2];
                    var cy = (sgnEqual && ac || (!sgnEqual && !ac)) ? current[3] : next[1];

                    _super.addSegment(conn, 'Straight', {
                        x1: current[0], y1: current[1], x2: current[2], y2: current[3]
                    });

                    _super.addSegment(conn, 'Arc', {
                        r: radiusToUse,
                        x1: current[2],
                        y1: current[3],
                        x2: next[0],
                        y2: next[1],
                        cx: cx,
                        cy: cy,
                        ac: ac
                    });
                } else {
                    // dx + dy are used to adjust for line width.
                    var dx = (current[2] === current[0]) ? 0 :
                        (current[2] > current[0]) ? (paintInfo.lw / 2) : -(paintInfo.lw / 2);
                    var dy = (current[3] === current[1]) ? 0 :
                        (current[3] > current[1]) ? (paintInfo.lw / 2) : -(paintInfo.lw / 2);
                    _super.addSegment(conn, 'Straight', {
                        x1: current[0] - dx, y1: current[1] - dy, x2: current[2] + dx, y2: current[3] + dy
                    });
                }
                current = next;
            }
            if (next) {
                // last segment
                _super.addSegment(conn, 'Straight', {
                    x1: next[0], y1: next[1], x2: next[2], y2: next[3]
                });
            }
        };

        this.setSegments = function(s) {
            userSuppliedSegments = s;
        };

        this.getSegs = function() {
            return segments;
        };

        this.getAbsSegments = function(conn) {
            var i;
            var j;
            var cur;
            var rect1 = conn.endpoints[0].canvas.getBoundingClientRect();
            var rect2 = conn.endpoints[1].canvas.getBoundingClientRect();
            var x = Math.min((rect1.left + rect1.right), (rect2.left + rect2.right)) / 2;
            var y = Math.min((rect1.top + rect1.bottom), (rect2.top + rect2.bottom)) / 2;
            var result = [];
            for (i = 0; i < segments.length; i++) {
                cur = [segments[i][0] + x, segments[i][1] + y, segments[i][2] + x, segments[i][3] + y, segments[i][4]];
                if (i > 0) {
                    j = result.length - 1;
                    if (cur[4] === 'v' && result[j][4] === 'v') {
                        if (cur[1] === result[j][3]) {
                            result[j][3] = cur[3];
                            continue;
                        } else if (cur[3] === result[j][1]) {
                            result[j][1] = cur[1];
                            continue;
                        }
                    } else if (cur[4] === 'h' && result[j][4] === 'h') {
                        if (cur[0] === result[j][2]) {
                            result[j][2] = cur[2];
                            continue;
                        } else if (cur[2] === result[j][0]) {
                            result[j][0] = cur[0];
                            continue;
                        }
                    }
                }
                result.push(cur);
            }
            return result;
        };

        this.isEditable = function() {
            return true;
        };

        /*
         Function: getOriginalSegments
         Gets the segments before the addition of rounded corners. This is used by the flowchart
         connector editor, since it only wants to concern itself with the original segments.
         */
        this.getOriginalSegments = function() {
            return userSuppliedSegments || segments;
        };

        this._compute = function(paintInfo, params) {
            if (params.clearEdits) {
                userSuppliedSegments = null;
            }

            if (userSuppliedSegments !== null) {
                writeSegments(this, userSuppliedSegments, paintInfo);
                return;
            }

            lastx = null;
            lasty = null;
            lastOrientation = null;

            segments = [];

            // compute the rest of the line
            var points = this.smartlineManager.getConnectionPath(this, paintInfo);
            if (points.length == 0) {
                // leave everything as is
                return;
            }

            // add space from center to line start
            points[0].y += 18;
            points[points.length - 1].y -= 18;

            // set valid archors
            var sourcePoint = points.shift(),
                targetPoint = points.pop(),
                correction,
                ENDPOINT_SPACE_TO_LINE = 4;
            var oldAnchorX = params.sourceEndpoint.anchor.x,
                oldAnchorY = params.sourceEndpoint.anchor.y;
            params.sourceEndpoint.anchor.x = (sourcePoint.x - params.sourceEndpoint.element.offsetLeft)/ params.sourceEndpoint.element.offsetWidth;
            params.sourceEndpoint.anchor.y = (sourcePoint.y - params.sourceEndpoint.element.offsetTop)/ params.sourceEndpoint.element.offsetHeight;
            params.targetEndpoint.anchor.x = (targetPoint.x - params.targetEndpoint.element.offsetLeft)/ params.targetEndpoint.element.offsetWidth;
            params.targetEndpoint.anchor.y = (targetPoint.y - params.targetEndpoint.element.offsetTop)/ params.targetEndpoint.element.offsetHeight;
            correction = {
                x: Math.min(sourcePoint.x, targetPoint.x),
                y: Math.min(sourcePoint.y, targetPoint.y)
            }
            if (oldAnchorX !== params.sourceEndpoint.anchor.x) {
                paintInfo.points[0] += (params.sourceEndpoint.anchor.x - oldAnchorX) * params.sourceEndpoint.element.offsetWidth;
            }
            if (oldAnchorY !== params.sourceEndpoint.anchor.y) {
                paintInfo.points[1] += (params.sourceEndpoint.anchor.y - oldAnchorY) * params.sourceEndpoint.element.offsetHeight;
            }

            paintInfo.sy += ENDPOINT_SPACE_TO_LINE + 1;

            if (points.length) {
                for (var i = 0; i < points.length; i++) {
                    addSegment(segments, points[i].x - correction.x, points[i].y - correction.y, paintInfo);
                }
            } else {
                addSegment(segments, sourcePoint.x - correction.x, sourcePoint.y - correction.y, paintInfo);
            }

            // end stub to end
            addSegment(segments, targetPoint.x - correction.x, targetPoint.y - correction.y - ENDPOINT_SPACE_TO_LINE, paintInfo);

            writeSegments(this, segments, paintInfo);
        };

        this.getPath = function() {
            var _last = null;
            var _lastAxis = null;
            var s = [];
            var segs = userSuppliedSegments || segments;
            var seg;
            var axis;
            var axisIndex;
            for (var i = 0; i < segs.length; i++) {
                seg = segs[i];
                axis = seg[4];
                axisIndex = (axis === 'v' ? 3 : 2);
                if (_last !== null && _lastAxis === axis) {
                    _last[axisIndex] = seg[axisIndex];
                } else {
                    if (seg[0] !== seg[2] || seg[1] !== seg[3]) {
                        s.push({
                            start: [seg[0], seg[1]],
                            end: [seg[2], seg[3]]
                        });
                        _last = seg;
                        _lastAxis = seg[4];
                    }
                }
            }
            return s;
        };

        this.setPath = function(path) {
            userSuppliedSegments = [];
            for (var i = 0; i < path.length; i++) {
                var lx = path[i].start[0];
                var ly = path[i].start[1];
                var x = path[i].end[0];
                var y = path[i].end[1];
                var o = lx === x ? 'v' : 'h';
                var sgnx = sgn(x - lx);
                var sgny = sgn(y - ly);

                userSuppliedSegments.push([lx, ly, x, y, o, sgnx, sgny]);
            }
        };
    }

    function juExtend(child, parent, _protoFn) {
        var i;
        parent = Object.prototype.toString.call(parent) === '[object Array]' ? parent : [parent];

        for (i = 0; i < parent.length; i++) {
            for (var j in parent[i].prototype) {
                if (parent[i].prototype.hasOwnProperty(j)) {
                    child.prototype[j] = parent[i].prototype[j];
                }
            }
        }

        var _makeFn = function(name, protoFn) {
            return function() {
                for (i = 0; i < parent.length; i++) {
                    if (parent[i].prototype[name]) {
                        parent[i].prototype[name].apply(this, arguments);
                    }
                }
                return protoFn.apply(this, arguments);
            };
        };

        var _oneSet = function(fns) {
            for (var k in fns) {
                if (fns.hasOwnProperty(k)) {
                    child.prototype[k] = _makeFn(k, fns[k]);
                }
            }
        };

        if (arguments.length > 2) {
            for (i = 2; i < arguments.length; i++) {
                _oneSet(arguments[i]);
            }
        }

        return child;
    }

    juExtend(Smartline, jsPlumb.Connectors.AbstractConnector);
    jsPlumb.registerConnectorType(Smartline, 'Smartline');
    _.each(jsPlumb.getRenderModes(), function(renderer) {
        jsPlumb.Connectors[renderer].Smartline = function() {
            Smartline.apply(this, arguments);
            jsPlumb.ConnectorRenderers[renderer].apply(this, arguments);
        };
        juExtend(jsPlumb.Connectors[renderer].Smartline, [Smartline, jsPlumb.ConnectorRenderers[renderer]]);
    });

    return Smartline;
});
<commit_msg>CRM-3386 connections should be always straight<commit_after>define(function(require) {
    'use strict';

    var jsPlumb = require('jsplumb');
    var _ = require('underscore');
    var JsPlumbManager = require('./jsplumb-manager');

    function Smartline(params) {
        this.type = 'Smartline';
        this.idPrefix = 'smartline-connector-';
        params = params || {};
        params.stub = params.stub === null || params.stub === void 0 ? 30 : params.stub;
        var segments;
        var _super = jsPlumb.Connectors.AbstractConnector.apply(this, arguments);
        this.smartlineManager = JsPlumbManager.getJsPlumbSmartlineManager(params._jsPlumb);
        var midpoint = params.midpoint === null || params.midpoint === void 0 ? 0.5 : params.midpoint;
        var alwaysRespectStubs = params.alwaysRespectStubs === true;
        var userSuppliedSegments = null;
        var lastx = null;
        var lasty = null;
        var lastOrientation;
        var cornerRadius = params.cornerRadius !== null && params.midpoint !== void 0 ? params.cornerRadius : 0;
        var showLoopback = params.showLoopback !== false;
        var sgn = function(n) {
            return n < 0 ? -1 : n === 0 ? 0 : 1;
        };
        /**
         * helper method to add a segment.
         */
        var addSegment = function(segments, x, y, paintInfo) {
            if (lastx === x && lasty === y) {
                return;
            }
            var lx = lastx === null ? paintInfo.sx : lastx;
            var ly = lasty === null ? paintInfo.sy : lasty;
            var o = lx === x ? 'v' : 'h';
            var sgnx = sgn(x - lx);
            var sgny = sgn(y - ly);

            lastx = x;
            lasty = y;
            segments.push([lx, ly, x, y, o, sgnx, sgny]);
        };
        var segLength = function(s) {
            return Math.sqrt(Math.pow(s[0] - s[2], 2) + Math.pow(s[1] - s[3], 2));
        };
        var _cloneArray = function(a) {
            var _a = [];
            _a.push.apply(_a, a);
            return _a;
        };
        var writeSegments = function(conn, segments, paintInfo) {
            var current = null;
            var next;
            for (var i = 0; i < segments.length - 1; i++) {

                current = current || _cloneArray(segments[i]);
                next = _cloneArray(segments[i + 1]);
                if (cornerRadius > 0 && current[4] !== next[4]) {
                    var radiusToUse = Math.min(cornerRadius, segLength(current), segLength(next));
                    // right angle. adjust current segment's end point, and next segment's start point.
                    current[2] -= current[5] * radiusToUse;
                    current[3] -= current[6] * radiusToUse;
                    next[0] += next[5] * radiusToUse;
                    next[1] += next[6] * radiusToUse;
                    var ac = (current[6] === next[5] && next[5] === 1) ||
                            ((current[6] === next[5] && next[5] === 0) && current[5] !== next[6]) ||
                            (current[6] === next[5] && next[5] === -1);
                    var sgny = next[1] > current[3] ? 1 : -1;
                    var sgnx = next[0] > current[2] ? 1 : -1;
                    var sgnEqual = sgny === sgnx;
                    var cx = (sgnEqual && ac || (!sgnEqual && !ac)) ? next[0] : current[2];
                    var cy = (sgnEqual && ac || (!sgnEqual && !ac)) ? current[3] : next[1];

                    _super.addSegment(conn, 'Straight', {
                        x1: current[0], y1: current[1], x2: current[2], y2: current[3]
                    });

                    _super.addSegment(conn, 'Arc', {
                        r: radiusToUse,
                        x1: current[2],
                        y1: current[3],
                        x2: next[0],
                        y2: next[1],
                        cx: cx,
                        cy: cy,
                        ac: ac
                    });
                } else {
                    // dx + dy are used to adjust for line width.
                    var dx = (current[2] === current[0]) ? 0 :
                        (current[2] > current[0]) ? (paintInfo.lw / 2) : -(paintInfo.lw / 2);
                    var dy = (current[3] === current[1]) ? 0 :
                        (current[3] > current[1]) ? (paintInfo.lw / 2) : -(paintInfo.lw / 2);
                    _super.addSegment(conn, 'Straight', {
                        x1: current[0] - dx, y1: current[1] - dy, x2: current[2] + dx, y2: current[3] + dy
                    });
                }
                current = next;
            }
            if (next) {
                // last segment
                _super.addSegment(conn, 'Straight', {
                    x1: next[0], y1: next[1], x2: next[2], y2: next[3]
                });
            }
        };

        this.setSegments = function(s) {
            userSuppliedSegments = s;
        };

        this.getSegs = function() {
            return segments;
        };

        this.getAbsSegments = function(conn) {
            var i;
            var j;
            var cur;
            var rect1 = conn.endpoints[0].canvas.getBoundingClientRect();
            var rect2 = conn.endpoints[1].canvas.getBoundingClientRect();
            var x = Math.min((rect1.left + rect1.right), (rect2.left + rect2.right)) / 2;
            var y = Math.min((rect1.top + rect1.bottom), (rect2.top + rect2.bottom)) / 2;
            var result = [];
            for (i = 0; i < segments.length; i++) {
                cur = [segments[i][0] + x, segments[i][1] + y, segments[i][2] + x, segments[i][3] + y, segments[i][4]];
                if (i > 0) {
                    j = result.length - 1;
                    if (cur[4] === 'v' && result[j][4] === 'v') {
                        if (cur[1] === result[j][3]) {
                            result[j][3] = cur[3];
                            continue;
                        } else if (cur[3] === result[j][1]) {
                            result[j][1] = cur[1];
                            continue;
                        }
                    } else if (cur[4] === 'h' && result[j][4] === 'h') {
                        if (cur[0] === result[j][2]) {
                            result[j][2] = cur[2];
                            continue;
                        } else if (cur[2] === result[j][0]) {
                            result[j][0] = cur[0];
                            continue;
                        }
                    }
                }
                result.push(cur);
            }
            return result;
        };

        this.isEditable = function() {
            return true;
        };

        /*
         Function: getOriginalSegments
         Gets the segments before the addition of rounded corners. This is used by the flowchart
         connector editor, since it only wants to concern itself with the original segments.
         */
        this.getOriginalSegments = function() {
            return userSuppliedSegments || segments;
        };

        this._compute = function(paintInfo, params) {
            if (params.clearEdits) {
                userSuppliedSegments = null;
            }

            if (userSuppliedSegments !== null) {
                writeSegments(this, userSuppliedSegments, paintInfo);
                return;
            }

            lastx = null;
            lasty = null;
            lastOrientation = null;

            segments = [];

            // compute the rest of the line
            var points = this.smartlineManager.getConnectionPath(this, paintInfo);
            if (points.length == 0) {
                // leave everything as is
                return;
            }

            // add space from center to line start
            points[0].y += 18;
            points[points.length - 1].y -= 18;

            // set valid archors
            var sourcePoint = points.shift(),
                targetPoint = points.pop(),
                correction,
                ENDPOINT_SPACE_TO_LINE = 4;
            var oldAnchorX = params.sourceEndpoint.anchor.x,
                oldAnchorY = params.sourceEndpoint.anchor.y;
            params.sourceEndpoint.anchor.x = (sourcePoint.x - params.sourceEndpoint.element.offsetLeft)/ params.sourceEndpoint.element.offsetWidth;
            params.sourceEndpoint.anchor.y = (sourcePoint.y - params.sourceEndpoint.element.offsetTop)/ params.sourceEndpoint.element.offsetHeight;
            params.targetEndpoint.anchor.x = (targetPoint.x - params.targetEndpoint.element.offsetLeft)/ params.targetEndpoint.element.offsetWidth;
            params.targetEndpoint.anchor.y = (targetPoint.y - params.targetEndpoint.element.offsetTop)/ params.targetEndpoint.element.offsetHeight;
            correction = {
                x: Math.min(sourcePoint.x, targetPoint.x),
                y: Math.min(sourcePoint.y, targetPoint.y)
            }
            if (oldAnchorX !== params.sourceEndpoint.anchor.x) {
                paintInfo.points[0] += (params.sourceEndpoint.anchor.x - oldAnchorX) * params.sourceEndpoint.element.offsetWidth;
            }
            if (oldAnchorY !== params.sourceEndpoint.anchor.y) {
                paintInfo.points[1] += (params.sourceEndpoint.anchor.y - oldAnchorY) * params.sourceEndpoint.element.offsetHeight;
            }

            paintInfo.sx = sourcePoint.x - correction.x;
            paintInfo.sy += ENDPOINT_SPACE_TO_LINE + 1;

            var style = window.getComputedStyle(params.sourceEndpoint.element),
                sourceBorderRadius = 0;
            if (style.borderRadius) {
                sourceBorderRadius = parseInt(style.borderRadius);
            }

            if (points.length) {
                for (var i = 0; i < points.length; i++) {
                    addSegment(segments, points[i].x - correction.x, points[i].y - correction.y, paintInfo);
                }
            } else {
                addSegment(segments, sourcePoint.x - correction.x, sourcePoint.y - correction.y, paintInfo);
            }

            // end stub to end
            addSegment(segments, targetPoint.x - correction.x, targetPoint.y - correction.y - ENDPOINT_SPACE_TO_LINE, paintInfo);

            writeSegments(this, segments, paintInfo);
        };

        this.getPath = function() {
            var _last = null;
            var _lastAxis = null;
            var s = [];
            var segs = userSuppliedSegments || segments;
            var seg;
            var axis;
            var axisIndex;
            for (var i = 0; i < segs.length; i++) {
                seg = segs[i];
                axis = seg[4];
                axisIndex = (axis === 'v' ? 3 : 2);
                if (_last !== null && _lastAxis === axis) {
                    _last[axisIndex] = seg[axisIndex];
                } else {
                    if (seg[0] !== seg[2] || seg[1] !== seg[3]) {
                        s.push({
                            start: [seg[0], seg[1]],
                            end: [seg[2], seg[3]]
                        });
                        _last = seg;
                        _lastAxis = seg[4];
                    }
                }
            }
            return s;
        };

        this.setPath = function(path) {
            userSuppliedSegments = [];
            for (var i = 0; i < path.length; i++) {
                var lx = path[i].start[0];
                var ly = path[i].start[1];
                var x = path[i].end[0];
                var y = path[i].end[1];
                var o = lx === x ? 'v' : 'h';
                var sgnx = sgn(x - lx);
                var sgny = sgn(y - ly);

                userSuppliedSegments.push([lx, ly, x, y, o, sgnx, sgny]);
            }
        };
    }

    function juExtend(child, parent, _protoFn) {
        var i;
        parent = Object.prototype.toString.call(parent) === '[object Array]' ? parent : [parent];

        for (i = 0; i < parent.length; i++) {
            for (var j in parent[i].prototype) {
                if (parent[i].prototype.hasOwnProperty(j)) {
                    child.prototype[j] = parent[i].prototype[j];
                }
            }
        }

        var _makeFn = function(name, protoFn) {
            return function() {
                for (i = 0; i < parent.length; i++) {
                    if (parent[i].prototype[name]) {
                        parent[i].prototype[name].apply(this, arguments);
                    }
                }
                return protoFn.apply(this, arguments);
            };
        };

        var _oneSet = function(fns) {
            for (var k in fns) {
                if (fns.hasOwnProperty(k)) {
                    child.prototype[k] = _makeFn(k, fns[k]);
                }
            }
        };

        if (arguments.length > 2) {
            for (i = 2; i < arguments.length; i++) {
                _oneSet(arguments[i]);
            }
        }

        return child;
    }

    juExtend(Smartline, jsPlumb.Connectors.AbstractConnector);
    jsPlumb.registerConnectorType(Smartline, 'Smartline');
    _.each(jsPlumb.getRenderModes(), function(renderer) {
        jsPlumb.Connectors[renderer].Smartline = function() {
            Smartline.apply(this, arguments);
            jsPlumb.ConnectorRenderers[renderer].apply(this, arguments);
        };
        juExtend(jsPlumb.Connectors[renderer].Smartline, [Smartline, jsPlumb.ConnectorRenderers[renderer]]);
    });

    return Smartline;
});
<|endoftext|>