songbooks 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +14 -0
 - data/.rspec +2 -0
 - data/.travis.yml +5 -0
 - data/Gemfile +4 -0
 - data/Guardfile +29 -0
 - data/LICENSE +22 -0
 - data/LICENSE.txt +21 -0
 - data/README.md +41 -0
 - data/Rakefile +6 -0
 - data/app/assets/javascripts/application.coffee +4 -0
 - data/app/assets/javascripts/components/filters/convertWhitespace.filter.coffee +3 -0
 - data/app/assets/javascripts/components/song_component/chord.directive.coffee +9 -0
 - data/app/assets/javascripts/components/song_component/literal.directive.coffee +6 -0
 - data/app/assets/javascripts/components/song_component/song_component.directive.coffee +6 -0
 - data/app/assets/javascripts/components/songbook/songbook.controller.coffee +29 -0
 - data/app/assets/javascripts/components/songs/song.controller.coffee +10 -0
 - data/app/assets/javascripts/components/songs/song.directive.coffee +7 -0
 - data/app/assets/javascripts/components/songs/song.service.coffee +98 -0
 - data/app/assets/javascripts/components/songs/songs.controller.coffee +21 -0
 - data/app/assets/javascripts/routes.coffee +11 -0
 - data/app/assets/stylesheets/application.scss +34 -0
 - data/app/fonts/DejaVuSans-Bold.ttf +0 -0
 - data/app/fonts/DejaVuSans-BoldOblique.ttf +0 -0
 - data/app/fonts/DejaVuSans-ExtraLight.ttf +0 -0
 - data/app/fonts/DejaVuSans-Oblique.ttf +0 -0
 - data/app/fonts/DejaVuSans.ttf +0 -0
 - data/app/fonts/DejaVuSansCondensed-Bold.ttf +0 -0
 - data/app/fonts/DejaVuSansCondensed-BoldOblique.ttf +0 -0
 - data/app/fonts/DejaVuSansCondensed-Oblique.ttf +0 -0
 - data/app/fonts/DejaVuSansCondensed.ttf +0 -0
 - data/app/fonts/DejaVuSansMono-Bold.ttf +0 -0
 - data/app/fonts/DejaVuSansMono-BoldOblique.ttf +0 -0
 - data/app/fonts/DejaVuSansMono-Oblique.ttf +0 -0
 - data/app/fonts/DejaVuSansMono.ttf +0 -0
 - data/app/fonts/DejaVuSerif-Bold.ttf +0 -0
 - data/app/fonts/DejaVuSerif-BoldItalic.ttf +0 -0
 - data/app/fonts/DejaVuSerif-Italic.ttf +0 -0
 - data/app/fonts/DejaVuSerif.ttf +0 -0
 - data/app/fonts/DejaVuSerifCondensed-Bold.ttf +0 -0
 - data/app/fonts/DejaVuSerifCondensed-BoldItalic.ttf +0 -0
 - data/app/fonts/DejaVuSerifCondensed-Italic.ttf +0 -0
 - data/app/fonts/DejaVuSerifCondensed.ttf +0 -0
 - data/app/tex/songbook.tex +12 -0
 - data/app/views/application.haml +54 -0
 - data/app/views/layouts/application.haml +40 -0
 - data/app/views/songbook.prawn +80 -0
 - data/app/views/songs/component.haml +2 -0
 - data/app/views/songs/index.jbuilder +5 -0
 - data/app/views/songs/show.haml +23 -0
 - data/app/views/songs/show.jbuilder +24 -0
 - data/app/views/songs/song.haml +4 -0
 - data/exe/sb_server +6 -0
 - data/lib/prawn_ext/font/afm.rb +20 -0
 - data/lib/songbooks.rb +32 -0
 - data/lib/songbooks/CLI.rb +13 -0
 - data/lib/songbooks/components/chord.rb +98 -0
 - data/lib/songbooks/components/literal.rb +57 -0
 - data/lib/songbooks/components/metadata.rb +69 -0
 - data/lib/songbooks/components/section.rb +73 -0
 - data/lib/songbooks/controllers/controller.rb +18 -0
 - data/lib/songbooks/controllers/songs_controller.rb +30 -0
 - data/lib/songbooks/folder.rb +32 -0
 - data/lib/songbooks/server.rb +65 -0
 - data/lib/songbooks/song.rb +53 -0
 - data/lib/songbooks/version.rb +3 -0
 - data/lib/songbooks/view_helper.rb +9 -0
 - data/public/javascripts/angular-local-storage.js +449 -0
 - data/public/javascripts/angular-route.js +991 -0
 - data/public/javascripts/angular.js +28904 -0
 - data/public/javascripts/application.js +8 -0
 - data/public/javascripts/components/filters/convertWhitespace.filter.js +8 -0
 - data/public/javascripts/components/song_component/chord.directive.js +13 -0
 - data/public/javascripts/components/song_component/literal.directive.js +9 -0
 - data/public/javascripts/components/song_component/song_component.directive.js +9 -0
 - data/public/javascripts/components/songbook/songbook.controller.js +33 -0
 - data/public/javascripts/components/songs/song.controller.js +12 -0
 - data/public/javascripts/components/songs/song.directive.js +9 -0
 - data/public/javascripts/components/songs/song.service.js +107 -0
 - data/public/javascripts/components/songs/songs.controller.js +22 -0
 - data/public/javascripts/jquery-2.1.4.min.js +4 -0
 - data/public/javascripts/routes.js +16 -0
 - data/public/stylesheets/application.css +24 -0
 - data/public/stylesheets/bootstrap-theme.min.css +5 -0
 - data/public/stylesheets/bootstrap.min.css +5 -0
 - data/songbooks.gemspec +51 -0
 - metadata +369 -0
 
| 
         @@ -0,0 +1,57 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'chord'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Songbooks
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Components
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Literal
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  #----------------------------------------------------------------
         
     | 
| 
      
 8 
     | 
    
         
            +
                  #                           Parsing
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #----------------------------------------------------------------
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  #
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # Tries to munch a literal from the given string.
         
     | 
| 
      
 13 
     | 
    
         
            +
                  # If the string starts with a valid literal, it is automatically
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # removed from the string
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # @return [Songbooks::Components::Literal, NilClass] a Literal containing the munched
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #   text or +nil+ if the string didn't start with a literal
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #
         
     | 
| 
      
 19 
     | 
    
         
            +
                  def self.munch_literal(text)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    result = ''
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    until text.length.zero?
         
     | 
| 
      
 23 
     | 
    
         
            +
                      # Munch leading whitespace
         
     | 
| 
      
 24 
     | 
    
         
            +
                      if text =~ /^(\s+)/
         
     | 
| 
      
 25 
     | 
    
         
            +
                        result << text.slice!(0...$1.length)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                      # If we reached a chord, we may not munch any further
         
     | 
| 
      
 29 
     | 
    
         
            +
                      break if Chord.starts_with_chord?(text)
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                      # Munch non-chord, non whitespace characters
         
     | 
| 
      
 32 
     | 
    
         
            +
                      if text =~/^([^\s+])/
         
     | 
| 
      
 33 
     | 
    
         
            +
                        result << text.slice!(0...$1.length)
         
     | 
| 
      
 34 
     | 
    
         
            +
                      end
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    result == '' ? nil : Literal.new(result)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  def initialize(string)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    @string = string
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 45 
     | 
    
         
            +
                    @string
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  def to_str
         
     | 
