view public/javascripts/context_menu.js @ 1082:997f6d7738f7 bug_531

In repo controller entry action, show the page for the file even if it's binary (so user still has access to history etc links). This makes it possible to use the entry action as the default when a file is clicked on
author Chris Cannam <chris.cannam@soundsoftware.ac.uk>
date Thu, 22 Nov 2012 18:04:17 +0000
parents cbb26bc654de
children 433d4f72a19b
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, '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');
          } else {
            tr.removeClassName('context-menu-selection');
          }
        } 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;
        }
      } 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);
          }
        }
      }
    }
  },
  
  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 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};
}