<commit_before>/*jslint browser: true */
(function ($, window, document) {
	'use strict';

	var IcbiaControl, controlMap;

	IcbiaControl = function () {};

	IcbiaControl.prototype = {
		optionAttributePrefix: 'data-icbiacontrol-',
		initialize: function ($el, options) {
			this.$el = $el;
			this.options = $.extend(this.defaultOptions, this.getHtmlOptions(), options);
			this.$el
				.change($.proxy(this.changeHandler, this))
				.focus($.proxy(this.focusHandler, this))
				.blur($.proxy(this.blurHandler, this));
			this.wrap();
			this.updateHitArea();
			this.updateWidget();
		},

		blurHandler: function (event) {
			this.wrapper.removeClass('focus');
		},

		focusHandler: function (event) {
			this.wrapper.addClass('focus');
		},

		changeHandler: function (event) {
			this.updateWidget();
		},

		updateWidget: $.noop,

		updateHitArea: function () {
			this.$el
				.css({
					width: this.widget.width(),
					height: this.widget.height()
				});
		},

		getHtmlOptions: function () {
			var self = this,
			    opts = {};
			$.each(this.$el[0].attributes, function (i, attr) {
				if (attr.name.indexOf(self.optionAttributePrefix) !== -1) {
					opts[attr.name.substr(self.optionAttributePrefix.length)] = attr.value;
				}
			});
			return opts;
		},

		defaultOptions: {
		},

		createWidget: function () {
			var wt = this.options.widgetTemplate,
			    widget = typeof wt === 'function' ? wt() : $($(wt).html());

			return widget
				.removeAttr(this.optionAttributePrefix + 'widgetTemplate')
				.addClass('icbiacontrol-widget')
				.addClass('icbia' + this.controlName + '-widget');
		},

		wrap: function () {
			if (!this.wrapper) {
				this.widget = this.createWidget();
				this.wrapper = $('')
					.addClass('icbia' + this.controlName)
					.css({
						position: 'relative',
						display: 'inline-block'
					})
					.append(this.widget)
					.insertBefore(this.$el)
					.append(
						this.$el.css({
							position: 'absolute',
							border: '1px solid #fff',  // To force the dimensions to take effect.
							top: 0,
							left: 0,
							opacity: 0
						})
					);
			}
		}
	};

	IcbiaControl.extend = function (attrs) {
		var SuperClass = this,
		    ctor = function () {};
		ctor.prototype = new SuperClass();
		ctor.prototype.constructor = ctor;
		$.extend(ctor.prototype, attrs);
		ctor.extend = SuperClass.extend;
		return ctor;
	};

	controlMap = {
		'select': IcbiaControl.extend({
			controlName: 'select',
			defaultOptions: $.extend({}, IcbiaControl.prototype.defaultOptions, {
				widgetTemplate: function () {
					return $(' ' +
							'                                                        ' +
							'                    ' +
							'                     ' +
							'                                                       ' +
							'                ' +
							'                                                       '
						);
				}
			}),
			updateWidget: function () {
				var label = this.$el.find('option:selected').html();
				this.widget.find('.icbiaselect-display').html(label || ' ');
				this.updateHitArea();
			}
		}),
		'input[type=checkbox]': IcbiaControl.extend({
			controlName: 'checkbox',
			defaultOptions: $.extend({}, IcbiaControl.prototype.defaultOptions, {
				widgetTemplate: function () {
					return $('');
				}
			}),
			updateWidget: function () {
				var isChecked = this.$el.is(':checked');
				this.wrapper
					.addClass(isChecked ? 'checked' : 'unchecked')
					.removeClass(isChecked ? 'unchecked' : 'checked');
				this.updateHitArea();
			}
		}),
		'input[type=radio]': IcbiaControl.extend({
			controlName: 'radio',
			defaultOptions: $.extend({}, IcbiaControl.prototype.defaultOptions, {
				widgetTemplate: function () {
					return $('');
				}
			}),
			updateWidget: function () {
				var isChecked = this.$el.is(':checked');
				this.wrapper
					.addClass(isChecked ? 'checked' : 'unchecked')
					.removeClass(isChecked ? 'unchecked' : 'checked');
				this.updateHitArea();
			},
			initialize: function ($el, options) {
				IcbiaControl.prototype.initialize.call(this, $el, options);
				$('input[name=' + this.$el.attr('name') + ']').not(this.$el)
					.change($.proxy(this.changeHandler, this));
			},
		})
	};

	function createIcbiaControl($el, options) {
		var plugin;
		$.each(controlMap, function (selector, Cls) {
			if ($el.is(selector)) {
				plugin = new Cls();
				plugin.initialize($el, options);
				return false;
			}
		});

		if (!plugin) {
			$.error('There\'s no control for the ' + $el.prop('tagName') + ' element ' + $el);
		}

		return plugin;
	}

	$.extend($.fn, {
		icbiaControl: function (optionsOrMethod) {
			var returnValue = this,
			    args = arguments;
			this.each(function (i, el) {
				var $el = $(el),
				    plugin = $el.data('icbiaControl'),
				    method = typeof optionsOrMethod === 'string' ? optionsOrMethod : null,
				    options = method === null ? optionsOrMethod || {} : {};

				if (!plugin) {
					if (method) {
						$.error('You can\'t call the icbiaControl method "' + method
								+ '" without first initializing the plugin by calling '
								+ 'icbiaControl() on the jQuery object.');
					} else {
						plugin = createIcbiaControl($el, options);
						$el.data('icbiaControl', plugin);
					}
				} else if (method) {
					if (typeof plugin[method] !== 'function') {
						$.error('Method "' + method + '" does not exist on jQuery.icbiaControl');
					} else {
						// NOTE: If you call a method that returns a value, you will only get the result from the last item in the collection.
						returnValue = plugin[method].apply(plugin, Array.prototype.slice.call(args, 1));
					}
				}
			});
			return returnValue;
		}
	});
}(this.jQuery, window, document));
<commit_msg>Pull common functionality into base class<commit_after>/*jslint browser: true */
(function ($, window, document) {
	'use strict';

	var IcbiaControl, AbstractCheckedControl, controlMap;

	IcbiaControl = function () {};

	IcbiaControl.prototype = {
		optionAttributePrefix: 'data-icbiacontrol-',
		initialize: function ($el, options) {
			this.$el = $el;
			this.options = $.extend(this.defaultOptions, this.getHtmlOptions(), options);
			this.$el
				.change($.proxy(this.changeHandler, this))
				.focus($.proxy(this.focusHandler, this))
				.blur($.proxy(this.blurHandler, this));
			this.wrap();
			this.updateHitArea();
			this.updateWidget();
		},

		blurHandler: function (event) {
			this.wrapper.removeClass('focus');
		},

		focusHandler: function (event) {
			this.wrapper.addClass('focus');
		},

		changeHandler: function (event) {
			this.updateWidget();
		},

		updateWidget: $.noop,

		updateHitArea: function () {
			this.$el
				.css({
					width: this.widget.width(),
					height: this.widget.height()
				});
		},

		getHtmlOptions: function () {
			var self = this,
			    opts = {};
			$.each(this.$el[0].attributes, function (i, attr) {
				if (attr.name.indexOf(self.optionAttributePrefix) !== -1) {
					opts[attr.name.substr(self.optionAttributePrefix.length)] = attr.value;
				}
			});
			return opts;
		},

		defaultOptions: {
		},

		createWidget: function () {
			var wt = this.options.widgetTemplate,
			    widget = typeof wt === 'function' ? wt() : $($(wt).html());

			return widget
				.removeAttr(this.optionAttributePrefix + 'widgetTemplate')
				.addClass('icbiacontrol-widget')
				.addClass('icbia' + this.controlName + '-widget');
		},

		wrap: function () {
			if (!this.wrapper) {
				this.widget = this.createWidget();
				this.wrapper = $('')
					.addClass('icbia' + this.controlName)
					.css({
						position: 'relative',
						display: 'inline-block'
					})
					.append(this.widget)
					.insertBefore(this.$el)
					.append(
						this.$el.css({
							position: 'absolute',
							border: '1px solid #fff',  // To force the dimensions to take effect.
							top: 0,
							left: 0,
							opacity: 0
						})
					);
			}
		}
	};

	IcbiaControl.extend = function (attrs) {
		var SuperClass = this,
		    ctor = function () {};
		ctor.prototype = new SuperClass();
		ctor.prototype.constructor = ctor;
		$.extend(ctor.prototype, attrs);
		ctor.extend = SuperClass.extend;
		return ctor;
	};

	// A base control for checkboxes and radio buttons.
	AbstractCheckedControl = IcbiaControl.extend({
		defaultOptions: $.extend({}, IcbiaControl.prototype.defaultOptions, {
			widgetTemplate: function () {
				return $('');
			}
		}),
		updateWidget: function () {
			var isChecked = this.$el.is(':checked');
			this.wrapper
				.addClass(isChecked ? 'checked' : 'unchecked')
				.removeClass(isChecked ? 'unchecked' : 'checked');
			this.updateHitArea();
		}
	});

	controlMap = {
		'select': IcbiaControl.extend({
			controlName: 'select',
			defaultOptions: $.extend({}, IcbiaControl.prototype.defaultOptions, {
				widgetTemplate: function () {
					return $(' ' +
							'                                                        ' +
							'                    ' +
							'                     ' +
							'                                                       ' +
							'                ' +
							'                                                       '
						);
				}
			}),
			updateWidget: function () {
				var label = this.$el.find('option:selected').html();
				this.widget.find('.icbiaselect-display').html(label || ' ');
				this.updateHitArea();
			}
		}),
		'input[type=checkbox]': AbstractCheckedControl.extend({
			controlName: 'checkbox'
		}),
		'input[type=radio]': AbstractCheckedControl.extend({
			controlName: 'radio',
			initialize: function ($el, options) {
				IcbiaControl.prototype.initialize.call(this, $el, options);
				$('input[name=' + this.$el.attr('name') + ']').not(this.$el)
					.change($.proxy(this.changeHandler, this));
			}
		})
	};

	function createIcbiaControl($el, options) {
		var plugin;
		$.each(controlMap, function (selector, Cls) {
			if ($el.is(selector)) {
				plugin = new Cls();
				plugin.initialize($el, options);
				return false;
			}
		});

		if (!plugin) {
			$.error('There\'s no control for the ' + $el.prop('tagName') + ' element ' + $el);
		}

		return plugin;
	}

	$.extend($.fn, {
		icbiaControl: function (optionsOrMethod) {
			var returnValue = this,
			    args = arguments;
			this.each(function (i, el) {
				var $el = $(el),
				    plugin = $el.data('icbiaControl'),
				    method = typeof optionsOrMethod === 'string' ? optionsOrMethod : null,
				    options = method === null ? optionsOrMethod || {} : {};

				if (!plugin) {
					if (method) {
						$.error('You can\'t call the icbiaControl method "' + method
								+ '" without first initializing the plugin by calling '
								+ 'icbiaControl() on the jQuery object.');
					} else {
						plugin = createIcbiaControl($el, options);
						$el.data('icbiaControl', plugin);
					}
				} else if (method) {
					if (typeof plugin[method] !== 'function') {
						$.error('Method "' + method + '" does not exist on jQuery.icbiaControl');
					} else {
						// NOTE: If you call a method that returns a value, you will only get the result from the last item in the collection.
						returnValue = plugin[method].apply(plugin, Array.prototype.slice.call(args, 1));
					}
				}
			});
			return returnValue;
		}
	});
}(this.jQuery, window, document));
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'olymp';
import Image, { cloudinaryUrl } from '../components/image';

