JQuery resizable problem when dynamically adding elements - javascript

ok so i have this script, and what it does is makes an ajax call to a page every time the link is clicked, gets the html element from the ajax puts it into the mainCanvas element, then assign drag and resize features to it.
(example of html recieved from ajax. ###### = the instanceID being passed to it via ajax so the ID is different for each instance)
ajax.php
<div id="Image_######" style=" width:55px; height:55px; position: absolute;">
<img class="Image_######" alt="" title="" src="http://www.imagemagick.org/Usage/thumbnails/hatching_orig.jpg" style="width: 100%; height: 100%;" />
</div>
the problem i am having with this is for some reason only the last element has the abbility to resize, they are all still draggable, but resize is broken for previously added elements as soon as the new element is added.
What i want to do is be able to add multiple elements and resize them all not just the last element added.
i suspect that it may have something to do with how I am appending the response html to the canvas, but I'm not sure. I'm more familiar with standard javascript than i am with the voodoo that is JQuery so any help would be much appreciated.
here is the code below, and here is a link to a running example http://sheac.com/resize-problem/
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.2.0/build/cssreset/reset-min.css">
<link rel="stylesheet" type="text/css" href="media/css/_library/jquery/ui-lightness/jquery-ui-1.8.5.custom.css">
<script type="text/javascript" src="media/js/_library/jquery/jquery-1.4.2.js"></script> <!-- jQuery Base -->
<script type="text/javascript" src="media/js/_library/jquery/jquery-ui-1.8.5.custom.js"></script> <!-- jQuery User-Interface Base -->
<script type="text/javascript" src="media/js/_library/jquery/jquery.ui.resizable.js"></script>
create new instance
<br /><br />
<div id="mainCanvas" style="border: 1px solid #CCC; width: 1000px; height: 500px;"></div>
<script type="text/javascript" language="javascript">
//<![CDATA[
var instanceID = 1000;
var properties = ["draggable", "resizableImage"];
function getInstance(){
var instanceID = getNextInstanceID();
$.get("ajax.php", {instanceID: instanceID},
function(response){
document.getElementById("mainCanvas").innerHTML += response;
runProperties(instanceID);
}
);
}
function getNextInstanceID() {
var iid = instanceID;
instanceID++;
return iid;
}
function runProperties(instanceID) {
if (properties != undefined) {
for (var t in properties) {
assignProperty(properties[t], instanceID);
}
}
}
function assignProperty(property, instanceID) {
switch(property) {
case "draggable":
$("#Image_"+instanceID).addClass(property);
$(function() {
$("." + property).draggable({
grid: [ 16, 16 ],
snap: false,
containment: "#mainCanvas",
scroll: false
});
});
break;
case "resizableImage":
$("#Image_"+instanceID).addClass(property);
$(function() {
$("." + property).resizable({
grid: [ 16, 16 ],
minWidth: 32,
maxWidth: 208,
minHeight: 32,
maxHeight: 208,
aspectRatio: 1/1
});
});
break;
}
}
//]]>
</script>

you make ALL images draggable and resizable in "assignProperty" function.
You just need to do this for new element:
function assignProperty(property, instanceID) {
switch(property) {
case "draggable":
$("#Image_"+instanceID).draggable({
grid: [ 16, 16 ],
snap: false,
containment: "#mainCanvas",
scroll: false
});
break;
case "resizableImage":
$("#Image_"+instanceID).resizable({
grid: [ 16, 16 ],
minWidth: 32,
maxWidth: 208,
minHeight: 32,
maxHeight: 208,
aspectRatio: 1/1
});
break;
}
}

Related

how to get fabricJS to work with touch events?

I have an application developped with phonegap and I am testing the touch support for fabricJS but somehow it doesn't work for me.
I tried creating a custom version here but it doesn't work with it.
I have this jsfiddle where I used another version called fabric_events.js but it doesn't seems to work too. (BTW how do you upload your own version to jsfiddle?)
so I tried the FabricJS touch events demo and it DOES work!!
since the demo worked I tried to download it's own version from http://fabricjs.com/lib/fabric_with_gestures.js but still no luck.
this is my code:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1, width=device-width, user-scalable=true" />
<script src="js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="js/fabric_with_gestures.js"></script>
<script type="text/javascript" >
$(document).ready
(
function () {
var canvas = new fabric.Canvas('c');
// Do some initializing stuff
fabric.Object.prototype.set({
transparentCorners: false,
cornerColor: 'rgba(102,153,255,0.5)',
cornerSize: 12,
padding: 5
});
alert('fabric.isTouchSupported=' + fabric.isTouchSupported);
var info = document.getElementById('info');
canvas.on({
'touch:gesture': function () {
var text = document.createTextNode(' Gesture ');
info.insertBefore(text, info.firstChild);
},
'touch:drag': function () {
var text = document.createTextNode(' Dragging ');
info.insertBefore(text, info.firstChild);
},
'touch:orientation': function () {
var text = document.createTextNode(' Orientation ');
info.insertBefore(text, info.firstChild);
},
'touch:shake': function () {
var text = document.createTextNode(' Shaking ');
info.insertBefore(text, info.firstChild);
},
'touch:longpress': function () {
var text = document.createTextNode(' Longpress ');
info.insertBefore(text, info.firstChild);
}
});
fabric.Image.fromURL('http://fabricjs.com/assets/pug_small.jpg', function (img) {
img.scale(0.5).set({
left: 150,
top: 150,
angle: -15
});
canvas.add(img);
});
canvas.add(new fabric.Rect({
left: 50,
top: 50,
fill: '#269926',
width: 100,
height: 100,
originX: 'left',
originY: 'top',
hasControls: true,
hasBorders: true,
selectable: true
}));
var obj = new fabric.Rect({
left: 20,
top: 20,
fill: '#555555',
width: 100,
height: 100,
originX: 'left',
originY: 'top',
hasControls: true,
hasBorders: true,
selectable: true
});
canvas.add(obj).renderAll();
canvas.setActiveObject(obj)
//canvas.sendToBack(obj)
}
);
</script>
<title></title>
<style>
canvas {
border: 1px solid #999;
}
</style>
</head>
<body>
<canvas id="c" width="200" height="200" style='z-index:-1'></canvas>
<p id='info' style='background: #eef; width: 583px; padding: 10px; overflow: scroll; height: 80px'></p>
</body>
</html>
Sorry for the late answer. I am working with Fabric.js at the moment and I do not have any problems with gestures. I have tried your code, it is generally working if you care for three things:
1.) Very important: Please remove style='z-index:-1' from the canvas itself. The z-index property specifies the stack order of an element and a negative number will not allow you to interact with the canvas in your example. More information: CSS z-index Property.
2.) Are you sure that you had created a Custom Build with "Interaction" and "Gestures"? "Gestures" is dependent on "Interaction". If you are unsure, create a Custom Build with all modules except "Node" (unless you want to use Node.js later).
3.) Fabric.js and jQuery must be in the subfolder 'js' regarding to your code. But I would think that it was like that already.
Then it should work for you, too.

