multiple color fade on scroll - javascript

I found this great piece of code on jsfiddle for fading between two colors onScroll using jQuery and the Color plugin.
What I would like to do is be able to fade three or more colors onScroll down the page.
I have tried (failing miserably) to edit the code myself but am just too new to JS and jQuery.
Help please?
$(document).ready(function(){
//** notice we are including jquery and the color plugin at
//** http://code.jquery.com/color/jquery.color-2.1.0.js
var scroll_pos = 0;
var animation_begin_pos = 0; //where you want the animation to begin
var animation_end_pos = 1000; //where you want the animation to stop
var beginning_color = new $.Color( 'rgb(210,50,98)' ); //we can set this here, but it'd probably be better to get it from the CSS; for the example we're setting it here.
var ending_color = new $.Color( 'rgb(0,197,209)' ); ;//what color we want to use in the end
$(document).scroll(function() {
scroll_pos = $(this).scrollTop();
if(scroll_pos >= animation_begin_pos && scroll_pos <= animation_end_pos ) {
// console.log( 'scrolling and animating' );
//we want to calculate the relevant transitional rgb value
var percentScrolled = scroll_pos / ( animation_end_pos - animation_begin_pos );
var newRed = beginning_color.red() + ( ( ending_color.red() - beginning_color.red() ) * percentScrolled );
var newGreen = beginning_color.green() + ( ( ending_color.green() - beginning_color.green() ) * percentScrolled );
var newBlue = beginning_color.blue() + ( ( ending_color.blue() - beginning_color.blue() ) * percentScrolled );
var newColor = new $.Color( newRed, newGreen, newBlue );
//console.log( newColor.red(), newColor.green(), newColor.blue() );
$('body').animate({ backgroundColor: newColor }, 0);
} else if ( scroll_pos > animation_end_pos ) {
$('body').animate({ backgroundColor: ending_color }, 0);
} else if ( scroll_pos < animation_begin_pos ) {
$('body').animate({ backgroundColor: beginning_color }, 0);
} else { }
});
});
Here is the fiddle:
http://jsfiddle.net/cgspicer/V4qh9/

Similar to Sterling's answer, my first attempt was to kind of insert another checkpoint for the third color. This process, as in Sterling's solution, begins to precipitate the necessity of sub-functions.
See it here: http://jsfiddle.net/5uU6y/1/
A better and more complete solution, in which you can declare multiple colors, can be achieved by creating an array which stores your beginning, ending, and color values that you can check against when the window is scrolled.
Here's that solution ( see it in action here: http://codepen.io/cgspicer/pen/tomvq/ )
$(document).ready(function(){
/**
requires http://code.jquery.com/color/jquery.color-2.1.0.js
*/
var colorsNPoints = [
{ 'begin' : 0, 'end': 100, 'color': 'rgb(220,20,60)' },
{ 'begin' : 100, 'end': 110, 'color': 'rgb(0,0,0)' },
{ 'begin' : 110, 'end': 210, 'color': 'rgb(50,205,50)' },
{ 'begin' : 210, 'end': 310, 'color': 'rgb(255,215,0)' },
{ 'begin' : 310, 'end': 410, 'color': 'rgb(220,20,60)' },
{ 'begin' : 410, 'end': 420, 'color': 'rgb(0,0,0)' },
{ 'begin' : 420, 'end': 520, 'color': 'rgb(50,205,50)' },
{ 'begin' : 520, 'end': 620, 'color': 'rgb(255,215,0)' },
{ 'begin' : 620, 'end': 720, 'color': 'rgb(220,20,60)' },
{ 'begin' : 720, 'end': 730, 'color': 'rgb(0,0,0)' },
{ 'begin' : 730, 'end': 830, 'color': 'rgb(50,205,50)' },
{ 'begin' : 830, 'end': 930, 'color': 'rgb(255,215,0)' }
];
$(document).scroll(function() {
var scrollPosition = $(this).scrollTop();
var currentRange = checkRange( scrollPosition, colorsNPoints );
if ( currentRange !== undefined ) {
console.log( currentRange );
var newColor = recalcColor( currentRange.prevColor, currentRange.nextColor, currentRange.progress );
$('body').css({ backgroundColor: newColor }, 0);
} else {
// do nothing, we're not within any ranges
}
});
// sub-functions
/**
* checks which, if any, of the scroll ranges the window is currently on
* returns an object containing necessary values
*/
function checkRange( yValue, rangesObj ) {
// loop over the object containing our ranges
for ( var i=0; i < rangesObj.length; i++ ) {
var rangeToCheck = rangesObj[i];
// check to see if we are within said range
if ( yValue >= rangeToCheck.begin && yValue <= rangeToCheck.end ) {
// set up a new object for refinement and return
var currentRangeObj = {};
currentRangeObj.prevColor = rangesObj[i-1] ? rangesObj[i-1].color : rangeToCheck.color; // store old color, falls back to range's color if no previous color exists
currentRangeObj.nextColor = rangeToCheck.color; // store new color
currentRangeObj.progress = calcPercentScrolled( rangeToCheck.begin, rangeToCheck.end, yValue ); //calculate the progress within the current range
return currentRangeObj;
} else {
}
}
}
/**
* calculates current percent scrolled
**/
function calcPercentScrolled( begin, end, current ) {
return (current - begin) / ( end - begin );
}
/**
* calculates new color
**/
function recalcColor( begin, end, factor ) {
var begin = $.Color( begin ),
end = $.Color( end );
var newRed = begin.red() + ( ( end.red() - begin.red() ) * factor );
var newGreen = begin.green() + ( ( end.green() - begin.green() ) * factor );
var newBlue = begin.blue() + ( ( end.blue() - begin.blue() ) * factor );
return $.Color( newRed, newGreen, newBlue );
}
});
Hope this helps!

