Dynamically change jquery contextmenu - javascript

I'm using this jquery plugin. The instantiation of the menu looks like this:
$.contextMenu({
selector:'.disposition-menu',
zIndex: 120,
callback: function(key, options) {
var stepID = $(this).closest('.card').attr("id").substring(5);
handle_disposition(key,stepID);
},
items: {
"pin": {name: "Pin to top"},
"unpin": {name:"Unpin"},
"complete": {name: "Mark step completed"},
"remove": {name: "Remove step from Map"},
},
events: {
show: function(){}, //this is where I'm lost
hide: function(){} //this is where I'm lost
},
trigger: 'hover'
});
The 'handle disposition' function interacts with php and the database to record the '.card' as pinned or unpinned in the database so that it appears properly when the page is reloaded. The HTML is a bootstrap 4 card like this:
<div class="card" >
<div class="card-header ">
<table class="title-table">
<tr>
<td>...</td>
<td>...</td>
<td>...</td>
<td class="disposition-menu">&vellip;</td>
</tr>
</table>
</div>
<div class="card-body">
...{body content}
</div>
</div>
What I am trying to do is toggle between the pin and unpin menu items. Only one of these should appear on the menu at a time. If the item is already "pinned" (i.e. flagged in database, and represented by a data attribute in the '.card' html) then "Unpin" should appear...and vice versa. Similarly as soon as the "Pin..." is clicked on the menu, the menu should immediately be changed to hide the "Pin" item and expose the "Unpin" item and vice versa
I've looked at the documentation for the plugin, but I'm a bit of a newbie when it comes to using functions after the keys with colons (eg selector: ) and callbacks. The plugin apparently has a "visible:" key, and also "show:" and "hide:" keys (used as per this issue, but I'm at a loss as to how to string these elements together to accomplish my objective.

Use build:
https://swisnl.github.io/jQuery-contextMenu/docs.html#build
If the build callback is found at registration, the menu is not built
right away. The menu creation is delayed to the point where the menu
is actually called to show.
$.contextMenu({
selector: ".menu",
build: function($trigger) {
var options = {
callback: function(key, options) {
var m = "clicked: " + key;
alert(m);
},
items: {}
};
if ($trigger.hasClass('pin')) {
options.items.unpin = {name: "unpin"};
} else {
options.items.pin = {name: "pin"};
}
return options;
}
});
.menu{
width: 100px;
padding: 10px;
background: red;
margin: 10px;
color: #FFF;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.9.0/jquery.contextMenu.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.9.0/jquery.contextMenu.min.js"></script>
<div class="menu pin">Pin</div>
<div class="menu">Unpin</div>
Example on demand:
https://swisnl.github.io/jQuery-contextMenu/demo/dynamic-create.html
Edit:
$.contextMenu({
selector: ".disposition-menu",
build: function($trigger) {
var options = {
callback: function(key, options) {
if(key == "pin")
$trigger.removeClass("unpin").addClass("pin");
else if(key == "unpin")
$trigger.removeClass("pin").addClass("unpin");
},
items: {}
};
if ($trigger.hasClass('pin')) {
options.items.unpin = {name: "unpin"};
} else {
options.items.pin = {name: "pin"};
}
return options;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.9.0/jquery.contextMenu.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.9.0/jquery.contextMenu.min.js"></script>
<div class="card" >
<div class="card-header ">
<table class="title-table">
<tr>
<td>...</td>
<td>...</td>
<td>...</td>
<td class="disposition-menu">&vellip;</td>
</tr>
</table>
</div>
<div class="card-body">
...{body content}
</div>
</div>

Here's how I solved the problem of "menu item swapping". Thanks to #ahed-kabalan for pointing me in the right direction.
The HTML didn't change from my question posted above. Here it is again for convenience:
<div class="card" >
<div class="card-header ">
<table class="title-table">
<tr>
<td>...</td>
<td>...</td>
<td>...</td>
<td class="disposition-menu">&vellip;</td>
</tr>
</table>
</div>
<div class="card-body">
...{body content}
</div>
</div>
The JS was modified to trigger a callback when the specific menu item was clicked and uses the visible key. This solution includes menu items that are modified when clicked and those that aren't affected. The menu appears when on hover, and the callbacks are only triggered on menu item selection. The unpin item is set to visible: false as a default - i.e. only the pin option will appear in the menu initially. Since build is really focused on building an entirely new menu, it wasn't necessary in my case. The JS now looks like this:
$.contextMenu({
selector:'.disposition-menu',
zIndex: 120,
callback: function(key, options) {
var stepID = $(this).closest('.card').attr("id").substring(5);
alert(stepID);
handle_disposition(key,stepID);
},
items: {
"pin": {name: "Pin to top",
callback: function(key, opt) {
opt.items['pin'].visible = false;
opt.items['unpin'].visible = true;
}
},
"unpin": {name:"Unpin",
callback: function(key, opt) {
opt.items['pin'].visible = true;
opt.items['unpin'].visible = false;
}
},
"complete": {name: "Mark step completed"},
"remove": {name: "Remove step from Map"}
},
trigger: 'hover'
});
Hope others will find this useful!

Related

draggable ui that implicate a condition on specific position

I am struggling in a specific problem. I actually have a draggable element based on a grid of 4 and I would like to create an event each time the draggable item reaches a specific position on this gird.
Here is the html of this grid,
<div class="selector">
<div class="title">
<h2>Vælg lånebeløb</h2>
</div>
<div class="draggable">
<h3 id="krd">kr</h3>
</div>
<div class="line">
<img src="./resources/images/line.png" alt="line">
</div>
<div class="legend">
<p>3.000</p>
<p>4.000</p>
<p>5.000</p>
<p>6.000</p>
</div>
</div>
and here is the jquery,
$("#krd").draggable({
grid: [ 190, 0 ],
cursor: "move",
containment: '.selector',
drag: function( event, ui ) {
if(ui.position.left = 190) {
$(".bluebox h2").text("3.000 Kr");
} else if (ui.position.left = 380) {
ect......
} {
}
}
});
What I am trying to do is that when we move the bar, it changes the text in the sidebar. I tried different options since but couldn't figure out what I am missing. Here is the link of the page on github of the project, maybe you will have an idea about it.
Here is the link of the code in github
https://github.com/erwanriou/goKredit---Frontpage/
and the render of the page to get a better idea of the problem.
https://erwanriou.github.io/goKredit---Frontpage/
Expanding upon my comment, I would advise using jQuery UI Slider. You will need to theme it, but the code would be:
$(function() {
$("#krd").slider({
min: 3,
max: 6,
value: 3,
slide: function(e, ui) {
$(".bluebox h2").text(ui.value + ".000 Kr");
}
});
});
Example (in progress): https://jsfiddle.net/Twisty/bjfuLjzL/2/

JQuery disable table row toggle when one row already toggled

I have a table or articles and a toggle on each row that displays the child row content. In the child row I also display Disqus comments. This all works fine but I do not want multiple rows opened up all at once and multiple Disqus comments loading, slowing down my page.
I want to disable all toggle buttons when one toggle is activated. Each toggle link (class option_toggle) and the row it's on has a unique ID. See below. How can I accomplish this via JQuery?
//Hide main article table's options row
$(document).ready(function() {
$(".option_toggle").click(function(e) {
e.preventDefault();
aid = $(this).attr('id');
//Determine if we are showing the comments or hiding the comments
is_hidden = $(this).parent().parent().next(".options_row").is( ":hidden" );
if(is_hidden)
{
disqus_container = '#disqus_container_' + aid;
jQuery('<div id="disqus_thread"></div>').insertBefore(disqus_container);
$.ajax({
type: 'POST',
url: 'http://www.example.com/disqus',
data: {'msmm_tn' : '12d406df3c8b2e178893e2c146d318e5', 'aid' : aid},
dataType: 'json',
success : function(data) {
if (data)
{
$('#disqus_container_' + aid).html(data.script);
DISQUS.reset({
reload: true,
config: function () {
this.page.url = 'http://www.example.com/#!'+ aid;
this.page.remote_auth_s3 = data.payload;
this.page.identifier = aid;
this.page.api_key = "cULB96iURBu1pZOtLOOSVlVgBj10SY9ctXWiv0eiQdzhdxqBq9UgmVr5SeSiaFiP";
}
});
}
}
});
}
else
{
//Remove the comments
$('#disqus_container_' + aid).prev('#disqus_thread').remove();
$('#disqus_container_' + aid).html('');
}
$(this).parent().parent().next(".options_row").toggle("fast");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<tbody>
<tr class="main_row" data-id="ROWID428272">
<td class="bkgcol-sunflower wht-border">
<td>
<a id="428272" class="option_toggle" href="#" title="Ratings/Comments">
</td>
<td class="key-title dark unpadded">
<td class="artcl_info text-center">Scitech</td>
<td class="text-center" style="width:10px">
<td class="text-center">
</tr>
<tr class="options_row" style="display: table-row;">
<td colspan="6">
<div class="row article_options">
<div class="row comments_row">
<div id="comments" class="col-md-12">
<div class="text-center article_title top_pad" style="width: 100%;">Comment on This Article</div>
<div id="disqus_thread">
<div id="disqus_container_428272">
</div>
</div>
</td>
</tr>
<tr class="main_row" data-id="ROWID427694">
I want to disable all toggle buttons when one toggle is activated.
$(".option_toggle").click(function(e) {
e.preventDefault();
// Remove click event handler defined above, and add a new one which prevents
// the click from doing anything
$(".option_toggle").off('click').on('click', function(e) {
e.preventDefault();
});
aid = $(this).attr('id');
// Continue with rest of your code ...
});
But is this really what you want? It means once you click a toggle, you cannot click any others. It also means all other toggles still look like links, maybe you should update styling to indicate they are disabled or something like that, eg add a disabled class and style that:
Javascript:
$(".option_toggle").addClass('disabled-link');
CSS:
a.disabled-link {
cursor: default;
color: #666;
text-decoration: none;
}

Add/Remove element-binding in Bindinghandler - knockout

Hello I have created a list and sliced it up and added pagingnation.
All works good but I would like the user to be able to disable pagingnation and just use regular scroll.
My html mark-up looks somewhat like this atm.
<div data-bind="event: { mousewheel: ScrolledPagingnation }">
</div>
Im thinking a custom handler is the right tool for the job? but havent really have any succes adding/removing the event..
<div data-bind="toggleScroll: EnablePagingnation">
</div>
EnablePagingnation is just an observable toggeling a boolen.
How can I implement adding/removing of the 'event object on my element?
Any other suitable approach is welcome aswell.. :)
ko.bindingHandlers.toggleScroll = {
update: function (element, valueAccessor, allBindings) {
var value = valueAccessor();
if (ko.unwrap(value) === true) {
//Pseudo Code
element add "event: { mousewheel: ScrolledPagination }"
} else {
//Clean the Binding
ko.cleanNode(element);
}
}
};
Don't use cleanNode. Ever.
You don't even need a bindingHandler. Just use an expression for the event handler. I used the click event in the snippet below.
vm = {
active: ko.observable(false),
v: ko.observable(1),
addToV: function() {
vm.v(vm.v() + 1);
}
};
ko.applyBindings(vm);
#area {
height: 10rem;
width: 10rem;
background-color: lightgreen;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="area" data-bind="event: {click: active() ? addToV : null}"></div>
Activate:
<input type="checkbox" data-bind="checked: active" />
<div data-bind="text: v"></div>

Simple pop up in jQuery for multiple table rows?

I would like to put a simple pop up in my table to display additional details regarding each row. I just want to ask for ideas on how to show the pop up in every row. Currently the pop up is only shown for the first one.
Here's my code:
#foreach (var name in Model){
<table>
<tr>
<td>Name</td>
<td> <button id="#name.id">Show</button></td>
</tr>
</table>
}
Script:
<script type="text/javascript">
$(function() {
$('#').click(function() { //what should I put in the #? considering that it would have different id's?
$("#popupdiv").dialog({
title: "jQuery Popup from Server Side",
width: 430,
height: 250,
modal: true,
buttons: {
Close: function() {
$(this).dialog('close');
}
}
});
return false;
});
})
View Pop:
<div id="popupdiv" title="Basic modal dialog" style="display: none">
<b> Welcome </b>
</div>
You should use a common class
<td> <button id="#name.id" type="button" class='popup-launcher'>Show</button></td>
Then you can use Class Selector (“.class”)
Selects all elements with the given class.
Script
$('.popup-launcher').click(function() {
//You can access elements id using this object
var id = this.id;
//Rest of your code
$("#popupdiv").dialog({
title: "jQuery Popup from Server Side",
width: 430,
height: 250,
modal: true,
buttons: {
Close: function() {
$(this).dialog('close');
}
}
});
return false;
});
$('button').click(function () {
var row = $(this).closest('tr').index();
alert('In row ' + row)
//$('table').find('tr:eq('+row+')').find('td:nth-child(1)');
//pop code here
})
FIDDLE
This way you can get all the data of the row where you click the button

Dynamically loading content in c# asp.net mvc 4 using javascript not working properly

I'm working on a website where the owner has exhibitions which he can add, edit and delete. The exhibitions are showed per year, once clicking on the 'Read more' button. I'm running into a weird problem with my pages, since I'm loading the content in a new div once clicking on 'Read more' and I need an unique identifier for this div. I'm using id="#Year here" to identify this div, however I run into this problem:
As you can see, it is not loading properly. I have the following code to load in all exhibitions per group:
#if(Model.Exhibitions.Count() > 0)
{
<h3 style="text-align: left; margin-left: 10px; padding-top: 10px;">#Model.Year</h3>
<table class="extable">
<tr>
<th style="width: 15%">#Translations.EXHIBITIONSTARTDATE</th>
<th style="width: 15%">#Translations.EXHIBITIONENDDATE</th>
<th style="width: 15%">#Translations.EXHIBITIONEVENT</th>
<th style="width: 40%">#Translations.EXHIBITIONDESCRIPTION</th>
<th style="width: 15%">#Translations.GALLERY</th>
</tr>
#foreach (Exhibition item in Model.Exhibitions)
{
#Html.Partial("_Exhibition", item)
}
</table>
}
<div class="more-exhi" id="#Model.Next"></div>
<script type="text/javascript">
(function () {
$('.more-exhi##Model.Year').attr('class', '');
$('.show-more').attr('data-year', '#Model.Next');
}) ();
</script>
#Model.Year is the year being send to the controller (for example, 2014). #Model.Next is the next existing year with exhibitions in descending order (for example, 2010). However the code is above is not working right, and I am not sure why. This is my javascript once someone clicks on the button 'Read more':
<script type="text/javascript">
(function () {
var div = $('#exhibitions');
div.find('.show-more').click(function () {
div.find('.more-exhi').hide().load('#Url.Action("Exhibitions", "Exhibition")', { year: $(this).attr('data-year') } ).fadeIn('1500');
div.find('.show-less').show();
});
})();
</script>
Could someone help me fixing this problem? I think I'm overseeing a problem here, as this shouldn't be too difficult.
Try to change this line of code into:
$('.more-exhi#' + #Model.Year).attr('class', '');
:)

Categories