Slideshow using Prototype and Scriptaculous - prototypejs

I wrote my first scriptaculous script to create a slideshow between some div element :
var SlideShow = Class.create({
initialize:function(element, delayStart){
this.element = element;
this.delayStart = delayStart;
this.slides = this.element.childElements();
this.numberOfSlides = this.slides.size();
this.numberActiveSlide = 1;
this.start_slideshow();
},
start_slideshow: function()
{
this.switch_slides.delay(this.delayStart);
},
switch_slides: function()
{
this.slides[this.numberActiveSlide].fade();
if (this.numberActiveSlide == this.numberOfSlides) { this.numberActiveSlide = 1; } else { this.numberActiveSlide = this.numberActiveSlide + 1; }
Effect.Appear.delay(this.slides[this.numberActiveSlide], 850);
this.switch_slides.delay(this.delay + 850);
}
});
document.observe("dom:loaded", function(){
var slideshows = $$('div.slideshow');
slideshows.each(
function(slideshow) {
s = new SlideShow(slideshow, 2);
});
});
But I always get this error and It's been hours I can't figure it out where my problem is!
Undefined is not an object (evaluating this.slides[this.numberActiveSlide]);
Thanks you !
Nick

99% sure it's a context issue. Make sure you bind your function calls so that this is retained throughout your code.
Debug what this is in switch_slides: it should be the same thing as this in start_slideshow. If it's not, bind your call to switch_slides to your instance:
start_slideshow: function()
{
this.switch_slides.bind(this).delay(this.delayStart);
},
You'll probably have to do the same in switch_slides where it calls itself.

Related

JSON and HTML troubles

i'm currently having some troubles with displaying the information from a JSON file to html. I'm currently using AJAX to get the data from the JSON file.
The main problem that i'm facing is with displaying all the data into one div.
function Test(){
request.open('GET','/json/anime.json');
request.onreadystatechange = function() {
if((request.readyState===4) && (request.status===200)) {
var json = JSON.parse(request.responseText);
for(var title in json.Title ) {
for(var ep in json.Episode) {
for(var img in json.Image) {
for(var link in json.Link) {
_title = json.Image[title];
episode = json.Image[ep];
image = json.Image[img];
_link = json.Image[link];
var div = document.createElement('div');
div.className = 'card card-inverse';
div.innerHTML = `<img class="card-img img-fluid img-responsive" src="${image}" data-toggle="modal">`;
document.getElementById('anime').appendChild(div);
}
}
}
}
}
}
request.send();
}
The JSON file looks like this...
{
Episode: [
...
],
Image: [
...
],
Link: [
...
],
Title: [
...
]
}
The way above is working if i'm only looping over one of the four arrays, however crashes chrome when trying to do the above task.
Any help would be appreciated.
Thanks
I decided to take a different approach moving away from ajax a little and moving more towards jquery. Below is what has so far worked out for me. Thanks to the people who commented above, really helped me think of ways to tackling it.
function DisplayCards() {
var i = 0;
$.getJSON('/json/anime.json', function(data) {
$.each(data, function(index) {
for(key in data[index]){
e = data.Image.length;
console.log(e);
if(i < e)
{
image = data.Image[key];
link = data.Link[key];
console.log(i += 1);
var div = document.createElement('div');
div.className = 'card card-inverse';
div.innerHTML = `<img class="card-img img-fluid img-responsive" src="${image}" data-toggle="modal">`;
var p = document.createElement('p');
p.innerHTML = 'id="wrapper" class="text"';
document.getElementById('anime').appendChild(div);
}
}
console.log(data);
});
});
}

How can I check until an element is clickable using nightwatchjs?

How can I check until an element is clickable using nightwatch js? I want to click on an element but when I run nightwatch, selenium does not click on the element because it is not clickable yet.
Something like this should work. Let me know if you have questions
var util = require('util');
var events = require('events');
/*
* This custom command allows us to locate an HTML element on the page and then wait until the element is both visible
* and does not have a "disabled" state. It rechecks the element state every 500ms until either it evaluates to true or
* it reaches maxTimeInMilliseconds (which fails the test). Nightwatch uses the Node.js EventEmitter pattern to handle
* asynchronous code so this command is also an EventEmitter.
*/
function WaitUntilElementIsClickable() {
events.EventEmitter.call(this);
this.startTimeInMilliseconds = null;
}
util.inherits(WaitUntilElementIsClickable, events.EventEmitter);
WaitUntilElementIsClickable.prototype.command = function (element, timeoutInMilliseconds) {
this.startTimeInMilliseconds = new Date().getTime();
var self = this;
var message;
if (typeof timeoutInMilliseconds !== 'number') {
timeoutInMilliseconds = this.api.globals.waitForConditionTimeout;
}
this.check(element, function (result, loadedTimeInMilliseconds) {
if (result) {
message = '#' + element + ' was clickable after ' + (loadedTimeInMilliseconds - self.startTimeInMilliseconds) + ' ms.';
} else {
message = '#' + element + ' was still not clickable after ' + timeoutInMilliseconds + ' ms.';
}
self.client.assertion(result, 'not visible or disabled', 'visible and not disabled', message, true);
self.emit('complete');
}, timeoutInMilliseconds);
return this;
};
WaitUntilElementIsClickable.prototype.check = function (element, callback, maxTimeInMilliseconds) {
var self = this;
var promises =[];
promises.push(new Promise(function(resolve) {
self.api.isVisible(element, function(result) {
resolve(result.status === 0 && result.value === true);
});
}));
promises.push(new Promise(function(resolve) {
self.api.getAttribute(element, 'disabled', function (result) {
resolve(result.status === 0 && result.value === null);
});
}));
Promise.all(promises)
.then(function(results) {
var now = new Date().getTime();
const visibleAndNotDisabled = !!results[0] && !!results[1];
if (visibleAndNotDisabled) {
callback(true, now);
} else if (now - self.startTimeInMilliseconds < maxTimeInMilliseconds) {
setTimeout(function () {
self.check(element, callback, maxTimeInMilliseconds);
}, 500);
} else {
callback(false);
}
})
.catch(function(error) {
setTimeout(function () {
self.check(element, callback, maxTimeInMilliseconds);
}, 500);
});
};
module.exports = WaitUntilElementIsClickable;
Add this code as a file to your commands folder. It should be called waitUntilElementIsClickable.js or whatever you want your command to be.
Usage is:
browser.waitUntilElementIsClickable('.some.css');
You can also use page elements:
var page = browser.page.somePage();
page.waitUntilElementIsClickable('#someElement');
You can use waitForElementVisible() combined with the :enabled CSS pseudo-class.
For example, the following will wait up to 10 seconds for #element to become enabled, then click it (note that the test will fail if the element doesn't become enabled after 10 seconds):
browser
.waitForElementVisible('#element:enabled', 10000)
.click('#element');
Can you show an example element,usually there should be an attribute name "disabled" if the button is not clickable, this should work.
browser.assert.attributeEquals(yourCSS, 'disabled', true)
I'm unable to comment but there are a couple of issues with the code suggested by Alex R.
First, the code will not work with Firefox as geckodriver does not return a 'status'. So this:
resolve(result.status === 0 && result.value === true)
needs to be changed to this:
resolve(result.value === true).
Second, the line:
self.client.assertion(result, 'not visible or disabled', 'visible and not disabled', message, true);
doesn't work and needs to be commented out in
order to get the code to run.