Javascript roulette table, drag and drop

Good morning everyone,
I need to create a roulette table where you can drag a poker chip on the number(graphically) using only javascript/css/html.
Question 1: What would be the best approach for this?
Question 2: I thought of using 2 for loops to initialize divs with all the numbers in them and then use drag and drop(http://luke.breuer.com/tutorial/javascript-drag-and-drop-tutorial.aspx) to "snap" the poker chip image to the closest div when it is released. Euhm... How would I know where to snap the image without using hundreds of if/else?
Thank you very much! Have a nice day! :)
Update:
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
#div1 {
width: 20px;
height: 40px;
padding: 10px;
border: 1px solid #aaaaaa;
}
#game {width:350px;height:70px;padding:10px;border:1px solid #aaaaaa;}
</style>
</head>
<body>
<p>Drag the W3Schools image into the rectangle:</p>
<br>
<div id="game">
</div>
<img id="drag1" src="images/c.png" draggable="true" ondragstart="drag(event)" width="336" height="69">
<script>
function allowDrop(ev)
{
ev.preventDefault();
}
function drag(ev)
{
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev)
{
ev.preventDefault();
var data=ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
}
function dragAlert() {
alert("Ondrag");
}
var numberCount = 1;
var divId = 0;
var div = document.createElement("div");
div.className = "div1";
/*divId = "id";
divId += numberCount;*/
div.id = "div1";
div.ondrop = function() {
drop(event);
};
div.ondragover = function() {
allowDrop(event);
};
document.getElementById("game").appendChild(div);
numberCount++;
</script>
</body>
</html>
Does anyone know why ondragover/ondrop doesn't work with this code?
I think you'd like interact.js. It's a standalone JavaScript drag and drop, resize and multitouch gesture module I wrote. I recently added snapping; it allows you to snap to a custom grid or more suitably in this case, custom anchors.
To make element draggable, you would call interact(element).draggable(true) then bind listeners to dragmove events:
interact(element).bind('dragmove', function (event) {
// use event.dx, event.dy and normal MouseEvent properties
// to move the element
});
And to configure the snapping to custom anchors:
interact.snap({
mode: 'anchors',
anchors: [
{x: 300, y: 100, range: 50},
{x: 100, y: 400, range: 40},
{x: 500, y: 400},
{x: 500, y: 500}
],
range: 30
});
I wrote a blog post explaining how to use it here: Drag and drop snap to grid with interact.js. The post also links to an interactive demo.