@withRouter
export default class Lightbox extends Component {
  ref = Math.random().toString(36).substr(2, 9);

  static contextTypes = {
    lightbox: PropTypes.object,
  };

  componentWillMount() {
    const { value } = this.props;

    if (value) { this.add(value); }
  }

  componentWillReceiveProps({ value }) {
    const { lightbox } = this.context;

    if (value.id !== this.props.value.id) {
      lightbox.remove(this.ref);
      this.add(value);
    }
  }

  componentWillUnmount() {
    const { lightbox } = this.context;

    lightbox.remove(this.ref);
  }

  add = (value) => {
    const { lightbox } = this.context;
    const width = 800;
    const getSrcSet = w =>
      `${cloudinaryUrl(value, {
        w: Math.floor(w),
      })} ${Math.floor(w)}w`;

    lightbox.add({
      ref: this.ref,
      gallery: lightbox.gallery,
      src: cloudinaryUrl(value, { w: width }),
      srcset: [
        getSrcSet(width),
        getSrcSet(width / 4 * 3),
        getSrcSet(width / 2),
        getSrcSet(width / 4),
      ],
      thumbnail: cloudinaryUrl(value, {
        w: 50,
        h: 50,
      }),
      caption:
        value.caption && value.source
          ? `${value.caption} - ${value.source}`
          : value.caption || value.source || '',
    });
  };

  onClick = (e) => {
    const { onClick, router, pathname, query } = this.props;
    router.push({ pathname, query: { ...query, lightbox: this.ref } });
    if (onClick) {
      onClick(e);
    }
  };

  render() {
    const {
      value,
      onClick,
      router,
      pathname,
      query,
      search,
      dispatch,
      location,
      ...rest
    } = this.props;

    if (!value || !value.url) {
      return <div />;
    }

    return <Image onClick={this.onClick} value={value} {...rest} />;
  }
}
<commit_msg>cursor & hover on lighbox-image<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'olymp';
import { createComponent } from 'olymp-fela';
import Image, { cloudinaryUrl } from '../components/image';

const Img = createComponent(
  ({ theme }) => ({
    cursor: 'pointer',
    onHover: {
      opacity: 0.85,
    },
  }),
  p => <Image {...p} />,
  p => Object.keys(p)
);

@withRouter
export default class Lightbox extends Component {
  ref = Math.random().toString(36).substr(2, 9);

  static contextTypes = {
    lightbox: PropTypes.object,
  };

  componentWillMount() {
    const { value } = this.props;

    if (value) {
      this.add(value);
    }
  }

  componentWillReceiveProps({ value }) {
    const { lightbox } = this.context;

    if (value.id !== this.props.value.id) {
      lightbox.remove(this.ref);
      this.add(value);
    }
  }

  componentWillUnmount() {
    const { lightbox } = this.context;

    lightbox.remove(this.ref);
  }

  add = (value) => {
    const { lightbox } = this.context;
    const width = 800;
    const getSrcSet = w =>
      `${cloudinaryUrl(value, {
        w: Math.floor(w),
      })} ${Math.floor(w)}w`;

    lightbox.add({
      ref: this.ref,
      gallery: lightbox.gallery,
      src: cloudinaryUrl(value, { w: width }),
      srcset: [
        getSrcSet(width),
        getSrcSet(width / 4 * 3),
        getSrcSet(width / 2),
        getSrcSet(width / 4),
      ],
      thumbnail: cloudinaryUrl(value, {
        w: 50,
        h: 50,
      }),
      caption:
        value.caption && value.source
          ? `${value.caption} - ${value.source}`
          : value.caption || value.source || '',
    });
  };

  onClick = (e) => {
    const { onClick, router, pathname, query } = this.props;
    router.push({ pathname, query: { ...query, lightbox: this.ref } });
    if (onClick) {
      onClick(e);
    }
  };

  render() {
    const {
      value,
      onClick,
      router,
      pathname,
      query,
      search,
      dispatch,
      location,
      ...rest
    } = this.props;

    if (!value || !value.url) {
      return <div />;
    }

    return <Img onClick={this.onClick} value={value} {...rest} />;
  }
}
<|endoftext|>


