Similate double click on drag end - jquery UI - javascript

Here I have a table with two column. In 1st is draggable div object so:
$(function() {
$( "div.available" ).draggable({
snap: "div.timeline-axis-grid"
});
});
and in 2nd column is timeline table based on google visualisation API.
http://jsbin.com/oLaqoToH/5
You will see when make double click on timeline table then you create a new div object into timeline.
Now I want to simulate double click when I end dragging object from 1st column to timeline.
So simple I want to add a div object from 1st column to timeline with this little hack.
Is there any way to do this?
Is this possbile to use with jquery?
How I can simulate dobuleclick on draggable ending?
UPDATE: I dont need to simulate double clikc becouse this action has an function:
http://almende.github.io/chap-links-library/js/timeline/timeline.js
/**
* Double click event occurred for an item
* #param {Event} event
*/
links.Timeline.prototype.onDblClick = function (event) {
var params = this.eventParams,
options = this.options,
dom = this.dom,
size = this.size;
event = event || window.event;
if (params.itemIndex != undefined) {
var item = this.items[params.itemIndex];
if (item && this.isEditable(item)) {
// fire the edit event
this.trigger('edit');
}
}
else {
if (options.editable) {
// create a new item
// get mouse position
params.mouseX = links.Timeline.getPageX(event);
params.mouseY = links.Timeline.getPageY(event);
var x = params.mouseX - links.Timeline.getAbsoluteLeft(dom.content);
var y = params.mouseY - links.Timeline.getAbsoluteTop(dom.content);
// create a new event at the current mouse position
var xstart = this.screenToTime(x);
var xend = this.screenToTime(x + size.frameWidth / 10); // add 10% of timeline width
if (options.snapEvents) {
this.step.snap(xstart);
this.step.snap(xend);
}
var content = options.NEW;
var group = this.getGroupFromHeight(y); // (group may be undefined)
var preventRender = true;
this.addItem({
'start': xstart,
'end': xend,
'content': content,
'group': this.getGroupName(group)
}, preventRender);
params.itemIndex = (this.items.length - 1);
this.selectItem(params.itemIndex);
this.applyAdd = true;
// fire an add event.
// Note that the change can be canceled from within an event listener if
// this listener calls the method cancelAdd().
this.trigger('add');
if (this.applyAdd) {
// render and select the item
this.render({animate: false});
this.selectItem(params.itemIndex);
}
else {
// undo an add
this.deleteItem(params.itemIndex);
}
}
}
links.Timeline.preventDefault(event);
};
How I can use this function to drag object to timeline instead to use doubleclick simulation??? Thanks!

$( "div.available" ).draggable({
snap: "div.timeline-axis-grid",
stop: function(e, ui) {
$(this).dblclick();
}
});

This worked for me:
$(function() {
$( "div.timeline-event" ).draggable({
snap: "div.timeline-axis-grid",
stop: function(event){ timeline.onDblClick(event); }
});
});

Related

How can I prevent a jQuery-UI accordion from selecting the wrong item on mouse over?

