text: (function (root, factory) {
    'use strict';
  
    if (typeof define === 'function' && define.amd) {
      define(['angular'], factory);
    } else if (typeof exports === 'object') {
      // factory(require('angular'));
      module.exports = factory;
    } else {
      // Browser globals (root is window), we don't register it.
      factory(root.angular);
    }
  }(this , function (angular) {
      'use strict';
  
      // In cases where Angular does not get passed or angular is a truthy value
      // but misses .module we can fall back to using window.
      angular = (angular && angular.module ) ? angular : window.angular;
  
  
      function isStorageSupported($window, storageType) {
  
        // Some installations of IE, for an unknown reason, throw "SCRIPT5: Error: Access is denied"
        // when accessing window.localStorage. This happens before you try to do anything with it. Catch
        // that error and allow execution to continue.
  
        // fix 'SecurityError: DOM Exception 18' exception in Desktop Safari, Mobile Safari
        // when "Block cookies": "Always block" is turned on
        var supported;
        try {
          supported = $window[storageType];
        }
        catch(err) {
          supported = false;
        }
  
        // When Safari (OS X or iOS) is in private browsing mode, it appears as though localStorage and sessionStorage
        // is available, but trying to call .setItem throws an exception below:
        // "QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage that exceeded the quota."
        if(supported) {
          var key = '__' + Math.round(Math.random() * 1e7);
          try {
            $window[storageType].setItem(key, key);
            $window[storageType].removeItem(key, key);
          }
          catch(err) {
            supported = false;
          }
        }
  
        return supported;
      }
  
      /**
       * @ngdoc overview
       * @name ngStorage
       */
  
      return angular.module('ngStorage', [])
  
      /**
       * @ngdoc object
       * @name ngStorage.$localStorage
       * @requires $rootScope
       * @requires $window
       */
  
      .provider('$localStorage', _storageProvider('localStorage'))
  
      /**
       * @ngdoc object
       * @name ngStorage.$sessionStorage
       * @requires $rootScope
       * @requires $window
       */
  
      .provider('$sessionStorage', _storageProvider('sessionStorage'));
  
      function _storageProvider(storageType) {
          var providerWebStorage = isStorageSupported(window, storageType);
  
          return function () {
            var storageKeyPrefix = 'ngStorage-';
  
            this.setKeyPrefix = function (prefix) {
              if (typeof prefix !== 'string') {
                throw new TypeError('[ngStorage] - ' + storageType + 'Provider.setKeyPrefix() expects a String.');
              }
              storageKeyPrefix = prefix;
            };
  
            var serializer = angular.toJson;
            var deserializer = angular.fromJson;
  
            this.setSerializer = function (s) {
              if (typeof s !== 'function') {
                throw new TypeError('[ngStorage] - ' + storageType + 'Provider.setSerializer expects a function.');
              }
  
              serializer = s;
            };
  
            this.setDeserializer = function (d) {
              if (typeof d !== 'function') {
                throw new TypeError('[ngStorage] - ' + storageType + 'Provider.setDeserializer expects a function.');
              }
  
              deserializer = d;
            };
  
            this.supported = function() {
              return !!providerWebStorage;
            };
  
            // Note: This is not very elegant at all.
            this.get = function (key) {
              return providerWebStorage && deserializer(providerWebStorage.getItem(storageKeyPrefix + key));
            };
  
            // Note: This is not very elegant at all.
            this.set = function (key, value) {
              return providerWebStorage && providerWebStorage.setItem(storageKeyPrefix + key, serializer(value));
            };
  
            this.remove = function (key) {
              providerWebStorage && providerWebStorage.removeItem(storageKeyPrefix + key);
            }
  
            this.$get = [
                '$rootScope',
                '$window',
                '$log',
                '$interval',
                '$document',
  
                function(
                    $rootScope,
                    $window,
                    $log,
                    $interval,
                    $document
                ){
  
                  // The magic number 10 is used which only works for some keyPrefixes...
                  // See https://github.com/gsklee/ngStorage/issues/137
                  var prefixLength = storageKeyPrefix.length;
  
                  // #9: Assign a placeholder object if Web Storage is unavailable to prevent breaking the entire AngularJS app
                  // Note: recheck mainly for testing (so we can use $window[storageType] rather than window[storageType])
                  var isSupported = isStorageSupported($window, storageType),
                      webStorage = isSupported || ($log.warn('This browser does not support Web Storage!'), {setItem: angular.noop, getItem: angular.noop, removeItem: angular.noop}),
                      $storage = {
                          $default: function(items) {
                              for (var k in items) {
                                  angular.isDefined($storage[k]) || ($storage[k] = angular.copy(items[k]) );
                              }
  
                              $storage.$sync();
                              return $storage;
                          },
                          $reset: function(items) {
                              for (var k in $storage) {
                                  '$' === k[0] || (delete $storage[k] && webStorage.removeItem(storageKeyPrefix + k));
                              }
  
                              return $storage.$default(items);
                          },
                          $sync: function () {
                              for (var i = 0, l = webStorage.length, k; i < l; i++) {
                                  // #8, #10: `webStorage.key(i)` may be an empty string (or throw an exception in IE9 if `webStorage` is empty)
                                  (k = webStorage.key(i)) && storageKeyPrefix === k.slice(0, prefixLength) && ($storage[k.slice(prefixLength)] = deserializer(webStorage.getItem(k)));
                              }
                          },
                          $apply: function() {
                              var temp$storage;
  
                              $interval.cancel(_debounce);
                              _debounce = null;
  
                              if (!angular.equals($storage, _last$storage)) {
                                  temp$storage = angular.copy(_last$storage);
                                  angular.forEach($storage, function(v, k) {
                                      if (angular.isDefined(v) && '$' !== k[0]) {
                                          webStorage.setItem(storageKeyPrefix + k, serializer(v));
                                          delete temp$storage[k];
                                      }
                                  });
  
                                  for (var k in temp$storage) {
                                      webStorage.removeItem(storageKeyPrefix + k);
                                  }
  
                                  _last$storage = angular.copy($storage);
                              }
                          },
                          $supported: function() {
                              return !!isSupported;
                          }
                      },
                      _last$storage,
                      _debounce;
  
                  $storage.$sync();
  
                  _last$storage = angular.copy($storage);
  
                  $rootScope.$watch(function() {
                      _debounce || (_debounce = $interval($storage.$apply, 100, 1, false));
                  });
  
                  // #6: Use `$window.addEventListener` instead of `angular.element` to avoid the jQuery-specific `event.originalEvent`
                  $window.addEventListener && $window.addEventListener('storage', function(event) {
                      if (!event.key) {
                        return;
                      }
  
                      // Reference doc.
                      var doc = $document[0];
  
                      if ( (!doc.hasFocus || !doc.hasFocus()) && storageKeyPrefix === event.key.slice(0, prefixLength) ) {
                          event.newValue ? $storage[event.key.slice(prefixLength)] = deserializer(event.newValue) : delete $storage[event.key.slice(prefixLength)];
  
                          _last$storage = angular.copy($storage);
  
                          $rootScope.$apply();
                      }
                  });
  
                  $window.addEventListener && $window.addEventListener('beforeunload', function() {
                      $storage.$apply();
                  });
  
                  return $storage;
                }
            ];
        };
      }
  
  }));
  