[extensions-web: 20/30] js: Add a basic sorting UI



commit 50170fff5119e2ffc4d2a5d02e04f5b37f76ef7a
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Mon Jan 2 15:41:20 2012 -0500

    js: Add a basic sorting UI
    
    Filtering comes later

 sweettooth/static/css/sweettooth.css   |   68 +++++++++++++++++++++++++
 sweettooth/static/js/filter.js         |   86 ++++++++++++++++++++++++++++++++
 sweettooth/static/js/hashparamutils.js |   41 +++++++++++++++
 sweettooth/static/js/main.js           |    3 +-
 sweettooth/static/js/paginator.js      |   42 ++--------------
 5 files changed, 202 insertions(+), 38 deletions(-)
---
diff --git a/sweettooth/static/css/sweettooth.css b/sweettooth/static/css/sweettooth.css
index e1a2635..0ea926c 100644
--- a/sweettooth/static/css/sweettooth.css
+++ b/sweettooth/static/css/sweettooth.css
@@ -179,6 +179,74 @@ hr.bottom_shadow {
     text-align: center;
 }
 
+/* Filtering and Sorting UI */
+/* ==================================================================== */
+
+a.filter-ui-link {
+    float: right;
+    border-radius: 4px;
+    font-size: 0.8em;
+    line-height: 2.2em;
+    margin-top: -2.2em;
+    padding: 0 1em;
+    cursor: pointer;
+
+    text-decoration: none;
+    color: #204a87;
+
+    -webkit-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
+    -moz-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
+    -ms-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
+    -o-transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
+    transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
+}
+
+.filter-ui-link.selected {
+    background-color: #fff;
+    text-decoration: none;
+    color: #222;
+}
+
+.filter-ui {
+    background-color: #fff;
+    position: absolute;
+
+    -webkit-transition: visiblity 0.2s ease-in-out;
+    border-radius: 0 0 4px 4px;
+    border: 1px solid #BABDB6;
+    border-top: none;
+    padding: 1em;
+    box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+
+    box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
+}
+
+.filter-ui h4 {
+    margin: 0;
+}
+
+.filter-sort-ui-sort-link {
+    text-decoration: none;
+    color: #444;
+    list-style-position: inside;
+    list-style-type: none;
+    padding: .5em 0 .5em 1em;
+    cursor: pointer;
+    margin-left: 0;
+    padding-left: 2em;
+}
+
+.filter-sort-ui-sort-link.selected {
+    list-style-type: disc;
+    padding-left: 1em;
+}
+
+.filter-sort-ui-sort-link:hover {
+    background-color: #e5e5e0;
+}
+
 /* Extension view */
 /* ==================================================================== */
 
diff --git a/sweettooth/static/js/filter.js b/sweettooth/static/js/filter.js
new file mode 100644
index 0000000..62bf5f3
--- /dev/null
+++ b/sweettooth/static/js/filter.js
@@ -0,0 +1,86 @@
+"use strict";
+
+require(['jquery', 'hashparamutils'], function($, hashparamutils) {
+
+    function makeLink(name, value, text) {
+        return $('<li>', {'class': 'filter-sort-ui-sort-link'}).
+            text(text).
+            click(function() {
+                var hp = hashparamutils.getHashParams();
+                hp[name] = value;
+                hashparamutils.setHashParams(hp);
+            });
+    }
+
+    var sortCriteria = {
+        'name': "Name",
+        'recent': "Recent",
+        'downloads': "Downloads",
+        'popularity': "Popularity"
+    };
+
+    $.fn.filterUIify = function() {
+
+        return this.each(function() {
+            var $elem = $(this);
+
+            function closeUI() {
+                if ($link.hasClass('selected')) {
+                    $('.filter-ui').slideUp('fast', function() {
+                        $(this).detach();
+                    });
+                    $link.removeClass('selected');
+                    return true;
+                }
+                return false;
+            }
+
+            var $link = $('<a>', {'class': 'filter-ui-link'}).
+                text("Filtering and Sorting").
+                click(function() {
+                    if (closeUI()) {
+                        return false;
+                    } else {
+                        $(this).addClass('selected');
+                        var pos = $elem.offset();
+                        var $filterUI = $('<div>', {'class': 'filter-ui'}).
+                            css({'top': pos.top + $elem.outerHeight(),
+                                 'left': pos.left,
+                                 'width': $elem.outerWidth()}).
+                            appendTo(document.body).
+                            hide().
+                            slideDown('fast');
+
+                        var $sortUI = $('<div>', {'class': 'filter-sort-ui'}).
+                            appendTo($filterUI).
+                            append('<h4>Sort by</h4>');
+
+                        var $sortUL = $('<ul>').appendTo($sortUI);
+
+                        var sortLinks = {};
+                        $.each(sortCriteria, function(key) {
+                            sortLinks[key] = makeLink('sort', key, this).
+                                appendTo($sortUL).
+                                click(function() {
+                                    closeUI();
+                                });
+                        });
+
+                        var hp = hashparamutils.getHashParams();
+                        if (hp.sort === undefined)
+                            hp.sort = 'name';
+
+                        if (sortLinks.hasOwnProperty(hp.sort))
+                            sortLinks[hp.sort].addClass('selected');
+
+                        return false;
+                    }
+                }).appendTo($elem);
+
+            $(document.body).click(function() {
+                if (closeUI())
+                    return false;
+            });
+        });
+    };
+});
diff --git a/sweettooth/static/js/hashparamutils.js b/sweettooth/static/js/hashparamutils.js
new file mode 100644
index 0000000..dee9d8c
--- /dev/null
+++ b/sweettooth/static/js/hashparamutils.js
@@ -0,0 +1,41 @@
+"use strict";
+
+define([], function() {
+
+    function getHashParams() {
+        var hash = window.location.hash;
+        if (!hash)
+            return {};
+
+        var values = hash.slice(1).split('&');
+        var obj = {};
+        for (var i = 0; i < values.length; i++) {
+            if (!values[i])
+                continue;
+
+            var kv = values[i].split('=');
+            obj[kv[0]] = kv[1];
+        }
+
+        return obj;
+    }
+
+    function makeHashParams(obj) {
+        var hash = '';
+        for (var key in obj) {
+            hash += key + '=' + obj[key] + '&';
+        }
+
+        // Remove last '&'
+        return hash.slice(0, -1);
+    }
+
+    function setHashParams(obj) {
+        window.location.hash = makeHashParams(obj);
+    }
+
+    return { getHashParams: getHashParams,
+             makeHashParams: makeHashParams,
+             setHashParams: setHashParams };
+
+});
diff --git a/sweettooth/static/js/main.js b/sweettooth/static/js/main.js
index 4c3596f..c1a3589 100644
--- a/sweettooth/static/js/main.js
+++ b/sweettooth/static/js/main.js
@@ -1,6 +1,6 @@
 "use strict";
 