| 
      
 49 
     | 
    
         
            +
                    @string
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def html_string
         
     | 
| 
      
 53 
     | 
    
         
            +
                    @string
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Songbooks
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Components
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Metadata
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  #----------------------------------------------------------------
         
     | 
| 
      
 6 
     | 
    
         
            +
                  #                        CONSTANTS
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #----------------------------------------------------------------
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  EMPTY_LINE_REGEXP = /\A\s*\r?\n/
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  REGEXPS = {
         
     | 
| 
      
 12 
     | 
    
         
            +
                      :title  => /\A@title\s*\r?\n?([^\n\r]+)/,
         
     | 
| 
      
 13 
     | 
    
         
            +
                      :artist => /\A@artist\s*\r?\n?([^\n\r]+)/,
         
     | 
| 
      
 14 
     | 
    
         
            +
                  }
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  #----------------------------------------------------------------
         
     | 
| 
      
 17 
     | 
    
         
            +
                  #                           Parsing
         
     | 
| 
      
 18 
     | 
    
         
            +
                  #----------------------------------------------------------------
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  #
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # Tries to parse metadata from the header of a given string.
         
     | 
| 
      
 22 
     | 
    
         
            +
                  # It automatically deletes empty / whitespace lines and the parsed
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # content from the given string.
         
     | 
| 
      
 24 
     | 
    
         
            +
                  #
         
     | 
| 
      
 25 
     | 
    
         
            +
                  # Currently supported metadata/annotations
         
     | 
| 
      
 26 
     | 
    
         
            +
                  #   @artist
         
     | 
| 
      
 27 
     | 
    
         
            +
                  #   @title
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # @param [String] text
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #   The string which possibly contains header data, usually a whole song file content
         
     | 
| 
      
 31 
     | 
    
         
            +
                  #
         
     | 
| 
      
 32 
     | 
    
         
            +
                  # @return [Songbooks::Components::Metadata]
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #   The parsed metadata with only the options set that could be parsed.
         
     | 
| 
      
 34 
     | 
    
         
            +
                  #
         
     | 
| 
      
 35 
     | 
    
         
            +
                  def self.munch_header(text)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    found   = true
         
     | 
| 
      
 37 
     | 
    
         
            +
                    options = {}
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    while found
         
     | 
| 
      
 40 
     | 
    
         
            +
                      found = false
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                      if (match = text.match(EMPTY_LINE_REGEXP))
         
     | 
| 
      
 43 
     | 
    
         
            +
                        text.slice!(0...match[0].length)
         
     | 
| 
      
 44 
     | 
    
         
            +
                        found = true
         
     | 
| 
      
 45 
     | 
    
         
            +
                      else
         
     | 
| 
      
 46 
     | 
    
         
            +
                        REGEXPS.each do |name, regexp|
         
     | 
| 
      
 47 
     | 
    
         
            +
                          if (match = text.match(regexp))
         
     | 
| 
      
 48 
     | 
    
         
            +
                            options[name] = match[1]
         
     | 
| 
      
 49 
     | 
    
         
            +
                            text.slice!(0...match[0].length)
         
     | 
| 
      
 50 
     | 
    
         
            +
                            found = true
         
     | 
| 
      
 51 
     | 
    
         
            +
                          end
         
     | 
| 
      
 52 
     | 
    
         
            +
                        end
         
     | 
| 
      
 53 
     | 
    
         
            +
                      end
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    Metadata.new(options)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  def initialize(options = {})
         
     | 
| 
      
 60 
     | 
    
         
            +
                    options.each do |k, v|
         
     | 
| 
      
 61 
     | 
    
         
            +
                      instance_variable_set("@#{k}", v)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  attr_reader :artist, :title
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,73 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'songbooks/components/chord'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'songbooks/components/literal'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Songbooks
         
     | 
| 
      
 5 
     | 
    
         
            +
              module Components
         
     | 
| 
      
 6 
     | 
    
         
            +
                class Section
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  #----------------------------------------------------------------
         
     | 
| 
      
 9 
     | 
    
         
            +
                  #                           CONSTANTS
         
     | 
| 
      
 10 
     | 
    
         
            +
                  #----------------------------------------------------------------
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  REGEXP = /^##\s*(.*)$/
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  #----------------------------------------------------------------
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #                            Parsing
         
     | 
| 
      
 16 
     | 
    
         
            +
                  #----------------------------------------------------------------
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  #
         
     | 
| 
      
 19 
     | 
    
         
            +
                  # Tries to parse the given text line as a section name identifier
         
     | 
| 
      
 20 
     | 
    
         
            +
                  #
         
     | 
| 
      
 21 
     | 
    
         
            +
                  # @return [Hash, NilClass] the parsed information or +nil+ if the given row
         
     | 
| 
      
 22 
     | 
    
         
            +
                  #   is not a valid section row
         
     | 
| 
      
 23 
     | 
    
         
            +
                  #
         
     | 
| 
      
 24 
     | 
    
         
            +
                  def self.parse_information(content)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    if content =~ REGEXP
         
     | 
| 
      
 26 
     | 
    
         
            +
                      return {name: $1}
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def initialize(name, initial = false)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @name          = name
         
     | 
| 
      
 33 
     | 
    
         
            +
                    @content_lines = []
         
     | 
| 
      
 34 
     | 
    
         
            +
                    @initial       = initial
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  #
         
     | 
| 
      
 38 
     | 
    
         
            +
                  # Parses the given line (chords and literals) and adds it to this section
         
     | 
| 
      
 39 
     | 
    
         
            +
                  #
         
     | 
| 
      
 40 
     | 
    
         
            +
                  def parse_line!(_line)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    line = _line.dup.rstrip
         
     | 
| 
      
 42 
     | 
    
         
            +
                    line_components = []
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    until line.length.zero?
         
     | 
| 
      
 45 
     | 
    
         
            +
                      component = Songbooks::Components::Chord.munch_chord(line)
         
     | 
| 
      
 46 
     | 
    
         
            +
                      component ||= Songbooks::Components::Literal.munch_literal(line)
         
     | 
| 
      
 47 
     | 
    
         
            +
                      line_components << component
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    add_line(line_components)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  def add_line(line)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @content_lines << line
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  def name
         
     | 
| 
      
 58 
     | 
    
         
            +
                    @name == 'Initial' ? '' : @name
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  def lines
         
     | 
| 
      
 62 
     | 
    
         
            +
                    @content_lines
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  def transpose!(amount)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    lines.flatten.each do |component|
         
     | 
| 
      
 67 
     | 
    
         
            +
                      next unless component.is_a?(Songbooks::Components::Chord)
         
     | 
| 
      
 68 
     | 
    
         
            +
                      component.transpose!(amount)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Songbooks
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Controllers
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Controller
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  def template
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @template.to_sym
         
     | 
| 
      
 7 
     | 
    
         
            +
                  end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def layout
         
     | 
| 
      
 10 
     | 
    
         
            +
                    (@layout || 'layouts/application').to_sym
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def resulting_instance_variables
         
     | 
| 
      
 14 
     | 
    
         
            +
                    instance_variables - [:@layout, :@params, :@template]
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'songbooks/controllers/controller'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Songbooks
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Controllers
         
     | 
