rails-assets-listjs 0.2.0.beta.4
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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/rails-assets-listjs.rb +10 -0
- data/lib/rails-assets-listjs/version.rb +7 -0
- data/rails-assets-listjs.gemspec +19 -0
- data/vendor/assets/javascripts/list.fuzzySearch.js +211 -0
- data/vendor/assets/javascripts/list.js +775 -0
- data/vendor/assets/javascripts/list.min.js +1 -0
- data/vendor/assets/javascripts/list.paging.js +86 -0
- metadata +74 -0
    
        data/.gitignore
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE.txt
    ADDED
    
    | @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            Copyright (c) 2012 Thomas Klemm
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            MIT License
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Permission is hereby granted, free of charge, to any person obtaining
         | 
| 6 | 
            +
            a copy of this software and associated documentation files (the
         | 
| 7 | 
            +
            "Software"), to deal in the Software without restriction, including
         | 
| 8 | 
            +
            without limitation the rights to use, copy, modify, merge, publish,
         | 
| 9 | 
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         | 
| 10 | 
            +
            permit persons to whom the Software is furnished to do so, subject to
         | 
| 11 | 
            +
            the following conditions:
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            The above copyright notice and this permission notice shall be
         | 
| 14 | 
            +
            included in all copies or substantial portions of the Software.
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 17 | 
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         | 
| 18 | 
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 19 | 
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         | 
| 20 | 
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         | 
| 21 | 
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         | 
| 22 | 
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         | 
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            # Rails::Assets::Listjs
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            TODO: Write a gem description
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ## Installation
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            Add this line to your application's Gemfile:
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                gem 'rails-assets-listjs'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            And then execute:
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                $ bundle
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            Or install it yourself as:
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                $ gem install rails-assets-listjs
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            ## Usage
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            TODO: Write usage instructions here
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            ## Contributing
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            1. Fork it
         | 
| 26 | 
            +
            2. Create your feature branch (`git checkout -b my-new-feature`)
         | 
| 27 | 
            +
            3. Commit your changes (`git commit -am 'Add some feature'`)
         | 
| 28 | 
            +
            4. Push to the branch (`git push origin my-new-feature`)
         | 
| 29 | 
            +
            5. Create new Pull Request
         | 
    
        data/Rakefile
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            require "bundler/gem_tasks"
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
            lib = File.expand_path('../lib', __FILE__)
         | 
| 3 | 
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| 4 | 
            +
            require 'rails-assets-listjs/version'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            Gem::Specification.new do |gem|
         | 
| 7 | 
            +
              gem.name          = "rails-assets-listjs"
         | 
| 8 | 
            +
              gem.version       = Rails::Assets::Listjs::VERSION
         | 
| 9 | 
            +
              gem.authors       = ["Thomas Klemm"]
         | 
| 10 | 
            +
              gem.email         = ["github@tklemm.eu"]
         | 
| 11 | 
            +
              gem.description   = %q{List.js - packaged by RailsAssets for the Rails Asset Pipeline}
         | 
| 12 | 
            +
              gem.summary       = %q{List.js - packaged by RailsAssets for the Rails Asset Pipeline}
         | 
| 13 | 
            +
              gem.homepage      = "http://www.railsassets.com"
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              gem.files         = `git ls-files`.split($/)
         | 
| 16 | 
            +
              gem.require_paths = ["lib"]
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              gem.add_dependency "railties", ">= 3.1"
         | 
| 19 | 
            +
            end
         | 
| @@ -0,0 +1,211 @@ | |
| 1 | 
            +
            /**
         | 
| 2 | 
            +
             * Locate the best instance of 'pattern' in 'text' using the Bitap algorithm.
         | 
| 3 | 
            +
             *
         | 
| 4 | 
            +
             * This method is a based on: Diff Match and Patch
         | 
| 5 | 
            +
             * http://code.google.com/p/google-diff-match-patch/
         | 
| 6 | 
            +
             * Author: fraser@google.com (Neil Fraser)
         | 
| 7 | 
            +
             * Modifications by: l.vanegeraat@gmail.com (Luuk van Egeraat)
         | 
| 8 | 
            +
             * Plugin by: jonny.stromberg@gmail.com (Jonny Strömberg / @javve)
         | 
| 9 | 
            +
             *
         | 
| 10 | 
            +
             * Licensed under the Apache License
         | 
| 11 | 
            +
             * http://www.apache.org/licenses/LICENSE-2.0
         | 
| 12 | 
            +
             *
         | 
| 13 | 
            +
             */
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            List.prototype.plugins.fuzzySearch = function(locals, options) {
         | 
| 16 | 
            +
                var self = this;
         | 
| 17 | 
            +
                var searchFunction = function(text, pattern, options) {
         | 
| 18 | 
            +
                    // Aproximately where in the text is the pattern expected to be found?
         | 
| 19 | 
            +
                    var Match_Location = options.location || 0;
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    //Determines how close the match must be to the fuzzy location (specified above). An exact letter match which is 'distance' characters away from the fuzzy location would score as a complete mismatch. A distance of '0' requires the match be at the exact location specified, a threshold of '1000' would require a perfect match to be within 800 characters of the fuzzy location to be found using a 0.8 threshold.
         | 
| 22 | 
            +
                    var Match_Distance = options.distance || 100;
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    // At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match (of both letters and location), a threshold of '1.0' would match anything.
         | 
| 25 | 
            +
                    var Match_Threshold = options.threshold || 0.4;
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    if (pattern === text) return true; // Exact match
         | 
| 28 | 
            +
                    if (pattern.length > 32) return false; // This algorithm cannot be used
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    // Set starting location at beginning text and initialise the alphabet.
         | 
| 31 | 
            +
                    var loc = Match_Location,
         | 
| 32 | 
            +
                        s = (function() {
         | 
| 33 | 
            +
                            var q = {};
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                            for (var i = 0; i < pattern.length; i++) {
         | 
| 36 | 
            +
                                q[pattern.charAt(i)] = 0;
         | 
| 37 | 
            +
                            }
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                            for (var i = 0; i < pattern.length; i++) {
         | 
| 40 | 
            +
                                q[pattern.charAt(i)] |= 1 << (pattern.length - i - 1);
         | 
| 41 | 
            +
                            }
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                            return q;
         | 
| 44 | 
            +
                        }());
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    // Compute and return the score for a match with e errors and x location.
         | 
| 47 | 
            +
                    // Accesses loc and pattern through being a closure.
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    function match_bitapScore_(e, x) {
         | 
| 50 | 
            +
                        var accuracy = e / pattern.length,
         | 
| 51 | 
            +
                            proximity = Math.abs(loc - x);
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                        if (!Match_Distance) {
         | 
| 54 | 
            +
                            // Dodge divide by zero error.
         | 
| 55 | 
            +
                            return proximity ? 1.0 : accuracy;
         | 
| 56 | 
            +
                        }
         | 
| 57 | 
            +
                        return accuracy + (proximity / Match_Distance);
         | 
| 58 | 
            +
                    }
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    var score_threshold = Match_Threshold, // Highest score beyond which we give up.
         | 
| 61 | 
            +
                        best_loc = text.indexOf(pattern, loc); // Is there a nearby exact match? (speedup)
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    if (best_loc != -1) {
         | 
| 64 | 
            +
                        score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold);
         | 
| 65 | 
            +
                        // What about in the other direction? (speedup)
         | 
| 66 | 
            +
                        best_loc = text.lastIndexOf(pattern, loc + pattern.length);
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                        if (best_loc != -1) {
         | 
| 69 | 
            +
                            score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold);
         | 
| 70 | 
            +
                        }
         | 
| 71 | 
            +
                    }
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                    // Initialise the bit arrays.
         | 
| 74 | 
            +
                    var matchmask = 1 << (pattern.length - 1);
         | 
| 75 | 
            +
                    best_loc = -1;
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    var bin_min, bin_mid;
         | 
| 78 | 
            +
                    var bin_max = pattern.length + text.length;
         | 
| 79 | 
            +
                    var last_rd;
         | 
| 80 | 
            +
                    for (var d = 0; d < pattern.length; d++) {
         | 
| 81 | 
            +
                        // Scan for the best match; each iteration allows for one more error.
         | 
| 82 | 
            +
                        // Run a binary search to determine how far from 'loc' we can stray at this
         | 
| 83 | 
            +
                        // error level.
         | 
| 84 | 
            +
                        bin_min = 0;
         | 
| 85 | 
            +
                        bin_mid = bin_max;
         | 
| 86 | 
            +
                        while (bin_min < bin_mid) {
         | 
| 87 | 
            +
                            if (match_bitapScore_(d, loc + bin_mid) <= score_threshold) {
         | 
| 88 | 
            +
                                bin_min = bin_mid;
         | 
| 89 | 
            +
                            } else {
         | 
| 90 | 
            +
                                bin_max = bin_mid;
         | 
| 91 | 
            +
                            }
         | 
| 92 | 
            +
                            bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min);
         | 
| 93 | 
            +
                        }
         | 
| 94 | 
            +
                        // Use the result from this iteration as the maximum for the next.
         | 
| 95 | 
            +
                        bin_max = bin_mid;
         | 
| 96 | 
            +
                        var start = Math.max(1, loc - bin_mid + 1);
         | 
| 97 | 
            +
                        var finish = Math.min(loc + bin_mid, text.length) + pattern.length;
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                        var rd = Array(finish + 2);
         | 
| 100 | 
            +
                        rd[finish + 1] = (1 << d) - 1;
         | 
| 101 | 
            +
                        for (var j = finish; j >= start; j--) {
         | 
| 102 | 
            +
                            // The alphabet (s) is a sparse hash, so the following line generates
         | 
| 103 | 
            +
                            // warnings.
         | 
| 104 | 
            +
                            var charMatch = s[text.charAt(j - 1)];
         | 
| 105 | 
            +
                            if (d === 0) {    // First pass: exact match.
         | 
| 106 | 
            +
                                rd[j] = ((rd[j + 1] << 1) | 1) & charMatch;
         | 
| 107 | 
            +
                            } else {    // Subsequent passes: fuzzy match.
         | 
| 108 | 
            +
                                rd[j] = (((rd[j + 1] << 1) | 1) & charMatch) |
         | 
| 109 | 
            +
                                                (((last_rd[j + 1] | last_rd[j]) << 1) | 1) |
         | 
| 110 | 
            +
                                                last_rd[j + 1];
         | 
| 111 | 
            +
                            }
         | 
| 112 | 
            +
                            if (rd[j] & matchmask) {
         | 
| 113 | 
            +
                                var score = match_bitapScore_(d, j - 1);
         | 
| 114 | 
            +
                                // This match will almost certainly be better than any existing match.
         | 
| 115 | 
            +
                                // But check anyway.
         | 
| 116 | 
            +
                                if (score <= score_threshold) {
         | 
| 117 | 
            +
                                    // Told you so.
         | 
| 118 | 
            +
                                    score_threshold = score;
         | 
| 119 | 
            +
                                    best_loc = j - 1;
         | 
| 120 | 
            +
                                    if (best_loc > loc) {
         | 
| 121 | 
            +
                                        // When passing loc, don't exceed our current distance from loc.
         | 
| 122 | 
            +
                                        start = Math.max(1, 2 * loc - best_loc);
         | 
| 123 | 
            +
                                    } else {
         | 
| 124 | 
            +
                                        // Already passed loc, downhill from here on in.
         | 
| 125 | 
            +
                                        break;
         | 
| 126 | 
            +
                                    }
         | 
| 127 | 
            +
                                }
         | 
| 128 | 
            +
                            }
         | 
| 129 | 
            +
                        }
         | 
