How to stop animation with jQuery timers? - javascript

I'm wondering how to stop an animation made with jQuery timers. I think I have tried everything, I would really like your help.
<!DOCTYPE html>
<html>
<head>
<meta content='yes' name='apple-mobile-web-app-capable'>
<meta content='default' name='apple-mobile-web-app-status-bar-style'>
<meta content='width=device-width, minimum-scale=1.0, maximum-scale=1.0' name='viewport'>
<title>HeartMath - Danmark</title>
<script src='http://code.jquery.com/jquery.min.js' type='text/javascript'></script>
<script src='http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js' type='text/javascript'></script>
<script src='inc/jquery.timers-1.1.2.js' type='text/javascript'></script>
<script type="text/javascript" >
jQuery.fn.log = function (msg) {
console.log("%s: %o", msg, this);
return this;
}; var fixgeometry = function() {
/* Some orientation changes leave the scroll position at something
* that isn't 0,0. This is annoying for user experience. */
scroll(0, 0);
/* Calculate the geometry that our content area should take */
var header = $(".header:visible");
var footer = $(".footer:visible");
var content = $(".content:visible");
var viewport_height = $(window).height();
var content_height = viewport_height - header.outerHeight() - footer.outerHeight();;
/* Trim margin/border/padding height */
content_height -= (content.outerHeight() - content.height());
content.height(content_height);
}; /* fixgeometry */
$(document).ready(function() {
$(window).bind("orientationchange resize pageshow", fixgeometry);
var animationSpeed = 3500;
var animationHeight = $(window).height() * 0.70;
$("input[type='radio']").bind( "change", function(event, ui) {
if($(this).val() == "true") {
startAnimation(animationSpeed);
$(this).log("animationen burde starte");
}
else {
stopAnimation();
$(this).log("animationen burde stopppe");
}
}).log("der blev trykket");
function startAnimation(animationDuration) {
$(".breather").everyTime(10, function(){
$(".breather").animate({top:animationHeight}, animationDuration).animate({top:"0"}, animationDuration);
}).log("startAnimation");
};
function stopAnimation() {
$(".breather").stopTime().stop().log("stopAnimation");
};
});
</script>
<style type="text/css">
html, body {
width: 100%;
}
div.breather {
display: block;
position:relative;
}
}
</style>
<link href='http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.css' rel='stylesheet'>
<link rel="stylesheet" type="text/css" href="jquery-mobile/hm-mobile-theme.css">
</head>
<body>
<div data-role='page' data-theme='a'>
<div class='header' id="header" data-role='header'> <img src="img/hm-logo.png" style="margin:0px auto;" height="40" /> </div>
<div class='content' data-role='content'>
<div class="breather">landscape!</div>
</div>
<div class='footer' data-role='footer'>
<div data-role="fieldcontain">
<fieldset data-role="controlgroup" data-type="horizontal">
<input type="radio" name="ignition" id="start" value="true" />
<label for="start">Start</label>
<input type="radio" name="ignition" id="stop" value="false" checked="checked" />
<label for="stop">Stop</label>
</fieldset>
</div>
</div>
</div>
</body>
</html>
What happens now is that when i press stop.. the animation just reverses and loops again

When you call .stop() to stop the jQuery animation, change it to .stop(true) to clear the animation queue (docs here). I'm not sure why there is a queue, but it looks like it has something to do with the timers plugin that you are using. Use queue().length to see how many animations are left in the queue.

Please make sure that the stopAnimation is being called by adding some debugging (console.log()). You call stopAnimation without an argument, but the function has an argument, that's not used.
So add some debugging to stopanimation and the if(val==false) statement. If that all works as expected we can continue the search.

Related

Rotate image via Range Slider