Try this. It's the same idea as the original code with a couple of minor additions. You can try to do it for n colors using the same idea using an array of start positions, end positions, and starting colors if you want some practice with Javascript. (And a better implementation)
Fiddle
$(document).ready(function(){
//** notice we are including jquery and the color plugin at
//** http://code.jquery.com/color/jquery.color-2.1.0.js
var body_end = $(document).height() / ;
var animation_begin_pos = 0; //where you want the animation to begin
var animation_middle_pos = body_end / 3;
var animation_end_pos = body_end / (3/2); //where you want the animation to stop
var beginning_color = new $.Color( 'rgb(210,50,98)' ); //we can set this here, but it'd probably be better to get it from the CSS; for the example we're setting it here.
var middle_color = new $.Color('rgb(255,0,0)');
var ending_color = new $.Color( 'rgb(0,197,209)' ); ;//what color we want to use in the end
/* */
function getPercentScrolled(scroll_pos, beginning_pos, end_pos){
return (scroll_pos - beginning_pos) / (end_pos - beginning_pos);
}
function getNewRGB(start_color, end_color, percentScrolled){
var newRed = start_color.red() + ( ( end_color.red() - start_color.red() ) * percentScrolled );
var newGreen = start_color.green() + ( ( end_color.green() - start_color.green() ) * percentScrolled );
var newBlue = start_color.blue() + ( ( end_color.blue() - start_color.blue() ) * percentScrolled );
console.log(newRed, newGreen, newBlue);
console.log(percentScrolled);
newRed = ((newRed > 0.0) ? newRed : 0.0);
newGreen = ((newGreen > 0.0) ? newGreen : 0.0);
newBlue = ((newBlue > 0.0) ? newBlue : 0.0);
return {red: newRed, green: newGreen, blue: newBlue};
}
$(document).scroll(function() {
var scroll_pos = $(this).scrollTop();
if(scroll_pos >= animation_begin_pos && scroll_pos <= animation_middle_pos ) {
//we want to calculate the relevant transitional rgb value
var percentScrolled = getPercentScrolled(scroll_pos, animation_begin_pos, animation_end_pos);
var updatedColor = getNewRGB(beginning_color, middle_color, percentScrolled);
var newColor = new $.Color( updatedColor['red'], updatedColor['green'], updatedColor['blue'] );
$('body').animate({ backgroundColor: newColor }, 0);
}
else if ( scroll_pos >= animation_middle_pos && scroll_pos < animation_end_pos) {
percentScrolled = getPercentScrolled(scroll_pos, animation_middle_pos, animation_end_pos);
updatedColor = getNewRGB(middle_color, ending_color, percentScrolled);
newColor = new $.Color( updatedColor['red'], updatedColor['green'], updatedColor['blue'] );
$('body').animate({ backgroundColor: newColor }, 0);
}
else if ( scroll_pos > animation_middle_pos ) {
$('body').animate({ backgroundColor: ending_color }, 0);
}
else if ( scroll_pos < animation_begin_pos ) {
$('body').animate({ backgroundColor: beginning_color }, 0);
}
});
});

Related

Make a slider responsive (jQuery)

