chewymole chewymole - 7 months ago 53
Javascript Question

Jquery UI-ContextMenu trigger menu on text selection

I am using the jquery-ui-contextmenu jquery plugin. I have several dynamically generated divs each with a pre tag. What i want to is to initialize the plugin once and when a user highlights text and releases the left mouse button to trigger the context menu located at the position of the mouse.

So far i have been able to trigger the menu but i cant seem to get the position of the menu to stick to the mouse once the button is released, also if the user right clicks they get 2 context menus.

Here is my fiddle as an example

$("div.editor").contextmenu({
delegate: "pre",
menu: [
{title: "Copy", cmd: "copy", uiIcon: "ui-icon-copy"},
{title: "----"},
{title: "More", children: [
{title: "Sub 1", cmd: "sub1"},
{title: "Sub 2", cmd: "sub1"}
]}
],
select: function(event, ui) {
alert("select " + ui.cmd + " on " + ui.target.text());
}
});

$("pre").bind("mouseup",function(e){
$("div.editor").contextmenu('open',$("pre"));
});

<div class="editor"><pre></pre></div>


This is just some example code, but its very very similar to what i am using. We have a form under each div that has several fields we want to populate with the large text that is contained within the pre tag. And there could be as many as 20 div.editor tags each with its own form.

The point is so a user can highlight a specific word or phrase and easily insert it into the appropriate form field. I can make it just use the highlight then right click method but that takes extra time for the user who has hundreds of these to do a day.

Any help would be greatly appreciated.

Thanks again

Answer

I found a solution, hopefully this helps somebody else who may want to do the same as i am.

So you have to add in the position when you define your contextmenu. Then do a bind on mouseup to fire the open method. I used the extraData feature to pass in the original mouse event. This is what made it position on the mouse instead of top left of the screen.

 $("div.editor").contextmenu({
            delegate: "pre",
            position: function(event, ui){
               return {my: "left top", at: "left bottom", of: ui.extraData, collision: "fit"}; 
            }, 
...});

Then after your definition of the context menu bind to the mouseup event to get the selected text. I am using a few functions to get the selected text and unselect the text (IE bug)

$("pre").bind("mouseup",function(e){
            mytext = getSelectionHtml(), t = $(e.target), p = $('#' + t.prop('id'));

            if(mytext.length > 0){
                deselHTML();
                console.log(mytext + ' selected, calling open on the context menu. ' + $(p).prop('class'));
                $("div.editor").contextmenu('open',$(t),e);

            }
        });