diff --git a/lib/GUI/css/main.less b/lib/GUI/css/main.less index f78c6b68c..39e2cbac2 100644 --- a/lib/GUI/css/main.less +++ b/lib/GUI/css/main.less @@ -1,6 +1,7 @@ @import "../../../node_modules/helpers.less/helpers.less"; @import "./markdown.less"; @import "./highlight.js.less"; +@import "./fontello.less"; /*** Main Styles ***/ body { @@ -8,16 +9,20 @@ body { font-family: "Lucida Grande", "Helvetica Neue", Helvetica, Arial, Sans-Serif; } +a, a:visited { + text-decoration: none; + color: #0D5AFF; +} + +a:hover { + text-decoration: underline; +} + h1 { text-align: center; a, a:visited { color: black; - text-decoration: none; - } - - a:hover { - text-decoration: underline; } } @@ -49,12 +54,21 @@ h1 { #search-form { float: right; + @media (max-width: 540px) { + float: none; + margin-top: 6px; + } + @height: 30px; input, button { margin: 0; vertical-align: top; border: 1px solid #CCC; + + &:focus { + outline: none; + } } input { @@ -64,10 +78,6 @@ h1 { padding: 0 5px; font-size: 16px; border-right: 0; - - &:focus { - outline: none; - } } button { @@ -75,7 +85,7 @@ h1 { width: @height; margin: 0; border-left: 0; - background: none; + background: #FFF; cursor: pointer; font-size: 16px; color: #999; @@ -94,12 +104,28 @@ h2 { background: #F3F3F3; .border-radius(4px); padding: 12px 15px 15px; + .transition(height .3s); + overflow: hidden; h3 { font-size: 24px; margin: 0 0 10px; } + .name:hover { + text-decoration: none; + } + + .name:before { + margin: 0; + margin-left: -10px; + .transformTransition(.15s); + } + + &.open .name:before { + .rotate(90deg); + } + .version { font-size: 16px; color: #666; diff --git a/lib/GUI/entry.handlebars b/lib/GUI/entry.handlebars index 899e27df5..14ce6c21f 100644 --- a/lib/GUI/entry.handlebars +++ b/lib/GUI/entry.handlebars @@ -1,6 +1,6 @@

- {{ name }} + {{ name }} v{{ version }}
By: {{ _npmUser.name }}

diff --git a/lib/GUI/index.handlebars b/lib/GUI/index.handlebars index a6f9e3497..fcde4b82e 100644 --- a/lib/GUI/index.handlebars +++ b/lib/GUI/index.handlebars @@ -20,7 +20,7 @@

Available Packages:
- +

diff --git a/lib/GUI/js/entry.js b/lib/GUI/js/entry.js index cb9483521..5591b54d5 100644 --- a/lib/GUI/js/entry.js +++ b/lib/GUI/js/entry.js @@ -1,27 +1,61 @@ var $ = require('unopinionate').selector, - onClick = require('onclick'); + onClick = require('onclick'), + transitionComplete = require('transition-complete'); $(function() { onClick('.entry .name', function() { var $this = $(this), $entry = $this.closest('.entry'); + //Close entry if($entry.hasClass('open')) { + $entry - .removeClass('open') - .find('.readme').remove(); + .height($entry.height()) + .removeClass('open'); + + setTimeout(function() { + $entry.css('height', $entry.attr('data-height') + 'px'); + }, 0); + + transitionComplete(function() { + $entry.find('.readme').remove(); + $entry.css('height', 'auto'); + }); } + //Open entry else { + //Close open entries + $('.entry.open').each(function() { + var $this = $(this); + $this + .height($this.attr('data-height')) + .removeClass('open'); + }); + + //Add the open class $entry.addClass('open'); + //Explicitly set heights for transitions + var height = $entry.height(); + $entry + .attr('data-height', height) + .css('height', height); + + //Get the data $.ajax({ url: '/-/readme/'+$entry.attr('data-name')+'/'+$entry.attr('data-version'), dataType: 'text', success: function(html) { - console.log(html); - $("
") + var $readme = $("
") .html(html) .appendTo($entry); + + $entry.height(height + $readme.outerHeight()); + + transitionComplete(function() { + $entry.css('height', 'auto'); + }); } }); } diff --git a/lib/GUI/js/search.js b/lib/GUI/js/search.js index aaa0dad20..d63a1c571 100644 --- a/lib/GUI/js/search.js +++ b/lib/GUI/js/search.js @@ -2,10 +2,11 @@ var $ = require('unopinionate').selector, template = require('../entry.handlebars'); $(function() { - var $form = $('#search-form'), - $input = $form.find('input'), + var $form = $('#search-form'), + $input = $form.find('input'), $searchResults = $("#search-results"), - $body = $('body'), + $body = $('body'), + $clear = $form.find('.clear'), request; $form.bind('submit keyup', function(e) { @@ -15,6 +16,11 @@ $(function() { $body.addClass('state-search'); + //Switch the icons + $clear + [q ? 'addClass' : 'removeClass']('icon-cancel') + [!q ? 'addClass' : 'removeClass']('icon-search'); + if(q) { if(request) { request.abort(); @@ -41,7 +47,7 @@ $(function() { } }); - $form.find('.clear').click(function(e) { + $clear.click(function(e) { e.preventDefault(); $input.val(''); $form.keyup(); diff --git a/lib/static/main.css b/lib/static/main.css index 929bdfe3e..a27c00275 100644 --- a/lib/static/main.css +++ b/lib/static/main.css @@ -484,21 +484,83 @@ Original style from softwaremaniacs.org (c) Ivan Sagalaev \n

\n "; + + "'>\n

\n "; if (helper = helpers.name) { stack1 = helper.call(depth0, {hash:{},data:data}); } else { helper = (depth0 && depth0.name); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } buffer += escapeExpression(stack1) @@ -32,35 +32,69 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; }); },{"handlebars/runtime":11}],2:[function(require,module,exports){ var $ = require('unopinionate').selector, - onClick = require('onclick'); + onClick = require('onclick'), + transitionComplete = require('transition-complete'); $(function() { onClick('.entry .name', function() { var $this = $(this), $entry = $this.closest('.entry'); + //Close entry if($entry.hasClass('open')) { + $entry - .removeClass('open') - .find('.readme').remove(); + .height($entry.height()) + .removeClass('open'); + + setTimeout(function() { + $entry.css('height', $entry.attr('data-height') + 'px'); + }, 0); + + transitionComplete(function() { + $entry.find('.readme').remove(); + $entry.css('height', 'auto'); + }); } + //Open entry else { + //Close open entries + $('.entry.open').each(function() { + var $this = $(this); + $this + .height($this.attr('data-height')) + .removeClass('open'); + }); + + //Add the open class $entry.addClass('open'); + //Explicitly set heights for transitions + var height = $entry.height(); + $entry + .attr('data-height', height) + .css('height', height); + + //Get the data $.ajax({ url: '/-/readme/'+$entry.attr('data-name')+'/'+$entry.attr('data-version'), dataType: 'text', success: function(html) { - console.log(html); - $("
") + var $readme = $("
") .html(html) .appendTo($entry); + + $entry.height(height + $readme.outerHeight()); + + transitionComplete(function() { + $entry.css('height', 'auto'); + }); } }); } }); }); -},{"onclick":12,"unopinionate":13}],3:[function(require,module,exports){ +},{"onclick":12,"transition-complete":13,"unopinionate":14}],3:[function(require,module,exports){ require('./search'); require('./entry'); @@ -69,10 +103,11 @@ var $ = require('unopinionate').selector, template = require('../entry.handlebars'); $(function() { - var $form = $('#search-form'), - $input = $form.find('input'), + var $form = $('#search-form'), + $input = $form.find('input'), $searchResults = $("#search-results"), - $body = $('body'), + $body = $('body'), + $clear = $form.find('.clear'), request; $form.bind('submit keyup', function(e) { @@ -82,6 +117,11 @@ $(function() { $body.addClass('state-search'); + //Switch the icons + $clear + [q ? 'addClass' : 'removeClass']('icon-cancel') + [!q ? 'addClass' : 'removeClass']('icon-search'); + if(q) { if(request) { request.abort(); @@ -108,14 +148,14 @@ $(function() { } }); - $form.find('.clear').click(function(e) { + $clear.click(function(e) { e.preventDefault(); $input.val(''); $form.keyup(); }); }); -},{"../entry.handlebars":1,"unopinionate":13}],5:[function(require,module,exports){ +},{"../entry.handlebars":1,"unopinionate":14}],5:[function(require,module,exports){ "use strict"; /*globals Handlebars: true */ var base = require("./handlebars/base"); @@ -755,7 +795,71 @@ $(document).bind('mousedown', click._doAnywheres); module.exports = click; -},{"unopinionate":13}],13:[function(require,module,exports){ +},{"unopinionate":14}],13:[function(require,module,exports){ +(function(root) { + var callbacks = []; + + var transitionComplete = function(callback) { + if(callbacks.length === 0) { + setEvent(); + } + + callbacks.push(callback); + }; + + function setEvent() { + document.addEventListener(eventName(), function() { + var i = callbacks.length; + while(i--) { + callbacks[i](); + } + + callbacks = []; + }); + } + + var _eventName; + + function eventName() { + if(!_eventName) { + // Sourced from: http://stackoverflow.com/questions/5023514/how-do-i-normalize-css3-transition-functions-across-browsers + var el = document.createElement('fakeelement'); + transitions = { + transition: 'transitionend', + OTransition: 'oTransitionEnd', + MozTransition: 'transitionend', + WebkitTransition: 'webkitTransitionEnd' + }; + + for(var t in transitions) { + if(el.style[t] !== undefined) { + _eventName = transitions[t]; + } + } + } + + return _eventName; + } + + /*** Export ***/ + + // AMD + if(typeof define === 'function' && define.amd) { + define([], function() { + return transitionComplete; + }); + } + // CommonJS + else if(typeof exports !== 'undefined') { + module.exports = transitionComplete; + } + // Browser Global + else { + root.transitionComplete = transitionComplete; + } +})(this); + +},{}],14:[function(require,module,exports){ (function (global){ (function(root) { var unopinionate = { diff --git a/package.json b/package.json index 651b26af5..94c319c7b 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "request": ">= 2.31.0", "semver": ">= 2.2.1", "tar.gz": "^0.1.1", + "transition-complete": "0.0.2", "underscore": "^1.6.0", "unopinionate": "0.0.4" },