I have a slider, I want to make them responsive the problem is the size of slider is into the jQuery file
sow how I can edit the code ?
code of jQuery
(function( window, $, undefined ) {
var $event = $.event, resizeTimeout;
$event.special.smartresize = {
setup: function() {
$(this).bind( "resize", $event.special.smartresize.handler );
},
teardown: function() {
$(this).unbind( "resize", $event.special.smartresize.handler );
},
handler: function( event, execAsap ) {
// Save the context
var context = this,
args = arguments;
// set correct event type
event.type = "smartresize";
if ( resizeTimeout ) { clearTimeout( resizeTimeout ); }
resizeTimeout = setTimeout(function() {
jQuery.event.handle.apply( context, args );
}, execAsap === "execAsap"? 0 : 100 );
}
};
$.fn.smartresize = function( fn ) {
return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] );
};
$.Slideshow = function( options, element ) {
this.$el = $( element );
/***** images ****/
// list of image items
this.$list = this.$el.find('ul.ei-slider-large');
// image items
this.$imgItems = this.$list.children('li');
// total number of items
this.itemsCount = this.$imgItems.length;
// images
this.$images = this.$imgItems.find('img:first');
/***** thumbs ****/
// thumbs wrapper
this.$sliderthumbs = this.$el.find('ul.ei-slider-thumbs').hide();
// slider elements
this.$sliderElems = this.$sliderthumbs.children('li');
// sliding div
this.$sliderElem = this.$sliderthumbs.children('li.ei-slider-element');
// thumbs
this.$thumbs = this.$sliderElems.not('.ei-slider-element');
// initialize slideshow
this._init( options );
};
$.Slideshow.defaults = {
// animation types:
// "sides" : new slides will slide in from left / right
// "center": new slides will appear in the center
animation : 'center', // sides || center
// if true the slider will automatically slide, and it will only stop if the user clicks on a thumb
autoplay : false,
// interval for the slideshow
slideshow_interval : 3000,
// speed for the sliding animation
speed : 800,
// easing for the sliding animation
easing : '',
// percentage of speed for the titles animation. Speed will be speed * titlesFactor
titlesFactor : 0.60,
// titles animation speed
titlespeed : 800,
// titles animation easing
titleeasing : '',
};
$.Slideshow.prototype = {
_init : function( options ) {
this.options = $.extend( true, {}, $.Slideshow.defaults, options );
// set the opacity of the title elements and the image items
this.$imgItems.css( 'opacity', 0 );
this.$imgItems.find('div.ei-title > *').css( 'opacity', 0 );
// index of current visible slider
this.current = 0;
var _self = this;
// preload images
// add loading status
this.$loading = $('<div class="ei-slider-loading">Loading</div>').prependTo( _self.$el );
$.when( this._preloadImages() ).done( function() {
// hide loading status
_self.$loading.hide();
// calculate size and position for each image
_self._setImagesSize();
// configure thumbs container
_self._initThumbs();
// show first
_self.$imgItems.eq( _self.current ).css({
'opacity' : 1,
'z-index' : 10
}).show().find('div.ei-title > *').css( 'opacity', 1 );
// if autoplay is true
if( _self.options.autoplay ) {
_self._startSlideshow();
}
// initialize the events
_self._initEvents();
});
},
_preloadImages : function() {
// preloads all the large images
var _self = this,
loaded = 0;
return $.Deferred(
function(dfd) {
_self.$images.each( function( i ) {
$('<img/>').load( function() {
if( ++loaded === _self.itemsCount ) {
dfd.resolve();
}
}).attr( 'src', $(this).attr('src') );
});
}
).promise();
},
_setImagesSize : function() {
// save ei-slider's width
this.elWidth = this.$el.width();
var _self = this;
this.$images.each( function( i ) {
var $img = $(this);
imgDim = _self._getImageDim( $img.attr('src') );
$img.css({
width : imgDim.width,
height : imgDim.height,
marginLeft : imgDim.left,
marginTop : imgDim.top
});
});
},
_getImageDim : function( src ) {
var $img = new Image();
$img.src = src;
var c_w = this.elWidth,
c_h = this.$el.height(),
r_w = c_h / c_w,
i_w = $img.width,
i_h = $img.height,
r_i = i_h / i_w,
new_w, new_h, new_left, new_top;
if( r_w > r_i ) {
new_h = c_h;
new_w = c_h / r_i;
}
else {
new_h = c_w * r_i;
new_w = c_w;
}
return {
width : new_w,
height : new_h,
left : ( c_w - new_w ) / 2,
top : ( c_h - new_h ) / 2
};
},
_initThumbs : function() {
// set the max-width of the slider elements to the one set in the plugin's options
// also, the width of each slider element will be 100% / total number of elements
this.$sliderElems.css({
'width' : 100 / this.itemsCount + '%'
});
// set the max-width of the slider and show it
this.$sliderthumbs.css( 'width', this.options.thumbMaxWidth * this.itemsCount + 'px' ).show();
},
_startSlideshow : function() {
var _self = this;
this.slideshow = setTimeout( function() {
var pos;
( _self.current === _self.itemsCount - 1 ) ? pos = 0 : pos = _self.current + 1;
_self._slideTo( pos );
if( _self.options.autoplay ) {
_self._startSlideshow();
}
}, this.options.slideshow_interval);
},
// shows the clicked thumb's slide
_slideTo : function( pos ) {
// return if clicking the same element or if currently animating
if( pos === this.current || this.isAnimating )
return false;
this.isAnimating = true;
var $currentSlide = this.$imgItems.eq( this.current ),
$nextSlide = this.$imgItems.eq( pos ),
_self = this,
preCSS = {zIndex : 10},
animCSS = {opacity : 1};
// new slide will slide in from left or right side
if( this.options.animation === 'sides' ) {
preCSS.left = ( pos > this.current ) ? -1 * this.elWidth : this.elWidth;
animCSS.left = 0;
}
// titles animation
$nextSlide.find('div.ei-title > h2')
.css( 'margin-right', 50 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 }, this.options.titlespeed, this.options.titleeasing )
.end()
.find('div.ei-title > h3')
.css( 'margin-right', -50 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 }, this.options.titlespeed, this.options.titleeasing )
$.when(
// fade out current titles
$currentSlide.css( 'z-index' , 1 ).find('div.ei-title > *').stop().fadeOut( this.options.speed / 2, function() {
// reset style
$(this).show().css( 'opacity', 0 );
}),
// animate next slide in
$nextSlide.css( preCSS ).stop().animate( animCSS, this.options.speed, this.options.easing ),
// "sliding div" moves to new position
this.$sliderElem.stop().animate({
left : this.$thumbs.eq( pos ).position().left
}, this.options.speed )
).done( function() {
// reset values
$currentSlide.css( 'opacity' , 0 ).find('div.ei-title > *').css( 'opacity', 0 );
_self.current = pos;
_self.isAnimating = false;
});
},
_initEvents : function() {
var _self = this;
// window resize
$(window).on( 'smartresize.eislideshow', function( event ) {
// resize the images
_self._setImagesSize();
// reset position of thumbs sliding div
_self.$sliderElem.css( 'left', _self.$thumbs.eq( _self.current ).position().left );
});
// click the thumbs
this.$thumbs.on( 'click.eislideshow', function( event ) {
if( _self.options.autoplay ) {
clearTimeout( _self.slideshow );
_self.options.autoplay = false;
}
var $thumb = $(this),
idx = $thumb.index() - 1; // exclude sliding div
_self._slideTo( idx );
return false;
});
}
};
var logError = function( message ) {
if ( this.console ) {
console.error( message );
}
};
$.fn.eislideshow = function( options ) {
if ( typeof options === 'string' ) {
var args = Array.prototype.slice.call( arguments, 1 );
this.each(function() {
var instance = $.data( this, 'eislideshow' );
if ( !instance ) {
logError( "cannot call methods on eislideshow prior to initialization; " +
"attempted to call method '" + options + "'" );
return;
}
if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
logError( "no such method '" + options + "' for eislideshow instance" );
return;
}
instance[ options ].apply( instance, args );
});
}
else {
this.each(function() {
var instance = $.data( this, 'eislideshow' );
if ( !instance ) {
$.data( this, 'eislideshow', new $.Slideshow( options, this ) );
}
});
}
return this;
};
})( window, jQuery );
How I can edit that to make them responsive ? can you give an example ?
I suggest you use something more simple (only 3 steps) instead of review this code.
Code:
Step 1: Link required files
First and most important, the jQuery library needs to be included (no need to download - link directly from Google). Next, download the package from this site and link the bxSlider CSS file (for the theme) and the bxSlider Javascript file.
<!-- jQuery library (served from Google) -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<!-- bxSlider Javascript file -->
<script src="/js/jquery.bxslider.min.js"></script>
<!-- bxSlider CSS file -->
<link href="/lib/jquery.bxslider.css" rel="stylesheet" />
Step 2: Create HTML markup
Create a <ul class="bxslider"> element, with a <li> for each slide. Slides can contain images, video, or any other HTML content!
<ul class="bxslider">
<li><img src="/images/pic1.jpg" /></li>
<li><img src="/images/pic2.jpg" /></li>
<li><img src="/images/pic3.jpg" /></li>
<li><img src="/images/pic4.jpg" /></li>
</ul>
Step 3: Call the bxSlider
Call .bxslider() on <ul class="bxslider">. Note that the call must be made inside of a $(document).ready() call, or the plugin will not work!
$(document).ready(function(){
$('.bxslider').bxSlider();
});
I really believe, this will be more helpful and simple.
Credits: http://bxslider.com
Different configurations
$('.bxslider').bxSlider({
mode: 'fade',
captions: true,
pagerCustom: '#bx-pager',
adaptiveHeight: true,
slideWidth: 150
});
Don't forget to read this: http://bxslider.com/options