Hi guys how to make the image rotate via range slider?
I built the function so it can range between 0 and 360 and show the value range, it's working fine, but how to apply this to rotate the image?
The crop image script documentation is here
I updated the code with the crop script, please help to rotate the image and output to a div
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Cropper.js</title>
<!-- <link rel="stylesheet" href="dist/cropper.css"> -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/0.8.1/cropper.css" />
<style>
.container {
max-width: 640px;
margin: 20px auto;
}
img {
max-width: 100%;
}
</style>
</head>
<body>
<div class="container">
<h1>Cropper with a range of aspect ratio</h1>
<div>
<img id="image" src="https://fengyuanchen.github.io/cropperjs/images/picture.jpg" alt="Picture">
</div>
<button onclick="cropper.getCroppedCanvas()">Save</button>
</div>
<!-- <script src="dist/cropper.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/0.8.1/cropper.js"></script>
<script>
window.addEventListener('DOMContentLoaded', function () {
var image = document.querySelector('#image');
var minAspectRatio = 1.0;
var maxAspectRatio = 1.0;
var cropper = new Cropper(image, {
ready: function () {
var cropper = this.cropper;
var containerData = cropper.getContainerData();
var cropBoxData = cropper.getCropBoxData();
var aspectRatio = cropBoxData.width / cropBoxData.height;
var newCropBoxWidth;
if (aspectRatio < minAspectRatio || aspectRatio > maxAspectRatio) {
newCropBoxWidth = cropBoxData.height * ((minAspectRatio + maxAspectRatio) / 2);
cropper.setCropBoxData({
left: (containerData.width - newCropBoxWidth) / 2,
width: newCropBoxWidth
});
}
},
cropmove: function () {
var cropper = this.cropper;
var cropBoxData = cropper.getCropBoxData();
var aspectRatio = cropBoxData.width / cropBoxData.height;
if (aspectRatio < minAspectRatio) {
cropper.setCropBoxData({
width: cropBoxData.height * minAspectRatio
});
} else if (aspectRatio > maxAspectRatio) {
cropper.setCropBoxData({
width: cropBoxData.height * maxAspectRatio
});
}
}
});
});
</script>
<script>
function updateTextInput(val) {
document.getElementById('textInput').value=val;
}
</script>
<input type="range" name="rangeInput" min="0" max="360" onchange="updateTextInput(this.value);">
<input type="text" id="textInput" value="">
<!-- FULL DOCUMENTATION ON https://github.com/fengyuanchen/cropperjs -->
</body>
</html>
You can use some javascript to set the rotation of the image when the slider value changes. Since you have jQuery:
$(function(){
let slider = $('input[type=range]'),
image = $('#image');
slider.on('change mousemove', function(){
image.css('transform', 'rotate(' + $(this).val() + 'deg)');
});
});
Side note: This type of event assignment - finding the element in javascript, rather than adding onchange attributes to the input - is much more flexible and maintainable.
Here's an example: https://codepen.io/benjamin-hull/pen/ewxboE
A couple of things to watch:
I've added the 'mousemove' event listener as well as 'change', so the user gets real-time feedback as they move the slider. This might be a problem, as mousemove can produce 100's of events. You might need to look at 'debouncing' that event to limit it to a sensible value.
In my example, I've set the slider to min -180, max 180 and a default of 0. This allows the user to rotate left and right.
You probably want the rotation to scale the image as well, so it always fills the frame.

what does the window pop before the pages even loads or the tap happens? JQUERY MOBILE

