jQuery contextMenu disable items based on div content - javascript

I've been going trough documents of this plugin and it looked promising, but at the end I wasn't able to find out that what I was looking for.
http://medialize.github.com/jQuery-contextMenu/docs.html
Here is what I wanted trough example, this is example of context menu items
$.contextMenu({
selector: '.context-menu-one',
callback: function(key, options) {
var m = "clicked: " + key;
window.console && console.log(m) || alert(m);
},
items: {
"item1": {name: "Clickable", icon: "edit"},
"item2": {
name: "Disabled",
icon: "cut",
disabled: function(key, opt) {
// this references the trigger element
return !this.data('cutDisabled');
}
}
}
});
. If my div (context-menu-one) has some content inside like <span class="test">x</span> disable or enable menu based on that.
So in the case above if my div(context-menu-one) has span with class test that has textvalue x disable menu item2
How would one do that? doesn't have to be code, leading me to good direction = good code if possible at all
Edit:
Here is jsfiddle example :
http://jsfiddle.net/XZEUN/2/
So because first context-menu-one has span with class x the item2 should be disabled, but not for other one

you need to define your own events like in this fiddle
html
<div class="context-menu-one box menu-1">
<strong>right click me</strong>
<span data-item="edit"></span>
</div>​
javascript
events: {
show: function(opt) {
var m = opt.$menu;
$(this).find('span[data-item]').each(function(i, e) { //<-- this search for all span with data-item attribute
var p = $(e).data('item') + 'Disabled'; //<-- here i compose editDisabled
if (m.data(p) === true) m.data(p, 1); //<-- this is for mantain previuos disabling
else m.data(p, true);
});
m = null; //<-- this for breaking possible circular references/memory leaks
},
hide: function(opt) {
var m = opt.$menu;
$(this).find('span[data-item]').each(function(i, e) {
var p = $(e).data('item') + 'Disabled';
if (m.data(p) === 1) m.data(p, true); //<-- this reset the previuos disabling
else m.removeData(p);
});
m = null;
}
}

If you want to disable a context menu binded to an specific selector you can do something like this:
$.contextMenu( 'destroy', '.context-menu-one' );
See example here:
http://jsfiddle.net/ATyjn/

Related

Kendo Menu selection issue

I've a kendo menu to dynamically enable or disable the kendo grid columns. When I select the options from the KendoMenu, the selection is firing twice. I've created the demo version below.
demo
$("#menu").kendoMenu({
dataSource: [{
text: "Menu",
items: ds
}],
openOnClick: true,
closeOnClick: false,
open: function () {
var selector;
$.each(grid.columns, function () {
if (this.hidden) {
selector = "input[data-field='" + this.field + "']";
$(selector).prop("checked", false);
}
});
},
select: function (e) {
// don't show/hide for menu button --- calling twice
if ($(e.item).parent().filter("div").length) return;
console.log("******");
var input = $(e.item).find("input.check");
var field = $(input).data("field");
if ($(input).is(":checked")) {
grid.showColumn(field);
} else {
grid.hideColumn(field);
}
}});
Check the console log while selecting the menu items.
Adding the checkbox to the menu item seems to lead to kendo firing the event for the menu click and the checkbox check. It seems hard to differentiate between the two instances, so it might be better to do something different to indicate the check. The following icons can be used - maybe use the tick icon instead of an actual checkbox:
http://demos.telerik.com/kendo-ui/styling/icons
I've fixed the issue with the updated code
$("#menu").kendoMenu({
dataSource: [{
text: "Menu",
items: ds
}],
openOnClick: true,
closeOnClick: false,
open: function () {
var selector;
$.each(grid.columns, function () {
if (this.hidden) {
selector = "input[data-field='" + this.field + "']";
$(selector).prop("checked", false);
}
});
},
select: function (e) {
// don't show/hide for menu button
if ($(e.item).parent().filter("div").length) return;
var removeItemFlag = false;
var input = $(e.item).find("label");
var selectedValue = input[0].innerHTML;
if(selectedValue)
{
for(var i=0; i< droplist.length; i++){
if(droplist[i] === selectedValue){
removeItemFlag = true
input[0].classList.remove = "fa fa-check-square-o";
input[0].className = "fa fa-square-o";
break;
}
}
var selectedIndex = droplist.indexOf(selectedValue);
if (selectedIndex > -1 && removeItemFlag) {
droplist.splice(selectedIndex, 1);
grid.hideColumn(selectedValue);
}else{
droplist.push(selectedValue);
grid.showColumn(selectedValue);
input[0].className = "fa fa-check-square-o";
}
}
}
});

Removing items from a list that contains items selected from an auto-complete Textbox

