I'm making a vanilla JS flappy bird game, but I'm getting a TypeError: Can't read property 'x' of undefined. for a pipeTop variable.
While the background image loads, I'm guessing the pipe image doesn't load before pipeTop[i].x is called.
I tried pre-loading all of the images, as well as include a window.onload for my draw function, but it doesn't seem to serve the images (or their properties) before the logic is implemented.
// draw images
window.onload = function draw() {
ctx.drawImage(bg,0,0);
for (var i = 0; i < pipe.length; i++){
ctx.drawImage(pipeTop, pipe[i].x, pipe[i].y);
ctx.drawImage(pipeBottom, pipe[i].x, pipe[i].y+constant);
pipe[i].x--;
if (pipe[i].x == 125){
pipe.push({
x : cvs.width,
y : Math.floor(Math.random()*pipeTop.height)-pipeTop.height
});
}
}
// Detect Collision
if (bX + bird.width >= pipe[i].x && bX <= pipe[i].x + pipeTop.width && (bY <= pipe[i].y + pipeTop.height || bY+bird.height >= pipe[i].y+constant || bY + bird.height >= cvs.height - fg.height)){
location.reload();
}
if (pipe[i].x == 5) {
score+= 5;
score.play();
}
Pre-loading I tried (now commented out) was:
// function preloadImage(url) {
// var img = new Image();
// img.src = url;
// }
// preloadImage(
// "images/pipeBottom.png",
// "images/pipeTop.png",
// "images/fg.png",
// "images/bg.png",
// "images/bird.png"
// )
The line that has the typeError is:
if (bX + bird.width >= pipe[i].x && bX <= pipe[i].x + pipeTop.width && (bY <= pipe[i].y + pipeTop.height || bY+bird.height >= pipe[i].y+constant || bY + bird.height >= cvs.height - fg.height)){....
Essentially, I'm trying to load the images before any game logic runs so that I avoid these Undefined and Type errors. Any help is appreciated.
I am working on an application that has a custom carousel and there is a desirable to intuitively move the inner contents of an item so its always in view until the item is truly out of scope.
^ so as the .item is moved in the left position. What techniques would you use to detect the edge to dynamically position the .unit padding-left value? So the text inside that cell is always viewable, even if the item starts to move out of position.
//Latest Fiddle
https://jsfiddle.net/atg5m6ym/3124/
$(document).ready(function() {
//console.log("ready!");
function isElementInViewport (el) {
//special bonus for those using jQuery
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
);
}
var currentPadding = 0;
var newPadd = 0;
function compensatePadding() {
var itemLeft = Math.abs(parseInt($('.caroseul').offset().left));
console.log("itemLeft", itemLeft)
newPadd = Math.abs(itemLeft);
$('.stick .unit').css("padding-left", newPadd + "px");
}
var unitWidth = $('.unit').width();
console.log("unitWidth", unitWidth);
function onVisibilityChange(el, callback) {
var old_visible;
return function() {
var visible = isElementInViewport(el);
if (visible != old_visible) {
old_visible = visible;
if (typeof callback == 'function') {
callback();
}
}
}
}
function checkVisible() {
console.log("checkvisible");
var labelGroups = $('.caroseul .item .wraps');
var length = labelGroups.length;
for (i = 0; i < length; i++) {
var isItemLabelInView = isElementInViewport(labelGroups[i]);
if(!isItemLabelInView){
$(labelGroups[i]).closest(".item").addClass("stick");
}
else{
$(labelGroups[i]).closest(".item").removeClass("stick");
//reset moved items
$('.unit').css("padding-left", 0);
}
console.log(" labelGroups[i]", labelGroups[i]);
console.log("isItemLabelInView", isItemLabelInView);
}
compensatePadding();
}
$('.container').on('scroll', checkVisible);
});
I tweaked a bit of your code - instead of checking if label is in viewport or not I have checked if label is moving out of viewport from left.
if ($(labelGroups[i]).offset().left < 0) {
$(labelGroups[i]).closest(".item").addClass("stick");
} else {
$(labelGroups[i]).closest(".item").removeClass("stick");
Besides this I have added a few conditions and offset values in compensatePadding() function.
Please refer this fiddle.
Using jquery for this pains me a bit, as I think you'd be better off using requestAnimationFrame...but, to answer your specific question, you could use something like this (I've specifically left the two aggregate values as separate vars in order to explain the point):
$(document).ready(function() {
function animateMe(){
$(".item").animate({
left: "-=5"
}, 1000, function() {
amountMovedLeft += 5;
if(amountMovedLeft >= amountUntilUnitHitsLeft){
$(".unit").animate({
right: "+=5"
}
}
});
}
var amountMovedLeft = 0;
var unitWidthHalf = $('.unit').width()/2;
var itemWidthHalf = $('.item').width()/2;
var amountUntilUnitHitsLeft = itemWidthHalf - unitWidthHalf;
setInterval(function(){
animateMe();
}, 1000);
});
I am using owl carousel on one of the pages and I am using following script from theme unify http://htmlstream.com/preview/unify-v1.7/shortcode_carousels.html
I want to hide the navigation buttons when the carousel has fewer items to show even in responsive mode something similar to what has been done in this example http://codepen.io/OwlFonk/pen/qhgjb?editors=101, in this codepen example button hide based on items visible in different screen sizes.
I tried to implement the same to the carousel but it is not working for me
fiddle http://codepen.io/anon/pen/gpYKvq
//Owl Slider v1
var owl = jQuery(".owl-slider").owlCarousel({
itemsDesktop : [1000,5],
itemsDesktopSmall : [900,4],
itemsTablet: [600,3],
itemsMobile : [479,2],
});
jQuery(".next-v1").click(function(){
owl.trigger('owl.next');
})
jQuery(".prev-v1").click(function(){
owl.trigger('owl.prev');
})
I don't know if you still need it, but (just in case) if it's just the buttons that you'd like to hide, you can check the window width (like #Mohamed-Yousef's example) and then just do a .hide(). This is how it should roughly look like:
var viewport = jQuery(window).width();
var itemCount = jQuery("#owl-demo div").length;
if(
(viewport >= 900 && itemCount > 5) //desktop
|| ((viewport >= 600 && viewport < 900) && itemCount > 4) //desktopsmall
|| ((viewport >= 479 && viewport < 600) && itemCount > 3) //tablet
|| (viewport < 479 && itemCount > 2) //mobile
)
{
jQuery('.next-v1, .prev-v1').hide();
}
else
{
jQuery('.next-v1, .prev-v1').show();
}
Make sure that this runs on document load and whatever other events would trigger changes in the carousel.
I'd also just like to mention that I made assumptions about how your code looks like via the code snippet you gave in your question above, and not from the fiddle you gave as the two are different from each other. The fiddle is what I think #Mohamed-Yousef was basing his answer from, as it looks like the default implementation of owl carousel (I didn't check it thoroughly though), while the one in your question looks like a manually implemented custom button that is set to trigger the owl.next/owl.prev events.
I know it's an old question, but also looked for a solution and found one in pure CSS, so maybe it will be useful for someone in future. To hide one dot we can use :only-child pseudo-class. The problem is that it's not supported well (only chrome), so better one is to use an alias of it ":first-child:last-child":
.owl-dot:first-child:last-child {
display: none;
}
you can simply check the number of Divs by using
$(document).ready(function () {
var carousel = $("#owl-demo");
if($("#owl-demo div").length + 1 > 5){
carousel.owlCarousel({
navigation:true,
navigationText: [
"<i class='icon-chevron-left icon-white'><</i>",
"<i class='icon-chevron-right icon-white'>></i>"
],
});
}
});
this check if more than 5 divs run owlCarousel and for responsive mode you need to check for $(window).width(); for example
if($(window).width() > 800 && $(window).width() < 1400){ // for desktop
if($("#owl-demo div").length + 1 > 5){
// run carousel....
}
}else if($(window).width() > 600 && $(window).width() < 800){ // for Tab
if($("#owl-demo div").length + 1 > 4){ // change it as your screen size
// run carousel....
}
}
and so on
var owl = jQuery(".owl-slider").owlCarousel({
itemsDesktop: [1000, 5],
itemsDesktopSmall: [900, 4],
itemsTablet: [600, 3],
itemsMobile: [479, 2],
afterInit: function() {
var viewport = jQuery(window).width();
var itemCount = jQuery(".owl-slider div").length;
if ((viewport >= 900 && itemCount > 5) //desktop
|| ((viewport >= 600 && viewport < 900) && itemCount > 4) //desktopsmall
|| ((viewport >= 479 && viewport < 600) && itemCount > 3) //tablet
|| (viewport < 479 && itemCount > 2) //mobile
) {
jQuery('.next-v1, .prev-v1').show();
} else {
jQuery('.next-v1, .prev-v1').hide();
}
},
afterUpdate: function() {
var viewport = jQuery(window).width();
var itemCount = jQuery("#owl-demo div").length;
if (
(viewport >= 900 && itemCount > 5) //desktop
|| ((viewport >= 600 && viewport < 900) && itemCount > 4) //desktopsmall
|| ((viewport >= 479 && viewport < 600) && itemCount > 3) //tablet
|| (viewport < 479 && itemCount > 2) //mobile
) {
jQuery('.next-v1, .prev-v1').show();
} else {
jQuery('.next-v1, .prev-v1').hide();
}
}
});
If you use Bootstrap 3, you can try my solution which is based on reponsive classes.
It doesnt need additional listener on resize or other events and is executed on initialize. Moreover its quite simple.
var $el = $('.my-carousel');
var breakpoints = {
0: {
items: 3
},
480: {
items: 4
},
769: {
items: 5
},
992: {
items: 4
},
1200: {
items: 5
}
};
var carousel = $el.owlCarousel({
loop: true,
margin: 10,
nav: false,
dots: false,
responsive: breakpoints
});
// get real items count
var items = $el.find('.owl-item:not(.cloned)').length;
// $nav = your navigation element, mine is custom
var $nav = $el.parent().find('.center-navigation');
// add responsive classes to hide navigation if needed
if(breakpoints[1200].items>=items) $nav.addClass('hidden-lg');
if(breakpoints[992].items>=items) $nav.addClass('hidden-md');
if(breakpoints[769].items>=items) $nav.addClass('hidden-sm');
if(breakpoints[480].items>=items) $nav.addClass('hidden-xs');
if(breakpoints[0].items>=items) $nav.addClass('hidden-xxs');
I tried this and it worked for me
function HideNavigationInCarousel(ContainerdivId,viewport)
{
var itemCount = jQuery("#" + ContainerdivId +" .owl-item").length;
// console.log(ContainerdivId + " " + viewport+ " "+itemCount);
if (viewport / itemCount > (jQuery("#" + ContainerdivId + " .owl-item").width()))
{
jQuery("#" + ContainerdivId + " .owl-prev,"+"#" + ContainerdivId +" .owl-next").hide();
}
else {
jQuery("#" + ContainerdivId + ".owl-prev,"+"#" + ContainerdivId +" .owl-next").show();
}
}
Instead of using responsive options, I suggest adding or removing a disabled class on prev/next button, when it's not active.
jQuery(".owl-slider")
.on('initialized.owl.carousel changed.owl.carousel refreshed.owl.carousel', function (event) {
if (!event.namespace) return;
var carousel = event.relatedTarget,
element = event.target,
current = carousel.current();
setTimeout(function() {
$('.owl-next', element).toggleClass('disabled', current === carousel.maximum());
$('.owl-prev', element).toggleClass('disabled', current === carousel.minimum());
}, 1);
})
.owlCarousel({
itemsDesktop : [1000,5],
itemsDesktopSmall : [900,4],
itemsTablet: [600,3],
itemsMobile : [479,2],
});
In CSS, you can either hide disabled element or change its style.
Here's my SASS code for disabled class CSS :
.owl-next,
.owl-prev {
opacity: 1;
transition: opacity 0.3s ease;
&.disabled {
opacity: 0;
}
}
This is an old question, but the simplest way I found to do it, is to use owlCarousel own vars:
function toggleArrows(){
var c = $('.carousel').data('owlCarousel');
if(c.options.items==c.itemsAmount){
$('.next, .prev').hide();
}else{
$('.next, .prev').show();
}
}
Owl carousel will update his internal var options.items based on the number of visible items.
You can run this on the window resize event, just be careful with the responsiveRefreshRate, which update the vars each 200ms (by default), so I run this code inside a timeout after window resize.
var tmtResize = false;
$(window).resize(function(){
if(tmtResize) clearTimeout(tmtResize);
tmtResize = setTimeout(function(){
toggleArrows();
}, 250);
});
Can anyone please help with a dodgy if statement, try as I might I can't see anything wrong with it, the code works when outside of the if statement:
var sizeBefore;
var sizeAfterResize;
var sizeBreakPoint;
var resizeTimer;
$(function() {
sizeBefore = $(window).width();
sizeBreakPoint = 500;
doneResizing();
});
function doneResizing(){
sizeAfterResize = $(window).width();
if ((sizeBefore < sizeBreakPoint) && (sizeAfterResize >= sizeBreakPoint)) {
alert('Before:' + sizeBefore);
alert('After:' + sizeAfterResize);
sizeBefore = sizeAfterResize;
// THIS RUNS WHEN OUTSIDE IF STATEMENT
}
}
$(window).resize(function() {
//doneResizing();
clearTimeout(resizeTimer);
resizeTimer = setTimeout(doneResizing, 100);
});
EDIT: This statement should only be true on both document ready or completion of resize when the window has been resized from smaller than sizeBreakPoint to larger than sizeBreakPoint - hope this clarifies
EDIT: SOLUTION
var sizeBefore;
var sizeAfterResize;
var sizeBreakPoint;
var resizeTimer;
$(function() {
sizeBefore = $(window).width();
sizeBreakPoint = 500;
doneResizing();
});
function doneResizing(){
sizeAfterResize = $(window).width();
if ((sizeBefore < sizeBreakPoint) && (sizeAfterResize >= sizeBreakPoint)) {
alert('Before:' + sizeBefore);
alert('After:' + sizeAfterResize);
}
sizeBefore = sizeAfterResize;
}
$(window).resize(function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(doneResizing, 100);
});
ok from looking and testing your if i can say:
if ((sizeBefore < sizeBreakPoint) && (sizeAfterResize >= sizeBreakPoint))
this is only true if your window starts with smaller then 500 and after you resize if it goes over 500. This because you never change you sizeBefore other then on page load.
Can you tell me what you really want to verify? Or if this what you really want.
** edit: suggested solution **
try to do something like this:
$(function() {
sizeBreakPointMin = 480;
sizeBreakPointMax = 520;
doneResizing();
});
function doneResizing(){
sizeAfterResize = $(window).width();
//this way you have a window where this is false and it's as you want to allow the window as in a fine size
//you can garantie that the window is always bigger then 480 and smaller then 520
if ((sizeAfterResize < sizeBreakPointMin) || (sizeAfterResize >= sizeBreakPointMax)) {
alert('Before:' + sizeBefore);
alert('After:' + sizeAfterResize);
// THIS RUNS WHEN OUTSIDE IF STATEMENT
}
}
from your code:
if ((sizeBefore < sizeBreakPoint) && (sizeAfterResize >= sizeBreakPoint)) {
...
sizeBefore = sizeAfterResize;
}
this two lines don't go well together because the first time this is true you just garantied that sizeAfterResize >= sizeBreakPoint making the next time you go check the if sizeBefore is will always be bigger then sizeBreakPoint making the if statement impossible to enter 2 times as it is (and if you don't change sizeBefore outside the if.
Hope this helps.
I think your problem lies within the if condition.
sizeBefore is whatever your screen width is at the document ready event, which if you have a fullscreen browser, will be bigger than 500 (which is your breakpoint value). But you're never updating the sizeBefore, so it will never be lower than the sizeBreakPoint, and so, this part of the if statement will never be true: (sizeBefore < sizeBreakPoint)
This is no direct answer to the question, just my own twist on a responsive JavaScript
// calculate viewport width so that we can load js conditionally
function responsive(){
var scaffolding = 'desktop';
var w = parseInt($(window).innerWidth(), 10);
if (w > 0 && w < 768) { scaffolding = 'phone'; }
if (w >= 768 && w <= 980) { scaffolding = 'tablet'; }
if (w > 980) { scaffolding = 'desktop'; }
return scaffolding;
}
if ( responsive() == phone ) {
// do stuff only on phones
}
if ( responsive() != phone ) {
// do stuff everywhere else but phones
}
You get to define what each breakpoint represents and what it is called, in a way that it still makes sense when you start using the condition later in the code.
I want the page to reload only if the browser window goes above or below 768px.
This was my attempt which failed.
if ($(window.width() > "769") {
$(window).resize(function () {
if ($(window).width() < "769") {
location.reload();
}
});
}
elseif($(window.width() < "769") {
$(window).resize(function () {
if ($(window).width() > "769") {
location.reload();
}
});
}
Im sures theres a really simple way of doing this.
demo jsFiddle
The proof that the page is reloaded is (the wait icon in the tab :D ) the Math random that generates a random number (in the demo.)
var ww = $(window).width();
var limit = 769;
function refresh() {
ww = $(window).width();
var w = ww<limit ? (location.reload(true)) : ( ww>limit ? (location.reload(true)) : ww=limit );
}
var tOut;
$(window).resize(function() {
var resW = $(window).width();
clearTimeout(tOut);
if ( (ww>limit && resW<limit) || (ww<limit && resW>limit) ) {
tOut = setTimeout(refresh, 100);
}
});
The timeout function will help on window resize to wait 100ms before calling the refresh function.
You can increase the timeout value to improve usability.
There are probably other and much better ways of doing what you really need, but:
if ($(window.width() > "769"){
Should be:
if ($(window).width() > 769){
Full code:
var width = $(window).width();
$(window).resize(function() {
if (width > 769 && $(window).width() < 769) {
location.reload();
}
else if (width < 769 && $(window).width() > 769) {
location.reload();
}
});
Live DEMO
It could be made with one if statement, but I preferred splitting it into two so it'll be easier to follow.