JQuery Reload to

I'm new to JQuery and Javascript, and can't find a good example online of how to refresh just the html object inside a div.
The html object is this graph from cosm.com
index.html
<div id="graph" >
<object type="text/html" style="width:100%; height:100%; margin:1%;"data="https://api.cosm.com/v2/feeds/120687/datastreams/sensor_reading.png?width=740&height=150&colour=%230055ff&duration=5minutes&legend=Vibrations%20measure%20%200%20-%3E%201024&title=Foosball%20Vibrations%20-%205%20Minutes&stroke_size=4&show_axis_labels=true&detailed_grid=true&scale=manual&max=75&timezone=Mountain%20Time%20(US%20%26%20Canada)" >
</object>
</div>
script.js
$(document).ready( function() {
updateGraph;
setInterval (updateGraph, 2000);
}
function updateGraph() {
//This line is not working!!!!
$('#graph').reload();
//$('#graph').load();
}
http://jsfiddle.net/spuder/PNK4k/
Try this out http://jsfiddle.net/Bvpft/16/
Tested in Chrome and FireFox. It refreshes and redownloads the image but not sure what it's supposed to be doing beyond that.
HTML
<!DOCTYPE html>
<body>
<div id="graph" >
<object type="text/html" style="width:100%; height:100%; margin:1%;" data="">
</object>
</div>
</body>
Javascript
$(document).ready( function() {
var graph = $('#graph'),
uri = 'https://api.cosm.com/v2/feeds/120687/datastreams/sensor_reading.png?',
params = {
width: 740,
height: 150,
colour: '#0055ff',
duration: '5minutes',
legend: 'Vibration measure 0 -> 1024 ',
title: 'Foosball Vibrations - 5 Minutes',
show_axis_labels: 'true',
detailed_grid: 'true',
scale: 'manual',
max: 75,
timezone: 'Mountain Time (US & Canada)'
};
var updateGraph = function() {
var data = uri + $.param(params);
graph.empty();
graph.append($('<object/>')
.prop({'type': 'text/html', data: data})
.css({'width': '100%', 'height': '100%'}))
};
updateGraph();
setInterval (updateGraph, 1000);
});
Edited - Changed to Image, made non-flickering, added no-caching (Tested in IE10, Chrome and FireFox): http://jsfiddle.net/JAYDb/4/
HTML
<div id="graph" ></div>
CSS
#graph {
background-color:#C0C0C0;
margin: 0 auto;
min-height: 200px ;
min-width: 750px ;
display: inline-block;
}
#graphObject{
display: block;
width: 100%;
}
Javascript
$(document).ready( function() {
var uri = 'https://api.cosm.com/v2/feeds/120687/datastreams/sensor_reading.png?',
params = {
width: 740,
height: 150,
colour: '#0055ff',
duration: '5minutes',
legend: 'Vibration measure 0 -> 1024 ',
title: 'Foosball Vibrations - 5 Minutes',
show_axis_labels: 'true',
detailed_grid: 'true',
scale: 'manual',
max: 75,
timezone: 'Mountain Time (US & Canada)'
};
var data = uri + $.param(params),
graph = $('#graph'),
obGraph = $('<img/>').prop({'id': 'graphObject'});
var updateGraph = function() {
var date = new Date(),
src = data + '&' + date.getTime();
obGraph.prop('src', '');
obGraph.prop('src', src);
};
graph.empty().append(obGraph);
updateGraph();
setInterval (updateGraph, 1000);
});
A closing bracket is missing?
$(document).ready
( function()
{
updateGraph;
setInterval (updateGraph, 2000);
}
); // missing
You're jsfiddle is not working, because no jQuery version was selected. I've made a working example:
$(document).ready( function() {
alert("OK");
updateGraph();
window.setInterval(updateGraph, 5000);
} );
function updateGraph() {
//This line is not working!!!!
alert("ok");
//$('graph').reload(); // unknown method?
}
http://jsfiddle.net/mmGT9/4/
What do you mean with "$('graph').reload(); ? Is that a custom function?
If you want to reload the "object", I would remove the object from the HTML area and leave just the blank DIV. Then add the following line in your javascript function.
$("#graph").html('<object type="text/html" style="width:100%; height:100%; margin:1%; " data="https://api.cosm.com/v2/feeds/120687/datastreams/sensor_reading.png?width=740&height=150&colour=%230055ff&duration=5minutes&legend=Vibrations%20measure%20%200%20-%3E%201024&title=Foosball%20Vibrations%20-%205%20Minutes&stroke_size=4&show_axis_labels=true&detailed_grid=true&scale=manual&max=75&timezone=Mountain%20Time%20(US%20%26%20Canada)" ></object>');
This will set the object into the element with the id "graph". Existing content within the div will be overridden. The function is called every n seconds and replaces the object, which force a reload. You can do it more pretty by using a variable.
Here is an example: http://jsfiddle.net/mmGT9/5/
jsFiddle
This Works..
I changed your object to an img tag
<img id='obj' style="width:100%; height:100%; margin:1%; " src=...
$('document').ready( function() {
var i;
var src = $('#obj').prop('src');
setInterval(function(){
i++;
$('#obj').prop('src',src+"&"+i);
},5000);
});