I've created an auto-complete Textbox, and a div under it.
When the client select an item from the Textbox, it automaticly appears in the div, after styling with CSS.
What I want to do now is to create an event, that when the client clicks on the styled selected items, they will disappear.
here is the JS code, and jsfiddle under it, for your comfort.
`$(function() {
/* Textbox ID */ $("#destinations").autocomplete({
select: function (event, ui) {
/* div ID */ $("#DestinationsChosen").html(function(i, origText)
{
var SelectedCountry = ui.item.value.toString();
var CurrentText = origText.toString();
if ((CurrentText.indexOf(SelectedCountry) >= 0))
{
alert("Already Exists");
return CurrentText;
}
return CurrentText + " <span class='toButton'>" + SelectedCountry + "</span>";
})
}
http://jsfiddle.net/dgu1ncsj/
thanks :)
Idan
Simplest solution for this existing code is to add the line:
$('.toButton').click(function(){$(this).remove(); });
Just after the $("#DestinationsChosen").html(...) block.
I don't recommend putting script in the tag itself because it's not a good habit, since it doesn't separate concerns. But my short answer has problems too, since it is getting all .toButtons each time and setting the listener again.
The better way to do this, is to create the toButton as a DOM node, and append it to the parent div. This way, you can put the listener on the node itself.
$(function() {
$("#destinations").autocomplete({
select: function (event, ui) {
$("#DestinationsChosen").append(function(i, origText){
var SelectedCountry = ui.item.value.toString();
var CurrentText = origText.toString();
if ((CurrentText.indexOf(SelectedCountry) >= 0))
{
alert("Already Exists");
}
var destination = document.createElement('span');
destination.classList.add('toButton');
destination.appendChild( document.createTextNode(SelectedCountry));
destination.addEventListener('click', function(){ this.remove(); });
return destination;
})
}
});
})
You could simply add an onclick event to each selected item. I have modified your code a bit. See the working code segment below:
$(function() {
$("#destinations").autocomplete({
select: function (event, ui) {
$("#DestinationsChosen").html(function(i, origText)
{
var SelectedCountry = ui.item.value.toString();
var CurrentText = origText.toString();
if ((CurrentText.indexOf(SelectedCountry) >= 0))
{
alert("Already Exists");
return CurrentText;
}
return CurrentText + " <span class='toButton' onclick='$(this).remove();'>" + SelectedCountry + "</span>";
})
}
});
})

dojo/cbtree uncheck all checkboxes and check selected checkbox

I want to make the checkbox work more or less like a radio button in this instance. This is what I have so far. I would like to be able to do this in the treeCheckboxClicked() function so that it would just uncheck all the remaining checkboxs then check the one that was selected.
buildTocTree: function (cp1) {
var self = this;
var toc = new TOC({
checkboxes: false,
enableDelete: true,
deleteRecursive: true,
showRoot: false,
checkBoxes: false,
}, self._viewId + '_tocTree');
toc.on("checkBoxClick", dojo.hitch(this, "treeCheckboxClicked"));
},
treeCheckboxClicked: function (e) {
if (e.checked) {
if (e.subLayers || e.name === 'GISLayer')
this.selectedLayerValue('');
else if (e.layerInfos)
this.selectedLayerValue('');
else
this.selectedLayerValue(e.name);
if (this.selectedLayerValue() != '')
this._selectedGISSourceLayer = e;
else
this._selectedGISSourceLayer = '';
}
}
Without knowing the internal details of the TOC widget, especially its DOM, it's difficult to know how to query all checkboxes within its template. Assuming your treeCheckboxClicked is already getting called, and e.target is the checkbox element itself, the following code should get you close to your desired functionality:
if (e.checked) {
query('checkbox', self.domNode).forEach(function (checkbox) {
checkbox.checked = checkbox != e.target;
});
//...
}
Note: This assumes the dojo/query module has been loaded.
Are you using agsjs.TOC? They have a handler included to do this for you. In the examplesat http://gmaps-utility-gis.googlecode.com/svn/tags/agsjs/latest/examples/toc.html they toggle the function off and on with a button, but you can make it default on and include the following snippet in your tree declaration. (replace DynaLayer 1 with your layer)
toc.on('toc-node-checked', function(evt){
// when check on one layer, turn off everything else on the public safety service.
if (evt.checked && evt.rootLayer && evt.serviceLayer && evt.rootLayer == dynaLayer1){
evt.rootLayer.setVisibleLayers([evt.serviceLayer.id])
}

js code to replace checkbox and closures

The following javascript (prototype 1.6) code hides all checkboxes on the page and inserts a div element with some css style and a click event to act as a fake-checkbox. It also looks out for a label next (or previous) the checkbox, to also trigger the same event.
When I click the div (fake_el) itself, everything works as expected, but when I try the same with the label, it only works one time. after that, the el isn't gonna change - as if it (the el) would be a value-parameter.
Any ideas here?
$$('input[type=checkbox]').each(function(el) {
if (el.visible()) {
var fake_el = new Element('div', { className:'checkbox checkbox_' + el.checked });
var label = (el.next() != null && el.next().tagName === 'LABEL' && el.next().readAttribute('for') === el.id) ? el.next() : undefined;
label = (el.previous() != null && el.previous().tagName === 'LABEL' && el.previous().readAttribute('for') === el.id) ? el.previous() : label;
var action = function(el) {
el.checked = (el.checked) ? false : true;
fake_el.className = 'checkbox checkbox_' + el.checked;
}
fake_el.observe('click', function() { action(el); });
if (label != null) { label.observe('click', function() { c.log(el); action(el); c.log(el); }); }
el.insert({ after:fake_el }).hide();
}
});
I changed a couple items and created a jsFiddle for this. First and foremost, c.log had to be changed to console.log for it to work for me :). After that, the only thing I changed was how the divs were added, since it wasn't working for me with insert. I set up some test data and away I went...
EDIT: Perhaps you don't have a non-label tag between two checkboxes and it is getting confused? Notice I have a br between label and the next checkbox, maybe you need to do something like that.

how to select all class except the clicked element in JQuery?

I have a website developed on Drupal. I use a module called collapsiblock (it is basicly a JQuery plugin) to achieve accordion like effect. It is working fine with me (although it is in Beta). But I want to modify it so that when the user clicks on one item of the accordion the other items will collapsed.
In its current stats, it is working in a way that when the user click on one item, it will check if the item is already collapsed or expanded and it will make the item the opposite. That means if the user clicks on one item it will expand and if he/she clicks on another item it will also expand, but it will not collapse the previously clicked item.
You can see the code below. I know where should I add the code to collapse and how to collapse and expand. My question is: How do I select all the items that have the class '.collapsiblock' except the one that the user has clicked??
Note: the item that has the class '.collapsiblockCollapsed' get collapsed and if this class is removed from the item it get expanded.
// $Id: collapsiblock.js,v 1.6 2010/08/18 19:17:37 gagarine Exp $
Drupal.Collapsiblock = Drupal.Collapsiblock || {};
Drupal.behaviors.collapsiblock = function (context) {
var cookieData = Drupal.Collapsiblock.getCookieData();
var slidetype = Drupal.settings.collapsiblock.slide_type;
var defaultState = Drupal.settings.collapsiblock.default_state;
var slidespeed = parseInt(Drupal.settings.collapsiblock.slide_speed);
$('div.block:not(.collapsiblock-processed)', context).addClass('collapsiblock-processed').each(function () {
var id = this.id;
var titleElt = $(':header:first', this).not($('.content :header',this));
if (titleElt.size()) {
titleElt = titleElt[0];
// Status values: 1 = not collapsible, 2 = collapsible and expanded, 3 = collapsible and collapsed, 4 = always collapsed
var stat = Drupal.settings.collapsiblock.blocks[this.id] ? Drupal.settings.collapsiblock.blocks[this.id] : defaultState;
if (stat == 1) {
return;
}
titleElt.target = $(this).find('div.content');
$(titleElt)
.addClass('collapsiblock')
.click(function () {
var st = Drupal.Collapsiblock.getCookieData();
if ($(this).is('.collapsiblockCollapsed')) {
$(this).removeClass('collapsiblockCollapsed');
if (slidetype == 1) {
$(this.target).slideDown(slidespeed);
}
else {
$(this.target).animate({height:'show', opacity:'show'}, slidespeed);
}
// Don't save cookie data if the block is always collapsed.
if (stat != 4) {
st[id] = 1;
}
}
else {
$(this).addClass('collapsiblockCollapsed');
if (slidetype == 1) {
$(this.target).slideUp(slidespeed);
}
else {
$(this.target).animate({height:'hide', opacity:'hide'}, slidespeed);
}
// Don't save cookie data if the block is always collapsed.
if (stat != 4) {
st[id] = 0;
}
}
// Stringify the object in JSON format for saving in the cookie.
var cookieString = '{ ';
var cookieParts = [];
$.each(st, function (id, setting) {
cookieParts[cookieParts.length] = ' "' + id + '": ' + setting;
});
cookieString += cookieParts.join(', ') + ' }';
$.cookie('collapsiblock', cookieString, {path: Drupal.settings.basePath});
});
// Leave active blocks uncollapsed. If the block is expanded, do nothing.
if (stat == 4 || (cookieData[id] == 0 || (stat == 3 && cookieData[id] == undefined)) && !$(this).find('a.active').size()) {
$(titleElt).addClass('collapsiblockCollapsed');
$(titleElt.target).hide();
}
}
});
};
Drupal.Collapsiblock.getCookieData = function () {
var cookieString = $.cookie('collapsiblock');
return cookieString ? Drupal.parseJson(cookieString) : {};
};
UPDATE:
Problem has been solved by adding the following code:
$('.collapsiblock').not(this).each(function(){
$(this).addClass('collapsiblockCollapsed');
$(this.target).animate({height:'hide', opacity:'hide'}, slidespeed);
});
just above the following line:
$(this).removeClass('collapsiblockCollapsed');
Use the not selector.
Example:
$('.collapsiblock').click(function(){
$('.collapsiblock').not(this).each(function(){
$(this).slideUp();
});
$(this).slideDown();
})
Try this,This is a better way because if you use each function it will load and in the future when you have more than a thousand div it will take a long time to slide up and slide down.
Example:
$('.collapsiblock').click(function(){
$('.collapsiblock').not(this).slideUp();
$(this).slideDown();
});
You could keep track of which element has already been clicked with your own jquery click handler and jquery's data(...) function. Then filter iterating your .collapsiblock items with jquery's filter (...) function to include the items you need.

Categories

Resources