| 130 | 
            +
                        // No hope for a (better) match at greater error levels.
         | 
| 131 | 
            +
                        if (match_bitapScore_(d + 1, loc) > score_threshold) {
         | 
| 132 | 
            +
                            break;
         | 
| 133 | 
            +
                        }
         | 
| 134 | 
            +
                        last_rd = rd;
         | 
| 135 | 
            +
                    }
         | 
| 136 | 
            +
                    return (best_loc < 0) ? false : true;
         | 
| 137 | 
            +
                };
         | 
| 138 | 
            +
             | 
| 139 | 
            +
             | 
| 140 | 
            +
                return (function() {
         | 
| 141 | 
            +
                    var func = function(searchString, columns) {
         | 
| 142 | 
            +
                        self.i = 1; // Reset paging
         | 
| 143 | 
            +
                        var searchArguments,
         | 
| 144 | 
            +
                            foundArgument,
         | 
| 145 | 
            +
                            matching = [],
         | 
| 146 | 
            +
                            found,
         | 
| 147 | 
            +
                            item,
         | 
| 148 | 
            +
                            text,
         | 
| 149 | 
            +
                            values,
         | 
| 150 | 
            +
                            is,
         | 
| 151 | 
            +
                            multiSearch = (typeof options.multiSearch !== 'boolean') ? true : options.multiSearch,
         | 
| 152 | 
            +
                            columns = (columns === undefined) ? self.items[0].values() : columns,
         | 
| 153 | 
            +
                            searchString = (searchString === undefined) ? "" : searchString,
         | 
| 154 | 
            +
                            target = searchString.target || searchString.srcElement; /* IE have srcElement */
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                        searchString = (target === undefined) ? (""+searchString).toLowerCase() : ""+target.value.toLowerCase();
         | 
| 157 | 
            +
                        is = self.items;
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                        // Substract arguments from the searchString or put searchString as only argument
         | 
| 160 | 
            +
                        searchArguments = multiSearch ? searchString.replace(/ +$/, '').split(/ +/) : [searchString];
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                        locals.templater.clear();
         | 
| 163 | 
            +
                        if (searchString === "") {
         | 
| 164 | 
            +
                            locals.reset.search();
         | 
| 165 | 
            +
                            self.searched = false;
         | 
| 166 | 
            +
                            self.update();
         | 
| 167 | 
            +
                        } else {
         | 
| 168 | 
            +
                            self.searched = true;
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                            for (var k = 0, kl = is.length; k < kl; k++) {
         | 
| 171 | 
            +
                                found = true;
         | 
| 172 | 
            +
                                item = is[k];
         | 
| 173 | 
            +
                                values = item.values();
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                                for(var i = 0; i < searchArguments.length; i++) {
         | 
| 176 | 
            +
                                    foundArgument = false;
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                                    for(var j in columns) {
         | 
| 179 | 
            +
                                        if(values.hasOwnProperty(j) && columns[j] !== null) {
         | 
| 180 | 
            +
                                            text = (values[j] != null) ? values[j].toString().toLowerCase() : "";
         | 
| 181 | 
            +
                                            if (searchFunction(text, searchArguments[i], options)) {
         | 
| 182 | 
            +
                                                foundArgument = true;
         | 
| 183 | 
            +
                                            }
         | 
| 184 | 
            +
                                        }
         | 
| 185 | 
            +
                                    }
         | 
| 186 | 
            +
                                    if(!foundArgument) found = false;
         | 
| 187 | 
            +
                                }
         | 
| 188 | 
            +
                                if (found) {
         | 
| 189 | 
            +
                                    item.found = true;
         | 
| 190 | 
            +
                                    matching.push(item);
         | 
| 191 | 
            +
                                } else {
         | 
| 192 | 
            +
                                    item.found = false;
         | 
| 193 | 
            +
                                }
         | 
| 194 | 
            +
                            }
         | 
| 195 | 
            +
                            self.update();
         | 
| 196 | 
            +
                        }
         | 
| 197 | 
            +
                        return self.visibleItems;
         | 
| 198 | 
            +
                    },
         | 
| 199 | 
            +
                    timeout;
         | 
| 200 | 
            +
             | 
| 201 | 
            +
                    return function() {
         | 
| 202 | 
            +
                        var context = this, args = arguments;
         | 
| 203 | 
            +
                        var later = function() {
         | 
| 204 | 
            +
                            timeout = null;
         | 
| 205 | 
            +
                            func.apply(context, args);
         | 
| 206 | 
            +
                        };
         | 
| 207 | 
            +
                        clearTimeout(timeout);
         | 
| 208 | 
            +
                        timeout = setTimeout(later, 100);
         | 
| 209 | 
            +
                    };
         | 
| 210 | 
            +
                }());
         | 
| 211 | 
            +
            };
         | 
| @@ -0,0 +1,775 @@ | |
| 1 | 
            +
            /*
         | 
| 2 | 
            +
            ListJS Beta 0.2.0
         | 
| 3 | 
            +
            By Jonny Strömberg (www.jonnystromberg.com, www.listjs.com)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            OBS. The API is not frozen. It MAY change!
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            License (MIT)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            Copyright (c) 2011 Jonny Strömberg http://jonnystromberg.com
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            Permission is hereby granted, free of charge, to any person
         | 
| 12 | 
            +
            obtaining a copy of this software and associated documentation
         | 
| 13 | 
            +
            files (the "Software"), to deal in the Software without restriction,
         | 
| 14 | 
            +
            including without limitation the rights to use, copy, modify, merge,
         | 
| 15 | 
            +
            publish, distribute, sublicense, and/or sell copies of the Software,
         | 
| 16 | 
            +
            and to permit persons to whom the Software is furnished to do so,
         | 
| 17 | 
            +
            subject to the following conditions:
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            The above copyright notice and this permission notice shall be
         | 
| 20 | 
            +
            included in all copies or substantial portions of the Software.
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 23 | 
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
         | 
| 24 | 
            +
            OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 25 | 
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
         | 
| 26 | 
            +
            HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
         | 
| 27 | 
            +
            WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
         | 
| 28 | 
            +
            FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
         | 
| 29 | 
            +
            OTHER DEALINGS IN THE SOFTWARE.
         | 
| 30 | 
            +
            */
         | 
