<commit_before>"use strict";

// set the baseUrl for module lookup to '/lib' folder
require.config({
    baseUrl: "/lib"
});

// let require load all the toplevel needed script and call us on domReady
require([   'order!jquery.min',
            'order!jquery-ui.min',
            'domReady',
            'order!./../js/clienttwo.js',
            'order!./../js/TreeBrowserControl.js',
            'order!./../js/JSTreeBrowserWidget.js',
            'order!./../js/delayctrl.js',
            'order!./../js/DynaTreeBrowserWidget.js',
            './../../common/LogManager.js',
            './../../common/CommonUtil.js',
            './../js/ModelEditorControl.js',
            './../js/ModelEditorSVGWidget.js',
            './../js/ModelEditorWidget.js' ], function (jquery,
                                                        jqueryUI,
                                                        domReady,
                                                        Client,
                                                        TreeBrowserControl,
                                                        JSTreeBrowserWidget,
                                                        DelayControl,
                                                        DynaTreeBrowserWidget,
                                                        logManager,
                                                        commonUtil,
                                                        ModelEditorControl,
                                                        ModelEditorSVGWidget,
                                                        ModelEditorWidget) {
    domReady(function () {

        //if ( commonUtil.DEBUG === true ) {
        logManager.setLogLevel(logManager.logLevels.ALL);
        //}

        var client,
            tDynaTree,
            tJSTree,
            modelEditorSVG,
            modelEditorHTML,
            doConnect,
            lastContainerWidth = 0,
            resizeMiddlePane;
        //var delayer = undefined;

        doConnect = function () {

            //figure out the server to connect to
            var serverLocation;

            //by default serverlocation is the same server the page loaded from
            if (commonUtil.ServerIP === "self") {
                serverLocation = 'http://' + window.location.hostname + ':' + commonUtil.ServerPort;
            } else {
                serverLocation = 'http://' + commonUtil.ServerIP + ':' + commonUtil.ServerPort;
            }

            client = new Client(serverLocation);
            client.connect(function () {
                client.makeconnect(function () {
                    tDynaTree = new TreeBrowserControl(client, new DynaTreeBrowserWidget("tbDynaTree"));
                    //delayer = new DelayControl(client.socket, document.getElementById("socketDelayer"));
                    tJSTree = new TreeBrowserControl(client, new JSTreeBrowserWidget("tbJSTree"));

                    modelEditorSVG = new ModelEditorControl(client, new ModelEditorSVGWidget("modelEditorSVG"));
                    modelEditorHTML = new ModelEditorControl(client, new ModelEditorWidget("modelEditorHtml"));
                });
            });
        };

        /*main*/
        doConnect();

        /*
         * Compute the size of the middle pane window based on current browser size
         */
        lastContainerWidth = 0;
        resizeMiddlePane = function () {
            var cW = $("#contentContainer").width(),
                eW = 0,
                eH = 0;
            if (cW !== lastContainerWidth) {
                $("#middlePane").outerWidth(cW - $("#leftPane").outerWidth() - $("#rightPane").outerWidth());
                lastContainerWidth = cW;

                //by default lay out in vertical split
                eW = Math.floor($("#middlePane").width() / 2);
                eH = Math.floor($("#middlePane").height());

                if (eW < 560) {
                    //inner children has to be laid out under each other (horizontal split)
                    eW = Math.floor($("#middlePane").width());
                    eH = Math.floor($("#middlePane").height() / 2);
                }

                $("#modelEditorContainer1").outerWidth(eW).outerHeight(eH);
                $("#modelEditorContainer2").outerWidth(eW).outerHeight(eH);

                //set container position correctly
                if (eW < 560) {
                    $("#modelEditorContainer2").offset({ "top": $("#modelEditorContainer1").outerHeight() + $("#modelEditorContainer1").position().top, "left": $("#modelEditorContainer1").position().left});
                } else {
                    $("#modelEditorContainer2").offset({ "top": $("#modelEditorContainer1").position().top, "left": $("#modelEditorContainer1").outerWidth() + $("#modelEditorContainer1").position().left });
                }

            }
        };

        //hook up windows resize event
        $(window).resize(function () {
            resizeMiddlePane();
        });

        //and call if for the first time as well
        resizeMiddlePane();
    });

});<commit_msg>fix positionning issue for modelEditorContainer2<commit_after>"use strict";

// set the baseUrl for module lookup to '/lib' folder
require.config({
    baseUrl: "/lib"
});

// let require load all the toplevel needed script and call us on domReady
require([   'order!jquery.min',
            'order!jquery-ui.min',
            'domReady',
            'order!./../js/clienttwo.js',
            'order!./../js/TreeBrowserControl.js',
            'order!./../js/JSTreeBrowserWidget.js',
            'order!./../js/delayctrl.js',
            'order!./../js/DynaTreeBrowserWidget.js',
            './../../common/LogManager.js',
            './../../common/CommonUtil.js',
            './../js/ModelEditorControl.js',
            './../js/ModelEditorSVGWidget.js',
            './../js/ModelEditorWidget.js',
            './../js/MultiLevelModelEditorControl.js' ], function (jquery,
                                                        jqueryUI,
                                                        domReady,
                                                        Client,
                                                        TreeBrowserControl,
                                                        JSTreeBrowserWidget,
                                                        DelayControl,
                                                        DynaTreeBrowserWidget,
                                                        logManager,
                                                        commonUtil,
                                                        ModelEditorControl,
                                                        ModelEditorSVGWidget,
                                                        ModelEditorWidget,
                                                        MultiLevelModelEditorControl) {
    domReady(function () {

        //if ( commonUtil.DEBUG === true ) {
        logManager.setLogLevel(logManager.logLevels.ALL);
        //}

        var client,
            tDynaTree,
            tJSTree,
            modelEditorSVG,
            modelEditorHTML,
            doConnect,
            lastContainerWidth = 0,
            resizeMiddlePane;
        //var delayer = undefined;

        doConnect = function () {

            //figure out the server to connect to
            var serverLocation;

            //by default serverlocation is the same server the page loaded from
            if (commonUtil.ServerIP === "self") {
                serverLocation = 'http://' + window.location.hostname + ':' + commonUtil.ServerPort;
            } else {
                serverLocation = 'http://' + commonUtil.ServerIP + ':' + commonUtil.ServerPort;
            }

            client = new Client(serverLocation);
            client.connect(function () {
                client.makeconnect(function () {
                    tDynaTree = new TreeBrowserControl(client, new DynaTreeBrowserWidget("tbDynaTree"));
                    //delayer = new DelayControl(client.socket, document.getElementById("socketDelayer"));
                    tJSTree = new TreeBrowserControl(client, new JSTreeBrowserWidget("tbJSTree"));

                    modelEditorSVG = new ModelEditorControl(client, new ModelEditorSVGWidget("modelEditorSVG"));
                    modelEditorHTML = new MultiLevelModelEditorControl(client, new ModelEditorWidget("modelEditorHtml"));
                });
            });
        };

        /*main*/
        doConnect();

        /*
         * Compute the size of the middle pane window based on current browser size
         */
        lastContainerWidth = 0;
        resizeMiddlePane = function () {
            var cW = $("#contentContainer").width(),
                eW = 0,
                eH = 0,
                horizontalSplit = false;
            if (cW !== lastContainerWidth) {
                $("#middlePane").outerWidth(cW - $("#leftPane").outerWidth() - $("#rightPane").outerWidth());
                lastContainerWidth = cW;

                //by default lay out in vertical split
                eW = Math.floor($("#middlePane").width() / 2);
                eH = Math.floor($("#middlePane").height());

                if (eW < 560) {
                    //inner children has to be laid out under each other (horizontal split)
                    eW = Math.floor($("#middlePane").width());
                    eH = Math.floor($("#middlePane").height() / 2);
                    horizontalSplit = true;
                }

                $("#modelEditorContainer1").outerWidth(eW).outerHeight(eH);
                $("#modelEditorContainer2").outerWidth(eW).outerHeight(eH);

                //set container position correctly
                if (horizontalSplit === true) {
                    $("#modelEditorContainer2").offset({ "top": $("#modelEditorContainer1").outerHeight() + $("#modelEditorContainer1").position().top, "left": $("#modelEditorContainer1").position().left});
                } else {
                    $("#modelEditorContainer2").offset({ "top": $("#modelEditorContainer1").position().top, "left": $("#modelEditorContainer1").outerWidth() + $("#modelEditorContainer1").position().left });
                }

            }
        };

        //hook up windows resize event
        $(window).resize(function () {
            resizeMiddlePane();
        });

        //and call if for the first time as well
        resizeMiddlePane();
    });

});<|endoftext|>


<commit_before>/*
 * Name: jQuery Clickable
 * Description: Designed to make other elements clickable/tapable/pressable based on a sibling or child $links!
 * Version: 0.9
 *
 * Author: Matt Lawson
 * License: licenced under MIT - http://opensource.org/licenses/mit-license.php
 */

// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;(function ($, window, document, undefined) {

  'use strict';

  // undefined is used here as the undefined global variable in ECMAScript 3 is
  // mutable (ie. it can be changed by someone else). undefined isn't really being
  // passed in so we can ensure the value of it is truly undefined. In ES5, undefined
  // can no longer be modified.

  // window and document are passed through as local variable rather than global
  // as this (slightly) quickens the resolution process and can be more efficiently
  // minified (especially when both are regularly referenced in your plugin).

  // Create the defaults once
  var pluginName = 'jqueryClickable',
      defaults = {
        clickable_child: null,                        // Used to make a child element clickable of which the script was executed
        select_link: null,                            // Used to specify which link to use within the clickable box should more than one link be found
        clickable_class: 'clickable',                 // The class that gets added to elements which have been successfully initialized
        hover_class: 'clickable-hover',               // The class that gets added to the onHover state of clickable elements
        focus_class: 'clickable-focus',               // The class that gets added to the onFocus state of clickable elements
        url_prefixes: ['http://', 'https://', 'www.'] // An array of different prefixes that can appear before each link
      };

  // The actual plugin constructor
  function Plugin(element, options) {
    this.element = element;
    // jQuery has an extend method which merges the contents of two or
    // more objects, storing the result in the first object. The first object
    // is generally empty as we don't want to alter the default options for
    // future instances of the plugin
    this.options = $.extend({}, defaults, options);
    this._defaults = defaults;
    this._name = pluginName;
    this.init();
  }

  Plugin.prototype = {
    init: function () {
      // Place initialization logic here
      // You already have access to the DOM element and
      // the options via the instance, e.g. this.element
      // and this.options
      // you can add more functions like the one below and
      // call them like so: this.yourOtherFunction(this.element, this.options).
      // this.options.propertyName

      var $self = this;

      return $(this.element).each(function() {
        // If the box contains more than one link check to see if all the $links in the box are
        // identical. If they are use one to make the box clickable use plugin defaults e.g.: $self.options.clickable_class
        var $link = null,
            attrs = {};

        if( $(this).find('a[href]').length > 1 ) {
          var $links = $(this).find('a[href]');

          if( $self.identicalHref($self, $links) ) {
            attrs = $self.getAttrs($links.get(0));
          } else {
            // If a fallback function for selecting a link is provided
            if( $self.options.select_link ) {
              $link = $self.options.select_link;

              //if link element is returned get the first link
              if( $link ) {
                attrs = $self.getAttrs($links.get(0));
              }
            }
          }
        } else {
          // If the box contains only one link, use it
          if( $(this).find('a[href]').length === 1 ) {
            attrs = $self.getAttrs($(this).find('a[href]'));
          }
        }

        if( attrs.href !== undefined ) {
          // If the element has a valid link to use, Bind the link and add a clickable_class
          $(this).addClass($self.options.clickable_class);
          $self.bindLink($self, $(this), attrs);
        }

      });
    },

    /*
     * Check that all link href attributes in an array are identical
     * @return boolean: true if all of the $links are identical, otherwise false
     */
    identicalHref: function ($self, $links) {
      var first = this.getTrimmedUrl($self, $links.get(0)),
          curr = null,
          is_identical = true;

      $.each($links, function() {
        curr = $self.getTrimmedUrl($self, $(this));
        if( curr !== first ) {
          is_identical = false;
        }
      });

      return is_identical;
    },

    /*
     * Function for extracting the full url from a link and trimming it
     * @return string: A trimmed url (prefixes removed)
     */
    getTrimmedUrl: function ($self, link) {
      return this.trimUrl($self, $(link).attr('href'));
    },

    /*
     * Function for removing standard URL prefixes specified in defaults
     * @return string: The trimmed url (prefixes removed)
     */
    trimUrl: function ($self, url) {
      url = $.trim(url);

      if( $self.options.url_prefixes ) {
        for( var prefix in $self.options.url_prefixes ) {
          if( url.indexOf($self.options.url_prefixes[prefix]) === 0 ) {
            url = url.substring($self.options.url_prefixes[prefix].length);
          }
        }
      }

      return url;
    },

    /*
     * Binds click handler to the target specified in defaults if not null,
     * otherwise apply the click handler to the clickable box
     */
    bindLink: function ($self, box, link_attrs) {
      var $bind_target = ($self.options.clickable_child && $(box).find($self.options.clickable_child).length > 0) ? $(box).find($self.options.clickable_child) : box;

      if( link_attrs.target === '_blank' ) {
        $bind_target.on('click', function(e) {
          e.preventDefault();
          window.open(link_attrs.href); // removed ,link_attrs.text to fix IE issue
        });
      } else {
        $bind_target.on('click', function(e) {
          e.preventDefault();
          window.location.href = link_attrs.href;
        });
      }

      $bind_target.hover(function() {
        $($bind_target).addClass($self.options.hover_class);
      },function() {
        $bind_target.removeClass($self.options.hover_class);
      });

      $bind_target.find('a').focus(function() {
        $bind_target.addClass($self.options.focus_class);
      });

      $bind_target.find('a').blur(function() {
        $bind_target.removeClass($self.options.focus_class);
      });
    },

    /*
     * Function used to get attributes from a link
     * @return: Object containing the $links attributes
     */
    getAttrs: function (link_element) {
      var href = ($(link_element).attr('href') !== "") ? $(link_element).attr('href') : null,
          target = ($(link_element).attr('target') !== "") ? $(link_element).attr('target') : null,
          text = $(link_element).text();

      return {href : href, target : target, text : text};
    }
  };

  // A really lightweight plugin wrapper around the constructor,
  // preventing against multiple instantiations
  $.fn[pluginName] = function (options) {
    return this.each(function () {
      if (!$.data(this, "plugin_" + pluginName)) {
        $.data(this, "plugin_" + pluginName, new Plugin(this, options));
      }
    });
  };

})(jQuery, window, document);
<commit_msg>Tweak to stop some compressors removing the plugin details comment<commit_after>/*!
 * Name: jQuery Clickable
 * Description: Designed to make other elements clickable/tapable/pressable based on a sibling or child $links!
 * Version: 0.9
 *
 * Author: Matt Lawson
 * License: licenced under MIT - http://opensource.org/licenses/mit-license.php
 */

// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;(function ($, window, document, undefined) {

  'use strict';

  // undefined is used here as the undefined global variable in ECMAScript 3 is
  // mutable (ie. it can be changed by someone else). undefined isn't really being
  // passed in so we can ensure the value of it is truly undefined. In ES5, undefined
  // can no longer be modified.

  // window and document are passed through as local variable rather than global
  // as this (slightly) quickens the resolution process and can be more efficiently
  // minified (especially when both are regularly referenced in your plugin).

  // Create the defaults once
  var pluginName = 'jqueryClickable',
      defaults = {
        clickable_child: null,                        // Used to make a child element clickable of which the script was executed
        select_link: null,                            // Used to specify which link to use within the clickable box should more than one link be found
        clickable_class: 'clickable',                 // The class that gets added to elements which have been successfully initialized
        hover_class: 'clickable-hover',               // The class that gets added to the onHover state of clickable elements
        focus_class: 'clickable-focus',               // The class that gets added to the onFocus state of clickable elements
        url_prefixes: ['http://', 'https://', 'www.'] // An array of different prefixes that can appear before each link
      };

  // The actual plugin constructor
  function Plugin(element, options) {
    this.element = element;
    // jQuery has an extend method which merges the contents of two or
    // more objects, storing the result in the first object. The first object
    // is generally empty as we don't want to alter the default options for
    // future instances of the plugin
    this.options = $.extend({}, defaults, options);
    this._defaults = defaults;
    this._name = pluginName;
    this.init();
  }

  Plugin.prototype = {
    init: function () {
      // Place initialization logic here
      // You already have access to the DOM element and
      // the options via the instance, e.g. this.element
      // and this.options
      // you can add more functions like the one below and
      // call them like so: this.yourOtherFunction(this.element, this.options).
      // this.options.propertyName

      var $self = this;

      return $(this.element).each(function() {
        // If the box contains more than one link check to see if all the $links in the box are
        // identical. If they are use one to make the box clickable use plugin defaults e.g.: $self.options.clickable_class
        var $link = null,
            attrs = {};

        if( $(this).find('a[href]').length > 1 ) {
          var $links = $(this).find('a[href]');

          if( $self.identicalHref($self, $links) ) {
            attrs = $self.getAttrs($links.get(0));
          } else {
            // If a fallback function for selecting a link is provided
            if( $self.options.select_link ) {
              $link = $self.options.select_link;

              //if link element is returned get the first link
              if( $link ) {
                attrs = $self.getAttrs($links.get(0));
              }
            }
          }
        } else {
          // If the box contains only one link, use it
          if( $(this).find('a[href]').length === 1 ) {
            attrs = $self.getAttrs($(this).find('a[href]'));
          }
        }

        if( attrs.href !== undefined ) {
          // If the element has a valid link to use, Bind the link and add a clickable_class
          $(this).addClass($self.options.clickable_class);
          $self.bindLink($self, $(this), attrs);
        }

      });
    },

    /*
     * Check that all link href attributes in an array are identical
     * @return boolean: true if all of the $links are identical, otherwise false
     */
    identicalHref: function ($self, $links) {
      var first = this.getTrimmedUrl($self, $links.get(0)),
          curr = null,
          is_identical = true;

      $.each($links, function() {
        curr = $self.getTrimmedUrl($self, $(this));
        if( curr !== first ) {
          is_identical = false;
        }
      });

      return is_identical;
    },

    /*
     * Function for extracting the full url from a link and trimming it
     * @return string: A trimmed url (prefixes removed)
     */
    getTrimmedUrl: function ($self, link) {
      return this.trimUrl($self, $(link).attr('href'));
    },

    /*
     * Function for removing standard URL prefixes specified in defaults
     * @return string: The trimmed url (prefixes removed)
     */
    trimUrl: function ($self, url) {
      url = $.trim(url);

      if( $self.options.url_prefixes ) {
        for( var prefix in $self.options.url_prefixes ) {
          if( url.indexOf($self.options.url_prefixes[prefix]) === 0 ) {
            url = url.substring($self.options.url_prefixes[prefix].length);
          }
        }
      }

      return url;
    },

    /*
     * Binds click handler to the target specified in defaults if not null,
     * otherwise apply the click handler to the clickable box
     */
    bindLink: function ($self, box, link_attrs) {
      var $bind_target = ($self.options.clickable_child && $(box).find($self.options.clickable_child).length > 0) ? $(box).find($self.options.clickable_child) : box;

      if( link_attrs.target === '_blank' ) {
        $bind_target.on('click', function(e) {
          e.preventDefault();
          window.open(link_attrs.href); // removed ,link_attrs.text to fix IE issue
        });
      } else {
        $bind_target.on('click', function(e) {
          e.preventDefault();
          window.location.href = link_attrs.href;
        });
      }

      $bind_target.hover(function() {
        $($bind_target).addClass($self.options.hover_class);
      },function() {
        $bind_target.removeClass($self.options.hover_class);
      });

      $bind_target.find('a').focus(function() {
        $bind_target.addClass($self.options.focus_class);
      });

      $bind_target.find('a').blur(function() {
        $bind_target.removeClass($self.options.focus_class);
      });
    },

    /*
     * Function used to get attributes from a link
     * @return: Object containing the $links attributes
     */
    getAttrs: function (link_element) {
      var href = ($(link_element).attr('href') !== "") ? $(link_element).attr('href') : null,
          target = ($(link_element).attr('target') !== "") ? $(link_element).attr('target') : null,
          text = $(link_element).text();

      return {href : href, target : target, text : text};
    }
  };

  // A really lightweight plugin wrapper around the constructor,
  // preventing against multiple instantiations
  $.fn[pluginName] = function (options) {
    return this.each(function () {
      if (!$.data(this, "plugin_" + pluginName)) {
        $.data(this, "plugin_" + pluginName, new Plugin(this, options));
      }
    });
  };

})(jQuery, window, document);
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012 PrimeBox (info@primebox.co.uk)
 *
 * This work is licensed under the Creative Commons
 * Attribution 3.0 Unported License. To view a copy
 * of this license, visit
 * http://creativecommons.org/licenses/by/3.0/.
 *
 * Documentation available at:
 * http://www.primebox.co.uk/projects/cookie-bar/
 *
 * When using this software you use it at your own risk. We hold
 * no responsibility for any damage caused by using this plugin
 * or the documentation provided.
 */