<commit_before>/*
 * ace-scroll - jQuery UI Widget
 * Copyright (c) 2013 Jesse Baird
 *
 * Depends on:
 *   - jQuery 1.4
 *   - jQuery UI 1.8.16 (core, widget factory, draggable, position)
 *   - jQuery mousewheel plugin - Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 *
 * events
 * 	click - user clicked on track or scrollbar
 * 	scroll - the scrollPos has changed
 *
*/
(function($) {

	var abs = Math.abs;

    $.widget("jb.acescroll", {
		options: {
			scrollSpeed: 100,
			animationSpeed: 150,
			orientation: 'vertical',
			//numeric value in % or false to disable(use css value and is always that width)
			minScrollBarWidth: 10,
			//hide the scrollbar if the  content is not scrollable, show it if it is
			//TODO: make work like css overflow property, none, auto, scroll
			autoHide: true,
			//in ms how fast we check the target element for scrollChanges like resize or content chagnes
			//set to 0 to disable
			scrollChangeInterval: 500,
			position: {
				my:'left top',
                at:'right top',
                offset:'5 0',
                collision:'none'
			}
		},
		name: 'jb-ace-scroll',

		_create: function() {

			var self = this,
				options = self.options,
				element = self.element;

			//add the target class first thinng. makes sure the math for the scrollDim will be correct
			element.addClass('jb-ace-scroll-target')

            self.wrapper = $('
'+
            					'
'+
            					'
'+
            						'

'+
            						'

'+
            						'

'+
            						'
'+
            					'
'+
            				'
'
            				).insertAfter(element);

            self.scrollbar = self.wrapper.find('.jb-ace-scroll-scrollbar');

            self.isDragging = false;

            self.wrapper.addClass('jb-ace-scroll-orientation-' + options.orientation )

            if( options.orientation == 'vertical' ){
            	self._scrollProp = 'scrollTop';
            	self._axis = 'y';
            }else{
            	self._scrollProp = 'scrollLeft';
            	self._axis = 'x';
            }

            self._positionWrapper();

            //keep track if the wrapper is visible, used when we check the element for scroll changes
            self._isWrapperVisible = true;

           //track the focus event on the mouse wheel in addition to is scrollable
           var _lastmousewheelTarget = null,
           /*
            * the default browser behavior has a timer between the mouse wheel events for the "target" gets reset
            * so in the case of multipule nested scrolled elements if you mouse over the first one and use the wheel it will scroll that one even if your mouse is over a child that has scroll
            * its only when you pause for about a second on a scrollable child then the child has scroll focus
            */
           		_lastmousewheeltargetTimer = 0;

           element
            .bind( 'scroll.' + this.name,function( event ){
            	self._positionScrollbar();

            	self._eventHelper('scroll', event, {} )

            	return self._getScrollDimension('scroll', event, {} );

            })
            .bind( 'mousewheel.' + this.name , function( event, delta, deltaX, deltaY){
        		//console.log( 'mosuewheel', event, delta, deltaX, deltaY );

        		var target = event.target;
        		//console.log( target, self._isScrollable( target ) )

        		clearTimeout( _lastmousewheeltargetTimer )

        		/*
        		 * if the event target can be scrolled and is not this element, let it do so
        		 * could be a another div with scroll, textarea or another acescroll instance
        		 * Also even if it is scrollable and not the the current instance of acescroll make sure it has an
        		 * instance of acescroll called on it before stopping the scroll event.
        		 */
        		if( _lastmousewheelTarget != null ){
        			if(  self._isScrollable( target ) && target != element[ 0 ] && $(target).hasClass('.jb-ace-scroll-target') ){
	        			return;
	        		}
        		}

        		_lastmousewheelTarget = target;

        		_lastmousewheeltargetTimer = setTimeout(function(){
        			_lastmousewheelTarget = null;
        		},500)

        		//vertical
        		if( self._isVert() ){

        			   var dirY = deltaY > 0 ? 'Up' : 'Down';

		               	if( this[ self._scrollProp ] == 0 && dirY == 'Up' || this[ self._scrollProp ] + self._viewPort == this.scrollHeight && dirY=='Down'  ){
		               		//can't scroll any more
		                    return;
		                }else{
		                	//only prevent the default if we can can scroll on this element
		                	this.scrollTop = this.scrollTop - deltaY * event.deltaFactor;
		                	return false;
		                }

        		}else{
        			//horizontal
        			this.scrollLeft = this.scrollLeft + deltaX * event.deltaFactor;
        		}

            })
            .bind('resize.' + this.name, function( event ) {
            	self._positionWrapper();
            });

            /*
             * bind events on the track and scrollbar
             *
             */

            //trigger click event
            this.wrapper.delegate( 'div','mousedown', function( event ){
            	return self._eventHelper('click', event, {} )
            })
            //click on the track move to that point
            this.wrapper
            	.find('.jb-ace-scroll-track')
            	.bind('click.' + this.name, function( e ){
            		//figure out the scroll top from the e.layerY
            		if( self._isVert() ){
            			element.animate({
	                    	'scrollTop': self._pixelRatio() * e.layerY
	                	},options.animationSpeed);
            		}else{
            			element.animate({
	                    	'scrollLeft': self._pixelRatio() * e.layerX
	                	},options.animationSpeed);
            		}
            	})
            	.bind('mouseenter.' + this.name,function(){
            		self.wrapper.addClass('jb-state-hover')
            	})
            	.bind('mouseleave.' + this.name,function(){
            		if( self.isDragging == true ){
            			return;
            		}
            		self.wrapper.removeClass('jb-state-hover')
            	})
            	.bind('mousedown.' + this.name,function(){

            		self.wrapper.addClass('jb-state-active')
            	})
            	.bind('mouseup.' + this.name,function(){

            		self.wrapper.removeClass('jb-state-active')
            	})

            this.wrapper.find('div.jb-ace-scroll-scrollbar-btn')
	            .hover(function(e){
	                $(this).toggleClass('jb-state-hover')
	            })
	            //TODO this interaction is kinda funky
	            .bind('click.' + this.name ,function(e){
	            	self.isDragging = true;
	            	var done = function(){
	            		//console.log( 'done')
	            		self.isDragging = false;
	            	}
	                if( self._isVert() ){
            			element.animate({
	                    	'scrollTop':'+='+(($(this).attr('data-dir')=='up')?-self._viewPort:self._viewPort)
	                	},options.animationSpeed,done);
            		}else{
            			element.animate({
	                    	'scrollLeft':'+='+(($(this).attr('data-dir')=='up')?-self._viewPort:self._viewPort)
	                	},options.animationSpeed,done);
            		}

	            })

           this.scrollbar.draggable({
                axis: self._axis,
                containment: 'parent',

                cancel: '.jb-ace-scroll-scrollbar-btn',
                start: function( e, ui ){
                	///if the scrollHeight is the same as the clientHeight then we can scroll
                	if( self._isScrollable( element[ 0 ] ) == false ){
                		return false;
                	}
                	self.isDragging = true;
                	// $(this).addClass('jb-state-active')
                	// self.wrapper.find('.jb-ace-scroll-track').addClass('jb-state-active')
                },
                drag: function(e,ui) {
                	if( self._isVert() ){
                		element[0].scrollTop = self._pixelRatio() * ui.position.top;
                	}else{
                		element[0].scrollLeft = self._pixelRatio() * ui.position.left;
                	}

               },
               stop: function(){
                	self.isDragging = false;
                	// $(this).removeClass('jb-state-active')

                	self.wrapper.removeClass('jb-state-active jb-state-hover')
                }
            });

            //recursively called

            self._handleElementChange();
		},

		destroy: function() {
			this.wrapper.remove();
			//remove wrapper and mouse wheel events
			$(window).unbind("resize");
		},
		//TODO: fix this up
		_setOption: function( key, value) {

			//if( option == 'orientation')
			$.Widget.prototype._setOption.apply( this, arguments );

			switch( key ){
				case 'position':
					this._positionWrapper();
					break;
			}

		},
        /*
            get the ratio of pixs to the target to scroll bar
        */
        _pixelRatio: function(){
          	if( this._isVert() ){
          		return (
          				( this.element[0].scrollHeight - this._viewPort)
          				/
          				( this._viewPort - this.scrollbar.outerHeight() )
          		);
          	}else{
          		return (
          				( this.element[0].scrollWidth - this._viewPort)
          				/
          				( this._viewPort - this.scrollbar.outerWidth() )
          		);
          	}
        },
        //used to set the scrollbar in the right position within the track
        _positionScrollbar: function(){

        	if( this.isDragging ){
        		///if draggging return becuase it messes witht the view
        		return;
        	}
        	if( this._isVert() ){
        		this.scrollbar.css( 'top',  ( this.element[ 0 ].scrollTop / this._pixelRatio()) )
        	}else{
        		this.scrollbar.css( 'left',  ( this.element[ 0 ].scrollLeft / this._pixelRatio()) )
        	}

        },
        //sets the s
        _positionWrapper: function(){
            var css = {},
            	element = this.element;
            if( this._isVert() ){

            	this._viewPort = element.innerHeight();
            	css[ 'height' ] = this._viewPort;

            }else{

				this._viewPort = element.innerWidth();
            	css[ 'width' ] = this._viewPort;
            }

            this.wrapper
	            .css(css)
	            .position( $.extend( this.options.position, { of:this.element}))

	        //since the wrapper _getScrollPosition might have changed make sure the scrollbar postion is perportional to it
	       	//set the width before posiion, insures that the bar doesnt overhang on the track
	        this.setScrollBarWidth();
	        this._positionScrollbar();

        },
        _isVert: function(){
        	return ( this.options.orientation == 'vertical' ) ? true : false;
        },
        /*
         * check if an element can be scrolled
         */
        _isScrollable: function( element ){
        	//vertical check
            if( this.options.orientation == 'vertical' ){

               if( element.scrollHeight > element.clientHeight ){
                  return true;
               }
               //horizontal check
            }else if( element.scrollWidth > element.clientWidth ){
            	return true;

            }
            return false;
        },

        _eventHelper: function( eventName, event, options ){
        	var isVert = this._isVert(),
        		element = this.element[0];

        	return this._trigger(
        		eventName,
        		event,
        		$.extend(
        			{},
        			{
        				scrollDimension: this._getScrollDimension(),
        				scrollPosition: this._getScrollPosition(),
        				viewPort: this._viewPort
        			},
        			options
        		)
        	)
        },

        //make the scrollbar size relitave to the scrollHeight/Width
        setScrollBarWidth: function(){
        	//this.scrollbar
        	//disabled option
        	if( this.options.minScrollBarWidth === false ){
        		return;
        	}
        	//figure out how many "pages" are in the scrollable and devide that by 100 to get the height perenctage
        	var height = 100 / Math.ceil( this._getScrollDimension() / this._viewPort ) ;

        	//console.log( 'height ', height, this._getScrollDimension(), this.element.css('overflow') )

        	if( height < this.options.minScrollBarWidth ){
        		height = this.options.minScrollBarWidth;
        	}
        	if( this._isVert() ){
        		this.scrollbar.css( 'height', height +'%' )
        	}else{
        		this.scrollbar.css( 'width', height +'%' )
        	}

        },
        //returns scrollHeight or scrollWidth depening orentation
        _getScrollDimension: function(){
        	var element = this.element[ 0 ];
        	return ( this._isVert() ) ? element.scrollHeight : element.scrollWidth;
        },
        //get the scrollbar position
        _getScrollPosition: function(){
        	var element = this.element[ 0 ];
        	return ( this._isVert() ) ? element.scrollTop : element.scrollLeft;
        },

        /*
         * ran at an interval
         * 	catches scroll postion and changes and if the element if visible it will show / hide the scrollbar
         */
        _handleElementChange: function(){
        	var self = this,
        		isScrollable = this._isScrollable( this.element[ 0 ] );

        	if( this._getScrollDimension() != this._prevScrollDimension && this._prevScrollDimension != undefined && isScrollable == true ){

        		this.setScrollBarWidth();

        	//hide the scrollbar if not scrollable
        	}else if( isScrollable == false && this.options.autoHide == true && this._isWrapperVisible == true ){

        		this.wrapper.hide();
        		this._isWrapperVisible = false;

        	}else if( isScrollable == true && this.options.autoHide == true && this._isWrapperVisible == false ){

        		this.wrapper.show();
        		//makes sure it gets positioned on the correctly based on the visible position
        		this._positionWrapper();
        		this._isWrapperVisible = true;

        	}

        	this._prevScrollDimension = this._getScrollDimension();

        	//call again
        	if( this.options.scrollChangeInterval != 0 ){
        		setTimeout(
	        		function(){
	        			self._handleElementChange()
	        		},
	        		this.options.scrollChangeInterval
	        	);
        	}
        }

	});
})(jQuery);
<commit_msg>dead option removal<commit_after>/*
 * ace-scroll - jQuery UI Widget
 * Copyright (c) 2013 Jesse Baird
 *
 * Depends on:
 *   - jQuery 1.4
 *   - jQuery UI 1.8.16 (core, widget factory, draggable, position)
 *   - jQuery mousewheel plugin - Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 *
 * events
 * 	click - user clicked on track or scrollbar
 * 	scroll - the scrollPos has changed
 *
*/
(function($) {

	var abs = Math.abs;

    $.widget("jb.acescroll", {
		options: {
			animationSpeed: 150,
			orientation: 'vertical',
			//numeric value in % or false to disable(use css value and is always that width)
			minScrollBarWidth: 10,
			//hide the scrollbar if the  content is not scrollable, show it if it is
			//TODO: make work like css overflow property, none, auto, scroll
			autoHide: true,
			//in ms how fast we check the target element for scrollChanges like resize or content chagnes
			//set to 0 to disable
			scrollChangeInterval: 500,
			position: {
				my:'left top',
                at:'right top',
                offset:'5 0',
                collision:'none'
			}
		},
		name: 'jb-ace-scroll',

		_create: function() {

			var self = this,
				options = self.options,
				element = self.element;

			//add the target class first thinng. makes sure the math for the scrollDim will be correct
			element.addClass('jb-ace-scroll-target')

            self.wrapper = $('
'+
            					'
'+
            					'
'+
            						'

'+
            						'

'+
            						'

'+
            						'
'+
            					'
'+
            				'
'
            				).insertAfter(element);

            self.scrollbar = self.wrapper.find('.jb-ace-scroll-scrollbar');

            self.isDragging = false;

            self.wrapper.addClass('jb-ace-scroll-orientation-' + options.orientation )

            if( options.orientation == 'vertical' ){
            	self._scrollProp = 'scrollTop';
            	self._axis = 'y';
            }else{
            	self._scrollProp = 'scrollLeft';
            	self._axis = 'x';
            }

            self._positionWrapper();

            //keep track if the wrapper is visible, used when we check the element for scroll changes
            self._isWrapperVisible = true;

           //track the focus event on the mouse wheel in addition to is scrollable
           var _lastmousewheelTarget = null,
           /*
            * the default browser behavior has a timer between the mouse wheel events for the "target" gets reset
            * so in the case of multipule nested scrolled elements if you mouse over the first one and use the wheel it will scroll that one even if your mouse is over a child that has scroll
            * its only when you pause for about a second on a scrollable child then the child has scroll focus
            */
           		_lastmousewheeltargetTimer = 0;

           element
            .bind( 'scroll.' + this.name,function( event ){
            	self._positionScrollbar();

            	self._eventHelper('scroll', event, {} )

            	return self._getScrollDimension('scroll', event, {} );

            })
            .bind( 'mousewheel.' + this.name , function( event, delta, deltaX, deltaY){
        		//console.log( 'mosuewheel', event, delta, deltaX, deltaY );

        		var target = event.target;
        		//console.log( target, self._isScrollable( target ) )

        		clearTimeout( _lastmousewheeltargetTimer )

        		/*
        		 * if the event target can be scrolled and is not this element, let it do so
        		 * could be a another div with scroll, textarea or another acescroll instance
        		 * Also even if it is scrollable and not the the current instance of acescroll make sure it has an
        		 * instance of acescroll called on it before stopping the scroll event.
        		 */
        		if( _lastmousewheelTarget != null ){
        			if(  self._isScrollable( target ) && target != element[ 0 ] && $(target).hasClass('.jb-ace-scroll-target') ){
	        			return;
	        		}
        		}

        		_lastmousewheelTarget = target;

        		_lastmousewheeltargetTimer = setTimeout(function(){
        			_lastmousewheelTarget = null;
        		},500)

        		//vertical
        		if( self._isVert() ){

        			   var dirY = deltaY > 0 ? 'Up' : 'Down';

		               	if( this[ self._scrollProp ] == 0 && dirY == 'Up' || this[ self._scrollProp ] + self._viewPort == this.scrollHeight && dirY=='Down'  ){
		               		//can't scroll any more
		                    return;
		                }else{
		                	//only prevent the default if we can can scroll on this element
		                	this.scrollTop = this.scrollTop - deltaY * event.deltaFactor;
		                	return false;
		                }

        		}else{
        			//horizontal
        			this.scrollLeft = this.scrollLeft + deltaX * event.deltaFactor;
        		}

            })
            .bind('resize.' + this.name, function( event ) {
            	self._positionWrapper();
            });

            /*
             * bind events on the track and scrollbar
             *
             */

            //trigger click event
            this.wrapper.delegate( 'div','mousedown', function( event ){
            	return self._eventHelper('click', event, {} )
            })
            //click on the track move to that point
            this.wrapper
            	.find('.jb-ace-scroll-track')
            	.bind('click.' + this.name, function( e ){
            		//figure out the scroll top from the e.layerY
            		if( self._isVert() ){
            			element.animate({
	                    	'scrollTop': self._pixelRatio() * e.layerY
	                	},options.animationSpeed);
            		}else{
            			element.animate({
	                    	'scrollLeft': self._pixelRatio() * e.layerX
	                	},options.animationSpeed);
            		}
            	})
            	.bind('mouseenter.' + this.name,function(){
            		self.wrapper.addClass('jb-state-hover')
            	})
            	.bind('mouseleave.' + this.name,function(){
            		if( self.isDragging == true ){
            			return;
            		}
            		self.wrapper.removeClass('jb-state-hover')
            	})
            	.bind('mousedown.' + this.name,function(){

            		self.wrapper.addClass('jb-state-active')
            	})
            	.bind('mouseup.' + this.name,function(){

            		self.wrapper.removeClass('jb-state-active')
            	})

            this.wrapper.find('div.jb-ace-scroll-scrollbar-btn')
	            .hover(function(e){
	                $(this).toggleClass('jb-state-hover')
	            })
	            //TODO this interaction is kinda funky
	            .bind('click.' + this.name ,function(e){
	            	self.isDragging = true;
	            	var done = function(){
	            		//console.log( 'done')
	            		self.isDragging = false;
	            	}
	                if( self._isVert() ){
            			element.animate({
	                    	'scrollTop':'+='+(($(this).attr('data-dir')=='up')?-self._viewPort:self._viewPort)
	                	},options.animationSpeed,done);
            		}else{
            			element.animate({
	                    	'scrollLeft':'+='+(($(this).attr('data-dir')=='up')?-self._viewPort:self._viewPort)
	                	},options.animationSpeed,done);
            		}

	            })

           this.scrollbar.draggable({
                axis: self._axis,
                containment: 'parent',

                cancel: '.jb-ace-scroll-scrollbar-btn',
                start: function( e, ui ){
                	///if the scrollHeight is the same as the clientHeight then we can scroll
                	if( self._isScrollable( element[ 0 ] ) == false ){
                		return false;
                	}
                	self.isDragging = true;
                	// $(this).addClass('jb-state-active')
                	// self.wrapper.find('.jb-ace-scroll-track').addClass('jb-state-active')
                },
                drag: function(e,ui) {
                	if( self._isVert() ){
                		element[0].scrollTop = self._pixelRatio() * ui.position.top;
                	}else{
                		element[0].scrollLeft = self._pixelRatio() * ui.position.left;
                	}

               },
               stop: function(){
                	self.isDragging = false;
                	// $(this).removeClass('jb-state-active')

                	self.wrapper.removeClass('jb-state-active jb-state-hover')
                }
            });

            //recursively called

            self._handleElementChange();
		},

		destroy: function() {
			this.wrapper.remove();
			//remove wrapper and mouse wheel events
			$(window).unbind("resize");
		},
		//TODO: fix this up
		_setOption: function( key, value) {

			//if( option == 'orientation')
			$.Widget.prototype._setOption.apply( this, arguments );

			switch( key ){
				case 'position':
					this._positionWrapper();
					break;
			}

		},
        /*
            get the ratio of pixs to the target to scroll bar
        */
        _pixelRatio: function(){
          	if( this._isVert() ){
          		return (
          				( this.element[0].scrollHeight - this._viewPort)
          				/
          				( this._viewPort - this.scrollbar.outerHeight() )
          		);
          	}else{
          		return (
          				( this.element[0].scrollWidth - this._viewPort)
          				/
          				( this._viewPort - this.scrollbar.outerWidth() )
          		);
          	}
        },
        //used to set the scrollbar in the right position within the track
        _positionScrollbar: function(){

        	if( this.isDragging ){
        		///if draggging return becuase it messes witht the view
        		return;
        	}
        	if( this._isVert() ){
        		this.scrollbar.css( 'top',  ( this.element[ 0 ].scrollTop / this._pixelRatio()) )
        	}else{
        		this.scrollbar.css( 'left',  ( this.element[ 0 ].scrollLeft / this._pixelRatio()) )
        	}

        },
        //sets the s
        _positionWrapper: function(){
            var css = {},
            	element = this.element;
            if( this._isVert() ){

            	this._viewPort = element.innerHeight();
            	css[ 'height' ] = this._viewPort;

            }else{

				this._viewPort = element.innerWidth();
            	css[ 'width' ] = this._viewPort;
            }

            this.wrapper
	            .css(css)
	            .position( $.extend( this.options.position, { of:this.element}))

	        //since the wrapper _getScrollPosition might have changed make sure the scrollbar postion is perportional to it
	       	//set the width before posiion, insures that the bar doesnt overhang on the track
	        this.setScrollBarWidth();
	        this._positionScrollbar();

        },
        _isVert: function(){
        	return ( this.options.orientation == 'vertical' ) ? true : false;
        },
        /*
         * check if an element can be scrolled
         */
        _isScrollable: function( element ){
        	//vertical check
            if( this.options.orientation == 'vertical' ){

               if( element.scrollHeight > element.clientHeight ){
                  return true;
               }
               //horizontal check
            }else if( element.scrollWidth > element.clientWidth ){
            	return true;

            }
            return false;
        },

        _eventHelper: function( eventName, event, options ){
        	var isVert = this._isVert(),
        		element = this.element[0];

        	return this._trigger(
        		eventName,
        		event,
        		$.extend(
        			{},
        			{
        				scrollDimension: this._getScrollDimension(),
        				scrollPosition: this._getScrollPosition(),
        				viewPort: this._viewPort
        			},
        			options
        		)
        	)
        },

        //make the scrollbar size relitave to the scrollHeight/Width
        setScrollBarWidth: function(){
        	//this.scrollbar
        	//disabled option
        	if( this.options.minScrollBarWidth === false ){
        		return;
        	}
        	//figure out how many "pages" are in the scrollable and devide that by 100 to get the height perenctage
        	var height = 100 / Math.ceil( this._getScrollDimension() / this._viewPort ) ;

        	//console.log( 'height ', height, this._getScrollDimension(), this.element.css('overflow') )

        	if( height < this.options.minScrollBarWidth ){
        		height = this.options.minScrollBarWidth;
        	}
        	if( this._isVert() ){
        		this.scrollbar.css( 'height', height +'%' )
        	}else{
        		this.scrollbar.css( 'width', height +'%' )
        	}

        },
        //returns scrollHeight or scrollWidth depening orentation
        _getScrollDimension: function(){
        	var element = this.element[ 0 ];
        	return ( this._isVert() ) ? element.scrollHeight : element.scrollWidth;
        },
        //get the scrollbar position
        _getScrollPosition: function(){
        	var element = this.element[ 0 ];
        	return ( this._isVert() ) ? element.scrollTop : element.scrollLeft;
        },

        /*
         * ran at an interval
         * 	catches scroll postion and changes and if the element if visible it will show / hide the scrollbar
         */
        _handleElementChange: function(){
        	var self = this,
        		isScrollable = this._isScrollable( this.element[ 0 ] );

        	if( this._getScrollDimension() != this._prevScrollDimension && this._prevScrollDimension != undefined && isScrollable == true ){

        		this.setScrollBarWidth();

        	//hide the scrollbar if not scrollable
        	}else if( isScrollable == false && this.options.autoHide == true && this._isWrapperVisible == true ){

        		this.wrapper.hide();
        		this._isWrapperVisible = false;

        	}else if( isScrollable == true && this.options.autoHide == true && this._isWrapperVisible == false ){

        		this.wrapper.show();
        		//makes sure it gets positioned on the correctly based on the visible position
        		this._positionWrapper();
        		this._isWrapperVisible = true;

        	}

        	this._prevScrollDimension = this._getScrollDimension();

        	//call again
        	if( this.options.scrollChangeInterval != 0 ){
        		setTimeout(
	        		function(){
	        			self._handleElementChange()
	        		},
	        		this.options.scrollChangeInterval
	        	);
        	}
        }

	});
})(jQuery);
<|endoftext|>


