Переглянути джерело

[notebook] Move radial menu ko binding to dedicated component for adding snippets

It's not worth maintaining a generic radial menu with the customisations needed by the notebook. As the notebook is the only place where it's used I've decided to drop the binding and move it to a specific component for the notebook instead.
Johan Åhlén 10 роки тому
батько
коміт
0fccd1c

+ 0 - 82
desktop/core/src/desktop/static/desktop/js/ko.hue-bindings.js

@@ -188,88 +188,6 @@ ko.bindingHandlers.numericTextInput = {
   }
 };
 
-ko.bindingHandlers.radialMenu = {
-  init: function(element, valueAccessor) {
-    var $element = $(element);
-    var allAlternatives = $("<div>").addClass('all-alternatives').hide().appendTo($element);
-    $element.data('hide-timeout', -1);
-  },
-
-  update: function(element, valueAccessor) {
-    var $element = $(element);
-    var options = valueAccessor();
-
-    var alternatives = options.alternatives;
-    var onSelect = options.onSelect || $.noop;
-    var minRadius = options.minRadius || 70;
-    var alternativeCss = options.alternativeCss;
-    var alternativeSize = options.alternativeSize || 65;
-
-    var textRenderer = options.textRenderer || function(item) {
-        return item[selectAttribute]();
-      };
-
-    var allAlternatives = $element.find('.all-alternatives');
-
-    var hideAlternatives = function () {
-      clearTimeout($element.data('hide-timeout'));
-      $element.data('hide-timeout', setTimeout(function () {
-        allAlternatives.fadeOut();
-      }, 600));
-    };
-
-    var select = function (alternative) {
-      onSelect(alternative);
-      clearTimeout($element.data('hide-timeout'));
-      allAlternatives.fadeOut();
-    };
-
-    allAlternatives.empty();
-
-    if (alternatives().length > 0) {
-      window.setTimeout(function() {
-        var circumference = alternatives().length * alternativeSize;
-        var radius = Math.max(minRadius, circumference / Math.PI / 2);
-        var radIncrements = 2 * Math.PI / alternatives().length;
-        var currentRad = -0.5 * Math.PI;
-        var iconRadius = $element.find("i").width() / 2;
-
-        $.each(alternatives(), function (index, alternative) {
-          var outerDiv = $("<div>")
-            .addClass(alternativeCss)
-            .css("left", radius * Math.cos(currentRad) + iconRadius)
-            .css("top", radius * Math.sin(currentRad) + iconRadius)
-            .on("click", function () {
-              select(alternative);
-            })
-            .on("mouseenter", function () {
-              clearTimeout($element.data('hide-timeout'));
-            })
-            .on("mouseleave", hideAlternatives)
-            .appendTo(allAlternatives);
-          $("<div>")
-            .text(textRenderer(alternative))
-            .appendTo(outerDiv);
-          currentRad += radIncrements;
-        });
-      }, 500);
-    }
-
-    if (! $element.data('radial-initialized')) {
-      $element.find("i")
-        .on("click", function() {
-          select();
-        })
-        .on("mouseenter", function() {
-          clearTimeout($element.data('hide-timeout'));
-          allAlternatives.fadeIn();
-        })
-        .on("mouseleave", hideAlternatives);
-      $element.data('radial-initialized', true);
-    }
-  }
-};
-
 ko.bindingHandlers.freshereditor = {
   init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
     var _el = $(element);

+ 55 - 14
desktop/core/src/desktop/templates/ko_components.mako

@@ -905,13 +905,17 @@ from desktop.views import _ko
 
 <%def name="addSnippetMenu()">
   <script type="text/html" id="add-snippet-menu-template">
-    <div class="add-snippet-button pointer" style="position:relative; width:65px; text-align: center;" data-bind="radialMenu: {
-        alternatives: snippetsInWheel,
-        textRenderer: function(attribute) { return attribute.name() },
-        onSelect: addNewSnippet,
-        alternativeCss: 'add-snippet-alt'
-      }">
-      <i class="add-last-used-snippet fa fa-plus-circle fa-5x" title="${ _('Add a new snippet') }"></i>
+    <div class="add-snippet-button" style="position:relative; width:65px; text-align: center;">
+      <i class="add-last-used-snippet pointer fa fa-plus-circle fa-5x" title="${ _('Add a new snippet') }" data-bind="click: addLastUsedSnippet, event: { 'mouseenter': showHistory, 'mouseleave': hideHistory }"></i>
+      <div class="all-alternatives" data-bind="foreach: snippetsInWheel">
+        <div class="add-snippet-alt pointer" style="display:none;" data-bind="
+            event: { 'mouseenter': $parent.showHistory, 'mouseleave': $parent.hideHistory },
+            fadeVisible: $parent.showingHistory(),
+            style: { 'left': $parent.positions[$index()].left, 'top': $parent.positions[$index()].top },
+            click: $parent.addNewSnippet">
+          <div data-bind="text: name()"></div>
+        </div>
+      </div>
     </div>
 
     <div id="addSnippetModal" class="modal hide fade">
