Mootools: How to Allow and Disallow var drag depending on checkbox checked or not?
window.addEvent('domready',function() {
var z = 2;
$$('#dragable').each(function(e) {
var drag = new Drag.Move(e,{
grid: false,
preventDefault: true,
onStart: function() {
e.setStyle('z-index',z++);
}
});
});
});
function check(tag){
if(tag.checked){
//checkbox checked
//How to Disallow Drag.Move for #dragable ?
//Unfortunately so it does not work - drag.destroy(); drag.removeEvents();
}else{
//How to Allow Drag.Move for #dragable ?
}
}
<input type="checkbox" onClick="check(this);">
<div id="dragable">Drag-able DIV</div>
Store the instance of Drag in MooTools Element Store so when the checkbox is clicked, we can retrieve this instance and manipulate it.
Drag.Move is an extension to the base Drag class, and if you see the docs, you will notice it has two methods for this situation:
attach
detach
You need to call these methods on the drag object that gets created when you call new Drag.Move(..) to enable or disable dragging.
So first create the drag object as you are already doing:
var drag = new Drag.Move(e, {
...
});
And then store a reference of this drag object inside the Element Store for later retrieval.
e.store('Drag', drag);
You can use any key you want here - I've used "Drag".
Then later in the check function, retrieve the drag object, and call attach or detach on it depending on the state of the checkbox.
function check(elem) {
var drag = elem.retrieve('Drag'); // retrieve the instance we stored before
if(elem.checked) {
drag.detach(); // disable dragging
}
else {
drag.attach(); // enable dragging
}
}
See your example modified to work this the checkbox.
On a side note, if you are retrieving an element by id, you don't need to use $$ as ideally there should only be only element with that id. $$("#dragable") is just too redundant and less performant. Use document.id('dragable') or $("dragable") instead.
Related
I want users to be able to click on some text inside the node and do some action, like show some dialog or open some other window. Is this possible?
In the documentation there is something like :
text-events : Whether events should occur on an element if the label receives an event; may be yes or no. You may want a style applied to the text on :active so you know the text is activatable.
it seems like the thing but there is no example how to use it on the label level..
EDIT: example
on the diagram
how I imagine it could be in the code:
label_element.on('tap', function(event){
// cyTarget holds a reference to the label
var evtTarget = event.cyTarget;
//...
});
or
cy.on('tap', function(event){
var evtTarget = event.cyTarget;
//evtTarget holds element but I can somehow get the text which got tap event??
});
According Cytoscape.js documentation, you may try do this using
cy.on('tap')
, like this:
Examples
Bind to events that bubble up from elements matching the specified node selector:
cy.on('tap', 'node', { foo: 'bar' }, function(evt){
console.log( evt.data.foo ); // 'bar'
var node = evt.cyTarget;
console.log( 'tapped ' + node.id() );
});
Bind to all tap events that the core receives:
cy.on('tap', function(event){
// cyTarget holds a reference to the originator
// of the event (core or element)
var evtTarget = event.cyTarget;
if( evtTarget === cy ){
console.log('tap on background');
} else {
console.log('tap on some element');
}
});
At http://js.cytoscape.org/#cy.on
If text-events: yes, tapping a node's label will trigger tap on the node.
If you want to have arbitrary UIs on top of nodes that can be independently interacted with, then you should create a separate layer in the DOM.
Rationale : The labels are relatively simple in Cytoscape.js, because supporting complex ones would be on the same order of complexity as the DOM. In that case, it's better to use the DOM as a layer on top of the graph rather than to reimplement it in Cytoscape.js.
I am trying to bind checked on a checkbox input which resides inside an anchor tag which, itself, is click bound.
Whilst I am aware that this may not be entirely valid (interactive content may not be descendant of anchor-tags), I would still like to get it to work as intended - even if just to understand it.
Currently, only the outside click event is handled and the click never arrives at my checkbox.
An example of what I am trying to achieve is here: http://jsfiddle.net/fzmppu93/2/
Having had a look through the KnockoutJS documentation, I tried clickBubble: true on the anchor-tag's click binding - to no avail.
The use case, if you're interested, is an unordered list containing links - each of these "links" contains information on a TV show: title, actors, image, synopsis. The show is selectable, but there are also 'quick-actions' to mark it as seen, star it, and so forth.
Is there another way of making a checkbox work inside an anchor-tag?
I have written a custom binding handler that is similar to "clickBubble", however mines allows to you to prevent the propagation of any event.
Here is the binding handler:
ko.bindingHandlers.preventBubble = {
init: function (element, valueAccessor) {
var eventName = ko.utils.unwrapObservable(valueAccessor());
var arr = eventName;
if (!eventName.pop) {
arr = [arr];
}
for (var p in arr) {
ko.utils.registerEventHandler(element, arr[p], function (event) {
event.cancelBubble = true;
if (event.stopPropagation) {
event.stopPropagation();
}
});
}
}
};
And here is a working fiddle of your example.
This is my code:
REDIPS.drag.event.deleted = function(){
//TODO
}
This is fired when an object is dropped in the 'trash' cell. I am trying to get the object id before it gets deleted, because I alse want to delete it in the database. How can I do this?
In the redips documentation it says :
deleted(cloned) Event handler invoked if element is deleted (dropped
to the "trash" table cell). Parameters: {Boolean} cloned Optional True
if cloned element is directly moved to the trash (in one move). If
cloned element is dropped to the table and then moved to the trash
then "cloned" parameter will be set to false.
src:http://www.redips.net/javascript/redips-drag-documentation/#event:deleted
Inside most of REDIPS.drag event handlers it's possible to retrieve reference to the dragged DIV element with rd.obj (or REDIPS.drag.obj). Here is how:
rd.event.clicked = function(currentCell) {
classDetailPage.lastGridItemId = rd.obj.id;
};
rd.event.deleted = function() {
classDetailPage.deleteGridItem(classDetailPage.lastGridItemId);
};
... or simply use reference to DIV element directly in "deleted" event handler:
rd.event.deleted = function() {
classDetailPage.deleteGridItem(rd.obj.id);
};
In the clicked function, you can set a backup for the div that will be deleted.
rd.event.clicked=function(currentCell){
classDetailPage.lastGridItemId = $(currentCell).find("div")[0].id;
};
rd.event.deleted = function(){
classDetailPage.deleteGridItem(classDetailPage.lastGridItemId);
};
I want to obtain the exact details for the item on a web page that has been clicked on, using jquery.
That item can be a form item (like a checkbox, text box, text area etc) or section of text (in a paragraph or div or other) or list or image ...
What I figured out is the following--
$(function(){
$('*')
.bind('click', function(event) {
//now obtain details of item that has been clicked on...
});
});
Now, I want the exact details- viz the div id/form id/paragraph #, ie all details for that particular item. How do i get this data? I understand that this data is available in the DOM but I just dont know how to get it in this particular case...
Probably the best way to do to use the target property of the event. By default, this returns a non-jQuery object, which isn't particularly useful, however wrapping it in $() solves this issue:
$(function() {
$(document).bind('click', function(event) {
var element = $(event.target);
alert(element.height()); // Get height
alert(element.attr('id')); // Get ID attribute
// ...
});
});
If you want to fix your current method, inside your click() handler, you can access the properties of that element using .attr(), and friends:
$(function() {
$('*').bind('click', function(event) {
alert($(this).height()); // Get height
alert($(this).attr('id')); // Get ID attribute
// ...
});
});
$(this) in the scope of the function references the element that was clicked. There is a list of functions that will return attributes here and here in the jQuery docs. $.attr('id') will return the element's ID, among other things, and $.data() will return data-* attributes.
To get attributes of parent elements, simply use $(this).parent(). For example, to get the ID of the form that contains the clicked element, use $(this).closest('form').attr('id');. Everything is relative to the clicked element ($(this)), so you can just use the DOM traversal functions.
However, using $('*').bind() is incredibly inefficient; you're binding an event handler to every element on the page, when really you should delegate events with .on() (jQuery 1.7+):
$(function() {
$('body').on('click', '*', function(event) {
alert($(this).height()); // Get height
alert($(this).attr('id')); // Get ID attribute
// ...
});
});
This approach only binds one event to <body> instead of an event to every element on the page.
Use the target of click event on page
$(document).click(function(event){
/* store native dom node*/
var tgt=event.target;
/* store jQuery object of dom node*/
var $tgt=$(tgt);
/* example element details*/
var details={ id : tgt.id, height: $tgt.height(), tag : tgt.tagName}
console.log( details)
})
Look at the event.target, and then you can use jQuery's .parents() method to look at every ancestor:
$(document).on('click', function(event) {
var $t = $(event.target); // the element that was actually clicked
var $p = $t.parents(); // the target's parents
var $form = $p.filter('form').first(); // the enclosing form, if it exists
});
I'm having a little issue with an application I'm making. I have a page where the user edits a document via dragging modules into the page or "canvas" area.
http://thinktankdesign.ca/temp_img.jpg
When the page is loaded, javascript haves the modules collapsible (like above). However after the user drags in a new module the effect is applied again some new modules can collapse as well. here is the problem. each time a module loads the same effect gets applied to the modules that already can collapse. It ends up breaking their animations.
heres the code that gets executed on page load.
//make colapsible
$("h1.handle").click(function() {
var object = $(this);
v$(this).next().toggle("fast", colapsible_class(object));
vreturn false;
}).addClass("open");
and heres the code that gets executed in the creation of a module via ajax
function get_module(id){
var template = $('input[name=template]').val();
$.post(window.location.href, { template: template, module: id, mode: 'create' },
function(data){
$(data).insertBefore(".target_wrapper");
//enable deletion of module
$(".js_no_modules").slideUp("slow");
$(enable_module_deletion());
//show delete button
$("button[name=delete]").show();
//make colapsible
$("h1.handle").click(function() {
var object = $(this);
$(this).next().toggle("fast", colapsible_class(object));
return false;
}).addClass("open");
}
);
}
I need a solid way of preventing the toggle effect to be applied to the same module twice
Use jQuery 1.3 live events instead.
//make colapsible
$("h1.handle").live("click", function() {
var object = $(this);
v$(this).next().toggle("fast", colapsible_class(object));
vreturn false;
}).addClass("open");
and then eliminate the click declaration in the second block of code, changing it to $("h1.handle").addClass("open");
Live events bind all current and future matching elements with an event.
In your Ajax success handler try the following:
//make collapsible
$("h1.handle:not(.open)").click(function() {
var object = $(this);
$(this).next().toggle("fast", colapsible_class(object));
return false;
}).addClass("open");
The best way to solve your problem is, instead of using $("h1.handle") on the AJAX callback, go for $(data).find("h1.handle"). Something like,
var x = $(data);
x.insertBefore(...);
/* your other code */
x.find('h1.handle').click(...).addClass(...);
Like that, only the newly added items will have the event bounded. The already present ones will not be touched.
If we want to answer your question instead of just solving your problem, then we have several alternatives, such as:
store, in your objects, that the onclick event handler has been set so that you don't set it twice
always bind the onclick event, but always unbind it first
use jQuery's live events and the addClass open only on the newly created items.
IMO, the first one is the easiest. You can accomplish it by using jQuery's data(). Then you could do something like:
$("h1.handle").each(function() {
var me = $(this);
// if already has click handler, don't do anything
if (me.data('click_set') != null) { return true; }
// otherwise, store the data and bind the click event
me.data('click_set', true).click(function() {
/* the code you already have on the click handler */
}).addClass('open');
}
The second alternative involves storing the function that you pass inline to the click event binder in a variable, and then using jQuery's unbind to disable it.