<commit_before>/**
*    A RowExpander changed from RowExpander.js in the Ext examples and some ideas taken
*    from the forum (http://extjs.com/forum/showthread.php?t=21017&page=3).
*
*    Override the createExpandingRowPanelItems function to make Ext expanded row content
*    (as opposed to using Ext.Template to make the expanded row content).
*
*    If config.store is passed in, pass a record for the row from that store instead
*    of the grid store into the createExpandingRowPanelItems function.
*
*    Renamed and incorporated into ext-extensions by jjulian 7/2009. Thanks to wolf.
*/
Ext.grid.PanelRowExpander = function(config){
    Ext.apply(this, config);
    Ext.grid.PanelRowExpander.superclass.constructor.call(this);

    this.state = {};

    this.addEvents({
        beforeexpand : true,
        expand: true,
        beforecollapse: true,
        collapse: true
    });
};

Ext.extend(Ext.grid.PanelRowExpander, Ext.util.Observable, {
    header: "",
    width: 20,
    sortable: false,
    fixed:true,
    dataIndex: '',
    id: 'expander',
    lazyRender : true,
    enableCaching: true,

    getRowClass : function(record, rowIndex, rowParams, ds){
        // cols: The column count to apply to the body row's TD colspan attribute (defaults to the current column count of the grid).
        rowParams.cols = rowParams.cols-1; // make it the width of the whole row
        return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed';
    },

    init : function(grid){
        this.grid = grid;

        var view = grid.getView();
        view.getRowClass = this.getRowClass.createDelegate(this);

        view.enableRowBody = true;

        grid.on('render', function(){
            view.mainBody.on( 'mousedown', this.onMouseDown, this );
        }, this);

        // store
        grid.getStore().on("load", function(store, records, options){
            Ext.select('div.x-grid3-row-expanded').replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed');
            this.state = {};
            }, this);

        if (this.store) {
          this.store.load(); // load here instead of in beforeExpand cuz that would wipe out additions to store
        }
    },

    onMouseDown : function( e, t ) {
        if(t.className == 'x-grid3-row-expander'){
            e.stopEvent();
            var row = e.getTarget('.x-grid3-row');
            this.toggleRow(row);
        }
    },

    renderer : function(v, p, record){
        p.cellAttr = 'rowspan="2"';
        return '

';
    },

    beforeExpand : function(record, rowBody, rowIndex){
        var isContinue = true;
        if(this.fireEvent('beforeexpand', this, record, rowBody, rowIndex, this.store) !== false){
            if(rowBody.innerHTML == '' || !this.enableCaching) {
                this.createExpandingRowPanel( record, rowBody, rowIndex );
            }
        } else {
            isContinue = false;
        }

        return isContinue;
    },

    toggleRow : function(row){
        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row);
    },

    expandRow : function(row){
        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        var record = this.grid.store.getAt(row.rowIndex);
        // if using additional store passed in config, pass record from it instead of from the grid store
        var recordToPass = this.store ? this.store.getAt(row.rowIndex) : record;
        var rowBody = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row);
        if(this.beforeExpand(recordToPass, rowBody, row.rowIndex)){
            this.state[record.id] = true;
            Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded');
            this.fireEvent('expand', this, recordToPass, rowBody, row.rowIndex);
        }
    },

    collapseRow : function(row){
        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        var record = this.grid.store.getAt(row.rowIndex);
        // if using additional store passed in config, pass record from it instead of from the grid store
        var recordToPass = this.store ? this.store.getAt(row.rowIndex) : record;
        var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true);
        if(this.fireEvent('beforcollapse', this, recordToPass, body, row.rowIndex) !== false){
            this.state[record.id] = false;
            Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed');
            this.fireEvent('collapse', this, recordToPass, body, row.rowIndex);
        }
    },

   createExpandingRowPanel: function( record, rowBody, rowIndex ) {
        // record.id is more stable than rowIndex for panel item's key; rows can be deleted.
        var panelItemIndex = record.id;

        // init array of expanding row panels if not already inited
        if ( !this.expandingRowPanel ) {
            this.expandingRowPanel = [];
        }

        // Add a new panel to the row body if not already there
        if ( !this.expandingRowPanel[panelItemIndex] ) {
            this.expandingRowPanel[panelItemIndex] = new Ext.Panel(
                {
                    layout:'fit', // Note, use 'form' to get form field labels to show
                    border: false,
                    bodyBorder: false,
                    items: this.createExpandingRowPanelItems( record, rowIndex )
                }
            );
            // 2009-07-26 12:52am jjulian When renderTo is specified in the config above, it
            // all happens *too fast* and the layout does not know that the element we are
            // rendering to actually has a size > 0.
            (function() {
              this.expandingRowPanel[panelItemIndex].render(rowBody);
            }).defer(100, this);
        }
    },

    /**
    * Override this method to put Ext form items into the expanding row panel.
    * @return Array of panel items.
    */
    createExpandingRowPanelItems: function( record, rowIndex ) {
        var panelItems = [];

        return panelItems;
    }

});

<commit_msg>clear the cache on reload<commit_after>/**
*    A RowExpander changed from RowExpander.js in the Ext examples and some ideas taken
*    from the forum (http://extjs.com/forum/showthread.php?t=21017&page=3).
*
*    Override the createExpandingRowPanelItems function to make Ext expanded row content
*    (as opposed to using Ext.Template to make the expanded row content).
*
*    If config.store is passed in, pass a record for the row from that store instead
*    of the grid store into the createExpandingRowPanelItems function.
*
*    Renamed and incorporated into ext-extensions by jjulian 7/2009. Thanks to wolf.
*/
Ext.grid.PanelRowExpander = function(config){
    Ext.apply(this, config);
    Ext.grid.PanelRowExpander.superclass.constructor.call(this);

    this.state = {};

    this.addEvents({
        beforeexpand : true,
        expand: true,
        beforecollapse: true,
        collapse: true
    });
};

Ext.extend(Ext.grid.PanelRowExpander, Ext.util.Observable, {
    header: "",
    width: 20,
    sortable: false,
    fixed:true,
    dataIndex: '',
    id: 'expander',
    lazyRender : true,
    enableCaching: true,

    getRowClass : function(record, rowIndex, rowParams, ds){
        // cols: The column count to apply to the body row's TD colspan attribute (defaults to the current column count of the grid).
        rowParams.cols = rowParams.cols-1; // make it the width of the whole row
        return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed';
    },

    init : function(grid){
        this.grid = grid;

        var view = grid.getView();
        view.getRowClass = this.getRowClass.createDelegate(this);

        view.enableRowBody = true;

        grid.on('render', function(){
            view.mainBody.on( 'mousedown', this.onMouseDown, this );
        }, this);

        // store
        grid.getStore().on("load", function(store, records, options){
            Ext.select('div.x-grid3-row-expanded').replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed');
            this.state = {};
            this.expandingRowPanel = [];
            }, this);

        if (this.store) {
          this.store.load(); // load here instead of in beforeExpand cuz that would wipe out additions to store
        }
    },

    onMouseDown : function( e, t ) {
        if(t.className == 'x-grid3-row-expander'){
            e.stopEvent();
            var row = e.getTarget('.x-grid3-row');
            this.toggleRow(row);
        }
    },

    renderer : function(v, p, record){
        p.cellAttr = 'rowspan="2"';
        return '

';
    },

    beforeExpand : function(record, rowBody, rowIndex){
        var isContinue = true;
        if(this.fireEvent('beforeexpand', this, record, rowBody, rowIndex, this.store) !== false){
            if(rowBody.innerHTML == '' || !this.enableCaching) {
                this.createExpandingRowPanel( record, rowBody, rowIndex );
            }
        } else {
            isContinue = false;
        }

        return isContinue;
    },

    toggleRow : function(row){
        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row);
    },

    expandRow : function(row){
        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        var record = this.grid.store.getAt(row.rowIndex);
        // if using additional store passed in config, pass record from it instead of from the grid store
        var recordToPass = this.store ? this.store.getAt(row.rowIndex) : record;
        var rowBody = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row);
        if(this.beforeExpand(recordToPass, rowBody, row.rowIndex)){
            this.state[record.id] = true;
            Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded');
            this.fireEvent('expand', this, recordToPass, rowBody, row.rowIndex);
        }
    },

    collapseRow : function(row){
        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        var record = this.grid.store.getAt(row.rowIndex);
        // if using additional store passed in config, pass record from it instead of from the grid store
        var recordToPass = this.store ? this.store.getAt(row.rowIndex) : record;
        var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true);
        if(this.fireEvent('beforcollapse', this, recordToPass, body, row.rowIndex) !== false){
            this.state[record.id] = false;
            Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed');
            this.fireEvent('collapse', this, recordToPass, body, row.rowIndex);
        }
    },

   createExpandingRowPanel: function( record, rowBody, rowIndex ) {
        // record.id is more stable than rowIndex for panel item's key; rows can be deleted.
        var panelItemIndex = record.id;

        // init array of expanding row panels if not already inited
        if ( !this.expandingRowPanel ) {
            this.expandingRowPanel = [];
        }

        // Add a new panel to the row body if not already there
        if ( !this.expandingRowPanel[panelItemIndex] ) {
            this.expandingRowPanel[panelItemIndex] = new Ext.Panel(
                {
                    layout:'fit', // Note, use 'form' to get form field labels to show
                    border: false,
                    bodyBorder: false,
                    items: this.createExpandingRowPanelItems( record, rowIndex )
                }
            );
            // 2009-07-26 12:52am jjulian When renderTo is specified in the config above, it
            // all happens *too fast* and the layout does not know that the element we are
            // rendering to actually has a size > 0.
            (function() {
              this.expandingRowPanel[panelItemIndex].render(rowBody);
            }).defer(100, this);
        }
    },

    /**
    * Override this method to put Ext form items into the expanding row panel.
    * @return Array of panel items.
    */
    createExpandingRowPanelItems: function( record, rowIndex ) {
        var panelItems = [];

        return panelItems;
    }

});

<|endoftext|>