I'm using a jquery-ui accordion that opens a section on mouse hover instead of on click, however I've noticed if you mouse over multiple items quickly, the item that gets selected is the first item your mouse was over, not the last one.
You can test this out on either their demo page or this copy of the demo on jsfiddle: Simply mouse over the last item so it expands, then move your mouse quickly to the first item, passing the 3nd and 2rd item as you go. The end result is the 3nd item is open, although your mouse is over the first item. (You can also do it in the reverse, but its easiest to duplicate the problem going from bottom to top)
How can I prevent this behavior from happening so the final item that is open is the one the mouse is over, and not the first item the mouse went over?
jQuery UI has implemented the hoverIntent functionality for their accordion selections to combat animation queue issues. The snippet they used is as follows ->
//on DOM ready
$(function() {
$("#accordion").accordion({
event: "click hoverintent"
);
});
var cfg = ($.hoverintent = {
sensitivity: 7,
interval: 100
});
$.event.special.hoverintent = {
setup: function() {
$( this ).bind( "mouseover", jQuery.event.special.hoverintent.handler );
},
teardown: function() {
$( this ).unbind( "mouseover", jQuery.event.special.hoverintent.handler );
},
handler: function( event ) {
var self = this,
args = arguments,
target = $( event.target ),
cX, cY, pX, pY;
function track( event ) {
cX = event.pageX;
cY = event.pageY;
};
pX = event.pageX;
pY = event.pageY;
function clear() {
target
.unbind( "mousemove", track )
.unbind( "mouseout", arguments.callee );
clearTimeout( timeout );
}
function handler() {
if ( ( Math.abs( pX - cX ) + Math.abs( pY - cY ) ) < cfg.sensitivity ) {
clear();
event.type = "hoverintent";
// prevent accessing the original event since the new event
// is fired asynchronously and the old event is no longer
// usable (#6028)
event.originalEvent = {};
jQuery.event.handle.apply( self, args );
} else {
pX = cX;
pY = cY;
timeout = setTimeout( handler, cfg.interval );
}
}
var timeout = setTimeout( handler, cfg.interval );
target.mousemove( track ).mouseout( clear );
return true;
}
};

A Function to Check if the Mouse is Still Hovering an Element Every 10 Milliseconds (and run a function if it is)

I was wondering if there is a function to be run after an element (e.g. div class="myiv") is hovered and check every X milliseconds if it's still hovered, and if it is, run another function.
EDIT: This did the trick for me:
http://jsfiddle.net/z8yaB/
For most purposes in simple interfaces, you may use jquery's hover function and simply store in a boolean somewhere if the mouse is hover. And then you may use a simple setInterval loop to check every ms this state. You yet could see in the first comment this answer in the linked duplicate (edit : and now in the other answers here).
But there are cases, especially when you have objects moving "between" the mouse and your object when hover generate false alarms.
For those cases, I made this function that checks if an event is really hover an element when jquery calls my handler :
var bubbling = {};
bubbling.eventIsOver = function(event, o) {
if ((!o) || o==null) return false;
var pos = o.offset();
var ex = event.pageX;
var ey = event.pageY;
if (
ex>=pos.left
&& ex<=pos.left+o.width()
&& ey>=pos.top
&& ey<=pos.top+o.height()
) {
return true;
}
return false;
};
I use this function to check that the mouse really leaved when I received the mouseout event :
$('body').delegate(' myselector ', 'mouseenter', function(event) {
bubbling.bubbleTarget = $(this);
// store somewhere that the mouse is in the object
}).live('mouseout', function(event) {
if (bubbling.eventIsOver(event, bubbling.bubbleTarget)) return;
// store somewhere that the mouse leaved the object
});
You can use variablename = setInterval(...) to initiate a function repeatedly on mouseover, and clearInterval(variablename) to stop it on mouseout.
http://jsfiddle.net/XE8sK/
var marker;
$('#test').on('mouseover', function() {
marker = setInterval(function() {
$('#siren').show().fadeOut('slow');
}, 500);
}).on('mouseout', function() {
clearInterval(marker);
});​
jQuery has the hover() method which gives you this functionality out of the box:
$('.myiv').hover(
function () {
// the element is hovered over... do stuff
},
function () {
// the element is no longer hovered... do stuff
}
);
To check every x milliseconds if the element is still hovered and respond adjust to the following:
var x = 10; // number of milliseconds
var intervalId;
$('.myiv').hover(
function () {
// the element is hovered over... do stuff
intervalId = window.setInterval(someFunction, x);
},
function () {
// the element is no longer hovered... do stuff
window.clearInterval(intervalId);
}
);
DEMO - http://jsfiddle.net/z8yaB/
var interval = 0;
$('.myiv').hover(
function () {
interval = setInterval(function(){
console.log('still hovering');
},1000);
},
function () {
clearInterval(interval);
}
);

Trying to get my slideshow plugin to infinitely loop (by going back to the first state)

I wrote a slideshow plugin, but for some reason maybe because I've been working on it all day, I can't figure out exactly how to get it to go back to state one, once it's reached the very last state when it's on auto mode.
I'm thinking it's an architectual issue at this point, because basically I'm attaching the amount to scroll left to (negatively) for each panel (a panel contains 4 images which is what is currently shown to the user). The first tab should get: 0, the second 680, the third, 1360, etc. This is just done by calculating the width of the 4 images plus the padding.
I have it on a setTimeout(function(){}) currently to automatically move it which works pretty well (unless you also click tabs, but that's another issue). I just want to make it so when it's at the last state (numTabs - 1), to animate and move its state back to the first one.
Code:
(function($) {
var methods = {
init: function(options) {
var settings = $.extend({
'speed': '1000',
'interval': '1000',
'auto': 'on'
}, options);
return this.each(function() {
var $wrapper = $(this);
var $sliderContainer = $wrapper.find('.js-slider-container');
$sliderContainer.hide().fadeIn();
var $tabs = $wrapper.find('.js-slider-tabs li a');
var numTabs = $tabs.size();
var innerWidth = $wrapper.find('.js-slider-container').width();
var $elements = $wrapper.find('.js-slider-container a');
var $firstElement = $elements.first();
var containerHeight = $firstElement.height();
$sliderContainer.height(containerHeight);
// Loop through each list element in `.js-slider-tabs` and add the
// distance to move for each "panel". A panel in this example is 4 images
$tabs.each(function(i) {
// Set amount to scroll for each tab
if (i === 1) {
$(this).attr('data-to-move', innerWidth + 20); // 20 is the padding between elements
} else {
$(this).attr('data-to-move', innerWidth * (i) + (i * 20));
}
});
// If they hovered on the panel, add paused to the data attribute
$('.js-slider-container').hover(function() {
$sliderContainer.attr('data-paused', true);
}, function() {
$sliderContainer.attr('data-paused', false);
});
// Start the auto slide
if (settings.auto === 'on') {
methods.auto($tabs, settings, $sliderContainer);
}
$tabs.click(function() {
var $tab = $(this);
var $panelNum = $(this).attr('data-slider-panel');
var $amountToMove = $(this).attr('data-to-move');
// Remove the active class of the `li` if it contains it
$tabs.each(function() {
var $tab = $(this);
if ($tab.parent().hasClass('active')) {
$tab.parent().removeClass('active');
}
});
// Add active state to current tab
$tab.parent().addClass('active');
// Animate to panel position
methods.animate($amountToMove, settings);
return false;
});
});
},
auto: function($tabs, settings, $sliderContainer) {
$tabs.each(function(i) {
var $amountToMove = $(this).attr('data-to-move');
setTimeout(function() {
methods.animate($amountToMove, settings, i, $sliderContainer);
}, i * settings.interval);
});
},
animate: function($amountToMove, settings, i, $sliderContainer) {
// Animate
$('.js-slider-tabs li').eq(i - 1).removeClass('active');
$('.js-slider-tabs li').eq(i).addClass('active');
$('#js-to-move').animate({
'left': -$amountToMove
}, settings.speed, 'linear', function() {});
}
};
$.fn.slider = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
return false;
}
};
})(jQuery);
$(window).ready(function() {
$('.js-slider').slider({
'speed': '10000',
'interval': '10000',
'auto': 'on'
});
});​
The auto and animate methods are where the magic happens. The parameters speed is how fast it's animated and interval is how often, currently set at 10 seconds.
Can anyone help me figure out how to get this to "infinitely loop", if you will?
Here is a JSFiddle
It would probably be better to let go of the .each() and setTimeout() combo and use just setInterval() instead. Using .each() naturally limits your loop to the length of your collection, so it's better to use a looping mechanism that's not, and that you can break at any point you choose.
Besides, you can readily identify the current visible element by just checking for .active, from what I can see.
You'd probably need something like this:
setInterval(function () {
// do this check here.
// it saves you a function call and having to pass in $sliderContainer
if ($sliderContainer.attr('data-paused') === 'true') { return; }
// you really need to just pass in the settings object.
// the current element you can identify (as mentioned),
// and $amountToMove is derivable from that.
methods.animate(settings);
}, i * settings.interval);
// ...
// cache your slider tabs outside of the function
// and just form a closure on that to speed up your manips
var slidertabs = $('.js-slider-tabs');
animate : function (settings) {
// identify the current tab
var current = slidertabs.find('li.active'),
// and then do some magic to determine the next element in the loop
next = current.next().length >= 0 ?
current.next() :
slidertabs.find('li:eq(0)')
;
current.removeClass('active');
next.addClass('active');
// do your stuff
};
The code is not optimized, but I hope you see where I'm getting at here.

