diff public/javascripts/context_menu.js @ 1115:433d4f72a19b redmine-2.2

Update to Redmine SVN revision 11137 on 2.2-stable branch
author Chris Cannam
date Mon, 07 Jan 2013 12:01:42 +0000
parents cbb26bc654de
children 622f24f53b42
line wrap: on
line diff
--- a/public/javascripts/context_menu.js	Wed Jun 27 14:54:18 2012 +0100
+++ b/public/javascripts/context_menu.js	Mon Jan 07 12:01:42 2013 +0000
@@ -1,232 +1,236 @@
-/* redMine - project management software
-   Copyright (C) 2006-2008  Jean-Philippe Lang */
+var contextMenuObserving;
+var contextMenuUrl;
 
-var observingContextMenuClick;
+function contextMenuRightClick(event) {
+  var target = $(event.target);
+  if (target.is('a')) {return;}
+  var tr = target.parents('tr').first();
+  if (!tr.hasClass('hascontextmenu')) {return;}
+  event.preventDefault();
+  if (!contextMenuIsSelected(tr)) {
+    contextMenuUnselectAll();
+    contextMenuAddSelection(tr);
+    contextMenuSetLastSelected(tr);
+  }
+  contextMenuShow(event);
+}
 
-ContextMenu = Class.create();
-ContextMenu.prototype = {
-	initialize: function (url) {
-	this.url = url;
-	this.createMenu();
+function contextMenuClick(event) {
+  var target = $(event.target);
+  var lastSelected;
 
-	if (!observingContextMenuClick) {
-		Event.observe(document, 'click', this.Click.bindAsEventListener(this));
-		Event.observe(document, 'contextmenu', this.RightClick.bindAsEventListener(this));
-		observingContextMenuClick = true;
-	}
-	
-	this.unselectAll();
-	this.lastSelected = null;
-	},
-  
-	RightClick: function(e) {
-		this.hideMenu();
-		// do not show the context menu on links
-		if (Event.element(e).tagName == 'A') { return; }
-		var tr = Event.findElement(e, 'tr');
-		if (tr == document || tr == undefined  || !tr.hasClassName('hascontextmenu')) { return; }
-		Event.stop(e);
-		if (!this.isSelected(tr)) {
-			this.unselectAll();
-			this.addSelection(tr);
-			this.lastSelected = tr;
-		}
-		this.showMenu(e);
-	},
-
-  Click: function(e) {
-  	this.hideMenu();
-  	if (Event.element(e).tagName == 'A' || Event.element(e).tagName == 'IMG') { return; }
-    if (Event.isLeftClick(e) || (navigator.appVersion.match(/\bMSIE\b/))) {      
-      var tr = Event.findElement(e, 'tr');
-      if (tr!=null && tr!=document && tr.hasClassName('hascontextmenu')) {
-        // a row was clicked, check if the click was on checkbox
-        var box = Event.findElement(e, 'input');
-        if (box!=document && box!=undefined) {
-          // a checkbox may be clicked
-          if (box.checked) {
-            tr.addClassName('context-menu-selection');
+  if (target.is('a') && target.hasClass('submenu')) {
+    event.preventDefault();
+    return;
+  }
+  contextMenuHide();
+  if (target.is('a') || target.is('img')) { return; }
+  if (event.which == 1 || (navigator.appVersion.match(/\bMSIE\b/))) {
+    var tr = target.parents('tr').first();
+    if (tr.length && tr.hasClass('hascontextmenu')) {
+      // a row was clicked, check if the click was on checkbox
+      if (target.is('input')) {
+        // a checkbox may be clicked
+        if (target.attr('checked')) {
+          tr.addClass('context-menu-selection');
+        } else {
+          tr.removeClass('context-menu-selection');
+        }
+      } else {
+        if (event.ctrlKey || event.metaKey) {
+          contextMenuToggleSelection(tr);
+        } else if (event.shiftKey) {
+          lastSelected = contextMenuLastSelected();
+          if (lastSelected.length) {
+            var toggling = false;
+            $('.hascontextmenu').each(function(){
+              if (toggling || $(this).is(tr)) {
+                contextMenuAddSelection($(this));
+              }
+              if ($(this).is(tr) || $(this).is(lastSelected)) {
+                toggling = !toggling;
+              }
+            });
           } else {
-            tr.removeClassName('context-menu-selection');
+            contextMenuAddSelection(tr);
           }
         } else {
-          if (e.ctrlKey || e.metaKey) {
-            this.toggleSelection(tr);
-          } else if (e.shiftKey) {
-            if (this.lastSelected != null) {
-              var toggling = false;
-              var rows = $$('.hascontextmenu');
-              for (i=0; i<rows.length; i++) {
-                if (toggling || rows[i]==tr) {
-                  this.addSelection(rows[i]);
-                }
-                if (rows[i]==tr || rows[i]==this.lastSelected) {
-                  toggling = !toggling;
-                }
-              }
-            } else {
-              this.addSelection(tr);
-            }
-          } else {
-            this.unselectAll();
-            this.addSelection(tr);
-          }
-          this.lastSelected = tr;
+          contextMenuUnselectAll();
+          contextMenuAddSelection(tr);
         }
+        contextMenuSetLastSelected(tr);
+      }
+    } else {
+      // click is outside the rows
+      if (target.is('a') && (target.hasClass('disabled') || target.hasClass('submenu'))) {
+        event.preventDefault();
       } else {
-        // click is outside the rows
-        var t = Event.findElement(e, 'a');
-        if (t == document || t == undefined) {
-          this.unselectAll();
-        } else {
-          if (Element.hasClassName(t, 'disabled') || Element.hasClassName(t, 'submenu')) {
-            Event.stop(e);
-          }
-        }
+        contextMenuUnselectAll();
       }
     }
-  },
-  
-  createMenu: function() {
-    if (!$('context-menu')) {
-      var menu = document.createElement("div");
-      menu.setAttribute("id", "context-menu");
-      menu.setAttribute("style", "display:none;");
-      document.getElementById("content").appendChild(menu);
-    }
-  },
-  
-  showMenu: function(e) {
-    var mouse_x = Event.pointerX(e);
-    var mouse_y = Event.pointerY(e);
-    var render_x = mouse_x;
-    var render_y = mouse_y;
-    var dims;
-    var menu_width;
-    var menu_height;
-    var window_width;
-    var window_height;
-    var max_width;
-    var max_height;
-
-    $('context-menu').style['left'] = (render_x + 'px');
-    $('context-menu').style['top'] = (render_y + 'px');		
-    Element.update('context-menu', '');
-
-    new Ajax.Updater({success:'context-menu'}, this.url, 
-      {asynchronous:true,
-       method: 'get',
-       evalScripts:true,
-       parameters:Form.serialize(Event.findElement(e, 'form')),
-       onComplete:function(request){
-				 dims = $('context-menu').getDimensions();
-				 menu_width = dims.width;
-				 menu_height = dims.height;
-				 max_width = mouse_x + 2*menu_width;
-				 max_height = mouse_y + menu_height;
-			
-				 var ws = window_size();
-				 window_width = ws.width;
-				 window_height = ws.height;
-			
-				 /* display the menu above and/or to the left of the click if needed */
-				 if (max_width > window_width) {
-				   render_x -= menu_width;
-				   $('context-menu').addClassName('reverse-x');
-				 } else {
-					 $('context-menu').removeClassName('reverse-x');
-				 }
-				 if (max_height > window_height) {
-				   render_y -= menu_height;
-				   $('context-menu').addClassName('reverse-y');
-				 } else {
-					 $('context-menu').removeClassName('reverse-y');
-				 }
-				 if (render_x <= 0) render_x = 1;
-				 if (render_y <= 0) render_y = 1;
-				 $('context-menu').style['left'] = (render_x + 'px');
-				 $('context-menu').style['top'] = (render_y + 'px');
-				 
-         Effect.Appear('context-menu', {duration: 0.20});
-         if (window.parseStylesheets) { window.parseStylesheets(); } // IE
-      }})
-  },
-  
-  hideMenu: function() {
-    Element.hide('context-menu');
-  },
-  
-  addSelection: function(tr) {
-    tr.addClassName('context-menu-selection');
-    this.checkSelectionBox(tr, true);
-    this.clearDocumentSelection();
-  },
-  
-  toggleSelection: function(tr) {
-    if (this.isSelected(tr)) {
-      this.removeSelection(tr);
-    } else {
-      this.addSelection(tr);
-    }
-  },
-  
-  removeSelection: function(tr) {
-    tr.removeClassName('context-menu-selection');
-    this.checkSelectionBox(tr, false);
-  },
-  
-  unselectAll: function() {
-    var rows = $$('.hascontextmenu');
-    for (i=0; i<rows.length; i++) {
-      this.removeSelection(rows[i]);
-    }
-  },
-  
-  checkSelectionBox: function(tr, checked) {
-  	var inputs = Element.getElementsBySelector(tr, 'input');
-  	if (inputs.length > 0) { inputs[0].checked = checked; }
-  },
-  
-  isSelected: function(tr) {
-    return Element.hasClassName(tr, 'context-menu-selection');
-  },
-  
-  clearDocumentSelection: function() {
-    if (document.selection) {
-      document.selection.clear(); // IE
-    } else {
-      window.getSelection().removeAllRanges();
-    }
   }
 }
 
+function contextMenuCreate() {
+  if ($('#context-menu').length < 1) {
+    var menu = document.createElement("div");
+    menu.setAttribute("id", "context-menu");
+    menu.setAttribute("style", "display:none;");
+    document.getElementById("content").appendChild(menu);
+  }
+}
+
+function contextMenuShow(event) {
+  var mouse_x = event.pageX;
+  var mouse_y = event.pageY;
+  var render_x = mouse_x;
+  var render_y = mouse_y;
+  var dims;
+  var menu_width;
+  var menu_height;
+  var window_width;
+  var window_height;
+  var max_width;
+  var max_height;
+
+  $('#context-menu').css('left', (render_x + 'px'));
+  $('#context-menu').css('top', (render_y + 'px'));
+  $('#context-menu').html('');
+
+  $.ajax({
+    url: contextMenuUrl,
+    data: $(event.target).parents('form').first().serialize(),
+    success: function(data, textStatus, jqXHR) {
+      $('#context-menu').html(data);
+      menu_width = $('#context-menu').width();
+      menu_height = $('#context-menu').height();
+      max_width = mouse_x + 2*menu_width;
+      max_height = mouse_y + menu_height;
+
+      var ws = window_size();
+      window_width = ws.width;
+      window_height = ws.height;
+
+      /* display the menu above and/or to the left of the click if needed */
+      if (max_width > window_width) {
+       render_x -= menu_width;
+       $('#context-menu').addClass('reverse-x');
+      } else {
+       $('#context-menu').removeClass('reverse-x');
+      }
+      if (max_height > window_height) {
+       render_y -= menu_height;
+       $('#context-menu').addClass('reverse-y');
+      } else {
+       $('#context-menu').removeClass('reverse-y');
+      }
+      if (render_x <= 0) render_x = 1;
+      if (render_y <= 0) render_y = 1;
+      $('#context-menu').css('left', (render_x + 'px'));
+      $('#context-menu').css('top', (render_y + 'px'));
+      $('#context-menu').show();
+
+      //if (window.parseStylesheets) { window.parseStylesheets(); } // IE
+
+    }
+  });
+}
+
+function contextMenuSetLastSelected(tr) {
+  $('.cm-last').removeClass('cm-last');
+  tr.addClass('cm-last');
+}
+
+function contextMenuLastSelected() {
+  return $('.cm-last').first();
+}
+
+function contextMenuUnselectAll() {
+  $('.hascontextmenu').each(function(){
+    contextMenuRemoveSelection($(this));
+  });
+  $('.cm-last').removeClass('cm-last');
+}
+
+function contextMenuHide() {
+  $('#context-menu').hide();
+}
+
+function contextMenuToggleSelection(tr) {
+  if (contextMenuIsSelected(tr)) {
+    contextMenuRemoveSelection(tr);
+  } else {
+    contextMenuAddSelection(tr);
+  }
+}
+
+function contextMenuAddSelection(tr) {
+  tr.addClass('context-menu-selection');
+  contextMenuCheckSelectionBox(tr, true);
+  contextMenuClearDocumentSelection();
+}
+
+function contextMenuRemoveSelection(tr) {
+  tr.removeClass('context-menu-selection');
+  contextMenuCheckSelectionBox(tr, false);
+}
+
+function contextMenuIsSelected(tr) {
+  return tr.hasClass('context-menu-selection');
+}
+
+function contextMenuCheckSelectionBox(tr, checked) {
+  tr.find('input[type=checkbox]').attr('checked', checked);
+}
+
+function contextMenuClearDocumentSelection() {
+  // TODO
+  if (document.selection) {
+    document.selection.clear(); // IE
+  } else {
+    window.getSelection().removeAllRanges();
+  }
+}
+
+function contextMenuInit(url) {
+  contextMenuUrl = url;
+  contextMenuCreate();
+  contextMenuUnselectAll();
+  
+  if (!contextMenuObserving) {
+    $(document).click(contextMenuClick);
+    $(document).contextmenu(contextMenuRightClick);
+    contextMenuObserving = true;
+  }
+}
+
 function toggleIssuesSelection(el) {
-	var boxes = el.getElementsBySelector('input[type=checkbox]');
-	var all_checked = true;
-	for (i = 0; i < boxes.length; i++) { if (boxes[i].checked == false) { all_checked = false; } }
-	for (i = 0; i < boxes.length; i++) {
-		if (all_checked) {
-			boxes[i].checked = false;
-			boxes[i].up('tr').removeClassName('context-menu-selection');
-		} else if (boxes[i].checked == false) {
-			boxes[i].checked = true;
-			boxes[i].up('tr').addClassName('context-menu-selection');
-		}
-	}
+  var boxes = $(el).parents('form').find('input[type=checkbox]');
+  var all_checked = true;
+  boxes.each(function(){ if (!$(this).attr('checked')) { all_checked = false; } });
+  boxes.each(function(){
+    if (all_checked) {
+      $(this).removeAttr('checked');
+      $(this).parents('tr').removeClass('context-menu-selection');
+    } else if (!$(this).attr('checked')) {
+      $(this).attr('checked', true);
+      $(this).parents('tr').addClass('context-menu-selection');
+    }
+  });
 }
 
 function window_size() {
-    var w;
-    var h;
-    if (window.innerWidth) {
-	w = window.innerWidth;
-	h = window.innerHeight;
-    } else if (document.documentElement) {
-	w = document.documentElement.clientWidth;
-	h = document.documentElement.clientHeight;
-    } else {
-	w = document.body.clientWidth;
-	h = document.body.clientHeight;
-    }
-    return {width: w, height: h};
+  var w;
+  var h;
+  if (window.innerWidth) {
+    w = window.innerWidth;
+    h = window.innerHeight;
+  } else if (document.documentElement) {
+    w = document.documentElement.clientWidth;
+    h = document.documentElement.clientHeight;
+  } else {
+    w = document.body.clientWidth;
+    h = document.body.clientHeight;
+  }
+  return {width: w, height: h};
 }