text: /*! bigSlide - v0.12.0 - 2016-08-01
  * http://ascott1.github.io/bigSlide.js/
  * Copyright (c) 2016 Adam D. Scott; Licensed MIT */
  
  module.exports = {
    init: init
  }
  
  function init($) {
    'use strict';
  
    // where inlineCSS is the string value of an element's style attribute
    // and toRemove is a string of space-separated CSS properties,
    // _cleanInlineCSS removes the CSS declaration for each property in toRemove from inlineCSS
    // and returns the resulting string
    function _cleanInlineCSS(inlineCSS, toRemove){
      var inlineCSSArray  = inlineCSS.split(';');
      var toRemoveArray   = toRemove.split(' ');
  
      var cleaned         = '';
      var keep;
  
      for (var i = 0, j = inlineCSSArray.length; i < j; i++) {
        keep = true;
        for (var a = 0, b = toRemoveArray.length; a < b; a++) {
          if (inlineCSSArray[i] === '' || inlineCSSArray[i].indexOf(toRemoveArray[a]) !== -1) {
            keep = false;
          }
        }
        if(keep) {cleaned += inlineCSSArray[i] + '; ';}
      }
  
      return cleaned;
    }
  
    if ($ != null) {
      $.fn.bigSlide = function(options) {
        // store the menuLink in a way that is globally accessible
        var menuLink = this;
  
        // plugin settings
        var settings = $.extend({
          'menu': ('#menu'),
          'push': ('.push'),
          'shrink': ('.shrink'),
          'hiddenThin': ('.hiddenThin'),
          'side': 'left',
          'menuWidth': '15.625em',
          'semiOpenMenuWidth': '4em',
          'speed': '300',
          'state': 'closed',
          'activeBtn': 'active',
          'easyClose': false,
          'saveState': false,
          'semiOpenStatus': false,
          'semiOpenScreenWidth': 480,
          'beforeOpen': function () {},
          'afterOpen': function() {},
          'beforeClose': function() {},
          'afterClose': function() {}
        }, options);
  
        // CSS properties set by bigSlide.js on all implicated DOM elements
        var baseCSSDictionary = 'transition -o-transition -ms-transition -moz-transitions webkit-transition ' + settings.side;
  
        var model = {
          //CSS properties set by bigSlide.js on this.$menu
          menuCSSDictionary: baseCSSDictionary + ' position top bottom height width',
          //CSS properties set by bigSlide.js on this.$push
          pushCSSDictionary: baseCSSDictionary,
          // store the menu's state in the model
          'state': settings.state
        };
  
        // talk back and forth between the view and state
        var controller = {
          init: function(){
            view.init();
          },
  
          // remove bigSlide behavior from the menu
          _destroy: function(){
            view._destroy();
  
            delete menuLink.bigSlideAPI;
  
            // return a reference to the DOM selection bigSlide.js was called on
            // so that the destroy method is chainable
            return menuLink;
          },
  
          // update the menu's state
          changeState: function(){
            if (model.state === 'closed') {
              model.state = 'open'
            } else {
              model.state = 'closed'
            }
          },
  
          // set the menu's state
          setState: function(state){
            model.state = state;
          },
  
          // check the menu's state
          getState: function(){
            return model.state;
          }
        };
  
        // the view contains all of the visual interactions
        var view = {
          init: function(){
            // cache DOM values
            this.$menu = $(settings.menu);
            this.$push = $(settings.push);
            this.$shrink = $(settings.shrink);
            this.$hiddenThin = $(settings.hiddenThin);
            this.width = settings.menuWidth;
            this.semiOpenMenuWidth = settings.semiOpenMenuWidth;
  
            // CSS for how the menu will be positioned off screen
            var positionOffScreen = {
              'position': 'absolute',
              'top': '0',
              'bottom': '0',
              'height': '100%'
            };
  
            // css for the sliding animation
            var animateSlide = {
              '-webkit-transition': settings.side + ' ' + settings.speed + 'ms ease',
              '-moz-transition': settings.side + ' ' + settings.speed + 'ms ease',
              '-ms-transition': settings.side + ' ' + settings.speed + 'ms ease',
              '-o-transition': settings.side + ' ' + settings.speed + 'ms ease',
              'transition': settings.side + ' ' + settings.speed + 'ms ease'
            };
  
            // css for the shrink animation
            var animateShrink = {
              '-webkit-transition': 'all ' + settings.speed + 'ms ease',
              '-moz-transition': 'all ' + settings.speed + 'ms ease',
              '-ms-transition': 'all ' + settings.speed + 'ms ease',
              '-o-transition': 'all ' + settings.speed + 'ms ease',
              'transition': 'all ' + settings.speed + 'ms ease'
            };
  
            // we want to add the css sliding animation when the page is loaded (on the first menu link click)
            var animationApplied = false;
  
            // manually add the settings values
            positionOffScreen[settings.side] = '-' + settings.menuWidth;
            positionOffScreen.width = settings.menuWidth;
  
            // get the initial state based on the last saved state or on the state option
            var initialState = 'closed';
            if (settings.saveState) {
              initialState = localStorage.getItem('bigSlide-savedState');
              if (!initialState) initialState = settings.state;
            } else {
              initialState = settings.state;
            }
  
            // set the initial state on the controller
            controller.setState(initialState);
  
            // add the css values to position things offscreen or inscreen depending on the initial state value
            this.$menu.css(positionOffScreen);
  
            var initialScreenWidth = $(window).width();
            if (initialState === 'closed') {
              if (settings.semiOpenStatus && initialScreenWidth > settings.semiOpenScreenWidth) {
                this.$hiddenThin.hide();
                this.$menu.css(settings.side, '0');
                this.$menu.css('width', this.semiOpenMenuWidth);
                this.$push.css(settings.side, this.semiOpenMenuWidth);
                this.$shrink.css({
                  'width': 'calc(100% - ' + this.semiOpenMenuWidth + ')'
                });
                this.$menu.addClass('semiOpen');
              } else {
                this.$push.css(settings.side, '0');
              }
            } else if (initialState === 'open') {
              this.$menu.css(settings.side, '0');
              this.$push.css(settings.side, this.width);
              this.$shrink.css({
                'width': 'calc(100% - ' + this.width + ')'
              });
              menuLink.addClass(settings.activeBtn);
            }
  
            var that = this;
  
            // register a click listener for desktop & touchstart for mobile
            menuLink.on('click.bigSlide touchstart.bigSlide', function(e) {
              // add the animation css if not present
              if (!animationApplied) {
                that.$menu.css(animateSlide);
                that.$push.css(animateSlide);
                that.$shrink.css(animateShrink);
                animationApplied = true;
              }
  
              e.preventDefault();
              if (controller.getState() === 'open') {
                view.toggleClose();
              } else {
                view.toggleOpen();
              }
            });
  
            // register a window resize listener for tracking the semi open status states
            // This could be more efficently or even there are people that could consider it unnecessary. We can think about it
            if (settings.semiOpenStatus) {
                $(window).resize(function() {
                    var screenWidth = $(window).width();
                    if (screenWidth > settings.semiOpenScreenWidth) {
                        if (controller.getState() === 'closed') {
                            that.$hiddenThin.hide();
                            that.$menu.css({ width: that.semiOpenMenuWidth});
                            that.$menu.css(settings.side, '0');
                            that.$push.css(settings.side, that.semiOpenMenuWidth);
                            that.$shrink.css({
                              'width': 'calc(100% - ' + that.semiOpenMenuWidth + ')'
                            });
                            that.$menu.addClass('semiOpen');
                        }
                    } else {
                        that.$menu.removeClass('semiOpen');
                        if (controller.getState() === 'closed') {
                            that.$menu.css(settings.side, '-' + that.width).css({width: that.width});
                            that.$push.css(settings.side, '0');
                            that.$shrink.css('width', '100%');
                            that.$hiddenThin.show();
                        }
                    }
                });
            }
  
            // this makes my eyes bleed, but adding it back in as it's a highly requested feature
            if (settings.easyClose) {
              $(document).on('click.bigSlide touchstart.bigSlide', function(e) {
               if (!$(e.target).parents().addBack().is(menuLink) && !$(e.target).closest(settings.menu).length && controller.getState() === 'open')  {
                 view.toggleClose();
               }
              });
            }
          },
  
          _destroy: function(){
            //remove inline styles generated by bigSlide.js while preserving any other inline styles
            this.$menu.each(function(){
              var $this = $(this);
              $this.attr( 'style', _cleanInlineCSS($this.attr('style'), model.menuCSSDictionary).trim() );
            });
  
            this.$push.each(function(){
              var $this = $(this);
              $this.attr( 'style', _cleanInlineCSS($this.attr('style'), model.pushCSSDictionary).trim() );
            });
  
            this.$shrink.each(function(){
              var $this = $(this);
              $this.attr( 'style', _cleanInlineCSS($this.attr('style'), model.pushCSSDictionary).trim() );
            });
  
            //remove active class and unbind bigSlide event handlers
            menuLink
              .removeClass(settings.activeBtn)
              .off('click.bigSlide touchstart.bigSlide');
  
            //release DOM references to avoid memory leaks
            this.$menu = null;
            this.$push = null;
            this.$shrink = null;
  
            //remove the local storage state
            localStorage.removeItem('bigSlide-savedState');
          },
  
          // toggle the menu open
          toggleOpen: function() {
            settings.beforeOpen();
            controller.changeState();
            view.applyOpenStyles();
            menuLink.addClass(settings.activeBtn);
            settings.afterOpen();
  
            // save the state
            if (settings.saveState) {
              localStorage.setItem('bigSlide-savedState', 'open');
            }
          },
  
          // toggle the menu closed
          toggleClose: function() {
            settings.beforeClose();
            controller.changeState();
            view.applyClosedStyles();
            menuLink.removeClass(settings.activeBtn);
            settings.afterClose();
  
            // save the state
            if (settings.saveState) {
              localStorage.setItem('bigSlide-savedState', 'closed');
            }
          },
  
          applyOpenStyles: function() {
            var screenWidth = $(window).width();
            if (settings.semiOpenStatus && screenWidth > settings.semiOpenScreenWidth) {
              this.$hiddenThin.show();
              this.$menu.animate({ width: this.width}, {duration: Math.abs(settings.speed - 100), easing: 'linear'});
              this.$push.css(settings.side, this.width);
              this.$shrink.css({
                'width': 'calc(100% - ' + this.width + ')'
              });
              this.$menu.removeClass('semiOpen');
            } else {
              this.$menu.css(settings.side, '0');
              this.$push.css(settings.side, this.width);
              this.$shrink.css({
                'width': 'calc(100% - ' + this.width + ')'
              });
            }
          },
  
          applyClosedStyles: function() {
            var screenWidth = $(window).width();
            if (settings.semiOpenStatus && screenWidth > settings.semiOpenScreenWidth) {
              this.$hiddenThin.hide();
              this.$menu.animate({ width: this.semiOpenMenuWidth}, {duration: Math.abs(settings.speed - 100), easing: 'linear'});
              this.$push.css(settings.side, this.semiOpenMenuWidth);
              this.$shrink.css({
                'width': 'calc(100% - ' + this.semiOpenMenuWidth + ')'
              });
              this.$menu.addClass('semiOpen');
            } else {
              this.$menu.css(settings.side, '-' + this.width);
              this.$push.css(settings.side, '0');
              this.$shrink.css('width', '100%');
            }
          }
  
        }
  
        controller.init();
  
        this.bigSlideAPI = {
          settings: settings,
          model: model,
          controller: controller,
          view: view,
          destroy: controller._destroy
        };
  
        return this;
      };
    }
  }