<commit_before>/*
 @author Zakai Hamilton
 @component ManagerDownload
 */

screens.manager.download = function ManagerDownload(me) {
    me.get = async function (from, to) {
        var exists = me.core.file.exists(to);
        if (exists) {
            me.log(to + " already downloaded");
            return to;
        }
        else {
            me.log("waiting to download file: " + from + " to: " + to);
            var unlock = await me.core.mutex.lock();
            me.log("downloading file: " + from + " to: " + to);
            try {
                await me.storage.file.downloadFile(from, to);
            }
            catch (err) {
                me.log("Failed to download file: " + from + " err: " + JSON.stringify(err));
                unlock();
                throw err;
            }
            unlock();
            me.log("file downloaded: " + from + " to: " + to);
            return to;
        }
    };
    me.clean = async function (path, extensions) {
        var deleted = 0, failed = 0, skipped = 0;
        var items = null;
        try {
            items = await me.core.file.readDir(path);
        }
        catch (err) {
            me.log("Cannot read dir, err: " + err.message || err);
            throw err;
        }
        if (items) {
            for (let item of items) {
                if(extensions) {
                    var extension = me.core.path.extension(item);
                    if(!extension || !extensions.includes(extension)) {
                        skipped++;
                        continue;
                    }
                }
                try {
                    await me.core.file.delete(path + "/" + item);
                    deleted++;
                }
                catch (err) {
                    me.log("cannot delete file: " + item);
                    failed++;
                }
            }
        }
        me.queue = [];
        return {deleted, failed, skipped};
    };
    return "server";
};<commit_msg>removing log<commit_after>/*
 @author Zakai Hamilton
 @component ManagerDownload
 */

screens.manager.download = function ManagerDownload(me) {
    me.get = async function (from, to) {
        var exists = me.core.file.exists(to);
        if (exists) {
            return to;
        }
        else {
            me.log("waiting to download file: " + from + " to: " + to);
            var unlock = await me.core.mutex.lock();
            me.log("downloading file: " + from + " to: " + to);
            try {
                await me.storage.file.downloadFile(from, to);
            }
            catch (err) {
                me.log("Failed to download file: " + from + " err: " + JSON.stringify(err));
                unlock();
                throw err;
            }
            unlock();
            me.log("file downloaded: " + from + " to: " + to);
            return to;
        }
    };
    me.clean = async function (path, extensions) {
        var deleted = 0, failed = 0, skipped = 0;
        var items = null;
        try {
            items = await me.core.file.readDir(path);
        }
        catch (err) {
            me.log("Cannot read dir, err: " + err.message || err);
            throw err;
        }
        if (items) {
            for (let item of items) {
                if(extensions) {
                    var extension = me.core.path.extension(item);
                    if(!extension || !extensions.includes(extension)) {
                        skipped++;
                        continue;
                    }
                }
                try {
                    await me.core.file.delete(path + "/" + item);
                    deleted++;
                }
                catch (err) {
                    me.log("cannot delete file: " + item);
                    failed++;
                }
            }
        }
        me.queue = [];
        return {deleted, failed, skipped};
    };
    return "server";
};<|endoftext|>


<commit_before>module.exports = (db, Sequelize) => {
  const Message = db.define('message', {
    id: {
      type: Sequelize.INTEGER,
      autoIncrement: true,
      primaryKey: true,
    },
    title: Sequelize.STRING,
    body: Sequelize.STRING,
  });

  return Message;
};
<commit_msg>Change message schema<commit_after>module.exports = (db, Sequelize) => {
  const Message = db.define('message', {
    id: {
      type: Sequelize.INTEGER,
      autoIncrement: true,
      primaryKey: true,
    },
    title: Sequelize.STRING,
    body: Sequelize.TEXT,
  });

  return Message;
};
<|endoftext|>


