text: var angularLocalStorage = angular.module('LocalStorageModule', []);
  
  angularLocalStorage.provider('localStorageService', function() {
  
    // You should set a prefix to avoid overwriting any local storage variables from the rest of your app
    // e.g. localStorageServiceProvider.setPrefix('yourAppName');
    // With provider you can use config as this:
    // myApp.config(function (localStorageServiceProvider) {
    //    localStorageServiceProvider.prefix = 'yourAppName';
    // });
    this.prefix = 'ls';
  
    // You could change web storage type localstorage or sessionStorage
    this.storageType = 'localStorage';
  
    // Cookie options (usually in case of fallback)
    // expiry = Number of days before cookies expire // 0 = Does not expire
    // path = The web path the cookie represents
    this.cookie = {
      expiry: 30,
      path: '/'
    };
  
    // Send signals for each of the following actions?
    this.notify = {
      setItem: true,
      removeItem: false
    };
  
    // Setter for the prefix
    this.setPrefix = function(prefix) {
      this.prefix = prefix;
      return this;
    };
  
     // Setter for the storageType
     this.setStorageType = function(storageType) {
       this.storageType = storageType;
       return this;
     };
  
    // Setter for cookie config
    this.setStorageCookie = function(exp, path) {
      this.cookie.expiry = exp;
      this.cookie.path = path;
      return this;
    };
  
    // Setter for cookie domain
    this.setStorageCookieDomain = function(domain) {
      this.cookie.domain = domain;
      return this;
    };
  
    // Setter for notification config
    // itemSet & itemRemove should be booleans
    this.setNotify = function(itemSet, itemRemove) {
      this.notify = {
        setItem: itemSet,
        removeItem: itemRemove
      };
      return this;
    };
  
    this.$get = ['$rootScope', '$window', '$document', '$parse', function($rootScope, $window, $document, $parse) {
      var self = this;
      var prefix = self.prefix;
      var cookie = self.cookie;
      var notify = self.notify;
      var storageType = self.storageType;
      var webStorage;
  
      // When Angular's $document is not available
      if (!$document) {
        $document = document;
      } else if ($document[0]) {
        $document = $document[0];
      }
  
      // If there is a prefix set in the config lets use that with an appended period for readability
      if (prefix.substr(-1) !== '.') {
        prefix = !!prefix ? prefix + '.' : '';
      }
      var deriveQualifiedKey = function(key) {
        return prefix + key;
      };
      // Checks the browser to see if local storage is supported
      var browserSupportsLocalStorage = (function () {
        try {
          var supported = (storageType in $window && $window[storageType] !== null);
  
          // When Safari (OS X or iOS) is in private browsing mode, it appears as though localStorage
          // is available, but trying to call .setItem throws an exception.
          //
          // "QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage
          // that exceeded the quota."
          var key = deriveQualifiedKey('__' + Math.round(Math.random() * 1e7));
          if (supported) {
            webStorage = $window[storageType];
            webStorage.setItem(key, '');
            webStorage.removeItem(key);
          }
  
          return supported;
        } catch (e) {
          storageType = 'cookie';
          $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
          return false;
        }
      }());
  
  
  
      // Directly adds a value to local storage
      // If local storage is not available in the browser use cookies
      // Example use: localStorageService.add('library','angular');
      var addToLocalStorage = function (key, value) {
        // Let's convert undefined values to null to get the value consistent
        if (isUndefined(value)) {
          value = null;
        } else if (isObject(value) || isArray(value) || isNumber(+value || value)) {
          value = toJson(value);
        }
  
        // If this browser does not support local storage use cookies
        if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
          if (!browserSupportsLocalStorage) {
              $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
          }
  
          if (notify.setItem) {
            $rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: 'cookie'});
          }
          return addToCookies(key, value);
        }
  
        try {
          if (webStorage) {webStorage.setItem(deriveQualifiedKey(key), value)};
          if (notify.setItem) {
            $rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: self.storageType});
          }
        } catch (e) {
          $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
          return addToCookies(key, value);
        }
        return true;
      };
  
      // Directly get a value from local storage
      // Example use: localStorageService.get('library'); // returns 'angular'
      var getFromLocalStorage = function (key) {
  
        if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
          if (!browserSupportsLocalStorage) {
            $rootScope.$broadcast('LocalStorageModule.notification.warning','LOCAL_STORAGE_NOT_SUPPORTED');
          }
  
          return getFromCookies(key);
        }
  
        var item = webStorage ? webStorage.getItem(deriveQualifiedKey(key)) : null;
        // angular.toJson will convert null to 'null', so a proper conversion is needed
        // FIXME not a perfect solution, since a valid 'null' string can't be stored
        if (!item || item === 'null') {
          return null;
        }
  
        if (item.charAt(0) === "{" || item.charAt(0) === "[" || isStringNumber(item)) {
          return fromJson(item);
        }
  
        return item;
      };
  
      // Remove an item from local storage
      // Example use: localStorageService.remove('library'); // removes the key/value pair of library='angular'
      var removeFromLocalStorage = function (key) {
        if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
          if (!browserSupportsLocalStorage) {
            $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
          }
  
          if (notify.removeItem) {
            $rootScope.$broadcast('LocalStorageModule.notification.removeitem', {key: key, storageType: 'cookie'});
          }
          return removeFromCookies(key);
        }
  
        try {
          webStorage.removeItem(deriveQualifiedKey(key));
          if (notify.removeItem) {
            $rootScope.$broadcast('LocalStorageModule.notification.removeitem', {key: key, storageType: self.storageType});
          }
        } catch (e) {
          $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
          return removeFromCookies(key);
        }
        return true;
      };
  
      // Return array of keys for local storage
      // Example use: var keys = localStorageService.keys()
      var getKeysForLocalStorage = function () {
  
        if (!browserSupportsLocalStorage) {
          $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
          return false;
        }
  
        var prefixLength = prefix.length;
        var keys = [];
        for (var key in webStorage) {
          // Only return keys that are for this app
          if (key.substr(0,prefixLength) === prefix) {
            try {
              keys.push(key.substr(prefixLength));
            } catch (e) {
              $rootScope.$broadcast('LocalStorageModule.notification.error', e.Description);
              return [];
            }
          }
        }
        return keys;
      };
  
      // Remove all data for this app from local storage
      // Also optionally takes a regular expression string and removes the matching key-value pairs
      // Example use: localStorageService.clearAll();
      // Should be used mostly for development purposes
      var clearAllFromLocalStorage = function (regularExpression) {
  
        // Setting both regular expressions independently
        // Empty strings result in catchall RegExp
        var prefixRegex = !!prefix ? new RegExp('^' + prefix) : new RegExp();
        var testRegex = !!regularExpression ? new RegExp(regularExpression) : new RegExp();
  
        if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
          if (!browserSupportsLocalStorage) {
            $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
          }
          return clearAllFromCookies();
        }
  
        var prefixLength = prefix.length;
  
        for (var key in webStorage) {
          // Only remove items that are for this app and match the regular expression
          if (prefixRegex.test(key) && testRegex.test(key.substr(prefixLength))) {
            try {
              removeFromLocalStorage(key.substr(prefixLength));
            } catch (e) {
              $rootScope.$broadcast('LocalStorageModule.notification.error',e.message);
              return clearAllFromCookies();
            }
          }
        }
        return true;
      };
  
      // Checks the browser to see if cookies are supported
      var browserSupportsCookies = (function() {
        try {
          return $window.navigator.cookieEnabled ||
            ("cookie" in $document && ($document.cookie.length > 0 ||
            ($document.cookie = "test").indexOf.call($document.cookie, "test") > -1));
        } catch (e) {
            $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
            return false;
        }
      }());
  
      // Directly adds a value to cookies
      // Typically used as a fallback is local storage is not available in the browser
      // Example use: localStorageService.cookie.add('library','angular');
      var addToCookies = function (key, value, daysToExpiry) {
  
        if (isUndefined(value)) {
          return false;
        } else if(isArray(value) || isObject(value)) {
          value = toJson(value);
        }
  
        if (!browserSupportsCookies) {
          $rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED');
          return false;
        }
  
        try {
          var expiry = '',
              expiryDate = new Date(),
              cookieDomain = '';
  
          if (value === null) {
            // Mark that the cookie has expired one day ago
            expiryDate.setTime(expiryDate.getTime() + (-1 * 24 * 60 * 60 * 1000));
            expiry = "; expires=" + expiryDate.toGMTString();
            value = '';
          } else if (isNumber(daysToExpiry) && daysToExpiry !== 0) {
            expiryDate.setTime(expiryDate.getTime() + (daysToExpiry * 24 * 60 * 60 * 1000));
            expiry = "; expires=" + expiryDate.toGMTString();
          } else if (cookie.expiry !== 0) {
            expiryDate.setTime(expiryDate.getTime() + (cookie.expiry * 24 * 60 * 60 * 1000));
            expiry = "; expires=" + expiryDate.toGMTString();
          }
          if (!!key) {
            var cookiePath = "; path=" + cookie.path;
            if(cookie.domain){
              cookieDomain = "; domain=" + cookie.domain;
            }
            $document.cookie = deriveQualifiedKey(key) + "=" + encodeURIComponent(value) + expiry + cookiePath + cookieDomain;
          }
        } catch (e) {
          $rootScope.$broadcast('LocalStorageModule.notification.error',e.message);
          return false;
        }
        return true;
      };
  
      // Directly get a value from a cookie
      // Example use: localStorageService.cookie.get('library'); // returns 'angular'
      var getFromCookies = function (key) {
        if (!browserSupportsCookies) {
          $rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED');
          return false;
        }
  
        var cookies = $document.cookie && $document.cookie.split(';') || [];
        for(var i=0; i < cookies.length; i++) {
          var thisCookie = cookies[i];
          while (thisCookie.charAt(0) === ' ') {
            thisCookie = thisCookie.substring(1,thisCookie.length);
          }
          if (thisCookie.indexOf(deriveQualifiedKey(key) + '=') === 0) {
            var storedValues = decodeURIComponent(thisCookie.substring(prefix.length + key.length + 1, thisCookie.length))
            try{
              var obj = JSON.parse(storedValues);
              return fromJson(obj)
            }catch(e){
              return storedValues
            }
          }
        }
        return null;
      };
  
      var removeFromCookies = function (key) {
        addToCookies(key,null);
      };
  
      var clearAllFromCookies = function () {
        var thisCookie = null, thisKey = null;
        var prefixLength = prefix.length;
        var cookies = $document.cookie.split(';');
        for(var i = 0; i < cookies.length; i++) {
          thisCookie = cookies[i];
  
          while (thisCookie.charAt(0) === ' ') {
            thisCookie = thisCookie.substring(1, thisCookie.length);
          }
  
          var key = thisCookie.substring(prefixLength, thisCookie.indexOf('='));
          removeFromCookies(key);
        }
      };
  
      var getStorageType = function() {
        return storageType;
      };
  
      // Add a listener on scope variable to save its changes to local storage
      // Return a function which when called cancels binding
      var bindToScope = function(scope, key, def, lsKey) {
        lsKey = lsKey || key;
        var value = getFromLocalStorage(lsKey);
  
        if (value === null && isDefined(def)) {
          value = def;
        } else if (isObject(value) && isObject(def)) {
          value = extend(def, value);
        }
  
        $parse(key).assign(scope, value);
  
        return scope.$watch(key, function(newVal) {
          addToLocalStorage(lsKey, newVal);
        }, isObject(scope[key]));
      };
  
      // Return localStorageService.length
      // ignore keys that not owned
      var lengthOfLocalStorage = function() {
        var count = 0;
        var storage = $window[storageType];
        for(var i = 0; i < storage.length; i++) {
          if(storage.key(i).indexOf(prefix) === 0 ) {
            count++;
          }
        }
        return count;
      };
  
      return {
        isSupported: browserSupportsLocalStorage,
        getStorageType: getStorageType,
        set: addToLocalStorage,
        add: addToLocalStorage, //DEPRECATED
        get: getFromLocalStorage,
        keys: getKeysForLocalStorage,
        remove: removeFromLocalStorage,
        clearAll: clearAllFromLocalStorage,
        bind: bindToScope,
        deriveKey: deriveQualifiedKey,
        length: lengthOfLocalStorage,
        cookie: {
          isSupported: browserSupportsCookies,
          set: addToCookies,
          add: addToCookies, //DEPRECATED
          get: getFromCookies,
          remove: removeFromCookies,
          clearAll: clearAllFromCookies
        }
      };
    }];
  });