| 31 | 
            +
            (function( window, undefined ) {
         | 
| 32 | 
            +
            "use strict";
         | 
| 33 | 
            +
            var document = window.document,
         | 
| 34 | 
            +
            	h;
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            var List = function(id, options, values) {
         | 
| 37 | 
            +
                var self = this,
         | 
| 38 | 
            +
            		templater,
         | 
| 39 | 
            +
            		init,
         | 
| 40 | 
            +
            		initialItems,
         | 
| 41 | 
            +
            		Item,
         | 
| 42 | 
            +
            		Templater,
         | 
| 43 | 
            +
            		sortButtons,
         | 
| 44 | 
            +
            		events = {
         | 
| 45 | 
            +
            		    'updated': []
         | 
| 46 | 
            +
            		};
         | 
| 47 | 
            +
                this.listContainer = (typeof(id) == 'string') ? document.getElementById(id) : id;
         | 
| 48 | 
            +
                // Check if the container exists. If not return instead of breaking the javascript
         | 
| 49 | 
            +
                if (!this.listContainer)
         | 
| 50 | 
            +
                    return;
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                this.items = [];
         | 
| 53 | 
            +
                this.visibleItems = []; // These are the items currently visible
         | 
| 54 | 
            +
                this.matchingItems = []; // These are the items currently matching filters and search, regadlessof visible count
         | 
| 55 | 
            +
                this.searched = false;
         | 
| 56 | 
            +
                this.filtered = false;
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                this.list = null;
         | 
| 59 | 
            +
                this.templateEngines = {};
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                this.page = options.page || 200;
         | 
| 62 | 
            +
                this.i = options.i || 1;
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                init = {
         | 
| 65 | 
            +
                    start: function(values, options) {
         | 
| 66 | 
            +
                        options.plugins = options.plugins || {};
         | 
| 67 | 
            +
                        this.classes(options);
         | 
| 68 | 
            +
                        templater = new Templater(self, options);
         | 
| 69 | 
            +
                        this.callbacks(options);
         | 
| 70 | 
            +
                        this.items.start(values, options);
         | 
| 71 | 
            +
                        self.update();
         | 
| 72 | 
            +
                        this.plugins(options.plugins);
         | 
| 73 | 
            +
                    },
         | 
| 74 | 
            +
                    classes: function(options) {
         | 
| 75 | 
            +
                        options.listClass = options.listClass || 'list';
         | 
| 76 | 
            +
                        options.searchClass = options.searchClass || 'search';
         | 
| 77 | 
            +
                        options.sortClass = options.sortClass || 'sort';
         | 
| 78 | 
            +
                    },
         | 
| 79 | 
            +
                    callbacks: function(options) {
         | 
| 80 | 
            +
                        self.list = h.getByClass(options.listClass, self.listContainer, true);
         | 
| 81 | 
            +
                        h.addEvent(h.getByClass(options.searchClass, self.listContainer), 'keyup', self.search);
         | 
| 82 | 
            +
                        sortButtons = h.getByClass(options.sortClass, self.listContainer);
         | 
| 83 | 
            +
                        h.addEvent(sortButtons, 'click', self.sort);
         | 
| 84 | 
            +
                    },
         | 
| 85 | 
            +
                    items: {
         | 
| 86 | 
            +
                        start: function(values, options) {
         | 
| 87 | 
            +
                            if (options.valueNames) {
         | 
| 88 | 
            +
                                var itemsToIndex = this.get(),
         | 
| 89 | 
            +
                                valueNames = options.valueNames;
         | 
| 90 | 
            +
                                if (options.indexAsync) {
         | 
| 91 | 
            +
                                    this.indexAsync(itemsToIndex, valueNames);
         | 
| 92 | 
            +
                                } else {
         | 
| 93 | 
            +
                                    this.index(itemsToIndex, valueNames);
         | 
| 94 | 
            +
                                }
         | 
| 95 | 
            +
                            }
         | 
| 96 | 
            +
                            if (values !== undefined) {
         | 
| 97 | 
            +
                                self.add(values);
         | 
| 98 | 
            +
                            }
         | 
| 99 | 
            +
                        },
         | 
| 100 | 
            +
                        get: function() {
         | 
| 101 | 
            +
                            // return h.getByClass('item', self.list);
         | 
| 102 | 
            +
                            var nodes = self.list.childNodes,
         | 
| 103 | 
            +
                            items = [];
         | 
| 104 | 
            +
                            for (var i = 0, il = nodes.length; i < il; i++) {
         | 
| 105 | 
            +
                                // Only textnodes have a data attribute
         | 
| 106 | 
            +
                                if (nodes[i].data === undefined) {
         | 
| 107 | 
            +
                                    items.push(nodes[i]);
         | 
| 108 | 
            +
                                }
         | 
| 109 | 
            +
                            }
         | 
| 110 | 
            +
                            return items;
         | 
| 111 | 
            +
                        },
         | 
| 112 | 
            +
                        index: function(itemElements, valueNames) {
         | 
| 113 | 
            +
                            for (var i = 0, il = itemElements.length; i < il; i++) {
         | 
| 114 | 
            +
                                self.items.push(new Item(valueNames, itemElements[i]));
         | 
| 115 | 
            +
                            }
         | 
| 116 | 
            +
                        },
         | 
| 117 | 
            +
                        indexAsync: function(itemElements, valueNames) {
         | 
| 118 | 
            +
                            var itemsToIndex = itemElements.splice(0, 100); // TODO: If < 100 items, what happens in IE etc?
         | 
| 119 | 
            +
                            this.index(itemsToIndex, valueNames);
         | 
| 120 | 
            +
                            if (itemElements.length > 0) {
         | 
| 121 | 
            +
                                setTimeout(function() {
         | 
| 122 | 
            +
                                    init.items.indexAsync(itemElements, valueNames);
         | 
| 123 | 
            +
                                    },
         | 
| 124 | 
            +
                                10);
         | 
| 125 | 
            +
                            } else {
         | 
| 126 | 
            +
                                self.update();
         | 
| 127 | 
            +
                                // TODO: Add indexed callback
         | 
| 128 | 
            +
                            }
         | 
| 129 | 
            +
                        }
         | 
| 130 | 
            +
                    },
         | 
| 131 | 
            +
                    plugins: function(plugins) {
         | 
| 132 | 
            +
                        var locals = {
         | 
| 133 | 
            +
                            templater: templater,
         | 
| 134 | 
            +
                            init: init,
         | 
| 135 | 
            +
                            initialItems: initialItems,
         | 
| 136 | 
            +
                            Item: Item,
         | 
| 137 | 
            +
                            Templater: Templater,
         | 
| 138 | 
            +
                            sortButtons: sortButtons,
         | 
| 139 | 
            +
                            events: events,
         | 
| 140 | 
            +
                            reset: reset
         | 
| 141 | 
            +
                        };
         | 
| 142 | 
            +
                        for (var i = 0; i < plugins.length; i++) {
         | 
| 143 | 
            +
                            plugins[i][1] = plugins[i][1] || {};
         | 
| 144 | 
            +
                            var pluginName = plugins[i][1].name || plugins[i][0];
         | 
| 145 | 
            +
                            self[pluginName] = self.plugins[plugins[i][0]].call(self, locals, plugins[i][1]);
         | 
| 146 | 
            +
                        }
         | 
| 147 | 
            +
                    }
         | 
| 148 | 
            +
                };
         | 
| 149 | 
            +
             | 
| 150 | 
            +
             | 
| 151 | 
            +
                /*
         | 
| 152 | 
            +
                * Add object to list
         | 
| 153 | 
            +
                */
         | 
| 154 | 
            +
                this.add = function(values, callback) {
         | 
| 155 | 
            +
                    if (callback) {
         | 
| 156 | 
            +
                        addAsync(values, callback);
         | 
| 157 | 
            +
                    }
         | 
| 158 | 
            +
                    var added = [],
         | 
| 159 | 
            +
                        notCreate = false;
         | 
| 160 | 
            +
                    if (values[0] === undefined){
         | 
| 161 | 
            +
                        values = [values];
         | 
| 162 | 
            +
                    }
         | 
| 163 | 
            +
                    for (var i = 0, il = values.length; i < il; i++) {
         | 
| 164 | 
            +
                        var item = null;
         | 
| 165 | 
            +
                        if (values[i] instanceof Item) {
         | 
| 166 | 
            +
                            item = values[i];
         | 
| 167 | 
            +
                            item.reload();
         | 
| 168 | 
            +
                        } else {
         | 
| 169 | 
            +
                            notCreate = (self.items.length > self.page) ? true : false;
         | 
| 170 | 
            +
                            item = new Item(values[i], undefined, notCreate);
         | 
| 171 | 
            +
                        }
         | 
| 172 | 
            +
                        self.items.push(item);
         | 
| 173 | 
            +
                        added.push(item);
         | 
| 174 | 
            +
                    }
         | 
| 175 | 
            +
                    self.update();
         | 
| 176 | 
            +
                    return added;
         | 
| 177 | 
            +
                };
         | 
| 178 | 
            +
             | 
| 179 | 
            +
                /*
         | 
| 180 | 
            +
                * Adds items asynchronous to the list, good for adding huge amount of
         | 
| 181 | 
            +
                * data. Defaults to add 100 items a time
         | 
| 182 | 
            +
                */
         | 
| 183 | 
            +
                var addAsync = function(values, callback, items) {
         | 
| 184 | 
            +
                    var valuesToAdd = values.splice(0, 100);
         | 
| 185 | 
            +
                    items = items || [];
         | 
| 186 | 
            +
                    items = items.concat(self.add(valuesToAdd));
         | 
| 187 | 
            +
                    if (values.length > 0) {
         | 
| 188 | 
            +
                        setTimeout(function() {
         | 
| 189 | 
            +
                            addAsync(values, callback, items);
         | 
| 190 | 
            +
                        }, 10);
         | 
| 191 | 
            +
                    } else {
         | 
| 192 | 
            +
                        self.update();
         | 
| 193 | 
            +
                        callback(items);
         | 
| 194 | 
            +
                    }
         | 
| 195 | 
            +
                };
         | 
| 196 | 
            +
             | 
| 197 | 
            +
            	this.show = function(i, page) {
         | 
| 198 | 
            +
            		this.i = i;
         | 
| 199 | 
            +
            		this.page = page;
         | 
| 200 | 
            +
            		self.update();
         | 
| 201 | 
            +
            	};
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                /* Removes object from list.
         | 
| 204 | 
            +
                * Loops through the list and removes objects where
         | 
| 205 | 
            +
                * property "valuename" === value
         | 
| 206 | 
            +
                */
         | 
| 207 | 
            +
                this.remove = function(valueName, value, options) {
         | 
| 208 | 
            +
                    var found = 0;
         | 
| 209 | 
            +
                    for (var i = 0, il = self.items.length; i < il; i++) {
         | 
| 210 | 
            +
                        if (self.items[i].values()[valueName] == value) {
         | 
| 211 | 
            +
                            templater.remove(self.items[i], options);
         | 
| 212 | 
            +
                            self.items.splice(i,1);
         | 
| 213 | 
            +
                            il--;
         | 
| 214 | 
            +
                            found++;
         | 
| 215 | 
            +
                        }
         | 
| 216 | 
            +
                    }
         | 
| 217 | 
            +
                    self.update();
         | 
| 218 | 
            +
                    return found;
         | 
| 219 | 
            +
                };
         | 
| 220 | 
            +
             | 
| 221 | 
            +
                /* Gets the objects in the list which
         | 
| 222 | 
            +
                * property "valueName" === value
         | 
| 223 | 
            +
                */
         | 
| 224 | 
            +
                this.get = function(valueName, value) {
         | 
| 225 | 
            +
                    var matchedItems = [];
         | 
| 226 | 
            +
                    for (var i = 0, il = self.items.length; i < il; i++) {
         | 
| 227 | 
            +
                        var item = self.items[i];
         | 
| 228 | 
            +
                        if (item.values()[valueName] == value) {
         | 
| 229 | 
            +
                            matchedItems.push(item);
         | 
| 230 | 
            +
                        }
         | 
| 231 | 
            +
                    }
         | 
| 232 | 
            +
                    if (matchedItems.length == 0) {
         | 
| 233 | 
            +
                        return null;
         | 
| 234 | 
            +
                    } else if (matchedItems.length == 1) {
         | 
| 235 | 
            +
                        return matchedItems[0];
         | 
| 236 | 
            +
                    } else {
         | 
| 237 | 
            +
                        return matchedItems;
         | 
| 238 | 
            +
                    }
         | 
| 239 | 
            +
                };
         | 
| 240 | 
            +
             | 
| 241 | 
            +
                /* Sorts the list.
         | 
| 242 | 
            +
                * @valueOrEvent Either a JavaScript event object or a valueName
         | 
| 243 | 
            +
                * @sortFunction (optional) Define if natural sorting does not fullfill your needs
         | 
| 244 | 
            +
                */
         | 
| 245 | 
            +
                this.sort = function(valueName, options) {
         | 
| 246 | 
            +
                    var length = self.items.length,
         | 
| 247 | 
            +
                        value = null,
         | 
| 248 | 
            +
                        target = valueName.target || valueName.srcElement, /* IE have srcElement */
         | 
| 249 | 
            +
                        sorting = '',
         | 
| 250 | 
            +
                        isAsc = false,
         | 
| 251 | 
            +
                        asc = 'asc',
         | 
| 252 | 
            +
                        desc = 'desc',
         | 
| 253 | 
            +
                        options = options || {};
         | 
| 254 | 
            +
             | 
| 255 | 
            +
                    if (target === undefined) {
         | 
| 256 | 
            +
                        value = valueName;
         | 
| 257 | 
            +
                        isAsc = options.asc || false;
         | 
| 258 | 
            +
                    } else {
         | 
| 259 | 
            +
                        value = h.getAttribute(target, 'data-sort');
         | 
| 260 | 
            +
                        isAsc = h.hasClass(target, asc) ? false : true;
         | 
| 261 | 
            +
                    }
         | 
| 262 | 
            +
                    for (var i = 0, il = sortButtons.length; i < il; i++) {
         | 
| 263 | 
            +
                        h.removeClass(sortButtons[i], asc);
         | 
| 264 | 
            +
                        h.removeClass(sortButtons[i], desc);
         | 
| 265 | 
            +
                    }
         | 
| 266 | 
            +
                    if (isAsc) {
         | 
| 267 | 
            +
                        if (target !== undefined) {
         | 
| 268 | 
            +
                            h.addClass(target, asc);
         | 
| 269 | 
            +
                        }
         | 
| 270 | 
            +
                        isAsc = true;
         | 
| 271 | 
            +
                    } else {
         | 
| 272 | 
            +
                        if (target !== undefined) {
         | 
| 273 | 
            +
                            h.addClass(target, desc);
         | 
| 274 | 
            +
                        }
         | 
| 275 | 
            +
                        isAsc = false;
         | 
| 276 | 
            +
                    }
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                    if (options.sortFunction) {
         | 
| 279 | 
            +
                        options.sortFunction = options.sortFunction;
         | 
| 280 | 
            +
                    } else {
         | 
| 281 | 
            +
                        options.sortFunction = function(a, b) {
         | 
| 282 | 
            +
                            return h.sorter.alphanum(a.values()[value].toLowerCase(), b.values()[value].toLowerCase(), isAsc);
         | 
| 283 | 
            +
                        };
         | 
| 284 | 
            +
                    }
         | 
| 285 | 
            +
                    self.items.sort(options.sortFunction);
         | 
| 286 | 
            +
                    self.update();
         | 
| 287 | 
            +
                };
         | 
| 288 | 
            +
             | 
| 289 | 
            +
                /*
         | 
| 290 | 
            +
                * Searches the list after values with content "searchStringOrEvent".
         | 
| 291 | 
            +
                * The columns parameter defines if all values should be included in the search,
         | 
| 292 | 
            +
                * defaults to undefined which means "all".
         | 
| 293 | 
            +
                */
         | 
| 294 | 
            +
                this.search = function(searchString, columns) {
         | 
| 295 | 
            +
                    self.i = 1; // Reset paging
         | 
| 296 | 
            +
                    var matching = [],
         | 
| 297 | 
            +
                        found,
         | 
| 298 | 
            +
                        item,
         | 
| 299 | 
            +
                        text,
         | 
| 300 | 
            +
                        values,
         | 
| 301 | 
            +
                        is,
         | 
| 302 | 
            +
                        columns = (columns === undefined) ? self.items[0].values() : columns,
         | 
| 303 | 
            +
                        searchString = (searchString === undefined) ? "" : searchString,
         | 
| 304 | 
            +
                        target = searchString.target || searchString.srcElement; /* IE have srcElement */
         | 
| 305 | 
            +
             | 
| 306 | 
            +
                    searchString = (target === undefined) ? (""+searchString).toLowerCase() : ""+target.value.toLowerCase();
         | 
| 307 | 
            +
                    is = self.items;
         | 
| 308 | 
            +
                    // Escape regular expression characters
         | 
| 309 | 
            +
                    searchString = searchString.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
         | 
| 310 | 
            +
             | 
| 311 | 
            +
                    templater.clear();
         | 
| 312 | 
            +
                    if (searchString === "" ) {
         | 
| 313 | 
            +
                        reset.search();
         | 
| 314 | 
            +
                        self.searched = false;
         | 
| 315 | 
            +
                        self.update();
         | 
| 316 | 
            +
                    } else {
         | 
| 317 | 
            +
                        self.searched = true;
         | 
| 318 | 
            +
             | 
| 319 | 
            +
                        for (var k = 0, kl = is.length; k < kl; k++) {
         | 
| 320 | 
            +
                            found = false;
         | 
| 321 | 
            +
                            item = is[k];
         | 
| 322 | 
            +
                            values = item.values();
         | 
| 323 | 
            +
             | 
| 324 | 
            +
                            for(var j in columns) {
         | 
| 325 | 
            +
                                if(values.hasOwnProperty(j) && columns[j] !== null) {
         | 
| 326 | 
            +
                                    text = (values[j] != null) ? values[j].toString().toLowerCase() : "";
         | 
| 327 | 
            +
                                    if ((searchString !== "") && (text.search(searchString) > -1)) {
         | 
| 328 | 
            +
                                        found = true;
         | 
| 329 | 
            +
                                    }
         | 
| 330 | 
            +
                                }
         | 
| 331 | 
            +
                            }
         | 
| 332 | 
            +
                            if (found) {
         | 
| 333 | 
            +
                                item.found = true;
         | 
| 334 | 
            +
                                matching.push(item);
         | 
| 335 | 
            +
                            } else {
         | 
| 336 | 
            +
                                item.found = false;
         | 
| 337 | 
            +
                            }
         | 
| 338 | 
            +
                        }
         | 
| 339 | 
            +
                        self.update();
         | 
| 340 | 
            +
                    }
         | 
| 341 | 
            +
                    return self.visibleItems;
         | 
| 342 | 
            +
                };
         | 
| 343 | 
            +
             | 
| 344 | 
            +
                /*
         | 
| 345 | 
            +
                * Filters the list. If filterFunction() returns False hides the Item.
         | 
| 346 | 
            +
                * if filterFunction == false are the filter removed
         | 
| 347 | 
            +
                */
         | 
| 348 | 
            +
                this.filter = function(filterFunction) {
         | 
| 349 | 
            +
                    self.i = 1; // Reset paging
         | 
| 350 | 
            +
                    reset.filter();
         | 
| 351 | 
            +
                    if (filterFunction === undefined) {
         | 
| 352 | 
            +
                        self.filtered = false;
         | 
| 353 | 
            +
                    } else {
         | 
| 354 | 
            +
                        self.filtered = true;
         | 
| 355 | 
            +
                        var is = self.items;
         | 
| 356 | 
            +
                        for (var i = 0, il = is.length; i < il; i++) {
         | 
| 357 | 
            +
                            var item = is[i];
         | 
| 358 | 
            +
                            if (filterFunction(item)) {
         | 
| 359 | 
            +
                                item.filtered = true;
         | 
| 360 | 
            +
                            } else {
         | 
| 361 | 
            +
                                item.filtered = false;
         | 
| 362 | 
            +
                            }
         | 
| 363 | 
            +
                        }
         | 
| 364 | 
            +
                    }
         | 
| 365 | 
            +
                    self.update();
         | 
| 366 | 
            +
                    return self.visibleItems;
         | 
| 367 | 
            +
                };
         | 
| 368 | 
            +
             | 
| 369 | 
            +
                /*
         | 
| 370 | 
            +
                * Get size of the list
         | 
| 371 | 
            +
                */
         | 
| 372 | 
            +
                this.size = function() {
         | 
| 373 | 
            +
                    return self.items.length;
         | 
| 374 | 
            +
                };
         | 
| 375 | 
            +
             | 
| 376 | 
            +
                /*
         | 
| 377 | 
            +
                * Removes all items from the list
         | 
| 378 | 
            +
                */
         | 
| 379 | 
            +
                this.clear = function() {
         | 
| 380 | 
            +
                    templater.clear();
         | 
| 381 | 
            +
                    self.items = [];
         | 
| 382 | 
            +
                };
         | 
| 383 | 
            +
             | 
| 384 | 
            +
                this.on = function(event, callback) {
         | 
| 385 | 
            +
                    events[event].push(callback);
         | 
| 386 | 
            +
                };
         | 
| 387 | 
            +
             | 
| 388 | 
            +
                var trigger = function(event) {
         | 
| 389 | 
            +
                    var i = events[event].length;
         | 
| 390 | 
            +
                    while(i--) {
         | 
| 391 | 
            +
                        events[event][i]();
         | 
| 392 | 
            +
                    }
         | 
| 393 | 
            +
                };
         | 
| 394 | 
            +
             | 
| 395 | 
            +
                var reset = {
         | 
| 396 | 
            +
                    filter: function() {
         | 
| 397 | 
            +
                        var is = self.items,
         | 
| 398 | 
            +
                            il = is.length;
         | 
| 399 | 
            +
                        while (il--) {
         | 
| 400 | 
            +
                            is[il].filtered = false;
         | 
| 401 | 
            +
                        }
         | 
| 402 | 
            +
                    },
         | 
| 403 | 
            +
                    search: function() {
         | 
| 404 | 
            +
                        var is = self.items,
         | 
| 405 | 
            +
                            il = is.length;
         | 
| 406 | 
            +
                        while (il--) {
         | 
| 407 | 
            +
                            is[il].found = false;
         | 
| 408 | 
            +
                        }
         | 
| 409 | 
            +
                    }
         | 
| 410 | 
            +
                };
         | 
| 411 | 
            +
             | 
| 412 | 
            +
             | 
| 413 | 
            +
                this.update = function() {
         | 
| 414 | 
            +
                    var is = self.items,
         | 
| 415 | 
            +
            			il = is.length;
         | 
| 416 | 
            +
             | 
| 417 | 
            +
                    self.visibleItems = [];
         | 
| 418 | 
            +
                    self.matchingItems = [];
         | 
| 419 | 
            +
                    templater.clear();
         | 
| 420 | 
            +
                    for (var i = 0; i < il; i++) {
         | 
| 421 | 
            +
                        if (is[i].matching() && ((self.matchingItems.length+1) >= self.i && self.visibleItems.length < self.page)) {
         | 
| 422 | 
            +
                            is[i].show();
         | 
| 423 | 
            +
                            self.visibleItems.push(is[i]);
         | 
| 424 | 
            +
                            self.matchingItems.push(is[i]);
         | 
| 425 | 
            +
            			} else if (is[i].matching()) {
         | 
| 426 | 
            +
                            self.matchingItems.push(is[i]);
         | 
| 427 | 
            +
                            is[i].hide();
         | 
| 428 | 
            +
            			} else {
         | 
| 429 | 
            +
                            is[i].hide();
         | 
| 430 | 
            +
            			}
         | 
| 431 | 
            +
                    }
         | 
| 432 | 
            +
                    trigger('updated');
         | 
| 433 | 
            +
                };
         | 
| 434 | 
            +
             | 
| 435 | 
            +
                Item = function(initValues, element, notCreate) {
         | 
| 436 | 
            +
                    var item = this,
         | 
| 437 | 
            +
                        values = {};
         | 
| 438 | 
            +
             | 
| 439 | 
            +
                    this.found = false; // Show if list.searched == true and this.found == true
         | 
| 440 | 
            +
                    this.filtered = false;// Show if list.filtered == true and this.filtered == true
         | 
| 441 | 
            +
             | 
| 442 | 
            +
                    var init = function(initValues, element, notCreate) {
         | 
| 443 | 
            +
                        if (element === undefined) {
         | 
| 444 | 
            +
                            if (notCreate) {
         | 
| 445 | 
            +
                                item.values(initValues, notCreate);
         | 
| 446 | 
            +
                            } else {
         | 
| 447 | 
            +
                                item.values(initValues);
         | 
| 448 | 
            +
                            }
         | 
| 449 | 
            +
                        } else {
         | 
| 450 | 
            +
                            item.elm = element;
         | 
| 451 | 
            +
                            var values = templater.get(item, initValues);
         | 
| 452 | 
            +
                            item.values(values);
         | 
| 453 | 
            +
                        }
         | 
| 454 | 
            +
                    };
         | 
| 455 | 
            +
                    this.values = function(newValues, notCreate) {
         | 
| 456 | 
            +
                        if (newValues !== undefined) {
         | 
| 457 | 
            +
                            for(var name in newValues) {
         | 
| 458 | 
            +
                                values[name] = newValues[name];
         | 
| 459 | 
            +
                            }
         | 
| 460 | 
            +
                            if (notCreate !== true) {
         | 
| 461 | 
            +
                                templater.set(item, item.values());
         | 
| 462 | 
            +
                            }
         | 
| 463 | 
            +
                        } else {
         | 
| 464 | 
            +
                            return values;
         | 
| 465 | 
            +
                        }
         | 
| 466 | 
            +
                    };
         | 
| 467 | 
            +
                    this.show = function() {
         | 
| 468 | 
            +
                        templater.show(item);
         | 
| 469 | 
            +
                    };
         | 
| 470 | 
            +
                    this.hide = function() {
         | 
| 471 | 
            +
                        templater.hide(item);
         | 
| 472 | 
            +
                    };
         | 
| 473 | 
            +
                    this.matching = function() {
         | 
| 474 | 
            +
                        return (
         | 
| 475 | 
            +
                            (self.filtered && self.searched && item.found && item.filtered) ||
         | 
| 476 | 
            +
                           	(self.filtered && !self.searched && item.filtered) ||
         | 
| 477 | 
            +
                            (!self.filtered && self.searched && item.found) ||
         | 
| 478 | 
            +
                            (!self.filtered && !self.searched)
         | 
| 479 | 
            +
                        );
         | 
| 480 | 
            +
                    };
         | 
| 481 | 
            +
                    this.visible = function() {
         | 
| 482 | 
            +
                        return (item.elm.parentNode) ? true : false;
         | 
| 483 | 
            +
                    };
         | 
| 484 | 
            +
                    init(initValues, element, notCreate);
         | 
| 485 | 
            +
                };
         | 
| 486 | 
            +
             | 
| 487 | 
            +
                /* Templater with different kinds of template engines.
         | 
| 488 | 
            +
                * All engines have these methods
         | 
| 489 | 
            +
                * - reload(item)
         | 
| 490 | 
            +
                * - remove(item)
         | 
| 491 | 
            +
                */
         | 
| 492 | 
            +
                Templater = function(list, settings) {
         | 
| 493 | 
            +
                    if (settings.engine === undefined) {
         | 
| 494 | 
            +
                        settings.engine = "standard";
         | 
| 495 | 
            +
                    } else {
         | 
| 496 | 
            +
                        settings.engine = settings.engine.toLowerCase();
         | 
| 497 | 
            +
                    }
         | 
| 498 | 
            +
                    return new self.constructor.prototype.templateEngines[settings.engine](list, settings);
         | 
| 499 | 
            +
                };
         | 
| 500 | 
            +
             | 
| 501 | 
            +
                init.start(values, options);
         | 
| 502 | 
            +
            };
         | 
| 503 | 
            +
             | 
| 504 | 
            +
            List.prototype.templateEngines = {};
         | 
| 505 | 
            +
            List.prototype.plugins = {};
         | 
| 506 | 
            +
             | 
| 507 | 
            +
            List.prototype.templateEngines.standard = function(list, settings) {
         | 
| 508 | 
            +
                var listSource = h.getByClass(settings.listClass, list.listContainer, true),
         | 
| 509 | 
            +
                    itemSource = getItemSource(settings.item),
         | 
| 510 | 
            +
                    templater = this;
         | 
| 511 | 
            +
             | 
| 512 | 
            +
                function getItemSource(item) {
         | 
| 513 | 
            +
                    if (item === undefined) {
         | 
| 514 | 
            +
                        var nodes = listSource.childNodes,
         | 
| 515 | 
            +
                            items = [];
         | 
| 516 | 
            +
             | 
| 517 | 
            +
                        for (var i = 0, il = nodes.length; i < il; i++) {
         | 
| 518 | 
            +
                            // Only textnodes have a data attribute
         | 
| 519 | 
            +
                            if (nodes[i].data === undefined) {
         | 
| 520 | 
            +
                                return nodes[i];
         | 
| 521 | 
            +
                            }
         | 
| 522 | 
            +
                        }
         | 
| 523 | 
            +
                        return null;
         | 
| 524 | 
            +
                    } else if (item.indexOf("<") !== -1) { // Try create html element of list, do not work for tables!!
         | 
| 525 | 
            +
                        var div = document.createElement('div');
         | 
| 526 | 
            +
                        div.innerHTML = item;
         | 
| 527 | 
            +
                        return div.firstChild;
         | 
| 528 | 
            +
                    } else {
         | 
| 529 | 
            +
                        return document.getElementById(settings.item);
         | 
| 530 | 
            +
                    }
         | 
| 531 | 
            +
                }
         | 
| 532 | 
            +
             | 
| 533 | 
            +
                var ensure = {
         | 
| 534 | 
            +
                    created: function(item) {
         | 
| 535 | 
            +
                        if (item.elm === undefined) {
         | 
| 536 | 
            +
                            templater.create(item);
         | 
| 537 | 
            +
                        }
         | 
| 538 | 
            +
                    }
         | 
| 539 | 
            +
                };
         | 
| 540 | 
            +
             | 
| 541 | 
            +
                /* Get values from element */
         | 
| 542 | 
            +
                this.get = function(item, valueNames) {
         | 
| 543 | 
            +
                    ensure.created(item);
         | 
| 544 | 
            +
                    var values = {};
         | 
| 545 | 
            +
                    for(var i = 0, il = valueNames.length; i < il; i++) {
         | 
| 546 | 
            +
                        var elm = h.getByClass(valueNames[i], item.elm, true);
         | 
| 547 | 
            +
                        values[valueNames[i]] = elm ? elm.innerHTML : "";
         | 
| 548 | 
            +
                    }
         | 
| 549 | 
            +
                    return values;
         | 
| 550 | 
            +
                };
         | 
| 551 | 
            +
             | 
| 552 | 
            +
                /* Sets values at element */
         | 
| 553 | 
            +
                this.set = function(item, values) {
         | 
| 554 | 
            +
                    ensure.created(item);
         | 
| 555 | 
            +
                    for(var v in values) {
         | 
| 556 | 
            +
                        if (values.hasOwnProperty(v)) {
         | 
| 557 | 
            +
                            // TODO speed up if possible
         | 
| 558 | 
            +
                            var elm = h.getByClass(v, item.elm, true);
         | 
| 559 | 
            +
                            if (elm) {
         | 
| 560 | 
            +
                                elm.innerHTML = values[v];
         | 
| 561 | 
            +
                            }
         | 
| 562 | 
            +
                        }
         | 
| 563 | 
            +
                    }
         | 
| 564 | 
            +
                };
         | 
| 565 | 
            +
             | 
| 566 | 
            +
                this.create = function(item) {
         | 
| 567 | 
            +
                    if (item.elm !== undefined) {
         | 
| 568 | 
            +
                        return;
         | 
| 569 | 
            +
                    }
         | 
| 570 | 
            +
                    /* If item source does not exists, use the first item in list as
         | 
| 571 | 
            +
                    source for new items */
         | 
| 572 | 
            +
                    var newItem = itemSource.cloneNode(true);
         | 
| 573 | 
            +
                    newItem.id = "";
         | 
| 574 | 
            +
                    item.elm = newItem;
         | 
| 575 | 
            +
                    templater.set(item, item.values());
         | 
| 576 | 
            +
                };
         | 
| 577 | 
            +
                this.remove = function(item) {
         | 
| 578 | 
            +
                    listSource.removeChild(item.elm);
         | 
| 579 | 
            +
                };
         | 
| 580 | 
            +
                this.show = function(item) {
         | 
| 581 | 
            +
                    ensure.created(item);
         | 
| 582 | 
            +
                    listSource.appendChild(item.elm);
         | 
| 583 | 
            +
                };
         | 
| 584 | 
            +
                this.hide = function(item) {
         | 
| 585 | 
            +
                    if (item.elm !== undefined && item.elm.parentNode === listSource) {
         | 
| 586 | 
            +
                        listSource.removeChild(item.elm);
         | 
| 587 | 
            +
                    }
         | 
| 588 | 
            +
                };
         | 
| 589 | 
            +
                this.clear = function() {
         | 
| 590 | 
            +
                    /* .innerHTML = ''; fucks up IE */
         | 
| 591 | 
            +
                    if (listSource.hasChildNodes()) {
         | 
| 592 | 
            +
                        while (listSource.childNodes.length >= 1)
         | 
| 593 | 
            +
                        {
         | 
| 594 | 
            +
                            listSource.removeChild(listSource.firstChild);
         | 
| 595 | 
            +
                        }
         | 
| 596 | 
            +
                    }
         | 
| 597 | 
            +
                };
         | 
| 598 | 
            +
            };
         | 
| 599 | 
            +
             | 
| 600 | 
            +
             | 
| 601 | 
            +
            /*
         | 
| 602 | 
            +
            * These helper functions are not written by List.js author Jonny (they may have been
         | 
| 603 | 
            +
            * adjusted, thought).
         | 
| 604 | 
            +
            */
         | 
| 605 | 
            +
            h = {
         | 
| 606 | 
            +
                /*
         | 
| 607 | 
            +
                * Cross browser getElementsByClassName, which uses native
         | 
| 608 | 
            +
                * if it exists. Modified version of Dustin Diaz function:
         | 
| 609 | 
            +
                * http://www.dustindiaz.com/getelementsbyclass
         | 
| 610 | 
            +
                */
         | 
| 611 | 
            +
                getByClass: (function() {
         | 
| 612 | 
            +
                    if (document.getElementsByClassName) {
         | 
| 613 | 
            +
                        return function(searchClass,node,single) {
         | 
| 614 | 
            +
                            if (single) {
         | 
| 615 | 
            +
                                return node.getElementsByClassName(searchClass)[0];
         | 
| 616 | 
            +
                            } else {
         | 
| 617 | 
            +
                                return node.getElementsByClassName(searchClass);
         | 
| 618 | 
            +
                            }
         | 
| 619 | 
            +
                        };
         | 
| 620 | 
            +
                    } else {
         | 
| 621 | 
            +
                        return function(searchClass,node,single) {
         | 
| 622 | 
            +
                            var classElements = [],
         | 
| 623 | 
            +
                                tag = '*';
         | 
| 624 | 
            +
                            if (node == null) {
         | 
| 625 | 
            +
                                node = document;
         | 
| 626 | 
            +
                            }
         | 
| 627 | 
            +
                            var els = node.getElementsByTagName(tag);
         | 
| 628 | 
            +
                            var elsLen = els.length;
         | 
| 629 | 
            +
                            var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
         | 
| 630 | 
            +
                            for (var i = 0, j = 0; i < elsLen; i++) {
         | 
| 631 | 
            +
                                if ( pattern.test(els[i].className) ) {
         | 
| 632 | 
            +
                                    if (single) {
         | 
| 633 | 
            +
                                        return els[i];
         | 
| 634 | 
            +
                                    } else {
         | 
| 635 | 
            +
                                        classElements[j] = els[i];
         | 
| 636 | 
            +
                                        j++;
         | 
| 637 | 
            +
                                    }
         | 
| 638 | 
            +
                                }
         | 
| 639 | 
            +
                            }
         | 
| 640 | 
            +
                            return classElements;
         | 
| 641 | 
            +
                        };
         | 
| 642 | 
            +
                    }
         | 
| 643 | 
            +
                })(),
         | 
| 644 | 
            +
                /* (elm, 'event' callback) Source: http://net.tutsplus.com/tutorials/javascript-ajax/javascript-from-null-cross-browser-event-binding/ */
         | 
| 645 | 
            +
                addEvent: (function( window, document ) {
         | 
| 646 | 
            +
                    if ( document.addEventListener ) {
         | 
| 647 | 
            +
                        return function( elem, type, cb ) {
         | 
| 648 | 
            +
                            if ((elem && !(elem instanceof Array) && !elem.length && !h.isNodeList(elem) && (elem.length !== 0)) || elem === window ) {
         | 
| 649 | 
            +
                                elem.addEventListener(type, cb, false );
         | 
| 650 | 
            +
                            } else if ( elem && elem[0] !== undefined ) {
         | 
| 651 | 
            +
                                var len = elem.length;
         | 
| 652 | 
            +
                                for ( var i = 0; i < len; i++ ) {
         | 
| 653 | 
            +
                                    h.addEvent(elem[i], type, cb);
         | 
| 654 | 
            +
                                }
         | 
| 655 | 
            +
                            }
         | 
| 656 | 
            +
                        };
         | 
| 657 | 
            +
                    }
         | 
| 658 | 
            +
                    else if ( document.attachEvent ) {
         | 
| 659 | 
            +
                        return function ( elem, type, cb ) {
         | 
| 660 | 
            +
                            if ((elem && !(elem instanceof Array) && !elem.length && !h.isNodeList(elem) && (elem.length !== 0)) || elem === window ) {
         | 
| 661 | 
            +
                                elem.attachEvent( 'on' + type, function() { return cb.call(elem, window.event); } );
         | 
| 662 | 
            +
                            } else if ( elem && elem[0] !== undefined ) {
         | 
| 663 | 
            +
                                var len = elem.length;
         | 
| 664 | 
            +
                                for ( var i = 0; i < len; i++ ) {
         | 
| 665 | 
            +
                                    h.addEvent( elem[i], type, cb );
         | 
| 666 | 
            +
                                }
         | 
| 667 | 
            +
                            }
         | 
| 668 | 
            +
                        };
         | 
| 669 | 
            +
                    }
         | 
| 670 | 
            +
                })(this, document),
         | 
| 671 | 
            +
                /* (elm, attribute) Source: http://stackoverflow.com/questions/3755227/cross-browser-javascript-getattribute-method */
         | 
| 672 | 
            +
                getAttribute: function(ele, attr) {
         | 
| 673 | 
            +
                    var result = (ele.getAttribute && ele.getAttribute(attr)) || null;
         | 
| 674 | 
            +
                    if( !result ) {
         | 
| 675 | 
            +
                        var attrs = ele.attributes;
         | 
| 676 | 
            +
                        var length = attrs.length;
         | 
| 677 | 
            +
                        for(var i = 0; i < length; i++) {
         | 
| 678 | 
            +
                            if (attr[i] !== undefined) {
         | 
| 679 | 
            +
                                if(attr[i].nodeName === attr) {
         | 
| 680 | 
            +
                                    result = attr[i].nodeValue;
         | 
| 681 | 
            +
                                }
         | 
| 682 | 
            +
                            }
         | 
| 683 | 
            +
                        }
         | 
| 684 | 
            +
                    }
         | 
| 685 | 
            +
                    return result;
         | 
| 686 | 
            +
                },
         | 
| 687 | 
            +
                /* http://stackoverflow.com/questions/7238177/detect-htmlcollection-nodelist-in-javascript */
         | 
| 688 | 
            +
                isNodeList: function(nodes) {
         | 
| 689 | 
            +
                    var result = Object.prototype.toString.call(nodes);
         | 
| 690 | 
            +
                    if (typeof nodes === 'object' && /^\[object (HTMLCollection|NodeList|Object)\]$/.test(result) && (nodes.length == 0 || (typeof nodes[0] === "object" && nodes[0].nodeType > 0))) {
         | 
| 691 | 
            +
                        return true;
         | 
| 692 | 
            +
                    }
         | 
| 693 | 
            +
                    return false;
         | 
| 694 | 
            +
                },
         | 
| 695 | 
            +
                hasClass: function(ele, classN) {
         | 
| 696 | 
            +
                    var classes = this.getAttribute(ele, 'class') || this.getAttribute(ele, 'className') || "";
         | 
| 697 | 
            +
                    return (classes.search(classN) > -1);
         | 
| 698 | 
            +
                },
         | 
| 699 | 
            +
                addClass: function(ele, classN) {
         | 
| 700 | 
            +
                    if (!this.hasClass(ele, classN)) {
         | 
| 701 | 
            +
                        var classes = this.getAttribute(ele, 'class') || this.getAttribute(ele, 'className') || "";
         | 
| 702 | 
            +
                        classes = classes + ' ' + classN + ' ';
         | 
| 703 | 
            +
                        classes = classes.replace(/\s{2,}/g, ' ');
         | 
| 704 | 
            +
                        ele.setAttribute('class', classes);
         | 
| 705 | 
            +
                    }
         | 
| 706 | 
            +
                },
         | 
| 707 | 
            +
                removeClass: function(ele, classN) {
         | 
| 708 | 
            +
                    if (this.hasClass(ele, classN)) {
         | 
| 709 | 
            +
                        var classes = this.getAttribute(ele, 'class') || this.getAttribute(ele, 'className') || "";
         | 
| 710 | 
            +
                        classes = classes.replace(classN, '');
         | 
| 711 | 
            +
                        ele.setAttribute('class', classes);
         | 
| 712 | 
            +
                    }
         | 
| 713 | 
            +
                },
         | 
| 714 | 
            +
                /*
         | 
| 715 | 
            +
                * The sort function. From http://my.opera.com/GreyWyvern/blog/show.dml/1671288
         | 
| 716 | 
            +
                */
         | 
| 717 | 
            +
                sorter: {
         | 
| 718 | 
            +
                    alphanum: function(a,b,asc) {
         | 
| 719 | 
            +
                        if (a === undefined || a === null) {
         | 
| 720 | 
            +
                            a = "";
         | 
| 721 | 
            +
                        }
         | 
| 722 | 
            +
                        if (b === undefined || b === null) {
         | 
| 723 | 
            +
                            b = "";
         | 
| 724 | 
            +
                        }
         | 
| 725 | 
            +
                        a = a.toString().replace(/&(lt|gt);/g, function (strMatch, p1){
         | 
| 726 | 
            +
                            return (p1 == "lt")? "<" : ">";
         | 
| 727 | 
            +
                        });
         | 
| 728 | 
            +
                        a = a.replace(/<\/?[^>]+(>|$)/g, "");
         | 
| 729 | 
            +
             | 
| 730 | 
            +
                        b = b.toString().replace(/&(lt|gt);/g, function (strMatch, p1){
         | 
| 731 | 
            +
                            return (p1 == "lt")? "<" : ">";
         | 
| 732 | 
            +
                        });
         | 
| 733 | 
            +
                        b = b.replace(/<\/?[^>]+(>|$)/g, "");
         | 
| 734 | 
            +
                        var aa = this.chunkify(a);
         | 
| 735 | 
            +
                        var bb = this.chunkify(b);
         | 
| 736 | 
            +
             | 
| 737 | 
            +
                        for (var x = 0; aa[x] && bb[x]; x++) {
         | 
| 738 | 
            +
                            if (aa[x] !== bb[x]) {
         | 
| 739 | 
            +
                                var c = Number(aa[x]), d = Number(bb[x]);
         | 
| 740 | 
            +
                                if (asc) {
         | 
| 741 | 
            +
                                    if (c == aa[x] && d == bb[x]) {
         | 
| 742 | 
            +
                                        return c - d;
         | 
| 743 | 
            +
                                    } else {
         | 
| 744 | 
            +
                                        return (aa[x] > bb[x]) ? 1 : -1;
         | 
| 745 | 
            +
                                    }
         | 
| 746 | 
            +
                                } else {
         | 
| 747 | 
            +
                                    if (c == aa[x] && d == bb[x]) {
         | 
| 748 | 
            +
                                        return d-c;//c - d;
         | 
| 749 | 
            +
                                    } else {
         | 
| 750 | 
            +
                                        return (aa[x] > bb[x]) ? -1 : 1; //(aa[x] > bb[x]) ? 1 : -1;
         | 
| 751 | 
            +
                                    }
         | 
| 752 | 
            +
                                }
         | 
| 753 | 
            +
                            }
         | 
| 754 | 
            +
                        }
         | 
| 755 | 
            +
                        return aa.length - bb.length;
         | 
| 756 | 
            +
                    },
         | 
| 757 | 
            +
                    chunkify: function(t) {
         | 
| 758 | 
            +
                        var tz = [], x = 0, y = -1, n = 0, i, j;
         | 
| 759 | 
            +
             | 
| 760 | 
            +
                        while (i = (j = t.charAt(x++)).charCodeAt(0)) {
         | 
| 761 | 
            +
                            var m = (i == 45 || i == 46 || (i >=48 && i <= 57));
         | 
| 762 | 
            +
                            if (m !== n) {
         | 
| 763 | 
            +
                                tz[++y] = "";
         | 
| 764 | 
            +
                                n = m;
         | 
| 765 | 
            +
                            }
         | 
| 766 | 
            +
                            tz[y] += j;
         | 
| 767 | 
            +
                        }
         | 
| 768 | 
            +
                        return tz;
         | 
| 769 | 
            +
                    }
         | 
| 770 | 
            +
                }
         | 
| 771 | 
            +
            };
         | 
| 772 | 
            +
             | 
| 773 | 
            +
            window.List = List;
         | 
| 774 | 
            +
            window.ListJsHelpers = h;
         | 
| 775 | 
            +
            })(window);
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            (function(a,b){"use strict";var c=a.document,d;var e=function(a,e,f){var g=this,i,j,k,l,m,n,o={updated:[]};this.listContainer=typeof a=="string"?c.getElementById(a):a;if(!this.listContainer)return;this.items=[];this.visibleItems=[];this.matchingItems=[];this.searched=false;this.filtered=false;this.list=null;this.templateEngines={};this.page=e.page||200;this.i=e.i||1;j={start:function(a,b){b.plugins=b.plugins||{};this.classes(b);i=new m(g,b);this.callbacks(b);this.items.start(a,b);g.update();this.plugins(b.plugins)},classes:function(a){a.listClass=a.listClass||"list";a.searchClass=a.searchClass||"search";a.sortClass=a.sortClass||"sort"},callbacks:function(a){g.list=d.getByClass(a.listClass,g.listContainer,true);d.addEvent(d.getByClass(a.searchClass,g.listContainer),"keyup",g.search);n=d.getByClass(a.sortClass,g.listContainer);d.addEvent(n,"click",g.sort)},items:{start:function(a,c){if(c.valueNames){var d=this.get(),e=c.valueNames;if(c.indexAsync){this.indexAsync(d,e)}else{this.index(d,e)}}if(a!==b){g.add(a)}},get:function(){var a=g.list.childNodes,c=[];for(var d=0,e=a.length;d<e;d++){if(a[d].data===b){c.push(a[d])}}return c},index:function(a,b){for(var c=0,d=a.length;c<d;c++){g.items.push(new l(b,a[c]))}},indexAsync:function(a,b){var c=a.splice(0,100);this.index(c,b);if(a.length>0){setTimeout(function(){j.items.indexAsync(a,b)},10)}else{g.update()}}},plugins:function(a){var b={templater:i,init:j,initialItems:k,Item:l,Templater:m,sortButtons:n,events:o,reset:r};for(var c=0;c<a.length;c++){a[c][1]=a[c][1]||{};var d=a[c][1].name||a[c][0];g[d]=g.plugins[a[c][0]].call(g,b,a[c][1])}}};this.add=function(a,c){if(c){p(a,c)}var d=[],e=false;if(a[0]===b){a=[a]}for(var f=0,h=a.length;f<h;f++){var i=null;if(a[f]instanceof l){i=a[f];i.reload()}else{e=g.items.length>g.page?true:false;i=new l(a[f],b,e)}g.items.push(i);d.push(i)}g.update();return d};var p=function(a,b,c){var d=a.splice(0,100);c=c||[];c=c.concat(g.add(d));if(a.length>0){setTimeout(function(){p(a,b,c)},10)}else{g.update();b(c)}};this.show=function(a,b){this.i=a;this.page=b;g.update()};this.remove=function(a,b,c){var d=0;for(var e=0,f=g.items.length;e<f;e++){if(g.items[e].values()[a]==b){i.remove(g.items[e],c);g.items.splice(e,1);f--;d++}}g.update();return d};this.get=function(a,b){var c=[];for(var d=0,e=g.items.length;d<e;d++){var f=g.items[d];if(f.values()[a]==b){c.push(f)}}if(c.length==0){return null}else if(c.length==1){return c[0]}else{return c}};this.sort=function(a,c){var e=g.items.length,f=null,i=a.target||a.srcElement,j="",k=false,l="asc",m="desc",c=c||{};if(i===b){f=a;k=c.asc||false}else{f=d.getAttribute(i,"data-sort");k=d.hasClass(i,l)?false:true}for(var o=0,p=n.length;o<p;o++){d.removeClass(n[o],l);d.removeClass(n[o],m)}if(k){if(i!==b){d.addClass(i,l)}k=true}else{if(i!==b){d.addClass(i,m)}k=false}if(c.sortFunction){c.sortFunction=c.sortFunction}else{c.sortFunction=function(a,b){return d.sorter.alphanum(a.values()[f].toLowerCase(),b.values()[f].toLowerCase(),k)}}g.items.sort(c.sortFunction);g.update()};this.search=function(a,c){g.i=1;var d=[],e,f,h,j,k,c=c===b?g.items[0].values():c,a=a===b?"":a,l=a.target||a.srcElement;a=l===b?(""+a).toLowerCase():""+l.value.toLowerCase();k=g.items;a=a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&");i.clear();if(a===""){r.search();g.searched=false;g.update()}else{g.searched=true;for(var m=0,n=k.length;m<n;m++){e=false;f=k[m];j=f.values();for(var o in c){if(j.hasOwnProperty(o)&&c[o]!==null){h=j[o]!=null?j[o].toString().toLowerCase():"";if(a!==""&&h.search(a)>-1){e=true}}}if(e){f.found=true;d.push(f)}else{f.found=false}}g.update()}return g.visibleItems};this.filter=function(a){g.i=1;r.filter();if(a===b){g.filtered=false}else{g.filtered=true;var c=g.items;for(var d=0,e=c.length;d<e;d++){var f=c[d];if(a(f)){f.filtered=true}else{f.filtered=false}}}g.update();return g.visibleItems};this.size=function(){return g.items.length};this.clear=function(){i.clear();g.items=[]};this.on=function(a,b){o[a].push(b)};var q=function(a){var b=o[a].length;while(b--){o[a][b]()}};var r={filter:function(){var a=g.items,b=a.length;while(b--){a[b].filtered=false}},search:function(){var a=g.items,b=a.length;while(b--){a[b].found=false}}};this.update=function(){var a=g.items,b=a.length;g.visibleItems=[];g.matchingItems=[];i.clear();for(var c=0;c<b;c++){if(a[c].matching()&&g.matchingItems.length+1>=g.i&&g.visibleItems.length<g.page){a[c].show();g.visibleItems.push(a[c]);g.matchingItems.push(a[c])}else if(a[c].matching()){g.matchingItems.push(a[c]);a[c].hide()}else{a[c].hide()}}q("updated")};l=function(a,c,d){var e=this,f={};this.found=false;this.filtered=false;var h=function(a,c,d){if(c===b){if(d){e.values(a,d)}else{e.values(a)}}else{e.elm=c;var f=i.get(e,a);e.values(f)}};this.values=function(a,c){if(a!==b){for(var d in a){f[d]=a[d]}if(c!==true){i.set(e,e.values())}}else{return f}};this.show=function(){i.show(e)};this.hide=function(){i.hide(e)};this.matching=function(){return g.filtered&&g.searched&&e.found&&e.filtered||g.filtered&&!g.searched&&e.filtered||!g.filtered&&g.searched&&e.found||!g.filtered&&!g.searched};this.visible=function(){return e.elm.parentNode?true:false};h(a,c,d)};m=function(a,c){if(c.engine===b){c.engine="standard"}else{c.engine=c.engine.toLowerCase()}return new g.constructor.prototype.templateEngines[c.engine](a,c)};j.start(f,e)};e.prototype.templateEngines={};e.prototype.plugins={};e.prototype.templateEngines.standard=function(a,e){function j(a){if(a===b){var d=f.childNodes,g=[];for(var h=0,i=d.length;h<i;h++){if(d[h].data===b){return d[h]}}return null}else if(a.indexOf("<")!==-1){var j=c.createElement("div");j.innerHTML=a;return j.firstChild}else{return c.getElementById(e.item)}}var f=d.getByClass(e.listClass,a.listContainer,true),g=j(e.item),i=this;var k={created:function(a){if(a.elm===b){i.create(a)}}};this.get=function(a,b){k.created(a);var c={};for(var e=0,f=b.length;e<f;e++){var g=d.getByClass(b[e],a.elm,true);c[b[e]]=g?g.innerHTML:""}return c};this.set=function(a,b){k.created(a);for(var c in b){if(b.hasOwnProperty(c)){var e=d.getByClass(c,a.elm,true);if(e){e.innerHTML=b[c]}}}};this.create=function(a){if(a.elm!==b){return}var c=g.cloneNode(true);c.id="";a.elm=c;i.set(a,a.values())};this.remove=function(a){f.removeChild(a.elm)};this.show=function(a){k.created(a);f.appendChild(a.elm)};this.hide=function(a){if(a.elm!==b&&a.elm.parentNode===f){f.removeChild(a.elm)}};this.clear=function(){if(f.hasChildNodes()){while(f.childNodes.length>=1){f.removeChild(f.firstChild)}}}};d={getByClass:function(){if(c.getElementsByClassName){return function(a,b,c){if(c){return b.getElementsByClassName(a)[0]}else{return b.getElementsByClassName(a)}}}else{return function(a,b,d){var e=[],f="*";if(b==null){b=c}var g=b.getElementsByTagName(f);var h=g.length;var i=new RegExp("(^|\\s)"+a+"(\\s|$)");for(var j=0,k=0;j<h;j++){if(i.test(g[j].className)){if(d){return g[j]}else{e[k]=g[j];k++}}}return e}}}(),addEvent:function(a,c){if(c.addEventListener){return function(c,e,f){if(c&&!(c instanceof Array)&&!c.length&&!d.isNodeList(c)&&c.length!==0||c===a){c.addEventListener(e,f,false)}else if(c&&c[0]!==b){var g=c.length;for(var i=0;i<g;i++){d.addEvent(c[i],e,f)}}}}else if(c.attachEvent){return function(c,e,f){if(c&&!(c instanceof Array)&&!c.length&&!d.isNodeList(c)&&c.length!==0||c===a){c.attachEvent("on"+e,function(){return f.call(c,a.event)})}else if(c&&c[0]!==b){var g=c.length;for(var i=0;i<g;i++){d.addEvent(c[i],e,f)}}}}}(this,c),getAttribute:function(a,c){var d=a.getAttribute&&a.getAttribute(c)||null;if(!d){var e=a.attributes;var f=e.length;for(var g=0;g<f;g++){if(c[g]!==b){if(c[g].nodeName===c){d=c[g].nodeValue}}}}return d},isNodeList:function(a){var b=Object.prototype.toString.call(a);if(typeof a==="object"&&/^\[object (HTMLCollection|NodeList|Object)\]$/.test(b)&&(a.length==0||typeof a[0]==="object"&&a[0].nodeType>0)){return true}return false},hasClass:function(a,b){var c=this.getAttribute(a,"class")||this.getAttribute(a,"className")||"";return c.search(b)>-1},addClass:function(a,b){if(!this.hasClass(a,b)){var c=this.getAttribute(a,"class")||this.getAttribute(a,"className")||"";c=c+" "+b+" ";c=c.replace(/\s{2,}/g," ");a.setAttribute("class",c)}},removeClass:function(a,b){if(this.hasClass(a,b)){var c=this.getAttribute(a,"class")||this.getAttribute(a,"className")||"";c=c.replace(b,"");a.setAttribute("class",c)}},sorter:{alphanum:function(a,c,d){if(a===b||a===null){a=""}if(c===b||c===null){c=""}a=a.toString().replace(/&(lt|gt);/g,function(a,b){return b=="lt"?"<":">"});a=a.replace(/<\/?[^>]+(>|$)/g,"");c=c.toString().replace(/&(lt|gt);/g,function(a,b){return b=="lt"?"<":">"});c=c.replace(/<\/?[^>]+(>|$)/g,"");var e=this.chunkify(a);var f=this.chunkify(c);for(var g=0;e[g]&&f[g];g++){if(e[g]!==f[g]){var h=Number(e[g]),i=Number(f[g]);if(d){if(h==e[g]&&i==f[g]){return h-i}else{return e[g]>f[g]?1:-1}}else{if(h==e[g]&&i==f[g]){return i-h}else{return e[g]>f[g]?-1:1}}}}return e.length-f.length},chunkify:function(a){var b=[],c=0,d=-1,e=0,f,g;while(f=(g=a.charAt(c++)).charCodeAt(0)){var h=f==45||f==46||f>=48&&f<=57;if(h!==e){b[++d]="";e=h}b[d]+=g}return b}}};a.List=e;a.ListJsHelpers=d})(window)
         | 
| @@ -0,0 +1,86 @@ | |
| 1 | 
            +
            List.prototype.plugins.paging = function(locals, options) {
         | 
| 2 | 
            +
                var list = this;
         | 
| 3 | 
            +
                var pagingList;
         | 
| 4 | 
            +
                var init = function() {
         | 
| 5 | 
            +
                    options = options || {};
         | 
| 6 | 
            +
                    pagingList = new List(list.listContainer.id, {
         | 
| 7 | 
            +
                        listClass: options.pagingClass || 'paging',
         | 
| 8 | 
            +
                        item: "<li><div class='page'></div></li>", // Have to contain something, can't set valueName at root element
         | 
| 9 | 
            +
                        valueNames: ['page', 'dotted'],
         | 
| 10 | 
            +
                        searchClass: 'nosearchclass',
         | 
| 11 | 
            +
                        sortClass: 'nosortclass'
         | 
| 12 | 
            +
                    });
         | 
| 13 | 
            +
                    list.on('updated', refresh);
         | 
| 14 | 
            +
                    refresh();
         | 
| 15 | 
            +
                };
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                var refresh = function() {
         | 
| 18 | 
            +
                    var l = list.matchingItems.length,
         | 
| 19 | 
            +
                        index = list.i,
         | 
| 20 | 
            +
                        page = list.page,
         | 
| 21 | 
            +
                        pages = Math.ceil(l / page),
         | 
| 22 | 
            +
                        currentPage = Math.ceil((index / page)),
         | 
| 23 | 
            +
                        innerWindow = options.innerWindow || 2,
         | 
| 24 | 
            +
                        left = options.left || options.outerWindow || 0,
         | 
| 25 | 
            +
                        right = options.right || options.outerWindow || 0,
         | 
| 26 | 
            +
                        right = pages - right;
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    pagingList.clear();
         | 
| 29 | 
            +
                    for (var i = 1; i <= pages; i++) {
         | 
| 30 | 
            +
                        var className = (currentPage === i) ? "active" : "";
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                        //console.log(i, left, right, currentPage, (currentPage - innerWindow), (currentPage + innerWindow));
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                        if (is.number(i, left, right, currentPage, innerWindow)) {
         | 
| 35 | 
            +
                            var item = pagingList.add({
         | 
| 36 | 
            +
                                page: "<a class='"+className+"' href='javascript:function Z(){Z=\"\"}Z()'>"+(i)+"</a>",
         | 
| 37 | 
            +
                                dotted: false
         | 
| 38 | 
            +
                            })[0];
         | 
| 39 | 
            +
                            addEvent(item.elm, i, page);
         | 
| 40 | 
            +
                        } else if (is.dotted(i, left, right, currentPage, innerWindow, pagingList.size())) {
         | 
| 41 | 
            +
                            pagingList.add({
         | 
| 42 | 
            +
                                page: "...",
         | 
| 43 | 
            +
                                dotted: true
         | 
| 44 | 
            +
                            });
         | 
| 45 | 
            +
                        }
         | 
| 46 | 
            +
                    }
         | 
| 47 | 
            +
                };
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                var is = {
         | 
| 50 | 
            +
                    number: function(i, left, right, currentPage, innerWindow) {
         | 
| 51 | 
            +
                       return this.left(i, left) || this.right(i, right) || this.innerWindow(i, currentPage, innerWindow);
         | 
| 52 | 
            +
                    },
         | 
| 53 | 
            +
                    left: function(i, left) {
         | 
| 54 | 
            +
                        return (i <= left);
         | 
| 55 | 
            +
                    },
         | 
| 56 | 
            +
                    right: function(i, right) {
         | 
| 57 | 
            +
                        return (i > right);
         | 
| 58 | 
            +
                    },
         | 
| 59 | 
            +
                    innerWindow: function(i, currentPage, innerWindow) {
         | 
| 60 | 
            +
                        return ( i >= (currentPage - innerWindow) && i <= (currentPage + innerWindow));
         | 
| 61 | 
            +
                    },
         | 
| 62 | 
            +
                    dotted: function(i, left, right, currentPage, innerWindow, currentPageItem) {
         | 
| 63 | 
            +
                        return this.dottedLeft(i, left, right, currentPage, innerWindow)
         | 
| 64 | 
            +
                        || (this.dottedRight(i, left, right, currentPage, innerWindow, currentPageItem));
         | 
| 65 | 
            +
                    },
         | 
| 66 | 
            +
                    dottedLeft: function(i, left, right, currentPage, innerWindow) {
         | 
| 67 | 
            +
                        return ((i == (left + 1)) && !this.innerWindow(i, currentPage, innerWindow) && !this.right(i, right))
         | 
| 68 | 
            +
                    },
         | 
| 69 | 
            +
                    dottedRight: function(i, left, right, currentPage, innerWindow, currentPageItem) {
         | 
| 70 | 
            +
                        if (pagingList.items[currentPageItem-1].values().dotted) {
         | 
| 71 | 
            +
                            return false
         | 
| 72 | 
            +
                        } else {
         | 
| 73 | 
            +
                            return ((i == (right)) && !this.innerWindow(i, currentPage, innerWindow) && !this.right(i, right))
         | 
| 74 | 
            +
                        }
         | 
| 75 | 
            +
                    }
         | 
| 76 | 
            +
                };
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                var addEvent = function(elm, i, page) {
         | 
| 79 | 
            +
                   ListJsHelpers.addEvent(elm, 'click', function() {
         | 
| 80 | 
            +
                       list.show((i-1)*page + 1, page);
         | 
| 81 | 
            +
                   });
         | 
| 82 | 
            +
                };
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                init();
         | 
| 85 | 
            +
                return this;
         | 
| 86 | 
            +
            };
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,74 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: rails-assets-listjs
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.2.0.beta.4
         | 
| 5 | 
            +
              prerelease: 6
         | 
| 6 | 
            +
            platform: ruby
         | 
| 7 | 
            +
            authors:
         | 
| 8 | 
            +
            - Thomas Klemm
         | 
| 9 | 
            +
            autorequire: 
         | 
| 10 | 
            +
            bindir: bin
         | 
| 11 | 
            +
            cert_chain: []
         | 
| 12 | 
            +
            date: 2012-09-01 00:00:00.000000000 Z
         | 
| 13 | 
            +
            dependencies:
         | 
| 14 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 15 | 
            +
              name: railties
         | 
| 16 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 17 | 
            +
                none: false
         | 
| 18 | 
            +
                requirements:
         | 
| 19 | 
            +
                - - ! '>='
         | 
| 20 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 21 | 
            +
                    version: '3.1'
         | 
| 22 | 
            +
              type: :runtime
         | 
| 23 | 
            +
              prerelease: false
         | 
| 24 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 25 | 
            +
                none: false
         | 
| 26 | 
            +
                requirements:
         | 
| 27 | 
            +
                - - ! '>='
         | 
| 28 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 29 | 
            +
                    version: '3.1'
         | 
| 30 | 
            +
            description: List.js - packaged by RailsAssets for the Rails Asset Pipeline
         | 
| 31 | 
            +
            email:
         | 
| 32 | 
            +
            - github@tklemm.eu
         | 
| 33 | 
            +
            executables: []
         | 
| 34 | 
            +
            extensions: []
         | 
| 35 | 
            +
            extra_rdoc_files: []
         | 
| 36 | 
            +
            files:
         | 
| 37 | 
            +
            - .gitignore
         | 
| 38 | 
            +
            - Gemfile
         | 
| 39 | 
            +
            - LICENSE.txt
         | 
| 40 | 
            +
            - README.md
         | 
| 41 | 
            +
            - Rakefile
         | 
| 42 | 
            +
            - lib/rails-assets-listjs.rb
         | 
| 43 | 
            +
            - lib/rails-assets-listjs/version.rb
         | 
| 44 | 
            +
            - rails-assets-listjs.gemspec
         | 
| 45 | 
            +
            - vendor/assets/javascripts/list.fuzzySearch.js
         | 
| 46 | 
            +
            - vendor/assets/javascripts/list.js
         | 
| 47 | 
            +
            - vendor/assets/javascripts/list.min.js
         | 
| 48 | 
            +
            - vendor/assets/javascripts/list.paging.js
         | 
| 49 | 
            +
            homepage: http://www.railsassets.com
         | 
| 50 | 
            +
            licenses: []
         | 
| 51 | 
            +
            post_install_message: 
         | 
| 52 | 
            +
            rdoc_options: []
         | 
| 53 | 
            +
            require_paths:
         | 
| 54 | 
            +
            - lib
         | 
| 55 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 56 | 
            +
              none: false
         | 
| 57 | 
            +
              requirements:
         | 
| 58 | 
            +
              - - ! '>='
         | 
| 59 | 
            +
                - !ruby/object:Gem::Version
         | 
| 60 | 
            +
                  version: '0'
         | 
| 61 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 62 | 
            +
              none: false
         | 
| 63 | 
            +
              requirements:
         | 
| 64 | 
            +
              - - ! '>'
         | 
| 65 | 
            +
                - !ruby/object:Gem::Version
         | 
| 66 | 
            +
                  version: 1.3.1
         | 
| 67 | 
            +
            requirements: []
         | 
| 68 | 
            +
            rubyforge_project: 
         | 
| 69 | 
            +
            rubygems_version: 1.8.23
         | 
| 70 | 
            +
            signing_key: 
         | 
| 71 | 
            +
            specification_version: 3
         | 
| 72 | 
            +
            summary: List.js - packaged by RailsAssets for the Rails Asset Pipeline
         | 
| 73 | 
            +
            test_files: []
         | 
| 74 | 
            +
            has_rdoc: 
         |