| 
      
 5 
     | 
    
         
            +
                class SongsController < Controller
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(params = {}, session = {})
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @params = params
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @session = session
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  attr_reader :session, :params
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def index
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @songs    = Songbooks.folder.songs
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @template = 'songs/index'
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def show
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @song = Songbooks.folder.song(params['identifier'])
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @template = 'songs/show'
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def generate
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @songs = @session['songbook'].map { |id| Songbooks.folder.song(id) }
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'songbooks/song'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Songbooks
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Folder
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(path)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @path = Pathname.new(path)
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader :path
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def song(identifier)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  songs_by_identifier[identifier]
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def songs
         
     | 
| 
      
 16 
     | 
    
         
            +
                  songs_by_identifier.values
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                private
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def songs_by_identifier
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @songs ||= chords_files.each_with_object({}) do |file_path, h|
         
     | 
| 
      
 23 
     | 
    
         
            +
                    song = Songbooks::Song.new(File.read(file_path))
         
     | 
| 
      
 24 
     | 
    
         
            +
                    h[song.identifier] = song
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                def chords_files
         
     | 
| 
      
 29 
     | 
    
         
            +
                  Dir[@path.join('**', '*.txt')]
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,65 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'sinatra/base'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'songbooks/controllers/songs_controller'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'songbooks/view_helper'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Songbooks
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Server < Sinatra::Base
         
     | 
| 
      
 7 
     | 
    
         
            +
                include Sinatra::Prawn::Helpers
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                configure do
         
     | 
| 
      
 10 
     | 
    
         
            +
                  enable :sessions
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  set :views, Songbooks.root.join('app', 'views').to_s
         
     | 
| 
      
 13 
     | 
    
         
            +
                  set :public_folder, Songbooks.root.join('public').to_s
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  set :prawn, { :page_layout => :portrait, :page_size => 'A4' }
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                get '/' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                  haml :application
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                get '/songs.json' do
         
     | 
| 
      
 23 
     | 
    
         
            +
                  controller = Songbooks::Controllers::SongsController.new(params)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  controller.index
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  controller.resulting_instance_variables.each do |var_name|
         
     | 
| 
      
 27 
     | 
    
         
            +
                    instance_variable_set(var_name, controller.instance_variable_get(var_name))
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  jbuilder controller.template
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                get '/songs/:identifier.json' do
         
     | 
| 
      
 34 
     | 
    
         
            +
                  controller = Songbooks::Controllers::SongsController.new(params)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  controller.show
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  controller.resulting_instance_variables.each do |var_name|
         
     | 
| 
      
 38 
     | 
    
         
            +
                    instance_variable_set(var_name, controller.instance_variable_get(var_name))
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  jbuilder controller.template
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                post '/songbook' do
         
     | 
| 
      
 45 
     | 
    
         
            +
                  @params = JSON.parse(request.body.read)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  session[:songbook] = params['songs']
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                get '/songbook.pdf' do
         
     | 
| 
      
 50 
     | 
    
         
            +
                  controller = Songbooks::Controllers::SongsController.new(params, session)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  controller.generate
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  controller.resulting_instance_variables.each do |var_name|
         
     | 
| 
      
 54 
     | 
    
         
            +
                    instance_variable_set(var_name, controller.instance_variable_get(var_name))
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  content_type 'application/pdf'
         
     | 
| 
      
 58 
     | 
    
         
            +
                  prawn :songbook
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                get '/static/*' do
         
     | 
| 
      
 62 
     | 
    
         
            +
                  haml params['splat'].first.to_sym
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
              end
         
     | 
| 
      
 65 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'songbooks/components/section'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'songbooks/components/metadata'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Songbooks
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Song
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_reader :artist, :title, :identifier
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize(content)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  parse_content(content)
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def identifier
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @identifier ||= [artist, title].join('-').gsub(/[^a-zA-Z\-_0-9]/, '_')
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def sections
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @sections ||= []
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def longest_section_caption
         
     | 
| 
      
 21 
     | 
    
         
            +
                  sections.map(&:name).sort_by(&:length).last
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                private
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def parse_content(content)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  current_section = Songbooks::Components::Section.new('Initial', true)
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  meta            = Songbooks::Components::Metadata.munch_header(content)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @artist, @title = meta.artist, meta.title
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  content.lines.each do |line|
         
     | 
| 
      
 33 
     | 
    
         
            +
                    if (information = Songbooks::Components::Section.parse_information(line))
         
     | 
| 
      
 34 
     | 
    
         
            +
                      self.sections << current_section
         
     | 
| 
      
 35 
     | 
    
         
            +
                      current_section = Songbooks::Components::Section.new(information[:name])
         
     | 
| 
      
 36 
     | 
    
         
            +
                    else
         
     | 
| 
      
 37 
     | 
    
         
            +
                      current_section.parse_line!(line)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  self.sections << current_section
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def transpose!(count)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  return if count == 0
         
     | 
| 
      
 46 
     | 
    
         
            +
                  sections.each { |section| section.transpose!(count) }
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def transpose(count)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  dup.transpose!(count)
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,449 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /**
         
     | 
| 
      
 2 
     | 
    
         
            +
             * An Angular module that gives you access to the browsers local storage
         
     | 
| 
      
 3 
     | 
    
         
            +
             * @version v0.2.3 - 2015-10-11
         
     | 
| 
      
 4 
     | 
    
         
            +
             * @link https://github.com/grevory/angular-local-storage
         
     | 
| 
      
 5 
     | 
    
         
            +
             * @author grevory <greg@gregpike.ca>
         
     | 
| 
      
 6 
     | 
    
         
            +
             * @license MIT License, http://www.opensource.org/licenses/MIT
         
     | 
| 
      
 7 
     | 
    
         
            +
             */
         
     | 
