Added experimental context menu (currently only for deleting elements)

git-svn-id: http://svg-edit.googlecode.com/svn/trunk@1663 eee81c28-f429-11dd-99c0-75d572ba1ddd
master
Alexis Deveria 2010-08-16 20:26:06 +00:00
parent 93d6dfa121
commit da4f9dacfa
6 changed files with 327 additions and 5 deletions

View File

@ -0,0 +1,198 @@
// jQuery Context Menu Plugin
//
// Version 1.01
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// Modified by Alexis Deveria
//
// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
//
// Terms of Use
//
// This plugin is dual-licensed under the GNU General Public License
// and the MIT License and is copyright A Beautiful Site, LLC.
//
if(jQuery)( function() {
$.extend($.fn, {
contextMenu: function(o, callback) {
// Defaults
if( o.menu == undefined ) return false;
if( o.inSpeed == undefined ) o.inSpeed = 150;
if( o.outSpeed == undefined ) o.outSpeed = 75;
// 0 needs to be -1 for expected results (no fade)
if( o.inSpeed == 0 ) o.inSpeed = -1;
if( o.outSpeed == 0 ) o.outSpeed = -1;
// Loop each context menu
$(this).each( function() {
var el = $(this);
var offset = $(el).offset();
// Add contextMenu class
$('#' + o.menu).addClass('contextMenu');
// Simulate a true right click
$(this).mousedown( function(e) {
var evt = e;
$(this).mouseup( function(e) {
var srcElement = $(this);
$(this).unbind('mouseup');
if( evt.button == 2 ) {
e.stopPropagation();
// Hide context menus that may be showing
$(".contextMenu").hide();
// Get this context menu
var menu = $('#' + o.menu);
if( $(el).hasClass('disabled') ) return false;
// Detect mouse position
var d = {}, x = e.pageX, y = e.pageY;
var x_off = $(window).width() - menu.width(),
y_off = $(window).height() - menu.height();
if(x > x_off) x = x_off-5;
if(y > y_off) y = y_off-5;
// Show the menu
$(document).unbind('click');
$(menu).css({ top: y, left: x }).fadeIn(o.inSpeed);
// Hover events
$(menu).find('A').mouseover( function() {
$(menu).find('LI.hover').removeClass('hover');
$(this).parent().addClass('hover');
}).mouseout( function() {
$(menu).find('LI.hover').removeClass('hover');
});
// Keyboard
$(document).keypress( function(e) {
switch( e.keyCode ) {
case 38: // up
if( $(menu).find('LI.hover').size() == 0 ) {
$(menu).find('LI:last').addClass('hover');
} else {
$(menu).find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover');
if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:last').addClass('hover');
}
break;
case 40: // down
if( $(menu).find('LI.hover').size() == 0 ) {
$(menu).find('LI:first').addClass('hover');
} else {
$(menu).find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover');
if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:first').addClass('hover');
}
break;
case 13: // enter
$(menu).find('LI.hover A').trigger('click');
break;
case 27: // esc
$(document).trigger('click');
break
}
});
// When items are selected
$('#' + o.menu).find('A').unbind('click');
$('#' + o.menu).find('LI:not(.disabled) A').click( function() {
$(document).unbind('click').unbind('keypress');
$(".contextMenu").hide();
// Callback
if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} );
return false;
});
// Hide bindings
setTimeout( function() { // Delay for Mozilla
$(document).click( function() {
$(document).unbind('click').unbind('keypress');
$(menu).fadeOut(o.outSpeed);
return false;
});
}, 0);
}
});
});
// Disable text selection
if( $.browser.mozilla ) {
$('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); });
} else if( $.browser.msie ) {
$('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); });
} else {
$('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); });
}
// Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
$(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; });
});
return $(this);
},
// Disable context menu items on the fly
disableContextMenuItems: function(o) {
if( o == undefined ) {
// Disable all
$(this).find('LI').addClass('disabled');
return( $(this) );
}
$(this).each( function() {
if( o != undefined ) {
var d = o.split(',');
for( var i = 0; i < d.length; i++ ) {
$(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');
}
}
});
return( $(this) );
},
// Enable context menu items on the fly
enableContextMenuItems: function(o) {
if( o == undefined ) {
// Enable all
$(this).find('LI.disabled').removeClass('disabled');
return( $(this) );
}
$(this).each( function() {
if( o != undefined ) {
var d = o.split(',');
for( var i = 0; i < d.length; i++ ) {
$(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');
}
}
});
return( $(this) );
},
// Disable context menu(s)
disableContextMenu: function() {
$(this).each( function() {
$(this).addClass('disabled');
});
return( $(this) );
},
// Enable context menu(s)
enableContextMenu: function() {
$(this).each( function() {
$(this).removeClass('disabled');
});
return( $(this) );
},
// Destroy context menu(s)
destroyContextMenu: function() {
// Destroy specified context menus
$(this).each( function() {
// Disable action
$(this).unbind('mousedown').unbind('mouseup');
});
return( $(this) );
}
});
})(jQuery);

View File

@ -0,0 +1,22 @@
// jQuery Context Menu Plugin
//
// Version 1.01
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
//
// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
//
// Terms of Use
//
// This plugin is dual-licensed under the GNU General Public License
// and the MIT License and is copyright A Beautiful Site, LLC.
//
jQuery&&function(){$.extend($.fn,{contextMenu:function(a,e){if(a.menu==undefined)return false;if(a.inSpeed==undefined)a.inSpeed=150;if(a.outSpeed==undefined)a.outSpeed=75;if(a.inSpeed==0)a.inSpeed=-1;if(a.outSpeed==0)a.outSpeed=-1;$(this).each(function(){var d=$(this),i=$(d).offset();$("#"+a.menu).addClass("contextMenu");$(this).mousedown(function(j){j.stopPropagation();$(this).mouseup(function(f){f.stopPropagation();var k=$(this);$(this).unbind("mouseup");if(j.button==2){$(".contextMenu").hide();
var b=$("#"+a.menu);if($(d).hasClass("disabled"))return false;var c={},g,h;if(self.innerHeight){c.pageYOffset=self.pageYOffset;c.pageXOffset=self.pageXOffset;c.innerHeight=self.innerHeight;c.innerWidth=self.innerWidth}else if(document.documentElement&&document.documentElement.clientHeight){c.pageYOffset=document.documentElement.scrollTop;c.pageXOffset=document.documentElement.scrollLeft;c.innerHeight=document.documentElement.clientHeight;c.innerWidth=document.documentElement.clientWidth}else if(document.body){c.pageYOffset=
document.body.scrollTop;c.pageXOffset=document.body.scrollLeft;c.innerHeight=document.body.clientHeight;c.innerWidth=document.body.clientWidth}f.pageX?g=f.pageX:g=f.clientX+c.scrollLeft;f.pageY?h=f.pageY:h=f.clientY+c.scrollTop;$(document).unbind("click");$(b).css({top:h,left:g}).fadeIn(a.inSpeed);$(b).find("A").mouseover(function(){$(b).find("LI.hover").removeClass("hover");$(this).parent().addClass("hover")}).mouseout(function(){$(b).find("LI.hover").removeClass("hover")});$(document).keypress(function(l){switch(l.keyCode){case 38:if($(b).find("LI.hover").size()==
0)$(b).find("LI:last").addClass("hover");else{$(b).find("LI.hover").removeClass("hover").prevAll("LI:not(.disabled)").eq(0).addClass("hover");$(b).find("LI.hover").size()==0&&$(b).find("LI:last").addClass("hover")}break;case 40:if($(b).find("LI.hover").size()==0)$(b).find("LI:first").addClass("hover");else{$(b).find("LI.hover").removeClass("hover").nextAll("LI:not(.disabled)").eq(0).addClass("hover");$(b).find("LI.hover").size()==0&&$(b).find("LI:first").addClass("hover")}break;case 13:$(b).find("LI.hover A").trigger("click");
break;case 27:$(document).trigger("click");break}});$("#"+a.menu).find("A").unbind("click");$("#"+a.menu).find("LI:not(.disabled) A").click(function(){$(document).unbind("click").unbind("keypress");$(".contextMenu").hide();e&&e($(this).attr("href").substr(1),$(k),{x:g-i.left,y:h-i.top,docX:g,docY:h});return false});setTimeout(function(){$(document).click(function(){$(document).unbind("click").unbind("keypress");$(b).fadeOut(a.outSpeed);return false})},0)}})});if($.browser.mozilla)$("#"+a.menu).each(function(){$(this).css({MozUserSelect:"none"})});
else $.browser.msie?$("#"+a.menu).each(function(){$(this).bind("selectstart.disableTextSelect",function(){return false})}):$("#"+a.menu).each(function(){$(this).bind("mousedown.disableTextSelect",function(){return false})});$(d).add($("UL.contextMenu")).bind("contextmenu",function(){return false})});return $(this)},disableContextMenuItems:function(a){if(a==undefined){$(this).find("LI").addClass("disabled");return $(this)}$(this).each(function(){if(a!=undefined)for(var e=a.split(","),d=0;d<e.length;d++)$(this).find('A[href="'+
e[d]+'"]').parent().addClass("disabled")});return $(this)},enableContextMenuItems:function(a){if(a==undefined){$(this).find("LI.disabled").removeClass("disabled");return $(this)}$(this).each(function(){if(a!=undefined)for(var e=a.split(","),d=0;d<e.length;d++)$(this).find('A[href="'+e[d]+'"]').parent().removeClass("disabled")});return $(this)},disableContextMenu:function(){$(this).each(function(){$(this).addClass("disabled")});return $(this)},enableContextMenu:function(){$(this).each(function(){$(this).removeClass("disabled")});
return $(this)},destroyContextMenu:function(){$(this).each(function(){$(this).unbind("mousedown").unbind("mouseup")});return $(this)}})}(jQuery);

View File

@ -1214,3 +1214,66 @@ span.zoom_tool {
-webkit-border-radius: 0px;
}
/* Generic context menu styles */
.contextMenu {
position: absolute;
width: 120px;
z-index: 99999;
border: solid 1px #CCC;
background: #EEE;
padding: 0px;
margin: 0px;
display: none;
}
.contextMenu LI {
list-style: none;
padding: 0px;
margin: 0px;
}
.contextMenu A {
color: #333;
text-decoration: none;
display: block;
line-height: 20px;
height: 20px;
background-position: 6px center;
background-repeat: no-repeat;
outline: none;
padding: 1px 5px;
padding-left: 28px;
}
.contextMenu LI.hover A {
background-color: #FFC;
}
.contextMenu LI.disabled A {
color: #AAA;
cursor: default;
}
.contextMenu LI.hover.disabled A {
background-color: transparent;
}
.contextMenu LI.separator {
border-top: solid 1px #CCC;
}
/*
Adding Icons
You can add icons to the context menu by adding
classes to the respective LI element(s)
*/
/*
.contextMenu LI.edit A { background-image: url(images/page_white_edit.png); }
.contextMenu LI.cut A { background-image: url(images/cut.png); }
.contextMenu LI.copy A { background-image: url(images/page_white_copy.png); }
.contextMenu LI.paste A { background-image: url(images/page_white_paste.png); }
.contextMenu LI.delete A { background-image: url(images/page_white_delete.png); }
.contextMenu LI.quit A { background-image: url(images/door.png); }
*/

View File

@ -16,6 +16,7 @@
<script type="text/javascript" src="svgicons/jquery.svgicons.js"></script>
<script type="text/javascript" src="jquerybbq/jquery.bbq.min.js"></script>
<script type="text/javascript" src="spinbtn/JQuerySpinBtn.js"></script>
<script type="text/javascript" src="contextmenu/jquery.contextMenu.js"></script>
<script type="text/javascript" src="svgcanvas.js"></script>
<script type="text/javascript" src="svg-editor.js"></script>
<script type="text/javascript" src="locale/locale.js"></script>
@ -665,5 +666,12 @@ script type="text/javascript" src="locale/locale.min.js"></script-->
</div>
</div>
<ul id="cmenu_canvas" class="contextMenu">
<li class="cut"><a href="#cut">Cut</a></li>
<li class="copy"><a href="#copy">Copy</a></li>
<li class="paste"><a href="#paste">Paste</a></li>
<li class="delete separator"><a href="#delete">Delete</a></li>
</ul>
</body>
</html>

View File

@ -1472,6 +1472,8 @@
} // if (elem != null)
else if (multiselected) {
$('#multiselected_panel').show();
} else {
$('#cmenu_canvas li').disableContextMenu();
}
// update history buttons
@ -1493,6 +1495,9 @@
if ( (elem && !is_node) || multiselected) {
// update the selected elements' layer
$('#selLayerNames').removeAttr('disabled').val(currentLayer);
// Enable regular menu options
$('#cmenu_canvas').enableContextMenuItems('#delete');
}
else {
$('#selLayerNames').attr('disabled', 'disabled');
@ -1847,8 +1852,11 @@
}
on_button = false;
}).mousedown(function(evt) {
var islib = $(evt.target).closest('div.tools_flyout').length;
if(!islib) $('.tools_flyout:visible').fadeOut();
// $(".contextMenu").hide();
// console.log('cm', $(evt.target).closest('.contextMenu'));
var islib = $(evt.target).closest('div.tools_flyout, .contextMenu').length;
if(!islib) $('.tools_flyout:visible,.contextMenu').fadeOut(250);
});
overlay.bind('mousedown',function() {
@ -3703,6 +3711,21 @@
$('#blur').SpinButton({ step: .1, min: 0, max: 10, callback: changeBlur });
$('#zoom').SpinButton({ min: 0.001, max: 10000, step: 50, stepfunc: stepZoom, callback: changeZoom });
$("#workarea").contextMenu({
menu: 'cmenu_canvas',
inSpeed: 0
},
function(action, el, pos) {
switch ( action ) {
case 'delete':
deleteSelected();
break;
}
});
$('#cmenu_canvas li').disableContextMenu();
$('#cmenu_canvas').enableContextMenuItems('#delete');
window.onbeforeunload = function() {
// Suppress warning if page is empty
if(undoMgr.getUndoStackSize() === 0) {

View File

@ -4200,7 +4200,14 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
// and do nothing else
var mouseDown = function(evt)
{
if(evt.button === 1 || canvas.spaceKey) return;
console.log(evt.button);
if(canvas.spaceKey) return;
var right_click = evt.button === 2;
if(right_click) {
current_mode = "select";
}
root_sctm = svgcontent.getScreenCTM().inverse();
var pt = transformPoint( evt.pageX, evt.pageY, root_sctm ),
mouse_x = pt.x * current_zoom,
@ -4242,6 +4249,7 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
case "select":
started = true;
current_resize_mode = "none";
if(right_click) started = false;
if (mouse_target != svgroot) {
// if this element is not yet selected, clear selection and select it
@ -4266,7 +4274,7 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
slist.insertItemBefore(svgroot.createSVGTransform(), 0);
}
}
else {
else if(!right_click){
clearSelection();
current_mode = "multiselect";
if (rubberBox == null) {
@ -4849,7 +4857,7 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
// this is done in when we recalculate the selected dimensions()
var mouseUp = function(evt)
{
if(evt.button === 1) return;
if(evt.button === 2) return;
var tempJustSelected = justSelected;
justSelected = null;
if (!started) return;