I have a piece of code for showing a picture that slides up from a div when the mouse enters the div, the code works exactly how i want except it bugs when the mouse hovers in and out too quickly and the animation doesn't have time to complete, I've already changed from mouseover and mouseout, to mouseenter and mouseleave and this hasn't seemed to help, any suggestions would be great
<script type="text/javascript">
document.observe("dom:loaded", function() {
var effectInExecution=null;
$('mid_about_us').observe('mouseenter', function() {
if(effectInExecution) effectInExecution.cancel();
effectInExecution=new Effect.SlideDown('about_us_mo',{style:'height:140px;', duration: 1.0 });
});
$('mid_about_us').observe('mouseleave', function() {
if(effectInExecution) effectInExecution.cancel();
effectInExecution=new Effect.SlideUp('about_us_mo',{style:'height:0px;', duration: 1.0 });
});
});
I wrote a Prototype class a while back to solve this problem, the issue can be fixed by supplying a scope parameter to the effect options. anyway here is the class i wrote:
var DivSlider = Class.create();
Object.extend(DivSlider, {
toggle: function(selector, element, options) {
element = $(element);
this.options = Object.extend({
duration: 0.5,
fps: 35,
scope: 'DivSlider',
forceOpen: false
}, options || {});
var toggle = element.visible();
if (toggle && this.options.forceOpen) {
//already open, leave.. still call callback
(this.options.after || Prototype.emptyFunction)
.bind(this, element)();
return;
}
var effects = new Array();
if (toggle) {
effects.push(new Effect.SlideUp(element, {
sync: true
}));
} else {
$$(selector).each(function(el) {
if ((element !== el) && el.visible()) {
effects.push(new Effect.SlideUp(el, {
sync: true
}));
}
});
effects.push(new Effect.SlideDown(element, {
sync: true
}));
}
new Effect.Parallel(effects, {
duration: this.options.duration,
fps: this.options.fps,
queue: {
position: 'end',
scope: this.options.scope
},
beforeStart: function() {
(this.options.before || Prototype.emptyFunction)
.bind(this, element)();
}.bind(this),
afterFinish: function() {
(this.options.after || Prototype.emptyFunction)
.bind(this, element)();
}.bind(this)
});
}
});
and to use it in your case you would simply use:
DivSlider.toggle('div.your_class', your_id);
in your enter/leave code, it can handle multiple div's of the same class also, allowing only one div per class to be open at any single time. If this does not fit your needs you can easily deconstruct the class to get the code you actually need.
Related
I am trying to automate a process in CasperJS. However, I am facing some discrepancy between the behavior on a real browser vs the same in CasperJS.
Update: Process works fine with slimerJS but gives issue with headless
Here is my script:
var casper = require('casper').create({
"waitTimeout": 10000
});
var inputElements = {
"url": "http://www.jabong.com/incult-Tapered-Jeans-In-Indigo-1032119.html?pos=4",
"size": "34",
"address": {
"email": "someemail#xyz.com"
}
}
casper.options.viewportSize = {width: 1679, height: 902};
casper.start(inputElements.url, function (){
this.wait(10000, function (){
console.log("loaded");
})
});
var x = require('casper').selectXPath;
var sizeToSelect = inputElements.size;
// select size
casper.thenClick(x("//*[contains(#class,'size-desktop')]//"+
"li[contains(#class,'first') and contains(#class,'popover-options')]//"+
"span[contains(text(),'"+sizeToSelect+"')]/"+
".."));
// add to bag
casper.thenClick(x("//*[#id='add-to-cart']"));
// view cart
casper.thenClick(x("//*[#id='header-bag-sec']/a"))
// take a screenshot
casper.then(function() {
console.log("saving screenshot");
this.capture('../../1_view_cart.png');
});
casper.then(function() {
console.log('clicked ok, new location is ' + this.getCurrentUrl());
});
// place order
casper.then(function (){
this.click("[href='https://www.jabong.com/checkout/']");
})
// take a screenshot
casper.then(function() {
console.log("saving screenshot");
this.capture('../../2_address_details.png');
});
casper.then(function (){
this.sendKeys("#login-email", inputElements.address.email);
})
casper.then(function (){
this.click("#do-guest-checkout");
});
// take a screenshot
casper.then(function() {
console.log("saving screenshot");
this.capture('../../3_guest_checkout.png');
});
casper.waitFor(function check() {
return this.evaluate(function() {
return document.querySelector('#btn-login-checkout').textContent == "Continue as Guest";
});
}, function then() {
this.click('#btn-login-checkout');
});
casper.run();
On the last page, clicking on checkbox "Checkout as Guest" on a browser removes the password input field and changes the text of the Login button to "Continue as Guest". Attached screenshot:
However, in CasperJS, the password input field and the Login button are not changing. Any idea what am I doing wrong ?
I have made this little test:
casper.test.begin('Test', function() {
casper.start();
casper.then(function() {
casper = this;
setTimeout(function(casper) {
casper.echo('wait 5s');
}, 5000);
});
casper.then(function() {
this.echo('should appear after 5s');
});
casper.run(function() {
this.test.done();
});
});
When I execute this test, my console shows only this line "should appear after 5s" but not the first sentence, in fact the second 'then' does not wait for 5 seconds.
It's a huge problem because it's the possible cause of many random failure in my casperjs test suite.
Maybe I have to use async (with series) to execute each step after the other.
Do you have this problem ? What's the best practice to execute some javascript functions one after the other in casperjs tests ?
Try to use wait() here:
casper.then(function() {
casper = this;
casper.echo('wait 5s');
});
casper.then(function() {
casper.wait(5000, function() {
this.echo('should appear after 5s');
});
});
"What's the best practice to execute some javascript functions one after the other in casperjs tests ?"
Here how i do :
login.js
casper.login = function (id,password) {
casper.then(function(){ //or this.then(...)
this.test.comment('----------------Connexion Only ! : --------------------');
if (!this.visible('#div_boxhover')) {
this.echo('Connexion box not visible before mouse on it!');
}
this.mouse.move(x('//*[#id="identification"]'));
if (this.visible('#div_boxhover')) {
this.echo('Connexion box visible after mouse on it!');
} else { this.echo("FAIL : Connexion box doesn't appear");}
//this.echo("I can see the logo");
this.fill(x('//*[#id="div_boxhover"][1]'), {
login: id,
pass: password
}, false);
this.click(x('//*[#name="log_in"]'));
this.waitForSelector(('.boxValid'), function() {
this.test.assertSelectorHasText('.boxValid', 'Vous êtes identifié en tant que Membre !');
this.test.assertTextExists('Succès', 'Page contains "succès" : so identification done');
});
});
};
scenario1.js
var x = require('casper').selectXPath;
phantom.injectJs( 'C:/bin/Aptana_casperjs/ccm/_functions/login.js');
casper.test.begin('\n********* Stack title : ***********\n', 3 , function suite(test) {
casper.start(yourUrl,function(){
//check one main element in the page
this.test.assertExists('.search','Search toolbar present');
})
//set a viewport (for slimerJS)
.viewport(1200,800)
//call an external function
.then(function() {
casper.login("pseudo","password");//this.login("pseudo","password");
})
//then click on a link + fill the form which appears
.thenClick('div.colMiddle > a.button', function(){
this.fillSelectors('form#frmqa', {
'select[name="cat"]' : "2",
'input[name="titre"]' : title,
'textarea[name="message"]' : message
}, false);
this.click('input#submitqa');
})
//wait for the redirection after a click at the end of a step
.waitForText(topic, function() {
this.test.assertSelectorHasText('.boxTitle', 'Mes discussions suivies', "New topic in 'Mes dicussions suivies'");
this.test.assertExists('a[actid="shqafrm"].button','Button answer topic present');
})
//click on a new link
.thenClick('a[actid="shqafrm"].button', function(){
//wait for the textarea to appear
this.waitForSelector('textarea[name="message"]',function(){
//send message and submit
this.sendKeys('textarea[name="message"]', newPost);
this.click('input#submitqa');
});
})
//check redirection or validation after a click on button/form/link
.waitForSelector('.article',function(){
test.assertTextExists(newPost, 'Answer in topic ' + title + ' done');
})
.run(function() {
this.test.comment('----------------------- Stack title over ------------------------\n');
test.done();
});
});
So i just call my functions in a new step.
I got the following:
http://jsfiddle.net/GsL8Z/
I want to toggle the size of an image. After each toggle, I want to replace the scaled image with its instance in right size.
This actually works pretty well, but only the first time. After the third click, the wrong class gets allocated.
Any help would be greatly appreciated!
HTML
<div id="projekt_1" class="projekt">
<ul class="bilder">
<li><img class="imgKlein" src="images/mainworks_th.jpg" alt="Mainworks"/></li>
</ul>
</div>
CSS
.imgGross{
height: 450px;
}
.imgKlein{
height: 215px;
}
JS
var status = true,
obj = $('.projekt'),
projekte = $.makeArray(obj),
obj = $('.bilder'),
projekte_li = $.makeArray(obj),
obj = $('.projekt li img'),
projekte_li_img = $.makeArray(obj);
var images = new Array (2);
images[0] = $('<img class="imgKlein"/>').attr({src: 'images/mainworks_th.jpg'});
images[1] = $('<img class="imgGross"/>').attr({src:'images/mainworks_pre.jpg'});
$('#projekt_1').click(function() {
if (status == true) {
$("img", this).switchClass( "imgKlein", "imgGross", 1000, "easeInOutQuad" );
setTimeout(function(){
$(projekte_li[0]).html(images[1]);
}, 2000);
status = false;
}
else {
$("img", this).switchClass( "imgGross", "imgKlein", 1000, "easeInOutQuad" );
setTimeout(function(){
$(projekte_li[0]).html(images[0]);
}, 2000);
status = true;
}
return false;
});
Somehow the switchClass is having problems with you replacing the whole html for the img. As a matter of fact you can just change the src.
Also, you are better off using .toggle() in jQuery to handle things changing back and forward on each click.
By the way, also the setTimeout can give problems. .switchClass() has a complete handler that runs after the animation is complete and you should use that.
So, the solution could be:
$('#projekt_1').toggle(
function(e) {
$("img", this).switchClass("imgKlein", "imgGross", 1000, "easeInOutQuad",
function() {
$(this).attr({ src: 'images/mainworks_pre.jpg', alt: "Mainworks_pre" });
});
return false;
},
function (e) {
$("img", this).switchClass("imgGross", "imgKlein", 1000, "easeInOutQuad",
function(){
$(this).attr({ src: 'images/mainworks_th.jpg', alt: "Mainworks_TH" });
});
return false;
}
);
Fiddle: http://jsfiddle.net/GsL8Z/2/
i testet something with the example from jquery-ui and it works
the code is little bit shorter than yours:
$(function() {
$( "#projekt_1" ).click(function(){
$(".imgKlein").switchClass( "imgKlein", "imgGross", 1000, "easeInOutQuad", function()
{
$("img").attr("src", "http://www.spielwiki.de/images/e/e9/Kleines_M%C3%A4dchen%2C_zu_gro%C3%9Fer_Luftballon.png");
});
$(".imgGross").switchClass( "imgGross", "imgKlein", 1000, "easeInOutQuad", function()
{
$("img").attr("src", "http://images.all-free-download.com/images/graphiclarge/small_house_329.jpg");
});
return false;
});
});
the link to the example: http://jsfiddle.net/DWrC6/24/
ok so im having a hard time hiding some layout sections (divs in my layout page and im using mvc3).
I have this js fragment which is basically the main logic:
$('.contentExpand').bind('click', function () {
$.cookie('right_container_visible', "false");
});
//Cookies Functions========================================================
//Cookie for showing the right container
if ($.cookie('right_container_visible') === 'false') {
if ($('#RightContainer:visible')) {
$('#RightContainer').hide();
}
$.cookie('right_container_visible', null);
} else {
if ($('#RightContainer:hidden')) {
$('#RightContainer').show();
}
}
as you can see, im hidding the container whenever i click into some links that have a specific css. This seems to work fine for simple tests. But when i start testing it like
.contentExpand click --> detail button click --> .contentExpand click --> [here unexpected issue: the line $.cookie('right_container_visible', null); is read but it doesnt set the vaule to null as if its ignoring it]
Im trying to understand whats the right logic to implement this. Anyone knows how i can solve this?
The simpliest solution is to create variable outside delegate of bind.
For example:
var rightContVisibility = $.cookie('right_container_visible');
$('.contentExpand').bind('click', function () {
$.cookie('right_container_visible', "false");
rightContVisibility = "false";
});
if (rightContVisibility === 'false') {
...
}
The best thing that worked for me was to create an event that can catch the resize of an element. I got this from another post but I dont remember which one. Anyway here is the code for the event:
//Event to catch rezising============================================================================
(function () {
var interval;
jQuery.event.special.contentchange = {
setup: function () {
var self = this,
$this = $(this),
$originalContent = $this.text();
interval = setInterval(function () {
if ($originalContent != $this.text()) {
$originalContent = $this.text();
jQuery.event.handle.call(self, { type: 'contentchange' });
}
}, 100);
},
teardown: function () {
clearInterval(interval);
}
};
})();
//=========================================================================================
//Function to resize the right container============================================================
(function ($) {
$.fn.fixRightContainer = function () {
this.each(function () {
var width = $(this).width();
var parentWidth = $(this).offsetParent().width();
var percent = Math.round(100 * width / parentWidth);
if (percent > 62) {
$('#RightContainer').remove();
}
});
};
})(jQuery);
//===================================================================================================
http://jsfiddle.net/hL6rT/1/
I've created div with a absolute positioned image inside it the idea is to fade the image in and out like a pulse. All went well until IE8 showed up.
See the link for code. Works fine in FF, that is to say the div fades in and out in a continuous loop. But in IE8 it fades in and out once and then stops.
Works fine in FF & IE8 with mootools 1.2.5, but not 1.3 or 1.3 Compatibility Mode.
For some bizarre reason if the alert after 'fadeIn' is included in the onComplete the function will display the alert and the second alert in the 'fadeOut' onComplete, but still NOT fade the div.
Help?
it is probably easier to do just the tween on the element via the oncomplete to make a blink effect:
http://jsfiddle.net/hL6rT/2/
var fadeImg = document.id('lucy');
fadeImg.set("tween", {
duration: 2000,
transition: Fx.Transitions.Quint.easeIn,
onComplete: function() {
this.element.fade(this.element.getStyle("opacity") == 0 ? 1 : 0);
}
}).fade(0);
// how you can cancel it
document.id("stop").addEvent("click", function(e) {
e.stop();
fadeImg.get("tween").cancel(); // this cancels it.
});
to fix your version:
http://jsfiddle.net/hL6rT/4/
works fine if you set the initial value of opacity to 0
var fadeImg = document.id('lucy').setStyle("opacity", 0);
var fadeIn = function() {
var inDiv = new Fx.Morph(fadeImg, {
link: 'cancel',
duration: 2000,
transition: Fx.Transitions.Quint.easeIn,
onComplete: function() {
fadeOut();
//alert('FadeIn Complete');
}
}).start({
'opacity': ['0', '1']
});
};
var fadeOut = function() {
var outDiv = new Fx.Morph(fadeImg, {
link: 'cancel',
duration: 2000,
transition: Fx.Transitions.Quint.easeOut,
onComplete: function() {
fadeIn();
//alert(FadeOut Complete!');
}
}).start({
'opacity': ['1', '0']
});
};
fadeIn();
update IE does not seem to consistently like this particular transition being chained. you may need to remove it and use the default one.