0

JSFiddle Demo

On my mail side nav I have a custom right-click hijack of which I have just made it so you can add a new sub-folder as partly seen below;

if ($(this).hasClass('NewSubFolder')) { if($('ul.inbox-nav li.Clicked').find('ul').length) { $('ul.inbox-nav li.Clicked > ul').prepend("<li class='NewSubFolder'><input type='text'></li>"); } else { $('ul.inbox-nav li.Clicked').append('<ul><li class="NewSubFolder"><input type="text"></li></ul>'); } $("ul.inbox-nav li.Clicked").removeClass('Clicked'); } 

This will add another tier where there is not one to prepend where there is, an input field. Currently you have to hit the enter key after typing something for the new folder name and then it will have worked its magic...

...However this newly appended list item does not work when you right-click it.

8
  • use a delegated event handler on the parent <ul> element that checks for ticks on an li (or a) element. Commented May 18, 2016 at 2:01
  • @Jhecht I'm new to delegated events, just tried $('#MailMenuSecondTier li').on("click", "contextmenu", function() { { of which broke my script. Could you please provide any more info? Thank you Commented May 18, 2016 at 2:19
  • @Jhecht I've just been looking into this and found this answer useful however this is on click of an element outside of where the content is appended therefore I'm not sure if this is the right solution? Commented May 18, 2016 at 2:31
  • got your brackets/parenthesis mixed around Tim. Commented May 18, 2016 at 2:32
  • 1
    got something, adding comments to code Commented May 18, 2016 at 3:45

2 Answers 2

0

Hopefully this gets what you need done.

Let me know if the comments are not clear enough.

EDIT

Made an edit to combine the two on(contextmenu) calls into one function. No need for redundancy.

