How to execute jquery when a variable with a CSS property changes - javascript

I need to set the scrollleft back to 0 on my wrapper when a specific css property changes. I'm a bit new to jquery and have never used variables, but I'm assuming that I'll need to declare the somewhat complex variable before the function, and then execute the function when the variable changes. Am I correct? It needs to continually respond like this to resize queries. This will be an epic solution for me if it works!
var changer = $(".dummy").css("float"); //whatever the float property is
$(document).ready(){
$(window).resize(function(){
if ($(".dummy").css("float") != changer ){
$(".wrapper").scrollLeft(0);
}
});

here is my suggestion: Use an ID for "dummy", if you have more than one "dummy" in your dom-tree you get an array with html elements from jquery.
$(document).ready(function() {
// First init for "dummy"
var $dummy = $("#dummy"),
dummyFloat = $dummy.css("float");
$(window).resize(function () {
var dynamicDummyFloat = $dummy.css("float");
if (dynamicDummyFloat != dummyFloat) {
$(".wrapper").scrollLeft(0);
dummyFloat = dynamicDummyFloat;
}
});
});

The code that you have written will work fine.

Related

Reset the initial state of an element after some DOM manimulations (native js)

I want to save the initial state of my Element (with all childs) and after that do some actions ( initialize scrollbar plugin ) and after the window resize event I want to clear these changed values to the saved "pure" element and after that re-initialize the scrollbar plugin (I just want to do a scrollbar element responsive with the different views).
I tried to use .cloneNode(true), jquery.clone(true) and jquery.replaceWith() but it doesn't work for me becase these methods somehow keep all chages that was done before. So I can't get the saved initial HTML.
Should I user outerHTML maybe? Thanks for any help.
var GLOBAL_rawScrollBarNode;
var GLOBAL_scrollBarParent;
$(document).ready(function($){
GLOBAL_rawScrollBarNode = $('#scrollbar3').clone();
GLOBAL_scrollBarParent = $('.portfolio-scroll-box')[0];
portfolioScrollbarOfDeviceWidth();
$(window).resize(function(){
portfolioScrollbarOfDeviceWidth();
});
function portfolioScrollbarOfDeviceWidth() {
var documentWidth = document.documentElement.clientWidth;
//GLOBAL_scrollBarParent.removeChild(document.getElementById('scrollbar3'));
//GLOBAL_scrollBarParent.appendChild(GLOBAL_rawScrollBarNode);
GLOBAL_scrollBarParent.replaceWith(GLOBAL_rawScrollBarNode[0])
var $scrollBarEl = $('#scrollbar3');
setTimeout(() => {
if (documentWidth < 942) {
console.log("XXX")
var bar = $scrollBarEl.tinyscrollbar({ axis: 'x',sizethumb: 135 });
console.log(bar);
} else {
console.log("YYY")
var bar = $scrollBarEl.tinyscrollbar({ axis: 'y',sizethumb: 135 });
console.log(bar);
}
}, 2000)
}
P.S. in case of the outerHTML of the saved ELEMENT and after that assign it like innerHTML to it's parent - it works fine. But I want to know how this issue can be resolved in other more elegant way :)

Changing css based on javascript value fetch from API

I have this code below that returns an updated value from an API every seconds in an html span tag:
$(document).ready(function(){
setInterval(function(){
$.get('https://api.kraken.com/0/public/Ticker?pair=XXBTZEUR', function(data){
var kraken_btc_eur = data.result.XXBTZEUR.c[0]
$("#kraken_btc_eur").text(kraken_btc_eur);
});
}, 1000);
});
How can I change the css of the <span id="kraken_btc_eur"> depending on whether the value of the variable var kraken_btc_eur changes from a prior value.
I figure I must include an IF statement, create a new variable to compare to the old update and clear the variable for this to be executed in the next second again PLUS different ID for up or down. I am not sure how to implement that.
Thanks all for your guidance.
Try something like:
$(function() {
var kraken_btc_eur_old = 0;
setInterval(function(){
$.get('https://api.kraken.com/0/public/Ticker?pair=XXBTZEUR', function(data){
var kraken_btc_eur = data.result.XXBTZEUR.c[0];
if (kraken_btc_eur_old != kraken_btc_eur) {
// Change css
}
kraken_btc_eur_old = kraken_btc_eur;
$("#kraken_btc_eur").text(kraken_btc_eur);
});
}, 1000);
});
Comparing current to new...
Something like:
if(kraken_btc_eur !== $("#kraken_btc_eur").text()) {
// if different change background and add new text
$("#kraken_btc_eur").css('background', 'red').text(kraken_btc_eur);
}
This way you only update if different, no point updating something with the same value

global variable gives "undefined" in jQuery

I have to functions that execute when two different <img> are clicked on. I have to communicate a variable between them.
Getting rid of the irrelevant code, what I have looks something like this:
var size=0;
$('#gallery img').click(function(){
window.size = $('#lightbox img').attr('data-size');
});
$('#lightbox i').click(function(){
var dest=window.size-1;
});
But, when I go to the javascript console, and type size, I get undefined.
Replace
window.size
With
size
because its javascript custom variable not a window object property
EDIT
var size=0;
$('#gallery img').click(function()
{
size = $('#lightbox img').attr('data-size');
});
$('#lightbox i').click(function()
{
var dest = size-1;
alert(dest);
alert(size);
});
above code will alert 0 and -1 if you first click on #ligtbox i now if you first click on #gallery img then it will alert result depending on click you made.
Change
window.size
to
size
and $('#lightbox img').attr('data-size');
to
$('#lightbox img').data('size');

Set onCLick callback inside object?

I have a carousel object, with images and a pager. The problem is I can't set the onClick to the pager. I'm obviously missing something here but I don't know what.
The error when I click in a pager item is:
Uncaught TypeError: Object #<HTMLDivElement> has no method 'scrollCarouselTo'
I set my onclick
carouselDots.on('click',function(){
this.scrollCarouselTo(1,5); // <-- problem lies here, how can i call this method?
});
and the scrollTo method
this.scrollCarouselTo=function(dotIndex, numDots)
{
//H_SCROLL.scrollToElement("#carouselItem"+dotIndex, 300);
H_SCROLL.scrollToPage(dotIndex, 0 , 300);
this.highlightCarouselDot(dotIndex, numDots);
}
Last, on my HTML file this is how I set it:
var tempCarousel = new Carousel();
tempCarousel.initialize(params,cont,scrollContainer);
My Carousel class: (parts of it that i think are relevant)
function Carousel() {
var container;
var pager;
var opt;
var thisCarousel;
//render the correct number of dots and highlight the indexed one
this.highlightCarouselDot=function(dotIndex, numDots)
{
var ui_str="";
console.log("numDots" + numDots);
for (var i=0;i<numDots;i++)
{
if (i==dotIndex)
ui_str+='<div class="carouselDot selected" id="carouselDot'+i+'"></div>';
else
ui_str+='<div class="carouselDot" id="carouselDot'+i+'"></div>';
}
console.log(ui_str);
console.log(pager);
pager.html(ui_str);
var carouselDots = $(pager.selector + " .carouselDot");
var dotSelected = $(pager.selector + " .selected");
carouselDots.css('background',opt.pagerImage);
carouselDots.width(opt.pagerSize);
carouselDots.height(opt.pagerSize);
carouselDots.on('click',function(){ //replace with touch
this.scrollCarouselTo(0,5);
});
dotSelected.css('background',opt.pagerSelectedImage);
}
this.scrollCarouselTo=function(dotIndex, numDots)
{
//H_SCROLL.scrollToElement("#carouselItem"+dotIndex, 300);
H_SCROLL.scrollToPage(dotIndex, 0 , 300);
this.highlightCarouselDot(dotIndex, numDots);
}
}
Thank you!
You are having trouble understanding where the scope is changing in your code. Yes this refers to the object you are in, but when you assign an event handler such as onclick, that function is run in the scope of the UI element that was clicked. This means that in your onclick code, this refers to the html object that was clicked, and not the highlightCarouselDot object.
One common solution to this problem is to use an extra variable to store the value of this.
var self = this;
at the start of your object, that way you can refer to self within your event handlers when you want to refer to the outside object.

How to pass an array to an user defined object or convert non-OO code to OO? javascript

I really have trouble with OO coding in js. I have written a piece of code which rotates through 3 divs, and pauses on hover of any div. This code is just regular js using an array/json as the input. the code is a bit long so sorry about that. I just need some guidance on how I can convert this primitive code to a better form, as in OO and encap. When I tried myself I could not pass the slides array/json to my defined object. Is there a trick or guideline i can follow on how to rewrite this to a better form?
Edit - What is a good guideline to follow so I can rewrite this with objects instead of global variables and loose functions
var slideIndex = 0;
var prevIndex = 0;
var t;
function initPromo(){
sortSlides();
nextPromo();
addListeners();
}
function addListeners(){
for(var i=0; i<slides.length; i++)
$(slides[i].el).hover(function(){ stopPromo(); }, function(){ resumePromo(); });
}
function resumePromo(){ startTimer(); }
function stopPromo(){ clearTimeout(t); }
function nextPromo(){
if(slideIndex > 0 || prevIndex > 0) $(slides[prevIndex].el).css("display","none");
$(slides[slideIndex].el).css("display","block");
prevIndex = slideIndex;
slideIndex = (slideIndex<slides.length-1) ? slideIndex+1 : 0;
startTimer();
}
function startTimer(){ t = setTimeout("nextPromo()", 3000); }
function SortByWeight(a,b) { return b.weight - a.weight; }
function SortByWeightFr(a,b) { return b.frWeight - a.frWeight; }
function sortSlides(){
($("body.en").length > 0) ? slides.sort(SortByWeight) : slides.sort(SortByWeightFr);
}
var slides = [
{
el:'#ps1',
weight:1,
frWeight:3
},
{
el:'#ps2',
weight:0.5,
frWeight:6
},
{
el:'#ps3',
weight:4,
frWeight:9
}
];
window.onload = function () {
initPromo();
};
HTML
<body class="en">
<div id="homepageSlides">
<div id="promoSlides">
<div id="ps1">ps1</div><div id="ps2">ps2</div><div id="ps3">ps3</div>
</div>
</div>
</body>
Edit: Early days in OO coding, not asked in the right way
Well your "plain javascript" code is already taking you part way there. The first function you have defined identies the domain object: Promo.
var Promo = function () { };
You have actions on an instance of promo, init, start, stop, resume, etc. These can be defined on the prototype of Promo.
Promo.prototype.init = function() {
// ...
};
It could get a little annoying typing prototype each time, so we could bundle the prototype into a pointer that allows us a lot easier access...
var Promo = function () { };
(function(obj) {
obj.init = function() {
// ...
};
})(Promo.prototype);
So we've got some structure but we need to now separate concerns. Throughout your plain javascript you've got config type data strewn through the code. It's generally a good idea to isolate these bits of data to a single entry point for your object.
obj.init = function(_el) {
// where _el is the base element of this widget
};
I see you're also using jQuery which is good because it gives you a lot of power. One convention I like to use is instead of passing a huge amount of config data into a given widget, I like to give my objects minimal config and let them inspect the HTML to determine additional configuration data. This has the added advantage of if you wanted to add slides in the future or otherwise make changes to the slide content you need'nt worry about changing the JS.
Let's say we were to alter the slide HTML to look like...
<div id="promoSlides">
<div data-type="slide" data-slide-id="1">ps1</div>
<div data-type="slide" data-slide-id="2">ps2</div>
<div data-type="slide" data-slide-id="3">ps3</div>
</div>
Using jQuery we could identify how many slides are present.
obj.init = function(_el) {
this.baseElement = $(_el);
this.slides = this.baseElement.find('*[data-type="slide"]');
};
Now we're passing in minimal config, we've separated out the identification of the slides to the HTML, and we've got a nice pattern for a self-sufficient object. The rest would be to fill in the details (totally untested, but something like this)...
var Promo = function () { };
(function (obj) {
obj.init = function(_el, _delay) {
// Initialize markup
this.baseElement = $(_el);
this.slides = this.baseElement.find('*[data-type="slide"]');
this.slideDelay = _delay;
// Sort slides
// (not sure what's going on here)
// Bind events
this.baseElement
.on('mouseenter', this.stop.bind(this))
.on('mouseleave', this.start.bind(this));
};
obj.start = function() {
this.timer = setInterval(this.advance.bind(this), this.slideDelay);
};
obj.stop = function() {
clearInterval(this.timer);
};
obj.advance = function() {
// Slide the visible slide off screen
// (note: the parent tag will need overflow:hidden)
var visible = this.baseElement.find('*[data-type="slide"]:visible');
visible.animate({ left: '-' + (visible.width()) + 'px' }, 1000);
// Slide the next slide in
var next = visible.next();
next.css('left', this.baseElement.width() + 1).animate({ left: '0' }, 1000);
};
})(Promo.prototype);
Note that I made use of bind which isn't supported yet in older versions of IE.
Its not the converting to object oriented style what is needed for that code there.
Here are issues i see there:
pollution of global scope
mixing fixed CSS rules with Javascript
use of .length attribute within a loop
no event delegation
misplacement of <script> tag, resulting in use of window.onload
creating new jQuery object when it is not needed
use of CSS3 selectors in jQuery calls
no clue how to use setTimeout()
tight coupling to HTML ( id on each slide )

Categories