| 
      
 8 
     | 
    
         
            +
            (function ( window, angular, undefined ) {
         
     | 
| 
      
 9 
     | 
    
         
            +
            /*jshint globalstrict:true*/
         
     | 
| 
      
 10 
     | 
    
         
            +
            'use strict';
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            var isDefined = angular.isDefined,
         
     | 
| 
      
 13 
     | 
    
         
            +
              isUndefined = angular.isUndefined,
         
     | 
| 
      
 14 
     | 
    
         
            +
              isNumber = angular.isNumber,
         
     | 
| 
      
 15 
     | 
    
         
            +
              isObject = angular.isObject,
         
     | 
| 
      
 16 
     | 
    
         
            +
              isArray = angular.isArray,
         
     | 
| 
      
 17 
     | 
    
         
            +
              extend = angular.extend,
         
     | 
| 
      
 18 
     | 
    
         
            +
              toJson = angular.toJson;
         
     | 
| 
      
 19 
     | 
    
         
            +
            var angularLocalStorage = angular.module('LocalStorageModule', []);
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            angularLocalStorage.provider('localStorageService', function() {
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              // You should set a prefix to avoid overwriting any local storage variables from the rest of your app
         
     | 
| 
      
 24 
     | 
    
         
            +
              // e.g. localStorageServiceProvider.setPrefix('yourAppName');
         
     | 
| 
      
 25 
     | 
    
         
            +
              // With provider you can use config as this:
         
     | 
| 
      
 26 
     | 
    
         
            +
              // myApp.config(function (localStorageServiceProvider) {
         
     | 
| 
      
 27 
     | 
    
         
            +
              //    localStorageServiceProvider.prefix = 'yourAppName';
         
     | 
| 
      
 28 
     | 
    
         
            +
              // });
         
     | 
| 
      
 29 
     | 
    
         
            +
              this.prefix = 'ls';
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              // You could change web storage type localstorage or sessionStorage
         
     | 
| 
      
 32 
     | 
    
         
            +
              this.storageType = 'localStorage';
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              // Cookie options (usually in case of fallback)
         
     | 
| 
      
 35 
     | 
    
         
            +
              // expiry = Number of days before cookies expire // 0 = Does not expire
         
     | 
| 
      
 36 
     | 
    
         
            +
              // path = The web path the cookie represents
         
     | 
| 
      
 37 
     | 
    
         
            +
              this.cookie = {
         
     | 
| 
      
 38 
     | 
    
         
            +
                expiry: 30,
         
     | 
| 
      
 39 
     | 
    
         
            +
                path: '/'
         
     | 
| 
      
 40 
     | 
    
         
            +
              };
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              // Send signals for each of the following actions?
         
     | 
| 
      
 43 
     | 
    
         
            +
              this.notify = {
         
     | 
| 
      
 44 
     | 
    
         
            +
                setItem: true,
         
     | 
| 
      
 45 
     | 
    
         
            +
                removeItem: false
         
     | 
| 
      
 46 
     | 
    
         
            +
              };
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              // Setter for the prefix
         
     | 
| 
      
 49 
     | 
    
         
            +
              this.setPrefix = function(prefix) {
         
     | 
| 
      
 50 
     | 
    
         
            +
                this.prefix = prefix;
         
     | 
| 
      
 51 
     | 
    
         
            +
                return this;
         
     | 
| 
      
 52 
     | 
    
         
            +
              };
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
               // Setter for the storageType
         
     | 
| 
      
 55 
     | 
    
         
            +
               this.setStorageType = function(storageType) {
         
     | 
| 
      
 56 
     | 
    
         
            +
                 this.storageType = storageType;
         
     | 
| 
      
 57 
     | 
    
         
            +
                 return this;
         
     | 
| 
      
 58 
     | 
    
         
            +
               };
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              // Setter for cookie config
         
     | 
| 
      
 61 
     | 
    
         
            +
              this.setStorageCookie = function(exp, path) {
         
     | 
| 
      
 62 
     | 
    
         
            +
                this.cookie.expiry = exp;
         
     | 
| 
      
 63 
     | 
    
         
            +
                this.cookie.path = path;
         
     | 
| 
      
 64 
     | 
    
         
            +
                return this;
         
     | 
| 
      
 65 
     | 
    
         
            +
              };
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              // Setter for cookie domain
         
     | 
| 
      
 68 
     | 
    
         
            +
              this.setStorageCookieDomain = function(domain) {
         
     | 
| 
      
 69 
     | 
    
         
            +
                this.cookie.domain = domain;
         
     | 
| 
      
 70 
     | 
    
         
            +
                return this;
         
     | 
| 
      
 71 
     | 
    
         
            +
              };
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
              // Setter for notification config
         
     | 
| 
      
 74 
     | 
    
         
            +
              // itemSet & itemRemove should be booleans
         
     | 
| 
      
 75 
     | 
    
         
            +
              this.setNotify = function(itemSet, itemRemove) {
         
     | 
| 
      
 76 
     | 
    
         
            +
                this.notify = {
         
     | 
| 
      
 77 
     | 
    
         
            +
                  setItem: itemSet,
         
     | 
| 
      
 78 
     | 
    
         
            +
                  removeItem: itemRemove
         
     | 
| 
      
 79 
     | 
    
         
            +
                };
         
     | 
| 
      
 80 
     | 
    
         
            +
                return this;
         
     | 
| 
      
 81 
     | 
    
         
            +
              };
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
              this.$get = ['$rootScope', '$window', '$document', '$parse', function($rootScope, $window, $document, $parse) {
         
     | 
| 
      
 84 
     | 
    
         
            +
                var self = this;
         
     | 
| 
      
 85 
     | 
    
         
            +
                var prefix = self.prefix;
         
     | 
| 
      
 86 
     | 
    
         
            +
                var cookie = self.cookie;
         
     | 
| 
      
 87 
     | 
    
         
            +
                var notify = self.notify;
         
     | 
| 
      
 88 
     | 
    
         
            +
                var storageType = self.storageType;
         
     | 
| 
      
 89 
     | 
    
         
            +
                var webStorage;
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                // When Angular's $document is not available
         
     | 
| 
      
 92 
     | 
    
         
            +
                if (!$document) {
         
     | 
| 
      
 93 
     | 
    
         
            +
                  $document = document;
         
     | 
| 
      
 94 
     | 
    
         
            +
                } else if ($document[0]) {
         
     | 
| 
      
 95 
     | 
    
         
            +
                  $document = $document[0];
         
     | 
| 
      
 96 
     | 
    
         
            +
                }
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                // If there is a prefix set in the config lets use that with an appended period for readability
         
     | 
| 
      
 99 
     | 
    
         
            +
                if (prefix.substr(-1) !== '.') {
         
     | 
| 
      
 100 
     | 
    
         
            +
                  prefix = !!prefix ? prefix + '.' : '';
         
     | 
| 
      
 101 
     | 
    
         
            +
                }
         
     | 
| 
      
 102 
     | 
    
         
            +
                var deriveQualifiedKey = function(key) {
         
     | 
| 
      
 103 
     | 
    
         
            +
                  return prefix + key;
         
     | 
| 
      
 104 
     | 
    
         
            +
                };
         
     | 
| 
      
 105 
     | 
    
         
            +
                // Checks the browser to see if local storage is supported
         
     | 
| 
      
 106 
     | 
    
         
            +
                var browserSupportsLocalStorage = (function () {
         
     | 
| 
      
 107 
     | 
    
         
            +
                  try {
         
     | 
| 
      
 108 
     | 
    
         
            +
                    var supported = (storageType in $window && $window[storageType] !== null);
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                    // When Safari (OS X or iOS) is in private browsing mode, it appears as though localStorage
         
     | 
| 
      
 111 
     | 
    
         
            +
                    // is available, but trying to call .setItem throws an exception.
         
     | 
| 
      
 112 
     | 
    
         
            +
                    //
         
     | 
| 
      
 113 
     | 
    
         
            +
                    // "QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage
         
     | 
| 
      
 114 
     | 
    
         
            +
                    // that exceeded the quota."
         
     | 
| 
      
 115 
     | 
    
         
            +
                    var key = deriveQualifiedKey('__' + Math.round(Math.random() * 1e7));
         
     | 
| 
      
 116 
     | 
    
         
            +
                    if (supported) {
         
     | 
| 
      
 117 
     | 
    
         
            +
                      webStorage = $window[storageType];
         
     | 
| 
      
 118 
     | 
    
         
            +
                      webStorage.setItem(key, '');
         
     | 
| 
      
 119 
     | 
    
         
            +
                      webStorage.removeItem(key);
         
     | 
| 
      
 120 
     | 
    
         
            +
                    }
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                    return supported;
         
     | 
| 
      
 123 
     | 
    
         
            +
                  } catch (e) {
         
     | 
| 
      
 124 
     | 
    
         
            +
                    storageType = 'cookie';
         
     | 
| 
      
 125 
     | 
    
         
            +
                    $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
         
     | 
| 
      
 126 
     | 
    
         
            +
                    return false;
         
     | 
| 
      
 127 
     | 
    
         
            +
                  }
         
     | 
| 
      
 128 
     | 
    
         
            +
                }());
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                // Directly adds a value to local storage
         
     | 
| 
      
 131 
     | 
    
         
            +
                // If local storage is not available in the browser use cookies
         
     | 
| 
      
 132 
     | 
    
         
            +
                // Example use: localStorageService.add('library','angular');
         
     | 
| 
      
 133 
     | 
    
         
            +
                var addToLocalStorage = function (key, value) {
         
     | 
| 
      
 134 
     | 
    
         
            +
                  // Let's convert undefined values to null to get the value consistent
         
     | 
| 
      
 135 
     | 
    
         
            +
                  if (isUndefined(value)) {
         
     | 
| 
      
 136 
     | 
    
         
            +
                    value = null;
         
     | 
| 
      
 137 
     | 
    
         
            +
                  } else {
         
     | 
| 
      
 138 
     | 
    
         
            +
                    value = toJson(value);
         
     | 
| 
      
 139 
     | 
    
         
            +
                  }
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                  // If this browser does not support local storage use cookies
         
     | 
| 
      
 142 
     | 
    
         
            +
                  if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
         
     | 
| 
      
 143 
     | 
    
         
            +
                    if (!browserSupportsLocalStorage) {
         
     | 
| 
      
 144 
     | 
    
         
            +
                        $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
         
     | 
| 
      
 145 
     | 
    
         
            +
                    }
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                    if (notify.setItem) {
         
     | 
| 
      
 148 
     | 
    
         
            +
                      $rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: 'cookie'});
         
     | 
| 
      
 149 
     | 
    
         
            +
                    }
         
     | 
| 
      
 150 
     | 
    
         
            +
                    return addToCookies(key, value);
         
     | 
| 
      
 151 
     | 
    
         
            +
                  }
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                  try {
         
     | 
| 
      
 154 
     | 
    
         
            +
                    if (webStorage) {
         
     | 
| 
      
 155 
     | 
    
         
            +
                      webStorage.setItem(deriveQualifiedKey(key), value);
         
     | 
| 
      
 156 
     | 
    
         
            +
                    }
         
     | 
| 
      
 157 
     | 
    
         
            +
                    if (notify.setItem) {
         
     | 
| 
      
 158 
     | 
    
         
            +
                      $rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: self.storageType});
         
     | 
| 
      
 159 
     | 
    
         
            +
                    }
         
     | 
| 
      
 160 
     | 
    
         
            +
                  } catch (e) {
         
     | 
| 
      
 161 
     | 
    
         
            +
                    $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
         
     | 
| 
      
 162 
     | 
    
         
            +
                    return addToCookies(key, value);
         
     | 
| 
      
 163 
     | 
    
         
            +
                  }
         
     | 
| 
      
 164 
     | 
    
         
            +
                  return true;
         
     | 
| 
      
 165 
     | 
    
         
            +
                };
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
                // Directly get a value from local storage
         
     | 
| 
      
 168 
     | 
    
         
            +
                // Example use: localStorageService.get('library'); // returns 'angular'
         
     | 
| 
      
 169 
     | 
    
         
            +
                var getFromLocalStorage = function (key) {
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                  if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
         
     | 
| 
      
 172 
     | 
    
         
            +
                    if (!browserSupportsLocalStorage) {
         
     | 
| 
      
 173 
     | 
    
         
            +
                      $rootScope.$broadcast('LocalStorageModule.notification.warning','LOCAL_STORAGE_NOT_SUPPORTED');
         
     | 
| 
      
 174 
     | 
    
         
            +
                    }
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
                    return getFromCookies(key);
         
     | 
| 
      
 177 
     | 
    
         
            +
                  }
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
                  var item = webStorage ? webStorage.getItem(deriveQualifiedKey(key)) : null;
         
     | 
| 
      
 180 
     | 
    
         
            +
                  // angular.toJson will convert null to 'null', so a proper conversion is needed
         
     | 
| 
      
 181 
     | 
    
         
            +
                  // FIXME not a perfect solution, since a valid 'null' string can't be stored
         
     | 
| 
      
 182 
     | 
    
         
            +
                  if (!item || item === 'null') {
         
     | 
| 
      
 183 
     | 
    
         
            +
                    return null;
         
     | 
| 
      
 184 
     | 
    
         
            +
                  }
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                  try {
         
     | 
| 
      
 187 
     | 
    
         
            +
                    return JSON.parse(item);
         
     | 
| 
      
 188 
     | 
    
         
            +
                  } catch (e) {
         
     | 
| 
      
 189 
     | 
    
         
            +
                    return item;
         
     | 
| 
      
 190 
     | 
    
         
            +
                  }
         
     | 
| 
      
 191 
     | 
    
         
            +
                };
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
                // Remove an item from local storage
         
     | 
