From f601d9f159a3fa2e9eccfd40c2418f08c9ce73aa Mon Sep 17 00:00:00 2001 From: John Crepezzi Date: Wed, 23 Nov 2011 11:31:50 -0500 Subject: [PATCH] Implement redesign of key --- config.js | 2 +- lib/static_handler.js | 1 + static/application.css | 86 +++++++++++++++++--- static/application.js | 142 ++++++++++++++++++++++++++-------- static/function-icons.png | Bin 0 -> 6826 bytes static/hover-dropdown-tip.png | Bin 0 -> 2869 bytes static/index.html | 18 ++++- static/logo.png | Bin 0 -> 4714 bytes 8 files changed, 203 insertions(+), 46 deletions(-) create mode 100644 static/function-icons.png create mode 100644 static/hover-dropdown-tip.png create mode 100644 static/logo.png diff --git a/config.js b/config.js index 22ff245..7dc7a8f 100644 --- a/config.js +++ b/config.js @@ -7,7 +7,7 @@ "maxLength": 400000, - "cacheStaticAssets": true, + "cacheStaticAssets": false, "logging": [ { diff --git a/lib/static_handler.js b/lib/static_handler.js index cd50d13..3cc5ec3 100644 --- a/lib/static_handler.js +++ b/lib/static_handler.js @@ -28,6 +28,7 @@ StaticHandler.contentTypeFor = function(ext) { else if (ext == '.html') return 'text/html'; else if (ext == '.ico') return 'image/ico'; else if (ext == '.txt') return 'text/plain'; + else if (ext == '.png') return 'image/png'; else { winston.error('unable to determine content type for static asset with extension: ' + ext); return 'text/plain'; diff --git a/static/application.css b/static/application.css index dbed46c..141e2b2 100644 --- a/static/application.css +++ b/static/application.css @@ -33,18 +33,80 @@ textarea { #key { position: fixed; - top: 20px; - right: 20px; - text-align: right; - z-index: -1000; /* watch out */ - color: #999; - font-size: 13px; - font-family: monospace; - line-height: 1.3em; + top: 0px; + right: 0px; + z-index: +1000; /* watch out */ } -#key em { - display: block; - margin-bottom: 5px; - color: #ccc !important; +#key .box1 { + padding: 5px; + text-align: center; + background: #00222b; } + +#key .box2 { + padding: 5px; + background: #08323c; + font-size: 0px; +} + +#key .box1 a.logo, #key .box1 a.logo:visited { + display: inline-block; + background: url(logo.png); + width: 126px; + height: 42px; +} + +#key .box1 a.logo:hover { + background-position: 0 bottom; +} + +#key .box2 .function { + background: url(function-icons.png); + width: 32px; + height: 37px; + display: inline-block; +} + +#key .box2 .function.enabled:hover { + cursor: hand; + cursor: pointer; +} + +#key .box3 { + background: #173e48; + font-family: Helvetica, sans-serif; + font-size: 12px; + line-height: 14px; + padding: 10px 15px; +} + +#key .box3 .label { + color: #fff; + font-weight: bold; +} + +#key .box3 .shortcut { + color: #c4dce3; + font-weight: normal; +} + +#key .box2 .function.save { background-position: 0px top; } +#key .box2 .function.enabled.save { background-position: 0px center; } +#key .box2 .function.enabled.save:hover { background-position: 0px bottom; } + +#key .box2 .function.new { background-position: -32px top; } +#key .box2 .function.enabled.new { background-position: -32px center; } +#key .box2 .function.enabled.new:hover { background-position: -32px bottom; } + +#key .box2 .function.duplicate { background-position: -64px top; } +#key .box2 .function.enabled.duplicate { background-position: -64px center; } +#key .box2 .function.enabled.duplicate:hover { background-position: -64px bottom; } + +#key .box2 .function.link { background-position: -96px top; } +#key .box2 .function.enabled.link { background-position: -96px center; } +#key .box2 .function.enabled.link:hover { background-position: -96px bottom; } + +#key .box2 .function.twitter { background-position: -128px top; } +#key .box2 .function.enabled.twitter { background-position: -128px center; } +#key .box2 .function.enabled.twitter:hover { background-position: -128px bottom; } diff --git a/static/application.js b/static/application.js index 393371c..5687ca7 100644 --- a/static/application.js +++ b/static/application.js @@ -61,6 +61,11 @@ var haste = function(appName, options) { this.$code = $('#box code'); this.options = options; this.configureShortcuts(); + this.configureButtons(); + // If twitter is disabled, hide the button + if (!options.twitter) { + $('#key .box2 .twitter').hide(); + } }; // Set the page title - include the appName @@ -71,23 +76,27 @@ haste.prototype.setTitle = function(ext) { // Show the light key haste.prototype.lightKey = function() { - var text = ''; - text += '' + this.appName + ''; - text += '^s - save
'; - text += '^n - new'; - $('#key').html(text); + this.configureKey(['new', 'save']); }; // Show the full key haste.prototype.fullKey = function() { - var text = ''; - text += '' + this.appName + ''; - text += '^n - new
'; - text += '^d - duplicate
'; - if (this.options.twitter) { - text += '^t - twitter'; - } - $('#key').html(text); + this.configureKey(['new', 'duplicate', 'twitter', 'link']); +}; + +// Set the key up for certain things to be enabled +haste.prototype.configureKey = function(enable) { + var $this, i = 0; + $('#key .box2 .function').each(function() { + $this = $(this); + for (i = 0; i < enable.length; i++) { + if ($this.hasClass(enable[i])) { + $this.addClass('enabled'); + return true; + } + } + $this.removeClass('enabled'); + }); }; // Remove the current document (if there is one) @@ -170,32 +179,101 @@ haste.prototype.lockDocument = function() { }); }; +haste.prototype.configureButtons = function() { + var _this = this; + this.buttons = [ + { + $where: $('#key .box2 .save'), + label: 'Save', + shortcutDescription: 'control + s', + shortcut: function(evt) { + return evt.ctrlKey && (evt.keyCode === 76 || evt.keyCode === 83); + }, + action: function() { + if (_this.$textarea.val().replace(/^\s+|\s+$/g, '') !== '') { + _this.lockDocument(); + } + } + }, + { + $where: $('#key .box2 .new'), + label: 'New', + shortcut: function(evt) { + return evt.ctrlKey && evt.keyCode === 78 + }, + shortcutDescription: 'control + n', + action: function() { + _this.newDocument(!_this.doc.key); + } + }, + { + $where: $('#key .box2 .duplicate'), + label: 'Duplicate & Edit', + shortcut: function(evt) { + return _this.doc.locked && evt.ctrlKey && evt.keyCode === 68; + }, + shortcutDescription: 'control + d', + action: function() { + _this.duplicateDocument(); + } + }, + { + $where: $('#key .box2 .twitter'), + label: 'Twitter', + shortcut: function(evt) { + return _this.options.twitter && _this.doc.locked && evt.ctrlKey && evt.keyCode == 84; + }, + shortcutDescription: 'control + t', + action: function() { + window.open('https://twitter.com/share?url=' + encodeURI(_this.baseUrl + _this.doc.key)); + } + }, + { + $where: $('#key .box2 .link'), + label: 'Copy URL', + action: function() { + alert('not yet implemented'); + } + } + ]; + for (var i = 0; i < this.buttons.length; i++) { + this.configureButton(this.buttons[i]); + } +}; + +haste.prototype.configureButton = function(options) { + // Handle the click action + options.$where.click(function(evt) { + evt.preventDefault(); + if ($(this).hasClass('enabled')) { + options.action(); + } + }); + // Show the label + options.$where.mouseenter(function(evt) { + $('#key .box3 .label').text(options.label); + $('#key .box3 .shortcut').text(options.shortcutDescription || ''); + $('#key .box3').show(); + }); + // Hide the label + options.$where.mouseleave(function(evt) { + $('#key .box3').hide(); + }); +}; + // Configure keyboard shortcuts for the textarea haste.prototype.configureShortcuts = function() { var _this = this; $(document.body).keydown(function(evt) { - // ^L or ^S for lock - if (evt.ctrlKey && (evt.keyCode === 76 || evt.keyCode === 83)) { - if (_this.$textarea.val().replace(/^\s+|\s+$/g, '') !== '') { + var button; + for (var i = 0 ; i < _this.buttons.length; i++) { + button = _this.buttons[i]; + if (button.shortcut && button.shortcut(evt)) { evt.preventDefault(); - _this.lockDocument(); + button.action(); + return; } } - // ^N for new document - else if (evt.ctrlKey && evt.keyCode === 78) { - evt.preventDefault(); - _this.newDocument(!_this.doc.key); - } - // ^D for duplicate - only when locked - else if (_this.doc.locked && evt.ctrlKey && evt.keyCode === 68) { - evt.preventDefault(); - _this.duplicateDocument(); - } - // ^T for redirecting to twitter - else if (_this.options.twitter && _this.doc.locked && evt.ctrlKey && evt.keyCode == 84) { - evt.preventDefault(); - window.open('https://twitter.com/share?url=' + encodeURI(_this.baseUrl + _this.doc.key)); - } }); }; diff --git a/static/function-icons.png b/static/function-icons.png new file mode 100644 index 0000000000000000000000000000000000000000..f2bb192c50c292c02ecf78515333529c23cdfb7a GIT binary patch literal 6826 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 -
+
+
+ +
+
+ + + + + +
+ +
+ diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a03ce90e90eb4b470deba7ba49128fb9fa59b0c3 GIT binary patch literal 4714 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 UNs+S|7#J8lUHx3vIVCg!0D4u`RsaA1 literal 0 HcmV?d00001