$(document).ready(function() { // Trigger action when the contexmenu is about to be shown $('#inbox-nav').on("contextmenu", 'a', function(event) { event.preventDefault(); $('.clicked').removeClass('clicked'); //Gets rid of all other clicked elements $(this).closest('li').addClass('clicked'); //Clicks the closest li element var menu = ($(this).is('#inbox-nav>li>a')) ? 'MailMenuFirstTier' : 'MailMenuSecondTier'; /*This is an inline if statement, read in words it goes like this: if this element is a direct level link, then we're going to need to use the first menu tier. else we're going to need use the second menu tier. */ $("#" + menu).finish().show(100) //dynamically calls the menu we're using. .css({ left: event.pageX, top: event.pageY }); //Moves the first mail menu to the event position }); /* check the element to see which menut to show instead of using two different things. */ $(document).on('mousedown', function(e) { //Mouse down events! if ($('.custom-menu').is(':visible') && !$(e.target).parent().hasClass('custom-menu')) { /* In English: if a custom menu is visible, AND the target of the click DOES NOT have the custom-menu class, hide the custom menu. */ $('.custom-menu').finish().hide(); } if ($(e.target).parent().hasClass('custom-menu')) { //Figure out what to do since your element is a child of the custom menu $('.custom-menu').finish().hide(); var action = $(e.target).data('action'); //Gets our action element var clicked = $('.clicked'); //gets the clicked element we will be working on. switch (action) { case 'new-folder': //If the clicked element does not have a child ul element, add one. $('input.rename').focusout(); //Any current input.renames will have their focus out method called if (clicked.children('ul').length == 0) { clicked.append($('<ul></ul>')) } var ul = clicked.children('ul'); //Either this child element existed before or we just made it the step before. var input = $('<input />', { type: 'text', value: 'New Sub Folder', class: 'rename', 'data-start': 'New Sub Folder', focusout: function() { var value = ($(this).val() == '') ? $(this).data('start') : $(this).val(); $(this).siblings('a').html(value).show(); $(this).remove(); }, autofocus: true }); //Creates an input tag of type text, with class rename, a placeholder value, and a focusout function. var anchor = $('<a>', { href: '#', css: { display: 'none' } }); //Creates an anchor tag that is originally hidden ul.append($('<li>').append([input, anchor])); ul.find('input').click(); //Adds the (should be selected) element and the anchor //The input element takes care of things from there break; // end new-folder case case 'rename-folder': $('input.rename').focusout(); //any current input.rename items will have their focusout method called var anchor = clicked.find('a'); //get our closest anchor of our clicked element anchor.before($('<input />', { type: 'text', value: anchor.html(), class: 'rename', 'data-start': anchor.html(), focusout: function() { var value = ($(this).val() == '') ? $(this).data('start') : $(this).val(); $(this).siblings('a').html(value).show(); $(this).remove(); }, autofocus: true })).hide(); //Creates an input element, adds it before the anchor element, //hides anchor element. the newly created input element takes care of things from there break; /* ADD NEW ACTIONS HERE */ default: return; break; } } }).on('keyup', 'input.rename', function(e) { //Used for laziness. If a user hits enter in the input.rename tag, we fire the focusout target e.preventDefault(); if (e.keyCode == 13) { $(e.target).focusout(); } }); });
.custom-menu { display: none; z-index: 1000; position: absolute; margin: 0; padding: 0; list-style: none; overflow: hidden; border: 1px solid #CCC; white-space: nowrap; font-family: sans-serif; background: #FFF; color: #333; border-radius: 5px; font-size: 12px; } .custom-menu li { padding: 8px 12px; cursor: pointer; } .custom-menu li:hover { background-color: #DEF; } menu { position: absolute; } .custom-menu .divider { content: " "; height: 1px; margin: 4px 10px; background: #929292; } #MailBodyList.custom-menu li.Title { color: #929292; } #MailBodyList.custom-menu li.Title:hover { background: #FFF; cursor: default; } #MailBodyList.custom-menu li.ForThisSenderMore { display: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <ul class="inbox-nav" id="inbox-nav"> <li class="active"> <a href="javascript:;" data-type="inbox" data-title="Inbox"> <div class="Arrow"></div>Inbox </a> <ul> <li><a href="javascript:;" data-type="inbox" data-title="Sub_1">Sub-Folder 1</a> </li> <li><a href="javascript:;" data-type="inbox" data-title="Sub_2">Sub-Folder 2</a> </li> <li> <a href="javascript:;" data-type="inbox" data-title="Sub_3">Sub-Folder 3</a> <ul> <li><a href="javascript:;" data-type="inbox" data-title="Sub_1">Sub-Folder 1</a> </li> <li><a href="javascript:;" data-type="inbox" data-title="Sub_2">Sub-Folder 2</a> </li> </ul> </li> <li><a href="javascript:;" data-type="inbox" data-title="Sub_4">Sub-Folder 4</a> </li> <li><a href="javascript:;" data-type="inbox" data-title="Sub_5">Sub-Folder 5</a> </li> </ul> </li> <li> <a href="javascript:;" data-type="important" data-title="Inbox"> Important </a> </li> <li> <a href="javascript:;" data-type="sent" data-title="Sent"> Sent </a> </li> <li> <a href="javascript:;" data-type="draft" data-title="Draft"> Draft <span class="badge badge-danger">8</span> </a> </li> <li> <a href="javascript:;" class="sbold uppercase" data-title="Trash"> Trash <span class="badge badge-info">23</span> </a> </li> <li> <a href="javascript:;" data-type="inbox" data-title="Promotions"> Promotions <span class="badge badge-warning">2</span> </a> </li> <li> <a href="javascript:;" data-type="inbox" data-title="News"> News </a> </li> </ul> <ul id="MailMenuFirstTier" class="custom-menu"> <li>Mark All As Read</li> <li>Empty Folder</li> </ul> <ul class="custom-menu" id="MailMenuSecondTier"> <li class="NewSubFolder" data-action="new-folder">New Sub-Folder</li> <li class="Rename" data-action="rename-folder">Rename</li> <li class="Delete" data-action="delete-folder">Delete</li> <li>Mark All As Read</li> <li>Empty Folder</li> </ul>

Sign up to request clarification or add additional context in comments.

13 Comments

I've noticed a couple of errors compared to my working fiddle other than the question. They lie around renaming and on input focusout. You can rename multiple at once and if li > ul the renaming input appears. Not sure if you can delete as I haven't included this additional code... Please give me some time to look through!
`Tried simply replacing my current script and nothing seems to work... Shmae my server is down!
Wow, this is a bit advanced for me... I cannot even find how you tell <li class="NewSubFolder" data-action="new-folder">New Sub-Folder</li> to make a new tier...
Thank you for your help, you have inspired myself a lot and somewhat improved on my skills! The about is still a problem but not enough to leave this an unvalid answer! +1 too :)
Cannot thank you enough for progressing my skills so rapidly, I've grasped this so well :)
|
-1

You can use .contextmenu() to overwrite right-clic behavior.

$('.NewSubFolder').contextmenu(function() { console.log("Right clic detected!"); }); 

Documentation here: https://api.jquery.com/contextmenu/

I hope it helps! :)

1 Comment

My fiddle already uses contextmenu() however if you right-click Sub-Folder 1 > Add Sub-Folder, enter a value and hit enter, this new list item does not allow contextmenu() to work...