containing div does not resize correctly - javascript

On this page, 3 reviews are displayed in a Bootstrap carousel. As you paginate through the reviews, the <div> with the grey background should resize to fit the length of the review. This works reasonably well until you wrap around the end of the review list.
For example, if you use the next button to go forwards through the reviews, then when you go from the last review (#3) to to the first review, a big empty space is left under the first review. Similarly if you use the prev button to go backwards through the reviews, then when you go from the first review to the last (#3), the text of the review overflows the containing div (see screenshot below).
In summary, whenever you wrap around the list of reviews, either by using the prev button to go from #1 to #3 or the next button to go from #3 to #1) the containing div is not correctly resized.
The event handlers that are called when the user paginates through this carousel are at the bottom of the page (reproduced here for convenience):
$(document).ready(function () {
$('#reviewsCarousel').carousel({
interval:null
});
// reviewsCarousel height animation and review counter (set .reviewCount to
// the amount of .item in #reviewsCarousel, on .nextReview or .prevReview button
// clicks: set the carousel-inner class to the animate to the height of the next
// item or the first item if there is no next item, on carousel slide, set the
// reviewIndex class text to the index position of the .active .item)
$("#reviewsCarousel .reviewCount").html($('#reviewsCarousel .item').length);
$("#reviewsCarousel .btn.nextReview").click(function () {
var reviewHeight = $("#reviewsCarousel .item.active").next(".item").height();
if (reviewHeight === undefined) {
var reviewHeight = $("#reviewsCarousel .item").first(".item").height();
}
$("#reviewsCarousel .carousel-inner").animate({"height":reviewHeight + "px"}, 400);
$('#reviewsCarousel').bind('slid', function () {
$("#reviewsCarousel .reviewIndex").html($("#reviewsCarousel .active").index("#reviewsCarousel .item") + 1);
});
});
$("#reviewsCarousel .btn.prevReview").click(function () {
var reviewHeight = $("#reviewsCarousel .item.active").prev(".item").height();
if (reviewHeight === undefined) {
var reviewHeight = $("#reviewsCarousel .item").last(".item").height();
}
$("#reviewsCarousel .carousel-inner").animate({"height":reviewHeight + "px"}, 400);
$('#reviewsCarousel').bind('slid', function () {
$("#reviewsCarousel .reviewIndex").html($("#reviewsCarousel .active").index("#reviewsCarousel .item") + 1);
});
});
});
Here are a couple of screenshots showing the problem:

I tried a little something in the console:
$("#reviewsCarousel .item.active").next(".item").height();
And found out it was null.
if (reviewHeight === undefined) // It's never this.
You never get in the if. undefined !== null :-)
Just use:
if (!reviewHeight)
Any falsey value is good enough.

reviewHeight will never be undefined
USE if (!reviewHeight) insted

Maybe best not to use strict comparison for this if statement. Try instead
if (reviewHeight == undefined)
This also enters the if statement if reviewHeight === null.

Related

Javascript, passing my string as an argument turns it to a 0

I'm using scrollmagic.io and am making an anchor navigation menu. I'm following this tutorial. The scroll works! Except it was scrolling back to the beginning and not to the page it should be at.
Here is my code:
// init controller
var controller = new ScrollMagic.Controller();
// animate scroll instead of a jump
controller.scrollTo(function(target) {
console.log('scroooooll');
console.log('target = '+target); // THIS IS PRINTING 0
console.log(typeof(target));
/* Commenting out what it should do for simplicity. */
});
// scroll action when you click the nav links
$(document).on('click', 'a[href^=#]', function(e) {
var id = $(this).attr('href'); // get the href of clicked link
if ($(id).length > 0) { // not empty links
e.preventDefault(); // prevent normal link action
// this is the function call
console.log('click');
console.log('id = '+id); // IT PRINTS CORRECT HERE
console.log(typeof(id));
controller.scrollTo(id); // scroll on click
// update the URL
if (window.history && window.history.pushState) {
history.pushState("", document.title, id);
}
}
});
And here is the output of my console log:
click
id = #{the-href-value}
string
scroooooll
target = 0
number
My Javascript is pretty rusty, but this doesn't seem right to me. Why is it changing my variable from a string to a 0 when I pass it as a parameter?
From the documents:
"This function will be used for future scroll position modifications.
This provides a way for you to change the behaviour of scrolling and
adding new behaviour like animation. The function receives the new
scroll position as a parameter and a reference to the container
element using this. It may also optionally receive an optional
additional parameter (see below)"
So, the first parameter is passed by controller.
You will get your parameter after that.
http://scrollmagic.io/docs/ScrollMagic.Controller.html#scrollTo
Try printing console.log(args);
controller.scrollTo(function(scrollPos, targetHrefISent) {
console.log('scroooooll');
console.log('target = '+targetHrefISent); // THIS IS PRINTING 0
console.log(typeof(targetHrefISent));
/* Commenting out what it should do for simplicity. */
});

