jQuery touchmove stops working when removing child - javascript

I have two divs:
<div class="main">
<div class="child" />
</div>
I've created an event listener for the main element which enables the user to drag the child element around
map.bind('touchmove', function(f) {
if (map.pinch) {
return;
}
f.preventDefault();
f.originalEvent.preventDefault();
f = f.originalEvent.touches[0];
map.handleMoveEvent(f);
});
map.handleMoveEvent = function(f) {
mover.css('left', map.getX() + (f.clientX - map.lastmouse.clientX) / scaler.scale);
mover.css('top', map.getY() + (f.clientY - map.lastmouse.clientY) / scaler.scale);
map.lastmouse = f;
map.moverMoved();
}
map.moverMoved = function() {
if (map.getX() > 0) {
map.tileX--;
mover.moveX(-TILE_WIDTH);
map.find(".child").moveX(TILE_WIDTH);
map.updateVisibleTiles();
}
if (map.getX() < -TILE_WIDTH) {
map.tileX++;
mover.moveX(TILE_WIDTH);
map.find(".child").moveX(-TILE_WIDTH);
map.updateVisibleTiles();
}
if (map.getY() > 0) {
map.tileY--;
mover.moveY(-TILE_HEIGHT);
map.find(".child").moveY(TILE_HEIGHT);
map.updateVisibleTiles();
}
if (map.getY() < -TILE_HEIGHT) {
map.tileY++;
mover.moveY(TILE_HEIGHT);
map.find(".child").moveY(-TILE_HEIGHT);
map.updateVisibleTiles();
}
$('#console').html(map.tileX + " " + map.tileY);
//$('#console').html(map.getX() + " " + map.getY());
};
map.updateVisibleTiles = function() {
mover.find(".child").remove();
for (x = Math.max(map.tileX - tiledistance, 0); x <= Math.min(map.tileX + tiledistance, map.getTileCount() - 1); x++) {
for (y = Math.max(map.tileY - tiledistance, 0); y <= Math.min(map.tileY + tiledistance, map.getTileCount() - 1); y++) {
var child = $(document.createElement('div'));
child.width(TILE_WIDTH);
child.height(TILE_HEIGHT);
var farbe = 'rgb(' + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ',' + (Math.floor(Math.random() * 256)) + ')';
child.css("background-color", farbe);
child.css('position', 'absolute');
child.addClass('child');
child.css('left', (x - map.tileX) * TILE_WIDTH);
child.css('top', (y - map.tileY) * TILE_HEIGHT);
mover.append(child);
}
}
}
In some situations i have to exchange the child while dragging
$('.main').find(".child").remove();
but after removing the touchmove does not fire anymore. It only happens when i start the touchmove by tapping on the child element... The problem is obvios to me, but what's the solution?

$().remove() removes the dom element and it's event listeners. Use $().detach() to preserve event listeners.
http://api.jquery.com/detach/
The .detach() method is the same as .remove(), except that .detach() keeps all jQuery data associated with the removed elements. This method is useful when removed elements are to be reinserted into the DOM at a later time.

i just created an invisible overlay which handles the event, this seems to work:
var toch = $(document.createElement('div'));
toch.css('position', 'absolute');
toch.css('width', '100%');
toch.css('height', '100%');
map.append(toch);
toch.bind('touchmove', function(f) {})

Related

Why I obtain this error message when from a dialog I try to perform a function defined into the parent page using parent.rifiutaSingolo()?