<commit_before>(function($) {
    devsite.devsite.Init($, {'FULL_SITE_SEARCH_ENABLED': 1, 'ENABLE_BLOCKED_VIDEO_PLACEHOLDER': 0, 'VERSION_HASH': '1d7f5dcee3', 'SITE_NAME': 'devsite', 'HISTORY_ENABLED': 1, 'SUBPATH': '', 'ENABLE_BLOCKED_LINK_TOOLTIP': 0, 'ALLOWED_HOSTS': ['.github.io'], 'BLOCK_RSS_FEEDS': 0, 'SCRIPTSAFE_DOMAIN': '.github.io'},
    '[]', 'en',
    true, '',
    {"f62218c009ec029abef196bba5aa34cf": false, "039e5d84b87fd75807ffb37b7f1bbf2c": true, "098dafe57affddc137df300142652cfd": false, "cb025a64a50094835616312f4774a53d": true, "51470233c56fc1fde50f00b73c52b216": false, "752953480de00a336d911a46966cc16d": false, "700def1a83e356c06c0925afb05de4b0": false, "6749dcb526ce9bde6993550c7d928d24": true},
    '/',
    'https://ephellon.github.io/Paramour/');

    var timer, blink = false, last = {}, ltr = $("html").css(["writing-mode"]);
      ltr = (ltr == "" || ltr == "vertical-lr");

      function updateCursor(textarea) {
        var start = textarea.selectionStart,
            end = textarea.selectionEnd,
            value = textarea.value,
            direction = textarea.selectionDirection;

        if(direction == undefined || direction == null)
          direction = ((last.start > start || end < last.end) && ltr)? "left": "right";
        else
          direction = (direction != "forward" && ltr)? "left": "right";

        if((last.start = start) == (last.end = end))
          return value.slice(0, start) +
            '' +
            value.slice(end, value.length);
        else
          return value.slice(0, start) +
            '' +
            value.slice(start, end) +
            '' +
            value.slice(end, value.length);
      }

      $(".pretty-input > textarea")
      .on("keydown", function(event) {
        var textarea = event.target, display = $(textarea).siblings(".prettyprint");

        clearTimeout(timer);
        timer = setTimeout(function() {
          display.val(function() {
            return updateCursor(textarea);
          });

          prettyPrint();
        }, 100);
      })
      .on("mousemove", function(event) {
        $(event.target).keydown();
      })
      .on("mousedown", function(event) {
        $(event.target).mousemove();
      });

      setInterval(function() {
        $(".cursor").css({"border-color": (blink = !blink)? "#ffffff": "#212121"});
      }, 500);

      var display = $(".pretty-input > textarea").siblings("pre");

      display
      .html(function(index, value) {
        return updateCursor(display.siblings("textarea")[index]) + "
";
      });

    })(jQuery);
    devsite.localInit = function() {};
<commit_msg>Update main.js<commit_after>
      (function($) {
      devsite.devsite.Init($, {'FULL_SITE_SEARCH_ENABLED': 1, 'ENABLE_BLOCKED_VIDEO_PLACEHOLDER': 0, 'VERSION_HASH': '1d7f5dcee3', 'SITE_NAME': 'devsite', 'HISTORY_ENABLED': 1, 'SUBPATH': '', 'ENABLE_BLOCKED_LINK_TOOLTIP': 0, 'ALLOWED_HOSTS': ['.github.io'], 'BLOCK_RSS_FEEDS': 0, 'SCRIPTSAFE_DOMAIN': '.github.io'},
      '[]', 'en',
      true, '',
      {"f62218c009ec029abef196bba5aa34cf": false, "039e5d84b87fd75807ffb37b7f1bbf2c": true, "098dafe57affddc137df300142652cfd": false, "cb025a64a50094835616312f4774a53d": true, "51470233c56fc1fde50f00b73c52b216": false, "752953480de00a336d911a46966cc16d": false, "700def1a83e356c06c0925afb05de4b0": false, "6749dcb526ce9bde6993550c7d928d24": true},
      '/',
      'https://ephellon.github.io/Paramour/');

        var timer, blink = false, last = {}, ltr = $("html").css(["writing-mode"]);
        ltr = (ltr == "" || ltr == "vertical-lr");

        function updateCursor(textarea) {
          var start = textarea.selectionStart,
              end = textarea.selectionEnd,
              value = textarea.value,
              direction = textarea.selectionDirection;

          if(direction == undefined || direction == null)
            direction = ((last.start > start || end < last.end) && ltr)? "left": "right";
          else
            direction = (direction != "forward" && ltr)? "left": "right";

          if((last.start = start) == (last.end = end))
            return value.slice(0, start) +
              '' +
              value.slice(end, value.length);
          else
            return value.slice(0, start) +
              '' +
              value.slice(start, end) +
              '' +
              value.slice(end, value.length);
        }

        $(".pretty-input > textarea")
        .on("keydown", function(event) {
          var textarea = event.target, display = $(textarea).siblings();

          clearTimeout(timer);
          timer = setTimeout(function() {
            display.html(function() {
              return updateCursor(textarea);
            });

            prettyPrint();
          }, 100);
        })
        .on("mousemove", function(event) {
          $(event.target).keydown();
        })
        .on("mousedown", function(event) {
          $(event.target).mousemove();
        });

        setInterval(function() {
          $(".cursor")
          .css({"border-color": (blink = !blink)? "#ffffff": "#212121"});
        }, 500);

        var siblings =
            $(".pretty-input > textarea")
            .siblings();
        siblings
        .html(function(index, value) {
          return updateCursor($(siblings).siblings()[index]) + "
";
        });

      })(jQuery);
      devsite.localInit = function() {};
<|endoftext|>


<commit_before>var _ = require('underscore');

// Use Parse.Cloud.define to define as many cloud functions as you want.
Parse.Cloud.define("getRandomSuggestionPairs", function(request, response) {
	var SuggestionObject = Parse.Object.extend("Suggestion");
	var SUGGESTION_COUNT = 25;
	var zeroSuggestions = [];
	var zeroLoaded = false;
	var oneSuggestions = [];
	var oneLoaded = false;
	loadSuggestionSet(0);
	loadSuggestionSet(1);

	function loadSuggestionSet(type) {
		var query = new Parse.Query(SuggestionObject);
		query.limit(SUGGESTION_COUNT);
		query.equalTo('type', type);
		query.ascending('updatedAt');
		if(request.params.skip)
			query.skip(request.params.skip);
		query.find({
			success: function onSuggestionSetLoaded(suggestionSet) {
				switch(type) {
					case 0 :
						zeroSuggestions = suggestionSet;
						zeroLoaded = true;
						break;
					case 1 :
						oneSuggestions = suggestionSet;
						oneLoaded = true;
						break;
				}
				if(zeroLoaded && oneLoaded)
					onSuggestionsLoaded();
			}
		});
	}

	function onSuggestionsLoaded() {
		var suggestionPairs = [];
		for(var i = 0; i < SUGGESTION_COUNT; i++) {
			var pair = {
				0: zeroSuggestions[i],
				1: oneSuggestions[i]
			}
			suggestionPairs.push(pair);
		}

		response.success(suggestionPairs);
	}

});

Parse.Cloud.define("votePair", function(request, response) {
	var VoteObject = Parse.Object.extend("Vote");
	var SuggestionObject = Parse.Object.extend("Suggestion");
	var saveCount = 0;

	if(!request.params.pair) {
		response.error('must send pair');
	} else {
		_.each(request.params.pair, function(suggestionId, index, pairs) {
			saveCount++;
			var newVote = new VoteObject();
			var opposite = pairs[index == 0 ? 1 : 0];
			newVote.set('owner', Parse.User.current());
			newVote.set('parent', suggestionId);
			newVote.set('pair', opposite);
			newVote.save({
				success: function(vote) {
					var suggestionObj = new SuggestionObject();
					suggestionObj.id = suggestionId;
					var relation = suggestionObj.relation("votes");
					relation.add(vote);
					suggestionObj.save({
						success: onSuccess,
						error: onError
					})
				},
				error: onError
			});
		});
	}

	function onSuccess(obj) {
		saveCount--;
		if(saveCount === 0)
			response.success('votes saved');
	}

	function onError(obj, error) {
		response.error(error);
	}
});
<commit_msg>added beforesave for new suggestions to add default values for new props<commit_after>var _ = require('underscore');

// Use Parse.Cloud.define to define as many cloud functions as you want.
Parse.Cloud.define("getRandomSuggestionPairs", function(request, response) {
	var SuggestionObject = Parse.Object.extend("Suggestion");
	var SUGGESTION_COUNT = 25;
	var zeroSuggestions = [];
	var zeroLoaded = false;
	var oneSuggestions = [];
	var oneLoaded = false;
	loadSuggestionSet(0);
	loadSuggestionSet(1);

	function loadSuggestionSet(type) {
		var query = new Parse.Query(SuggestionObject);
		query.limit(SUGGESTION_COUNT);
		query.equalTo('type', type);
		query.ascending('updatedAt');
		if(request.params.skip)
			query.skip(request.params.skip);
		query.find({
			success: function onSuggestionSetLoaded(suggestionSet) {
				switch(type) {
					case 0 :
						zeroSuggestions = suggestionSet;
						zeroLoaded = true;
						break;
					case 1 :
						oneSuggestions = suggestionSet;
						oneLoaded = true;
						break;
				}
				if(zeroLoaded && oneLoaded)
					onSuggestionsLoaded();
			}
		});
	}

	function onSuggestionsLoaded() {
		var suggestionPairs = [];
		for(var i = 0; i < SUGGESTION_COUNT; i++) {
			var pair = {
				0: zeroSuggestions[i],
				1: oneSuggestions[i]
			}
			suggestionPairs.push(pair);
		}

		response.success(suggestionPairs);
	}

});

