How can I interact with the tooltip in jQuery?
You know, the little pop-up appearing when you hover an <a> element or an <img>.
I wanted to make that one follow my cursor when I move onto that tag. Exactly like this.
You might wanna look at jQuery UI's tooltip or the QTip plugin.
A part for mouse tracking tooltip: Mouse tracking
I didn't not tried it but it seems nice: one more
Here is simple jquery plugin for custom tooltip. jsFiddle
You can specify mouseFollow: true to achieve movable tooltip that follows cursor.
JS
(function ($) {
$.fn.tooltip = function (options) {
var defaults = {
background: '#fff',
border: '1px solid #999',
color: 'black',
rounded: false,
mouseFollow: false,
textChangeOnClick: false
},
settings = $.extend({}, defaults, options);
this.each(function () {
var $this = $(this),
title = null,
hovering = null;
//set class
if (!settings.textChangeOnClick) {
$this.addClass('_tooltip');
}
$(this).data('title', $this.attr('title'))
$(this).attr('title', '');
$this.hover(
// mouse over
function (e) {
//check change
if ($this.attr('title') != '') {
if ($this.attr('title') != $this.data('title')) {
$this.data('title', $this.attr('title'));
$this.attr('title','');
}
} else {
$this.removeAttr('title');
}
$this.attr('title', '');
hovering = true;
$('#tooltip').remove();
//create box
if ($this.data('title') != '') {
$('<div id="tooltip" />')
.appendTo('body')
.text($this.data('title'))
.hide()
.css({
backgroundColor: settings.background,
color: settings.color,
border: settings.border,
top: e.pageY + 10,
left: e.pageX + 20
})
.fadeIn(500);
}
if (settings.rounded) {
$('#tooltip').addClass('rounded');
}
},
//mouse out
function () {
hovering = false;
$('#tooltip').remove();
});
//text change
if (settings.textChangeOnClick) {
//on click
$this.on('click', function () {
if (hovering) {
//set new
$this.data('title',$(this).attr('title'));
$(this).attr('title', '');
$('#tooltip').text($this.data('title'));
}
});
}
//mouse follow
if (settings.mouseFollow) {
$this.mousemove(function (e) {
$('#tooltip').css({
top: e.pageY + 10,
left: e.pageX + 20
});
});
}
});
return this;
}
})(jQuery);
SET PLUGIN FOR ELEMENT
$('a').tooltip({
mouseFollow: true
});
HTML
CSS
#tooltip
{
border: 1px solid #BFBFBF;
float: left;
font-size: 11px;
max-width: 250px;
padding: 5px;
position: absolute;
color: #464646;
z-index: 999999;
}
.rounded
{
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
Related
I am using https://github.com/jasonujmaalvis/show-more to show and hide text on a mobile device. What I want to do is toggle between images on show more and show less:
So far I have:
Jquery:
source file:
;
(function($, window, document, undefined) {
'use strict';
var pluginName = 'showmore',
defaults = {
closedHeight: 100,
buttonTextMore: 'show more',
buttonTextLess: 'show less',
buttonCssClass: 'showmore-button',
animationSpeed: 0.5,
openHeightOffset: 0,
onlyWithWindowMaxWidth: 0
};
function Plugin(element, options) {
this.element = element;
this.settings = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.btn;
this.init();
}
$.extend(Plugin.prototype, {
init: function() {
if (this.settings.onlyWithWindowMaxWidth > 0) {
this.bindResize();
this.responsive();
} else {
this.showmore();
}
},
bindResize: function() {
var self = this;
var resizeTimer;
$(window).on('resize', function() {
if (resizeTimer) {
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(function() {
self.responsive();
}, 250);
});
},
responsive: function() {
if ($(window).innerWidth() <= this.settings.onlyWithWindowMaxWidth) {
this.showmore();
} else {
this.remove();
}
},
showmore: function() {
if (this.btn) {
return;
}
var self = this;
var element = $(this.element);
var settings = this.settings;
if (settings.animationSpeed > 10) {
settings.animationSpeed = settings.animationSpeed / 1000;
}
var showMoreInner = $('<div />', {
'class': settings.buttonCssClass + '-inner more',
text: settings.buttonTextMore
});
var showLessInner = $('<div />', {
'class': settings.buttonCssClass + '-inner less',
text: settings.buttonTextLess
});
element.addClass('closed').css({
'height': settings.closedHeight,
'overflow': 'hidden'
});
var resizeTimer;
$(window).on('resize', function() {
if (!element.hasClass('closed')) {
if (resizeTimer) {
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(function() {
// resizing has "stopped"
self.setOpenHeight(true);
}, 150); // this must be less than bindResize timeout!
}
});
var showMoreButton = $('<div />', {
'class': settings.buttonCssClass,
html: showMoreInner
});
showMoreButton.on('click', function(event) {
event.preventDefault();
if (element.hasClass('closed')) {
self.setOpenHeight();
element.removeClass('closed');
showMoreButton.html(showLessInner);
} else {
element.css({
'height': settings.closedHeight,
'transition': 'all ' + settings.animationSpeed + 's ease'
}).addClass('closed');
showMoreButton.html(showMoreInner);
}
});
element.after(showMoreButton);
this.btn = showMoreButton;
},
setOpenHeight: function(noAnimation) {
$(this.element).css({
'height': this.getOpenHeight()
});
if (noAnimation) {
$(this.element).css({
'transition': 'none'
});
} else {
$(this.element).css({
'transition': 'all ' + this.settings.animationSpeed + 's ease'
});
}
},
getOpenHeight: function() {
$(this.element).css({'height': 'auto', 'transition': 'none'});
var targetHeight = $(this.element).innerHeight();
$(this.element).css({'height': this.settings.closedHeight});
// we must call innerHeight() otherwhise there will be no css animation
$(this.element).innerHeight();
return targetHeight;
},
remove: function() {
// var element = $(this.element);
if ($(this.element).hasClass('closed')) {
this.setOpenHeight();
}
if (this.btn) {
this.btn.off('click').empty().remove();
this.btn = undefined;
}
}
});
$.fn[pluginName] = function(options) {
return this.each(function() {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
}
});
};
})(jQuery, window, document);
my Jquery:
$('.read-more').showmore({
closedHeight: 100,
shadow: true,
onlyWithWindowMaxWidth: 576,
buttonCssClass: 'showmore-button',
buttonTextLess: 'Read less',
buttonTextMore: 'Read more'
});
CSS
.home-text .showmore-button {
margin-bottom: 25px;
background-image: url('../assets/images/plus-octagon-light.svg')!important;
background-repeat: no-repeat;
width: 150px;
padding-left: 40px;
height: 30px;
display: block;
}
.home-text .showmore-button::active {
margin-bottom: 25px;
background-image: url('../assets/images/minus-octagon-light.svg')!important;
background-repeat: no-repeat;
width: 150px;
padding-left: 40px;
height: 30px;
display: block;
}
.read-more { line-height:24px; }
.read-more_content { position:relative; overflow:hidden; }
.read-more_trigger { width:100%; height:45px; line-height:45px; cursor:pointer; }
.read-more_trigger span { display:block; }
html
<div class="home-text"><p>xxxxxxxx</p>
</div>
So I am trying to toggle between icons on show more and show less. Any ideas? I know if I used Jquery as stand alone functions I could use the toggle class, but as this is a JS plugin that is where I am thinking where to add it?
After viewing the JQuery code more, the solution that worked for me was changing the CSS with the following classes:
.showmore-button-inner.more {
margin-bottom: 25px;
background-image: url('../assets/images/plus-octagon-light.svg')!important;
background-repeat: no-repeat;
width: 150px;
padding-left: 40px;
height: 30px;
display: block;
}
.showmore-button-inner.less {
margin-bottom: 25px;
background-image: url('../assets/images/minus-octagon-light.svg')!important;
background-repeat: no-repeat;
width: 150px;
padding-left: 40px;
height: 30px;
display: block;
}
Ok so I have a div with an animation:
var x = true;
function dynamicTaskbar(thumb) {
function anim1() {
thumb.style.backgroundColor = "green";
}
function anim2() {
thumb.style.backgroundColor = "blue";
}
if (x === false) {
thumb.style.backgroundColor = "red";
thumb.removeEventListener("mouseover", anim1);
thumb.removeEventListener("mouseleave", anim2);
x = true;
} else {
thumb.style.backgroundColor = "blue";
thumb.addEventListener("mouseover", anim1);
thumb.addEventListener("mouseleave", anim2);
x = false;
}
}
//Create window's thumbnail for taskbar
var thumbnail = document.createElement("div");
thumbnail.setAttribute("class", "thumbnail");
taskbar.append(thumbnail);
taskbar.style.width = taskbar.style.width + thumbnail.style.width + "px";
thumbnail.addEventListener("mousedown", function() {
dynamicTaskbar(thumbnail);
});
#taskbar {
background-color: red;
border: solid 1px black;
width: 50px;
height: 30px;
}
.thumbnail {
width: 50px;
height: 30px;
border: solid 1px black;
}
<div id="taskbar"></div>
By default, the div is red.
When it is clicked:
If x is true, it becomes false and the div turns blue. Two event listeners, mouseover (the div becomes green) and mouseleave (the div becomes red again) are added.
If x is false, it becomes true and the div turns red. But here is my problem: both event listeners (mouseover and mouseleave) are suppose to be removed, but it doesn't work. I searched over the Internet but found nothing that fixed my problem.
Any help?
The solution for this problem is extracting the anim1() and anim2() funtions from the dynamicTaskbar() function.
Since both functions are located inside the dynamicTaskbar() function they are created again and again with each execution of the function causing the instances to be different then the initial ones.
If for example in the first execution (1st click) of dynamicTaskbar() the "object id" of anim1() will be "1" and in the second execution it will be "2". Therefore when you're trying to remove the listener you're actually trying to remove it for a different object reference.
Take a look at the example:
var x = true;
function anim1(thumb) {
thumbnail.style.backgroundColor = "green";
}
function anim2(thumb) {
thumbnail.style.backgroundColor = "blue";
}
function dynamicTaskbar(thumb) {
if (x === false) {
thumbnail.style.backgroundColor = "red";
thumbnail.removeEventListener("mouseover", anim1);
thumbnail.removeEventListener("mouseleave", anim2);
x = true;
} else {
thumbnail.style.backgroundColor = "blue";
thumbnail.addEventListener("mouseover", anim1);
thumbnail.addEventListener("mouseleave", anim2);
x = false;
}
}
//Create window's thumbnail for taskbar
var thumbnail = document.createElement("div");
thumbnail.setAttribute("class", "thumbnail");
taskbar.append(thumbnail);
taskbar.style.width = taskbar.style.width + thumbnail.style.width + "px";
thumbnail.addEventListener("mousedown", function() {
dynamicTaskbar(thumbnail);
});
#taskbar {
background-color: red;
border: solid 1px black;
width: 50px;
height: 30px;
}
.thumbnail {
width: 50px;
height: 30px;
border: solid 1px black;
}
<div id="taskbar"></div>
I need to set the icon for cursor when a user is dragging DIV (red div in the following example).
I have tried several attempt, including using CSS cursor:move and event.dataTransfer.dropEffect with no success, as the icon always show up a "crossed circle".
Any ideas how to solve this issue using HTML5 drag-and-drop API?
http://jsbin.com/hifidunuqa/1/
<script>
window.app = {
config: {
canDrag: false,
cursorOffsetX: null,
cursorOffsetY: null
},
reset: function () {
this.config.cursorOffsetX = null;
this.config.cursorOffsetY = null;
},
start: function () {
document.getElementById('target').addEventListener('dragstart', function (event) {
console.log('+++++++++++++ dragstart')
this.config.cursorOffsetX = event.offsetX;
this.config.cursorOffsetY = event.offsetY;
this.adjustPostion(event);
event.dataTransfer.effectAllowed = 'move';
event.dataTransfer.dropEffect = 'move';
}.bind(this));
document.getElementById('target').addEventListener('drag', function (event) {
console.log('+++++++++++++ drag')
this.adjustPostion(event);
}.bind(this));
document.getElementById('target').addEventListener('dragend', function (event) {
console.log('+++++++++++++ dragend')
this.reset();
}.bind(this));;
},
adjustPostion: function (event) {
if (event.pageX <= 0 || event.pageY <= 0) {
console.log('skipped');
return;
}
var elm = document.getElementById('target');
elm.style.left = (event.pageX - this.config.cursorOffsetX) + 'px';
elm.style.top = (event.pageY - this.config.cursorOffsetY) + 'px';
console.log(event.pageX);
console.log(event.pageY);
}
};
</script>
use mousedown and mousemove
window.app = {
dragging: false,
config: {
canDrag: false,
cursorOffsetX: null,
cursorOffsetY: null
},
reset: function () {
this.config.cursorOffsetX = null;
this.config.cursorOffsetY = null;
},
start: function () {
document.getElementById('target').addEventListener('mousedown', function (event) {
console.log('+++++++++++++ dragstart');
this.dragging = true;
this.config.cursorOffsetX = event.offsetX;
this.config.cursorOffsetY = event.offsetY;
this.adjustPostion(event);
}.bind(this));
document.getElementById('target').addEventListener('mousemove', function (event) {
if (this.dragging) {
console.log('+++++++++++++ drag');
event.target.style.cursor = 'move';
this.adjustPostion(event);
}
}.bind(this));
document.getElementById('target').addEventListener('mouseup', function (event) {
console.log('+++++++++++++ dragend');
this.dragging = false;
event.target.style.cursor = 'pointer';
this.reset();
}.bind(this));
},
adjustPostion: function (event) {
if (event.clientX <= 0 || event.clientY <= 0) {
console.log('skipped');
return;
}
var elm = document.getElementById('target');
elm.style.left = (event.clientX - this.config.cursorOffsetX) + 'px';
elm.style.top = (event.clientY - this.config.cursorOffsetY) + 'px';
console.log(event.pageX);
console.log(event.pageY);
}
};
#target {
position: absolute;
top: 100px;
left: 100px;
width: 400px;
height: 400px;
background-color: red;
-moz-user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
user-select: none;
}
#ui1 {
position: absolute;
top: 50px;
left: 50px;
width: 100px;
height: 400px;
background-color: blue;
z-index: 100;
}
#ui2 {
position: absolute;
top: 50px;
left: 550px;
width: 100px;
height: 400px;
background-color: green;
z-index: 100;
}
<!-- simulate -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>title</title>
</head>
<body onload="window.app.start();">
<div id="ui1"></div>
<div id="ui2"></div>
<div id="target"></div>
</body>
</html>
Do you actually need the Drag API? I found that I was using the Drag API because I was having trouble with the reliability of mouse events (mouseups not being captured, for example).
The Drag API is only for drag-and-drop functionality, and, if you're simply fiddling with the reliability of your clicking and pointing events, a new API, .setPointerCapture is made to handle these cases more effectively. Here's the minimal viable way to achieve this:
el.onpointerdown = ev => {
el.onpointermove = pointerMove
el.setPointerCapture(ev.pointerId)
}
pointerMove = ev => {
console.log('Dragged!')
}
el.onpointerUp = ev => {
el.onpointermove = null
el.releasePointerCapture(ev.pointerId)
}
Beautifully, you will maintain full control over your cursor's display style.
I didn't care about a particular cursor, I just wanted to get rid of the "crossed circle" one. My solution was to include dragover event (with following function) to all elements, that already had dragenter, dragstart and dragend events.
function dragover(event)
{
event.dataTransfer.dropEffect = "move";
event.preventDefault();
}
Adding event.dataTransfer.setData(); should solve the problem. Once the element is recognized as draggable the browser will add a move cursor automatically once you drag. Of course, you will have to remove all other cursor: move declarations to see the cursor changing while dragging.
Minimal example:
document.getElementById('target').addEventListener('dragstart', function (event) {
event.dataTransfer.setData( 'text/plain', '' );
}.bind(this));
If you still want to change the icon (e.g. to use a custom drag icon), you could access the element style using event.target.style.cursor.
For more info see MDN Drag & Drop and MDN Recommended Drag Types
I am currently styling the nav buttons of hero slider using css, below is my code, however I want to achieve the buttons like on the slider on www.bbc.co.uk. With the expanding div and the text appearing. Could sombeody show me how please?
This is the css for the buttons I would like to edit
.hero-carousel-nav li {
position: absolute;
bottom: 48px;
right: 48px;
list-style: none;
}
.hero-carousel-nav li.prev {
left: 48px;
right: auto;
}
.hero-carousel-nav li a {
background: #FFF;
color: #fff;
border: none;
outline: none;
display: block;
float: left;
padding: 5px 20px;
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
border-radius: 10px;
behavior: url(/assets/PIE.htc);
}
.hero-carousel-nav li a:hover {
background: #06C;
}
and this is my javascript which includes the coding for the previous and next nav buttons that I would like to edit.
jQuery.fn.heroCarousel = function(options){
options = jQuery.extend({
animationSpeed: 1000,
navigation: true,
easing: '',
timeout: 5000,
pause: true,
pauseOnNavHover: true,
prevText: 'Previous',
nextText: 'Next',
css3pieFix: false,
currentClass: 'current',
onLoad: function(){},
onStart: function(){},
onComplete: function(){}
}, options);
if(jQuery.browser.msie && parseFloat(jQuery.browser.version) < 7){
options.animationSpeed = 0;
}
return this.each(function() {
var carousel = jQuery(this),
elements = carousel.children();
currentItem = 1;
childWidth = elements.width();
childHeight = elements.height();
if(elements.length > 2){
elements.each(function(i){
if(options.itemClass){
jQuery(this).addClass(options.itemClass);
}
});
elements.filter(':first').addClass(options.currentClass).before(elements.filter(':last'));
var carouselWidth = Math.round(childWidth * carousel.children().length),
carouselMarginLeft = '-'+ Math.round(childWidth + Math.round(childWidth / 2) ) +'px'
carousel.addClass('hero-carousel-container').css({
'position': 'relative',
'overflow': 'hidden',
'left': '50%',
'top': 0,
'margin-left': carouselMarginLeft,
'height': childHeight,
'width': carouselWidth
});
carousel.before('<ul class="hero-carousel-nav"><li class="prev">'+options.prevText+'</li><li class="next">'+options.nextText+'</li></ul>');
var carouselNav = carousel.prev('.hero-carousel-nav'),
timeoutInterval;
if(options.timeout > 0){
var paused = false;
if(options.pause){
carousel.hover(function(){
paused = true;
},function(){
paused = false;
});
}
if(options.pauseOnNavHover){
carouselNav.hover(function(){
paused = true;
},function(){
paused = false;
});
}
function autoSlide(){
if(!paused){
carouselNav.find('.next a').trigger('click');
}
}
timeoutInterval = window.setInterval(autoSlide, options.timeout);
}
carouselNav.find('a').data('disabled', false).click(function(e){
e.preventDefault();
var navItem = jQuery(this),
isPrevious = navItem.parent().hasClass('prev'),
elements = carousel.children();
if(navItem.data('disabled') === false){
options.onStart(carousel, carouselNav, elements.eq(currentItem), options);
if(isPrevious){
animateItem(elements.filter(':last'), 'previous');
}else{
animateItem(elements.filter(':first'), 'next');
}
navItem.data('disabled', true);
setTimeout(function(){
navItem.data('disabled', false);
}, options.animationSpeed+200);
if(options.timeout > 0){
window.clearInterval(timeoutInterval);
timeoutInterval = window.setInterval(autoSlide, options.timeout);
}
}
});
function animateItem(object,direction){
var carouselPosLeft = parseFloat(carousel.position().left),
carouselPrevMarginLeft = parseFloat(carousel.css('margin-left'));
if(direction === 'previous'){
object.before( object.clone().addClass('carousel-clone') );
carousel.prepend( object );
var marginLeft = Math.round(carouselPrevMarginLeft - childWidth);
var plusOrMinus = '+=';
}else{
object.after( object.clone().addClass('carousel-clone') );
carousel.append( object );
var marginLeft = carouselMarginLeft;
var plusOrMinus = '-=';
}
if(options.css3pieFix){
fixPieClones(jQuery('.carousel-clone'));
}
carousel.css({
'left': carouselPosLeft,
'width': Math.round(carouselWidth + childWidth),
'margin-left': marginLeft
}).animate({'left':plusOrMinus+childWidth}, options.animationSpeed, options.easing, function(){
carousel.css({
'left': '50%',
'width': carouselWidth,
'margin-left': carouselPrevMarginLeft
});
jQuery('.carousel-clone').remove();
finishCarousel();
});
}
function fixPieClones(clonedObject){
var itemPieId = clonedObject.attr('_pieId');
if(itemPieId){
clonedObject.attr('_pieId', itemPieId+'_cloned');
}
clonedObject.find('*[_pieId]').each(function(i, item){
var descendantPieId = $(item).attr('_pieId');
$(item).attr('_pieId', descendantPieId+'_cloned');
});
}
function finishCarousel(){
var elements = carousel.children();
elements.removeClass(options.currentClass).eq(currentItem).addClass(options.currentClass);
options.onComplete(carousel, carousel.prev('.hero-carousel-nav'), elements.eq(currentItem), options);
}
if(jQuery.browser.msie){
carouselNav.find('a').attr("hideFocus", "true");
}
options.onLoad(carousel, carouselNav, carousel.children().eq(currentItem), options);
}
});
};
BBC website is actually using a custom javascript library called glow. you might want to look at this:
Alternatively you can also use this slider, by checking the source code.
I have a fullcalendar with external elements being dragged onto it. I'm relatively new to jquery. I don't know quite how to get the ID of the object being dragged to a "trash can" icon. I simply want to drag items off of the calendar to a image and when I let go of the mouse the item is removed.
This is my code.....
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<link rel='stylesheet' type='text/css' href='../fullcalendar.css' />
<script type='text/javascript' src='../jquery/jquery.js'></script>
<script type='text/javascript' src='../jquery/jquery-ui-custom.js'></script>
<script type='text/javascript' src='../fullcalendar.min.js'></script>
<script type='text/javascript'>
$(document).ready(function() {
/* initialize the external events
-----------------------------------------------------------------*/
$('#external-events div.external-event').each(function() {
// create an Event Object (http://arshaw.com/fullcalendar/docs/event_data/Event_Object/)
// it doesn't need to have a start or end
var eventObject = {
title: $.trim($(this).text()) // use the element's text as the event title
};
// store the Event Object in the DOM element so we can get to it later
$(this).data('eventObject', eventObject);
// make the event draggable using jQuery UI
$(this).draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
});
/* initialize the calendar
-----------------------------------------------------------------*/
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
droppable: true, // this allows things to be dropped onto the calendar !!!
drop: function(date, allDay) { // this function is called when something is dropped
// retrieve the dropped element's stored Event Object
var originalEventObject = $(this).data('eventObject');
// we need to copy it, so that multiple events don't have a reference to the same object
var copiedEventObject = $.extend({}, originalEventObject);
// assign it the date that was reported
copiedEventObject.start = date;
copiedEventObject.allDay = allDay;
// render the event on the calendar
// the last `true` argument determines if the event "sticks" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/)
$('#calendar').fullCalendar('renderEvent', copiedEventObject, true);
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
$(this).remove();
}
}
});
});
</script>
<style type='text/css'>
body {
margin-top: 40px;
text-align: center;
font-size: 14px;
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
}
#wrap {
width: 1100px;
margin: 0 auto;
}
#external-events {
float: left;
width: 150px;
padding: 0 10px;
border: 1px solid #ccc;
background: #eee;
text-align: left;
}
#external-events h4 {
font-size: 16px;
margin-top: 0;
padding-top: 1em;
}
.external-event { /* try to mimick the look of a real event */
margin: 10px 0;
padding: 2px 4px;
background: #3366CC;
color: #fff;
font-size: .85em;
cursor: pointer;
}
#external-events p {
margin: 1.5em 0;
font-size: 11px;
color: #666;
}
#external-events p input {
margin: 0;
vertical-align: middle;
}
#calendar {
float: right;
width: 900px;
}
</style>
</head>
<body>
<div id='wrap'>
<div id='external-events'>
<h4>Draggable Events</h4>
<div class='external-event'>even1</div>
<div class='external-event'>even2</div>
<p>
<input type='checkbox' id='drop-remove' /> <label for='drop-remove'>remove after drop</label>
</p>
</div>
<div id='calendar'></div>
<img src="redmond/images/trash.png" id="trash">
<div style='clear:both'></div>
</div>
</body>
</html>
Complete tutorial, how to add "move to trash" function to fullcalendar
HERE IS DEMO
if you do not want to use droppable:
from fullcalendar.css delete this lines
.fc-view
{
/* prevents dragging outside of widget */
width: 100%;
overflow: hidden;
}
find in fullcalenar.js (line cca 6086)
function eachEventElement(event, exceptElement, funcName) {
var elements = eventElementsByID[event._id],
i, len = elements.length;
for (i=0; i<len; i++) {
if (!exceptElement || elements[i][0] != exceptElement[0]) {
elements[i][funcName]();
}
}
}
and change to:
function eachEventElement(event, exceptElement, funcName) {
var elements = eventElementsByID[event._id],
i;
if (elements != null) {
var len = elements.length;
for (i = 0; i < len; i++) {
if (!exceptElement || elements[i][0] != exceptElement[0]) {
elements[i][funcName]();
}
}
}
}
in js:
//actually cursor position
var currentMousePos = {
x: -1,
y: -1
};
//set actually cursor pos
jQuery(document).ready(function () {
jQuery(document).on("mousemove", function (event) {
currentMousePos.x = event.pageX;
currentMousePos.y = event.pageY;
});
});
//check if cursor is in trash
function isElemOverDiv() {
var trashEl = jQuery('#calendarTrash');
var ofs = trashEl.offset();
var x1 = ofs.left;
var x2 = ofs.left + trashEl.outerWidth(true);
var y1 = ofs.top;
var y2 = ofs.top + trashEl.outerHeight(true);
if (currentMousePos.x >= x1 && currentMousePos.x <= x2 &&
currentMousePos.y >= y1 && currentMousePos.y <= y2) {
return true;
}
return false;
}
//fullcalendar mouseover callback
eventMouseover: function (event, jsEvent) {
$(this).mousemove(function (e) {
var trashEl = jQuery('#calendarTrash');
if (isElemOverDiv()) {
if (!trashEl.hasClass("to-trash")) {
trashEl.addClass("to-trash");
}
} else {
if (trashEl.hasClass("to-trash")) {
trashEl.removeClass("to-trash");
}
}
});
},
//fullcalendar eventdragstop callback
eventDragStop: function (event, jsEvent, ui, view) {
if (isElemOverDiv()) {
jQuery('#fr-calendar').fullCalendar('removeEvents', event.id);
var trashEl = jQuery('#calendarTrash');
if (trashEl.hasClass("to-trash")) {
trashEl.removeClass("to-trash");
}
}
},
in fullcalendar set option dragRevertDuration: 0,
in fullcalendar declaration add loading callback function for append a trashcalendar:
loading: function (bool) {
if (!bool) {
jQuery('.fc-header-left').append('<div id="calendarTrash" class="calendar-trash"><img src="' + imagePath + '/cal-trash.png"></img></div>');
}
},
css for trash:
div.calendar-trash{
float: left;
padding-right: 8px;
margin-right:5px;
padding-left:8px;
padding-top: 3px;
cursor: pointer;
}
.to-trash{
background-color:#EAEAEA;
-webkit-border-radius: 5em;
border-radius: 5em;
}
If loading callback not working, add trash on end of jquery document ready function.
foo.JFS('.fc-header-left').append('<div id="calendarTrash" class="calendar-trash"><img src="/images/cal-trash.png"></img></div>');
trash icon:
first of all you're gonna need to remove overflow statement from css:
.fc-view
{
/* prevents dragging outside of widget */
width: 100%;
overflow: hidden;
}
then you can use eventDragStop
here is something I just did hope it helps. I dont know if you are using php/mysql but if your not just remove the ajax call and keep what is in the success function.
$('#calendar').children('.fc-content').children().append('<div id="calendarTrash" style="float: right; padding-top: 5px; padding-right: 5px; padding-left: 5px;"><span class="ui-icon ui-icon-trash"></span></div>');
//listens for drop event
$("#calendarTrash").droppable({
tolerance: 'pointer',
drop: function(event, ui) {
if ( dragged && ui.helper && ui.helper[0] === dragged[0] ) {
var event = dragged[1];
var answer = confirm("Delete Event?")
if (answer)
{
$.ajax({
url:'/employees/removeevent?id='+event.id,
dataType: 'json',
async: false,
error: function(xhr, ajaxOptions, thrownError)
{
//console.log(xhr.status);
//console.log(thrownError);
},
success: function()
{
calendar.fullCalendar( 'removeEvents' , event.id );
}
});
}
}
}
});
eventDragStart: function( event, jsEvent, ui, view ) {
dragged = [ ui.helper[0], event ];
},
i tell us drop: function(event, ui) ui :: ui holds an empty object. Before version 2.1, the jQuery UI object. :) and work then jsEvent :) sn :
eventDragStop: function(event, jsEvent, ui, view) {
if (isElemOverDiv(jsEvent, $('div#external-events'))) {
console.log(isElemOverDiv(jsEvent, $('div#external-events')));
$('.calendario').fullCalendar('removeEvents', event.id);
}
}
var isElemOverDiv = function(draggedItem, dropArea) {
var p = dropArea;
var position = p.position();
console.log("EL DROP AREA left: " + position.left + ", top: " + position.top);
console.log('draggedItem.pageY ', draggedItem.clientX, draggedItem.pageY);
if (draggedItem.clientX >= position.left && draggedItem.pageY >= position.top) {
return true;
}
return false;
}
<div id="calendarTrash" class="calendar-trash"><img src="images\trash.png" alt="image"/></div>
` eventDragStop: function(event,jsEvent) {
var trashEl = jQuery('#calendarTrash');
var ofs = trashEl.offset();
var x1 = ofs.left;
var x2 = ofs.left + trashEl.outerWidth(true);
var y1 = ofs.top;
var y2 = ofs.top + trashEl.outerHeight(true);
if (jsEvent.pageX >= x1 && jsEvent.pageX<= x2 &&
jsEvent.pageY >= y1 && jsEvent.pageY <= y2) {
if (confirm("Are you sure to detete " + event.title +" ?")) {
//pour annuker les informations
$('#external-calendar').fullCalendar('removeEvents', event._id);
}
}
}