| 
      
 194 
     | 
    
         
            +
                // Example use: localStorageService.remove('library'); // removes the key/value pair of library='angular'
         
     | 
| 
      
 195 
     | 
    
         
            +
                var removeFromLocalStorage = function () {
         
     | 
| 
      
 196 
     | 
    
         
            +
                  var i, key;
         
     | 
| 
      
 197 
     | 
    
         
            +
                  for (i=0; i<arguments.length; i++) {
         
     | 
| 
      
 198 
     | 
    
         
            +
                    key = arguments[i];
         
     | 
| 
      
 199 
     | 
    
         
            +
                    if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
         
     | 
| 
      
 200 
     | 
    
         
            +
                      if (!browserSupportsLocalStorage) {
         
     | 
| 
      
 201 
     | 
    
         
            +
                        $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
         
     | 
| 
      
 202 
     | 
    
         
            +
                      }
         
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
                      if (notify.removeItem) {
         
     | 
| 
      
 205 
     | 
    
         
            +
                        $rootScope.$broadcast('LocalStorageModule.notification.removeitem', {key: key, storageType: 'cookie'});
         
     | 
| 
      
 206 
     | 
    
         
            +
                      }
         
     | 
| 
      
 207 
     | 
    
         
            +
                      removeFromCookies(key);
         
     | 
| 
      
 208 
     | 
    
         
            +
                    }
         
     | 
| 
      
 209 
     | 
    
         
            +
                    else {
         
     | 
| 
      
 210 
     | 
    
         
            +
                      try {
         
     | 
| 
      
 211 
     | 
    
         
            +
                        webStorage.removeItem(deriveQualifiedKey(key));
         
     | 
| 
      
 212 
     | 
    
         
            +
                        if (notify.removeItem) {
         
     | 
| 
      
 213 
     | 
    
         
            +
                          $rootScope.$broadcast('LocalStorageModule.notification.removeitem', {
         
     | 
| 
      
 214 
     | 
    
         
            +
                            key: key,
         
     | 
| 
      
 215 
     | 
    
         
            +
                            storageType: self.storageType
         
     | 
| 
      
 216 
     | 
    
         
            +
                          });
         
     | 
| 
      
 217 
     | 
    
         
            +
                        }
         
     | 
| 
      
 218 
     | 
    
         
            +
                      } catch (e) {
         
     | 
| 
      
 219 
     | 
    
         
            +
                        $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
         
     | 
| 
      
 220 
     | 
    
         
            +
                        removeFromCookies(key);
         
     | 
| 
      
 221 
     | 
    
         
            +
                      }
         
     | 
| 
      
 222 
     | 
    
         
            +
                    }
         
     | 
| 
      
 223 
     | 
    
         
            +
                  }
         
     | 