I have the following problem trying to perform a JavaScript function from a dialog that is defined into the parent page that opened this dialog.
So I have this situation:
I have a parent page page named autorizzaFattura2 that is the page that open the dialog (when the user click on a link the dialog is opened) by this JavaScript:
function openDialog2(pagina,larghezza,lunghezza,tipo) {
//alert("INTO openDialog2(), pagina: " + pagina, " larghezza: " + larghezza + " lunghezza: " + lunghezza + " tipo: " + tipo);
larghezza = '950px';
lunghezza = '470px';
lunghezza2 = '530px';
if (tipo == 3) {
larghezza = '950px';
lunghezza = '470px';
lunghezza2 = '530px';
}
if (tipo == 9) {
larghezza = '950px';
lunghezza = '470px';
lunghezza2 = '530px';
}
unitaLargo = larghezza.substring(larghezza.length - 2, larghezza.length)
unitaLungo = lunghezza.substring(lunghezza.length - 2, lunghezza.length)
var puntiLarghezza = 0;
var puntiLunghezza = 0;
if (unitaLargo != "px") {
//per default è in percentuale
Wlargo = (screen.width * larghezza) / 100;
puntiLarghezza = Wlargo;
Wlargo = Wlargo + "px";
} else {
Wlargo = larghezza
puntiLarghezza = larghezza.substring(0, larghezza.length - 2);
}
if (unitaLungo != "px") {
//per default è in percentuale
Wlungo = (screen.height * lunghezza) / 100;
puntiLunghezza = Wlungo;
Wlungo = Wlungo + "px";
} else {
Wlungo = lunghezza
puntiLunghezza = lunghezza.substring(0, lunghezza.length - 2);
}
var l = (screen.width / 2) - (puntiLarghezza / 2);
var t = (screen.height / 2) - (puntiLunghezza / 2);
DialParam = 'width=' + Wlargo + ',height=' + Wlungo + ',toolbar=no,directories=no,';
DialParam = DialParam + 'toolbar=no,location=no,directories=no,status=no,menubar=no,copyhistory=no,scrollbars=yes,resizable=no';
//alert("pagina: " + pagina);
pag_aperta = window.open(pagina, 'popUp_', DialParam);
pag_aperta.moveTo(l, t);
pag_aperta.focus();
}
So, as you can see, the popup is opened by the window.open() statement, this one:
pag_aperta = window.open(pagina, 'popUp_', DialParam);
OK, into this parent page (autorizzaFattura2) there is also defined the rifiutaSingolo() JavaScript function, this one:
function rifiutaSingolo() {
alert("Into rifiutaSingolo()");
chiudi();
$('#myRejectNote').css("visibility", "visible");
$('#rifiutaTable').css("visibility", "visible");
$("#dialogReject").dialog("open");
document.getElementById('myRejectNote').focus();
}
OK, into the dialog opened by the openDialog2() function there is this button that clicked have to perform the rifiutaSingolo() function defined into the parent page:
<input style="color: #FFFFFF; font: bold 10px tahoma,arial,helvetica,sans-serif" class="bottone" readonly="readonly" type="button" value="Rifiuta" onclick="parent.rifiutaSingolo()">
I tried to do it using the parent, in this way: onclick="parent.rifiutaSingolo()" but it don't work and the rifiutaSingolo() function is not performed and in the FireBug console I obtain this error message (when I click on the button):
TypeError: parent.rifiutaSingolo is not a function
Why? What am I missing? How can I fix this issue and correctly perform the rifiutaSingolo() function defined into the parent page?
Solved by myself.
The problem was that my dialog was not a real dialog but it was created and showd by window.open
pag_aperta = window.open(pagina, 'popUp_', DialParam);
So to perform the rifiutaSingolo() defined into the parent page I can't use this:
onclick="parent.rifiutaSingolo()"
because it is related to the dialog but I have to use this:
onclick="window.opener.rifiutaSingolo()"
that is related to the window

Change animation css attribute with javascript onmousemove?