lazy load doesnt work with hidden elements

this is my simple test code for lazy load
http://codepen.io/kevkev/pen/bVVGdE
it works so far .. but the thing is that hidden images in an onclick function for buttons etc. doesnt work!
(watch through my code and scroll to end and push the button)
you can see in the network feedback that it already had load the images.
i could figure out that the problem is "display:none"
.pop {
display:none;
z-index:99;
position:absolute;
width:100%;
height:auto;
background:inherit;
}
Because display: none; elements are unknown in position. And the lazyloader doesn't know, when and if you change this. Therefore it decides to eager load it. If you want a lazyloader that automatically detects this use https://github.com/aFarkas/lazysizes/.
As alternative I would recommend justlazy, because it's more lightweight and don't uses jQuery.
1. Define placeholder (similar to that what you have done):
<span data-src="path/to/image" data-alt="alt" data-title="title"
class="placeholder">
</span>
2. Initialize lazy loading after your button click:
$(document).ready(function () {
$("#art").click(function () {
$("#art_pop").fadeIn(300);
Justlazy.registerLazyLoadByClass("placeholder", {
// image will be loaded if it is 300 pixels
// below the lower display border
threshold: 300
});
});
// other code ..
});
thanks guys! but I also got a working solution on this:
http://codepen.io/kevkev/full/meebpQ/
$(document).ready(function () {
$("#art").click(function () {
$("#art_pop").fadeIn(300);
});
$(".pop > span, .pop").click(function () {
$(".pop").fadeOut(600);
});
});
;(function($) {
$.fn.unveil = function(threshold, callback) {
var $w = $(window),
th = threshold || 0,
retina = window.devicePixelRatio > 1,
attrib = retina? "data-src-retina" : "data-src",
images = this,
loaded;
this.one("unveil", function() {
var source = this.getAttribute(attrib);
source = source || this.getAttribute("data-src");
if (source) {
this.setAttribute("src", source);
if (typeof callback === "function") callback.call(this);
}
});
function unveil() {
var inview = images.filter(function() {
var $e = $(this);
if ($e.is(":hidden")) return;
var wt = $w.scrollTop(),
wb = wt + $w.height(),
et = $e.offset().top,
eb = et + $e.height();
return eb >= wt - th && et <= wb + th;
});
loaded = inview.trigger("unveil");
images = images.not(loaded);
}
$w.on("scroll.unveil resize.unveil lookup.unveil", unveil);
unveil();
return this;
};
})(window.jQuery || window.Zepto);
/* OWN JAVASCRIPT */
$(document).ready(function() {
$("img").unveil(200, function() {
$(this).load(function() {
this.style.opacity = 1;
});
});
});

hidding elements in a layout page mvc3

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);
//===================================================================================================

prototype ajax, undefined json after second setTimeout

Having problem with prototype ajax and setTimeout. Here is my code shortened:
//new ajax request
....onComplete: function (transport) { //json as this -> array[$i].something
var json = transport.responseJSON;
var $i = 0;
window.setTimeout(function () {
SLOW();
},
500); //display every json[$i] with custom delay
function SLOW() {
$i++;
if (json[$i].something !== null) { //insert in proper div id in the html document
window.setTimeout(function () {
$('document_div' + json[$i].something).innerHTML = json[$i].something_to_display;
},
500);
window.setTimeout(function () {
$('document_div' + json[$i].something).innerHTML = json[$i].something_to_display;
},
1000);...window.setTimeout(function () {
SLOW();
},
500);
} else {
//stop and continue
}
Getting this error: json[$i] is undefined.
EDIT: looks like i'm getting this error on second timeout, the first one changes the div correctly.
Done.
Solution was to re-var json again before using it in setTimeout.
var json_something = json[$i].something; //and so on...
var json_something_to_display = json[$i].something_to_display
window.setTimeout(function() { $('document_div'+json_something).innerHTML = json_something_to_display; }, 500);
Can somebody explain why this is needed? Why varing json is not enough and it disapears somewhere after one window.setTimeout function?

Resources