Canvas Greek google fonts not rendering correctly

I assume that this is a bug but if any of you know any work around please let me know.
First of all, the fonts are loaded 101%.
I load Google fonts synchronously
I check with interval to make sure that the font is loaded.
I convert a string into an image (with the below function) by using canvas with success (when
I use English characters)
After rendering a couple English characters I try to render a Greek
word but canvas fall backs to browsers default font.
Firefox doesn't have any issue at all, it works great. The issue is
with Chrome.
Bellow is the function that creates a ribbon-label background image on the top left corner from a given string (PS: this function return imageData that are being merged with other imageData later on):
ImageProcessor.prototype.createLabelImageData = function ( str, size, font, color, backgroundColor, shadowColor, shadowOffsetX, shadowOffsetY, shadowBlur, width, height ) {
this.canvas.width = width || this.settings.width;
this.canvas.height = height || this.settings.height;
this.ctx.clearRect( 0, 0, this.canvas.width, this.canvas.height );
this.ctx.font = "Bold " + ( size || 64 ) + "px " + ( font || "Arial" );
this.ctx.textAlign = "center";
this.ctx.textBaseline = "middle";
var labelHeight = ( size || 64 ) + ( ( size || 64 ) / 4 );
var labelTop = this.canvas.height / 2 - labelHeight / 2;
var labelWidth = this.canvas.width;
var strLen = this.ctx.measureText( str + " " ).width;
var side = Math.sqrt( ( strLen * strLen ) / 2 );
var distance = Math.sqrt( ( side * side ) - ( ( strLen / 2 ) * ( strLen / 2 ) ) );
this.ctx.save();
this.ctx.rotate( -Math.PI / 4 );
this.ctx.translate( -this.canvas.width / 2, -this.canvas.height / 2 + distance );
this.ctx.fillStyle = ( backgroundColor || '#f00' );
this.ctx.beginPath();
this.ctx.moveTo( 0, labelTop );
this.ctx.lineTo( labelWidth, labelTop );
this.ctx.lineTo( labelWidth, labelTop + labelHeight );
this.ctx.lineTo( 0, labelTop + labelHeight );
this.ctx.closePath();
this.ctx.fill();
if ( shadowColor ) {
this.ctx.shadowColor = shadowColor;
this.ctx.shadowOffsetX = ( shadowOffsetX || 0 );
this.ctx.shadowOffsetY = ( shadowOffsetY || 0 );
this.ctx.shadowBlur = ( shadowBlur || size || 64 );
}
this.ctx.fillStyle = ( color || "#fff" );
this.ctx.fillText( str, this.canvas.width / 2, this.canvas.height / 2 );
this.ctx.restore();
var imageData = this.ctx.getImageData( 0, 0, this.canvas.width, this.canvas.height );
this.canvas.width = this.settings.width;
this.canvas.height = this.settings.height;
return imageData;
};
Well after some testing, trial and error and many many hours of reading...
I found out that it doesn't matter if the font has been downloaded when you want to use it in canvas. What worked for me before anything else and any check was to create n*2 div elements (n the number of fonts loaded) and position them outside of the view-port. n*2 because in some I added font-weight:bold.
Bottom line is that the exact font you wish to use in canvas must be:
Preloaded
Create a dummy dom element with innerHTML text of all language
variations (latin & greek in my case).
Keep in mid that you have to create extra elements for the bold variation of the font.
Here is the code that I'm currently using to preload fonts and make sure they are available in canvas.
Vise.prototype.initializeFonts = function ( settings, globalCallback ) {
var that = this; // reference to parent class
/********************************************
********************************************
**
**
** Default settings
**
**
********************************************
********************************************/
var defaults = {
interval: 100,
timeout: 10000,
families: [
'Open+Sans+Condensed:300,300italic,700:latin,greek',
'Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800:latin,greek',
'Roboto+Condensed:300italic,400italic,700italic,400,700,300:latin,greek',
'Roboto:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic:latin,greek'
]
};
// initialization
this.fonts = new Fonts( $.extend( true, defaults, settings ) );
this.fonts.onload = globalCallback;
this.fonts.load();
};
/********************************************
********************************************
**
**
** Fonts class
**
**
********************************************
********************************************/
function Fonts( settings ) {
this.settings = settings;
this.success = [];
this.fail = [];
this.interval = null;
this.elapsedTime = this.settings.interval;
this.fontDetective = new Detector();
}
Fonts.prototype.load = function () {
WebFont.load( {
google: {
families: this.settings.families
}
} );
for ( var i in this.settings.families ) {
var el, elBold;
var familyStr = this.settings.families[ i ];
var family = familyStr.split( ':' )[ 0 ].replace( /[+]/gi, ' ' );
el = document.createElement( "div" );
el.innerHTML = "Font loader Φόρτωμα γραμματοσειράς";
el.style.fontFamily = family;
el.style.color = "#f00";
el.style.position = "fixed";
el.style.zIndex = 9999;
el.style.left = "9999px";
document.body.appendChild( el );
elBold = document.createElement( "div" );
elBold.innerHTML = "Font loader Φόρτωμα γραμματοσειράς";
elBold.style.fontFamily = family;
elBold.style.fontWeight = "bold";
elBold.style.color = "#f00";
elBold.style.position = "fixed";
elBold.style.zIndex = 9999;
elBold.style.left = "9999px";
document.body.appendChild( elBold );
}
this.interval = setInterval( this.areLoaded.bind( this ), this.settings.interval );
};
Fonts.prototype.areLoaded = function () {
for ( var i in this.settings.families ) {
var familyStr = this.settings.families[ i ];
var family = familyStr.split( ':' )[ 0 ].replace( /[+]/gi, ' ' );
var successIdx, failIdx;
if ( this.fontDetective.detect( family ) ) {
successIdx = this.success.indexOf( family );
failIdx = this.fail.indexOf( family );
if ( successIdx === -1 ) {
this.success.push( family );
console.log( "[" + family + "] was successfully loaded." );
}
if ( failIdx > -1 ) {
this.fail.splice( failIdx, 1 );
}
} else {
successIdx = this.success.indexOf( family );
failIdx = this.fail.indexOf( family );
if ( successIdx > -1 ) {
this.success.splice( successIdx, 1 );
}
if ( failIdx === -1 ) {
this.fail.push( family );
}
}
}
if ( this.elapsedTime >= this.settings.timeout ) {
clearInterval( this.interval );
var err = new Error( "Unable to load fonts: " + this.fail.toString() );
this.onload( err, null );
return;
}
if ( this.success.length === this.settings.families.length ) {
clearInterval( this.interval );
this.onload( null, null );
return;
}
this.elapsedTime += this.settings.interval;
};
This is what worked for me in case someone else has the same issue on chrome.
PS: Take a look at fontdetect.js which I use in my code.