Parse.Cloud.define("votePair", function(request, response) {
	var VoteObject = Parse.Object.extend("Vote");
	var SuggestionObject = Parse.Object.extend("Suggestion");
	var saveCount = 0;

	if(!request.params.pair) {
		response.error('must send pair');
	} else {
		_.each(request.params.pair, function(suggestionId, index, pairs) {
			saveCount++;
			var newVote = new VoteObject();
			var opposite = pairs[index == 0 ? 1 : 0];
			newVote.set('owner', Parse.User.current());
			newVote.set('parent', suggestionId);
			newVote.set('pair', opposite);
			newVote.save({
				success: function(vote) {
					var suggestionObj = new SuggestionObject();
					suggestionObj.id = suggestionId;
					var relation = suggestionObj.relation("votes");
					relation.add(vote);
					suggestionObj.save({
						success: onSuccess,
						error: onError
					})
				},
				error: onError
			});
		});
	}

	function onSuccess(obj) {
		saveCount--;
		if(saveCount === 0)
			response.success('votes saved');
	}

	function onError(obj, error) {
		response.error(error);
	}
});

Parse.Cloud.beforeSave("Suggestion", function(request, response) {
	if(request.object.isNew()) {
		request.object.set("backgroundUpdatedAt", new Date());
		request.object.set("totalVotes", 0);
	}
	response.success();
});<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import Annotation from './Annotation';
import AddAnnotation from './AddAnnotation';
import Can, { can } from '../Can';

class Annotations extends Component {
  render() {
    const props = this.props;

    return (

        {props.annotations.map(function(annotation) {
          return (

<Annotation annotation={annotation.node} annotated={props.annotated} annotatedType={props.annotatedType} />

          );
        })}

        {props.annotatedType === 'Media' ? ( // TODO: remove to support Source as well
          <Can permissions={props.annotated.permissions} permission={`update ${props.annotatedType}`}>
            <AddAnnotation annotated={props.annotated} annotatedType={props.annotatedType} types={props.types} />
          </Can>
        ) : <AddAnnotation annotated={props.annotated} annotatedType={props.annotatedType} types={props.types} />}

    );
  }
}

export default Annotations;
<commit_msg>Use correct create annotation permission<commit_after>import React, { Component, PropTypes } from 'react';
import Annotation from './Annotation';
import AddAnnotation from './AddAnnotation';
import Can, { can } from '../Can';

class Annotations extends Component {
  render() {
    const props = this.props;

    return (

        {props.annotations.map(function(annotation) {
          return (

<Annotation annotation={annotation.node} annotated={props.annotated} annotatedType={props.annotatedType} />

          );
        })}

        {props.annotatedType === 'Media' ? ( // TODO: remove to support Source as well
          <Can permissions={props.annotated.permissions} permission='create Comment'>
            <AddAnnotation annotated={props.annotated} annotatedType={props.annotatedType} types={props.types} />
          </Can>
        ) : <AddAnnotation annotated={props.annotated} annotatedType={props.annotatedType} types={props.types} />}

    );
  }
}

export default Annotations;
<|endoftext|>


<commit_before>/**
 * Asserts that a given exception is thrown when executing the given
 * function.
 *
 * @param Error/RegExp expectedException
 *   Error: The constructor of the error expected, or a superclass
 *          constructor.
 *   RegExp: A RegExp supposed to match the message of the exception.
 * @param Function func
 *   The function to execute.
 * @param optional string message
 *   An error message to save if the assertion fails.
 */
Module("Cactus.Dev.Assertion", function (m) {
  var C = Cactus.Data.Collection;
  var assert = require("assert");
  m.ok = function (v, msg) { true.should.equal(v, msg); };
  m.not = function (v, msg) { false.should.equal(v, msg); };
  m.equal = function (a, b, msg) {
    if (!a) {
      assert.strictEqual(a, b, msg);
    } else {
      a.should.equal(b, msg);
    }
  };
  m.instance = function (a, b, msg) { a.should.instanceof(b, msg); };
  m.notequal = function (a, b, msg) { a.should.not.equal(b, msg); };
  m.eql = function (a, b, msg) { a.should.eql(b, msg); };
  m.reg = function (reg, str, msg) {
    assert.ok(reg.test(str), msg || reg + " !~ " + str);
  };
  m.listreg = function (regs, list, msgs) {
    msgs = msgs || [];
    m.equal(regs.length, list.length);
    for (var i = 0; i < regs.length; i++) {
      m.reg(regs[i], list[i], msgs[i]);
    }
  };
  m.unorderedeql = function (a, b, msg) {
    var intersection = C.intersection(a, b);
    assert.ok(intersection.length === a.length && a.length === b.length,
              msg || intersection.length + " elements intersecting.");
  };
  m.contEx = function (cont, reg) {
    var e;
    return cont.except(function (_e) {
      e = _e;
      this.CONTINUE();
    }).ensure(function () {
      if (!e) {
        throw new Error("assertContEx: No error was thrown.");
      }
      assert.ok(reg.test(e.message), "assertContEx: Caught unexpected: " + e.message);
      this.CONTINUE();
    });
  };
  m.exception = function (expectedException, func, message) {
    var returnValue = "*not available*";
    var exception = null;
    try {
      returnValue = func();
    } catch (err) {
      exception = err;
    }
    if (message === undefined) {
      if (exception === null) {
        if (expectedException instanceof RegExp) {
          message = "expected an exception matching " +
            expectedException +
            ", but no exception was thrown. " +
            "Function return value: +" + returnValue + "+";
        } else {
          message = "expected to catch +" +
            getFunctionName(expectedException)  + "+," +
            " but no exception was thrown." +
            "Function return value: +" + returnValue + "+";
        }
      } else {
        if (expectedException instanceof RegExp) {
          message = "expected an exception message matching " +
            expectedException + ", but got: " +
            exception.message;
        } else {
          message = "expected to catch +" +
            expectedException.name +
            "+, but caught +" +
            exception.constructor.name + "+";
        }
      }
    }
    var exceptionThrown = !!exception;
    // Match regexp =~ error message if regexp is specified, otherwise
    // check the instance of the exception.
    var condition;
    if (expectedException instanceof RegExp) {
      if (!exception) {
        condition = false;
      } else {
        condition = expectedException.test(exception.message);
      }
    } else {
      condition = exception instanceof expectedException;
    }
    assert.ok(exceptionThrown && condition, message);
  };
});
<commit_msg>Assertion.contEx now properly fails on no errors thrown.<commit_after>/**
 * Asserts that a given exception is thrown when executing the given
 * function.
 *
 * @param Error/RegExp expectedException
 *   Error: The constructor of the error expected, or a superclass
 *          constructor.
 *   RegExp: A RegExp supposed to match the message of the exception.
 * @param Function func
 *   The function to execute.
 * @param optional string message
 *   An error message to save if the assertion fails.
 */
Module("Cactus.Dev.Assertion", function (m) {
  var C = Cactus.Data.Collection;
  var assert = require("assert");
  m.ok = function (v, msg) { true.should.equal(v, msg); };
  m.not = function (v, msg) { false.should.equal(v, msg); };
  m.equal = function (a, b, msg) {
    if (!a) {
      assert.strictEqual(a, b, msg);
    } else {
      a.should.equal(b, msg);
    }
  };
  m.instance = function (a, b, msg) { a.should.instanceof(b, msg); };
  m.notequal = function (a, b, msg) { a.should.not.equal(b, msg); };
  m.eql = function (a, b, msg) { a.should.eql(b, msg); };
  m.reg = function (reg, str, msg) {
    assert.ok(reg.test(str), msg || reg + " !~ " + str);
  };
  m.listreg = function (regs, list, msgs) {
    msgs = msgs || [];
    m.equal(regs.length, list.length);
    for (var i = 0; i < regs.length; i++) {
      m.reg(regs[i], list[i], msgs[i]);
    }
  };
  m.unorderedeql = function (a, b, msg) {
    var intersection = C.intersection(a, b);
    assert.ok(intersection.length === a.length && a.length === b.length,
              msg || intersection.length + " elements intersecting.");
  };
  m.contEx = function (cont, reg) {
    var e;
    return cont.except(function (_e) {
      e = _e;
      this.CONTINUE();
    }).ensure(function () {
      var cont = this.getCONTINUE();
      setTimeout(function () {
        if (!e) {
          throw new Error("assertContEx: No error was thrown.");
        }
        assert.ok(reg.test(e.message), "assertContEx: Caught unexpected: " + e.message);
        cont();
      }, 0);
    });
  };
  m.exception = function (expectedException, func, message) {
    var returnValue = "*not available*";
    var exception = null;
    try {
      returnValue = func();
    } catch (err) {
      exception = err;
    }
    if (message === undefined) {
      if (exception === null) {
        if (expectedException instanceof RegExp) {
          message = "expected an exception matching " +
            expectedException +
            ", but no exception was thrown. " +
            "Function return value: +" + returnValue + "+";
        } else {
          message = "expected to catch +" +
            getFunctionName(expectedException)  + "+," +
            " but no exception was thrown." +
            "Function return value: +" + returnValue + "+";
        }
      } else {
        if (expectedException instanceof RegExp) {
          message = "expected an exception message matching " +
            expectedException + ", but got: " +
            exception.message;
        } else {
          message = "expected to catch +" +
            expectedException.name +
            "+, but caught +" +
            exception.constructor.name + "+";
        }
      }
    }
    var exceptionThrown = !!exception;
    // Match regexp =~ error message if regexp is specified, otherwise
    // check the instance of the exception.
    var condition;
    if (expectedException instanceof RegExp) {
      if (!exception) {
        condition = false;
      } else {
        condition = expectedException.test(exception.message);
      }
    } else {
      condition = exception instanceof expectedException;
    }
    assert.ok(exceptionThrown && condition, message);
  };
});
<|endoftext|>


<commit_before>/*globals document,window,$,jQuery */
/*jslint white: true, onevar: true, undef: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, strict: true, newcap: true, immed: true, indent: 2 */

"use strict";

/*
 * jQuery UI Lightbox
 *
 * Copyright (c) 2009 Benjamin Doherty
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Depends:
 *  ui.core.js
 *  ui.dialog.js
 *  jquery.mousewheel.js (optional)
 */