(function($){
	$.cookieBar = function(options,val){
		if(options=='cookies'){
			var doReturn = 'cookies';
		}else if(options=='set'){
			var doReturn = 'set';
		}else{
			var doReturn = false;
		}
		var defaults = {
			message: 'We use cookies to track usage and preferences.', //Message displayed on bar
			acceptButton: true, //Set to true to show accept/enable button
			acceptText: 'I Understand', //Text on accept/enable button
			acceptFunction: false, //Callback function that triggers when user accepts
			declineButton: false, //Set to true to show decline/disable button
			declineText: 'Disable Cookies', //Text on decline/disable button
			declineFunction: false, //Callback function that triggers when user declines
			policyButton: false, //Set to true to show Privacy Policy button
			policyText: 'Privacy Policy', //Text on Privacy Policy button
			policyFunction: false, //Callback function that triggers before redirect when user clicks policy button
			policyURL: '/privacy-policy/', //URL of Privacy Policy
			autoEnable: true, //Set to true for cookies to be accepted automatically. Banner still shows
			acceptOnContinue: false, //Set to true to silently accept cookies when visitor moves to another page
			expireDays: 365, //Number of days for cookieBar cookie to be stored for
			forceShow: false, //Force cookieBar to show regardless of user cookie preference
			effect: 'slide', //Options: slide, fade, hide
			element: 'body', //Element to append/prepend cookieBar to. Remember "." for class or "#" for id.
			append: false, //Set to true for cookieBar HTML to be placed at base of website. Actual position may change according to CSS
			fixed: false, //Set to true to add the class "fixed" to the cookie bar. Default CSS should fix the position
			bottom: false, //Force CSS when fixed, so bar appears at bottom of website
			customClass: '', // Optional cookie bar class. Target #cookiebar.<customClass> to avoid !important overwrites and separate multiple classes by spaces
			zindex: '', //Can be set in CSS, although some may prefer to set here
			redirect: String(window.location.href), //Current location. Setting to false stops redirect
			domain: String(window.location.hostname), //Location of privacy policy
			referrer: String(document.referrer), //Where visitor has come from
		};
		var options = $.extend(defaults,options);

		//Sets expiration date for cookie
		var expireDate = new Date();
		expireDate.setTime(expireDate.getTime()+(options.expireDays*24*60*60*1000));
		expireDate = expireDate.toGMTString();

		var cookieEntry = 'cb-enabled={value}; expires='+expireDate+'; path=/';

		//Retrieves current cookie preference
		var i,cookieValue='',aCookie,aCookies=document.cookie.split('; ');
		for (i=0;i<aCookies.length;i++){
			aCookie = aCookies[i].split('=');
			if(aCookie[0]=='cb-enabled'){
    			cookieValue = aCookie[1];
			}
		}
		//Sets up default cookie preference if not already set
		if(cookieValue=='' && doReturn!='cookies' && options.autoEnable){
			cookieValue = 'enabled';
			document.cookie = cookieEntry.replace('{value}','enabled');
		}
		if(options.acceptOnContinue){
			if(options.referrer.indexOf(options.domain)>=0 && String(window.location.href).indexOf(options.policyURL)==-1 && doReturn!='cookies' && doReturn!='set' && cookieValue!='accepted' && cookieValue!='declined'){
				doReturn = 'set';
				val = 'accepted';
			}
		}
		if(doReturn=='cookies'){
			//Returns true if cookies are enabled, false otherwise
			if(cookieValue=='enabled' || cookieValue=='accepted'){
				return true;
			}else{
				return false;
			}
		}else if(doReturn=='set' && (val=='accepted' || val=='declined')){
			//Sets value of cookie to 'accepted' or 'declined'
			document.cookie = cookieEntry.replace('{value}',val);
			if(val=='accepted'){
				return true;
			}else{
				return false;
			}
		}else{
			//Sets up enable/accept button if required
			var message = options.message.replace('{policy_url}',options.policyURL);

			if(options.acceptButton){
				var acceptButton = ''+options.acceptText+'';
			}else{
				var acceptButton = '';
			}
			//Sets up disable/decline button if required
			if(options.declineButton){
				var declineButton = ''+options.declineText+'';
			}else{
				var declineButton = '';
			}
			//Sets up privacy policy button if required
			if(options.policyButton){
				var policyButton = ''+options.policyText+'';
			}else{
				var policyButton = '';
			}
			//Whether to add "fixed" class to cookie bar
			if(options.fixed){
				if(options.bottom){
					var classes = ' class="fixed bottom ' + options.customClass + '"';
				}else{
					var classes = ' class="fixed ' + options.customClass + '"';
				}
			}else{
				var classes = ' class="' + options.customClass + '"';
			}
			if(options.zindex!=''){
				var zindex = ' style="z-index:'+options.zindex+';"';
			}else{
				var zindex = '';
			}

			//Displays the cookie bar if arguments met
			if(options.forceShow || cookieValue=='enabled' || cookieValue==''){
				if(options.append){
					$(options.element).append('

'+message+acceptButton+declineButton+policyButton+'

');
				}else{
					$(options.element).prepend('

'+message+acceptButton+declineButton+policyButton+'

');
				}
			}

			//Sets the cookie preference to accepted if enable/accept button pressed
			$('#cookie-bar .cb-enable').click(function(){
				document.cookie = cookieEntry.replace('{value}','accepted');
				if (options.acceptFunction && typeof(options.acceptFunction) === 'function') {
					options.acceptFunction();
				}
				if(cookieValue!='enabled' && cookieValue!='accepted' && options.redirect !== false){
					window.location = options.redirect;
				}else{
					if(options.effect=='slide'){
						$('#cookie-bar').slideUp(300,function(){$('#cookie-bar').remove();});
					}else if(options.effect=='fade'){
						$('#cookie-bar').fadeOut(300,function(){$('#cookie-bar').remove();});
					}else{
						$('#cookie-bar').hide(0,function(){$('#cookie-bar').remove();});
					}
					return false;
				}
			});
			//Sets the cookie preference to declined if disable/decline button pressed
			$('#cookie-bar .cb-disable').click(function(){
				var deleteDate = new Date();
				deleteDate.setTime(deleteDate.getTime()-(864000000));
				deleteDate = deleteDate.toGMTString();
				aCookies=document.cookie.split('; ');
				for (i=0;i<aCookies.length;i++){
					aCookie = aCookies[i].split('=');
					if(aCookie[0].indexOf('_')>=0){
						document.cookie = aCookie[0]+'=0; expires='+deleteDate+'; domain='+options.domain.replace('www','')+'; path=/';
					}else{
						document.cookie = aCookie[0]+'=0; expires='+deleteDate+'; path=/';
					}
				}
				document.cookie = cookieEntry.replace('{value}','declined');
				if (options.declineFunction && typeof(options.declineFunction) === 'function') {
					options.declineFunction();
				}
				if(cookieValue=='enabled' && cookieValue!='accepted' && options.redirect !== false){
					window.location = options.redirect;
				}else{
					if(options.effect=='slide'){
						$('#cookie-bar').slideUp(300,function(){$('#cookie-bar').remove();});
					}else if(options.effect=='fade'){
						$('#cookie-bar').fadeOut(300,function(){$('#cookie-bar').remove();});
					}else{
						$('#cookie-bar').hide(0,function(){$('#cookie-bar').remove();});
					}
					return false;
				}
			});
			//Triggers when the user clicks the policy button
			$('#cookie-bar .cb-policy').click(function(){
				if (options.policyFunction && typeof(options.policyFunction) === 'function') {
					options.policyFunction();
				}
			});
		}
	};
})(jQuery);<commit_msg>Added bang to copyright<commit_after>/*!
 * Copyright (C) 2012 PrimeBox (info@primebox.co.uk)
 *
 * This work is licensed under the Creative Commons
 * Attribution 3.0 Unported License. To view a copy
 * of this license, visit
 * http://creativecommons.org/licenses/by/3.0/.
 *
 * Documentation available at:
 * http://www.primebox.co.uk/projects/cookie-bar/
 *
 * When using this software you use it at your own risk. We hold
 * no responsibility for any damage caused by using this plugin
 * or the documentation provided.
 */
(function($){
	$.cookieBar = function(options,val){
		if(options=='cookies'){
			var doReturn = 'cookies';
		}else if(options=='set'){
			var doReturn = 'set';
		}else{
			var doReturn = false;
		}
		var defaults = {
			message: 'We use cookies to track usage and preferences.', //Message displayed on bar
			acceptButton: true, //Set to true to show accept/enable button
			acceptText: 'I Understand', //Text on accept/enable button
			acceptFunction: false, //Callback function that triggers when user accepts
			declineButton: false, //Set to true to show decline/disable button
			declineText: 'Disable Cookies', //Text on decline/disable button
			declineFunction: false, //Callback function that triggers when user declines
			policyButton: false, //Set to true to show Privacy Policy button
			policyText: 'Privacy Policy', //Text on Privacy Policy button
			policyFunction: false, //Callback function that triggers before redirect when user clicks policy button
			policyURL: '/privacy-policy/', //URL of Privacy Policy
			autoEnable: true, //Set to true for cookies to be accepted automatically. Banner still shows
			acceptOnContinue: false, //Set to true to silently accept cookies when visitor moves to another page
			expireDays: 365, //Number of days for cookieBar cookie to be stored for
			forceShow: false, //Force cookieBar to show regardless of user cookie preference
			effect: 'slide', //Options: slide, fade, hide
			element: 'body', //Element to append/prepend cookieBar to. Remember "." for class or "#" for id.
			append: false, //Set to true for cookieBar HTML to be placed at base of website. Actual position may change according to CSS
			fixed: false, //Set to true to add the class "fixed" to the cookie bar. Default CSS should fix the position
			bottom: false, //Force CSS when fixed, so bar appears at bottom of website
			customClass: '', // Optional cookie bar class. Target #cookiebar.<customClass> to avoid !important overwrites and separate multiple classes by spaces
			zindex: '', //Can be set in CSS, although some may prefer to set here
			redirect: String(window.location.href), //Current location. Setting to false stops redirect
			domain: String(window.location.hostname), //Location of privacy policy
			referrer: String(document.referrer), //Where visitor has come from
		};
		var options = $.extend(defaults,options);

		//Sets expiration date for cookie
		var expireDate = new Date();
		expireDate.setTime(expireDate.getTime()+(options.expireDays*24*60*60*1000));
		expireDate = expireDate.toGMTString();

		var cookieEntry = 'cb-enabled={value}; expires='+expireDate+'; path=/';

		//Retrieves current cookie preference
		var i,cookieValue='',aCookie,aCookies=document.cookie.split('; ');
		for (i=0;i<aCookies.length;i++){
			aCookie = aCookies[i].split('=');
			if(aCookie[0]=='cb-enabled'){
    			cookieValue = aCookie[1];
			}
		}
		//Sets up default cookie preference if not already set
		if(cookieValue=='' && doReturn!='cookies' && options.autoEnable){
			cookieValue = 'enabled';
			document.cookie = cookieEntry.replace('{value}','enabled');
		}
		if(options.acceptOnContinue){
			if(options.referrer.indexOf(options.domain)>=0 && String(window.location.href).indexOf(options.policyURL)==-1 && doReturn!='cookies' && doReturn!='set' && cookieValue!='accepted' && cookieValue!='declined'){
				doReturn = 'set';
				val = 'accepted';
			}
		}
		if(doReturn=='cookies'){
			//Returns true if cookies are enabled, false otherwise
			if(cookieValue=='enabled' || cookieValue=='accepted'){
				return true;
			}else{
				return false;
			}
		}else if(doReturn=='set' && (val=='accepted' || val=='declined')){
			//Sets value of cookie to 'accepted' or 'declined'
			document.cookie = cookieEntry.replace('{value}',val);
			if(val=='accepted'){
				return true;
			}else{
				return false;
			}
		}else{
			//Sets up enable/accept button if required
			var message = options.message.replace('{policy_url}',options.policyURL);

			if(options.acceptButton){
				var acceptButton = ''+options.acceptText+'';
			}else{
				var acceptButton = '';
			}
			//Sets up disable/decline button if required
			if(options.declineButton){
				var declineButton = ''+options.declineText+'';
			}else{
				var declineButton = '';
			}
			//Sets up privacy policy button if required
			if(options.policyButton){
				var policyButton = ''+options.policyText+'';
			}else{
				var policyButton = '';
			}
			//Whether to add "fixed" class to cookie bar
			if(options.fixed){
				if(options.bottom){
					var classes = ' class="fixed bottom ' + options.customClass + '"';
				}else{
					var classes = ' class="fixed ' + options.customClass + '"';
				}
			}else{
				var classes = ' class="' + options.customClass + '"';
			}
			if(options.zindex!=''){
				var zindex = ' style="z-index:'+options.zindex+';"';
			}else{
				var zindex = '';
			}

			//Displays the cookie bar if arguments met
			if(options.forceShow || cookieValue=='enabled' || cookieValue==''){
				if(options.append){
					$(options.element).append('

'+message+acceptButton+declineButton+policyButton+'

');
				}else{
					$(options.element).prepend('

'+message+acceptButton+declineButton+policyButton+'

');
				}
			}

			//Sets the cookie preference to accepted if enable/accept button pressed
			$('#cookie-bar .cb-enable').click(function(){
				document.cookie = cookieEntry.replace('{value}','accepted');
				if (options.acceptFunction && typeof(options.acceptFunction) === 'function') {
					options.acceptFunction();
				}
				if(cookieValue!='enabled' && cookieValue!='accepted' && options.redirect !== false){
					window.location = options.redirect;
				}else{
					if(options.effect=='slide'){
						$('#cookie-bar').slideUp(300,function(){$('#cookie-bar').remove();});
					}else if(options.effect=='fade'){
						$('#cookie-bar').fadeOut(300,function(){$('#cookie-bar').remove();});
					}else{
						$('#cookie-bar').hide(0,function(){$('#cookie-bar').remove();});
					}
					return false;
				}
			});
			//Sets the cookie preference to declined if disable/decline button pressed
			$('#cookie-bar .cb-disable').click(function(){
				var deleteDate = new Date();
				deleteDate.setTime(deleteDate.getTime()-(864000000));
				deleteDate = deleteDate.toGMTString();
				aCookies=document.cookie.split('; ');
				for (i=0;i<aCookies.length;i++){
					aCookie = aCookies[i].split('=');
					if(aCookie[0].indexOf('_')>=0){
						document.cookie = aCookie[0]+'=0; expires='+deleteDate+'; domain='+options.domain.replace('www','')+'; path=/';
					}else{
						document.cookie = aCookie[0]+'=0; expires='+deleteDate+'; path=/';
					}
				}
				document.cookie = cookieEntry.replace('{value}','declined');
				if (options.declineFunction && typeof(options.declineFunction) === 'function') {
					options.declineFunction();
				}
				if(cookieValue=='enabled' && cookieValue!='accepted' && options.redirect !== false){
					window.location = options.redirect;
				}else{
					if(options.effect=='slide'){
						$('#cookie-bar').slideUp(300,function(){$('#cookie-bar').remove();});
					}else if(options.effect=='fade'){
						$('#cookie-bar').fadeOut(300,function(){$('#cookie-bar').remove();});
					}else{
						$('#cookie-bar').hide(0,function(){$('#cookie-bar').remove();});
					}
					return false;
				}
			});
			//Triggers when the user clicks the policy button
			$('#cookie-bar .cb-policy').click(function(){
				if (options.policyFunction && typeof(options.policyFunction) === 'function') {
					options.policyFunction();
				}
			});
		}
	};
})(jQuery);
<|endoftext|>


<commit_before>var module = angular.module("lvl.directives.dragdrop", ['lvl.services']);

module.directive('lvlDraggable', ['$rootScope', 'uuid', function($rootScope, uuid) {
	    return {
	        restrict: 'A',
	        link: function(scope, el, attrs, controller) {
	        	angular.element(el).attr("draggable", "true");

	            var id = angular.element(el).attr("id");
	            if (!id) {
	                id = uuid.new()
	                angular.element(el).attr("id", id);
	            }

	            el.bind("dragstart", function(e) {
	                e.dataTransfer.setData('text', id);

	                $rootScope.$emit("LVL-DRAG-START");
	            });

	            el.bind("dragend", function(e) {
	                $rootScope.$emit("LVL-DRAG-END");
	            });
	        }
    	}
	}]);

module.directive('lvlDropTarget', ['$rootScope', 'uuid', function($rootScope, uuid) {
	    return {
	        restrict: 'A',
	        scope: {
	            onDrop: '&'
	        },
	        link: function(scope, el, attrs, controller) {
	            var id = angular.element(el).attr("id");
	            if (!id) {
	                id = uuid.new()
	                angular.element(el).attr("id", id);
	            }

	            el.bind("dragover", function(e) {
	              if (e.preventDefault) {
	                e.preventDefault(); // Necessary. Allows us to drop.
	              }

	              e.dataTransfer.dropEffect = 'move';  // See the section on the DataTransfer object.
	              return false;
	            });

	            el.bind("dragenter", function(e) {
	              // this / e.target is the current hover target.
	              angular.element(e.target).addClass('lvl-over');
	            });

	            el.bind("dragleave", function(e) {
	              angular.element(e.target).removeClass('lvl-over');  // this / e.target is previous target element.
	            });

	            el.bind("drop", function(e) {
	              if (e.preventDefault) {
	                e.preventDefault(); // Necessary. Allows us to drop.
	              }

	              if (e.stopPropagation) {
	                e.stopPropagation(); // Necessary. Allows us to drop.
	              }
	            	var data = e.dataTransfer.getData("text");
	                var dest = document.getElementById(id);
	                var src = document.getElementById(data);

	                scope.onDrop({dragEl: src, dropEl: dest});
	            });

	            $rootScope.$on("LVL-DRAG-START", function() {
	                var el = document.getElementById(id);
	                angular.element(el).addClass("lvl-target");
	            });

	            $rootScope.$on("LVL-DRAG-END", function() {
	                var el = document.getElementById(id);
	                angular.element(el).removeClass("lvl-target");
	                angular.element(el).removeClass("lvl-over");
	            });
	        }
    	}
	}]);
<commit_msg>Add 'dragid' and 'dropid' and forward these ids in the callback, this has 2 advantages:  - avoid $parse:isecdom error in newer versions of AngularJS  - you can have multiple drag and drop elements with the same id<commit_after>var module = angular.module("lvl.directives.dragdrop", ['lvl.services']);

module.directive('lvlDraggable', ['$rootScope', 'uuid', function($rootScope, uuid) {
	    return {
	        restrict: 'A',
	        scope: {
	            dragid : '='
	        },
	        link: function(scope, el, attrs, controller) {
	        	angular.element(el).attr("draggable", "true");

	            var id;
	            if (scope.dragid) {
	                id = scope.dragid;
	            } else {
                        id = angular.element(el).attr("id");
                        if (!id) {
                            id = uuid.new()
                            angular.element(el).attr("id", id);
                        }
	            }

	            el.bind("dragstart", function(e) {
	                e.dataTransfer.setData('text', id);

	                $rootScope.$emit("LVL-DRAG-START");
	            });

	            el.bind("dragend", function(e) {
	                $rootScope.$emit("LVL-DRAG-END");
	            });
	        }
    	}
	}]);

module.directive('lvlDropTarget', ['$rootScope', 'uuid', function($rootScope, uuid) {
	    return {
	        restrict: 'A',
	        scope: {
	            onDrop: '&',
	            dropid: '='
	        },
	        link: function(scope, el, attrs, controller) {
	            var id;
	            if (scope.dropid) {
	                id = scope.dropid;
	            } else {
	                id = angular.element(el).attr("id");
	                if (!id) {
	                    id = uuid.new()
	                    angular.element(el).attr("id", id);
	                }
	            }

	            el.bind("dragover", function(e) {
	              if (e.preventDefault) {
	                e.preventDefault(); // Necessary. Allows us to drop.
	              }

	              e.dataTransfer.dropEffect = 'move';  // See the section on the DataTransfer object.
	              return false;
	            });

	            el.bind("dragenter", function(e) {
	              // this / e.target is the current hover target.
	              angular.element(e.target).addClass('lvl-over');
	            });

	            el.bind("dragleave", function(e) {
	              angular.element(e.target).removeClass('lvl-over');  // this / e.target is previous target element.
	            });

	            el.bind("drop", function(e) {
	              if (e.preventDefault) {
	                e.preventDefault(); // Necessary. Allows us to drop.
	              }

	              if (e.stopPropagation) {
	                e.stopPropagation(); // Necessary. Allows us to drop.
	              }
	            	var data = e.dataTransfer.getData("text");
	                var dest = id;
	                var src = data;

	                scope.onDrop({dragEl: src, dropEl: dest});
	            });

	            $rootScope.$on("LVL-DRAG-START", function() {
	                var el = document.getElementById(id);
	                angular.element(el).addClass("lvl-target");
	            });

	            $rootScope.$on("LVL-DRAG-END", function() {
	                var el = document.getElementById(id);
	                angular.element(el).removeClass("lvl-target");
	                angular.element(el).removeClass("lvl-over");
	            });
	        }
    	}
	}]);
<|endoftext|>


<commit_before>/*

jQuery.Freefocus 0.7.0

Copyright (c) 2013-2014 Ilia Ablamonov. Licensed under the MIT license.

*/

(function ($) {
  'use strict';

  /*

  ### $.freefocus({options...}, {moveOptions...})

  Set up keyboard navigation.

  Options:

  - `focusedSelector` - selector for currently focused (or active) element. default: `':focus'`
  - `hoverFocus` - focus target elements on mouse enter. default: `false`
  - `throttle` - throttle key input for specified time (in milliseconds).
    You'll need underscore.js included to use this feature. default: `false`

  Move options are passed to `$.fn.freefocus`

  Usage:
  ```
  $.freefocus({hoverFocus: true})
  ```

  ### $.freefocus('remove')

  Remove previously set keyboard navigation.

  ### $.freefocus('cache', options)

  Compute and cache dimension information for focusable elements. Options: `focusablesSelector`, `focusablesFilter`

  */

  $.freefocus = function (setupOptions, moveOptions) {
    if (setupOptions === 'remove') {
      removeHandlers();
      return;
    }

    if (setupOptions === 'cache') {
      cacheFocusables(moveOptions);
      return;
    }

    setupOptions = $.extend({}, $.freefocus.setupOptions, setupOptions);

    var keyHandler = function (move) {
      var options = $.extend({}, moveOptions, { move: move });

      $(setupOptions.focusedSelector).freefocus(options);
    };

    if (typeof setupOptions.throttle === 'number') {
      keyHandler = _.throttle(keyHandler, setupOptions.throttle);
    }

    addHandler('keydown', function (event) {
      var move = $.freefocus.keys[event.which];

      if (!move)
        return;

      event.preventDefault();

      keyHandler(move);
    });

    if (setupOptions.hoverFocus) {
      if (!moveOptions.focusablesSelector)
        throw new Error('focusablesSelector is required for hoverFocus');
      addHandler('mouseenter', moveOptions.focusablesSelector, function () {
        var trigger = (moveOptions || {}).trigger || $.freefocus.moveOptions.trigger;
        var target = $(this);
        if (setupOptions.focusablesFilter)
          target = target.filter(setupOptions.focusablesFilter);
        return target.trigger(trigger);
      });
    }
  };

  /*

  ### .freefocus({moveOptions...})

  Move 'focus' from active element to one of the targets by triggering specified event.

  Options:

  - `move` - move direction: `left` | `right` | `up` | `down`. no default
  - `focusablesSelector` - selector for navigation targets. default: a long selector describing all focusable options in web browsers.
    You may want to provide something shorter to improve performance or use `:focusable` from jQuery UI.
  - `focusablesFilter` — selector that filters targets after they were selected using `focusablesSelector`.
    Separated for performance reasons. default: `':visible'`
  - `focusablesContext` — element or selector, conext for navigation targets search. default: `undefined`
  - `targets` - jQuery object containing 'focusable' elements. no default
    You should supply either focusablesSelector/Filter (preferred if you use nav-*) or explicit targets.
  - `debug` - print weighting information over targets. default: `false`
  - `trigger` - event to trigger on selected target. default: `'focus'`
  - `preTrigger` - event to trigger on selected target before the `trigger` one. default: `false` (don't trigger)
    Useful if `trigger` is `focus` to move the next focused element into view to avoid native behavior.
  - `useNavProps` - respect `nav-*` directional focus navigation style properties. default: `true`
  - `maxDistance` - maximum distance to element to still consider moving to it. default: `Infinity`
  - `cache` - cache dimension information for element. default: `false`.
    You'll need to manually reset cache for moved elements by using `$(element).freefocus('moved')`

  Usage:
  ```
  $(':focus').freefocus({move: 'right', targets: $('[tabindex]')})
  ```

  ### .freefocus('dimensions')

  Get element dimensions `{top, left, width, height}`. Uses cache, if it's enabled.

  ### .freefocus('moved')

  Clears cache for element.

  */

  $.fn.freefocus = function (options) {
    if (options === 'dimensions') {
      var box = getElementBox(this, true);
      return {
        left: box.x1,
        top: box.y1,
        width: box.x2 - box.x1,
        height: box.y2 - box.y1
      };
    }

    if (options === 'moved') {
      this.data('freefocus-dimensions', null);
      return;
    }

    options = $.extend({}, $.freefocus.moveOptions, options);

    if ($.freefocus.moves[options.move] === null)
      throw new Error('Unknown move direction "' + options.move + '"');
    if (!options.targets && !options.focusablesSelector)
      throw new Error('Options should contain either focusablesSelector or targets');
    if (options.targets && !(options.targets instanceof $))
      throw new Error('Argument targets should be a jQuery object');
    if (this.size() > 1)
      throw new Error('Can\'t move from multiple elements');
    if (!this.size())
      return this; // It's useful to be silent here

    if (options.debug) {
      clearDots();
    }

    updateFocusPoint(this, options.move, options.cache);

    var to = targetFromNavProps(this, options) || targetWithMinDistance(this, options);

    if (!to || !to.length)
      return this; // It's useful to be silent here

    moveFocusPoint(to, options.move, options.debug, options.cache);

    if (options.preTrigger) {
      to.trigger(options.preTrigger);
    }
    to.trigger(options.trigger);

    return this;
  };

  /*

  Defaults:

  */

  $.freefocus.moveOptions = {
    focusablesSelector: [
                          'a[href]',
                          'area[href]',
                          'input:enabled',
                          'select:enabled',
                          'textarea:enabled',
                          'button:enabled',
                          'iframe',
                          'object',
                          'embed',
                          '*[tabindex]',
                          '*[contenteditable]'
                        ].join(', '),
    focusablesFilter: ':visible',
    focusablesContext: undefined,
    trigger: 'focus',
    preTrigger: false,
    debug: false,
    useNavProps: true,
    maxDistance: Infinity
  };

  $.freefocus.setupOptions = {
    focusedSelector: ':focus',
    hoverFocus: false,
    throttle: false
  };

  $.freefocus.keys = {
    37: 'left',
    38: 'up',
    39: 'right',
    40: 'down'
  };

  $.freefocus.moves = {
    left: {},
    right: {},
    up: {},
    down: {}
  };

  /*

  Private:

  */

  $.freefocus.focusPoint = {};

  function targetFromNavProps($el, options) {
    var to =
      $el.get(0).style['nav' + (options.move.charAt(0).toUpperCase()) + (options.move.slice(1))] ||
      parseStyleString($el.attr('style') || '')['nav-' + options.move];

    if (!to)
      return;

    if (to === 'none')
      return $();

    if (to.indexOf('#') !== 0)
      throw new Error('Invalid nav-' + options.move + ' selector "' + to + '": only #id allowed.');

    var target = $(to);

    if (options.focusablesFilter && !target.is(options.focusablesFilter))
      return;

    return target;
  }

  function parseStyleString(style) {
    var result = {};
    style.split(';').forEach(function (rule) {
      var kv = rule.split(':');
      if (kv[1])
        result[kv[0].trim()] = kv[1].trim();
    });
    return result;
  }

  function updateFocusPoint($el, direction, cache) {
    var box = getElementBox($el, cache);
    var fp = $.freefocus.focusPoint;

    // If the element was focused by freefocus,
    // thus we have valid current focus point
    if (!$el.is(fp.$el)) {
      fp.$el = $el;
      fp.box = {
        x: (box.x2 - box.x1) / 2,
        y: (box.y2 - box.y1) / 2
      };
    }
    fp.updatedInDirection = coordsInDirection(boxCoordsToClient(fp.box, box), direction);
    fp.updatedInDirection.fwd = boxInDirection(box, direction).fwd2;
  }

  function moveFocusPoint($el, direction, debug, cache) {
    var box = getElementBox($el, cache);
    var fp = $.freefocus.focusPoint;

    fp.$el = $el;

    var boxInDir = boxInDirection(box, direction);
    var movedInDirection = {
      fwd: boxInDir.fwd1,
      ort: bound(fp.updatedInDirection.ort, boxInDir.ort1, boxInDir.ort2)
    };
    fp.box = clientCoordsToBox(coordsFromDirection(movedInDirection, direction), box);

    if (debug) {
      putDot(coordsFromDirection(movedInDirection, direction), '#00f', 'entry focus point for ' + $el.html());
    }
  }

  function targetWithMinDistance($fromEl, options) {
    var fromBox = boxInDirection(getElementBox($fromEl, options.cache), options.move);

    if (options.debug) {
      putDot(coordsFromDirection($.freefocus.focusPoint.updatedInDirection, options.move), '#0f0', 'exit focus point for ' + $fromEl.html());
    }

    var minDistance = Infinity;
    var $resultEl = null;

    var targets;
    if (options.targets) {
      targets = options.targets;
    } else {
      targets = $(options.focusablesSelector, options.focusablesContext);
      if (options.focusablesFilter)
        targets = targets.filter(options.focusablesFilter);
    }

    targets.each(function () {
      var $toEl = $(this);

      // Skip currently focused element
      if ($toEl.is($fromEl))
        return;

      var toBox = boxInDirection(getElementBox($toEl, options.cache), options.move);

      // Skip elements that are not in the direction of movement
      if (toBox.fwd2 <= fromBox.fwd2)
        return;

      var dist = distance(fromBox, toBox);

      if (dist < options.maxDistance && dist < minDistance) {
        $resultEl = $toEl;
        minDistance = dist;
      }
    });

    if (options.debug && $resultEl) {
      console.log('Distance from', $fromEl.get(0), 'to', $resultEl.get(0), 'is', minDistance);
    }

    return $resultEl;
  }

  function distance(fromBox, toBox) {
    var fromPoint = $.freefocus.focusPoint.updatedInDirection;

    var toPoint = {
      fwd: toBox.fwd1,
      ort: bound(fromPoint.ort, toBox.ort1, toBox.ort2)
    };

    var fwdDist = Math.abs(toPoint.fwd - fromPoint.fwd);
    var ortDist = Math.abs(toPoint.ort - fromPoint.ort);

    // The Euclidian distance between the current focus point position and
    // its potential position in the candidate.
    // If the two positions have the same coordinate on the axis orthogonal
    // to the navigation direction, dotDist is forced to 0 in order to favor
    // elements in direction of navigation
    var dotDist;
    if (toPoint.ort === fromPoint.ort) {
      dotDist = 0;
    } else {
      dotDist = Math.sqrt(fwdDist * fwdDist + ortDist * ortDist);
    }

    // The overlap between the opposing edges of currently focused element and the candidate.
    // Elements are rewarded for having high overlap with the currently focused element.
    var overlap = boxOverlap(fromBox, toBox);

    return dotDist + fwdDist + 2 * ortDist - Math.sqrt(overlap);
  }

  function boxOverlap(box1, box2) {
    var orts = {
      ort1: box1.ort1,
      ort2: box1.ort2
    };

    if (box2.ort1 > orts.ort1)
      orts.ort1 = box2.ort1;
    if (box2.ort2 < orts.ort2)
      orts.ort2 = box2.ort2;

    var result = orts.ort2 - orts.ort1;
    if (result < 0)
      result = 0;

    return result;
  }

  function computeElementBox($el) {
    var offset = $el.offset();
    return {
      x1: offset.left,
      y1: offset.top,
      x2: offset.left + $el.outerWidth(),
      y2: offset.top + $el.outerHeight()
    };
  }

  function getElementBox($el, cache) {
    if (!cache)
      return computeElementBox($el);

    var box = $el.data('freefocus-dimensions');
    if (!box) {
      box = computeElementBox($el);
      $el.data('freefocus-dimensions', box);
    }
    return box;
  }

  function boxInDirection(box, direction) {
    var p1 = coordsInDirection({ x: box.x1, y: box.y1 }, direction);
    var p2 = coordsInDirection({ x: box.x2, y: box.y2 }, direction);
    return {
      fwd1: Math.min(p1.fwd, p2.fwd),
      ort1: Math.min(p1.ort, p2.ort),
      fwd2: Math.max(p1.fwd, p2.fwd),
      ort2: Math.max(p1.ort, p2.ort)
    };
  }

  function coordsInDirection(coords, direction) {
    switch (direction) {
      case 'left':
        return { fwd: -coords.x, ort: -coords.y };
      case 'right':
        return { fwd:  coords.x, ort:  coords.y };
      case 'down':
        return { fwd:  coords.y, ort: -coords.x };
      case 'up':
        return { fwd: -coords.y, ort:  coords.x };
    }
  }

  function coordsFromDirection(coords, direction) {
    switch (direction) {
      case 'left':
        return { x: -coords.fwd, y: -coords.ort };
      case 'right':
        return { x:  coords.fwd, y:  coords.ort };
      case 'down':
        return { x: -coords.ort, y:  coords.fwd };
      case 'up':
        return { x:  coords.ort, y: -coords.fwd };
    }
  }

  function boxCoordsToClient(coords, box) {
    return {
      x: coords.x + box.x1,
      y: coords.y + box.y1
    };
  }

  function clientCoordsToBox(coords, box) {
    return {
      x: coords.x - box.x1,
      y: coords.y - box.y1
    };
  }

  function bound(val, min, max) {
    return Math.min(Math.max(val, min), max);
  }

  function cacheFocusables(options) {
    var targets = $(options.focusablesSelector, options.focusablesContext);
    if (options.focusablesFilter)
      targets = targets.filter(options.focusablesFilter);
    targets.each(function () {
      getElementBox($(this), true);
    });
  }

  /*

  Debug:

  */

  function clearDots() {
    $('.freefocus-debug').remove();
  }

  function putDot(coords, color, title) {
    $('

').appendTo($('body')).css({
      position: 'absolute',
      left: coords.x - 3,
      top: coords.y - 3,
      width: 6,
      height: 6,
      background: color,
      'border-radius': 3
    }).attr('title', title);
  }

  /*

  Event handlers:

  */

  var eventHandlers = [];
  var $document = $(document);

  function addHandler() {
    $document.on.apply($document, arguments);
    eventHandlers.push(arguments);
  }

  function removeHandlers() {
    eventHandlers.forEach(function (args) {
      $document.off.apply($document, args);
    });
    eventHandlers = [];
  }
})(jQuery);
<commit_msg>Don't cache dimensions call results<commit_after>/*

jQuery.Freefocus 0.7.0

Copyright (c) 2013-2014 Ilia Ablamonov. Licensed under the MIT license.

*/

(function ($) {
  'use strict';

  /*

  ### $.freefocus({options...}, {moveOptions...})

  Set up keyboard navigation.

  Options:

  - `focusedSelector` - selector for currently focused (or active) element. default: `':focus'`
  - `hoverFocus` - focus target elements on mouse enter. default: `false`
  - `throttle` - throttle key input for specified time (in milliseconds).
    You'll need underscore.js included to use this feature. default: `false`

  Move options are passed to `$.fn.freefocus`

  Usage:
  ```
  $.freefocus({hoverFocus: true})
  ```

  ### $.freefocus('remove')

  Remove previously set keyboard navigation.

  ### $.freefocus('cache', options)

  Compute and cache dimension information for focusable elements. Options: `focusablesSelector`, `focusablesFilter`

  */

  $.freefocus = function (setupOptions, moveOptions) {
    if (setupOptions === 'remove') {
      removeHandlers();
      return;
    }

    if (setupOptions === 'cache') {
      cacheFocusables(moveOptions);
      return;
    }

    setupOptions = $.extend({}, $.freefocus.setupOptions, setupOptions);

    var keyHandler = function (move) {
      var options = $.extend({}, moveOptions, { move: move });

      $(setupOptions.focusedSelector).freefocus(options);
    };

    if (typeof setupOptions.throttle === 'number') {
      keyHandler = _.throttle(keyHandler, setupOptions.throttle);
    }

    addHandler('keydown', function (event) {
      var move = $.freefocus.keys[event.which];

      if (!move)
        return;

      event.preventDefault();

      keyHandler(move);
    });

    if (setupOptions.hoverFocus) {
      if (!moveOptions.focusablesSelector)
        throw new Error('focusablesSelector is required for hoverFocus');
      addHandler('mouseenter', moveOptions.focusablesSelector, function () {
        var trigger = (moveOptions || {}).trigger || $.freefocus.moveOptions.trigger;
        var target = $(this);
        if (setupOptions.focusablesFilter)
          target = target.filter(setupOptions.focusablesFilter);
        return target.trigger(trigger);
      });
    }
  };

  /*

  ### .freefocus({moveOptions...})

  Move 'focus' from active element to one of the targets by triggering specified event.

  Options:

  - `move` - move direction: `left` | `right` | `up` | `down`. no default
  - `focusablesSelector` - selector for navigation targets. default: a long selector describing all focusable options in web browsers.
    You may want to provide something shorter to improve performance or use `:focusable` from jQuery UI.
  - `focusablesFilter` — selector that filters targets after they were selected using `focusablesSelector`.
    Separated for performance reasons. default: `':visible'`
  - `focusablesContext` — element or selector, conext for navigation targets search. default: `undefined`
  - `targets` - jQuery object containing 'focusable' elements. no default
    You should supply either focusablesSelector/Filter (preferred if you use nav-*) or explicit targets.
  - `debug` - print weighting information over targets. default: `false`
  - `trigger` - event to trigger on selected target. default: `'focus'`
  - `preTrigger` - event to trigger on selected target before the `trigger` one. default: `false` (don't trigger)
    Useful if `trigger` is `focus` to move the next focused element into view to avoid native behavior.
  - `useNavProps` - respect `nav-*` directional focus navigation style properties. default: `true`
  - `maxDistance` - maximum distance to element to still consider moving to it. default: `Infinity`
  - `cache` - cache dimension information for element. default: `false`.
    You'll need to manually reset cache for moved elements by using `$(element).freefocus('moved')`

  Usage:
  ```
  $(':focus').freefocus({move: 'right', targets: $('[tabindex]')})
  ```

  ### .freefocus('dimensions')

  Get element dimensions `{top, left, width, height}`. Uses cache, if it's enabled.

  ### .freefocus('moved')

  Clears cache for element.

  */

  $.fn.freefocus = function (options) {
    if (options === 'dimensions') {
      var box = getElementBox(this, true, false);
      return {
        left: box.x1,
        top: box.y1,
        width: box.x2 - box.x1,
        height: box.y2 - box.y1
      };
    }

    if (options === 'moved') {
      this.data('freefocus-dimensions', null);
      return;
    }

    options = $.extend({}, $.freefocus.moveOptions, options);

    if ($.freefocus.moves[options.move] === null)
      throw new Error('Unknown move direction "' + options.move + '"');
    if (!options.targets && !options.focusablesSelector)
      throw new Error('Options should contain either focusablesSelector or targets');
    if (options.targets && !(options.targets instanceof $))
      throw new Error('Argument targets should be a jQuery object');
    if (this.size() > 1)
      throw new Error('Can\'t move from multiple elements');
    if (!this.size())
      return this; // It's useful to be silent here

    if (options.debug) {
      clearDots();
    }

    updateFocusPoint(this, options.move, options.cache);

    var to = targetFromNavProps(this, options) || targetWithMinDistance(this, options);

    if (!to || !to.length)
      return this; // It's useful to be silent here

    moveFocusPoint(to, options.move, options.debug, options.cache);

    if (options.preTrigger) {
      to.trigger(options.preTrigger);
    }
    to.trigger(options.trigger);

    return this;
  };

  /*

  Defaults:

  */

  $.freefocus.moveOptions = {
    focusablesSelector: [
                          'a[href]',
                          'area[href]',
                          'input:enabled',
                          'select:enabled',
                          'textarea:enabled',
                          'button:enabled',
                          'iframe',
                          'object',
                          'embed',
                          '*[tabindex]',
                          '*[contenteditable]'
                        ].join(', '),
    focusablesFilter: ':visible',
    focusablesContext: undefined,
    trigger: 'focus',
    preTrigger: false,
    debug: false,
    useNavProps: true,
    maxDistance: Infinity
  };

  $.freefocus.setupOptions = {
    focusedSelector: ':focus',
    hoverFocus: false,
    throttle: false
  };

  $.freefocus.keys = {
    37: 'left',
    38: 'up',
    39: 'right',
    40: 'down'
  };

  $.freefocus.moves = {
    left: {},
    right: {},
    up: {},
    down: {}
  };

  /*

  Private:

  */

  $.freefocus.focusPoint = {};

  function targetFromNavProps($el, options) {
    var to =
      $el.get(0).style['nav' + (options.move.charAt(0).toUpperCase()) + (options.move.slice(1))] ||
      parseStyleString($el.attr('style') || '')['nav-' + options.move];

    if (!to)
      return;

    if (to === 'none')
      return $();

    if (to.indexOf('#') !== 0)
      throw new Error('Invalid nav-' + options.move + ' selector "' + to + '": only #id allowed.');

    var target = $(to);

    if (options.focusablesFilter && !target.is(options.focusablesFilter))
      return;

    return target;
  }

  function parseStyleString(style) {
    var result = {};
    style.split(';').forEach(function (rule) {
      var kv = rule.split(':');
      if (kv[1])
        result[kv[0].trim()] = kv[1].trim();
    });
    return result;
  }

  function updateFocusPoint($el, direction, cache) {
    var box = getElementBox($el, cache, cache);
    var fp = $.freefocus.focusPoint;

    // If the element was focused by freefocus,
    // thus we have valid current focus point
    if (!$el.is(fp.$el)) {
      fp.$el = $el;
      fp.box = {
        x: (box.x2 - box.x1) / 2,
        y: (box.y2 - box.y1) / 2
      };
    }
    fp.updatedInDirection = coordsInDirection(boxCoordsToClient(fp.box, box), direction);
    fp.updatedInDirection.fwd = boxInDirection(box, direction).fwd2;
  }

  function moveFocusPoint($el, direction, debug, cache) {
    var box = getElementBox($el, cache, cache);
    var fp = $.freefocus.focusPoint;

    fp.$el = $el;

    var boxInDir = boxInDirection(box, direction);
    var movedInDirection = {
      fwd: boxInDir.fwd1,
      ort: bound(fp.updatedInDirection.ort, boxInDir.ort1, boxInDir.ort2)
    };
    fp.box = clientCoordsToBox(coordsFromDirection(movedInDirection, direction), box);

    if (debug) {
      putDot(coordsFromDirection(movedInDirection, direction), '#00f', 'entry focus point for ' + $el.html());
    }
  }

  function targetWithMinDistance($fromEl, options) {
    var fromBox = boxInDirection(getElementBox($fromEl, options.cache, options.cache), options.move);

    if (options.debug) {
      putDot(coordsFromDirection($.freefocus.focusPoint.updatedInDirection, options.move), '#0f0', 'exit focus point for ' + $fromEl.html());
    }

    var minDistance = Infinity;
    var $resultEl = null;

    var targets;
    if (options.targets) {
      targets = options.targets;
    } else {
      targets = $(options.focusablesSelector, options.focusablesContext);
      if (options.focusablesFilter)
        targets = targets.filter(options.focusablesFilter);
    }

    targets.each(function () {
      var $toEl = $(this);

      // Skip currently focused element
      if ($toEl.is($fromEl))
        return;

      var toBox = boxInDirection(getElementBox($toEl, options.cache, options.cache), options.move);

      // Skip elements that are not in the direction of movement
      if (toBox.fwd2 <= fromBox.fwd2)
        return;

      var dist = distance(fromBox, toBox);

      if (dist < options.maxDistance && dist < minDistance) {
        $resultEl = $toEl;
        minDistance = dist;
      }
    });

    if (options.debug && $resultEl) {
      console.log('Distance from', $fromEl.get(0), 'to', $resultEl.get(0), 'is', minDistance);
    }

    return $resultEl;
  }

  function distance(fromBox, toBox) {
    var fromPoint = $.freefocus.focusPoint.updatedInDirection;

    var toPoint = {
      fwd: toBox.fwd1,
      ort: bound(fromPoint.ort, toBox.ort1, toBox.ort2)
    };

    var fwdDist = Math.abs(toPoint.fwd - fromPoint.fwd);
    var ortDist = Math.abs(toPoint.ort - fromPoint.ort);

    // The Euclidian distance between the current focus point position and
    // its potential position in the candidate.
    // If the two positions have the same coordinate on the axis orthogonal
    // to the navigation direction, dotDist is forced to 0 in order to favor
    // elements in direction of navigation
    var dotDist;
    if (toPoint.ort === fromPoint.ort) {
      dotDist = 0;
    } else {
      dotDist = Math.sqrt(fwdDist * fwdDist + ortDist * ortDist);
    }

    // The overlap between the opposing edges of currently focused element and the candidate.
    // Elements are rewarded for having high overlap with the currently focused element.
    var overlap = boxOverlap(fromBox, toBox);

    return dotDist + fwdDist + 2 * ortDist - Math.sqrt(overlap);
  }

  function boxOverlap(box1, box2) {
    var orts = {
      ort1: box1.ort1,
      ort2: box1.ort2
    };

    if (box2.ort1 > orts.ort1)
      orts.ort1 = box2.ort1;
    if (box2.ort2 < orts.ort2)
      orts.ort2 = box2.ort2;

    var result = orts.ort2 - orts.ort1;
    if (result < 0)
      result = 0;

    return result;
  }

  function computeElementBox($el) {
    var offset = $el.offset();
    return {
      x1: offset.left,
      y1: offset.top,
      x2: offset.left + $el.outerWidth(),
      y2: offset.top + $el.outerHeight()
    };
  }

  function getElementBox($el, readCache, writeCache) {
    var box;

    if (readCache)
      box = $el.data('freefocus-dimensions');
    if (!box)
      box = computeElementBox($el);
    if (writeCache)
      $el.data('freefocus-dimensions', box);

    return box;
  }

  function boxInDirection(box, direction) {
    var p1 = coordsInDirection({ x: box.x1, y: box.y1 }, direction);
    var p2 = coordsInDirection({ x: box.x2, y: box.y2 }, direction);
    return {
      fwd1: Math.min(p1.fwd, p2.fwd),
      ort1: Math.min(p1.ort, p2.ort),
      fwd2: Math.max(p1.fwd, p2.fwd),
      ort2: Math.max(p1.ort, p2.ort)
    };
  }

  function coordsInDirection(coords, direction) {
    switch (direction) {
      case 'left':
        return { fwd: -coords.x, ort: -coords.y };
      case 'right':
        return { fwd:  coords.x, ort:  coords.y };
      case 'down':
        return { fwd:  coords.y, ort: -coords.x };
      case 'up':
        return { fwd: -coords.y, ort:  coords.x };
    }
  }

  function coordsFromDirection(coords, direction) {
    switch (direction) {
      case 'left':
        return { x: -coords.fwd, y: -coords.ort };
      case 'right':
        return { x:  coords.fwd, y:  coords.ort };
      case 'down':
        return { x: -coords.ort, y:  coords.fwd };
      case 'up':
        return { x:  coords.ort, y: -coords.fwd };
    }
  }

  function boxCoordsToClient(coords, box) {
    return {
      x: coords.x + box.x1,
      y: coords.y + box.y1
    };
  }

  function clientCoordsToBox(coords, box) {
    return {
      x: coords.x - box.x1,
      y: coords.y - box.y1
    };
  }

  function bound(val, min, max) {
    return Math.min(Math.max(val, min), max);
  }

  function cacheFocusables(options) {
    var targets = $(options.focusablesSelector, options.focusablesContext);
    if (options.focusablesFilter)
      targets = targets.filter(options.focusablesFilter);
    targets.each(function () {
      getElementBox($(this), true, true);
    });
  }

  /*

  Debug:

  */

  function clearDots() {
    $('.freefocus-debug').remove();
  }

  function putDot(coords, color, title) {
    $('

').appendTo($('body')).css({
      position: 'absolute',
      left: coords.x - 3,
      top: coords.y - 3,
      width: 6,
      height: 6,
      background: color,
      'border-radius': 3
    }).attr('title', title);
  }

  /*

  Event handlers:

  */

  var eventHandlers = [];
  var $document = $(document);

  function addHandler() {
    $document.on.apply($document, arguments);
    eventHandlers.push(arguments);
  }

  function removeHandlers() {
    eventHandlers.forEach(function (args) {
      $document.off.apply($document, args);
    });
    eventHandlers = [];
  }
})(jQuery);
<|endoftext|>


<commit_before>/*!
 * jQuery lockfixed plugin
 * http://www.directlyrics.com/code/lockfixed/
 *
 * Copyright 2012 Yvo Schaap
 * Released under the MIT license
 * http://www.directlyrics.com/code/lockfixed/license.txt
 *
 * Date: Sun March 4 2014 12:00:01 GMT
 */
(function($, undefined){
	$.extend({
		/**
		 * Lockfixed initiated
		 * @param {Element} el - a jquery element, DOM node or selector string
		 * @param {Object} config - offset - forcemargin
		 */
		"lockfixed": function(el, config){
			if (config && config.offset) {
				config.offset.bottom = parseInt(config.offset.bottom,10);
				config.offset.top = parseInt(config.offset.top,10);
			}else{
				config.offset = {bottom: 100, top: 0};
			}
			var el = $(el);
			if(el && el.offset()){
				var el_position = el.css("position"),
					el_margin_top = parseInt(el.css("marginTop"),10),
					el_position_top = el.css("top"),
					el_top = el.offset().top,
					pos_not_fixed = false;

				/*
				 * We prefer feature testing, too much hassle for the upside
				 * while prettier to use position: fixed (less jitter when scrolling)
				 * iOS 5+ + Android has fixed support, but issue with toggeling between fixed and not and zoomed view
				 */
				if (config.forcemargin === true || navigator.userAgent.match(/\bMSIE (4|5|6)\./) || navigator.userAgent.match(/\bOS ([0-9])_/) || navigator.userAgent.match(/\bAndroid ([0-9])\./i)){
					pos_not_fixed = true;
				}

				/*
				// adds throttle to scroll call
				$(window).bind('scroll',el,function(e){

					window.setTimeout(function(){
						$(document).trigger('lockfixed:pageupdate');
					},25);
				});
				*/

				$(window).bind('DOMContentLoaded load scroll resize orientationchange lockfixed:pageupdate',el,function(e){
					// if we have a input focus don't change this (for smaller screens)
					if(pos_not_fixed && document.activeElement && document.activeElement.nodeName === "INPUT"){
						return;
					}

					var top = 0,
						el_height = el.outerHeight(),
						el_width = el.outerWidth(),
						max_height = $(document).height() - config.offset.bottom,
						scroll_top = $(window).scrollTop();

					// if element is not currently fixed position, reset measurements ( this handles DOM changes in dynamic pages )
					if (el.css("position") !== "fixed" && !pos_not_fixed) {
						el_top = el.offset().top;
						el_position_top = el.css("top");
					}

					if (scroll_top >= (el_top-(el_margin_top ? el_margin_top : 0)-config.offset.top)){

						if(max_height < (scroll_top + el_height + el_margin_top + config.offset.top)){
							top = (scroll_top + el_height + el_margin_top + config.offset.top) - max_height;
						}else{
							top = 0;
						}

						if (pos_not_fixed){
							el.css({'marginTop': (parseInt(scroll_top - el_top - top,10) + (2 * config.offset.top))+'px'});
						}else{
							el.css({'position': 'fixed','top':(config.offset.top-top)+'px','width':el_width +"px"});
						}
					}else{
						el.css({'position': el_position,'top': el_position_top, 'width':el_width +"px", 'marginTop': (el_margin_top && !pos_not_fixed ? el_margin_top : 0)+"px"});
					}
				});
			}
		}
	});
})(jQuery);<commit_msg>Fixes two bugs<commit_after>/*!
 * jQuery lockfixed plugin
 * http://www.directlyrics.com/code/lockfixed/
 *
 * Copyright 2012 Yvo Schaap
 * Released under the MIT license
 * http://www.directlyrics.com/code/lockfixed/license.txt
 *
 * Date: Sun March 4 2014 12:00:01 GMT
 */
(function($, undefined){
	$.extend({
		/**
		 * Lockfixed initiated
		 * @param {Element} el - a jquery element, DOM node or selector string
		 * @param {Object} config - offset - forcemargin
		 */
		"lockfixed": function(el, config){
			if (config && config.offset) {
				config.offset.bottom = parseInt(config.offset.bottom,10);
				config.offset.top = parseInt(config.offset.top,10);
			}else{
				config.offset = {bottom: 100, top: 0};
			}
			var el = $(el);
			if(el && el.offset()){
				var el_position = el.css("position"),
					el_margin_top = parseInt(el.css("marginTop"),10) || 0,
					el_position_top = el.css("top"),
					el_top = el.offset().top,
					pos_not_fixed = false;

				/*
				 * We prefer feature testing, too much hassle for the upside
				 * while prettier to use position: fixed (less jitter when scrolling)
				 * iOS 5+ + Android has fixed support, but issue with toggeling between fixed and not and zoomed view
				 */
				if (config.forcemargin === true || navigator.userAgent.match(/\bMSIE (4|5|6)\./) || navigator.userAgent.match(/\bOS ([0-9])_/) || navigator.userAgent.match(/\bAndroid ([0-9])\./i)){
					pos_not_fixed = true;
				}

				/*
				// adds throttle to scroll call
				$(window).bind('scroll',el,function(e){

					window.setTimeout(function(){
						$(document).trigger('lockfixed:pageupdate');
					},25);
				});
				*/

				$(window).bind('DOMContentLoaded load scroll resize orientationchange lockfixed:pageupdate',el,function(e){
					// if we have a input focus don't change this (for smaller screens)
					if(pos_not_fixed && document.activeElement && document.activeElement.nodeName === "INPUT"){
						return;
					}

					var top = 0,
						el_height = el.outerHeight(),
						el_width = el.outerWidth(),
						max_height = $(document).height() - config.offset.bottom,
						scroll_top = $(window).scrollTop();

					// if element is not currently fixed position, reset measurements ( this handles DOM changes in dynamic pages )
					if (el.css("position") !== "fixed" && !pos_not_fixed) {
						el_top = el.offset().top;
						el_position_top = el.css("top");
					}

					if (scroll_top >= (el_top-(el_margin_top ? el_margin_top : 0)-config.offset.top)){

						if(
							max_height < (scroll_top + el_height + el_margin_top + config.offset.top) &&
							el_height + config.offset.top > $(window).height()
						){
							top = (scroll_top + el_height + el_margin_top + config.offset.top) - max_height;
						}else{
							top = 0;
						}

						if (pos_not_fixed){
							el.css({'marginTop': (parseInt(scroll_top - el_top - top,10) + (2 * config.offset.top))+'px'});
						}else{
							el.css({'position': 'fixed','top':(config.offset.top-top)+'px','width':el_width +"px"});
						}
					}else{
						el.css({'position': el_position,'top': el_position_top, 'width':el_width +"px", 'marginTop': (el_margin_top && !pos_not_fixed ? el_margin_top : 0)+"px"});
					}
				});
			}
		}
	});
})(jQuery);
<|endoftext|>