bug in closing tooltip on esc

I am just a beginner in jquery. I have used the tooltip script from this site. http://www.twinhelix.com/dhtml/supernote/demo/#demo4 .They used the following function to close the tooltip on clicking the close button.
<script type="text/javascript">
// SuperNote setup: Declare a new SuperNote object and pass the name used to
// identify notes in the document, and a config variable hash if you want to
// override any default settings.
var supernote = new SuperNote('supernote', {});
// Available config options are:
//allowNesting: true/false // Whether to allow triggers within triggers.
//cssProp: 'visibility' // CSS property used to show/hide notes and values.
//cssVis: 'inherit'
//cssHid: 'hidden'
//IESelectBoxFix: true/false // Enables the IFRAME select-box-covering fix.
//showDelay: 0 // Millisecond delays.
//hideDelay: 500
//animInSpeed: 0.1 // Animation speeds, from 0.0 to 1.0; 1.0 disables.
//animOutSpeed: 0.1
// You can pass several to your "new SuperNote()" command like so:
//{ name: value, name2: value2, name3: value3 }
// All the script from this point on is optional!
// Optional animation setup: passed element and 0.0-1.0 animation progress.
// You can have as many custom animations in a note object as you want.
function animFade(ref, counter)
{
//counter = Math.min(counter, 0.9); // Uncomment to make notes translucent.
var f = ref.filters, done = (counter == 1);
if (f)
{
if (!done && ref.style.filter.indexOf("alpha") == -1)
ref.style.filter += ' alpha(opacity=' + (counter * 100) + ')';
else if (f.length && f.alpha) with (f.alpha)
{
if (done) enabled = false;
else { opacity = (counter * 100); enabled=true }
}
}
else ref.style.opacity = ref.style.MozOpacity = counter*0.999;
};
supernote.animations[supernote.animations.length] = animFade;
// Optional custom note "close" button handler extension used in this example.
// This picks up click on CLASS="note-close" elements within CLASS="snb-pinned"
// notes, and closes the note when they are clicked.
// It can be deleted if you're not using it.
addEvent(document, 'click', function(evt)
{
var elm = evt.target || evt.srcElement, closeBtn, note;
while (elm)
{
if ((/note-close/).test(elm.className)) closeBtn = elm;
if ((/snb-pinned/).test(elm.className)) { note = elm; break }
elm = elm.parentNode;
}
if (closeBtn && note)
{
var noteData = note.id.match(/([a-z_\-0-9]+)-note-([a-z_\-0-9]+)/i);
for (var i = 0; i < SuperNote.instances.length; i++)
if (SuperNote.instances[i].myName == noteData[1])
{
setTimeout('SuperNote.instances[' + i + '].setVis("' + noteData[2] +
'", false, true)', 100);
cancelEvent(evt);
}
}
});
// Extending the script: you can capture mouse events on note show and hide.
// To get a reference to a note, use 'this.notes[noteID]' within a function.
// It has properties like 'ref' (the note element), 'trigRef' (its trigger),
// 'click' (whether its shows on click or not), 'visible' and 'animating'.
addEvent(supernote, 'show', function(noteID)
{
// Do cool stuff here!
});
addEvent(supernote, 'hide', function(noteID)
{
// Do cool stuff here!
});
// If you want draggable notes, feel free to download the "DragResize" script
// from my website http://www.twinhelix.com -- it's a nice addition :).
</script>
I have tried to edit this function for closing the tooltip on clicking the esckey too. But i couldn't. How can i modify the function?

