From 9546817ad26f01c609b6a7191c118b10b0aafc05 Mon Sep 17 00:00:00 2001 From: Ivanq Date: Sun, 31 Dec 2017 16:10:00 +0300 Subject: [PATCH] Add menu --- plugins/Sidebar/SidebarPlugin.py | 14 +++--- plugins/Sidebar/media/Menu.coffee | 46 ++++++++++++++++++ plugins/Sidebar/media/Menu.css | 19 ++++++++ plugins/Sidebar/media/all.css | 24 +++++++++ plugins/Sidebar/media/all.js | 81 ++++++++++++++++++++++++++++++- 5 files changed, 176 insertions(+), 8 deletions(-) create mode 100644 plugins/Sidebar/media/Menu.coffee create mode 100644 plugins/Sidebar/media/Menu.css diff --git a/plugins/Sidebar/SidebarPlugin.py b/plugins/Sidebar/SidebarPlugin.py index 4e7298a0..e23d322c 100644 --- a/plugins/Sidebar/SidebarPlugin.py +++ b/plugins/Sidebar/SidebarPlugin.py @@ -428,13 +428,9 @@ class UiWebsocketPlugin(object): body.append(_(u"""
- - {_[Sign and publish]} - v - + + {_[Sign and publish]} + \u22EE
@@ -474,6 +470,10 @@ class UiWebsocketPlugin(object): body.append("") body.append("") + body.append("") + self.response(to, "".join(body)) def downloadGeoLiteDb(self, db_path): diff --git a/plugins/Sidebar/media/Menu.coffee b/plugins/Sidebar/media/Menu.coffee new file mode 100644 index 00000000..3785009b --- /dev/null +++ b/plugins/Sidebar/media/Menu.coffee @@ -0,0 +1,46 @@ +class Menu + constructor: (@button) -> + @elem = $(".menu.template").clone().removeClass("template") + @elem.appendTo("body") + @items = [] + + show: -> + if window.visible_menu and window.visible_menu.button[0] == @button[0] # Same menu visible then hide it + window.visible_menu.hide() + @hide() + else + button_pos = @button.offset() + @elem.css({"top": button_pos.top+@button.outerHeight(), "left": button_pos.left}) + @button.addClass("menu-active") + @elem.addClass("visible") + if window.visible_menu then window.visible_menu.hide() + window.visible_menu = @ + + + hide: -> + @elem.removeClass("visible") + @button.removeClass("menu-active") + window.visible_menu = null + + + addItem: (title, cb) -> + item = $(".menu-item.template", @elem).clone().removeClass("template") + item.html(title) + item.on "click", => + if not cb(item) + @hide() + return false + item.appendTo(@elem) + @items.push item + return item + + + log: (args...) -> + console.log "[Menu]", args... + +window.Menu = Menu + +# Hide menu on outside click +$("body").on "click", (e) -> + if window.visible_menu and e.target != window.visible_menu.button[0] and $(e.target).parent()[0] != window.visible_menu.elem[0] + window.visible_menu.hide() diff --git a/plugins/Sidebar/media/Menu.css b/plugins/Sidebar/media/Menu.css new file mode 100644 index 00000000..e2afa16e --- /dev/null +++ b/plugins/Sidebar/media/Menu.css @@ -0,0 +1,19 @@ +.menu { + background-color: white; padding: 10px 0px; position: absolute; top: 0px; left: 0px; max-height: 0px; overflow: hidden; transform: translate(0px, -30px); pointer-events: none; + box-shadow: 0px 2px 8px rgba(0,0,0,0.3); border-radius: 2px; opacity: 0; transition: opacity 0.2s ease-out, transform 1s ease-out, max-height 0.2s ease-in-out; +} +.menu.visible { opacity: 1; max-height: 350px; transform: translate(0px, 0px); transition: opacity 0.1s ease-out, transform 0.3s ease-out, max-height 0.3s ease-in-out; pointer-events: all } + +.menu-item { display: block; text-decoration: none; color: black; padding: 6px 24px; transition: all 0.2s; border-bottom: none; font-weight: normal; padding-left: 30px; } +.menu-item-separator { margin-top: 5px; border-top: 1px solid #eee } + +.menu-item:hover { background-color: #F6F6F6; transition: none; color: inherit; border: none } +.menu-item:active, .menu-item:focus { background-color: #AF3BFF; color: white; transition: none } +.menu-item.selected:before { + content: "L"; display: inline-block; transform: rotateZ(45deg) scaleX(-1); + font-weight: bold; position: absolute; margin-left: -17px; font-size: 12px; margin-top: 2px; +} + +@media only screen and (max-width: 800px) { +.menu, .menu.visible { position: absolute; left: unset !important; right: 20px; } +} \ No newline at end of file diff --git a/plugins/Sidebar/media/all.css b/plugins/Sidebar/media/all.css index 8b48d73c..99082916 100644 --- a/plugins/Sidebar/media/all.css +++ b/plugins/Sidebar/media/all.css @@ -1,5 +1,29 @@ +/* ---- plugins/Sidebar/media/Menu.css ---- */ + + +.menu { + background-color: white; padding: 10px 0px; position: absolute; top: 0px; left: 0px; max-height: 0px; overflow: hidden; -webkit-transform: translate(0px, -30px); -moz-transform: translate(0px, -30px); -o-transform: translate(0px, -30px); -ms-transform: translate(0px, -30px); transform: translate(0px, -30px) ; pointer-events: none; + -webkit-box-shadow: 0px 2px 8px rgba(0,0,0,0.3); -moz-box-shadow: 0px 2px 8px rgba(0,0,0,0.3); -o-box-shadow: 0px 2px 8px rgba(0,0,0,0.3); -ms-box-shadow: 0px 2px 8px rgba(0,0,0,0.3); box-shadow: 0px 2px 8px rgba(0,0,0,0.3) ; -webkit-border-radius: 2px; -moz-border-radius: 2px; -o-border-radius: 2px; -ms-border-radius: 2px; border-radius: 2px ; opacity: 0; -webkit-transition: opacity 0.2s ease-out, transform 1s ease-out, max-height 0.2s ease-in-out; -moz-transition: opacity 0.2s ease-out, transform 1s ease-out, max-height 0.2s ease-in-out; -o-transition: opacity 0.2s ease-out, transform 1s ease-out, max-height 0.2s ease-in-out; -ms-transition: opacity 0.2s ease-out, transform 1s ease-out, max-height 0.2s ease-in-out; transition: opacity 0.2s ease-out, transform 1s ease-out, max-height 0.2s ease-in-out ; +} +.menu.visible { opacity: 1; max-height: 350px; -webkit-transform: translate(0px, 0px); -moz-transform: translate(0px, 0px); -o-transform: translate(0px, 0px); -ms-transform: translate(0px, 0px); transform: translate(0px, 0px) ; -webkit-transition: opacity 0.1s ease-out, transform 0.3s ease-out, max-height 0.3s ease-in-out; -moz-transition: opacity 0.1s ease-out, transform 0.3s ease-out, max-height 0.3s ease-in-out; -o-transition: opacity 0.1s ease-out, transform 0.3s ease-out, max-height 0.3s ease-in-out; -ms-transition: opacity 0.1s ease-out, transform 0.3s ease-out, max-height 0.3s ease-in-out; transition: opacity 0.1s ease-out, transform 0.3s ease-out, max-height 0.3s ease-in-out ; pointer-events: all } + +.menu-item { display: block; text-decoration: none; color: black; padding: 6px 24px; -webkit-transition: all 0.2s; -moz-transition: all 0.2s; -o-transition: all 0.2s; -ms-transition: all 0.2s; transition: all 0.2s ; border-bottom: none; font-weight: normal; padding-left: 30px; } +.menu-item-separator { margin-top: 5px; border-top: 1px solid #eee } + +.menu-item:hover { background-color: #F6F6F6; -webkit-transition: none; -moz-transition: none; -o-transition: none; -ms-transition: none; transition: none ; color: inherit; border: none } +.menu-item:active, .menu-item:focus { background-color: #AF3BFF; color: white; -webkit-transition: none ; -moz-transition: none ; -o-transition: none ; -ms-transition: none ; transition: none } +.menu-item.selected:before { + content: "L"; display: inline-block; -webkit-transform: rotateZ(45deg) scaleX(-1); -moz-transform: rotateZ(45deg) scaleX(-1); -o-transform: rotateZ(45deg) scaleX(-1); -ms-transform: rotateZ(45deg) scaleX(-1); transform: rotateZ(45deg) scaleX(-1) ; + font-weight: bold; position: absolute; margin-left: -17px; font-size: 12px; margin-top: 2px; +} + +@media only screen and (max-width: 800px) { +.menu, .menu.visible { position: absolute; left: unset !important; right: 20px; } +} + + /* ---- plugins/Sidebar/media/Scrollbable.css ---- */ diff --git a/plugins/Sidebar/media/all.js b/plugins/Sidebar/media/all.js index f4b19251..88a7742a 100644 --- a/plugins/Sidebar/media/all.js +++ b/plugins/Sidebar/media/all.js @@ -57,6 +57,86 @@ }).call(this); +/* ---- plugins/Sidebar/media/Menu.coffee ---- */ + + +(function() { + var Menu, + slice = [].slice; + + Menu = (function() { + function Menu(button) { + this.button = button; + this.elem = $(".menu.template").clone().removeClass("template"); + this.elem.appendTo("body"); + this.items = []; + } + + Menu.prototype.show = function() { + var button_pos; + if (window.visible_menu && window.visible_menu.button[0] === this.button[0]) { + window.visible_menu.hide(); + return this.hide(); + } else { + button_pos = this.button.offset(); + this.elem.css({ + "top": button_pos.top + this.button.outerHeight(), + "left": button_pos.left + }); + this.button.addClass("menu-active"); + this.elem.addClass("visible"); + if (window.visible_menu) { + window.visible_menu.hide(); + } + return window.visible_menu = this; + } + }; + + Menu.prototype.hide = function() { + this.elem.removeClass("visible"); + this.button.removeClass("menu-active"); + return window.visible_menu = null; + }; + + Menu.prototype.addItem = function(title, cb) { + var item; + item = $(".menu-item.template", this.elem).clone().removeClass("template"); + item.html(title); + item.on("click", (function(_this) { + return function() { + if (!cb(item)) { + _this.hide(); + } + return false; + }; + })(this)); + item.appendTo(this.elem); + this.items.push(item); + return item; + }; + + Menu.prototype.log = function() { + var args; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + return console.log.apply(console, ["[Menu]"].concat(slice.call(args))); + }; + + return Menu; + + })(); + + window.Menu = Menu; + + $("body").on("click", function(e) { + if (window.visible_menu && e.target !== window.visible_menu.button[0] && $(e.target).parent()[0] !== window.visible_menu.elem[0]) { + return window.visible_menu.hide(); + } + }); + +}).call(this); + + + /* ---- plugins/Sidebar/media/RateLimit.coffee ---- */ @@ -809,7 +889,6 @@ window.initScrollable = function () { }).call(this); - /* ---- plugins/Sidebar/media/morphdom.js ---- */