The "Call 2062710041" pops up before the pages loads all the way and the the button isnt event touched. Whats wrong with the code?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>home</title>
<link rel="stylesheet" href="themes/style.min.css" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2 /jquery.mobile.structure-1.3.2.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script> <script>
$('#phone').on( 'tap',"#phone",goto());{
function goto(event){
window.location = 'tel:2062710041'}};
</script>
</head>
<body>
<div data-role="page" data-theme="a">
<div data-role="header" data-position="inline" >
<div class="leftstyle"> <img src="message.gif" width="40" height="39"></div>
<div class="rightstyle"> <img src="call.gif" id="phone" width="40" height="39"> </div>
<div class="center"> <img src="LOGO.png" width="209" height="210" > </div>
Using this method below will allow you to wait until the page is loaded to perform anything inside of it. This is jQuery's ready function.
$(document).ready(function() { /* your code. */ });
Same process outside of jQuery.
document.onload = function(){ /* your code. */ };
Use jquery's ready() function to bind the tap on full load. Try:
$(document).ready(function () {/*your code*/})
You also have a couple of extra {} brackets
$('#phone').on('click', function(event){
event.preventDefault();
if(event.handled !== true)
{
location.href = 'tel:2062710041';
event.handled = true;
}
return false;
});`

auto-resizing text input box html

I created an input (type text) box and made it auto-resize quite simply. However, there are a few glitches that I can't seem to fix:
when I start typing the box shrinks a tiny bit
when I press backspace (or directional arrows), the box expands first, and then shrinks when I continue typing.
Here is my code:
function Expander() {
this.start = function () {
$("#inputbox").keydown(function(e) {
this.style.width = 0;
var newWidth = this.scrollWidth + 10;
if( this.scrollWidth >= this.clientWidth )
newWidth += 10;
this.style.width = newWidth + 'px';
});
}
}
$(function() {
window.app = new Expander();
window.app.start();
});
input {
margin-left:3em;
min-width:100px;
max-width:600px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<meta charset="UTF-8">
<body>
<div id="wrap">
<input type="text" id="inputbox" name="input" placeholder="I want this to resize smoothly." width="100px"/>
</div>
<div id="counter"></div>
</body>
You can try this.
We put the content in a hidden span & then adjust width according to span scrollWidth.
function Expander() {
this.start = function () {
$('#inputbox').on('keydown',function(e) {
$("#hidden_span").html("");
$("#hidden_span").append("<p>"+$(this).val()+"</p>");
var hidden_span_scroll_width=$("#hidden_span")[0].scrollWidth;
if(hidden_span_scroll_width> 100||hidden_span_scroll_width< 600){
$(this).css("width",hidden_span_scroll_width);
}
});
}
}
$(function() {
window.app = new Expander();
window.app.start();
});
input {
margin-left:3em;
min-width:100px;
max-width:600px;
}
#hidden_span{
position:absolute;
top:0px;
left:0px;
visibility:hidden;
width:10px;
white-space:nowrap;
overflow:hidden;
}
<head>
<meta charset="UTF-8">
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
</head>
<body>
<div id="wrap">
<input type="text" id="inputbox" name="input" placeholder="I want this to resize smoothly." />
</div>
<div id="counter"></div>
<span id="hidden_span"></span>
</body>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<title>Test page</title>
</head>
<body>
<style>
input {
margin-left:3em;
min-width:100px;
max-width:600px;
}
#hidden_span{
position:absolute;
top:0px;
left:0px;
visibility:hidden;
width:10px;
white-space:nowrap;
overflow:hidden;
}
</style>
<script>
function Expander() {
this.start = function () {
$('#inputbox').on('keydown',function(e) {
$("#hidden_span").html("");
$("#hidden_span").append("<p>"+$(this).val()+"</p>");
var hidden_span_scroll_width=$("#hidden_span")[0].scrollWidth;
if(hidden_span_scroll_width> 100||hidden_span_scroll_width< 600){
$(this).css("width",hidden_span_scroll_width);
}
});
}
}
$(function() {
window.app = new Expander();
window.app.start();
});
</script>
<div id="wrap">
<input type="text" id="inputbox" name="input" placeholder="yes" />
</div>
<div id="counter"></div>
<span id="hidden_span"></span>
</body>
</html>
At first you can use jQuery methods to avoid crossbrowser problem. And scrollWidth returns either the width in pixels of the content of an element or the width of the element itself, whichever is greater. So enlarge newWidth only when content width strongly larger than element width.
$("#inputbox").keydown(function(e) {
var a = $(this).width(), newWidth;
if(this.scrollWidth - a > 0){
newWidth = a + 10;
}else if(e.keyCode==8){
newWidth = a - 10;
}
$(this).css("width", newWidth);
});
If you don't want to make input smaller when pressed backspace - delete else if part of code.
<input type="text" id="inputbox" name="input" placeholder="yes" width="100px"/>
Remove the width="100px", like this:
<input type="text" id="inputbox" name="input" placeholder="yes"/>
And it won't resize down anymore when starting to type.
Live example:
http://jsfiddle.net/2EMfd/
Though, the exanding function doesn't seem to work in my browser?
*Edit, did a simple expand function on the inputbox is this what you where trying? http://jsfiddle.net/2EMfd/1/

Greensock TimelineMax Javascript Singleton Different in Firefox

I'm relatively new javascript, but I am comfortable in other languages. I'm trying to use the Greensock timeline to construct modular sequences to reduce code duplication. I'm trying to have a singleton timeline that is accessible by all my functions. I tried just using a global var and attaching to() methods to it. That worked in chrome and iexplorer, but not Firefox. I received a "this.timeline is null" error in the Firefox error console. Then I tried this:
var TL = (function() {
var tl = new TimelineMax();
function returnInstance() {
return tl;
}
return {
inst: function() {
return returnInstance();
}
}
})();
This made the singleton I want, but I get the same error only in FF. The code below works fine in both chrome and iexplorer:
dev.html:
<html>
<body>
<-- Page content... -->
<script type='text/javascript' src='js/jquery.js'></script>
<script type='text/javascript' src='js/TweenMax.min.js'></script>
<script type='text/javascript' src='js/foo.js'></script>
<script type='text/javascript'>
$(document).ready(function(){
init();
});
</script>
</body>
</html>
foo.js:
//...singleton code from above...
function init(){
do1();
do2(-2);
}
do1(delay){
delay = delay || 0;
var gTL = TL.inst();
gTL.to($("#bar"),2,{css:{autoAlpha:1}},delay);
}
do2(delay){
delay = delay || 0;
var gTL = TL.inst();
gTL.to($("#canv"),2,{css:{autoAlpha:1}},delay);
}
So, this will make #bar and #canv enter at the same time (if I call do2(0); then #canv will come in after #bar is done).
Do you have any insight into what I'm doing wrong or why FF is handling the code differently?
Thanks for your help.
EDIT1
Browser Versions:
Chrome(19.0.1084.56)
Internet Explorer(9.0.8112.16421)
Firefox(13.0)
EDIT2
The error generates from inside of the TweenMax.min.js file.
EDIT3
Before trying to use a global timeline and a singleton, I implemented the desired functionality by passing a TimelineMax reference to each function and returning the updated TimelineMax. So, my code looked a little like this:
foo.js
function init() {
var tl = new TimelineMax();
tl = do1(tl);
tl = do2(tl);
}
do1(TL){
TL.to(...);
return TL;
}
do2(TL){
TL.to(...);
return TL;
}
This seemed to work fine in Firefox, but it's a little more tedious to play hot potato with the timeline object. Is that the preferred method? Where can I find well formed coding standards and best practices for javascript?
EDIT4
Here is the full non-working code. It works as expected in both chrome and ie, but I receive an error in FF coming from the TweenMax.js library.
dev_page2.html:
<!DOCTYPE HTML>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
<link rel="stylesheet" type="text/css" href="css/dev.css">
<!--[if lt IE 7]>
<style media="screen" type="text/css">
#main {
height:100%;
}
</style>
<![endif]-->
</head>
<body class="whiteBG">
<header class="center">
<div id="bar" class="invisible">
<nav>
<!-- nav elements here... -->
</nav><!-- nav -->
</div><!-- bar -->
<canvas id="ani" class='invisible center' width='840' height='420'></canvas>
</header><!-- End header -->
<section id="main">
<div id="content" class="center">
<p>
</p><blockquote>
</blockquote><p class="signature">
</p><p class="float-left">
</p><p class="float-left">
</p>
</div> <!-- End content -->
</section>
<footer class="invisible center">
<div id="footerLeft">
</div>
<div id="footerCenter">
</div>
<div id="footerRight">
</div>
</footer><!-- End footer -->
<script type="text/javascript" src="js/Jquery.js">
</script>
<script type="text/javascript" src="js/TweenMax.js"></script>
<script type="text/javascript" src="js/dev2.js"></script>
<script type="text/javascript">
$(document).ready(function() {
init();
});
</script>
</body>
</html>
dev2.js:
// Copyright 2012 Gray Designs. All Rights Reserved.
/*
* #author rocky.grayjr#gmail.com (Rocky Gray)
* #date May 13, 2012
*/
function init()
{
enterNavBar();
drawCanvas();
enterCanvas(-2);
enterFooter(-1);
}
var TL = (function() {
var tl = new TimelineMax();
function returnInstance() {
return tl;
}
return {
inst: function() {
return returnInstance();
}
}
})();
function enterNavBar(delay)
{
delay = delay || 0;
var gTL = TL.inst();
//nav bar fade in
gTL.to($("#bar"),2,{css:{autoAlpha:1},ease:Quad.easeIn,onComplete:function(){
$("#bar").removeClass('invisible');
}},delay);
}
function enterCanvas(delay)
{
delay = delay || 0;
var gTL = TL.inst();
gTL.to($("#ani"),2,{css:{autoAlpha:1},ease:Quad.easeIn,onComplete:function(){
$("#ani").removeClass('invisible');
}},delay);
}
function enterFooter(delay)
{
delay = delay || 0;
var gTL = TL.inst();
//nav bar fade in
gTL.to($("footer"),2,{css:{autoAlpha:1},ease:Quad.easeIn,onComplete:function(){
$("footer").removeClass('invisible');
}},delay)
}
function drawCanvas()
{
//var canv = document.getElementById("ani");
var $canv = $('#ani');
var ctx = $canv[0].getContext("2d");
ctx.fillStyle="#000";
ctx.fillRect(0,0,840, 420,0);
}
It sounds like you might be using an outdated version of the GreenSock files. This sounds like an issue that was very rare and was fixed in a more recent version (my apologies for any hassles). Would you mind downloading the latest and trying again? http://www.greensock.com/v12/

Slide div inside another div effect

I am trying to create sliding images effect:
Online demolink text.
The problem is when you click rapidly and randomly on the buttons and not wait for animation to finish causing unpredicted results and even stopping the functionality to work. (and once it stopped in the middle of 2 images...)
How Can I make it work without bugs?
I know that there are some other tools for that sliding like jquery and other approaches like changing the position attribute and not the scrollLeft attribute.
But I want to do it as it is, with scrollLeft, if it possible of course.
The Code:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Untitled Document</title>
<style type="text/css">
body
{
padding:0px;
margin:0px;
}
#imageContainer
{
width: 500px;
position: relative;
}
#div
{
overflow: hidden;
white-space: nowrap;
}
#div img {
cursor: pointer;
vertical-align: bottom;
width: 500px;
padding:0px;
margin:0px;
display:inline;
}
</style>
<script type="text/javascript">
var scrollIntervalID;
var currentIndex=0;
function Scroll(ind){
var dir = ind ==currentIndex?0:ind<currentIndex?-1:1;
var steps = Math.abs(ind-currentIndex);
scrollIntervalID = setInterval(function(){
var i=(steps*10)-1;
return function(){
if (i <= 0)
clearInterval(scrollIntervalID);
var elm = document.getElementById("div");
elm.scrollLeft +=dir * 50;
i--;
document.getElementById("span").innerHTML=elm.scrollLeft;
}
}(), 15);
currentIndex=ind;
}
</script>
</head>
<body>
<div id="imageContainer">
<div id="div">
<img id="image1" src="Images/pic1.jpg" width="500px"/><img id="image2" src="Images/pic2.jpg" width="500px"/><img id="image3" src="Images/pic3.jpg" width="500px"/><img id="image4" src="Images/pic4.jpg" width="500px"/>
</div>
</div>
<div>
<input type="button" value="1" onclick="Scroll(0);"/>
<input type="button" value="2" onclick="Scroll(1);"/>
<input type="button" value="3" onclick="Scroll(2);"/>
<input type="button" value="4" onclick="Scroll(3);"/>
</div>
<span id="span"></span>
</body>
</html>
I would sriously recommend you to use frameworks like jQuery but if you insist to work on the current version, you have to take care of scenarios which happens during the animation.
You have scrollIntervalID, but it is not used outside the scope of the function. You can try clearing the interval timer by using clearInterval when a previous sliding animation is in progress and advance the position to the intended one before performing the next animation.
You need to stop the previous animation from operating before starting a new one. At the beginning, set:
var scrollIntervalID= null;
Then at the start of function Scroll add:
if (scrollIntervalID!==null) {
clearInterval(scrollIntervalID);
scrollIntervalID= null;
}
You'll also want to base the starting position of the animation on the current value of scrollLeft, rather than trying to remember the currentIndex.
this is a quick fix, I am not a javascript expert. but it works based on my quick testing
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Untitled Document</title>
<style type="text/css">
body
{
padding:0px;
margin:0px;
}
#imageContainer
{
width: 500px;
position: relative;
}
#div
{
overflow: hidden;
white-space: nowrap;
}
#div img {
cursor: pointer;
vertical-align: bottom;
width: 500px;
padding:0px;
margin:0px;
display:inline;
}
</style>
<script type="text/javascript">
var scrollIntervalID;
var currentIndex=0;
var start = true;
function Scroll(ind){
if(start){
var dir = ind ==currentIndex?0:ind<currentIndex?-1:1;
var steps = Math.abs(ind-currentIndex);
scrollIntervalID = setInterval(function(){
start = false;
var i=(steps*10)-1;
return function(){
if (i <= 0)
clearInterval(scrollIntervalID);
var elm = document.getElementById("div");
elm.scrollLeft +=dir * 50;
i--;
document.getElementById("span").innerHTML=elm.scrollLeft;
}
}(), 0);
currentIndex=ind;
start = true;
}
}
</script>
</head>
<body>
<div id="imageContainer">
<div id="div">
<img id="image1" src="Images/pic1.jpg" width="500px"/><img id="image2" src="Images/pic2.jpg" width="500px"/><img id="image3" src="Images/pic3.jpg" width="500px"/><img id="image4" src="Images/pic4.jpg" width="500px"/>
</div>
</div>
<div>
<input type="button" value="1" onclick="Scroll(0);"/>
<input type="button" value="2" onclick="Scroll(1);"/>
<input type="button" value="3" onclick="Scroll(2);"/>
<input type="button" value="4" onclick="Scroll(3);"/>
</div>
<span id="span"></span>
</body>

Categories