(function ($) {

  $.widget('ui.lightbox', {
    _init: function () {
      var self = this;

      // consider event delegation to make this more dynamic
      $(this.options.selector, this.element).click(function (event) {
        event.preventDefault();
        self.open(this);
      });
      $(document).keydown(function (event) {
        if (!self.lightbox || !self.lightbox.dialog('isOpen')) {
          return;
        }
        switch (event.keyCode) {
        case $.ui.keyCode.ESCAPE:
          if (self.options.closeOnEscape) {
            self.close();
          }
          break;
        case $.ui.keyCode.LEFT:
          self.prev("left");
          event.preventDefault();
          break;
        case $.ui.keyCode.UP:
          self.prev("up");
          event.preventDefault();
          break;
        case $.ui.keyCode.RIGHT:
          self.next("right");
          event.preventDefault();
          break;
        case $.ui.keyCode.DOWN:
          self.next("down");
          event.preventDefault();
          break;
        }
      });
      if ($.fn.mousewheel) {
        $(document).mousewheel(function (event, delta) {
          if (!self.lightbox.dialog('isOpen')) {
            return;
          }
          event.preventDefault();
          if (self.lightbox.is(":animated")) {
            return;
          }
          if (delta < 0) {
            self.next("down");
          }
          if (delta > 0) {
            self.prev("up");
          }
        });
      }
    },

    _makeDialog: function () {
      return $('
').dialog({
        autoOpen: false,
        closeOnEscape: false,
        modal: false,
        show: null,
        hide: null,
        dialogClass: this.options.dialogClass,
        position: this.options.position,
        resizable: this.options.resizable,
        draggable: this.options.draggable,
        height: this.options.height,
        width: this.options.width,
        // TODO: Support overlay by implementing focus,dragstop,resizestop
        open: function (event, ui) {
          $('.ui-dialog-buttonpane button', $(this).parents('.ui-dialog'))
            .each(function (index, domElement) {
              $(domElement).addClass('button-' + index);
            });
        }
      });
    },

    _buttons: {
      'Previous': function (eventObject) {
        $(this).dialog('option', '_lightbox').prev("right");
      },
      'Next': function (eventObject) {
        $(this).dialog('option', '_lightbox').next("left");
      }
    },

    destroy: function () {
      (this.overlay && this.overlay.destroy());
      this.element
        .unbind('.lightbox')
        .removeData('lightbox');
    },

    open: function (anchor) {
      var viewer = (this.lightbox = this._makeDialog());

      this.overlay = this.options.modal ? new $.ui.lightbox.overlay(viewer.data('dialog')) : null;
      this.setCurrentAnchor(anchor);

      viewer.dialog('option', 'buttons', this._buttons)
        .bind('dialogclose.lightbox', this._dialogClose)
        .dialog('open');

      viewer.dialog('option', '_lightbox', this);
    },

    close: function () {
      var self = this,
        anchor = this.getCurrentAnchor(),
        viewer = this.lightbox;

      (this.overlay && this.overlay.destroy());

      $.ui.lightbox.overlay.resize();

      // TODO: these need to be destroyed with the widget.
      viewer.dialog('destroy').remove();
    },

    next: function (direction) {
      this._rotate(":gt(", ":first", direction || "up");
    },

    prev: function (direction) {
      this._rotate(":lt(", ":last", direction || "down");
    },

    _anchors: function () {
      // if deemed necessary, cache selection here
      return this.element.find(this.options.selector);
    },

    _setData: function (key, value) {
      switch (key) {
      case "cursor":
        this.options[key] = value;
        this.spinner = new $.ui.lightbox.spinner(this);
        this._display(this._loadContent(value));
        this.spinner.destroy();
        break;
      }

      $.widget.prototype._setData.apply(this, arguments);
    },

    _display: function (content) {
      var anchor = this.getCurrentAnchor(),
        viewer = this.lightbox,
        size = this._calculateSize(content),
        $el = $(content).css(size).appendTo(viewer);

      viewer.dialog('option', 'title', $(anchor).attr('title') + this.options.titleSuffix);
      viewer.dialog('option', this._resize($el, size.width, size.height));
    },

    _loadContent: function (anchor) {
      var self = this,
        content = 'BUG',
        type = this.options.type ? this.options.type : this._deriveType(anchor);

      switch (type) {
      case "image":
        content = new Image();
        content.src = anchor.href;
        break;
      case "flash":
      case "flashvideo":
      case "quicktime":
      case "realplayer":
      case "windowsmedia":
        $(anchor).media({
          width: this.options.width,
          height: this.options.height,
          src: anchor.href,
          autoplay: 1
        }, function (element, options) {
        }, function (element, data, options, playerName) {
          content = $(data).html();
          $(data).media('undo');
        });
        break;
      case "iframe":
        content = this._element('iframe').attr('src', anchor.href).attr('frameborder', 0).attr('border', 0).html();
        break;
      case "html":
      case "dom":
        var reference = $($(anchor).attr('href'));
        content = $('
').append(reference.clone().show()).remove().html();
        break;
      case "ajax":
      case "script":
        $.ajax({
          url: anchor.href,
          type: (parseInt(self.options.post, 10) === 1) ? "POST" : "GET",
          cache: true,
          async: false,
          data: self.options.parameters,
          dataType: (type === "ajax") ? "html" : "script",
          success: function (data, textStatus) {
            content = data;
          }
        });
        break;
      }

      return content;
    },

    _deriveType: function (anchor) {
      var reference = anchor.href;
      if (reference.toLowerCase().match(/\.(gif|jpg|jpeg|png)(\?[0123456789]+)?$/)) {
        return "image";
      }
      if (reference.toLowerCase().match(/\.(swf)(\?[0123456789]+)?$/)) {
        return "flash";
      }
      if (reference.toLowerCase().match(/\.(flv)(\?[0123456789]+)?$/)) {
        return "flashvideo";
      }
      if (reference.toLowerCase().match(/\.(aif|aiff|aac|au|bmp|gsm|mov|mid|midi|mpg|mpeg|m4a|m4v|mp4|psd|qt|qtif|qif|qti|snd|tif|tiff|wav|3g2|3gp|wbmp)(\?[0123456789]+)?$/)) {
        return "quicktime";
      }
      if (reference.toLowerCase().match(/\.(ra|ram|rm|rpm|rv|smi|smil)(\?[0123456789]+)?$/)) {
        return "realplayer";
      }
      if (reference.toLowerCase().match(/\.(asf|avi|wma|wmv)(\?[0123456789]+)?$/)) {
        return "windowsmedia";
      }
      return "ajax";
    },

    _preloadNeighbours: function () {
      var anchors = this._anchors(),
        index = anchors.index(this.getCurrentAnchor());
      anchors.filter(this._neighbours(anchors.length, index)).each(function () {
        //new Image().src = this.href;
      });
    },

    _neighbours: function (index, length) {
      return ":eq(" + (index === 0 ? length - 1 : index - 1) + "), :eq(" + (index === length - 1 ? 0 : index + 1) + ")";
    },

    _position: function (img) {
    },

    _calculateSize: function (content) {
      var width,height;
      $.swap($(content).appendTo('
').appendTo(document.body)[0], {
        position: "absolute",
        visibility: "hidden",
        display: "block"
      }, function () {
        width = $(this).width(),
        height = $(this).height();
        $(this).remove();
      });
      return { width: width, height: height };
    },

    _resize: function (elem, width, height) {
      var viewer = this.lightbox,
        dialog = viewer.data('dialog'),
        offset = 20,
        finalWidth,finalHeight,

        // difference
        deltaContentWidth = viewer.outerWidth() - viewer.width(),
        deltaContentHeight = viewer.outerHeight() - viewer.height(),

        dialogTitlebarWidth = dialog.uiDialogTitlebar.outerWidth(),
        dialogTitlebarHeight = dialog.uiDialogTitlebar.outerHeight(),

        // Window
        wWidth = $(window).width(),
        wHeight = $(window).height(),

        size = {width: width, height: height};

      // Desired width
      finalWidth = size.width + deltaContentWidth,
      finalHeight = size.height + deltaContentHeight + dialogTitlebarHeight,

      ratio = Math.min(
        Math.min(
          Math.min(wWidth - deltaContentWidth - offset, size.width) / size.width,
          Math.min(wHeight - deltaContentHeight - dialogTitlebarHeight - offset, size.height) / size.height, 1)),

      $.extend(size, {
        width: Math.round(ratio * size.width),
        height: Math.round(ratio * size.height)
      });

      elem.css(size);

      if (ratio !== 1) {
        elem.attr('width', '').attr('height', '');
      }

      return { width: size.width + deltaContentWidth, height: size.height + deltaContentHeight + dialogTitlebarHeight };
    },

    setCurrentAnchor: function (anchor) {
      this._setData('cursor', anchor);
    },

    getCurrentAnchor: function () {
      return this._getData('cursor');
    },

    _rotate: function (selectorA, selectorB, direction) {
      var self = this,
        content,
        anchors = this._anchors(),
        target = current = this.getCurrentAnchor(),
        viewer = this.lightbox,
        dialog = viewer.data('dialog').uiDialog,

        effectOut = {
          direction: direction
        },
        effectIn = {
          direction: {up:"down",down:"up",left:"right",right:"left"}[direction]
        };

      if (!this.getCurrentAnchor()) {
        console.log('Called _rotate without an anchor');
        return;
      }

      if (anchors.length === 1) {
        return;
      }

      target = anchors.filter(selectorA + anchors.index(current) + ")" + selectorB)[0];
      if (!target && this.options.loop && anchors.length > 1) {
        target = anchors.filter(selectorB)[0];
      }

      dialog.hide(this.options.rotateOut, effectOut, this.options.duration, function () {
        viewer
          .unbind('dialogclose.lightbox')
          .bind('dialogclose.lightbox', self._rotateClose).dialog('close');
        self.setCurrentAnchor(target);
        $(this).show(self.options.rotateIn, effectIn, self.options.duration, function () {
          viewer
            .dialog('open')
            .unbind('dialogclose.lightbox')
            .bind('dialogclose.lightbox', self._dialogClose);
        });
      });
    },

    // Swappable dialog event handlers.

    _rotateClose: function (event, ui) {
      $(this).empty();
    },

    _dialogClose: function (event, ui) {
      $(this).empty().dialog('option', '_lightbox').close();
    },

    _element: function (type, clazz) {
      return $("<" + type + "/>").addClass(clazz).hide();
    }
  });

  $.extend($.ui.lightbox, {
    defaults: {
      loop: true,
      modal: true,
      overlay: {},
      post: 0,
      dialogClass: 'ui-lightbox',
      closeOnEscape: true,
      resizable: false,
      draggable: false,
      selector: "a[href]:has(img[src])",
      titleSuffix: "",
      position: 'center',
      width: 'auto',
      height: 'auto',
      parameters: {},
      duration: 1000,
      rotateIn: 'drop',
      rotateOut: 'drop',
      show: '',
      hide: ''
    },
    uuid: 0,
    overlay: function (dialog) {
      this.$el = $.ui.lightbox.overlay.create(dialog);
    },
    spinner: function (lightbox) {
      this.$el = $.ui.lightbox.spinner.create(lightbox);
    }
  });

  $.extend($.ui.lightbox.overlay, $.ui.dialog.overlay, {});

  $.extend($.ui.lightbox.overlay.prototype, $.ui.dialog.overlay.prototype, {
    destroy: function() {
      $.ui.lightbox.overlay.destroy(this.$el);
    }
  });

  $.extend($.ui.lightbox.spinner, {
    instances: [],
    create: function (lightbox) {
      if (this.instances.length === 0) {
        var $el = $('

').appendTo(document.body)
          .addClass('ui-loading-indicator ui-corner-all').fadeIn("slow");

        this.instances.push($el);
        return $el;
      };
    },
    destroy: function($el) {
      this.instances.splice($.inArray(this.instances, $el), 1);

      $el.remove();
    }
  });

  $.extend($.ui.lightbox.spinner.prototype, {
    destroy: function() {
      $.ui.lightbox.spinner.destroy(this.$el);
    }
  });

})(jQuery);
<commit_msg>jslint.<commit_after>/*globals document,window,$,jQuery,Image */
/*jslint white: true, browser: true, onevar: true, undef: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, strict: true, newcap: true, immed: true, indent: 2 */

"use strict";

/*
 * jQuery UI Lightbox
 *
 * Copyright (c) 2009 Benjamin Doherty
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Depends:
 *  ui.core.js
 *  ui.dialog.js
 *  jquery.mousewheel.js (optional)
 */
(function ($) {

  $.widget('ui.lightbox', {
    _init: function () {
      var self = this;

      // consider event delegation to make this more dynamic
      $(this.options.selector, this.element).click(function (event) {
        event.preventDefault();
        self.open(this);
      });
      $(document).keydown(function (event) {
        if (!self.lightbox || !self.lightbox.dialog('isOpen')) {
          return;
        }
        switch (event.keyCode) {
        case $.ui.keyCode.ESCAPE:
          if (self.options.closeOnEscape) {
            self.close();
          }
          break;
        case $.ui.keyCode.LEFT:
          self.prev("left");
          event.preventDefault();
          break;
        case $.ui.keyCode.UP:
          self.prev("up");
          event.preventDefault();
          break;
        case $.ui.keyCode.RIGHT:
          self.next("right");
          event.preventDefault();
          break;
        case $.ui.keyCode.DOWN:
          self.next("down");
          event.preventDefault();
          break;
        }
      });
      if ($.fn.mousewheel) {
        $(document).mousewheel(function (event, delta) {
          if (!self.lightbox.dialog('isOpen')) {
            return;
          }
          event.preventDefault();
          if (self.lightbox.is(":animated")) {
            return;
          }
          if (delta < 0) {
            self.next("down");
          }
          if (delta > 0) {
            self.prev("up");
          }
        });
      }
    },

    _makeDialog: function () {
      return $('
').dialog({
        autoOpen: false,
        closeOnEscape: false,
        modal: false,
        show: null,
        hide: null,
        dialogClass: this.options.dialogClass,
        position: this.options.position,
        resizable: this.options.resizable,
        draggable: this.options.draggable,
        height: this.options.height,
        width: this.options.width,
        // TODO: Support overlay by implementing focus,dragstop,resizestop
        open: function (event, ui) {
          $('.ui-dialog-buttonpane button', $(this).parents('.ui-dialog'))
            .each(function (index, domElement) {
              $(domElement).addClass('button-' + index);
            });
        }
      });
    },

    _buttons: {
      'Previous': function (eventObject) {
        $(this).dialog('option', '_lightbox').prev("right");
      },
      'Next': function (eventObject) {
        $(this).dialog('option', '_lightbox').next("left");
      }
    },

    destroy: function () {
      (this.overlay && this.overlay.destroy());
      this.element
        .unbind('.lightbox')
        .removeData('lightbox');
    },

    open: function (anchor) {
      var viewer = (this.lightbox = this._makeDialog());

      this.overlay = this.options.modal ? new $.ui.lightbox.overlay(viewer.data('dialog')) : null;
      this.setCurrentAnchor(anchor);

      viewer.dialog('option', 'buttons', this._buttons)
        .bind('dialogclose.lightbox', this._dialogClose)
        .dialog('open');

      viewer.dialog('option', '_lightbox', this);
    },

    close: function () {
      var viewer = this.lightbox;

      (this.overlay && this.overlay.destroy());

      $.ui.lightbox.overlay.resize();

      // TODO: these need to be destroyed with the widget.
      viewer.dialog('destroy').remove();
    },

    next: function (direction) {
      this._rotate(":gt(", ":first", direction || "up");
    },

    prev: function (direction) {
      this._rotate(":lt(", ":last", direction || "down");
    },

    _anchors: function () {
      // if deemed necessary, cache selection here
      return this.element.find(this.options.selector);
    },

    _setData: function (key, value) {
      if (key === 'cursor') {
        this.options[key] = value;
        this.spinner = new $.ui.lightbox.spinner(this);
        this._display(this._loadContent(value));
        this.spinner.destroy();
      }

      $.widget.prototype._setData.apply(this, arguments);
    },

    _display: function (content) {
      var anchor = this.getCurrentAnchor(),
        viewer = this.lightbox,
        size = this._calculateSize(content),
        $el = $(content).css(size).appendTo(viewer);

      viewer.dialog('option', 'title', $(anchor).attr('title') + this.options.titleSuffix);
      viewer.dialog('option', this._resize($el, size.width, size.height));
    },

    _loadContent: function (anchor) {
      var self = this,
        content = 'BUG',
        type = this.options.type ? this.options.type : this._deriveType(anchor);

      switch (type) {
      case "image":
        content = new Image();
        content.src = anchor.href;
        break;
      case "flash":
      case "flashvideo":
      case "quicktime":
      case "realplayer":
      case "windowsmedia":
        $(anchor).media({
          width: this.options.width,
          height: this.options.height,
          src: anchor.href,
          autoplay: 1
        }, function (element, options) {
        }, function (element, data, options, playerName) {
          content = $(data).html();
          $(data).media('undo');
        });
        break;
      case "iframe":
        content = this._element('iframe').attr('src', anchor.href).attr('frameborder', 0).attr('border', 0).html();
        break;
      case "html":
      case "dom":
        content = $('
').append($(anchor.href).clone().show()).remove().html();
        break;
      case "ajax":
      case "script":
        $.ajax({
          url: anchor.href,
          type: (parseInt(self.options.post, 10) === 1) ? "POST" : "GET",
          cache: true,
          async: false,
          data: self.options.parameters,
          dataType: (type === "ajax") ? "html" : "script",
          success: function (data, textStatus) {
            content = data;
          }
        });
        break;
      }

      return content;
    },

    _deriveType: function (anchor) {
      var reference = anchor.href;
      if (reference.toLowerCase().match(/\.(gif|jpg|jpeg|png)(\?[0123456789]+)?$/)) {
        return "image";
      }
      if (reference.toLowerCase().match(/\.(swf)(\?[0123456789]+)?$/)) {
        return "flash";
      }
      if (reference.toLowerCase().match(/\.(flv)(\?[0123456789]+)?$/)) {
        return "flashvideo";
      }
      if (reference.toLowerCase().match(/\.(aif|aiff|aac|au|bmp|gsm|mov|mid|midi|mpg|mpeg|m4a|m4v|mp4|psd|qt|qtif|qif|qti|snd|tif|tiff|wav|3g2|3gp|wbmp)(\?[0123456789]+)?$/)) {
        return "quicktime";
      }
      if (reference.toLowerCase().match(/\.(ra|ram|rm|rpm|rv|smi|smil)(\?[0123456789]+)?$/)) {
        return "realplayer";
      }
      if (reference.toLowerCase().match(/\.(asf|avi|wma|wmv)(\?[0123456789]+)?$/)) {
        return "windowsmedia";
      }
      return "ajax";
    },

    _preloadNeighbours: function () {
      var anchors = this._anchors(),
        index = anchors.index(this.getCurrentAnchor());
      anchors.filter(this._neighbours(anchors.length, index)).each(function () {
        //new Image().src = this.href;
      });
    },

    _neighbours: function (index, length) {
      return ":eq(" + (index === 0 ? length - 1 : index - 1) + "), :eq(" + (index === length - 1 ? 0 : index + 1) + ")";
    },

    _position: function (img) {
    },

    _calculateSize: function (content) {
      var width, height;
      $.swap($(content).appendTo('
').appendTo(document.body)[0], {
        position: "absolute",
        visibility: "hidden",
        display: "block"
      }, function () {
        width = $(this).width();
        height = $(this).height();
        $(this).remove();
      });
      return { width: width, height: height };
    },

    _resize: function (elem, width, height) {
      var viewer = this.lightbox,
        dialog = viewer.data('dialog'),
        offset = 20,

        // difference
        deltaContentWidth = viewer.outerWidth() - viewer.width(),
        deltaContentHeight = viewer.outerHeight() - viewer.height(),

        dialogTitlebarHeight = dialog.uiDialogTitlebar.outerHeight(),

        // Window
        wWidth = $(window).width(),
        wHeight = $(window).height(),

        size = {width: width, height: height},

        // Desired width
        finalWidth = size.width + deltaContentWidth,
        finalHeight = size.height + deltaContentHeight + dialogTitlebarHeight,

        ratio = Math.min(
          Math.min(
            Math.min(wWidth - deltaContentWidth - offset, size.width) / size.width,
            Math.min(wHeight - deltaContentHeight - dialogTitlebarHeight - offset, size.height) / size.height, 1));

      $.extend(size, {
        width: Math.round(ratio * size.width),
        height: Math.round(ratio * size.height)
      });

      elem.css(size);

      if (ratio !== 1) {
        elem.attr('width', '').attr('height', '');
      }

      finalWidth = size.width + deltaContentWidth;
      finalHeight = size.height + deltaContentHeight + dialogTitlebarHeight;

      return { width: finalWidth, height: finalHeight };
    },

    setCurrentAnchor: function (anchor) {
      this._setData('cursor', anchor);
    },

    getCurrentAnchor: function () {
      return this._getData('cursor');
    },

    _rotate: function (selectorA, selectorB, direction) {
      var self = this,
        anchors = this._anchors(),
        current = this.getCurrentAnchor(),
        target = this.getCurrentAnchor(),
        viewer = this.lightbox,
        dialog = viewer.data('dialog').uiDialog,

        effectOut = {
          direction: direction
        },
        effectIn = {
          direction: {up: "down", down: "up", left: "right", right: "left" }[direction]
        };

      if (anchors.length === 1) {
        return;
      }

      target = anchors.filter(selectorA + anchors.index(current) + ")" + selectorB)[0];
      if (!target && this.options.loop && anchors.length > 1) {
        target = anchors.filter(selectorB)[0];
      }

      dialog.hide(this.options.rotateOut, effectOut, this.options.duration, function () {
        viewer
          .unbind('dialogclose.lightbox')
          .bind('dialogclose.lightbox', self._rotateClose).dialog('close');
        self.setCurrentAnchor(target);
        $(this).show(self.options.rotateIn, effectIn, self.options.duration, function () {
          viewer
            .dialog('open')
            .unbind('dialogclose.lightbox')
            .bind('dialogclose.lightbox', self._dialogClose);
        });
      });
    },

    // Swappable dialog event handlers.

    _rotateClose: function (event, ui) {
      $(this).empty();
    },

    _dialogClose: function (event, ui) {
      $(this).empty().dialog('option', '_lightbox').close();
    },

    _element: function (type, clazz) {
      return $("<" + type + "/>").addClass(clazz).hide();
    }
  });

  $.extend($.ui.lightbox, {
    defaults: {
      loop: true,
      modal: true,
      overlay: {},
      post: 0,
      dialogClass: 'ui-lightbox',
      closeOnEscape: true,
      resizable: false,
      draggable: false,
      selector: "a[href]:has(img[src])",
      titleSuffix: "",
      position: 'center',
      width: 'auto',
      height: 'auto',
      parameters: {},
      duration: 1000,
      rotateIn: 'drop',
      rotateOut: 'drop',
      show: '',
      hide: ''
    },
    uuid: 0,
    overlay: function (dialog) {
      this.$el = $.ui.lightbox.overlay.create(dialog);
    },
    spinner: function (lightbox) {
      this.$el = $.ui.lightbox.spinner.create(lightbox);
    }
  });

  $.extend($.ui.lightbox.overlay, $.ui.dialog.overlay, {});

  $.extend($.ui.lightbox.overlay.prototype, $.ui.dialog.overlay.prototype, {
    destroy: function () {
      $.ui.lightbox.overlay.destroy(this.$el);
    }
  });

  $.extend($.ui.lightbox.spinner, {
    instances: [],
    create: function (lightbox) {
      if (this.instances.length === 0) {
        var $el = $('

').appendTo(document.body)
          .addClass('ui-loading-indicator ui-corner-all').fadeIn("slow");

        this.instances.push($el);
        return $el;
      }
    },
    destroy: function ($el) {
      this.instances.splice($.inArray(this.instances, $el), 1);

      $el.remove();
    }
  });

  $.extend($.ui.lightbox.spinner.prototype, {
    destroy: function () {
      $.ui.lightbox.spinner.destroy(this.$el);
    }
  });

})(jQuery);
<|endoftext|>


<commit_before>/*globals document,window,$,jQuery */
/*jslint white: true, onevar: true, undef: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, strict: true, newcap: true, immed: true, indent: 2 */

"use strict";

/*
 * jQuery UI Lightbox
 *
 * Copyright (c) 2009 Benjamin Doherty
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Depends:
 *  ui.core.js
 *  ui.dialog.js
 *  jquery.mousewheel.js (optional)
 */
(function ($) {

  $.widget('ui.lightbox', {
    _init: function () {
      var self = this;

      // consider event delegation to make this more dynamic
      $(this.options.selector, this.element).click(function (event) {
        event.preventDefault();
        self.open(this);
      });
      $(document).keydown(function (event) {
        if (!self.lightbox.dialog('isOpen')) {
          return;
        }
        switch (event.keyCode) {
        case $.ui.keyCode.ESCAPE:
          if (self.options.closeOnEscape) {
            self.close();
          }
          break;
        case $.ui.keyCode.LEFT:
          self.prev("left");
          event.preventDefault();
          break;
        case $.ui.keyCode.UP:
          self.prev("up");
          event.preventDefault();
          break;
        case $.ui.keyCode.RIGHT:
          self.next("right");
          event.preventDefault();
          break;
        case $.ui.keyCode.DOWN:
          self.next("down");
          event.preventDefault();
          break;
        }
      });
      if ($.fn.mousewheel) {
        $(document).mousewheel(function (event, delta) {
          if (!self.lightbox.dialog('isOpen')) {
            return;
          }
          event.preventDefault();
          if (self.lightbox.is(":animated")) {
            return;
          }
          if (delta < 0) {
            self.next("down");
          }
          if (delta > 0) {
            self.prev("up");
          }
        });
      }
    },

    _makeDialog: function () {
      return $('<div/>').dialog({
        autoOpen: false,
        closeOnEscape: false,
        modal: false,
        dialogClass: this.options.dialogClass,
        position: this.options.position,
        resizable: this.options.resizable,
        draggable: this.options.draggable,
        height: this.options.height,
        width: this.options.width,
        // TODO: Support overlay by implementing focus,dragstop,resizestop
        open: function (event, ui) {
          $('.ui-dialog-buttonpane button', $(this).parents('.ui-dialog'))
            .each(function (index, domElement) {
              $(domElement).addClass('button-' + index);
            });
        }
      });
    },

    _buttons: {
      'Previous': function (eventObject) {
        $(this).dialog('option', '_lightbox').prev("right");
      },
      'Next': function (eventObject) {
        $(this).dialog('option', '_lightbox').next("right");
      }
    },

    _showLoadingIndicator: function () {
      var self = this;

      this.loadingIndicatorTimeout = setTimeout(function() {
        if (!self.loadingIndicator) {
          self.loadingIndicator = self._element("div", "ui-loading-indicator ui-corner-all").appendTo(document.body);
        }
        self.loadingIndicator.fadeIn("slow");
      }, 250);
    },

    _hideLoadingIndicator: function () {
      clearTimeout(this.loadingIndicatorTimeout);
      if (this.loadingIndicator) {
        this.loadingIndicator.hide();
      }
    },

    destroy: function () {
      (this.overlay && this.overlay.destroy());
      this.element
        .unbind('.lightbox')
        .removeData('lightbox');
    },

    open: function (anchor) {
      var viewer = (this.lightbox = this._makeDialog());

      this.overlay = this.options.modal ? new $.ui.lightbox.overlay(viewer.data('dialog')) : null;
      this.setCurrentAnchor(anchor);

      viewer.dialog('option', 'show', this.options.show)
        .dialog('option', 'hide', this.options.hide)
        .dialog('option', 'buttons', this._buttons)
        .dialog('option', 'close', self._dialogClose)
        .dialog('open');

      viewer.dialog('option', '_lightbox', this);
    },

    close: function () {
      var self = this,
        anchor = this.getCurrentAnchor(),
        viewer = this.lightbox;

      if (!this.lightbox.dialog('isOpen')) {
        viewer.dialog('close');
      }

      (this.overlay && this.overlay.destroy());

      $.ui.lightbox.overlay.resize();

      // TODO: these need to be destroyed with the widget.
      viewer.dialog('destroy').remove();
    },

    next: function (direction) {
      this._rotate(":gt(", ":first", direction || "up");
    },

    prev: function (direction) {
      this._rotate(":lt(", ":last", direction || "down");
    },

    _anchors: function () {
      // if deemed necessary, cache selection here
      return this.element.find(this.options.selector);
    },

    _setData: function (key, value) {
      switch (key) {
      case "cursor":
        this.options[key] = value;
        this._showLoadingIndicator();
        this._display(this._loadContent(value));
        this._hideLoadingIndicator();
        break;
      }

      $.widget.prototype._setData.apply(this, arguments);
    },

    _display: function (content) {
      var anchor = this.getCurrentAnchor(),
        viewer = this.lightbox;

      viewer.dialog('option', 'title', $(anchor).attr('title') + this.options.titleSuffix);

      viewer.empty();
      viewer.append(content.show());
    },

    _loadContent: function (anchor) {
      var self = this,
        content = 'BUG',
        type = this.options.type ? this.options.type : this._deriveType(anchor);

      switch (type) {
      case "image":
        content = this._element('img')
          .attr("src", anchor.href)
          .load(function (event) {
            self.lightbox.dialog('option', 'position', self.options.position);
          });
        break;
      case "flash":
      case "flashvideo":
      case "quicktime":
      case "realplayer":
      case "windowsmedia":
        $(anchor).media({
          width: this.options.width,
          height: this.options.height,
          src: anchor.href,
          autoplay: 1
        }, function (element, options) {
        }, function (element, data, options, playerName) {
          content = $(data).clone();
          $(data).media('undo');
        });
        break;
      case "iframe":
        content = this._element('iframe').attr('src', anchor.href).attr('frameborder', 0).attr('border', 0);
        break;
      case "html":
      case "dom":
        var reference = $($(anchor).attr('href'));

        content = $(reference).clone();
        break;
      case "ajax":
      case "script":
        $.ajax({
          url: anchor.href,
          type: (parseInt(self.options.post, 10) === 1) ? "POST" : "GET",
          cache: true,
          async: false,
          data: self.options.parameters,
          dataType: (type === "ajax") ? "html" : "script",
          success: function (data, textStatus) {
            content = $(data);
          }
        });
        break;
      }

      return content;
    },

    _deriveType: function (anchor) {
      var reference = anchor.href;
      if (reference.toLowerCase().match(/\.(gif|jpg|jpeg|png)(\?[0123456789]+)?$/)) {
        return "image";
      }
      if (reference.toLowerCase().match(/\.(swf)(\?[0123456789]+)?$/)) {
        return "flash";
      }
      if (reference.toLowerCase().match(/\.(flv)(\?[0123456789]+)?$/)) {
        return "flashvideo";
      }
      if (reference.toLowerCase().match(/\.(aif|aiff|aac|au|bmp|gsm|mov|mid|midi|mpg|mpeg|m4a|m4v|mp4|psd|qt|qtif|qif|qti|snd|tif|tiff|wav|3g2|3gp|wbmp)(\?[0123456789]+)?$/)) {
        return "quicktime";
      }
      if (reference.toLowerCase().match(/\.(ra|ram|rm|rpm|rv|smi|smil)(\?[0123456789]+)?$/)) {
        return "realplayer";
      }
      if (reference.toLowerCase().match(/\.(asf|avi|wma|wmv)(\?[0123456789]+)?$/)) {
        return "windowsmedia";
      }
      return "ajax";
    },

    _preloadNeighbours: function () {
      var anchors = this._anchors(),
        index = anchors.index(this.getCurrentAnchor());
      anchors.filter(this._neighbours(anchors.length, index)).each(function () {
        //new Image().src = this.href;
      });
    },

    _neighbours: function (index, length) {
      return ":eq(" + (index === 0 ? length - 1 : index - 1) + "), :eq(" + (index === length - 1 ? 0 : index + 1) + ")";
    },

    _position: function (img) {
    },

    _resize: function (content) {
      var viewer = this.lightbox,
        dialog = this.lightbox.data('dialog'),
        offset = 20,
        type = this._deriveType(this.getCurrentAnchor()),
        cWidth,cHeight,finalWidth,finalHeight,
        // difference
        deltaContentWidth = viewer.outerWidth() - viewer.width(),
        deltaContentHeight = viewer.outerHeight() - viewer.height(),

        dialogTitlebarWidth = dialog.uiDialogTitlebar.outerWidth(),
        dialogTitlebarHeight = dialog.uiDialogTitlebar.outerHeight(),

        // Window
        wWidth = $(window).width(),
        wHeight = $(window).height(),

        size = (this.size = {});

      $.swap(content[0], {
        position: "absolute",
        visibility: "hidden",
        display: "block"
      }, function () {
        cWidth = $(this).attr('width') || $(this).width(),
        cHeight = $(this).attr('height') || $(this).height();
      });

      // Desired width
      finalWidth = cWidth + deltaContentWidth,
      finalHeight = cHeight + deltaContentHeight + dialogTitlebarHeight,

      ratio = Math.min(
        Math.min(
          Math.min(wWidth - deltaContentWidth - offset, cWidth) / cWidth,
          Math.min(wHeight - deltaContentHeight - dialogTitlebarHeight - offset, cHeight) / cHeight, 1)),

      $.extend(size, {
        width: Math.round(ratio * cWidth),
        height: Math.round(ratio * cHeight)
      });

      if (type == 'image') {
        content.css('width', size.width);
        content.css('height', size.height);
      }

      viewer.dialog('option', 'width', size.width + deltaContentWidth);
      viewer.dialog('option', 'height', size.height + deltaContentHeight + dialogTitlebarHeight);
      viewer.css({
        width: size.width + deltaContentWidth,
        height: size.height + deltaContentHeight
      });
    },

    setCurrentAnchor: function (anchor) {
      this._setData('cursor', anchor);
    },
    getCurrentAnchor: function () {
      return this._getData('cursor');
    },

    _rotate: function (selectorA, selectorB, direction) {
      var self = this,
        content,
        anchors = this._anchors(),
        target = current = this.getCurrentAnchor(),
        viewer = this.lightbox,
        dialog = viewer.data('dialog').uiDialog;

      if (!this.getCurrentAnchor()) {
        console.log('Called _rotate without an anchor');
        return;
      }

      if (anchors.length === 1) {
        return;
      }

      target = anchors.filter(selectorA + anchors.index(current) + ")" + selectorB)[0];
      if (!target && this.options.loop && anchors.length > 1) {
        target = anchors.filter(selectorB)[0];
      }

      dialog.hide(this.options.rotateOut, {
        direction: direction
      }, this.options.duration, function () {
        viewer.dialog('option', 'close', self._rotateClose).dialog('close');
        self.setCurrentAnchor(target);
        $(this).show(self.options.rotateIn, {
          direction: {
            up: "down",
            down: "up",
            left: "right",
            right: "left"
          }[direction]
        }, self.options.duration, function () {
          viewer.dialog('open').dialog('option', 'close', self._dialogClose);
        });
      });
    },

    // Swappable dialog event handlers.

    _rotateClose: function (event, ui) {
      $(this).empty();
    },

    _dialogClose: function (event, ui) {
      $(this).empty().dialog('_lightbox').close();
    },

    _element: function (type, clazz) {
      return $("<" + type + "/>").addClass(clazz).hide();
    }
  });

  $.extend($.ui.lightbox, {
    defaults: {
      loop: true,
      modal: true,
      overlay: {},
      post: 0,
      dialogClass: 'ui-lightbox',
      closeOnEscape: true,
      resizable: false,
      draggable: false,
      selector: "a[href]:has(img[src])",
      titleSuffix: "",
      position: 'center',
      width: 'auto',
      height: 'auto',
      parameters: {},
      duration: 1000,
      rotateIn: 'drop',
      rotateOut: 'drop',
      show: '',
      hide: ''
    },
    uuid: 0,
    overlay: function (dialog) {
      this.$el = $.ui.lightbox.overlay.create(dialog);
    }
  });

  $.extend($.ui.lightbox.overlay, $.ui.dialog.overlay, {});

  $.extend($.ui.lightbox.overlay.prototype, $.ui.dialog.overlay.prototype, {
    destroy: function() {
      $.ui.lightbox.overlay.destroy(this.$el);
    }
  });
})(jQuery);
<commit_msg>check that lightbox exists before trying to process keyboard events.<commit_after>/*globals document,window,$,jQuery */
/*jslint white: true, onevar: true, undef: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, strict: true, newcap: true, immed: true, indent: 2 */

"use strict";

/*
 * jQuery UI Lightbox
 *
 * Copyright (c) 2009 Benjamin Doherty
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Depends:
 *  ui.core.js
 *  ui.dialog.js
 *  jquery.mousewheel.js (optional)
 */
(function ($) {

  $.widget('ui.lightbox', {
    _init: function () {
      var self = this;

      // consider event delegation to make this more dynamic
      $(this.options.selector, this.element).click(function (event) {
        event.preventDefault();
        self.open(this);
      });
      $(document).keydown(function (event) {
        if (!self.lightbox || !self.lightbox.dialog('isOpen')) {
          return;
        }
        switch (event.keyCode) {
        case $.ui.keyCode.ESCAPE:
          if (self.options.closeOnEscape) {
            self.close();
          }
          break;
        case $.ui.keyCode.LEFT:
          self.prev("left");
          event.preventDefault();
          break;
        case $.ui.keyCode.UP:
          self.prev("up");
          event.preventDefault();
          break;
        case $.ui.keyCode.RIGHT:
          self.next("right");
          event.preventDefault();
          break;
        case $.ui.keyCode.DOWN:
          self.next("down");
          event.preventDefault();
          break;
        }
      });
      if ($.fn.mousewheel) {
        $(document).mousewheel(function (event, delta) {
          if (!self.lightbox.dialog('isOpen')) {
            return;
          }
          event.preventDefault();
          if (self.lightbox.is(":animated")) {
            return;
          }
          if (delta < 0) {
            self.next("down");
          }
          if (delta > 0) {
            self.prev("up");
          }
        });
      }
    },

    _makeDialog: function () {
      return $('<div/>').dialog({
        autoOpen: false,
        closeOnEscape: false,
        modal: false,
        dialogClass: this.options.dialogClass,
        position: this.options.position,
        resizable: this.options.resizable,
        draggable: this.options.draggable,
        height: this.options.height,
        width: this.options.width,
        // TODO: Support overlay by implementing focus,dragstop,resizestop
        open: function (event, ui) {
          $('.ui-dialog-buttonpane button', $(this).parents('.ui-dialog'))
            .each(function (index, domElement) {
              $(domElement).addClass('button-' + index);
            });
        }
      });
    },

    _buttons: {
      'Previous': function (eventObject) {
        $(this).dialog('option', '_lightbox').prev("right");
      },
      'Next': function (eventObject) {
        $(this).dialog('option', '_lightbox').next("right");
      }
    },

    _showLoadingIndicator: function () {
      var self = this;

      this.loadingIndicatorTimeout = setTimeout(function() {
        if (!self.loadingIndicator) {
          self.loadingIndicator = self._element("div", "ui-loading-indicator ui-corner-all").appendTo(document.body);
        }
        self.loadingIndicator.fadeIn("slow");
      }, 250);
    },

    _hideLoadingIndicator: function () {
      clearTimeout(this.loadingIndicatorTimeout);
      if (this.loadingIndicator) {
        this.loadingIndicator.hide();
      }
    },

    destroy: function () {
      (this.overlay && this.overlay.destroy());
      this.element
        .unbind('.lightbox')
        .removeData('lightbox');
    },

    open: function (anchor) {
      var viewer = (this.lightbox = this._makeDialog());

      this.overlay = this.options.modal ? new $.ui.lightbox.overlay(viewer.data('dialog')) : null;
      this.setCurrentAnchor(anchor);

      viewer.dialog('option', 'show', this.options.show)
        .dialog('option', 'hide', this.options.hide)
        .dialog('option', 'buttons', this._buttons)
        .dialog('option', 'close', self._dialogClose)
        .dialog('open');

      viewer.dialog('option', '_lightbox', this);
    },

    close: function () {
      var self = this,
        anchor = this.getCurrentAnchor(),
        viewer = this.lightbox;

      if (!this.lightbox.dialog('isOpen')) {
        viewer.dialog('close');
      }

      (this.overlay && this.overlay.destroy());

      $.ui.lightbox.overlay.resize();

      // TODO: these need to be destroyed with the widget.
      viewer.dialog('destroy').remove();
    },

    next: function (direction) {
      this._rotate(":gt(", ":first", direction || "up");
    },

    prev: function (direction) {
      this._rotate(":lt(", ":last", direction || "down");
    },

    _anchors: function () {
      // if deemed necessary, cache selection here
      return this.element.find(this.options.selector);
    },

    _setData: function (key, value) {
      switch (key) {
      case "cursor":
        this.options[key] = value;
        this._showLoadingIndicator();
        this._display(this._loadContent(value));
        this._hideLoadingIndicator();
        break;
      }

      $.widget.prototype._setData.apply(this, arguments);
    },

    _display: function (content) {
      var anchor = this.getCurrentAnchor(),
        viewer = this.lightbox;

      viewer.dialog('option', 'title', $(anchor).attr('title') + this.options.titleSuffix);

      viewer.empty();
      viewer.append(content.show());
    },

    _loadContent: function (anchor) {
      var self = this,
        content = 'BUG',
        type = this.options.type ? this.options.type : this._deriveType(anchor);

      switch (type) {
      case "image":
        content = this._element('img')
          .attr("src", anchor.href)
          .load(function (event) {
            self.lightbox.dialog('option', 'position', self.options.position);
          });
        break;
      case "flash":
      case "flashvideo":
      case "quicktime":
      case "realplayer":
      case "windowsmedia":
        $(anchor).media({
          width: this.options.width,
          height: this.options.height,
          src: anchor.href,
          autoplay: 1
        }, function (element, options) {
        }, function (element, data, options, playerName) {
          content = $(data).clone();
          $(data).media('undo');
        });
        break;
      case "iframe":
        content = this._element('iframe').attr('src', anchor.href).attr('frameborder', 0).attr('border', 0);
        break;
      case "html":
      case "dom":
        var reference = $($(anchor).attr('href'));

        content = $(reference).clone();
        break;
      case "ajax":
      case "script":
        $.ajax({
          url: anchor.href,
          type: (parseInt(self.options.post, 10) === 1) ? "POST" : "GET",
          cache: true,
          async: false,
          data: self.options.parameters,
          dataType: (type === "ajax") ? "html" : "script",
          success: function (data, textStatus) {
            content = $(data);
          }
        });
        break;
      }

      return content;
    },

    _deriveType: function (anchor) {
      var reference = anchor.href;
      if (reference.toLowerCase().match(/\.(gif|jpg|jpeg|png)(\?[0123456789]+)?$/)) {
        return "image";
      }
      if (reference.toLowerCase().match(/\.(swf)(\?[0123456789]+)?$/)) {
        return "flash";
      }
      if (reference.toLowerCase().match(/\.(flv)(\?[0123456789]+)?$/)) {
        return "flashvideo";
      }
      if (reference.toLowerCase().match(/\.(aif|aiff|aac|au|bmp|gsm|mov|mid|midi|mpg|mpeg|m4a|m4v|mp4|psd|qt|qtif|qif|qti|snd|tif|tiff|wav|3g2|3gp|wbmp)(\?[0123456789]+)?$/)) {
        return "quicktime";
      }
      if (reference.toLowerCase().match(/\.(ra|ram|rm|rpm|rv|smi|smil)(\?[0123456789]+)?$/)) {
        return "realplayer";
      }
      if (reference.toLowerCase().match(/\.(asf|avi|wma|wmv)(\?[0123456789]+)?$/)) {
        return "windowsmedia";
      }
      return "ajax";
    },

    _preloadNeighbours: function () {
      var anchors = this._anchors(),
        index = anchors.index(this.getCurrentAnchor());
      anchors.filter(this._neighbours(anchors.length, index)).each(function () {
        //new Image().src = this.href;
      });
    },

    _neighbours: function (index, length) {
      return ":eq(" + (index === 0 ? length - 1 : index - 1) + "), :eq(" + (index === length - 1 ? 0 : index + 1) + ")";
    },

    _position: function (img) {
    },

    _resize: function (content) {
      var viewer = this.lightbox,
        dialog = this.lightbox.data('dialog'),
        offset = 20,
        type = this._deriveType(this.getCurrentAnchor()),
        cWidth,cHeight,finalWidth,finalHeight,
        // difference
        deltaContentWidth = viewer.outerWidth() - viewer.width(),
        deltaContentHeight = viewer.outerHeight() - viewer.height(),

        dialogTitlebarWidth = dialog.uiDialogTitlebar.outerWidth(),
        dialogTitlebarHeight = dialog.uiDialogTitlebar.outerHeight(),

        // Window
        wWidth = $(window).width(),
        wHeight = $(window).height(),

        size = (this.size = {});

      $.swap(content[0], {
        position: "absolute",
        visibility: "hidden",
        display: "block"
      }, function () {
        cWidth = $(this).attr('width') || $(this).width(),
        cHeight = $(this).attr('height') || $(this).height();
      });

      // Desired width
      finalWidth = cWidth + deltaContentWidth,
      finalHeight = cHeight + deltaContentHeight + dialogTitlebarHeight,

      ratio = Math.min(
        Math.min(
          Math.min(wWidth - deltaContentWidth - offset, cWidth) / cWidth,
          Math.min(wHeight - deltaContentHeight - dialogTitlebarHeight - offset, cHeight) / cHeight, 1)),

      $.extend(size, {
        width: Math.round(ratio * cWidth),
        height: Math.round(ratio * cHeight)
      });

      if (type == 'image') {
        content.css('width', size.width);
        content.css('height', size.height);
      }

      viewer.dialog('option', 'width', size.width + deltaContentWidth);
      viewer.dialog('option', 'height', size.height + deltaContentHeight + dialogTitlebarHeight);
      viewer.css({
        width: size.width + deltaContentWidth,
        height: size.height + deltaContentHeight
      });
    },

    setCurrentAnchor: function (anchor) {
      this._setData('cursor', anchor);
    },
    getCurrentAnchor: function () {
      return this._getData('cursor');
    },

    _rotate: function (selectorA, selectorB, direction) {
      var self = this,
        content,
        anchors = this._anchors(),
        target = current = this.getCurrentAnchor(),
        viewer = this.lightbox,
        dialog = viewer.data('dialog').uiDialog;

      if (!this.getCurrentAnchor()) {
        console.log('Called _rotate without an anchor');
        return;
      }

      if (anchors.length === 1) {
        return;
      }

      target = anchors.filter(selectorA + anchors.index(current) + ")" + selectorB)[0];
      if (!target && this.options.loop && anchors.length > 1) {
        target = anchors.filter(selectorB)[0];
      }

      dialog.hide(this.options.rotateOut, {
        direction: direction
      }, this.options.duration, function () {
        viewer.dialog('option', 'close', self._rotateClose).dialog('close');
        self.setCurrentAnchor(target);
        $(this).show(self.options.rotateIn, {
          direction: {
            up: "down",
            down: "up",
            left: "right",
            right: "left"
          }[direction]
        }, self.options.duration, function () {
          viewer.dialog('open').dialog('option', 'close', self._dialogClose);
        });
      });
    },

    // Swappable dialog event handlers.

    _rotateClose: function (event, ui) {
      $(this).empty();
    },

    _dialogClose: function (event, ui) {
      $(this).empty().dialog('_lightbox').close();
    },

    _element: function (type, clazz) {
      return $("<" + type + "/>").addClass(clazz).hide();
    }
  });

  $.extend($.ui.lightbox, {
    defaults: {
      loop: true,
      modal: true,
      overlay: {},
      post: 0,
      dialogClass: 'ui-lightbox',
      closeOnEscape: true,
      resizable: false,
      draggable: false,
      selector: "a[href]:has(img[src])",
      titleSuffix: "",
      position: 'center',
      width: 'auto',
      height: 'auto',
      parameters: {},
      duration: 1000,
      rotateIn: 'drop',
      rotateOut: 'drop',
      show: '',
      hide: ''
    },
    uuid: 0,
    overlay: function (dialog) {
      this.$el = $.ui.lightbox.overlay.create(dialog);
    }
  });

  $.extend($.ui.lightbox.overlay, $.ui.dialog.overlay, {});

  $.extend($.ui.lightbox.overlay.prototype, $.ui.dialog.overlay.prototype, {
    destroy: function() {
      $.ui.lightbox.overlay.destroy(this.$el);
    }
  });
})(jQuery);
<|endoftext|>


<commit_before>var keystone = require('keystone');
var Types = keystone.Field.Types;

var UpdateHandlerTest = new keystone.List('UpdateHandlerTest', {
	nocreate: true,
});

UpdateHandlerTest.add({
	name: { type: Types.Name, required: true },
	email: { type: Types.Email },
	image: { type: Types.CloudinaryImage },
});

UpdateHandlerTest.track = true;
UpdateHandlerTest.defaultSort = '-createdAt';
UpdateHandlerTest.defaultColumns = 'name, email, createdAt';
UpdateHandlerTest.register();
<commit_msg>UpdateHandlerTest model should test the track list option<commit_after>var keystone = require('keystone');
var Types = keystone.Field.Types;

var UpdateHandlerTest = new keystone.List('UpdateHandlerTest', {
	nocreate: true,
	track: true,
});

UpdateHandlerTest.add({
	name: { type: Types.Name, required: true },
	email: { type: Types.Email },
	image: { type: Types.CloudinaryImage },
});

UpdateHandlerTest.track = true;
UpdateHandlerTest.defaultSort = '-createdAt';
UpdateHandlerTest.defaultColumns = 'name, email, createdAt';
UpdateHandlerTest.register();
<|endoftext|>