<commit_before>/* globals define jQuery */
(function (factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define([ 'jquery' ], factory)
  } else {
    // Browser globals
    factory(jQuery)
  }
}(function ($) {
  $.widget('ui.rotatable', $.ui.mouse, {
    widgetEventPrefix: 'rotate',

    options: {
      angle: false,       // specify an angle in radians (for backward compatability)
      degrees: false,     // specify angle in degrees
      handle: false,      // an image to use for a handle
      handleOffset: {     // where the handle should appear
        top: 0,
        left: 0
      },
      radians: false,     // specify angle in radians
      rotate: null,       // a callback for during rotation
      rotationCenterOffset: {   // offset the center of the element for rotation
        top: 0,
        left: 0
      },
      snap: false,        // boolean flag, should the element snap to a certain rotation?
      start: null,        // callback when rotation starts
      step: 22.5,         // angle in degrees that the rotation should be snapped to
      stop: null,         // callback when rotation stops
      transforms: null,   // other transforms to performed on the element
      wheelRotate: true   // boolean flag, should the element rotate when the mousewheel is rotated?
    },

    // accessor for the angle in radians
    angle: function (angle) {
      if (angle === undefined) {
        return this.options.angle
      }
      this.options.angle = angle
      this.elementCurrentAngle = angle
      this._performRotation(this.options.angle)
    },

    // calculates the element center if needed and returns it
    getElementCenter: function () {
      if (this.elementCenter == null) {
        this.elementCenter = this._calculateElementCenter()
      }

      return this.elementCenter
    },

    // accessor for the handle
    handle: function (handle) {
      if (handle === undefined) {
        return this.options.handle
      }
      this.options.handle = handle
    },

    plugins: {},

    /* accessor for the center of rotation
    * takes an object with keys of top and left
    */
    rotationCenterOffset: function (offset) {
      if (offset === undefined) {
        return this.options.rotationCenterOffset
      }
      if (offset.top !== null) {
        this.options.rotationCenterOffset.top = offset.top
      }
      if (offset.left !== null) {
        this.options.rotationCenterOffset.left = offset.left
      }
    },

    // listener for rotating the element
    rotateElement: function (event) {
      if (!this.element || this.element.disabled) {
        return false
      }

      if (!event.which) {
        this.stopRotate(event)
        return false
      }

      var rotateAngle = this._calculateRotateAngle(event)
      var previousRotateAngle = this.elementCurrentAngle
      this.elementCurrentAngle = rotateAngle

        // Plugins callbacks need to be called first.
      this._propagate('rotate', event)

      if (this._propagate('rotate', event) === false) {
        this.elementCurrentAngle = previousRotateAngle
        return false
      }
      var ui = this.ui()
      if (this._trigger('rotate', event, ui) === false) {
        this.elementCurrentAngle = previousRotateAngle
        return false
      } else if (ui.angle.current !== rotateAngle) {
        rotateAngle = ui.angle.current
        this.elementCurrentAngle = rotateAngle
      }

      this._performRotation(rotateAngle)

      if (previousRotateAngle !== rotateAngle) {
        this.hasRotated = true
      }

      return false
    },

    // listener for starting rotation
    startRotate: function (event) {
      var center = this.getElementCenter()
      var startXFromCenter = event.pageX - center.x
      var startYFromCenter = event.pageY - center.y
      this.mouseStartAngle = Math.atan2(startYFromCenter, startXFromCenter)
      this.elementStartAngle = this.elementCurrentAngle
      this.hasRotated = false

      this._propagate('start', event)

      $(document).bind('mousemove', this.listeners.rotateElement)
      $(document).bind('mouseup', this.listeners.stopRotate)

      return false
    },

    // listener for stopping rotation
    stopRotate: function (event) {
      if (!this.element || this.element.disabled) {
        return
      }

      $(document).unbind('mousemove', this.listeners.rotateElement)
      $(document).unbind('mouseup', this.listeners.stopRotate)

      this.elementStopAngle = this.elementCurrentAngle

      this._propagate('stop', event)

      setTimeout(function () { this.element = false }, 10)
      return false
    },

    // listener for mousewheel rotation
    wheelRotate: function (event) {
      var angle = this._angleInRadians(Math.round(event.originalEvent.deltaY / 10))
      if (this.options.snap || event.shiftKey) {
        angle = this._calculateSnap(angle)
      }
      angle = this.elementCurrentAngle + angle
      this.angle(angle)
      this._trigger('rotate', event, this.ui())
    },

    // for callbacks
    ui: function () {
      return {
        api: this,
        element: this.element,
        angle: {
          start: this.elementStartAngle,
          current: this.elementCurrentAngle,
          stop: this.elementStopAngle
        }
      }
    },

/* *********************** private functions ************************** */
    // calculates the radians for a given angle in degrees
    _angleInRadians: function (degrees) {
      return degrees * Math.PI / 180
    },

    // calculates the degrees for a given angle in radians
    _angleInDegrees: function (radians) {
      return radians * 180 / Math.PI
    },

    // calculates the center of the element
    _calculateElementCenter: function () {
      var elementOffset = this._getElementOffset()

      // Rotation center given via options
      if (this._isRotationCenterSet()) {
        return {
          x: elementOffset.left + this.rotationCenterOffset().left,
          y: elementOffset.top + this.rotationCenterOffset().top
        }
      }

      // Deduce rotation center from transform-origin
      if (this.element.css('transform-origin') !== undefined) {
        var originPx = this.element.css('transform-origin').match(/([\d.]+)px +([\d.]+)px/)
        if (originPx != null) {
          return {
            x: elementOffset.left + parseFloat(originPx[1]),
            y: elementOffset.top + parseFloat(originPx[2])
          }
        }
      }

      // Default rotation center: middle of the element
      return {
        x: elementOffset.left + this.element.width() / 2,
        y: elementOffset.top + this.element.height() / 2
      }
    },

    // calculates the angle that the element should snap to and returns it in radians
    _calculateSnap: function (radians) {
      var degrees = this._angleInDegrees(radians)
      degrees = Math.round(degrees / this.options.step) * this.options.step
      return this._angleInRadians(degrees)
    },

    // calculates the angle to rotate the element to, based on input
    _calculateRotateAngle: function (event) {
      var center = this.getElementCenter()

      var xFromCenter = event.pageX - center.x
      var yFromCenter = event.pageY - center.y
      var mouseAngle = Math.atan2(yFromCenter, xFromCenter)
      var rotateAngle = mouseAngle - this.mouseStartAngle + this.elementStartAngle

      if (this.options.snap || event.shiftKey) {
        rotateAngle = this._calculateSnap(rotateAngle)
      }

      return rotateAngle
    },

    // constructor
    _create: function () {
      var handle
      if (!this.options.handle) {
        handle = $(document.createElement('div'))
        handle.addClass('ui-rotatable-handle')
        if (this.options.handleOffset.top !== 0 || this.options.handleOffset.left !== 0) {
          handle.css('position', 'relative')
          handle.css('top', this.options.handleOffset.top + 'px')
          handle.css('left', this.options.handleOffset.left + 'px')
        }
      } else {
        handle = this.options.handle
      }

      this.listeners = {
        rotateElement: $.proxy(this.rotateElement, this),
        startRotate: $.proxy(this.startRotate, this),
        stopRotate: $.proxy(this.stopRotate, this),
        wheelRotate: $.proxy(this.wheelRotate, this)
      }

      if (this.options.wheelRotate) {
        this.element.bind('wheel', this.listeners.wheelRotate)
      }

      handle.draggable({ helper: 'clone', start: this._dragStart, handle: handle })
      handle.bind('mousedown', this.listeners.startRotate)

      if (!handle.closest(this.element).length) {
        handle.appendTo(this.element)
      }
      this.rotationCenterOffset(this.options.rotationCenterOffset)

      if (this.options.degrees) {
        this.elementCurrentAngle = this._angleInRadians(this.options.degrees)
      }
      this.elementCurrentAngle = this.options.radians || this.options.angle || 0
      this._performRotation(this.elementCurrentAngle)
    },

    // destructor
    _destroy: function () {
      this.element.removeClass('ui-rotatable')
      this.element.find('.ui-rotatable-handle').remove()

      if (this.options.wheelRotate) {
        this.element.unbind('wheel', this.listeners.wheelRotate)
      }
    },

    // used for the handle
    _dragStart: function (event) {
      if (this.element) {
        return false
      }
    },

    // retrieves the element offset
    _getElementOffset: function () {
      this._performRotation(0)
      var offset = this.element.offset()
      this._performRotation(this.elementCurrentAngle)
      return offset
    },

    _getTransforms: function (angle) {
      var transforms = 'rotate(' + angle + 'rad)'

      if (this.options.transforms) {
        transforms += ' ' + (function (transforms) {
          var t = []
          for (var i in transforms) {
            if (transforms.hasOwnProperty(i) && transforms[i]) {
              t.push(i + '(' + transforms[i] + ')')
            }
          }
          return t.join(' ')
        }(this.options.transforms))
      }
      return transforms
    },

    // checks to see if the element has a rotationCenterOffset set
    _isRotationCenterSet: function () {
      return (this.options.rotationCenterOffset.top !== 0 || this.options.rotationCenterOffset.left !== 0)
    },

    // performs the actual rotation on the element
    _performRotation: function (angle) {
      if (this._isRotationCenterSet()) {
        this.element.css('transform-origin', this.options.rotationCenterOffset.left + 'px ' + this.options.rotationCenterOffset.top + 'px')
        this.element.css('-ms-transform-origin', this.options.rotationCenterOffset.left + 'px ' + this.options.rotationCenterOffset.top + 'px') /* IE 9 */
        this.element.css('-webkit-transform-origin', this.options.rotationCenterOffset.left + 'px ' + this.options.rotationCenterOffset + 'px') /* Chrome, Safari, Opera */
      }

      var transforms = this._getTransforms(angle)

      this.element.css('transform', transforms)
      this.element.css('-moz-transform', transforms)
      this.element.css('-webkit-transform', transforms)
      this.element.css('-o-transform', transforms)
    },

    // propagates events
    _propagate: function (n, event) {
      $.ui.plugin.call(this, n, [event, this.ui()]);
      (n !== 'rotate' && this._trigger(n, event, this.ui()))
    }
  })

  return $.ui.rotatable
}))
<commit_msg>Fixes bug #39<commit_after>/* globals define jQuery */
(function (factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define([ 'jquery' ], factory)
  } else {
    // Browser globals
    factory(jQuery)
  }
}(function ($) {
  $.widget('ui.rotatable', $.ui.mouse, {
    widgetEventPrefix: 'rotate',

    options: {
      angle: false,       // specify an angle in radians (for backward compatability)
      degrees: false,     // specify angle in degrees
      handle: false,      // an image to use for a handle
      handleOffset: {     // where the handle should appear
        top: 0,
        left: 0
      },
      radians: false,     // specify angle in radians
      rotate: null,       // a callback for during rotation
      rotationCenterOffset: {   // offset the center of the element for rotation
        top: 0,
        left: 0
      },
      snap: false,        // boolean flag, should the element snap to a certain rotation?
      start: null,        // callback when rotation starts
      step: 22.5,         // angle in degrees that the rotation should be snapped to
      stop: null,         // callback when rotation stops
      transforms: null,   // other transforms to performed on the element
      wheelRotate: true   // boolean flag, should the element rotate when the mousewheel is rotated?
    },

    // accessor for the angle in radians
    angle: function (angle) {
      if (angle === undefined) {
        return this.options.angle
      }
      this.options.angle = angle
      this.elementCurrentAngle = angle
      this._performRotation(this.options.angle)
    },

    // calculates the element center if needed and returns it
    getElementCenter: function () {
      if (this.elementCenter == null) {
        this.elementCenter = this._calculateElementCenter()
      }

      return this.elementCenter
    },

    // accessor for the handle
    handle: function (handle) {
      if (handle === undefined) {
        return this.options.handle
      }
      this.options.handle = handle
    },

    plugins: {},

    /* accessor for the center of rotation
    * takes an object with keys of top and left
    */
    rotationCenterOffset: function (offset) {
      if (offset === undefined) {
        return this.options.rotationCenterOffset
      }
      if (offset.top !== null) {
        this.options.rotationCenterOffset.top = offset.top
      }
      if (offset.left !== null) {
        this.options.rotationCenterOffset.left = offset.left
      }
    },

    // listener for rotating the element
    rotateElement: function (event) {
      if (!this.element || this.element.disabled || this.options.disabled) {
        return false
      }

      if (!event.which) {
        this.stopRotate(event)
        return false
      }

      var rotateAngle = this._calculateRotateAngle(event)
      var previousRotateAngle = this.elementCurrentAngle
      this.elementCurrentAngle = rotateAngle

        // Plugins callbacks need to be called first.
      this._propagate('rotate', event)

      if (this._propagate('rotate', event) === false) {
        this.elementCurrentAngle = previousRotateAngle
        return false
      }
      var ui = this.ui()
      if (this._trigger('rotate', event, ui) === false) {
        this.elementCurrentAngle = previousRotateAngle
        return false
      } else if (ui.angle.current !== rotateAngle) {
        rotateAngle = ui.angle.current
        this.elementCurrentAngle = rotateAngle
      }

      this._performRotation(rotateAngle)

      if (previousRotateAngle !== rotateAngle) {
        this.hasRotated = true
      }

      return false
    },

    // listener for starting rotation
    startRotate: function (event) {
      var center = this.getElementCenter()
      var startXFromCenter = event.pageX - center.x
      var startYFromCenter = event.pageY - center.y
      this.mouseStartAngle = Math.atan2(startYFromCenter, startXFromCenter)
      this.elementStartAngle = this.elementCurrentAngle
      this.hasRotated = false

      this._propagate('start', event)

      $(document).bind('mousemove', this.listeners.rotateElement)
      $(document).bind('mouseup', this.listeners.stopRotate)

      return false
    },

    // listener for stopping rotation
    stopRotate: function (event) {
      if (!this.element || this.element.disabled) {
        return
      }

      $(document).unbind('mousemove', this.listeners.rotateElement)
      $(document).unbind('mouseup', this.listeners.stopRotate)

      this.elementStopAngle = this.elementCurrentAngle

      this._propagate('stop', event)

      setTimeout(function () { this.element = false }, 10)
      return false
    },

    // listener for mousewheel rotation
    wheelRotate: function (event) {
      var angle = this._angleInRadians(Math.round(event.originalEvent.deltaY / 10))
      if (this.options.snap || event.shiftKey) {
        angle = this._calculateSnap(angle)
      }
      angle = this.elementCurrentAngle + angle
      this.angle(angle)
      this._trigger('rotate', event, this.ui())
    },

    // for callbacks
    ui: function () {
      return {
        api: this,
        element: this.element,
        angle: {
          start: this.elementStartAngle,
          current: this.elementCurrentAngle,
          stop: this.elementStopAngle
        }
      }
    },

/* *********************** private functions ************************** */
    // calculates the radians for a given angle in degrees
    _angleInRadians: function (degrees) {
      return degrees * Math.PI / 180
    },

    // calculates the degrees for a given angle in radians
    _angleInDegrees: function (radians) {
      return radians * 180 / Math.PI
    },

    // calculates the center of the element
    _calculateElementCenter: function () {
      var elementOffset = this._getElementOffset()

      // Rotation center given via options
      if (this._isRotationCenterSet()) {
        return {
          x: elementOffset.left + this.rotationCenterOffset().left,
          y: elementOffset.top + this.rotationCenterOffset().top
        }
      }

      // Deduce rotation center from transform-origin
      if (this.element.css('transform-origin') !== undefined) {
        var originPx = this.element.css('transform-origin').match(/([\d.]+)px +([\d.]+)px/)
        if (originPx != null) {
          return {
            x: elementOffset.left + parseFloat(originPx[1]),
            y: elementOffset.top + parseFloat(originPx[2])
          }
        }
      }

      // Default rotation center: middle of the element
      return {
        x: elementOffset.left + this.element.width() / 2,
        y: elementOffset.top + this.element.height() / 2
      }
    },

    // calculates the angle that the element should snap to and returns it in radians
    _calculateSnap: function (radians) {
      var degrees = this._angleInDegrees(radians)
      degrees = Math.round(degrees / this.options.step) * this.options.step
      return this._angleInRadians(degrees)
    },

    // calculates the angle to rotate the element to, based on input
    _calculateRotateAngle: function (event) {
      var center = this.getElementCenter()

      var xFromCenter = event.pageX - center.x
      var yFromCenter = event.pageY - center.y
      var mouseAngle = Math.atan2(yFromCenter, xFromCenter)
      var rotateAngle = mouseAngle - this.mouseStartAngle + this.elementStartAngle

      if (this.options.snap || event.shiftKey) {
        rotateAngle = this._calculateSnap(rotateAngle)
      }

      return rotateAngle
    },

    // constructor
    _create: function () {
      var handle
      if (!this.options.handle) {
        handle = $(document.createElement('div'))
        handle.addClass('ui-rotatable-handle')
        if (this.options.handleOffset.top !== 0 || this.options.handleOffset.left !== 0) {
          handle.css('position', 'relative')
          handle.css('top', this.options.handleOffset.top + 'px')
          handle.css('left', this.options.handleOffset.left + 'px')
        }
      } else {
        handle = this.options.handle
      }

      this.listeners = {
        rotateElement: $.proxy(this.rotateElement, this),
        startRotate: $.proxy(this.startRotate, this),
        stopRotate: $.proxy(this.stopRotate, this),
        wheelRotate: $.proxy(this.wheelRotate, this)
      }

      if (this.options.wheelRotate) {
        this.element.bind('wheel', this.listeners.wheelRotate)
      }

      handle.draggable({ helper: 'clone', start: this._dragStart, handle: handle })
      handle.bind('mousedown', this.listeners.startRotate)

      if (!handle.closest(this.element).length) {
        handle.appendTo(this.element)
      }
      this.rotationCenterOffset(this.options.rotationCenterOffset)

      if (this.options.degrees) {
        this.elementCurrentAngle = this._angleInRadians(this.options.degrees)
      }
      this.elementCurrentAngle = this.options.radians || this.options.angle || 0
      this._performRotation(this.elementCurrentAngle)
    },

    // destructor
    _destroy: function () {
      this.element.removeClass('ui-rotatable')
      this.element.find('.ui-rotatable-handle').remove()

      if (this.options.wheelRotate) {
        this.element.unbind('wheel', this.listeners.wheelRotate)
      }
    },

    // used for the handle
    _dragStart: function (event) {
      if (this.element) {
        return false
      }
    },

    // retrieves the element offset
    _getElementOffset: function () {
      this._performRotation(0)
      var offset = this.element.offset()
      this._performRotation(this.elementCurrentAngle)
      return offset
    },

    _getTransforms: function (angle) {
      var transforms = 'rotate(' + angle + 'rad)'

      if (this.options.transforms) {
        transforms += ' ' + (function (transforms) {
          var t = []
          for (var i in transforms) {
            if (transforms.hasOwnProperty(i) && transforms[i]) {
              t.push(i + '(' + transforms[i] + ')')
            }
          }
          return t.join(' ')
        }(this.options.transforms))
      }
      return transforms
    },

    // checks to see if the element has a rotationCenterOffset set
    _isRotationCenterSet: function () {
      return (this.options.rotationCenterOffset.top !== 0 || this.options.rotationCenterOffset.left !== 0)
    },

    // performs the actual rotation on the element
    _performRotation: function (angle) {
      if (this._isRotationCenterSet()) {
        this.element.css('transform-origin', this.options.rotationCenterOffset.left + 'px ' + this.options.rotationCenterOffset.top + 'px')
        this.element.css('-ms-transform-origin', this.options.rotationCenterOffset.left + 'px ' + this.options.rotationCenterOffset.top + 'px') /* IE 9 */
        this.element.css('-webkit-transform-origin', this.options.rotationCenterOffset.left + 'px ' + this.options.rotationCenterOffset + 'px') /* Chrome, Safari, Opera */
      }

      var transforms = this._getTransforms(angle)

      this.element.css('transform', transforms)
      this.element.css('-moz-transform', transforms)
      this.element.css('-webkit-transform', transforms)
      this.element.css('-o-transform', transforms)
    },

    // propagates events
    _propagate: function (n, event) {
      $.ui.plugin.call(this, n, [event, this.ui()]);
      (n !== 'rotate' && this._trigger(n, event, this.ui()))
    }
  })

  return $.ui.rotatable
}))
<|endoftext|>


