view public/javascripts/context_menu.js @ 8:0c83d98252d9 yuya

* Add custom repo prefix and proper auth realm, remove auth cache (seems like an unwise feature), pass DB handle around, various other bits of tidying
author Chris Cannam
date Thu, 12 Aug 2010 15:31:37 +0100
parents 513646585e45
children af80e5618e9b
line wrap: on
line source
/* redMine - project management software
   Copyright (C) 2006-2008  Jean-Philippe Lang */

var observingContextMenuClick;

ContextMenu = Class.create();
ContextMenu.prototype = {
	initialize: function (url) {
	this.url = url;
	this.createMenu();

	if (!observingContextMenuClick) {
		Event.observe(document, 'click', this.Click.bindAsEventListener(this));
		Event.observe(document, (window.opera ? 'click' : '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; }
		// right-click simulated by Alt+Click with Opera
		if (window.opera && !e.altKey) { 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') { return; }
    if (window.opera && e.altKey) {	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');
          } else {
            tr.removeClassName('context-menu-selection');
          }
        } else {
          if (e.ctrlKey) {
            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;
        }
      } 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);
          }
        }
      }
    }
    else{
      this.RightClick(e);
    }
  },
  
  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,
       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 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');
		}
	}
}

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