Making a plane seat chart

I'm trying to use a plane seat map generator. What it does is really simple. You insert the passengers for first, business and economy on html inputs. And automatically a chart should appear. This work is perform by javascript. I'm trying to run it but something is going wrong. It just does not work. It shows the table where you should put the inputs and a number 7 under it. I guess that's happening because I am missing some javascript. When you fill the input nothing happens.
To make it easier I put the code on jsfiddle. http://jsfiddle.net/g4kzo4fo/
Because I have to paste code here you have my javascript. I think the problem is somewhere here:
makeRequest(request, id, false);
$('#'+id).dialog({ width: 'auto', height: 'auto', modal: true, resizable: false });
$('#'+id).dialog('open');
}
var AircraftConfigCheck = {
capacity : 200,
business : 0,
economy: 0,
first: 0,
businessFree : 0,
economyFree : 0,
firstFree: 0,
total : function() {
return (parseInt(this.business) || 0) * 2 + (parseInt(this.economy) || 0) + (parseInt(this.first) || 0) * 4;
},
checkBusiness : function() {
if( this.total() > this.capacity ) {
this.business = Math.floor( ( this.capacity - this.economy - this.first * 4 ) / 2 );
}
},
checkEconomy : function() {
if( this.total() > this.capacity ) {
this.economy = this.capacity - this.business * 2 - this.first * 4;
}
},
checkFirst : function() {
if( this.total() > this.capacity ) {
this.first = Math.floor( ( this.capacity - this.economy - this.business * 2 ) / 4 );
}
},
updateCapacity : function() {
this.businessFree = Math.max( 0, Math.floor( ( this.capacity - this.total() ) / 2 ) );
this.firstFree = Math.max( 0, Math.floor( ( this.capacity - this.total() ) / 4 ) );
this.economyFree = Math.max( 0, this.capacity - this.total() );
},
setValues : function() {
$("#business").val( this.business );
$("#economy").val( this.economy );
$("#first").val( this.first );
$("#businessFree").html( this.businessFree );
$("#economyFree").html( this.economyFree );
$("#firstFree").html( this.firstFree );
/*$("#first").val( this.total() ); */
this.render();
},
render : function() {
makeRequest('http://www.fsairlines.net/crewcenter/aircraft_config_ajax.php5?max_pax='+this.capacity+
'&first_seats='+this.first+
'&business_seats='+this.business+
'&economy_seats='+this.economy,
'aircraft',
true
);
}
}
$(function() {
$(".seatInput").keyup(function() {
switch( $(this).attr("id") ) {
case "economy":
AircraftConfigCheck.economy = $("#economy").val();
AircraftConfigCheck.checkEconomy();
AircraftConfigCheck.updateCapacity();
AircraftConfigCheck.setValues();
break;
case "business":
AircraftConfigCheck.business = $("#business").val();
AircraftConfigCheck.checkBusiness();
AircraftConfigCheck.updateCapacity();
AircraftConfigCheck.setValues();
break;
case "first":
AircraftConfigCheck.first = $("#first").val();
AircraftConfigCheck.checkFirst();
AircraftConfigCheck.updateCapacity();
AircraftConfigCheck.setValues();
break;
}
});
});
Thanks in advance!
LASTEST UPDATE: http://jsfiddle.net/g4kzo4fo/4/
You have quite a few syntax errors in your code which is why it isn't running.
This part of the code doesn't make any sense:
makeRequest(request, id, false);
$('#'+id).dialog({ width: 'auto', height: 'auto', modal: true, resizable: false });
$('#'+id).dialog('open');
}
The makeRequest() function doesn't exist so you can't call it. And, there's an extraneous } at the end of this block.
Then, later inside the render function, you try to call makeRequest() again, but it doesn't exist.
The very first thing you should do when running any Javascript code that you've just written is to check the error console or debug console in the browser for errors. Then, anytime that something isn't working properly check the console again. Then, when you're testing your code, check the error console again.

How to bind two stores to one view in Sencha?