How do I get this If statement to run once until it comes back round (the condition is constantly true until slide changes)

I've created a Flickity slider through Jquery and require a little assitance.
I'm using the selectedIndex as a condition to check what slider is visable. See code below:
$carousel.on( 'select.flickity', function() {
if (flkty.selectedIndex === 0) {
hideAllText();
text0.fadeIn('slow');
}
});
This is saying, when slider 0 (initial slide) fade in var text0.
I want to do this for 6 sliders but as the slide doesn't change until 4 seconds has been the if statement keeps running so it keeps hiding and showing text.
Any ideas how I can make this a one time run until the slide comes round again.
Thanks :)
This should result in the relevant code only being executed once:
text0Shown = false;
$carousel.on('select.flickity', function() {
if (!text0Shown && flkty.selectedIndex === 0) {
text0Shown = true;
hideAllText();
text0.fadeIn('slow');
}
});

jQuery remove class item keeps coming back

Here is the situation.
I'm trying to remove an div class item based when the user clicks on a rating.
The problem I have is that every time I click on the item it goes away, however when I move the mouse the item that I removed comes back.
Here is my current code:
<div class="star_'.($iPos+1).' ratings_stars ratings_vote" onmouseover="overRating(this);" onmouseout="outRating(this);" onClick="selectEmailRating(this);" ></div>
The above item is the div that is calling the JavaScript. When I click on the rating I run the code that is in the following function below:
function selectEmailRating(elem) {
var star = elem;
var rating = widget.data('fsr').rating;
if($(star).attr('class') === 'star_'+ rating + ' ratings_stars ratings_over ratings_vote'){
$(elem).andSelf().removeClass();
$(star).attr('class', 'star_'+ rating + ' ratings_stars');
$(star).attr('class').unbind('onmouseover').unbind('onmouseout');
}
function outRating(elem) {
$(elem).prevAll().andSelf().removeClass('ratings_over');
setRating($(elem).parent());
}
function overRating(elem) {
$(elem).prevAll().andSelf().addClass('ratings_over');
$(elem).nextAll().removeClass('ratings_vote');
}
function setRating(widget) {
var votes = $(widget).data('fsr').rating;
$(widget).find('.star_' + votes).prevAll().andSelf().addClass('ratings_vote');
$(widget).find('.star_' + votes).nextAll().removeClass('ratings_vote');
}
As you see in the code, it is removing the item, however, it is coming back when I move the mouse. Is there a way to make sure when I click on the item to remove it stays removed?
I may be wrong here, but you didn't "bind" the onmouse* events to the element, you added attributes.
You may overwrite the onmouse* attributes with $(elemment).attr('onmouseout', '') or something alike.
and you might want to have a look at https://api.jquery.com/hasclass/
Well I found a solution..
After trying to figure out why the rating keeps coming back, it was the due to the fact that the outRating function was causing the problem. Here is what I did...
The old outRating function:
function outRating(elem) {
$(elem).prevAll().andSelf().removeClass('ratings_over');
setRating($(elem).parent());
}
The new outRating function:
function outRating(elem) {
var star = elem;
var widget = $(elem).parent();
var rating = widget.data('fsr').rating;
$(elem).prevAll().andSelf().removeClass('ratings_over');
if($(star).attr('class') !== 'star_'+ rating + ' ratings_stars') {
setRating($(elem).parent());
}
}

How to save the last hovered state on an HTML element?

I am working on a Wordpress shortcode for generating dynamically circles.
At my current version I have a problem with saving my current and my last hover state.
Here is a fiddle
I have a problem displaying the text under the circles. The text should be displayed from the last hovered circle until I hover over a new one.
Is there maybe a better solution to my problem?
I think my problem is in the hover end.
[...] ,function () {
$contentBoxPrevious = $contentBoxCurrent;
$contentBoxCurrent.removeClass('active-text');
$(this).removeClass('hover active');
}
Move this line
$contentBoxPrevious.removeClass('active-text');
from the handleOut function to the middle of handleIn function like this https://jsfiddle.net/eu0jcmh0/
What you were doing wrong was that you were removing the "active-text" class every time you moused out of the element instead of removed it when you moused on another element, hope I helped!
Your code looked way too complicated...
So I just rewrote it my way to achieve what I think you want as a result.
Here's the code:
$(document).ready(function() {
// Set all texts invisible
$(".text-content").css({
"opacity": 0
});
// Declare previous and active indexes vars
var previous_index;
var active_index;
$(".icon-circle").hover(function() {
// On mouseenter, getting this index.
active_index = $(this).data("index");
// Show associated text.
$(this).parent().find(".text-content").css({
"opacity": 1
});
// Hide previous associated text.
if (active_index != previous_index) {
$("[data-index='" + previous_index + "']").parent().find(".text-content").css({
"opacity": 0
});
}
}, function() {
// On mouseout, just keeping previous index...
previous_index = active_index;
});
});
Working Fiddle.

Target previous element with jQuery

I'm creating portfolio section where every portfolio item shows as an image and every portfolio item has its own div which is hidden and contains more information about that item. When the user clicks on some portfolio item (image) div with more information for that item is shown. Each div with more info has two classes, portf-[nid] and portf ([nid] is Node ID, I work in Drupal and this class with [nid] helps me to target portfolio item with more info div for that item).
Each of the more info divs contains arrows for item listing (next and previous) and I need to get them function, so when the user clicks on previous I need to hide current and show the previous item if it exists(when clicks on next to hide current and show next item if it exists).
My markup looks like:
<div class="portf-3 portf">
//some elements
</div>
<div class="portf-6 portf">
//some elements
</div>
<div class="portf-7 portf">
//some elements
</div>
My question is how to hide the div I'm currently on and show the previous (or next). For example: if it is currently shown div with class portf-6 and user clicks on previous arrow, this div is being hidden and div with class portf-3 is being shown.
It's not the problem to hide/show the div but how to check if there is the div above/below the current div and to target that div above or below the current div?
Here you are:
function GoToPrev()
{
var isTheLast = $('.portf:visible').prev('.portf').length === 0;
if(!isTheLast)
{
$('.portf:visible').hide().prev().show();
}
}
function GoToNext()
{
var isTheLast = $('.portf:visible').next('.portf').length === 0;
if(!isTheLast)
{
$('.portf:visible').hide().next().show();
}
}
To check if prev / next element is present or not, you can make use of .length property as shown below
if($('.portf:visible').prev('.portf').length > 0) // greater than 0 means present else not
same for next element
if($('.portf:visible').next('.portf').length > 0)
As you also need to update the next and previous buttons, I would suggest a more structured approach to the whole thing:
function update(delta) {
var $portfs = $('.portf');
var $current = $portfs.filter(':visible');
var index = $portfs.index($current) + delta;
if (index < 0) {
index = 0;
}
if (index > $portfs.length){
index = $portfs.length;
}
$current.hide();
$portfs.eq(index).show();
$('#prev').toggle(index > 0);
$('#next').toggle(index < $portfs.length-1);
}
$('#prev').click(function () {
update(-1);
});
$('#next').click(function () {
update(1);
});
// Hide all initially
$('.portf').hide();
// Show the first with appropriate logic
update(1);
JSFiddle: http://jsfiddle.net/TrueBlueAussie/xp0peoxw/
This uses a common function that takes a delta direction value and makes the decisions on range capping an when to hide/show the next/previous buttons.
The code can be shortened further, but I was aiming for readability of the logic.
If the next/prev buttons are correctly shown the range checking is not needed, so it simplifies to:
function update(delta) {
var $portfs = $('.portf');
var $current = $portfs.filter(':visible');
var index = $portfs.index($current) + delta;
$current.hide();
$portfs.eq(index).show();
$('#prev').toggle(index > 0);
$('#next').toggle(index < $portfs.length-1);
}
JSFiddle: http://jsfiddle.net/TrueBlueAussie/xp0peoxw/1/

Categories