| 
      
 224 
     | 
    
         
            +
                };
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
                // Return array of keys for local storage
         
     | 
| 
      
 227 
     | 
    
         
            +
                // Example use: var keys = localStorageService.keys()
         
     | 
| 
      
 228 
     | 
    
         
            +
                var getKeysForLocalStorage = function () {
         
     | 
| 
      
 229 
     | 
    
         
            +
             
     | 
| 
      
 230 
     | 
    
         
            +
                  if (!browserSupportsLocalStorage) {
         
     | 
| 
      
 231 
     | 
    
         
            +
                    $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
         
     | 
| 
      
 232 
     | 
    
         
            +
                    return false;
         
     | 
| 
      
 233 
     | 
    
         
            +
                  }
         
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
      
 235 
     | 
    
         
            +
                  var prefixLength = prefix.length;
         
     | 
| 
      
 236 
     | 
    
         
            +
                  var keys = [];
         
     | 
| 
      
 237 
     | 
    
         
            +
                  for (var key in webStorage) {
         
     | 
| 
      
 238 
     | 
    
         
            +
                    // Only return keys that are for this app
         
     | 
| 
      
 239 
     | 
    
         
            +
                    if (key.substr(0,prefixLength) === prefix) {
         
     | 
| 
      
 240 
     | 
    
         
            +
                      try {
         
     | 
| 
      
 241 
     | 
    
         
            +
                        keys.push(key.substr(prefixLength));
         
     | 
| 
      
 242 
     | 
    
         
            +
                      } catch (e) {
         
     | 
| 
      
 243 
     | 
    
         
            +
                        $rootScope.$broadcast('LocalStorageModule.notification.error', e.Description);
         
     | 
| 
      
 244 
     | 
    
         
            +
                        return [];
         
     | 
| 
      
 245 
     | 
    
         
            +
                      }
         
     | 
| 
      
 246 
     | 
    
         
            +
                    }
         
     | 
| 
      
 247 
     | 
    
         
            +
                  }
         
     | 
| 
      
 248 
     | 
    
         
            +
                  return keys;
         
     | 
| 
      
 249 
     | 
    
         
            +
                };
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
                // Remove all data for this app from local storage
         
     | 
| 
      
 252 
     | 
    
         
            +
                // Also optionally takes a regular expression string and removes the matching key-value pairs
         
     | 
| 
      
 253 
     | 
    
         
            +
                // Example use: localStorageService.clearAll();
         
     | 
| 
      
 254 
     | 
    
         
            +
                // Should be used mostly for development purposes
         
     | 
| 
      
 255 
     | 
    
         
            +
                var clearAllFromLocalStorage = function (regularExpression) {
         
     | 
| 
      
 256 
     | 
    
         
            +
             
     | 
| 
      
 257 
     | 
    
         
            +
                  // Setting both regular expressions independently
         
     | 
| 
      
 258 
     | 
    
         
            +
                  // Empty strings result in catchall RegExp
         
     | 
| 
      
 259 
     | 
    
         
            +
                  var prefixRegex = !!prefix ? new RegExp('^' + prefix) : new RegExp();
         
     | 
| 
      
 260 
     | 
    
         
            +
                  var testRegex = !!regularExpression ? new RegExp(regularExpression) : new RegExp();
         
     | 
| 
      
 261 
     | 
    
         
            +
             
     | 
| 
      
 262 
     | 
    
         
            +
                  if (!browserSupportsLocalStorage || self.storageType === 'cookie') {
         
     | 
| 
      
 263 
     | 
    
         
            +
                    if (!browserSupportsLocalStorage) {
         
     | 
| 
      
 264 
     | 
    
         
            +
                      $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
         
     | 
| 
      
 265 
     | 
    
         
            +
                    }
         
     | 
| 
      
 266 
     | 
    
         
            +
                    return clearAllFromCookies();
         
     | 
| 
      
 267 
     | 
    
         
            +
                  }
         
     | 
| 
      
 268 
     | 
    
         
            +
             
     | 
| 
      
 269 
     | 
    
         
            +
                  var prefixLength = prefix.length;
         
     | 
| 
      
 270 
     | 
    
         
            +
             
     | 
| 
      
 271 
     | 
    
         
            +
                  for (var key in webStorage) {
         
     | 
| 
      
 272 
     | 
    
         
            +
                    // Only remove items that are for this app and match the regular expression
         
     | 
| 
      
 273 
     | 
    
         
            +
                    if (prefixRegex.test(key) && testRegex.test(key.substr(prefixLength))) {
         
     | 
| 
      
 274 
     | 
    
         
            +
                      try {
         
     | 
| 
      
 275 
     | 
    
         
            +
                        removeFromLocalStorage(key.substr(prefixLength));
         
     | 
| 
      
 276 
     | 
    
         
            +
                      } catch (e) {
         
     | 
| 
      
 277 
     | 
    
         
            +
                        $rootScope.$broadcast('LocalStorageModule.notification.error',e.message);
         
     | 
| 
      
 278 
     | 
    
         
            +
                        return clearAllFromCookies();
         
     | 
| 
      
 279 
     | 
    
         
            +
                      }
         
     | 
| 
      
 280 
     | 
    
         
            +
                    }
         
     | 
| 
      
 281 
     | 
    
         
            +
                  }
         
     | 
| 
      
 282 
     | 
    
         
            +
                  return true;
         
     | 
| 
      
 283 
     | 
    
         
            +
                };
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
      
 285 
     | 
    
         
            +
                // Checks the browser to see if cookies are supported
         
     | 
| 
      
 286 
     | 
    
         
            +
                var browserSupportsCookies = (function() {
         
     | 
| 
      
 287 
     | 
    
         
            +
                  try {
         
     | 
| 
      
 288 
     | 
    
         
            +
                    return $window.navigator.cookieEnabled ||
         
     | 
| 
      
 289 
     | 
    
         
            +
                      ("cookie" in $document && ($document.cookie.length > 0 ||
         
     | 
| 
      
 290 
     | 
    
         
            +
                      ($document.cookie = "test").indexOf.call($document.cookie, "test") > -1));
         
     | 
| 
      
 291 
     | 
    
         
            +
                  } catch (e) {
         
     | 
| 
      
 292 
     | 
    
         
            +
                      $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
         
     | 
| 
      
 293 
     | 
    
         
            +
                      return false;
         
     | 
| 
      
 294 
     | 
    
         
            +
                  }
         
     | 
| 
      
 295 
     | 
    
         
            +
                }());
         
     | 
| 
      
 296 
     | 
    
         
            +
             
     | 
| 
      
 297 
     | 
    
         
            +
                // Directly adds a value to cookies
         
     | 
| 
      
 298 
     | 
    
         
            +
                // Typically used as a fallback is local storage is not available in the browser
         
     | 
| 
      
 299 
     | 
    
         
            +
                // Example use: localStorageService.cookie.add('library','angular');
         
     | 