TinyMCE - custom link button - "add link" is fine, but can't find any documentation for "edit link" and accessing link attributes

I've added a custom button to TinyMCE which brings up a bespoke link-picker. When the user selects some text and clicks the button the dialog appears and when they've picked the url I'm using execCommand('insertHTML', false, "<a href... etc">) on the selection.
This works fine - now, when the link has already been created, and the user wants to edit it, they click the link button again (when the cursor is inside the linked text as normal), but then here is the situation - I don't know how to access the already created link and it's attributes to then load up and populate the dialogue again!
Have search TinyMCE site, Stack, Google in general. Hoping for (and also slightly dreading) a simple answer - but if not, a complex one will be fine!!
If anybody knows the answer or can point me to it, I'd be extremely grateful. Thanks in advance,
Rob
EDIT - bits of my code to explain need
In the TinyMCE init:
setup: function (ed) {
ed.addButton("link", {
title: "Link",
onclick: function (evt) {
Intranet.TextEditor._loadUrlDialog(jQueryTextAreaObject, evt);
}
});
}
The function which is called above:
_loadUrlDialog: function (jQueryTextAreaObject, clickEvent) {
var mce = $(jQueryTextAreaObject).tinymce();
var isSelected = mce.selection.getContent().length != 0 ? true : false;
if (isSelected) {
Intranet.UrlDialog.Fn.LoadDialog("", true, "", function (url, target, title) {
var theTarget = target == false ? "_self" : "_blank";
var link = "" + mce.selection.getContent() + "";
mce.execCommand('insertHTML', false, link); // creates new link
});
}
else {
/// THIS IS THE MISSING BIT!
};
}
You have two ways of achieving this:
When pushing the button you check for the selection parent node. If the node is a link then you can get the link information from the html a-element. To populate your dialogue you will know what to do.
The other option is to add a contextmenu on rightclick, which will provide the necessary functionalities.
Here is the plugin code for this (keep in mind that you will have to add "customcontextmenu" to the plugin-setting of your tinymce).
/**
* editor_plugin_src.js
*
* Plugin for contextmenus.
*/
(function() {
var Event = tinymce.dom.Event, each = tinymce.each, DOM = tinymce.DOM;
tinymce.PluginManager.requireLangPack('customcontextmenu');
/**
* This plugin a context menu to TinyMCE editor instances.
*
* #class tinymce.plugins.customcontextmenu
*/
tinymce.create('tinymce.plugins.customcontextmenu', {
/**
* Initializes the plugin, this will be executed after the plugin has been created.
* This call is done before the editor instance has finished it's initialization so use the onInit event
* of the editor instance to intercept that event.
*
* #method init
* #param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
* #param {string} url Absolute URL to where the plugin is located.
*/
init : function(ed) {
var t = this, lastRng;
t.editor = ed;
// Registiere commands
ed.addCommand('edit_inline_element', function() {
//edit_inline_element(ed, ed.right_clicked_node); //ed.right_clicked_node is the actually clicked node
//call or do whatever you need here
});
// delete link
ed.addCommand('delete_inline_element', function() {
$(ed.right_clicked_node).replaceWith($(ed.right_clicked_node).html());
});
// assign the right clicked node (it is the evt.target)
ed.onClick.add(function(ed, evt) {
if (evt.button == 2) ed.right_clicked_node = evt.target;
});
/**
* This event gets fired when the context menu is shown.
*
* #event onContextMenu
* #param {tinymce.plugins.ContextMenu} sender Plugin instance sending the event.
* #param {tinymce.ui.DropMenu} menu Drop down menu to fill with more items if needed.
*/
t.onContextMenu = new tinymce.util.Dispatcher(this);
ed.onContextMenu.add(function(ed, e) {
if (!e.ctrlKey) {
// Restore the last selection since it was removed
if (lastRng)
ed.selection.setRng(lastRng);
var menu = t._getMenu(ed);
if ((typeof menu).toLowerCase() == 'object')
{
menu.showMenu(e.clientX, e.clientY);
Event.add(ed.getDoc(), 'click', function(e) {
hide(ed, e);
});
Event.cancel(e);
}
// sonst Standardmenu anzeigen
}
});
ed.onRemove.add(function() {
if (t._menu)
t._menu.removeAll();
});
function hide(ed, e) {
lastRng = null;
// Since the contextmenu event moves
// the selection we need to store it away
if (e && e.button == 2) {
lastRng = ed.selection.getRng();
return;
}
if (t._menu) {
t._menu.removeAll();
t._menu.destroy();
Event.remove(ed.getDoc(), 'click', hide);
}
};
ed.onMouseDown.add(hide);
ed.onKeyDown.add(hide);
},
_getMenu: function(ed){
var t = this, m = t._menu, se = ed.selection, col = se.isCollapsed(), el = se.getNode() || ed.getBody(), am, p1, p2;
if (m) {
m.removeAll();
m.destroy();
}
p1 = DOM.getPos(ed.getContentAreaContainer());
p2 = DOM.getPos(ed.getContainer());
m = ed.controlManager.createDropMenu('contextmenu', {
offset_x : p1.x + ed.getParam('contextmenu_offset_x', 0),
offset_y : p1.y + ed.getParam('contextmenu_offset_y', 0),
constrain : 1
});
t._menu = m;
if ((typeof ed.right_clicked_node) !== "undefined" && ed.right_clicked_node.nodeName.toLowerCase() == 'a' )
{
m.add({
title: $(ed.right_clicked_node).attr('title'),
});
m.addSeparator();
m.add({
title: 'Edit link',
icon: 'edit_inline_element',
cmd: 'edit_link'
});
m.add({
title: 'Delete link',
icon: 'delete_inline_element',
cmd: 'delete_link'
});
t.onContextMenu.dispatch(t, m, el, col);
return m;
}
else {
// kein Menu anzeigen
return 0;
}
}
});
// Register plugin
tinymce.PluginManager.add('customcontextmenu', tinymce.plugins.customcontextmenu);
})();

Categories