So im making this little trick on my website that when you move your cursor on the screen it changes the speed at which the logo of the site rotates.
For some reason i cannot seem to be able to change the animation attribute of the element im rotating on the fly with js. I also added a textbox to display the mouse X position which im using for the speed of the roation of the logo, and it displays the string correctly so i guess its probably a silly syntax error.
<style type="text/css">
#logorota {
animation: 15s linear 0s normal none infinite rot_inf;
}
#keyframes rot_inf {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(359deg);
}
}
</style>
<body>
<script>
document.captureEvents(Event.MOUSEMOVE);
document.onmousemove = mousePos, logoSpeed;
function mousePos (x) {
var mouseX = x.pageX / 100;
document.mouseMovs.mousePos.value = mouseX + "s linear 0s normal none infinite rot_inf"; //displays the string correctly.
};
function logoSpeed (x)
{
var mouseX = x.pageX / 100;
document.getElementById('logorota').style.animation = mouseX + "s linear 0s normal none infinite rot_inf";
};
</script>
<div>
<img src="logorota.png" id="logorota">
<form name="mouseMovs">
<input type="text" name="mousePos" /> Mouse position <br />
</form>
</div>
</body>
EDIT: Added http://jsfiddle.net/ot4zyp30/
I have a solution here for webkit, working right. It is a lil tricky to change these values on the fly.
Attached to 'mousemove', this script adds / removes the animation rule & class continiously and alters some values so it rotates smooth enough.
Theres bunch of stuff you wanna change if you use this. Atleast make sure the stylesheet index is good etc. in this case i use 1 since thats the jsFiddle stylesheet index.
EDIT: works on firefox now too
http://jsfiddle.net/9nj4dgeq/
//
document.addEventListener('mousemove', function(event) {
Rotator.init(event, document.getElementsByClassName("img")[0]);
}, false);
//
var Rotator = {
init: function(event, element_) {
var element = element_,
compatibility = {
prefixes: ["-webkit-", "-moz-"],
},
browserPrefix,
browserEvent = event.clientX,
stylesheet = 0;
for (var k in compatibility) {
if (k === "prefixes") {
for (var i = 0; i < compatibility[k].length; i += 1) {
if (window.getComputedStyle(element, null).getPropertyValue(compatibility[k][i] + "transform") !== null) {
browserPrefix = compatibility.prefixes[i];
}
}
}
}
this.rotate(element, browserPrefix, browserEvent, stylesheet);
},
rotate: function(element_, browserPrefix_, browserEvent_, stylesheet_) {
var element = element_,
className = element.className,
browserPrefix = browserPrefix_,
browserEvent = browserEvent_,
stylesheet = stylesheet_,
blanks = [
"#" + browserPrefix + "keyframes ",
" {from{" + browserPrefix + "transform:rotate( ",
"deg);}to{" + browserPrefix + "transform:rotate(",
"deg);}}",
".",
"{" + browserPrefix + "animation-name:",
";" + browserPrefix + "animation-timing-function:linear;" + browserPrefix + "animation-iteration-count:infinite;" + browserPrefix + "animation-duration:",
"s}"],
name = "rotating" + browserEvent,
speed = String(browserEvent / 100),
transform = window.getComputedStyle(element, null).getPropertyValue(browserPrefix + "transform"),
values, a, b, angle, toAngle;
if (transform !== "none") {
values = transform.split('(')[1];
values = values.split(')')[0];
values = values.split(',');
a = values[0];
b = values[1];
angle = Math.round(Math.atan2(b, a) * (180 / Math.PI));
}
toAngle = 360 + angle;
document.styleSheets[stylesheet].insertRule(blanks[0] + name + blanks[1] + angle + blanks[2] +
(function () {
if (!toAngle) {
return 10;
} else {
return toAngle;
}
}()) + blanks[3], 0);
document.styleSheets[stylesheet].insertRule(blanks[4] + className + blanks[5] + name + blanks[6] + speed + blanks[7], 0);
if (document.styleSheets[stylesheet].cssRules.length > 8) {
for (var rules = document.styleSheets[stylesheet].cssRules.length; rules > 2; rules -= 1) {
document.styleSheets[stylesheet].deleteRule([rules] - 1);
}
}
}
}

Move each character of a div based on mouse movement