| 
      
 300 
     | 
    
         
            +
                var addToCookies = function (key, value, daysToExpiry) {
         
     | 
| 
      
 301 
     | 
    
         
            +
             
     | 
| 
      
 302 
     | 
    
         
            +
                  if (isUndefined(value)) {
         
     | 
| 
      
 303 
     | 
    
         
            +
                    return false;
         
     | 
| 
      
 304 
     | 
    
         
            +
                  } else if(isArray(value) || isObject(value)) {
         
     | 
| 
      
 305 
     | 
    
         
            +
                    value = toJson(value);
         
     | 
| 
      
 306 
     | 
    
         
            +
                  }
         
     | 
| 
      
 307 
     | 
    
         
            +
             
     | 
| 
      
 308 
     | 
    
         
            +
                  if (!browserSupportsCookies) {
         
     | 
| 
      
 309 
     | 
    
         
            +
                    $rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED');
         
     | 
| 
      
 310 
     | 
    
         
            +
                    return false;
         
     | 
| 
      
 311 
     | 
    
         
            +
                  }
         
     | 
| 
      
 312 
     | 
    
         
            +
             
     | 
| 
      
 313 
     | 
    
         
            +
                  try {
         
     | 
| 
      
 314 
     | 
    
         
            +
                    var expiry = '',
         
     | 
| 
      
 315 
     | 
    
         
            +
                        expiryDate = new Date(),
         
     | 
| 
      
 316 
     | 
    
         
            +
                        cookieDomain = '';
         
     | 
| 
      
 317 
     | 
    
         
            +
             
     | 
| 
      
 318 
     | 
    
         
            +
                    if (value === null) {
         
     | 
| 
      
 319 
     | 
    
         
            +
                      // Mark that the cookie has expired one day ago
         
     | 
| 
      
 320 
     | 
    
         
            +
                      expiryDate.setTime(expiryDate.getTime() + (-1 * 24 * 60 * 60 * 1000));
         
     | 
| 
      
 321 
     | 
    
         
            +
                      expiry = "; expires=" + expiryDate.toGMTString();
         
     | 
| 
      
 322 
     | 
    
         
            +
                      value = '';
         
     | 
| 
      
 323 
     | 
    
         
            +
                    } else if (isNumber(daysToExpiry) && daysToExpiry !== 0) {
         
     | 
| 
      
 324 
     | 
    
         
            +
                      expiryDate.setTime(expiryDate.getTime() + (daysToExpiry * 24 * 60 * 60 * 1000));
         
     | 
| 
      
 325 
     | 
    
         
            +
                      expiry = "; expires=" + expiryDate.toGMTString();
         
     | 
| 
      
 326 
     | 
    
         
            +
                    } else if (cookie.expiry !== 0) {
         
     | 
| 
      
 327 
     | 
    
         
            +
                      expiryDate.setTime(expiryDate.getTime() + (cookie.expiry * 24 * 60 * 60 * 1000));
         
     | 
| 
      
 328 
     | 
    
         
            +
                      expiry = "; expires=" + expiryDate.toGMTString();
         
     | 
| 
      
 329 
     | 
    
         
            +
                    }
         
     | 
| 
      
 330 
     | 
    
         
            +
                    if (!!key) {
         
     | 
| 
      
 331 
     | 
    
         
            +
                      var cookiePath = "; path=" + cookie.path;
         
     | 
| 
      
 332 
     | 
    
         
            +
                      if(cookie.domain){
         
     | 
| 
      
 333 
     | 
    
         
            +
                        cookieDomain = "; domain=" + cookie.domain;
         
     | 
| 
      
 334 
     | 
    
         
            +
                      }
         
     | 
| 
      
 335 
     | 
    
         
            +
                      $document.cookie = deriveQualifiedKey(key) + "=" + encodeURIComponent(value) + expiry + cookiePath + cookieDomain;
         
     | 
| 
      
 336 
     | 
    
         
            +
                    }
         
     | 
| 
      
 337 
     | 
    
         
            +
                  } catch (e) {
         
     | 
| 
      
 338 
     | 
    
         
            +
                    $rootScope.$broadcast('LocalStorageModule.notification.error',e.message);
         
     | 
| 
      
 339 
     | 
    
         
            +
                    return false;
         
     | 
| 
      
 340 
     | 
    
         
            +
                  }
         
     | 
| 
      
 341 
     | 
    
         
            +
                  return true;
         
     | 
| 
      
 342 
     | 
    
         
            +
                };
         
     | 
| 
      
 343 
     | 
    
         
            +
             
     | 
| 
      
 344 
     | 
    
         
            +
                // Directly get a value from a cookie
         
     | 
| 
      
 345 
     | 
    
         
            +
                // Example use: localStorageService.cookie.get('library'); // returns 'angular'
         
     | 
| 
      
 346 
     | 
    
         
            +
                var getFromCookies = function (key) {
         
     | 
| 
      
 347 
     | 
    
         
            +
                  if (!browserSupportsCookies) {
         
     | 
| 
      
 348 
     | 
    
         
            +
                    $rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED');
         
     | 
| 
      
 349 
     | 
    
         
            +
                    return false;
         
     | 
| 
      
 350 
     | 
    
         
            +
                  }
         
     | 
| 
      
 351 
     | 
    
         
            +
             
     | 
| 
      
 352 
     | 
    
         
            +
                  var cookies = $document.cookie && $document.cookie.split(';') || [];
         
     | 
| 
      
 353 
     | 
    
         
            +
                  for(var i=0; i < cookies.length; i++) {
         
     | 
| 
      
 354 
     | 
    
         
            +
                    var thisCookie = cookies[i];
         
     | 
| 
      
 355 
     | 
    
         
            +
                    while (thisCookie.charAt(0) === ' ') {
         
     | 
| 
      
 356 
     | 
    
         
            +
                      thisCookie = thisCookie.substring(1,thisCookie.length);
         
     | 
| 
      
 357 
     | 
    
         
            +
                    }
         
     | 
| 
      
 358 
     | 
    
         
            +
                    if (thisCookie.indexOf(deriveQualifiedKey(key) + '=') === 0) {
         
     | 
| 
      
 359 
     | 
    
         
            +
                      var storedValues = decodeURIComponent(thisCookie.substring(prefix.length + key.length + 1, thisCookie.length));
         
     | 
| 
      
 360 
     | 
    
         
            +
                      try {
         
     | 
| 
      
 361 
     | 
    
         
            +
                        return JSON.parse(storedValues);
         
     | 
| 
      
 362 
     | 
    
         
            +
                      } catch(e) {
         
     | 
| 
      
 363 
     | 
    
         
            +
                        return storedValues;
         
     | 
| 
      
 364 
     | 
    
         
            +
                      }
         
     | 
| 
      
 365 
     | 
    
         
            +
                    }
         
     | 
| 
      
 366 
     | 
    
         
            +
                  }
         
     | 
| 
      
 367 
     | 
    
         
            +
                  return null;
         
     | 
| 
      
 368 
     | 
    
         
            +
                };
         
     | 
| 
      
 369 
     | 
    
         
            +
             
     | 
| 
      
 370 
     | 
    
         
            +
                var removeFromCookies = function (key) {
         
     | 
| 
      
 371 
     | 
    
         
            +
                  addToCookies(key,null);
         
     | 
| 
      
 372 
     | 
    
         
            +
                };
         
     | 