<commit_before>// Copyright 2018, University of Colorado Boulder

/**
 * Tests for Enumeration
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
define( function( require ) {
  'use strict';

  // modules
  const Enumeration = require( 'PHET_CORE/Enumeration' );

  QUnit.module( 'Enumeration' );

  QUnit.test( 'Basic enumeration', function( assert ) {
    const CardinalDirection = new Enumeration( [ 'NORTH', 'SOUTH', 'EAST', 'WEST' ] );

    assert.equal( CardinalDirection.NORTH, 'NORTH', 'Equality for NORTH' );
    assert.equal( CardinalDirection.SOUTH, 'SOUTH', 'Equality for SOUTH' );
    assert.equal( CardinalDirection.EAST, 'EAST', 'Equality for EAST' );
    assert.equal( CardinalDirection.WEST, 'WEST', 'Equality for WEST' );

    assert.equal( CardinalDirection.includes( CardinalDirection.NORTH ), true, 'NORTH is in the enumeration' );
    assert.equal( CardinalDirection.includes( 'NORTH' ), false, 'Strings shouln\'t match' );
    assert.equal( CardinalDirection.includes( 'YORKSHIRE_TERRIER_WITH_THE_CANDLE_STICK_IN_THE_BALLROOM' ), false,
      'Not in the enumeration' );
    assert.equal( CardinalDirection.includes( { name: 'NORTH' } ), false, 'Should not be able to synthesize Enumeration values' );

    // Test toString
    var object = {};
    object[ CardinalDirection.NORTH ] = 'exit';
    assert.equal( object.NORTH, 'exit', 'toString should work seamlessly' );

    window.assert && assert.throws( function() {
      CardinalDirection.SOMETHING_AFTER_THE_FREEZE = 5;
    }, 'Should not be able to set things after initialization' );

    window.assert && assert.throws( function() {
      const x = new Enumeration( [ 'lowercase', 'should', 'fail' ] );
      assert.ok( !!x, 'fake assertion so x is used' );
    }, 'Enumeration should fail for lowercase values' );
  } );

  QUnit.test( 'Before freeze test', function( assert ) {
    const E = new Enumeration( [ 'A', 'B' ], E => {
      E.opposite = e => {
        window.assert && window.assert( E.includes( e ) );
        return e === E.A ? E.B : E.A;
      };
    } );

    assert.equal( E.A, 'A', 'Equality for A' );
    assert.equal( E.B, 'B', 'Equality for B' );
    assert.equal( E.opposite( E.A ), E.B, 'Custom function check 1' );
    assert.equal( E.opposite( E.B ), E.A, 'Custom function check 2' );

    window.assert && assert.throws( function() {
      E.SOMETHING_AFTER_THE_FREEZE = 5;
    }, 'Should not be able to set things after initialization' );
  } );

  QUnit.test( 'VALUES', function( assert ) {
    const People = new Enumeration( [ 'ALICE', 'BOB' ] );
    window.assert && assert.throws( () => {
      People.VALUES = 'something else';
    }, 'Setting values after initialization should throw an error.' );
  } );
} );
<commit_msg>Add one assertion so tests can run without ?ea<commit_after>// Copyright 2018, University of Colorado Boulder

/**
 * Tests for Enumeration
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
define( function( require ) {
  'use strict';

  // modules
  const Enumeration = require( 'PHET_CORE/Enumeration' );

  QUnit.module( 'Enumeration' );

  QUnit.test( 'Basic enumeration', function( assert ) {
    const CardinalDirection = new Enumeration( [ 'NORTH', 'SOUTH', 'EAST', 'WEST' ] );

    assert.equal( CardinalDirection.NORTH, 'NORTH', 'Equality for NORTH' );
    assert.equal( CardinalDirection.SOUTH, 'SOUTH', 'Equality for SOUTH' );
    assert.equal( CardinalDirection.EAST, 'EAST', 'Equality for EAST' );
    assert.equal( CardinalDirection.WEST, 'WEST', 'Equality for WEST' );

    assert.equal( CardinalDirection.includes( CardinalDirection.NORTH ), true, 'NORTH is in the enumeration' );
    assert.equal( CardinalDirection.includes( 'NORTH' ), false, 'Strings shouln\'t match' );
    assert.equal( CardinalDirection.includes( 'YORKSHIRE_TERRIER_WITH_THE_CANDLE_STICK_IN_THE_BALLROOM' ), false,
      'Not in the enumeration' );
    assert.equal( CardinalDirection.includes( { name: 'NORTH' } ), false, 'Should not be able to synthesize Enumeration values' );

    // Test toString
    var object = {};
    object[ CardinalDirection.NORTH ] = 'exit';
    assert.equal( object.NORTH, 'exit', 'toString should work seamlessly' );

    window.assert && assert.throws( function() {
      CardinalDirection.SOMETHING_AFTER_THE_FREEZE = 5;
    }, 'Should not be able to set things after initialization' );

    window.assert && assert.throws( function() {
      const x = new Enumeration( [ 'lowercase', 'should', 'fail' ] );
      assert.ok( !!x, 'fake assertion so x is used' );
    }, 'Enumeration should fail for lowercase values' );
  } );

  QUnit.test( 'Before freeze test', function( assert ) {
    const E = new Enumeration( [ 'A', 'B' ], E => {
      E.opposite = e => {
        window.assert && window.assert( E.includes( e ) );
        return e === E.A ? E.B : E.A;
      };
    } );

    assert.equal( E.A, 'A', 'Equality for A' );
    assert.equal( E.B, 'B', 'Equality for B' );
    assert.equal( E.opposite( E.A ), E.B, 'Custom function check 1' );
    assert.equal( E.opposite( E.B ), E.A, 'Custom function check 2' );

    window.assert && assert.throws( function() {
      E.SOMETHING_AFTER_THE_FREEZE = 5;
    }, 'Should not be able to set things after initialization' );
  } );

  QUnit.test( 'VALUES', function( assert ) {
    const People = new Enumeration( [ 'ALICE', 'BOB' ] );
    assert.ok( true, 'at least one assertion must run per test' );
    window.assert && assert.throws( () => {
      People.VALUES = 'something else';
    }, 'Setting values after initialization should throw an error.' );
  } );
} );
<|endoftext|>


<commit_before><commit_msg>update to twitter vm<commit_after>var my = my || {};

my.TweetsVm = (function () {
    var _handle = '@PicenoWines';
    var _twitterApiUrl = "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name="+_handle;
    var _tweets = ko.observableArray();
    var SetTweets = function(response){
        var tweets = response;
    };
    var GetTweets = function () {
        $get(_twitterApiUrl, SetTweets);
    };
    // This would be the 'revealing' part
    // you define the implementations above, and
    // decide what you expose via the object literal below
    return {
        GetTweets: GetTweets,
        Tweets:  _tweets
    };
})();
 <|endoftext|>


<commit_before>VISH.Editor.Quiz = (function(V,$,undefined){

	var _hiddenLinkToInitQuizSettings;

	var init = function(){
		V.Editor.Quiz.MC.init();
		V.Editor.Quiz.TF.init();
		V.Editor.Quiz.Sorting.init();
		V.Editor.Quiz.Open.init();

		//Quiz Settings
		_hiddenLinkToInitQuizSettings = $('');
		$(_hiddenLinkToInitQuizSettings).fancybox({
			'autoDimensions' : false,
			'height': 360,
			'width': 400,
			'scrolling': 'no',
			'showCloseButton': false,
			'padding' : 0,
			"onStart"  : function(data){
				var qSF = $("#quizSettings_fancybox");

				//Load Quiz
				var quiz = V.Editor.getCurrentArea();
				var quizType = $(quiz).attr("quiztype");
				var quizModule = _getQuizModule(quizType);
				$(qSF).find("input[type='hidden'][name='elId']").val($(quiz).attr("id"));

				//Load Settings
				var qSettings = $(quiz).attr("elSettings");
				var nAttempts = 1;
				var quizScore = 10;
				var shuffleChoices = false;
				var disableShuffleChoices = false;
				var ARSEnabled = false;

				if(typeof qSettings == "string"){
					try {
						qSettings = JSON.parse(qSettings);

						if(typeof qSettings.nAttempts != "undefined"){
							nAttempts = qSettings.nAttempts;
						}
						if(typeof qSettings.quizScore != "undefined"){
							quizScore = qSettings.quizScore;
						}
						if(qSettings.ARSEnabled===true){
							ARSEnabled = true;
						}
						if(qSettings.shuffleChoices===true){
							shuffleChoices = true;
						}
					} catch(e){}
				}

				//Force options by quiz type
				switch(quizType){
					case V.Constant.QZ_TYPE.OPEN:
						shuffleChoices = false;
						disableShuffleChoices = true;
						break;
					case V.Constant.QZ_TYPE.MCHOICE:
						break;
					case V.Constant.QZ_TYPE.TF:
						break;
					case V.Constant.QZ_TYPE.SORTING:
						shuffleChoices = true;
						disableShuffleChoices = true;
						break;
					default:
						break;
				};

				//Fill and reset form

				var isSelfAssessment = false;
				if((quizModule)&&(typeof quizModule.isSelfAssessment == "function")){
					isSelfAssessment = quizModule.isSelfAssessment(quiz);
				}

				//Number of Attempts
				var nAttemptsDOM = $(qSF).find("#quizSettings_nAttempts");
				if(!isSelfAssessment){
					//Disable nAttempts
					$(nAttemptsDOM).prop('disabled',true);
					$(nAttemptsDOM).parent().addClass("disableSettingsField");
					$(nAttemptsDOM).val(1);
				} else {
					$(nAttemptsDOM).prop('disabled',false);
					$(nAttemptsDOM).parent().removeClass("disableSettingsField");
					$(nAttemptsDOM).val(nAttempts);
				}

				//Quiz score
				var quizScoreDOM = $(qSF).find("select[name='quizScorePoints']");
				if(!isSelfAssessment){
					//Disable quizScore
					$(quizScoreDOM).prop('disabled',true);
					$(quizScoreDOM).parent().addClass("disableSettingsField");
					$(quizScoreDOM).val(0);
				} else {
					$(quizScoreDOM).prop('disabled',false);
					$(quizScoreDOM).parent().removeClass("disableSettingsField");
					$(quizScoreDOM).val(quizScore);
				}

				//Shuffle Choices
				var shuffleChoicesCheckbox = $(qSF).find("input[type='checkbox'][name='shuffleChoices']");
				$(shuffleChoicesCheckbox).prop('checked', shuffleChoices);
				if(disableShuffleChoices){
					$(shuffleChoicesCheckbox).parent().addClass("disableSettingsField");
					$(shuffleChoicesCheckbox).attr('disabled', 'disabled');
				} else {
					$(shuffleChoicesCheckbox).parent().removeClass("disableSettingsField");
					$(shuffleChoicesCheckbox).removeAttr('disabled');
				}

				//ARS Enabled
				var ARSEnabledCheckbox = $(qSF).find("input[type='checkbox'][name='enableARS']");
				$(ARSEnabledCheckbox).prop('checked', ARSEnabled);

				// //Post actions
				// switch(quizType){
				// 	case V.Constant.QZ_TYPE.OPEN:
				// 		break;
				// 	case V.Constant.QZ_TYPE.MCHOICE:
				// 		break;
				// 	case V.Constant.QZ_TYPE.TF:
				// 		break;
				// 	case V.Constant.QZ_TYPE.SORTING:
				// 		break;
				// 	default:
				// 		break;
				// };
			},
			"onComplete" : function(data){
			},
			"onClosed"  : function(data){
			}
		});
	};

	var onQuizSettingsDone = function(){
		//Get Settings
		var qSF = $("#quizSettings_fancybox");
		var qSettings = {};

		var nAttemptsDOM = $(qSF).find("#quizSettings_nAttempts");
		if(!$(nAttemptsDOM).is(":disabled")){
			qSettings.nAttempts = $(nAttemptsDOM).val();
		}

		var quizScoreDOM = $(qSF).find("select[name='quizScorePoints']");
		if(!$(quizScoreDOM).is(":disabled")){
			qSettings.quizScore = $(quizScoreDOM).val();
		}

		qSettings.shuffleChoices = $(qSF).find("input[type='checkbox'][name='shuffleChoices']").is(":checked");
		qSettings.ARSEnabled = $(qSF).find("input[type='checkbox'][name='enableARS']").is(":checked");

		//Get quiz
		var quizId = $(qSF).find("input[type='hidden'][name='elId']").val();
		var quiz = $("#"+quizId);

		//Save Settings
		var qSSerialized = JSON.stringify(qSettings);
		$(quiz).attr("elSettings",qSSerialized);

		$.fancybox.close();
	};

	/*
	 * Quiz modules
	 */
	var _getQuizModule = function(quiz_type){
		switch(quiz_type){
			case V.Constant.QZ_TYPE.OPEN:
				return V.Editor.Quiz.Open;
				break;
			case V.Constant.QZ_TYPE.MCHOICE:
				return V.Editor.Quiz.MC;
				break;
			case V.Constant.QZ_TYPE.TF:
				return V.Editor.Quiz.TF;
				break;
			case V.Constant.QZ_TYPE.SORTING:
				return V.Editor.Quiz.Sorting;
				break;
			default:
				return null;
				break;
		}
	};

	/*
	 * Add a new Quiz
	 */
	var add = function(quizType,area){
		var current_area;
		if(area) {
			current_area = area;
		} else {
			current_area = V.Editor.getCurrentArea();
		}

		if(_getQuizModule(quizType)){
			_getQuizModule(quizType).add(current_area);
		}

		$.fancybox.close();
	};

	/*
	 * return quiz in JSON
	 */
	var save = function(area){
		var current_area;
		if(area) {
			current_area = area;
		} else {
			current_area = V.Editor.getCurrentArea();
		}

		var quizType = $(area).attr("quiztype");
		if(_getQuizModule(quizType)){
			return _getQuizModule(quizType).save(current_area);
		}
	};

	var draw = function(area,quiz){
		if(_getQuizModule(quiz.quiztype)){
			_getQuizModule(quiz.quiztype).draw(area,quiz);
		}
	};

	var showQuizSettings = function(){
		$(_hiddenLinkToInitQuizSettings).trigger("click");
	};

	/*
	 * Quiz exporting
	 * Usage example: VISH.Editor.Quiz.exportTo("QTI", function(){ alert("Success")}, function(){alert("Fail")})
	 */
	var _exportTo = function(format,successCallback,failCallback){
		var cJSONQuiz = _getCurrentJSONQuiz();

		if(typeof cJSONQuiz == "undefined"){
			if(typeof failCallback == "function"){
				failCallback();
			}
			return;
		}

		V.Editor.API.uploadTmpJSON(cJSONQuiz,format,successCallback,failCallback);
	};

	var onExportTo = function(format){
		$.fancybox.close();

		_exportTo(format,function(){
			//Success
		},function(){
			setTimeout(function(){
				//On fail
				var options = {};
				options.width = 600;
				options.height = 185;

				if(format=="QTI"){
					options.text = V.I18n.getTrans("i.exportQuizToQTIerrorNotification");
				} else if(format=="MoodleXML"){
					options.text = V.I18n.getTrans("i.exportQuizToMoodleXMLerrorNotification");
				}

				var button1 = {};
				button1.text = V.I18n.getTrans("i.Ok");
				button1.callback = function(){
					$.fancybox.close();
				}
				options.buttons = [button1];
				V.Utils.showDialog(options);
			},600);
		});
	};

	var _getCurrentJSONQuiz = function(){
		var quizJSON = undefined;
		var presentation = V.Editor.savePresentation();
		var cslide = V.Slides.getCurrentSlide();

		if(typeof cslide == "object"){
			var cslideId = $(cslide).attr("id");

		 	$.each(presentation.slides, function(index,value){
				if((value.id == cslideId)&&(value.containsQuiz == true)){
					$.each(value.elements, function(index,elVal){
						if(elVal.type == "quiz"){
							quizJSON = elVal;
						}
					});
	 			}
		 	});
		}
		return quizJSON;
	};

	var afterCopyQuiz = function(quizDOM){
		var quizType = $(quizDOM).attr("quiztype");
		var quizModule = _getQuizModule(quizType);
		if((quizModule)&&(typeof quizModule.afterCopyQuiz == "function")){
			return quizModule.afterCopyQuiz(quizDOM);
		}
	};

	return {
		init				: init,
		add					: add,
		save				: save,
		draw				: draw,
		onExportTo			: onExportTo,
		showQuizSettings	: showQuizSettings,
		onQuizSettingsDone	: onQuizSettingsDone,
		afterCopyQuiz		: afterCopyQuiz
	};

}) (VISH, jQuery);<commit_msg>Bug fixed on quiz settings<commit_after>VISH.Editor.Quiz = (function(V,$,undefined){

	var _hiddenLinkToInitQuizSettings;

	var init = function(){
		V.Editor.Quiz.MC.init();
		V.Editor.Quiz.TF.init();
		V.Editor.Quiz.Sorting.init();
		V.Editor.Quiz.Open.init();

		//Quiz Settings
		_hiddenLinkToInitQuizSettings = $('');
		$(_hiddenLinkToInitQuizSettings).fancybox({
			'autoDimensions' : false,
			'height': 400,
			'width': 400,
			'scrolling': 'no',
			'showCloseButton': false,
			'padding' : 0,
			"onStart"  : function(data){
				var qSF = $("#quizSettings_fancybox");

				//Load Quiz
				var quiz = V.Editor.getCurrentArea();
				var quizType = $(quiz).attr("quiztype");
				var quizModule = _getQuizModule(quizType);
				$(qSF).find("input[type='hidden'][name='elId']").val($(quiz).attr("id"));

				//Load Settings
				var qSettings = $(quiz).attr("elSettings");
				var nAttempts = 1;
				var quizScore = 10;
				var shuffleChoices = false;
				var disableShuffleChoices = false;
				var ARSEnabled = false;

				if(typeof qSettings == "string"){
					try {
						qSettings = JSON.parse(qSettings);

						if(typeof qSettings.nAttempts != "undefined"){
							nAttempts = qSettings.nAttempts;
						}
						if(typeof qSettings.quizScore != "undefined"){
							quizScore = qSettings.quizScore;
						}
						if(qSettings.ARSEnabled===true){
							ARSEnabled = true;
						}
						if(qSettings.shuffleChoices===true){
							shuffleChoices = true;
						}
					} catch(e){}
				}

				//Force options by quiz type
				switch(quizType){
					case V.Constant.QZ_TYPE.OPEN:
						shuffleChoices = false;
						disableShuffleChoices = true;
						break;
					case V.Constant.QZ_TYPE.MCHOICE:
						break;
					case V.Constant.QZ_TYPE.TF:
						break;
					case V.Constant.QZ_TYPE.SORTING:
						shuffleChoices = true;
						disableShuffleChoices = true;
						break;
					default:
						break;
				};

				//Fill and reset form

				var isSelfAssessment = false;
				if((quizModule)&&(typeof quizModule.isSelfAssessment == "function")){
					isSelfAssessment = quizModule.isSelfAssessment(quiz);
				}

				//Number of Attempts
				var nAttemptsDOM = $(qSF).find("#quizSettings_nAttempts");
				if(!isSelfAssessment){
					//Disable nAttempts
					$(nAttemptsDOM).prop('disabled',true);
					$(nAttemptsDOM).parent().addClass("disableSettingsField");
					$(nAttemptsDOM).val(1);
				} else {
					$(nAttemptsDOM).prop('disabled',false);
					$(nAttemptsDOM).parent().removeClass("disableSettingsField");
					$(nAttemptsDOM).val(nAttempts);
				}

				//Quiz score
				var quizScoreDOM = $(qSF).find("select[name='quizScorePoints']");
				if(!isSelfAssessment){
					//Disable quizScore
					$(quizScoreDOM).prop('disabled',true);
					$(quizScoreDOM).parent().addClass("disableSettingsField");
					$(quizScoreDOM).val(0);
				} else {
					$(quizScoreDOM).prop('disabled',false);
					$(quizScoreDOM).parent().removeClass("disableSettingsField");
					$(quizScoreDOM).val(quizScore);
				}

				//Shuffle Choices
				var shuffleChoicesCheckbox = $(qSF).find("input[type='checkbox'][name='shuffleChoices']");
				$(shuffleChoicesCheckbox).prop('checked', shuffleChoices);
				if(disableShuffleChoices){
					$(shuffleChoicesCheckbox).parent().addClass("disableSettingsField");
					$(shuffleChoicesCheckbox).attr('disabled', 'disabled');
				} else {
					$(shuffleChoicesCheckbox).parent().removeClass("disableSettingsField");
					$(shuffleChoicesCheckbox).removeAttr('disabled');
				}

				//ARS Enabled
				var ARSEnabledCheckbox = $(qSF).find("input[type='checkbox'][name='enableARS']");
				$(ARSEnabledCheckbox).prop('checked', ARSEnabled);

				// //Post actions
				// switch(quizType){
				// 	case V.Constant.QZ_TYPE.OPEN:
				// 		break;
				// 	case V.Constant.QZ_TYPE.MCHOICE:
				// 		break;
				// 	case V.Constant.QZ_TYPE.TF:
				// 		break;
				// 	case V.Constant.QZ_TYPE.SORTING:
				// 		break;
				// 	default:
				// 		break;
				// };
			},
			"onComplete" : function(data){
			},
			"onClosed"  : function(data){
			}
		});
	};

	var onQuizSettingsDone = function(){
		//Get Settings
		var qSF = $("#quizSettings_fancybox");
		var qSettings = {};

		var nAttemptsDOM = $(qSF).find("#quizSettings_nAttempts");
		if(!$(nAttemptsDOM).is(":disabled")){
			qSettings.nAttempts = $(nAttemptsDOM).val();
		}

		var quizScoreDOM = $(qSF).find("select[name='quizScorePoints']");
		if(!$(quizScoreDOM).is(":disabled")){
			qSettings.quizScore = $(quizScoreDOM).val();
		}

		qSettings.shuffleChoices = $(qSF).find("input[type='checkbox'][name='shuffleChoices']").is(":checked");
		qSettings.ARSEnabled = $(qSF).find("input[type='checkbox'][name='enableARS']").is(":checked");

		//Get quiz
		var quizId = $(qSF).find("input[type='hidden'][name='elId']").val();
		var quiz = $("#"+quizId);

		//Save Settings
		var qSSerialized = JSON.stringify(qSettings);
		$(quiz).attr("elSettings",qSSerialized);

		$.fancybox.close();
	};

	/*
	 * Quiz modules
	 */
	var _getQuizModule = function(quiz_type){
		switch(quiz_type){
			case V.Constant.QZ_TYPE.OPEN:
				return V.Editor.Quiz.Open;
				break;
			case V.Constant.QZ_TYPE.MCHOICE:
				return V.Editor.Quiz.MC;
				break;
			case V.Constant.QZ_TYPE.TF:
				return V.Editor.Quiz.TF;
				break;
			case V.Constant.QZ_TYPE.SORTING:
				return V.Editor.Quiz.Sorting;
				break;
			default:
				return null;
				break;
		}
	};

	/*
	 * Add a new Quiz
	 */
	var add = function(quizType,area){
		var current_area;
		if(area) {
			current_area = area;
		} else {
			current_area = V.Editor.getCurrentArea();
		}

		if(_getQuizModule(quizType)){
			_getQuizModule(quizType).add(current_area);
		}

		$.fancybox.close();
	};

	/*
	 * return quiz in JSON
	 */
	var save = function(area){
		var current_area;
		if(area) {
			current_area = area;
		} else {
			current_area = V.Editor.getCurrentArea();
		}

		var quizType = $(area).attr("quiztype");
		if(_getQuizModule(quizType)){
			return _getQuizModule(quizType).save(current_area);
		}
	};

	var draw = function(area,quiz){
		if(_getQuizModule(quiz.quiztype)){
			_getQuizModule(quiz.quiztype).draw(area,quiz);
		}
	};

	var showQuizSettings = function(){
		$(_hiddenLinkToInitQuizSettings).trigger("click");
	};

	/*
	 * Quiz exporting
	 * Usage example: VISH.Editor.Quiz.exportTo("QTI", function(){ alert("Success")}, function(){alert("Fail")})
	 */
	var _exportTo = function(format,successCallback,failCallback){
		var cJSONQuiz = _getCurrentJSONQuiz();

		if(typeof cJSONQuiz == "undefined"){
			if(typeof failCallback == "function"){
				failCallback();
			}
			return;
		}

		V.Editor.API.uploadTmpJSON(cJSONQuiz,format,successCallback,failCallback);
	};

	var onExportTo = function(format){
		$.fancybox.close();

		_exportTo(format,function(){
			//Success
		},function(){
			setTimeout(function(){
				//On fail
				var options = {};
				options.width = 600;
				options.height = 185;

				if(format=="QTI"){
					options.text = V.I18n.getTrans("i.exportQuizToQTIerrorNotification");
				} else if(format=="MoodleXML"){
					options.text = V.I18n.getTrans("i.exportQuizToMoodleXMLerrorNotification");
				}

				var button1 = {};
				button1.text = V.I18n.getTrans("i.Ok");
				button1.callback = function(){
					$.fancybox.close();
				}
				options.buttons = [button1];
				V.Utils.showDialog(options);
			},600);
		});
	};

	var _getCurrentJSONQuiz = function(){
		var quizJSON = undefined;
		var presentation = V.Editor.savePresentation();
		var cslide = V.Slides.getCurrentSlide();

		if(typeof cslide == "object"){
			var cslideId = $(cslide).attr("id");

		 	$.each(presentation.slides, function(index,value){
				if((value.id == cslideId)&&(value.containsQuiz == true)){
					$.each(value.elements, function(index,elVal){
						if(elVal.type == "quiz"){
							quizJSON = elVal;
						}
					});
	 			}
		 	});
		}
		return quizJSON;
	};

	var afterCopyQuiz = function(quizDOM){
		var quizType = $(quizDOM).attr("quiztype");
		var quizModule = _getQuizModule(quizType);
		if((quizModule)&&(typeof quizModule.afterCopyQuiz == "function")){
			return quizModule.afterCopyQuiz(quizDOM);
		}
	};

	return {
		init				: init,
		add					: add,
		save				: save,
		draw				: draw,
		onExportTo			: onExportTo,
		showQuizSettings	: showQuizSettings,
		onQuizSettingsDone	: onQuizSettingsDone,
		afterCopyQuiz		: afterCopyQuiz
	};

}) (VISH, jQuery);<|endoftext|>