@@ -949,28 +953,51 @@ from desktop.views import _ko
         name: function() { return "..." }
       };
 
+      var WHEEL_RADIUS = 70;
+      var PLUS_ICON_RADIUS = 27.859; // FA-5X
+
+      var calculatePositions = function(alternativeCount) {
+        var radius = WHEEL_RADIUS;
+        var radIncrements = 2 * Math.PI / alternativeCount;
+        var currentRad = -0.5 * Math.PI;
+
+        var result = [];
+
+        for (var i = 0; i < alternativeCount; i++) {
+          result.push({
+            left: radius * Math.cos(currentRad) + PLUS_ICON_RADIUS  + 'px',
+            top: radius * Math.sin(currentRad) + PLUS_ICON_RADIUS  + 'px'
+          });
+          currentRad += radIncrements;
+        }
+
+        return result;
+      };
+
       function AddSnippetMenuViewModel (params) {
         var self = this;
         self.notebook = params.notebook;
         self.availableSnippets = params.availableSnippets;
-
         self.snippetHistory = ko.observableArray([].concat(self.availableSnippets.slice(0,4)));
+        self.positions = calculatePositions(self.snippetHistory().length + 1);
+        self.showingHistory = ko.observable(false);
 
         self.snippetsInWheel = ko.computed(function () {
-          var result = self.snippetHistory().concat(SHOW_MODAL_SNIPPET_ALT);
-          return result;
+          return self.snippetHistory().concat(SHOW_MODAL_SNIPPET_ALT);
         });
 
+        self.addLastUsedSnippet = function() {
+          self.addNewSnippet(self.snippetHistory()[0]);
+        };
+
         self.addNewSnippet = function (alternative) {
+          clearTimeout(hideTimeout);
+          self.showingHistory(false);
           $("#addSnippetModal").modal('hide');
           if (alternative && alternative.type() === SHOW_MODAL_SNIPPET_ALT.type()) {
             $("#addSnippetModal").modal('show');
             return;
           }
-          if (! alternative && self.snippetHistory().length > 0) {
-            self.notebook.newSnippet(self.snippetHistory()[0].type());
-            return;
-          }
 
           var currentIndex = self.snippetHistory().indexOf(alternative);
           if (currentIndex > -1) {
@@ -982,6 +1009,20 @@ from desktop.views import _ko
 
           self.notebook.newSnippet(alternative.type())
         };
+
+        var hideTimeout = -1;
+
+        self.showHistory = function () {
+          clearTimeout(hideTimeout);
+          self.showingHistory(true);
+        };
+
+        self.hideHistory = function () {
+          clearTimeout(hideTimeout);
+          hideTimeout = window.setTimeout(function () {
+            self.showingHistory(false);
+          }, 500);
+        };
       }
 
       ko.components.register('add-snippet-menu', {