-require(['jquery', 'messages', 'extensions', 'uploader',
+require(['jquery', 'messages', 'extensions', 'uploader', 'filter',
          'jquery.cookie', 'jquery.jeditable',
          'jquery.timeago', 'jquery.rating'], function($, messages) {
     if (!$.ajaxSettings.headers)
@@ -106,6 +106,7 @@ require(['jquery', 'messages', 'extensions', 'uploader',
             paginatorify('/ajax/extensions-list/').
             bind('page-loaded', function() {
                 $('li.extension').addOutOfDateIndicator();
+                $('#extensions-list .before-paginator').filterUIify();
             });
 
         $('#error_report').fillInErrors();
diff --git a/sweettooth/static/js/paginator.js b/sweettooth/static/js/paginator.js
index bb189ff..01fb7fa 100644
--- a/sweettooth/static/js/paginator.js
+++ b/sweettooth/static/js/paginator.js
@@ -1,38 +1,6 @@
 "use strict";
 
-define(['jquery', 'jquery.hashchange'], function($) {
-
-    function getHashParams() {
-        var hash = window.location.hash;
-        if (!hash)
-            return {};
-
-        var values = hash.slice(1).split('&');
-        var obj = {};
-        for (var i = 0; i < values.length; i++) {
-            if (!values[i])
-                continue;
-
-            var kv = values[i].split('=');
-            obj[kv[0]] = kv[1];
-        }
-
-        return obj;
-    }
-
-    function makeHashParams(obj) {
-        var hash = '';
-        for (var key in obj) {
-            hash += key + '=' + obj[key] + '&';
-        }
-
-        // Remove last '&'
-        return hash.slice(0, -1);
-    }
-
-    function setHashParams(obj) {
-        window.location.hash = makeHashParams(obj);
-    }
+define(['jquery', 'hashparamutils', 'jquery.hashchange'], function($, hashparamutils) {
 
     $.fn.paginatorify = function(url, context) {
         if (!this.length)
@@ -70,8 +38,8 @@ define(['jquery', 'jquery.hashchange'], function($) {
 
                 numPages = result.numpages;
 
-                $beforePaginator = buildPaginator();
-                $afterPaginator = buildPaginator();
+                $beforePaginator = buildPaginator().addClass('before-paginator');
+                $afterPaginator = buildPaginator().addClass('after-paginator');
 
                 var $newContent = $(result.html);
 
@@ -93,7 +61,7 @@ define(['jquery', 'jquery.hashchange'], function($) {
             hp.page = pageNumber;
 
             return $('<a>', {'class': 'number ' + styleClass,
-                             'href': '#' + makeHashParams(hp)}).text(text);
+                             'href': '#' + hashparamutils.makeHashParams(hp)}).text(text);
         }
 
         function buildPaginator() {
@@ -140,7 +108,7 @@ define(['jquery', 'jquery.hashchange'], function($) {
         }
 
         $(window).hashchange(function() {
-            var hp = getHashParams();
+            var hp = hashparamutils.getHashParams();
             if (hp.page === undefined)
                 hp.page = 1;
             else



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]