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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

$Tly9RQ%4($ms_1A!h$I^NDAa4SmU*PuvBvn^WY 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 A00000 literal 0 HcmV?d00001 diff --git a/static/hover-dropdown-tip.png b/static/hover-dropdown-tip.png new file mode 100644 index 0000000000000000000000000000000000000000..4841492447d9a0fe80fe2a6907912c7f5c64128f GIT binary patch literal 2869 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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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 WD;x|uTIAggb3jMKK)nuPAO1gjRn=Ai literal 0 HcmV?d00001