| 
      
 373 
     | 
    
         
            +
             
     | 
| 
      
 374 
     | 
    
         
            +
                var clearAllFromCookies = function () {
         
     | 
| 
      
 375 
     | 
    
         
            +
                  var thisCookie = null, thisKey = null;
         
     | 
| 
      
 376 
     | 
    
         
            +
                  var prefixLength = prefix.length;
         
     | 
| 
      
 377 
     | 
    
         
            +
                  var cookies = $document.cookie.split(';');
         
     | 
| 
      
 378 
     | 
    
         
            +
                  for(var i = 0; i < cookies.length; i++) {
         
     | 
| 
      
 379 
     | 
    
         
            +
                    thisCookie = cookies[i];
         
     | 
| 
      
 380 
     | 
    
         
            +
             
     | 
| 
      
 381 
     | 
    
         
            +
                    while (thisCookie.charAt(0) === ' ') {
         
     | 
| 
      
 382 
     | 
    
         
            +
                      thisCookie = thisCookie.substring(1, thisCookie.length);
         
     | 
| 
      
 383 
     | 
    
         
            +
                    }
         
     | 
| 
      
 384 
     | 
    
         
            +
             
     | 
| 
      
 385 
     | 
    
         
            +
                    var key = thisCookie.substring(prefixLength, thisCookie.indexOf('='));
         
     | 
| 
      
 386 
     | 
    
         
            +
                    removeFromCookies(key);
         
     | 
| 
      
 387 
     | 
    
         
            +
                  }
         
     | 
| 
      
 388 
     | 
    
         
            +
                };
         
     | 
| 
      
 389 
     | 
    
         
            +
             
     | 
| 
      
 390 
     | 
    
         
            +
                var getStorageType = function() {
         
     | 
| 
      
 391 
     | 
    
         
            +
                  return storageType;
         
     | 
| 
      
 392 
     | 
    
         
            +
                };
         
     | 
| 
      
 393 
     | 
    
         
            +
             
     | 
| 
      
 394 
     | 
    
         
            +
                // Add a listener on scope variable to save its changes to local storage
         
     | 
| 
      
 395 
     | 
    
         
            +
                // Return a function which when called cancels binding
         
     | 
| 
      
 396 
     | 
    
         
            +
                var bindToScope = function(scope, key, def, lsKey) {
         
     | 
| 
      
 397 
     | 
    
         
            +
                  lsKey = lsKey || key;
         
     | 
| 
      
 398 
     | 
    
         
            +
                  var value = getFromLocalStorage(lsKey);
         
     | 
| 
      
 399 
     | 
    
         
            +
             
     | 
| 
      
 400 
     | 
    
         
            +
                  if (value === null && isDefined(def)) {
         
     | 
| 
      
 401 
     | 
    
         
            +
                    value = def;
         
     | 
| 
      
 402 
     | 
    
         
            +
                  } else if (isObject(value) && isObject(def)) {
         
     | 
| 
      
 403 
     | 
    
         
            +
                    value = extend(def, value);
         
     | 
| 
      
 404 
     | 
    
         
            +
                  }
         
     | 
| 
      
 405 
     | 
    
         
            +
             
     | 
| 
      
 406 
     | 
    
         
            +
                  $parse(key).assign(scope, value);
         
     | 
| 
      
 407 
     | 
    
         
            +
             
     | 
| 
      
 408 
     | 
    
         
            +
                  return scope.$watch(key, function(newVal) {
         
     | 
| 
      
 409 
     | 
    
         
            +
                    addToLocalStorage(lsKey, newVal);
         
     | 
| 
      
 410 
     | 
    
         
            +
                  }, isObject(scope[key]));
         
     | 
| 
      
 411 
     | 
    
         
            +
                };
         
     | 
| 
      
 412 
     | 
    
         
            +
             
     | 
| 
      
 413 
     | 
    
         
            +
                // Return localStorageService.length
         
     | 
| 
      
 414 
     | 
    
         
            +
                // ignore keys that not owned
         
     | 
| 
      
 415 
     | 
    
         
            +
                var lengthOfLocalStorage = function() {
         
     | 
| 
      
 416 
     | 
    
         
            +
                  var count = 0;
         
     | 
| 
      
 417 
     | 
    
         
            +
                  var storage = $window[storageType];
         
     | 
| 
      
 418 
     | 
    
         
            +
                  for(var i = 0; i < storage.length; i++) {
         
     | 
| 
      
 419 
     | 
    
         
            +
                    if(storage.key(i).indexOf(prefix) === 0 ) {
         
     | 
| 
      
 420 
     | 
    
         
            +
                      count++;
         
     | 
| 
      
 421 
     | 
    
         
            +
                    }
         
     | 
| 
      
 422 
     | 
    
         
            +
                  }
         
     | 
| 
      
 423 
     | 
    
         
            +
                  return count;
         
     | 
| 
      
 424 
     | 
    
         
            +
                };
         
     | 
| 
      
 425 
     | 
    
         
            +
             
     | 
| 
      
 426 
     | 
    
         
            +
                return {
         
     | 
| 
      
 427 
     | 
    
         
            +
                  isSupported: browserSupportsLocalStorage,
         
     | 
| 
      
 428 
     | 
    
         
            +
                  getStorageType: getStorageType,
         
     | 
| 
      
 429 
     | 
    
         
            +
                  set: addToLocalStorage,
         
     | 
| 
      
 430 
     | 
    
         
            +
                  add: addToLocalStorage, //DEPRECATED
         
     | 
| 
      
 431 
     | 
    
         
            +
                  get: getFromLocalStorage,
         
     | 
| 
      
 432 
     | 
    
         
            +
                  keys: getKeysForLocalStorage,
         
     | 
| 
      
 433 
     | 
    
         
            +
                  remove: removeFromLocalStorage,
         
     | 
| 
      
 434 
     | 
    
         
            +
                  clearAll: clearAllFromLocalStorage,
         
     | 
| 
      
 435 
     | 
    
         
            +
                  bind: bindToScope,
         
     | 
| 
      
 436 
     | 
    
         
            +
                  deriveKey: deriveQualifiedKey,
         
     | 
| 
      
 437 
     | 
    
         
            +
                  length: lengthOfLocalStorage,
         
     | 
| 
      
 438 
     | 
    
         
            +
                  cookie: {
         
     | 
| 
      
 439 
     | 
    
         
            +
                    isSupported: browserSupportsCookies,
         
     | 
| 
      
 440 
     | 
    
         
            +
                    set: addToCookies,
         
     | 
| 
      
 441 
     | 
    
         
            +
                    add: addToCookies, //DEPRECATED
         
     | 
| 
      
 442 
     | 
    
         
            +
                    get: getFromCookies,
         
     | 
| 
      
 443 
     | 
    
         
            +
                    remove: removeFromCookies,
         
     | 
| 
      
 444 
     | 
    
         
            +
                    clearAll: clearAllFromCookies
         
     | 
| 
      
 445 
     | 
    
         
            +
                  }
         
     | 
| 
      
 446 
     | 
    
         
            +
                };
         
     | 
| 
      
 447 
     | 
    
         
            +
              }];
         
     | 
| 
      
 448 
     | 
    
         
            +
            });
         
     | 
| 
      
 449 
     | 
    
         
            +
            })( window, window.angular );
         
     |