I'm developing a site and I don't know how to create a javascript animation that looks like this:
I have a div that have some text on it, and when the user moves his mouse over this text, I want each character to move independently of each other, in order to maintain a certain distance from it (the mouse). Also, I want this animation to have rotation, but it isn't that important now. Here's an image explanation:
Here's what I did so far:
HTML:
<div class="div1">Hello World</div>
Javascript:
var chars = $(".div1").html().split('');
$(".div1").empty();
for(var i = 0; i < chars.length; i++){
$(".div1").append("<span class='letter'>"+chars[i]+"</span>");
}
JSFiddle
Can someone help me to achieve this effect? I don't know how to proceed and there's no site or answer that helped me. You can use jQuery or pure JavaScript but, please, keep it simple! Thank you.
Oh here we go, I've found a solution for this.
What I did was using a different class name for each character (.letter + character number) and then created a way of moving the characters depending on the mouse position and distance compared to each character, so, for example, when the distance between the mouse and a character is less than X, and the mouse Y is less than the character Y, then the character will go down.
Thanks to adeneo and Derek
Here's the relevant code:
JavaScript:
var chars = $(".div1").html().split('');
$(".div1").empty();
for (var i = 0; i < chars.length; i++) {
$(".div1").append("<span class='letter" + i + "'>" + chars[i] + "</span>");
$(".letter" + i).css({
"position":"relative",
});
$(".letter" + i).css({
"transition": "0.5s"
});
}
$(document).on("mousemove", function (e) {
for (var i = 0; i < chars.length; i++) {
var x = e.pageX,
y = e.pageY;
var distx = x - $(".letter" + i).offset().left + ($(".letter" + i).width() / 2);
var disty = y - $(".letter" + i).offset().top;
if (Math.abs(distx) < 24 && Math.abs(disty) < 24) {
if (distx > 6 || distx < -6) {
if (x < $(".letter" + i).offset().left) {
$(".letter" + i).css({
"left": + (24 / Math.abs(distx) * Math.abs(distx)),
"position": "relative"
});
} else {
$(".letter" + i).css({
"left": - (24 / Math.abs(distx) * Math.abs(distx)),
"position": "relative"
});
}
}
if (disty > 12 || disty < -12) {
if (y < $(".letter" + i).offset().top + 6) {
$(".letter" + i).css({
"top": + (24 / Math.abs(disty) * Math.abs(disty)),
"position": "relative"
});
} else {
$(".letter" + i).css({
"top": - (24 / Math.abs(disty) * Math.abs(disty)),
"position": "relative"
});
}
}
}
distx = 0;
disty = 0;
}
});
HTML:
<div class="div1">Hello World</div>
Updated JSFiddle with CSS Transitions to improve smoothness
Well since you say yo want to learn, i'll give a code to help you out, but you have to work your way through, i haven't test it, i just wrote it blindly so it propably won't work but might give you a good idea of what must be done.
Html:
<div class="container">
<div id="coolDiv" class="scatterContainer">Hello World</div>
</div>
Css:
*{margin:0;}
span:hover{
color:#0CF;
}
.scatterContainer{
display: inline;
}
.container {
margin: 30px auto;
}
Javascript
LetterScatterer = (function() {
function LetterScatterer(id) {
this.id = id
this.$el = $('#' + this.id);
this.rangeOfaction = 3; // Number of characters to affect
this.maxVerticalMovement = 10; // Value in px
this.minVerticalMovement = 2
this.duration = 100; // In miliseconds
// Event Listeners
this.$el.on(mousemove((function(_this){
return function(e){
var x = e.pageX;
var y = e.pageY;
return _this.scatter(x, y);
}
})(this));
}
LetterScatterer.prototype.splitCharacters = function() {
var nodes = [];
var nodesQ = 0;
var _this = this;
this.chars = $el.text().split('');
$el.empty();
for(var i = 0; i < chars.length; i++){
var markup = "<span class='letter'>"+chars[i]+"</span>";
nodes.push(markup);
}
this.$nodes = $(nodes);
this.nodesWidth = [];
this.$nodes.each(function(){
var width = $(this).outerWidth();
_this.nodesWidth.push(width);
});
$el.append(this.$nodes);
}
LetterScatterer.prototype.scatter = function(x, y) {
var epicenter;
var offset = 0;
var midPoint, farestLeft;
for(var i = 0, len = this.nodesWidth.length; i < len; i++){
offset += this.nodesWidth[i];
if(x <= offset){
epicenter = i;
break;
}
}
leftRange = (this.rangeOfaction - 1) / 2; // We remove one, this is our epicenter, then we get left and right halves
farestLeft = epicenter - leftRange;
for(var i = farestLeft; i < this.rangeOfaction; i++){
this.animateY($node[i]);
}
}
LetterScatterer.prototype.animateY = function(node, verticalDisplacement) {
var $node = $(node);
$node.animate({margin-top: verticalDisplacement + 'px'}, this.duration);
}
return LetterScatterer;
})();
letterScatterer = new LetterScatterer('coolDiv');
What you see in the code is a classlike function, first you pass it the id of the element containing the text that will be scattered. There are some config varaibles, range of action is lets say, if you mouse over one character, how many characters to the left and to the right (also including the current hovered element) should be animated, the max and min verticalMovement, determines how much should move the one that is hovered (max) and those further apart will use min, those in between should interpolate, but i didn't code that far.
We then got a mousemove listener, that calls the method scatter, this method finds which items is currently hovered by adding up each character widht, but now i think about it, it should be easier to just add a listener to the span, and get the current index of that element with the jQuery method index(), then based on that index you animate that one and those in the range. You must create the code that calculates the rotation, and x movement if you want to, but i think i gave you a lot to start, it took me a while to code it, so i hope it helps and this answer satisfies your question. :)