I am trying to build a custom component in Sencha Touch which would display values from two stores. I am trying to build upon Ext.us.Cover which extends from Ext.data.DataView. Since I am a beginner in Sencha, I could use some help on how to accomplish binding two stores to one view.
Here is what I have currently:
/**
* #class Ext.ux.CrossCover
* #extend Ext.DataView
*
* A CrossCover represents two intersecting Cover flows
* #author Abhishek Mukherjee
*/
Ext.define('Ext.ux.CrossCover',{
extend: 'Ext.DataView',
xtype: 'cover',
config:{
/**
* #cfg {Number} selectedIndex The idx from the Store that will be active first. Only one item can be active at a
* time
* #accessor
* #evented
*/
selectedIndex: 0,
/**
* #cfg {String} itemCls
* A css class name to be added to each item element.
*/
itemCls: '',
/**
* #cfg {Boolean} preventSelectionOnItemTap
* Prevent selection when item is tapped. This is false by default.
*/
preventSelectionOnItemTap: false,
/**
* #cfg {Number} angle for cover background items
* This is the angle that not selected items are moved in space.
*/
angle: 75,
/**
* #cfg {Boolean} set to true if you want a flat representation. Defaults to false so the
* coverflow remains 3d.
*/
flat: false,
/**
* #cfg {Boolean} preventOrientationChange
* Prevent attaching refresh method to orientation change event on Ext.Viewport
*/
preventOrientationChange: false,
/**
* #cfg {Ext.data.Store} horizontalStore
* Store containing data for horizontal cover-flow
*/
horizontalStore: '',
//private
baseCls: 'ux-cover',
//private
itemBaseCls: 'ux-cover-item-inner',
//private
scrollable: null,
//private
orientationCls: undefined
},
offset: 0,
horizontalOffset: 0,
//override
initialize: function(){
console.log("Called");
//we need somehow to put the itemCls to the tpl wraper element
this.innerItemCls = this.getItemCls();
if(this.innerItemCls) {
this.setItemCls(this.innerItemCls+'-wrap');
}
this.callParent();
console.log(this.element.type);
this.element.on({
drag: 'onDrag',
dragstart: 'onDragStart',
dragend: 'onDragEnd',
scope: this
});
this.on({
painted: 'onPainted',
itemtap: 'doItemTap',
scope: this
});
if(!this.getPreventOrientationChange()){
//subscribe to orientation change on viewport
Ext.Viewport.on('orientationchange', this.refresh, this);
}
this.setItemTransformation = (this.getFlat())?this.setItemTransformFlat:this.setItemTransform3dVertical;
},
getElementConfig: function(){
console.log("getElementConfig Called");
return {
reference: 'element',
children:[{
reference: 'innerElement',
className: 'ux-cover-scroller'
}]
};
},
applyFlat: function(flat) {
return (Ext.os.is('Android')? true : flat);
},
updateOrientationCls: function(newOrientation, oldOrientation) {
var baseCls = this.getBaseCls();
if(this.element && newOrientation != oldOrientation) {
this.element.removeCls(baseCls+'-'+oldOrientation);
this.element.addCls(baseCls+'-'+newOrientation);
}
},
applyItemTpl: function(config){
console.log("applyItemTpl Called");
if(Ext.isArray(config)){
config = config.join("");
}
return new Ext.XTemplate('<div class="' + this.getItemBaseCls() + ' ' + this.getItemCls() + ' ">'+config+'</div>');
},
onPainted: function(){
this.refresh();
},
//private
getTargetEl: function(){
console.log("getTargetEl Called");
return this.innerElement;
},
onDragStart: function(){
console.log("onDragStart Called");
this.getTargetEl().dom.style.webkitTransitionDuration = "0s";
},
onDrag: function(e){
console.log("onDrag Called");
var curr = this.getOffset(),
offset,
ln = this.getViewItems().length,
selectedIndex,
delta = (e.deltaY - e.previousDeltaY);
//slow down on border conditions
selectedIndex = this.getSelectedIndex();
if ((selectedIndex === 0 && e.deltaY > 0) || (selectedIndex === ln - 1 && e.deltaY < 0)) {
delta *= 0.5;
}
offset = curr + delta;
this.setOffset(offset, true);
},
onDragEnd: function(){
console.log("onDragEnd Called");
var idx = this.getSelectedIndex(),
y = - (idx * this.gap);
this.getTargetEl().dom.style.webkitTransitionDuration = "0.4s";
//this.setOffset(x);
this.applySelectedIndex(idx);
},
doItemTap: function(cover, index, item, evt){
if(!this.getPreventSelectionOnItemTap() && this.getSelectedIndex() !== index){
this.setSelectedIndex(index);
}
},
getSelectedIndex: function(){
console.log("getSelectedIndex Called");
var idx, ln;
if(this.isRendered()){
ln = this.getViewItems().length;
idx = - Math.round(this.getOffset() / this.gap);
this.selectedIndex = Math.min(Math.max(idx, 0), ln - 1);
}
return this.selectedIndex;
},
applySelectedIndex: function(idx){
console.log("applySelectedINdex Called");
if(this.isRendered()){
this.updateOffsetToIdx(idx);
this.selectWithEvent(this.getStore().getAt(idx));
}else{
this.selectedIndex = idx;
}
// apply horizontal index
this.applySelectedHorizontalIndex(idx);
},
applySelectedHorizontalIndex: function(idx){
console.log("applySelectedHorizontalIndex Called");
if(this.isRendered()){
this.updateHorizontalOffsetToIdx(idx);
this.selectWithEvent(this.getHorizontalStore().data.items[idx]);
}else{
this.selectedIndex = idx;
}
},
updateOffsetToIdx: function(idx){
console.log("updateOffsetToIdx Called");
var ln = this.getViewItems().length,
offset;
idx = Math.min(Math.max(idx, 0), ln - 1);
offset= -(idx * this.gap);
this.setOffset(offset);
},
updateHorizontalOffsetToIdx: function(idx){
console.log("updateHorizontalOffsetToIdx Called");
var ln = this.getHorizontalStore().data.items.length,
offset;
// console.log("Number of horizontal items is ")
idx = Math.min(Math.max(idx, 0), ln - 1);
offset= -(idx * this.gap);
this.setHorizontalOffset(offset);
},
setOffset: function(offset){
console.log("setOffset Called");
// Set offset for the vertical cover
var items = this.getViewItems(),
idx = 0,
l = items.length,
item;
this.offset = offset;
// Changing the translation to Y-axis
this.getTargetEl().dom.style.webkitTransform = "translate3d( 0," + offset + "px, 0)";
for(;idx<l;idx++){
item = Ext.get(items[idx]);
this.setItemTransformation(item, idx, offset);
}
},
setHorizontalOffset: function(offset){
console.log("setHorizontalOffset Called");
// Set offset for the horizontal cover
var hitems = this.getHorizontalStore().data.items,
hidx = 0,
hl = hitems.length,
hitem;
console.log("horizontal store items :"+hl);
this.horizontalOffset = offset;
// Changing the translation to X-axis
this.getTargetEl().dom.style.webkitTransform = "translate3d( " + offset + "px, 0, 0)";
for(;hidx<hl;hidx++){
hitem = document.createElement("div");
var newContent = document.createTextNode(hitems[hidx].data.preferredName);
hitem.appendChild(newContent);
console.log("hitem is"+hitem);
this.setItemTransform3dHorizontal(hitem, hidx, offset);
}
},
getOffset: function(){
console.log("getOffset Called");
return this.offset;
},
getHorizontalOffset: function(){
console.log(" getHorizontaloffset Called");
return this.horizontalOffset;
},
getBaseItemBox: function(containerBox){
console.log("getBaseItemBox Called");
var cH = containerBox.height,
cW = containerBox.width,
sizeFactor = (cW > cH) ? 0.68 : 0.52,
h, w;
h = w = Math.min(containerBox.width, containerBox.height) * sizeFactor;
return {
top: (containerBox.height - w) / 2 ,
height: h * 1.5,
width: w,
left: (containerBox.width - w) / 2
};
},
setBoundaries: function(itemBox){
console.log("setBoundaries Called");
var w = itemBox.width;
if(this.getFlat()){
this.gap = w * 1.1;
this.threshold = this.gap / 3;
this.delta = w * 0.2;
} else {
this.gap = w / 3;
this.threshold = this.gap / 2;
this.delta = w * 0.4;
}
},
setItemTransformation: Ext.emptyFn,
setItemTransform3dVertical: function(item, idx, offset){
console.log("type of item is:"+ item.type);
console.log("Called setItemTransform3dVertical"+offset);
var x = idx * this.gap,
ix = x + offset,
transf = "";
if(ix < this.threshold && ix >= - this.threshold){
// Changing the translation to Y-axis
transf = "translate3d( 0,"+x+"px, 150px)";
this.selectedIndex = idx;
}else if(ix > 0){
// Changing the rotation to x-axis
transf = "translate3d( 0 ,"+(x+this.delta)+"px, 0 ) rotateX(-"+this.getAngle()+"deg)";
}else{
// Changing the rotation to x-axis
transf = "translate3d( 0, "+(x-this.delta)+"px, 0 ) rotateX("+this.getAngle()+"deg)";
}
item.dom.style.webkitTransform = transf;
},
setItemTransform3dHorizontal: function(item, idx, offset){
console.log("Called setItemTransform3dHorizontal"+offset);
console.log("item receieved::"+item + " idx is "+idx+" offset is "+offset);
var x = idx * this.gap,
ix = x + offset,
transf = "";
if(ix < this.threshold && ix >= - this.threshold){
// Changing the translation to X-axis
transf = "translate3d( "+x+"px, 0, 150px)";
this.selectedIndex = idx;
}else if(ix > 0){
// Changing the rotation to Y-axis
transf = "translate3d( "+(x+this.delta)+"px, 0 , 0 ) rotateY(-"+this.getAngle()+"deg)";
}else{
// Changing the rotation to Y-axis
transf = "translate3d( "+(x-this.delta)+"px, 0, 0 ) rotateY("+this.getAngle()+"deg)";
}
item.style.webkitTransform = transf;
},
setItemTransformFlat: function(item, idx, offset){
var x = idx * this.gap,
ix = x + offset,
transf = "";
if(ix < this.threshold && ix >= - this.threshold){
// Changing the translation to Y-axis
transf = "translate3d( 0, "+x+"px, 150px)";
this.selectedIndex = idx;
}else if(ix > 0){
transf = "translate3d("+(x+this.delta)+"px, 0, 0)";
}else{
transf = "translate3d("+(x-this.delta)+"px, 0, 0)";
}
item.dom.style.webkitTransform = transf;
},
doRefresh: function(me){
console.log("doRefresh Called");
var container = me.container,
items, idx = 0, l,
orientation = Ext.Viewport.getOrientation();
this.setOrientationCls(orientation);
this.callParent([me]);
items = container.getViewItems();
l = items.length;
this.itemBox = this.getBaseItemBox(this.element.getBox());
this.setBoundaries(this.itemBox);
for(;idx<l;idx++){
this.resizeItem(items[idx]);
}
this.setSelectedIndex(this.selectedIndex);
// Refresh the horizontal cover flow
this.refreshHorizontalCover();
},
refreshHorizontalCover: function(){
console.log("refreshHorizontalCover Called");
//var container = me.container,
var hitems, hidx = 0, hl;
// orientation = Ext.Viewport.getOrientation();
//this.setOrientationCls(orientation);
//this.callParent([me]);
hitems = this.getHorizontalStore().data.items;
hl = hitems.length;
this.itemBox = this.getBaseItemBox(this.element.getBox());
this.setBoundaries(this.itemBox);
for(;hidx<hl;hidx++){
var item = document.createElement("div");
var newContent = document.createTextNode(hitems[hidx].data.preferredName);
item.appendChild(newContent); //add the text node to the newly created div.
this.resizeHorizontalItem(item);
}
this.setSelectedIndex(this.selectedIndex);
},
resizeItem: function(element){
console.log("resizeItem Called");
var itemBox = this.itemBox,
item = Ext.get(element);
item.setBox(itemBox);
/**
itemBox has an extra long in height to avoid reflection opacity over other items
I need to create a wrapper element with same bg to avoid that issue.
*/
item.down('.'+this.getItemBaseCls()).setBox({height: itemBox.height/1.5, width: itemBox.width});
},
resizeHorizontalItem: function(element){
console.log("resizeHorizontalItem Called");
var itemBox = this.itemBox,
item = Ext.get(element);
item.setBox(itemBox);
/**
itemBox has an extra long in height to avoid reflection opacity over other items
I need to create a wrapper element with same bg to avoid that issue.
*/
//item.down('.'+this.getItemBaseCls()).setBox({height: itemBox.height/1.5, width: itemBox.width});
},
//override
onStoreUpdate: function(store, record, newIndex, oldIndex) {
var me = this,
container = me.container,
item;
oldIndex = (typeof oldIndex === 'undefined') ? newIndex : oldIndex;
if (oldIndex !== newIndex) {
container.moveItemsToCache(oldIndex, oldIndex);
container.moveItemsFromCache([record]);
}
else {
item = container.getViewItems()[newIndex];
// Bypassing setter because sometimes we pass the same record (different data)
container.updateListItem(record, item);
me.resizeItem(item);
}
}
});
Idea here is to have two cover flows, one horizontal and other vertical intersecting in middle. I can display one cover flow, but the other one is not getting displayed ( or is out of view). Since for one cover I can use properties from DataView , displaying the first is relatively easier than the second. I could help some suggestion on how to display the second.
I would appreciate any help with this. Thanks a lot for your time.
Data View in Ext is bound to one store. I think that much less coding would be to take two views and put them in a layout.
I solved it by super-imposing two separate views on top of each other and passing on the event from the top view to the underlying view when the drag was on a particular direction.