Reloading jQuery function within another function

this is a tricksy one, i am not even sure on how to word the title for this.
so what i have is a bit of a mix up i have a jQuery function called slideonlyone, that toggles divs and within the divs i have a jQuery plugin called the royalSlider(content slider).
what happens is when i first load up the page i have the one div un-toggled by default and the royalSlider plugin works fine. the moment i toggle the page to another div with the royalSlider plugin, it fails to load that plugin.
the head of my page looks like this:
<head>
<link rel="stylesheet" href="/css/system.css" type="text/css">
<link rel="stylesheet" href="/css/royalslider.css" type="text/css">
<link rel="stylesheet" href="/css/default/rs-default-inverted.css" type="text/css">
<script src="/js/jquery-1.8.3.min.js" type="text/javascript"></script>
<script src="/js/jquery.royalslider.js" type="text/javascript"></script>
<script src="/js/systems_jquery.js" type="text/javascript"></script>
<script type="text/javascript">
function slideonlyone(thechosenone) {
$('.systems_detail').each(function(index) {
if ($(this).attr("id") == thechosenone) {
$(this).slideDown(200);
}
else {
$(this).slideUp(600);
}
});
}
</script>
</head>
the royalSlider is called in a seperate file i load called 'systems_jquery.js'
jQuery(document).ready(function($) {
var rsi = $('#slider-in-laptop').royalSlider({
autoHeight: false,
arrowsNav: false,
fadeinLoadedSlide: false,
controlNavigationSpacing: 0,
controlNavigation: 'bullets',
imageScaleMode: 'fill',
imageAlignCenter: true,
loop: false,
loopRewind: false,
numImagesToPreload: 6,
keyboardNavEnabled: true,
autoScaleSlider: true,
autoScaleSliderWidth: 486,
autoScaleSliderHeight: 315
}).data('royalSlider');
$('#slider-next').click(function() {
rsi.next();
});
$('#slider-prev').click(function() {
rsi.prev();
});
});
the html looks like this
i have this as a type of brief summary- when they click on the div is loads the slideonlyone function which toggles the products details
<a href="javascript:slideonlyone('beagle_box');">
<div class="system_box">
<h2>BEE management systems</h2>
<p>________________</p>
</div>
</a>
This is the product details div.
<div class="systems_detail" id="sms_box">
<div class="laptopBg">
<img src="/images/laptop.png" class="imgBg" width="707" height="400">
<div id="slider-in-laptop" class="royalSlider rsDefaultInv">
<img src="/images/1.jpg">
<img src="/images/2.jpg" data-rsvideo="https://vimeo.com/45778774">
<img src="/images/3.jpg">
<img src="/images/4.jpg">
</div>
</div>
</div>
as you can see that apart of the details is the royalSlider it shows screen shots of the product. but since its only just appearing the images are not loaded into the slider and images are displayed under each other as if the plugin is broken but when i inspect the element and go to the console i can see that its not broken. so i suspect that the royalSlider is going to need to reload when ever i toggle the div so that it finds the IDs again??
is it possible to reload the royalSlider function when ever i toggle/slide some content from my slidonlyone function?
NOTE: if i toggle the div and the slider drops its content if i reload the page it picks them up again. so its definitely the royalSlider needing to reload once i have toggeld the div -- or reload the page once i have toggled the page.
Well if you want to run 'royalSlider' again than just wrap whole thing in a function. Then just run it at the time you think you need to reload it ('documentReady' or 'click', etc):
royalSliderReload = function() {
var rsi = $('#slider-in-laptop').royalSlider({
autoHeight: false,
arrowsNav: false,
fadeinLoadedSlide: false,
controlNavigationSpacing: 0,
controlNavigation: 'bullets',
imageScaleMode: 'fill',
imageAlignCenter: true,
loop: false,
loopRewind: false,
numImagesToPreload: 6,
keyboardNavEnabled: true,
autoScaleSlider: true,
autoScaleSliderWidth: 486,
autoScaleSliderHeight: 315
}).data('royalSlider');
$('#slider-next').click(function() {
rsi.next();
});
$('#slider-prev').click(function() {
rsi.prev();
});
}
$(document).ready(function(e) {
royalSliderReload();
});
function slideonlyone(thechosenone) {
$('.systems_detail').each(function (index) {
if ($(this).attr("id") == thechosenone) {
$(this).slideDown(200);
royalSliderReload(); // slider will reload here
} else {
$(this).slideUp(600);
}
});
}