Putting simple functions that contain jquery in a jquery execution queue

I have a number of functions containing jquery that should be executed sequentially. They aren't used to create effects but rather to position certain elements at a calculated location inside a div. All online resources on jquery queue are focused on the creation of transitions or animations so it's hard to find a simple example on how to execute a number of simple functions sequentially.
I have these functions:
function bigItemRecalc(recalc, idBase, innerHeight, i) {
if (recalc < 0) {
$('#' + idBase + i).css('max-height', (innerHeight + (2 * recalc)));
recalc = 0;
}
return recalc;
}
function firstCheck(recalc, idBase, i) {
if (i == 1) {
$('#' + idBase + i).css('margin-top', recalc * -1);
}
}
function lastCheck(recalc, idBase, itemAmount, i) {
if (i == itemAmount) {
$('#' + idBase + i).css('margin-top', recalc);
}
}
function truncateItems(totalHeight, widgetHeight, idBase, i) {
if (totalHeight > (widgetHeight - 20)) {
$('#' + idBase + i).remove();
$('#' + idBase + "b" + i).remove();
}
}
In another function I want to execute these sequentially by using a jquery queue preferably , but I haven't got a clue how.
The code is called here:
function styleWidget(itemAmount, widgetHeight, widgetWidth, idBase) {
var innerHeight;
var outerHeight;
var recalc;
var totalHeight = 0;
var totalWidth = 0;
for (var i = 1; i <= itemAmount; i++)
{
if (widgetHeight >= widgetWidth)
{
totalHeight += $('#'+idBase+i).height();
innerHeight = $('#' + idBase + i).height();
outerHeight = (widgetHeight/itemAmount);
recalc = ((outerHeight / 2) - (innerHeight / 2));
recalc = bigItemRecalc(recalc, idBase, innerHeight, i);
$('#' + idBase + i).css('padding-top', recalc);
firstCheck(recalc, idBase, i);
lastCheck(recalc, idBase, itemAmount, i);
truncateItems(totalHeight, widgetHeight, idBase, i);
}
else
{
innerHeight = $('#'+idBase+i).height();
outerHeight = widgetHeight;
recalc = ((outerHeight/2)-(innerHeight/2));
$('#'+idBase+i).css('padding-top',recalc);
totalWidth += $('#'+idBase+i).width();
if (totalWidth > (widgetWidth-20))
{
$('#' + idBase + i).remove();
$('#' + idBase + "b" + i).remove();
}
}
}
}
The bottom part hasn't been updated just yet, but it can be ignored as it's being tested with portrait mode widgets.
I think I've found a clue. When no delay is introduced the values of totalHeight and innerHeight seem very low. So I assume that the page isn't fully loaded by the time the script is executed. Every time a new widget is generated the above script is called like this:
$(document).ready(styleWidget(3, 225, 169, 'id-871206010'));
This fixed it:Why does Firefox 5 ignore document.ready?
It seems like reloading the page did not trigger the .ready() function.