Accessing an object returns undefined while it's not

I'm fairly new to JavaScript but I'm a long time programmer and I just can't understand what's happening.
I have this:
var MainTable = {
"k1": 0,
"k2": 9,
"k3": 20
};
And when I want to access a specific element:
var index = "k1";
var value = MainTable[index];
And now, for a reason that totally eludes me, it returns undefined instead of 0 each and every time. I've been at it for about 2 hours now and I just don't get it.
Thanks !
EDIT with full code:
// These shouldn't be modified
var maxEPoints = 29;
var maxGold = 50;
var hudBarWidth_HR = 650; // 650 is for hr (px)
var hudBarWidth_LR = 350;
var IN_COMBAT = false;
var IN_COMBAT_WAITING = false;
var WolfDamageTable =
{
"m11_1": 99,
"m11_2": 99,
"m11_3": 8,
"m11_4": 8,
"m11_5": 7,
"m11_6": 6,
"m11_7": 5,
"m11_8": 4,
"m11_9": 3,
"m11_10": 0,
};
var EnemyDamageTable =
{
"m11_1": 0,
"m11_2": 0,
"m11_3": 0,
"m11_4": 0,
"m11_5": 1,
"m11_6": 2,
"m11_7": 3,
"m11_8": 4,
"m11_9": 5,
"m11_10": 6,
};
function ComputeCombatDamage( aPoints, ePoints, skill, endurance )
{
var ratio = ( aPoints - parseInt( skill ) ).toString();
var absRatio = ( aPoints - parseInt( skill ) );
var randVal = GIMME_A_RANDOM().toString();
$( "td#tableWolfSkill" ).html( aPoints.toString() );
$( "td#tableWolfEndurance" ).html( ePoints.toString() );
$( "td#ratio" ).html( ratio.toString() + " / " + randVal.toString() );
// ... code where I process the string index
var eDamage = EnemyDamageTable[eIndex]; // -> problem
var wDamage = WolfDamageTable[wIndex];
var wolfEndurance = ePoints - wDamage;
var enemyEndurance = endurance - eDamage;
var barWidth = ( wolfEndurance / maxEPoints ) * hudBarWidth_HR;
IN_COMBAT = wolfEndurance > 0 && enemyEndurance > 0;
return IN_COMBAT;
}
/*********************************************************************
* custom function to initiate the battle sequence
*********************************************************************/
function LoadBattle()
{
IN_COMBAT = true;
var aPoints = 0;
var ePoints = 0;
var gold = 0;
var name = $( "span#enemyName" ).html();
var skill = $( "span#enemySkill" ).html();
var endurance = $( "span#enemyEndurance" ).html();
if( skill.length == 0 ||
endurance.length == 0 )
{
alert( "Content is not properly formated for combat!" );
return;
}
window.location = "#fight_start";
// Set up the table before showing it
$( "td#tableEnemyName" ).html( name );
$( "td#tableEnemySkill" ).html( skill );
$( "td#tableEnemyEndurance" ).html( endurance );
var keepGoing = true;
while( IN_COMBAT )
{
if( typeof( Storage ) !== "undefined" )
{
aPoints = localStorage.aPoints;
ePoints = localStorage.ePoints;
}
keepGoing = ComputeCombatDamage( aPoints, ePoints, skill, endurance );
//endurance = $( "td#enemyResultEndurance" ).html();
if( keepGoing == false )
{
break;
}
//WaitCombat();
}
}
To me the error seems to come from
var eDamage = EnemyDamageTable[eIndex];
var wDamage = WolfDamageTable[wIndex];
In function ComputeCombatDamage
I've minimized it as much as possible now.
wIndex and eIndex are not defined. I could elaborate more, but that should say it all.

Categories

Resources