Creating an swf on an swf with jQuery

I have this javascript file which is a modified version of the VideoLightBox script:
jQuery(function(){
var $=jQuery;
var swfID = "video_overlay";
if(!document.getElementById("vcontainer")){
$("body").append($("<div id='voverlay'></div>"));
$("#voverlay").append($("<div id = 'vcontainer'></div>"));
}
$("#videogallery a[rel]").overlay({
api:true,
expose: (0?{
color:'#424542',
loadSpeed:400,
opacity:0
}:null),
effect:"apple",
onClose: function(){
swfobject.removeSWF(swfID);
},
// create video object for overlay
onBeforeLoad: function(){
// check and create overlay contaner
var c = document.getElementById(swfID);
if(!c){
var d = $("<div></div>");
d.attr({id: swfID});
$("#vcontainer").append(d);
};
var wmkText="© 2011 BORKH";
var wmkLink="http://borkh.co.uk";
c = wmkText? $('<div></div>'):0;
if (c) {
c.css({
position:'absolute',
right:'38px',
top:'38px',
padding:'0 0 0 0'
});
$("#vcontainer").append(c);
};
// for IE use iframe
if (c && document.all){
var f = $('<iframe src="javascript:false"></iframe>');
f.css({
position:'absolute',
left:0,
top:0,
width:'100%',
height:'100%',
filter:'alpha(opacity=0)'
});
f.attr({
scrolling:"no",
framespacing:0,
border:0,
frameBorder:"no"
});
c.append(f);
};
var d = c? $(document.createElement("A")):c;
if(d){
d.css({
position:'relative',
display:'block',
'background-color':'',
color:'#626d73',
'font-family': 'RegisterSansBTNDmRegular, Helvetica, Arial',
'font-size':'11px',
'font-weight':'normal',
'font-style':'normal',
'text-decoration': 'none',
padding:'1px 5px',
opacity:.7,
filter:'alpha(opacity=70)',
width:'auto',
height:'auto',
margin:'0 0 0 0',
outline:'none'
});
d.attr({href:wmkLink});
d.html(wmkText);
d.bind('contextmenu', function(eventObject){
return false;
});
c.append(d);
}
// create SWF
var src = this.getTrigger().attr("href");
if (typeof(d)!='number' && (!c || !c.html || !c.html())) return;
if (false){
var this_overlay = this;
// if local
window.videolb_complite_event = function (){ this_overlay.close() };
// if youtoube
window.onYouTubePlayerReady = function (playerId){
var player = $('#'+swfID).get(0);
if (player.addEventListener) player.addEventListener("onStateChange", "videolb_YTStateChange");
else player.attachEvent("onStateChange", "videolb_YTStateChange");
window.videolb_YTStateChange = function(newState){
if (!newState) this_overlay.close()
}
}
}
swfobject.createSWF(
{ data:src, width:"100%", height:"100%", wmode:"opaque" },
{ allowScriptAccess: "always", allowFullScreen: true, FlashVars: (false?"complete_event=videolb_complite_event()&enablejsapi=1":"") },
swfID
);
}
}); });
The script opens a flash swf file in a "popup" lightbox fashion and plays it either from youtube or via a player locally. I was however wondering if it was possible to create a secondary swf to float on top of the player (noting that this of course would have the wmode:"transparent") and hereby create an opening curtain effect revealing the first swf and the player. I've been trying for quite some time now to load the top clip via createSWF and to create an additional div to contain it and float it using absolute position however I can't seem to get it right.. I know that the div float perfectly on top of each other when using:
<head>
<style type="text/css" media="screen">
<!--
#bottom{
position:absolute;
width: 500px;
height: 400px;
}
#top{
position:absolute;
width:500px;
height:400px;
top: 0px;
left: 0px;
}
-->
</style>
</head>
<body>
<div id="bottom">
"MAIN CLIP"
<div id="top">
"CURTAIN EFFECT"
</div>
</div>
However I'm not strong enough in javascripting to transfer it.
Any help, ideas, hints or suggestions are much appreciated!
Thanks
Andreas
I think your idea will work, but could get quite tricky.
What I would recommend instead is creating a "curtain swf" that instead loads something like the Chromeless YouTube player inside of it. This way you can listen for when the video is done loading/buffering and reveal the curtains when that happens.

Categories