I'm using cropper.js on MVC 5 Razor page where i do not want user to select cropping area with mouse, I want to initialize cropper object with predefined clipping (selected) area that user can't resize, but user can move clipping area on the picture to crop a part of picture.
I was not able to find any option to disable clipping, i checked on their Git page and it looks like it does not have ability, moreover i posted my request on Git page but did not get any response. i need help how can i workaround to achieve this.
window.onload = function() {
var Cropper = window.Cropper;
var URL = window.URL || window.webkitURL;
var container = document.querySelector('.img-container');
var image = container.getElementsByTagName('img').item(0);
var download = '';
var actions = document.getElementById('actions');
var dataX = 128;
var dataY = 72;
var dataHeight = 1024;
var dataWidth = 576;
var dataRotate = 0;
var dataScaleX = -1;
var dataScaleY = 1;
var options = {
aspectRatio: 16 / 9,
preview: '.img-preview',
ready: function (e) {
console.log(e.type);
},
cropstart: function (e) {
console.log(e.type, e.detail.action);
},
cropmove: function (e) {
console.log(e.type, e.detail.action);
},
cropend: function (e) {
console.log(e.type, e.detail.action);
},
crop: function (e) {
var data = e.detail;
console.log(e.type);
dataX.value = Math.round(data.x);
dataY.value = Math.round(data.y);
dataHeight.value = Math.round(data.height);
dataWidth.value = Math.round(data.width);
dataRotate.value = typeof data.rotate !== 'undefined' ? data.rotate : '';
dataScaleX.value = typeof data.scaleX !== 'undefined' ? data.scaleX : '';
dataScaleY.value = typeof data.scaleY !== 'undefined' ? data.scaleY : '';
},
zoom: function (e) {
console.log(e.type, e.detail.ratio);
}
};
var cropper = new Cropper(image, options);
}
.img-container {
min-height: 497px;
max-width: 497px;
margin-bottom: 1rem;
background-color: white;
text-align: center;
width: 100%;
}
.img-container > img {
max-width: 100%;
}
img {
vertical-align: middle;
border-style: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.5/cropper.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.5/cropper.css" rel="stylesheet"/>
<div class="img-container">
<img src="https://images.pexels.com/photos/266011/pexels-photo-266011.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" id="croppr" />
</div>
With reference to help by #Chris W. I was able to setup with fixed clipping area.
var image = document.getElementById('croppr');
var cropper = new Cropper(image, {
dragMode: 'move',
aspectRatio: 16 / 9,
autoCropArea: 0.65,
restore: false,
guides: false,
center: false,
highlight: false,
cropBoxMovable: true,
cropBoxResizable: false,
toggleDragModeOnDblclick: false,
});
.img-container {
min-height: 497px;
max-width: 497px;
margin-bottom: 1rem;
background-color: white;
text-align: center;
width: 100%;
}
.img-container > img {
max-width: 100%;
}
img {
vertical-align: middle;
border-style: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.5/cropper.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.5/cropper.css" rel="stylesheet"/>
<div class="img-container">
<img src="https://images.pexels.com/photos/266011/pexels-photo-266011.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" id="croppr" />
</div>
Related
I have fabric js multiple canvases and I would like to add Text on the selected canvas, instead of the last item of the array.
If a user creates multiple canvases then I need an option to add the text on the selected canvas.
Please run the code snippet or see the codepen demo of the current approach...
Thank you!
//================== Create Canvas start =================
var createCanvas = document.getElementById("createCanvas");
var canvasInstances = [];
createCanvas.addEventListener('click',function(){
var canvasContainer = document.getElementById("canvasContainer");
var newcanvas = document.createElement("canvas");
//newcanvas.classList.add("active");
canvasContainer.append(newcanvas);
var fabricCanvasObj = new fabric.Canvas(newcanvas, {
height: 400,
width: 400,
backgroundColor: '#ffffff',
});
canvasInstances.push(fabricCanvasObj);
console.log(canvasInstances);
})
//================== Create Canvas End =================
//================== Add Text ================
var addText = document.getElementById("addText");
addText.addEventListener('click',function(){
canvasInstances.forEach(function(current,id,array){
if(id === array.length - 1){
const converText = new fabric.IText(`Type Text`,{
type: 'text',
width: 200,
fontSize: 20,
left: 20,
top: 20,
fill: '#444'
});
current.add(converText);
current.renderAll();
return false;
}
})
})
//================== Add End =================
*{
box-sizing: border-box;
}
body{
background:#ccc;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 200px;
}
.canvas-container{
margin-bottom:10px;
}
.add-text{
margin: 20px;
width: 400px;
text-align: center;
border:1px dashed red;
padding: 15px;
cursor:pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.5.0/fabric.min.js"></script>
<div class="add-text" id="addText">Add Text</div>
<div id="canvasContainer">
</div>
<button id="createCanvas">Create Canvas</button>
Declare canvasobject globally, you can try below code
<script type="text/javascript">
var canvasobject;
window.onload = function () {
canvasobject = new fabric.Canvas('myCanvas');
canvasobject.backgroundColor = '#0056d6';
canvasobject.renderAll();
//
function addtext() {
var textvalue = "Type here";
var fontcolor = "#333";
var fontFamily = "Baloo 2";
var myfont = new FontFaceObserver(fontFamily);
myfont.load()
.then(function () {
// when font is loaded, use it.
var text = new fabric.Text(textvalue, {
left: 100,
top: 100,
fontFamily: fontFamily,
fill: fontcolor,
});
canvasobject.add(text);
canvasobject.renderAll();
}).catch(function (e) {
//console.log(e);
console.log('font loading failed ' + fontFamily);
});
}
}
I have a bunch of CSS and SVG elements that get placed into a div and I would like the user to be able to pan and zoom around to all of them. I am using the library from Jquery Panzoom. Is there a way to contain it so that if the user has an element outside of the viewport they will be able to pan to the edge of the container with all of the elements inside of it?
Below I will provide an example of what it's doing now. When it is all zoomed in and there is still an element not seen, I would like to be able to pan to the other element.
When Everything is seen, I would like it to not be able to pan but still zoom.
When it is zoomed all of the ways out, I would like the container to be the width of the viewport. The problem I am having is that if I set the container to be the width of the viewport at its most zoomed out level. It decides to hide below the viewport.
Example
Example using Panzoom
Code from codepen
Html
<div id="chart_container">
<div class="flowchart-example-container" id="example"></div>
</div>
<div class="draggable_operators">
<div class="draggable_operators_label">
Operators (drag and drop them in the flowchart):
</div>
<div class="draggable_operators_divs">
<div class="draggable_operator" data-nb-inputs="1" data-nb-outputs="0">1 input</div>
<div class="draggable_operator" data-nb-inputs="0" data-nb-outputs="1">1 output</div>
<div class="draggable_operator" data-nb-inputs="1" data-nb-outputs="1">1 input & 1 output</div>
<div class="draggable_operator" data-nb-inputs="1" data-nb-outputs="2">1 in & 2 out</div>
<div class="draggable_operator" data-nb-inputs="2" data-nb-outputs="1">2 in & 1 out</div>
<div class="draggable_operator" data-nb-inputs="2" data-nb-outputs="2">2 in & 2 out</div>
</div>
</div>
<button class="delete_selected_button">Delete selected operator / link</button>
CSS
body {
font-family: 'Helvetica Neue', Helvetica, Arial, serif;
font-size: 15px;
font-weight: 400;
line-height: 1.5;
color: #666;
}
#chart_container {
width: 100%;
height: 500px;
overflow: hidden;
background: repeating-linear-gradient( 45deg, #eee, #eee 10px, #e5e5e5 10px, #e5e5e5 20px);
border: 1px solid black;
}
.flowchart-example-container {
height: 200px;
border: 1px solid #BBB;
margin-bottom: 10px;
}
#example {
width: 2000px;
height: 2000px;
background: white;
}
.draggable_operators_label {
margin-bottom: 5px;
}
.draggable_operators_divs {
margin-bottom: 20px;
}
.draggable_operator {
display: inline-block;
padding: 2px 5px 2px 5px;
border: 1px solid #ccc;
cursor: grab;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
Javascript
$(document).ready(function() {
var $flowchart = $('#example');
var $container = $flowchart.parent();
var cx = $flowchart.width() / 2;
var cy = $flowchart.height() / 2;
// Panzoom initialization...
$flowchart.panzoom();
// Centering panzoom
$flowchart.panzoom('pan', -cx + $container.width() / 2, -cy + $container.height() / 2);
// Panzoom zoom handling...
var possibleZooms = [0.5, 0.75, 1, 2, 3];
var currentZoom = 2;
$container.on('mousewheel.focal', function(e) {
e.preventDefault();
var delta = (e.delta || e.originalEvent.wheelDelta) || e.originalEvent.detail;
var zoomOut = delta ? delta < 0 : e.originalEvent.deltaY > 0;
currentZoom = Math.max(0, Math.min(possibleZooms.length - 1, (currentZoom + (zoomOut * 2 - 1))));
$flowchart.flowchart('setPositionRatio', possibleZooms[currentZoom]);
$flowchart.panzoom('zoom', possibleZooms[currentZoom], {
animate: false,
focal: e
});
});
var data = {
operators: {
operator1: {
top: cy - 100,
left: cx - 200,
properties: {
title: 'Operator 1',
inputs: {},
outputs: {
output_1: {
label: 'Output',
}
}
}
},
operator2: {
top: cy,
left: cx + 140,
properties: {
title: 'Operator 2',
inputs: {
input_1: {
label: 'Input 1',
},
input_2: {
label: 'Input 2',
},
},
outputs: {}
}
},
},
links: {
link_1: {
fromOperator: 'operator1',
fromConnector: 'output_1',
toOperator: 'operator2',
toConnector: 'input_2',
},
}
};
// Apply the plugin on a standard, empty div...
$flowchart.flowchart({
data: data,
linkWidth: 5
});
$flowchart.parent().siblings('.delete_selected_button').click(function() {
$flowchart.flowchart('deleteSelected');
});
var $draggableOperators = $('.draggable_operator');
function getOperatorData($element) {
var nbInputs = parseInt($element.data('nb-inputs'));
var nbOutputs = parseInt($element.data('nb-outputs'));
var data = {
properties: {
title: $element.text(),
inputs: {},
outputs: {}
}
};
var i = 0;
for (i = 0; i < nbInputs; i++) {
data.properties.inputs['input_' + i] = {
label: 'Input ' + (i + 1)
};
}
for (i = 0; i < nbOutputs; i++) {
data.properties.outputs['output_' + i] = {
label: 'Output ' + (i + 1)
};
}
return data;
}
var operatorId = 0;
$draggableOperators.draggable({
cursor: "move",
opacity: 0.7,
helper: 'clone',
appendTo: 'body',
zIndex: 1000,
helper: function(e) {
var $this = $(this);
var data = getOperatorData($this);
return $flowchart.flowchart('getOperatorElement', data);
},
stop: function(e, ui) {
var $this = $(this);
var elOffset = ui.offset;
var containerOffset = $container.offset();
if (elOffset.left > containerOffset.left &&
elOffset.top > containerOffset.top &&
elOffset.left < containerOffset.left + $container.width() &&
elOffset.top < containerOffset.top + $container.height()) {
var flowchartOffset = $flowchart.offset();
var relativeLeft = elOffset.left - flowchartOffset.left;
var relativeTop = elOffset.top - flowchartOffset.top;
var positionRatio = $flowchart.flowchart('getPositionRatio');
relativeLeft /= positionRatio;
relativeTop /= positionRatio;
var data = getOperatorData($this);
data.left = relativeLeft;
data.top = relativeTop;
$flowchart.flowchart('addOperator', data);
}
}
});
});
I want to check if server at URL is responding, then set the text of my < p > tag to 'server is online' or 'server is offline'.
I can make a page on my server that returns for ex. 'success' as a plain text. And if my javascript can catch this message it should write 'server is online', else it should try to connect for maximum 5 or more seconds, then write a message 'server is offline'.
I tried the code from this answer, but it turns offline after 1500 ms.
<body onload="Pinger_ping('google.com')">
...
<p id = "status">Checking server status...</p>
...
<script type="text/javascript">
function Pinger_ping(ip, callback) {
if(!this.inUse) {
this.inUse = true;
this.callback = callback
this.ip = ip;
var _that = this;
this.img = new Image();
var status=document.getElementById('status');
this.img.onload = function() {status.innerHTML="online";};
this.img.onerror = function() {status.innerHTML="online";};
this.start = new Date().getTime();
this.img.src = "http://" + ip;
this.timer = setTimeout(function() {status.innerHTML="offline";}, 1500);
}
}
</script>
You may try this solution, here I am using image load event to track the connection status.
(function(win) {
var _ = {};
_.win = win;
_.doc = _.win.document;
_.status = _.doc.createElement('div');
_.status.className = "hide";
_.status.innerHTML = "You are now offline !";
_.doc.getElementsByTagName('body')[0].appendChild(_.status);
_.img = new Image();
_.loop = function() {
_.win.setTimeout(_.nextSrc, 5000);
};
_.onLine = function() {
_.status.className = "hide"; // hide
_.loop();
};
_.offLine = function() {
_.status.className = "net-err"; // show
_.loop();
};
_.img.onload = _.onLine;
_.img.onerror = _.offLine;
_.nextSrc = function() {
_.img.src = "https://raw.githubusercontent.com/arvind-web-corner/offline-status/gh-pages/blank.png?" + _.win.Math.random();
};
_.loop();
})(window);
* {
font-family: Calibri, Arial !important;
}
.net-err {
width: 100%;
display: block;
z-index: 999;
padding: 15px 10px;
background: rgb(255, 9, 9);
color: #fff;
font-weight: bold !important;
text-align: center;
position: fixed;
top: -1px;
left: -1px;
border: 1px solid #ddd;
font-size: 30px;
opacity: 0.9;
filter: alpha(opacity=90);
/* IE */
}
.hide {
display: none;
}
<!DOCTYPE html>
<html>
<head>
<title>Status</title>
</head>
<body>
<h1>This page will be tracking your internet connection</h1>
<h2>You will be notified when you loose connection</h2>
<h3>e.g. Go to File > Work Offline</h3>
</body>
</html>
script, demo
I'm using the PDF.js library to render a pdf into the canvas. That pdf has hyperlinks in there, The PDF.js library is drawing the pdf into the canvas but the hyperlinks don't work.
Any Idea if it possible that hyperlinks work into the canvas?
Thanks
Here is a fiddle that shows you how to enable annotations (including hyperlinks) in PDF files.
The original PDF file used in the fiddle is here.
I used viewer code (web/page_view.js,web/viewer.css) as refrence to write this fiddle.
HTML:
<!doctype html>
<html lang="en">
<head>
<link href="style.css" rel="stylesheet" media="screen" />
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="http://seikichi.github.io/tmp/PDFJS.0.8.715/pdf.min.js" type="text/javascript"></script>
<script src="http://seikichi.github.io/tmp/PDFJS.0.8.715/ui_utils.js"></script>
<script src="./main.js" type="text/javascript"></script>
</head>
<body>
<div id="pdfContainer" class="pdf-content">
<canvas id="the-canvas"></canvas>
<div class="annotationLayer"></div>
</div>
</body>
</html>
CSS:
body {
font-family: arial, verdana, sans-serif;
}
.pdf-content {
border: 1px solid #000000;
}
.annotationLayer > a {
display: block;
position: absolute;
}
.annotationLayer > a:hover {
opacity: 0.2;
background: #ff0;
box-shadow: 0px 2px 10px #ff0;
}
.annotText > div {
z-index: 200;
position: absolute;
padding: 0.6em;
max-width: 20em;
background-color: #FFFF99;
box-shadow: 0px 2px 10px #333;
border-radius: 7px;
}
.annotText > img {
position: absolute;
opacity: 0.6;
}
.annotText > img:hover {
opacity: 1;
}
.annotText > div > h1 {
font-size: 1.2em;
border-bottom: 1px solid #000000;
margin: 0px;
}
JavaScript:
PDFJS.workerSrc = 'http://seikichi.github.io/tmp/PDFJS.0.8.715/pdf.min.worker.js';
$(function () {
var pdfData = loadPDFData();
PDFJS.getDocument(pdfData).then(function (pdf) {
return pdf.getPage(1);
}).then(function (page) {
var scale = 1;
var viewport = page.getViewport(scale);
var $canvas = $('#the-canvas');
var canvas = $canvas.get(0);
var context = canvas.getContext("2d");
canvas.height = viewport.height;
canvas.width = viewport.width;
var $pdfContainer = $("#pdfContainer");
$pdfContainer.css("height", canvas.height + "px")
.css("width", canvas.width + "px");
var renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
setupAnnotations(page, viewport, canvas, $('.annotationLayer'));
});
function setupAnnotations(page, viewport, canvas, $annotationLayerDiv) {
var canvasOffset = $(canvas).offset();
var promise = page.getAnnotations().then(function (annotationsData) {
viewport = viewport.clone({
dontFlip: true
});
for (var i = 0; i < annotationsData.length; i++) {
var data = annotationsData[i];
var annotation = PDFJS.Annotation.fromData(data);
if (!annotation || !annotation.hasHtml()) {
continue;
}
var element = annotation.getHtmlElement(page.commonObjs);
data = annotation.getData();
var rect = data.rect;
var view = page.view;
rect = PDFJS.Util.normalizeRect([
rect[0],
view[3] - rect[1] + view[1],
rect[2],
view[3] - rect[3] + view[1]]);
element.style.left = (canvasOffset.left + rect[0]) + 'px';
element.style.top = (canvasOffset.top + rect[1]) + 'px';
element.style.position = 'absolute';
var transform = viewport.transform;
var transformStr = 'matrix(' + transform.join(',') + ')';
CustomStyle.setProp('transform', element, transformStr);
var transformOriginStr = -rect[0] + 'px ' + -rect[1] + 'px';
CustomStyle.setProp('transformOrigin', element, transformOriginStr);
if (data.subtype === 'Link' && !data.url) {
// In this example, I do not handle the `Link` annotations without url.
// If you want to handle those annotations, see `web/page_view.js`.
continue;
}
$annotationLayerDiv.append(element);
}
});
return promise;
}
});
function loadPDFData() {
/*jshint multistr: true */
var base64pdfData = '...'; //should contain base64 representing the PDF
function base64ToUint8Array(base64) {
var raw = atob(base64);
var uint8Array = new Uint8Array(new ArrayBuffer(raw.length));
for (var i = 0, len = raw.length; i < len; ++i) {
uint8Array[i] = raw.charCodeAt(i);
}
return uint8Array;
}
return base64ToUint8Array(base64pdfData);
}
Enable Text Selection in PDF.JS
Step 1: Adding a Element to Hold the Text Layer
<div id="text-layer"></div>
This div will be in addition to the element where the PDF is rendered, so the HTML will look like :
<canvas id="pdf-canvas"></canvas>
<div id="text-layer"></div>
Step 2 : Adding CSS for Text Layer
Add the following to your CSS file :
#text-layer {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
overflow: hidden;
opacity: 0.2;
line-height: 1.0;
}
#text-layer > div {
color: transparent;
position: absolute;
white-space: pre;
cursor: text;
transform-origin: 0% 0%;
}
Step 3: Getting the PDF Text
After the PDF has been rendered in the canvas, you need to get the text contents of the PDF, and place that text in the text layer.
// page is the page context of the PDF page
// viewport is the viewport required in renderContext
// For more see https://usefulangle.com/post/20/pdfjs-tutorial-1-preview-pdf-during-upload-wih-next-prev-buttons
page.render(renderContext).then(function() {
// Returns a promise, on resolving it will return text contents of the page
return page.getTextContent();
}).then(function(textContent) {
// PDF canvas
var pdf_canvas = $("#pdf-canvas");
// Canvas offset
var canvas_offset = pdf_canvas.offset();
// Canvas height
var canvas_height = pdf_canvas.get(0).height;
// Canvas width
var canvas_width = pdf_canvas.get(0).width;
// Assign CSS to the text-layer element
$("#text-layer").css({ left: canvas_offset.left + 'px', top: canvas_offset.top + 'px', height: canvas_height + 'px', width: canvas_width + 'px' });
// Pass the data to the method for rendering of text over the pdf canvas.
PDFJS.renderTextLayer({
textContent: textContent,
container: $("#text-layer").get(0),
viewport: viewport,
textDivs: []
});
});
source: https://usefulangle.com/post/90/javascript-pdfjs-enable-text-layer
setupAnnotations = (page, viewport, canvas, annotationLayerDiv) => {
let pdfjsLib = window['pdfjs-dist/build/pdf'];
let pdfjsViewer = window['pdfjs-dist/web/pdf_viewer'];
//BELOW--------- Create Link Service using pdf viewer
let pdfLinkService = new pdfjsViewer.PDFLinkService();
page.getAnnotations().then(function (annotationsData) {
viewport = viewport.clone({
dontFlip: true
});
let pdf_canvas = canvas;
// Render the annotation layer
annotationLayerDiv.style.left = pdf_canvas.offsetLeft + 'px';
annotationLayerDiv.style.top = pdf_canvas.offsetTop + 'px';
annotationLayerDiv.style.height = viewport.height + 'px';
annotationLayerDiv.style.width = viewport.width + 'px';
pdfjsLib.AnnotationLayer.render({
viewport: viewport,
div: annotationLayerDiv,
annotations: annotationsData,
page: page,
linkService: pdfLinkService,
enableScripting: true,
renderInteractiveForms: true
});
}
IMP ---- Do not forget to add this CSS
.annotation-layer{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
overflow: hidden;
opacity: 1;
}
.annotation-layer section{
position: absolute;
cursor: pointer;
}
.annotation-layer section a{
display: block;
width: 100%;
height: 10px;
}
In above example, Link service instance is created using class in pdf viewer, which is being passed as parameter to annotation layer render method.
Please refer source code of PDF.js refer to /web/pdf_viewer.js - class PDFLinkService for more information.
PDF.js version - v2.9.359
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);
}
}
}