How can I fit a turn.js flipbook into a parent div?
I have the code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My webpage</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript" src="/assets/js/modernizr.2.5.3.min.js"></script>
<script type="text/javascript" src="/assets/js/hash.js"></script>
</head>
<body style="overflow: auto;">
<div id='parent_div' style="width: 800px; overflow: auto;">
<div class="magazine-viewport">
<div class="container">
<div class="magazine">
<!-- Next button -->
<div ignore="1" class="next-button"></div>
<!-- Previous button -->
<div ignore="1" class="previous-button"></div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
function loadApp() {
var flipbook = $('.magazine');
$('.magazine-viewport').css('position', 'unset');
// Check if the CSS was already loaded
if (flipbook.width()==0 || flipbook.height()==0) {
setTimeout(loadApp, 10);
return;
}
// Create the flipbook
flipbook.turn({
// Magazine width
width: 922,
// Magazine height
height: 600,
// Duration in millisecond
duration: 1000,
// Hardware acceleration
acceleration: !isChrome(),
// Enables gradients
gradients: true,
// Auto center this flipbook
autoCenter: true,
// Elevation from the edge of the flipbook when turning a page
elevation: 50,
// The number of pages
pages: 12,
// Events
when: {
turning: function(event, page, view) {
var book = $(this),
currentPage = book.turn('page'),
pages = book.turn('pages');
// Update the current URI
Hash.go('page/' + page).update();
// Show and hide navigation buttons
disableControls(page);
$('.thumbnails .page-'+currentPage).
parent().
removeClass('current');
$('.thumbnails .page-'+page).
parent().
addClass('current');
},
turned: function(event, page, view) {
disableControls(page);
$(this).turn('center');
if (page==1) {
$(this).turn('peel', 'br');
}
},
missing: function (event, pages) {
// Add pages that aren't in the magazine
for (var i = 0; i < pages.length; i++)
addPage(pages[i], $(this));
}
}
});
// Zoom.js
$('.magazine-viewport').zoom({
flipbook: $('.magazine'),
max: function() {
return largeMagazineWidth()/$('.magazine').width();
},
when: {
swipeLeft: function() {
$(this).zoom('flipbook').turn('next');
},
swipeRight: function() {
$(this).zoom('flipbook').turn('previous');
},
resize: function(event, scale, page, pageElement) {
if (scale==1)
loadSmallPage(page, pageElement);
else
loadLargePage(page, pageElement);
},
zoomIn: function () {
$('.thumbnails').hide();
$('.made').hide();
$('.magazine').removeClass('animated').addClass('zoom-in');
$('.zoom-icon').removeClass('zoom-icon-in').addClass('zoom-icon-out');
if (!window.escTip && !$.isTouch) {
escTip = true;
$('<div />', {'class': 'exit-message'}).
html('<div>Press ESC to exit</div>').
appendTo($('body')).
delay(2000).
animate({opacity:0}, 500, function() {
$(this).remove();
});
}
},
zoomOut: function () {
$('.exit-message').hide();
$('.thumbnails').fadeIn();
$('.made').fadeIn();
$('.zoom-icon').removeClass('zoom-icon-out').addClass('zoom-icon-in');
setTimeout(function(){
$('.magazine').addClass('animated').removeClass('zoom-in');
resizeViewport();
}, 0);
}
}
});
// Zoom event
if ($.isTouch)
$('.magazine-viewport').bind('zoom.doubleTap', zoomTo);
else
$('.magazine-viewport').bind('zoom.tap', zoomTo);
// Using arrow keys to turn the page
$(document).keydown(function(e){
var previous = 37, next = 39, esc = 27;
switch (e.keyCode) {
case previous:
// left arrow
$('.magazine').turn('previous');
e.preventDefault();
break;
case next:
//right arrow
$('.magazine').turn('next');
e.preventDefault();
break;
case esc:
$('.magazine-viewport').zoom('zoomOut');
e.preventDefault();
break;
}
});
// URIs - Format #/page/1
Hash.on('^page\/([0-9]*)$', {
yep: function(path, parts) {
var page = parts[1];
if (page!==undefined) {
if ($('.magazine').turn('is'))
$('.magazine').turn('page', page);
}
},
nop: function(path) {
if ($('.magazine').turn('is'))
$('.magazine').turn('page', 1);
}
});
$(window).resize(function() {
resizeViewport();
}).bind('orientationchange', function() {
resizeViewport();
});
// Events for thumbnails
$('.thumbnails').click(function(event) {
var page;
if (event.target && (page=/page-([0-9]+)/.exec($(event.target).attr('class'))) ) {
$('.magazine').turn('page', page[1]);
}
});
$('.thumbnails li').
bind($.mouseEvents.over, function() {
$(this).addClass('thumb-hover');
}).bind($.mouseEvents.out, function() {
$(this).removeClass('thumb-hover');
});
if ($.isTouch) {
$('.thumbnails').
addClass('thumbanils-touch').
bind($.mouseEvents.move, function(event) {
event.preventDefault();
});
} else {
$('.thumbnails ul').mouseover(function() {
$('.thumbnails').addClass('thumbnails-hover');
}).mousedown(function() {
return false;
}).mouseout(function() {
$('.thumbnails').removeClass('thumbnails-hover');
});
}
// Regions
if ($.isTouch) {
$('.magazine').bind('touchstart', regionClick);
} else {
$('.magazine').click(regionClick);
}
// Events for the next button
$('.next-button').bind($.mouseEvents.over, function() {
$(this).addClass('next-button-hover');
}).bind($.mouseEvents.out, function() {
$(this).removeClass('next-button-hover');
}).bind($.mouseEvents.down, function() {
$(this).addClass('next-button-down');
}).bind($.mouseEvents.up, function() {
$(this).removeClass('next-button-down');
}).click(function() {
$('.magazine').turn('next');
});
// Events for the next button
$('.previous-button').bind($.mouseEvents.over, function() {
$(this).addClass('previous-button-hover');
}).bind($.mouseEvents.out, function() {
$(this).removeClass('previous-button-hover');
}).bind($.mouseEvents.down, function() {
$(this).addClass('previous-button-down');
}).bind($.mouseEvents.up, function() {
$(this).removeClass('previous-button-down');
}).click(function() {
$('.magazine').turn('previous');
});
resizeViewport();
$('.magazine').addClass('animated');
}
// Zoom icon
$('.zoom-icon').bind('mouseover', function() {
if ($(this).hasClass('zoom-icon-in'))
$(this).addClass('zoom-icon-in-hover');
if ($(this).hasClass('zoom-icon-out'))
$(this).addClass('zoom-icon-out-hover');
}).bind('mouseout', function() {
if ($(this).hasClass('zoom-icon-in'))
$(this).removeClass('zoom-icon-in-hover');
if ($(this).hasClass('zoom-icon-out'))
$(this).removeClass('zoom-icon-out-hover');
}).bind('click', function() {
if ($(this).hasClass('zoom-icon-in'))
$('.magazine-viewport').zoom('zoomIn');
else if ($(this).hasClass('zoom-icon-out'))
$('.magazine-viewport').zoom('zoomOut');
});
// Load the HTML4 version if there's not CSS transform
yepnope({
test : Modernizr.csstransforms,
yep: ['/assets/js/turn.js'],
nope: ['/assets/js/turn.html4.min.js'],
both: ['/assets/js/zoom.min.js', '/js/magazine.js', '/css/magazine.css'],
complete: loadApp
});
</script>
</body>
</html>
The problem is that the flipbook should fit in to "parent_div" (800px) and the width that it is taking is the width of the explorer. In this way it centers it at the center of my screen and not the center of the div.
Any help would greatly be appresiated.
Turns out I had a function in /js/magazine.js that was resizing my viewport to the entire window's width.
So I just changed the code:
var width = $(window).width();
for
var width = $('#parent_div').width();
And voiala.
PS: This code was gotten entirely from an example of turn.js.
I hope this answer helps other people as future reference.
Related
I am trying to modify this example http://waynegm.github.io/imgNotes/examples/basic_interactive.html#
in order to get a select option to appear inside the dialog box when user clicks on the image. Currently the code places a marker on the area the user selects when in edit mode and opens a dialog box allowing them to enter text, with the options to save / cancel.
Inside the dialog box I want to change the textarea to a select list like:
<select>
<option value="head">Head</option>
<option value="leftarm">Left Arm</option>
<option value="rightarm">Right Arm</option>
<option value="leg">Leg</option>
</select>
It seems like it should be a simple change, I have made others samples where simple on image click makes the drop down appear. But this example has everything else I need like the options to delete and recording the co-ords of the place marker.
The current HTML:
<html>
<head>
<title>jQuery imgNotes - Interactive Base</title>
<style type="text/css" media="all">#import "css/marker.css";</style>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css" media="screen">
<script type="text/javascript" src="src/imgNotes.js"></script>
</head>
<body>
<div id="imgdiv" style="text-align: center">
<img id="image" src="image/personsit.jpg" style="border: 30px solid #ccc; padding:20px;" width=400/>
<br/>
<button id="toggleEdit">Edit</button> <button id="export">Export</button>
</div>
<div id=txt></div>
<script type="text/javascript">
;(function($) {
$(document).ready(function() {
var $img = $("#image").imgNotes();
//$img.imgNotes("import", [ {x: "0.5", y:"0.5", note:"AFL Grand Final Trophy"},
// {x: "0.4", y:"0.269", note: "Shoulder"},
// {x: "0.824", y: "0.593", note: "Fluffy microphone"}]);
var $toggle = $("#toggleEdit");
if ($img.imgNotes("option","canEdit")) {
$toggle.text("View");
} else {
$toggle.text("Edit");
}
$toggle.on("click", function() {
var $this = $(this);
if ($this.text()=="Edit") {
$this.text("View");
$img.imgNotes("option", "canEdit", true);
} else {
$this.text('Edit');
$img.imgNotes('option', 'canEdit', false);
}
});
var $export = $("#export");
$export.on("click", function() {
var $table = $("<table/>").addClass("gridtable");
var notes = $img.imgNotes('export');
$table.append("<th>X</th><th>Y</th><th>NOTE</th>");
$.each(notes, function(index, item) {
$table.append("<tr><td>" + item.x + "</td><td>" + item.y + "</td><td>" + item.note + "</td></tr>");
});
$('#txt').html($table);
});
});
})(jQuery);
</script>
</body>
</html>
imgNotes.js file
;(function($) {
$.widget("wgm.imgNotes", {
options: {
zoom: 1,
zoomStep: 0.1,
zoomable: true,
canEdit: false,
vAll: "middle",
hAll: "middle",
/*
* Default callback to create a marker indicating a note location
* See the examples for more elaborate alternatives.
*/
onAdd: function() {
this.options.vAll = "bottom";
this.options.hAll = "middle";
return $(document.createElement('span')).addClass("marker black").html(this.noteCount);
},
/*
* Default callback when the marker is clicked and the widget has canEdit = true
* Opens a dialog with a textarea to write a note.
* See the examples for a more elaborate alternative that includes a WYSIWYG editor
*/
onEdit: function(ev, elem) {
var $elem = $(elem);
$("#dialog-2").remove();
return $('<div id="dialog-2"></div>').dialog({
title: "Body Parts",
resizable: false,
modal: true,
height: "300",
width: "450",
position: { my: "left bottom", at: "right top", of: elem},
buttons: {
"Save": function() {
var txt = $('textarea', this).val();
// Put the editied note back into the data area of the element
// Very important that this step is included in custom callback implementations
$elem.data("note", txt);
$(this).dialog("close");
},
"Delete": function() {
$elem.trigger("remove");
$(this).dialog("close");
},
Cancel: function() {
$(this).dialog("close");
}
},
open: function() {
$(this).css("overflow", "hidden");
var textarea = $('<textarea id="txt" style="height:100%; width:100%;">');
$(this).html(textarea);
// Get the note text and put it into the textarea for editing
textarea.val($elem.data("note"));
}
})
},
/*
* Default callback when the marker is clicked and the widget has canEdit = false
* Opens a dialog displaying the contents of the marker's note
* See examples for alternatives such as using tooltips.
*/
onShow: function(ev, elem) {
var $elem = $(elem);
$('#NoteDialog').remove();
return $('<div id="NoteDialog"></div>').dialog({
modal: false,
resizable: false,
height: 300,
width: 250,
position: { my: "left bottom", at: "right top", of: elem},
buttons: {
"Close" : function() {
$(this).dialog("close");
}
},
open: function() {
// Get the note text and put it into the textarea for editing
$(this).html($elem.data("note"));
$(this).closest(".ui-dialog").find(".ui-dialog-titlebar:first").hide();
},
close: function() {
$(this).dialog("destroy");
}
});
},
/*
* Default callback when the markers are repainted
*/
onUpdateMarker: function(elem) {
var $elem = $(elem);
var $img = $(this.img);
var pos = $img.imgViewer("imgToView", $elem.data("relx"), $elem.data("rely"));
if (pos) {
$elem.css({
left: (pos.x - $elem.data("xOffset")),
top: (pos.y - $elem.data("yOffset")),
position: "absolute"
});
}
},
/*
* Default callback when the image view is repainted
*/
onUpdate: function() {
var self = this;
$.each(this.notes, function() {
self.options.onUpdateMarker.call(self, this);
});
}
},
_create: function() {
var self = this;
if (!this.element.is("img")) {
$.error('imgNotes plugin can only be applied to img elements');
}
// the note/marker elements
self.notes = [];
// the number of notes
self.noteCount = 0;
// the original img element
self.img = self.element[0];
var $img = $(self.img);
// attach the imgViewer plugin for zooming and panning with a custon click and update callbacks
$img.imgViewer({
onClick: function(ev, imgv) {
if (self.options.canEdit) {
ev.preventDefault();
var rpos = imgv.cursorToImg(ev.pageX, ev.pageY);
if (rpos) {
var elem = self.addNote(rpos.x, rpos.y);
self._trigger("onEdit", ev, elem);
}
}
},
onUpdate: function(ev, imgv) {
self.options.zoom = imgv.options.zoom;
self.options.onUpdate.call(self);
},
zoom: self.options.zoom,
zoomStep: self.options.zoomStep,
zoomable: self.options.zoomable
});
$img.imgViewer("update");
},
/*
* Remove the plugin
*/
destroy: function() {
this.clear();
$(this.img).imgViewer("destroy");
$.Widget.prototype.destroy.call(this);
},
_setOption: function(key, value) {
switch(key) {
case 'vAll':
switch(value) {
case 'top': break;
case 'bottom': break;
default: value = 'middle';
}
break;
case 'hAll':
switch(value) {
case 'left': break;
case 'right': break;
default: value = 'middle';
}
break;
}
var version = $.ui.version.split('.');
if (version[0] > 1 || version[1] > 8) {
this._super(key, value);
} else {
$.Widget.prototype._setOption.apply(this, arguments);
}
switch(key) {
case 'zoom':
$(this.img).imgViewer("option", "zoom", value);
break;
case 'zoomStep':
$(this.img).imgViewer("option", "zoomStep", value);
break;
case 'zoomable':
$(this.img).imgViewer("option", "zoomable", value);
break;
}
},
/*
* Pan the view to be centred at the given relative image location
*/
panTo: function(relx, rely) {
return $(this.img).imgViewer("panTo", relx, rely);
},
/*
* Add a note
*/
addNote: function(relx, rely, text) {
var self = this;
this.noteCount++;
var elem = this.options.onAdd.call(this);
var $elem = $(elem);
$(this.img).imgViewer("addElem",elem);
$elem.data("relx", relx).data("rely", rely).data("note", text);
switch (this.options.vAll) {
case "top": $elem.data("yOffset", 0); break;
case "bottom": $elem.data("yOffset", $elem.height()); break;
default: $elem.data("yOffset", Math.round($elem.height()/2));
}
switch (this.options.hAll) {
case "left": $elem.data("xOffset", 0); break;
case "right": $elem.data("xOffset", $elem.width()); break;
default: $elem.data("xOffset", Math.round($elem.width()/2));
}
$elem.click(function(ev) {
ev.preventDefault();
if (self.options.canEdit) {
self._trigger("onEdit", ev, elem);
} else {
self._trigger("onShow", ev, elem);
}
});
$elem.on("remove", function() {
self._delete(elem);
});
this.notes.push(elem);
$(this.img).imgViewer("update");
return elem;
},
/*
* Number of notes
*/
count: function() {
return this.noteCount;
},
/*
* Delete a note
*/
_delete: function(elem) {
this.notes = this.notes.filter(function(v) { return v!== elem; });
$(elem).off();
$(elem).remove();
$(this.img).imgViewer("update");
},
/*
* Clear all notes
*/
clear: function() {
var self = this;
var total = self.notes.length;
for ( var i = 0; i < total; i++ ){
var $this = self.notes[i];
$this.off();
$this.remove();
}
self.notes=[];
self.noteCount = 0;
},
/*
* Add notes from a javascript array
*/
import: function(notes) {
var self = this;
$.each(notes, function() {
self.addNote(this.x, this.y, this.note);
});
$(this.img).imgViewer("update");
},
/*
* Export notes to an array
*/
export: function() {
var notes = [];
$.each(this.notes, function() {
var $elem = $(this);
notes.push({
x: $elem.data("relx"),
y: $elem.data("rely"),
note: $elem.data("note")
});
});
return notes;
}
});
})(jQuery);
I would really appreciate if anyone could help me out.
when i get error Uncaught TypeError: Cannot read property 'alt' of null , my script works fine in browser but sometimes i see dragged object gets stucked when i inspect via device inscept i see belwo error
my script stops executing how can i prevent that ??..
see http://liveweave.com/GknZjq
(function () {
var canvas = new fabric.Canvas('canvas');
var canvas_el = document.getElementById('canvas');
var canvas1 = new fabric.Canvas('canvas1');
var group;
fabric.Image.fromURL('img/blank.png', function (img) {
var img1 = img.set({
left: 0,
top: 0
});
fabric.Image.fromURL('img/blank.png', function (img) {
var img2 = img.set({
left: 0,
top: 0
});
group = new fabric.Group([img1, img2], {
left: 0,
top: 0
});
canvas.add(group)
});
});
fabric.Image.fromURL('img/blank.png', function (img) {
var img1 = img.set({
left: 0,
top: 0
});
fabric.Image.fromURL('img/blank.png', function (img) {
var img2 = img.set({
left: 0,
top: 0
});
group1 = new fabric.Group([img1, img2], {
left: 0,
top: 0
});
canvas1.add(group1)
});
});
$(document).ready(function () {
/* Define drag and drop zones */
var $drop = $('#canvas-drop-area,#canvas-drop-area1'),
$gallery = $('td > #image-list li'),
$draggedImage=null;
/* Define the draggable properties */
$gallery.draggable({
helper: 'clone',
start: function (e) {
$draggedImage=event.target;
$drop.css({
'display': 'block'
})
},
stop: function () {
$(this).find('img').css({
/* 'opacity': 0.4 */
});
$drop.css({
'display': 'none'
});
$draggedImage=null;
},
revert: true
});
/* Define the events for droppable properties */
$drop.droppable({
over: function (event, ui) {
$(this).addClass('active');
},
drop: function (event, ui) {
var image =$draggedImage&& $draggedImage.src;
console.log($draggedImage.alt);
img_to_canvas(image,$draggedImage.alt,$(event.target).is("#canvas-drop-area")?1:2);
},
out: function (event, ui) {
$(this).removeClass('active');
},
deactivate: function (event, ui) {
$(this).removeClass('active');
}
});
});
var img_to_canvas = function(image,sendfront,checkcanvas) {
var img = new Image();
img.src = image;
if(checkcanvas =='1'){
if(sendfront=='top'){
fabric.util.loadImage(img.src, function (img) {
group.item(0).setElement(img);
canvas.renderAll();
});
}else{
fabric.util.loadImage(img.src, function (img) {
group.item(1).setElement(img);
canvas.renderAll();
});
}
canvas.calcOffset();
}else{
if(sendfront=='top'){
fabric.util.loadImage(img.src, function (img) {
group1.item(0).setElement(img);
canvas1.renderAll();
});
}else{
fabric.util.loadImage(img.src, function (img) {
group1.item(1).setElement(img);
canvas1.renderAll();
});
}
canvas1.calcOffset();
}
}
})();
I think the issue is because you're accessing the the dragged element inside drop handler from a variable that you're setting in draggables start event, which in turn you're setting back to null in it's stop handler.
You don't need to do this, you can access the dropped elements from the drop event callbacks arguments. Also, you don't need to change the CSS of droppable from the start, stop callbacks of draggable, you can use the activate and deactivate options of droppable itself.
The code for your draggable - droppable interaction should be something along the following lines:
$(document).ready(function () {
/* Define drag and drop zones */
var $drop = $('#canvas-drop-area,#canvas-drop-area1'),
$gallery = $('td > #image-list li'),
$draggedImage=null;
/* Define the draggable properties */
$gallery.draggable({
helper: 'clone',
start: function (e) {
$drop.css('display','block')
},
stop: function () {
$(this).find('img').css({
/* 'opacity': 0.4 */
});
},
revert: true
});
/* Define the events for droppable properties */
$drop.droppable({
over: function (event, ui) {
$(this).addClass('active');
},
drop: function (event, ui) {
var image = ui.draggable.find("img").get(0);
img_to_canvas(image, image.alt,$(event.target).is("#canvas-drop-area")?1:2);
},
out: function (event, ui) {
$(this).removeClass('active');
},
deactivate: function (event, ui) {
$(this).removeClass('active').css("display","none");
}
});
});
I am using fabric.js library to create a drag and drop moodboard creator. Everything works perfect, except in Firefox when I drag and drop the image to the canvas. It adds the image, but redirects to the img url. After the redirect, When I click on the back btn it goes back to the previous page and the image is on the canvas.
I have been searching and reading for a few hours now, trying all kinds of things. It seems that something in my code is preventing either "e.stopPropagation();" or "e.preventDefault()" from functioning correctly. I just cant seem to find the gremlin.
Any help would be great. Thanks!
UPDATE: Added JSFiddle.
here is a jsfiddle with my code:
http://jsfiddle.net/bQxMu/
UPDATE 2:
Fixed the issue, here is the part that fixed it:
function handleDrop(e) {
// this / e.target is current target element.
/*
if (e.stopPropagation) {
e.stopPropagation(); // stops the browser from redirecting.
}
*/
e.stopPropagation(); // Stops some browsers from redirecting.
e.preventDefault(); // Stops some browsers from redirecting.
var img = document.querySelector('#images img.img_dragging');
console.log('event: ', e);
var newImage = new fabric.Image(img, {
width: img.width,
height: img.height,
// Set the center of the new object based on the event coordinates relative
// to the canvas container.
left: e.layerX,
top: e.layerY
});
canvas.add(newImage);
return false;
}
Thanks for all the help :)
window.onload=function(){
var canvas = new fabric.Canvas('canvas');
canvas.backgroundColor = '#ffffff';
function handleDragStart(e) {
[].forEach.call(images, function (img) {
img.classList.remove('img_dragging');
});
this.classList.add('img_dragging');
}
function handleDragOver(e) {
if (e.preventDefault) {
e.preventDefault(); // Necessary. Allows us to drop.
}
e.dataTransfer.dropEffect = 'copy';
return false;
}
function handleDragEnter(e) {
// this / e.target is the current hover target.
this.classList.add('over');
}
function handleDragLeave(e) {
e.stopPropagation();
this.classList.remove('over'); // this / e.target is previous target element.
}
function handleDrop(e) {
// this / e.target is current target element.
if (e.stopPropagation) {
e.stopPropagation(); // stops the browser from redirecting.
}
var img = document.querySelector('#images img.img_dragging');
console.log('event: ', e);
var newImage = new fabric.Image(img, {
width: img.width,
height: img.height,
// Set the center of the new object based on the event coordinates relative
// to the canvas container.
left: e.layerX,
top: e.layerY
});
canvas.add(newImage);
return false;
}
function handleDragEnd(e) {
// this/e.target is the source node.
[].forEach.call(images, function (img) {
img.classList.remove('img_dragging');
});
}
var removeSelectedEl = document.getElementById('remove-selected');
removeSelectedEl.onclick = function() {
var activeObject = canvas.getActiveObject(),
activeGroup = canvas.getActiveGroup();
if (activeGroup) {
var objectsInGroup = activeGroup.getObjects();
canvas.discardActiveGroup();
objectsInGroup.forEach(function(object) {
canvas.remove(object);
});
}
else if (activeObject) {
canvas.remove(activeObject);
$("#imageControl").fadeOut('slow');
}
};
var sendBackwardsEl = document.getElementById('send-backwards');
sendBackwardsEl.onclick = function() {
var activeObject = canvas.getActiveObject();
if (activeObject) {
canvas.sendBackwards(activeObject);
}
};
var sendToBackEl = document.getElementById('send-to-back');
sendToBackEl.onclick = function() {
var activeObject = canvas.getActiveObject();
if (activeObject) {
canvas.sendToBack(activeObject);
}
};
var bringForwardEl = document.getElementById('bring-forward');
bringForwardEl.onclick = function() {
var activeObject = canvas.getActiveObject();
if (activeObject) {
canvas.bringForward(activeObject);
}
};
var bringToFrontEl = document.getElementById('bring-to-front');
bringToFrontEl.onclick = function() {
var activeObject = canvas.getActiveObject();
if (activeObject) {
canvas.bringToFront(activeObject);
}
};
document.getElementById('saveImg').onclick = function() {
if (!fabric.Canvas.supports('toDataURL')) {
alert('This browser doesn\'t provide means to serialize canvas to an image');
}
else {
canvas.deactivateAll().renderAll();
window.open(canvas.toDataURL('png'));
}
};
canvas.on('selection:cleared', function(options) {
var activeObject = canvas.getActiveObject();
if (activeObject === null) {
$("#imageControl").fadeOut('slow');
}
});
canvas.on('object:selected', function(options) {
var activeObject = canvas.getActiveObject();
if (options.target && activeObject !== null) {
$("#imageControl").show('slow');
}
});
canvas.on('selection:created', function(options) {
if (options.target) {
$("#imageControl").show('slow');
}
});
if (Modernizr.draganddrop) {
// Browser supports HTML5 DnD.
// Bind the event listeners for the image elements
var images = document.querySelectorAll('#images img');
[].forEach.call(images, function (img) {
img.addEventListener('dragstart', handleDragStart, false);
img.addEventListener('dragend', handleDragEnd, false);
});
// Bind the event listeners for the canvas
var canvasContainer = document.getElementById('canvas-container');
canvasContainer.addEventListener('dragenter', handleDragEnter, false);
canvasContainer.addEventListener('dragover', handleDragOver, false);
canvasContainer.addEventListener('dragleave', handleDragLeave, false);
canvasContainer.addEventListener('drop', handleDrop, false);
} else {
// Replace with a fallback to a library solution.
alert("This browser doesn't support the HTML5 Drag and Drop API.");
}
}
HTML:
<div id="images">
<img draggable="true" src="http://i.imgur.com/q9aLMza.png" width="70" height="90"></img>
</div>
<div id="canvas-container-controls">
<div id="imageControlWrapper">
<div id="imageControl">
<button class= "imgBtn" id="saveImg">Save Canvas</button>
<button class="imgBtn" id="remove-selected">Remove selected object/group</button>
<button id="send-backwards" class="imgBtn">Send backwards</button>
<button id="send-to-back" class="imgBtn">Send to back</button>
<button id="bring-forward" class="imgBtn">Bring forwards</button>
<button id="bring-to-front" class="imgBtn">Bring to front</button>
</div>
</div>
<div id="canvas-container">
<canvas id="canvas" width="400" height="400"></canvas>
</div>
</div>
Add an e.preventDefault() in handleDrop: http://jsfiddle.net/wN29y/
function handleDrop(e) {
// this / e.target is current target element.
e.preventDefault();
if (e.stopPropagation) {
e.stopPropagation(); // stops the browser from redirecting.
}
var img = document.querySelector('#images img.img_dragging');
console.log('event: ', e);
var newImage = new fabric.Image(img, {
width: img.width,
height: img.height,
// Set the center of the new object based on the event coordinates relative
// to the canvas container.
left: e.layerX,
top: e.layerY
});
canvas.add(newImage);
return false;
}
My understanding is that you should have e.stopPropagation in handleDragOver, otherwise the browser still accepts the event, and opens the image.
(Similar to my answer here: Why can't I get file dropping to work with jquery?)
I'm using slidejs from http://www.slidesjs.com/ and I wanted to refresh the list of images, because I need to add and remove images on the fly.
Is there any way to do this? I've tried to use the delete $.fn.pluginName but no luck.
Thanks
I've come up with a (rather funky) solution. It might not be the best way since heavy DOM manipulations/starting the plugin is used, but I hope you get the idea. The result can be found on this JSFiddle.
HTML
<input type="button" id="add" value="Add slide!" />
<div id="slides">
<img src="http://placehold.it/100x100" />
<img src="http://placehold.it/120x120" />
<img src="http://placehold.it/140x140" />
<img src="http://placehold.it/160x160" />
<img src="http://placehold.it/180x180" />
</div>
JavaScript
// Create a clone of the images array
var $originalClone = $("#slides").children().clone();
// Remove the parent (we'll create it dynamically)
$("#slides").remove();
// Create the new slides, add the children & add it to the DOM
var $newSlides = $("<div />")
.append($originalClone)
.appendTo($("body"));
// Execute the slide plugin
$newSlides.slidesjs({
width: 940,
height: 528
});
$("#add").on("click", function() {
// Remove the old slider
$newSlides.remove();
// Create a new slider, add the children & add it to the DOM
var $newSlides2 = $("<div />")
.append($originalClone)
.appendTo($("body"));
// Add the new image to the newly created slider
$("<img />")
.attr("src", "http://placehold.it/200x200")
.appendTo($newSlides2);
// Execute the slide plugin
$newSlides2.slidesjs({
width: 940,
height: 528
});
// In this demo, the button "add slide" can be clicked once
$("#add").remove();
});
I hope this solution gives you a hint in the good direction!
I recently had the same issue and manage to solve it by changing the plugin.
Here's my solution:
Add these following lines before Plugin.prototype.init = function() {:
Plugin.prototype.refresh = function (number){
var $element=$(this.element);
var _this = this;
this.data = $.data(this);
$(this.element).find(".slidesjs-pagination-item").remove();
$.data(this, "total", $(".slidesjs-control", $element).children().not(".slidesjs-navigation", $element).length);
$.each($(".slidesjs-control", $element).children(), function(i) {
var $slide;
$slide = $(this);
return $slide.attr("slidesjs-index", i);
});
$.each($(".slidesjs-control", $element).children(), function(i) {
var $slide;
$slide = $(this);
return $slide.attr("slidesjs-index", i);
});
if (this.data.touch) {
$(".slidesjs-control", $element).on("touchstart", function(e) {
return _this._touchstart(e);
});
$(".slidesjs-control", $element).on("touchmove", function(e) {
return _this._touchmove(e);
});
$(".slidesjs-control", $element).on("touchend", function(e) {
return _this._touchend(e);
});
}
$element.fadeIn(0);
this.update();
if (this.data.touch) {
this._setuptouch();
}
$(".slidesjs-control", $element).children(":eq(" + this.data.current + ")").eq(0).fadeIn(0, function() {
return $(this).css({
zIndex: 10
});
});
if (this.options.navigation.active) {
prevButton = $("<a>", {
"class": "slidesjs-previous slidesjs-navigation",
href: "#",
title: "Previous",
text: "Previous"
}).appendTo($element);
nextButton = $("<a>", {
"class": "slidesjs-next slidesjs-navigation",
href: "#",
title: "Next",
text: "Next"
}).appendTo($element);
}
$(".slidesjs-next", $element).click(function(e) {
e.preventDefault();
_this.stop(true);
return _this.next(_this.options.navigation.effect);
});
$(".slidesjs-previous", $element).click(function(e) {
e.preventDefault();
_this.stop(true);
return _this.previous(_this.options.navigation.effect);
});
if (this.options.play.active) {
playButton = $("<a>", {
"class": "slidesjs-play slidesjs-navigation",
href: "#",
title: "Play",
text: "Play"
}).appendTo($element);
stopButton = $("<a>", {
"class": "slidesjs-stop slidesjs-navigation",
href: "#",
title: "Stop",
text: "Stop"
}).appendTo($element);
playButton.click(function(e) {
e.preventDefault();
return _this.play(true);
});
stopButton.click(function(e) {
e.preventDefault();
return _this.stop(true);
});
if (this.options.play.swap) {
stopButton.css({
display: "none"
});
}
}
if (this.options.pagination.active) {
pagination = $("<ul>", {
"class": "slidesjs-pagination"
}).appendTo($element);
$.each(new Array(this.data.total), function(i) {
var paginationItem, paginationLink;
paginationItem = $("<li>", {
"class": "slidesjs-pagination-item"
}).appendTo(pagination);
paginationLink = $("<a>", {
href: "#",
"data-slidesjs-item": i,
html: i + 1
}).appendTo(paginationItem);
return paginationLink.click(function(e) {
e.preventDefault();
_this.stop(true);
return _this.goto(($(e.currentTarget).attr("data-slidesjs-item") * 1) + 1);
});
});
}
$(window).bind("resize", function() {
return _this.update();
});
this._setActive();
if (number){
this.goto(number+1);
} else {
this.goto(0);
}
};
Then, change the content of return $.fn[pluginName] = function(options,the_args) { to this:
return $.fn[pluginName] = function(options,the_args) {
var the_return=this.each(function() {
if (!$.data(this, "plugin_" + pluginName)) {
return $.data(this, "plugin_" + pluginName, new Plugin(this, options));
}
});
if (typeof options=="string"){
var element=this.get(0);
if (arguments.length>1){
var the_args=Array.prototype.slice.call(arguments);;
the_args.splice(0,1);
var plugin=$.data(element, "plugin_" + pluginName);
return plugin[options].apply(plugin,the_args);
} else {
return $.data(element, "plugin_" + pluginName)[options]();
}
}
return the_return;
};
This way, you could call other functions of the plugin like goto.
In the code, you just need to call the refresh function like this:
$("#id_of_container").slidesjs("refresh");
or, if you want to refresh and jump to another slide, call it like this:
$("#id_of_container").slidesjs("refresh",number_of_slide);
where number_of_slide is an int number starting at 0;
Here is my copy and paste solution. Removes single current tab.
$('#SLIDESID').slidesjs({
//...
});
// ... later somewhere else ... //
var currentIndex = $('#SLIDESID').data().plugin_slidesjs.data.current;
//remove active tab
$('#SLIDESID [slidesjs-index="' + currentIndex + '"]').remove();
$('#SLIDESID [data-slidesjs-item="' + currentIndex + '"]').parent().remove();
//reindex tabs
var tabs = $('#SLIDESID [slidesjs-index]');
tabs.each(function(idx, elem){
$(elem).attr('slidesjs-index', idx);
});
//reindex pagination
$('#SLIDESID [data-slidesjs-item]').each(function(idx, elem){
$(elem).attr('data-slidesjs-item', idx);
$(elem).text(idx+1);
});
//tweek plugin data
$('#SLIDESID').data().plugin_slidesjs.data.total = tabs.length;
$('#SLIDESID').data().plugin_slidesjs.data.current--;
//animate to new element by clicking on NEXT
$('#SLIDESID .slidesjs-next').click();
I'm using this script on my tumblr page, which gives posts different random text colors:
function get_random_color() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;}
$(function() {
$(".post").each(function() {
$(this).css("color", get_random_color());
}); });
The thing is the script isn't working for elements loaded with infinite scrolling. Can anyone help me rewrite this code? I don't know how to write javascript sadly.
Take a look at your blog's main.js script. You can call your custom function when you grab the new elements from another page. This is my proposed revision of your main.js file.
$(window).load(function () {
var $wall = $('#content');
$wall.imagesLoaded(function () {
$wall.masonry({
itemSelector: '.post',
isAnimated: false
});
});
$wall.infinitescroll({
navSelector: '#pagination',
nextSelector: '#pagination li a.pagination_nextlink',
itemSelector: '.post',
loadingImg: "http://static.tumblr.com/kwz90l7/bIdlst7ub/transparent.png",
loadingText: " ",
donetext: " ",
bufferPx: 100,
debug: false,
errorCallback: function () {
$('#infscr-loading').animate({
opacity: .8
}, 2000).fadeOut('normal');
}
}, function (newElements) {
var $newElems = $(newElements);
$newElems.hide();
$newElems.each(function(value){
value.css("color", get_random_color());
});
$newElems.imagesLoaded(function () {
$wall.masonry('appended', $newElems, {
isAnimated: false,
animationOptions: {
duration: 900,
easing: 'linear',
queue: false
}
}, function () {
$newElems.fadeIn('slow');
});
});
$(document).ready(function () {
$("a[rel^='prettyPhoto']").prettyPhoto({
deeplinking: false,
default_width: 600,
default_height: 550,
allow_resize: true,
});
});
});
$('#content').show(500);
});
function get_random_color() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
}
What I've done is add your get_random_color function and called it from within the Infinite Scroll call to add a custom color to each of the elements in $newElems so really, all I've done is taken your code and integrated it differently than what you were trying to do, which wasn't working. This should, theoretically, work. If it doesn't or you have questions, let me know.