function doesn't execute on jquery document ready

I have a javascript function that resize and centers images based on the surrounding container size (that in turn depend on the window size). I use jquery as js framework. The function need to be executed after document load (on document ready) but also when and if the user changes size of the browser, ie I have the following running in the html-document:
$(document).ready(function(){
fixImageSizes();
});
$(window).resize(function() {
fixImageSizes();
});
But for some unknown reason the function is only executed when a user resizes the browser and not after loading. Can anyone please help with this?
(my function is below for knowledge...)
function fixImageSizes()
{
var cw = $('#imagecontainer').width();
var ch = $('#imagecontainer').height();
$('#imagecontainer img').each(function()
{
var iw = $(this).css('width');
var ih = $(this).css('height');
if (parseInt(iw) < parseInt(cw)) // image width < viewport
{
var newih = Math.ceil(parseInt(ih) * parseInt(cw) / parseInt(iw)) + 'px';
var newimargint = '-' + Math.ceil(parseInt(newih)/2) + 'px';
var newimarginl = '-' + Math.ceil(parseInt(cw)/2) + 'px';
$(this).css({'width':cw,'height':newih,'margin-left':newimarginl,'margin-top':newimargint});
}
if (parseInt(ih) < parseInt(ch)) // image height < viewport
{
var newiw = Math.ceil(parseInt(iw) * parseInt(ch) / parseInt(ih)) + 'px';
var newimargint = '-' + Math.ceil(parseInt(ch)/2) + 'px';
var newimarginl = '-' + Math.ceil(parseInt(newiw)/2) + 'px';
$(this).css({'width':newiw,'height':ch,'margin-left':newimarginl,'margin-top':newimargint});
}
if (parseInt(ih) > parseInt(ch) && parseInt(iw) > parseInt(cw)) // viewport smaller than image, shrink image
{
if (parseInt(ch) - parseInt(ih) > parseInt(cw) - parseInt(iw)) // difference is less on height
{
var newiw = Math.ceil(parseInt(iw) * parseInt(ch) / parseInt(ih)) + 'px';
var newimargint = '-' + Math.ceil(parseInt(ch)/2) + 'px';
var newimarginl = '-' + Math.ceil(parseInt(newiw)/2) + 'px';
$(this).css({'width':newiw,'height':ch,'margin-left':newimarginl,'margin-top':newimargint});
}
else // difference less on width
{
var newih = Math.ceil(parseInt(ih) * parseInt(cw) / parseInt(iw)) + 'px';
var newimargint = '-' + Math.ceil(parseInt(newih)/2) + 'px';
var newimarginl = '-' + Math.ceil(parseInt(cw)/2) + 'px';
$(this).css({'width':cw,'height':newih,'margin-left':newimarginl,'margin-top':newimargint});
}
}
});
You should use the load event instead of the ready event.
The ready event runs after the document has loaded, but before the images has loaded, so you won't have the correct size of all elements.
The function is probably executing (you can double-check with a simple alert), but the images you are "fixing" is probably not loaded yet. You can use the window.onload event or listen to the image load event like this:
var scale = function() {
// rescale
};
$('#imagecontainer img').each(function() {
this.complete ? scale.call(this) : $(this).load(scale);
});
Try this:
$(window).load(function (){
fixImageSizes();
});

Categories

Resources