Using .width() returns undefined - javascript

I'm currently building a script to create a slider and stumbled upon an error I can't seem to solve. Basically I trying to get the width of a container and multiply it base on the number of slides inside.
Here is a snippet a of the code I'm working on. Whenever I try to use .width in order to fetch the width of a container it returns undefined on the console. I tried looking back and forth on my code but I can't seem to pinpoint the issue.
_setSliderWidth() {
this.sliderBanner = this.$el.find('.slider-banner');
this.sliderBannerWidth = this.sliderBanner.width();
console.log(this.sliderBannerWidth);
this.slides.width(this.sliderBannerWidth);
this.slidesContainer.width(this.sliderBanner.width() * this.slideCount);
}
-- -- -- -- --
'use strict';
(function($) {
/**
* Base Image Slider class
*/
class ImageSlider {
constructor(el) {
this.$el = $(el);
this._dom();
this.slideCount = this.slides.length;
this.currentSlide = 0;
this.arrows = {
prev: this.$el.find('.arrow.-prev'),
next: this.$el.find('.arrow.-next')
};
// image formatting and detection
this.$el.find('img').each(function(e, el) {
let $img = $(el);
if ($img.height() > $img.width())
$img.addClass('-portrait');
});
this._setSliderWidth();
}
_dom() {
this.slides = this.$el.find('.slides');
this.slidesContainer = this.$el.find('.slider-items');
}
init() {
this._bind();
this._evaluatePosition();
}
_bind() {
this.arrows.next.on('click', this._nextSlide.bind(this));
this.arrows.prev.on('click', this._prevSlide.bind(this));
}
_nextSlide() {
this.currentSlide++;
this._moveSlide();
}
_prevSlide() {
this.currentSlide--;
this._moveSlide();
}
_setSliderWidth() {
this.sliderBanner = this.$el.find('.slider-banner');
this.sliderBannerWidth = this.sliderBanner.width();
console.log(this.sliderBannerWidth);
this.slides.width(this.sliderBannerWidth);
this.slidesContainer.width(this.sliderBanner.width() * this.slideCount);
}
_moveSlide() {
// set the min and max range
if (this.currentSlide < 0) this.currentSlide = 0;
if (this.currentSlide > this.slideCount - 1) this.currentSlide = this.slideCount - 1;
this._evaluatePosition();
this._move();
}
_move() {
let position = this.currentSlide * -100;
this.slidesContainer.css({
transform: 'translate(' + position + '%, 0)'
});
}
_evaluatePosition() {
this.arrows.prev.toggleClass('-hide', (this.currentSlide === 0));
this.arrows.next.toggleClass('-hide', (this.currentSlide === this.slideCount - 1));
}
}
$(document).ready(function() {
//--------------------------------------------------
// Image Slider
let $imageSliders = $('.image-slider');
$imageSliders.each(function(e, el) {
let imageSlider = new ImageSlider(el);
imageSlider.init();
});
//--------------------------------------------------
// Slider Banner
let $bannerSliders = $('.slider-banner');
$bannerSliders.each(function(e, el) {
let bannerSlider = new ImageSlider(el);
bannerSlider.init();
});
});
})(jQuery);
HTML
<div class="slider-banner -alternate">
<span href="#" class="arrow -prev -hide"></span>
<span href="#" class="arrow -next"></span>
<div class="slider-items">
<div class="slides">
<div class="image" style="background-image:url(/iom/sites/default/files/2018-07/partnerships-2_0.jpg)">
<div class="banner-detail">
<div class="article-detail">
<div class="timestamp">
page
</div>
<h2 class="title">
Migrant Integration
</h2>
<div class="mini-caption">
IOM supports policies and strategies that promote the social, economic and cultural inclusion of migrants within existing legal frameworks in countries of destination.
</div>
More Details
</div>
</div>
</div>
</div>
<div class="slides">
<div class="image" style="background-image:url(/iom/sites/default/files/2018-07/definitional-issues_1.jpg)">
<div class="banner-detail">
<div class="article-detail">
<div class="timestamp">
page
</div>
<h2 class="title">
Forum on Migration, Trade and the Global Economy
</h2>
<div class="mini-caption">
IOM, together with partners ICTSD and FundanciĆ³n Foro del Sur will host the Forum on Migration, Trade & the Global Economy in Buenos Aires on 14 December.
</div>
More Details
</div>
</div>
</div>
</div>
<div class="slides">
<div class="image" style="background-image:url(/iom/sites/default/files/2018-07/identity-management_0.jpg)">
<div class="banner-detail">
<div class="article-detail">
<div class="timestamp">
page
</div>
<h2 class="title">
Comparative Research on the Assisted Voluntary Return and Reintegration of Migrants
</h2>
<div class="mini-caption">
Assisted Voluntary Return and Reintegration (AVRR) is an indispensable part of a comprehensive approach to migration management aiming at orderly and humane return and reintegration of migrants.
</div>
More Details
</div>
</div>
</div>
</div>
</div>
</div>

It seems from your screenshots and code that the this. sliderBanner object does NOT return a DOM object and thus the .width() would be undefined.
To resolve you can:
1) Retrieve the DOM object through a weird method of this.sliderBanner.prevObject. More information in this thread: What is prevObject and why is my selector returning that?
The main problem is that the .find from the $el object can't doesn't have the slider banner object within it's DOM, so...
2) Try using this.sliderBanner = $(".slider banner") to select the banner from the document object instead

Related

Iterate through multiple parent divs (with same class) to access the child divs inside (same class) using Javascript

I am trying to iterate through the parent class "cardTags" to change the background color of each child div "tag" depending on what the value is (using .textContent)
For HTML I have:
<div class = 'card'>
<div class='cardTags'>
<div class='tag' id='tag1'>
<header> Auction </header>
</div>
<div class='tag' id='tag2'>
<header> 3d 40m 23s left </header>
</div>
<div class='tag' id='tag3'>
<header> $39 </header>
</div>
</div>
</div>
<div class = 'card'>
<div class='cardTags'>
<div class='tag' id='tag1'>
<header> Sell </header>
</div>
<div class='tag' id='tag2'>
<header> Used </header>
</div>
<div class='tag' id='tag3'>
<header> $59 </header>
</div>
</div>
</div>
For Javascript
function checkTags() {
var category = document.getElementById('tag1');
var condition = document.getElementById('tag2');
var specialty = document.getElementById('tag3');
var textCategory = category.textContent;
var textCondition = condition.textContent;
var textSpecialty = specialty.textContent;
if (textCategory = "Auction") {
category.style.backgroundColor = "#00FF00";
} else if (textCategory = "Trade" {
category.style.backgroundColor = "#00FF00";
} else {
category.style.backgroundColor = "#00FF00";
}
if (textCondition.length = 'Used') {
condition.style.backgroundColor = '#f75555';
} else if (textCondition = 'New') {
condition.style.backgroundColor = '#2fb62f';
} else {
condition.style.backgroundColor = '#f9f906';
}
}
I know the javascript above will only look at 1 div "cardTags" not all the other ones, which is why I am trying to know how can I iterate through each "cardTags" div and see the child divs inside and change the background colors of those divs depending on the values within them. Currently javascript only recognizes one set.
1. id attributes should be unique, currently you have the same id on more than one child element of the parent divs. So you should use the shared className for the children.
2. I modified the classNames of each child tag to be tag1, tag2, tag3, respectively on each set of children.
3. You had some typo's or badly formatted code as well, where you were missing a parenthesis on one of your else-if statements.
4. You were assigning values instead of doing equality comparison in your if and else-if, so I fixed that as well.
5. Also, you were attempting to do comparison of string values and the text content of the headers had leading and trailing space, so I added the trim() function on each call to textContent to remove the extra whitespace for equality comparison.
6. You also had one string comparison where you had appended .length at the end of the string variable, which was causing issues as well.
7. Please see the following for a working example:
window.addEventListener("DOMContentLoaded", () => {
checkTags();
});
function checkTags() {
//get the parents
const parents = document.querySelectorAll('div.cardTags');
parents.forEach((el) => {
const category = el.querySelector('div.tag1');
const condition = el.querySelector('div.tag2');
const specialty = el.querySelector('div.tag3');
const textCategory = category.querySelector('header').textContent.trim();
const textCondition = condition.querySelector('header').textContent.trim();
const textSpecialty = specialty.querySelector('header').textContent.trim();
if (textCategory === "Auction") {
category.style.backgroundColor = "#00FF00";
} else if (textCategory === "Trade") {
category.style.backgroundColor = "#00FF00";
} else {
category.style.backgroundColor = "#00FF00";
}
if (textCondition === 'Used') {
condition.style.backgroundColor = '#f75555';
} else if (textCondition === 'New') {
condition.style.backgroundColor = '#2fb62f';
} else {
condition.style.backgroundColor = '#f9f906';
}
});
}
<div class = 'card'>
<div class='cardTags'>
<div class='tag1'>
<header> Auction </header>
</div>
<div class='tag2'>
<header> 3d 40m 23s left </header>
</div>
<div class='tag3'>
<header> $39 </header>
</div>
</div>
</div>
<div class = 'card'>
<div class='cardTags'>
<div class='tag1'>
<header> Sell </header>
</div>
<div class='tag2'>
<header> Used </header>
</div>
<div class='tag3'>
<header> $59 </header>
</div>
</div>
</div>

Creating a div slider in jquery

I am trying to make an image change when I click on a piece of text on a website that I am building.
At this moment I have created a class called device with one of them being device active as shown below:
<div class="col-md-3">
<div class="device active">
<img src="app/assets/images/mockup.png" alt="">
</div>
<div class="device">
<img src="app/assets/images/mockup.png" alt="">
</div>
<div class="device">
<img src="app/assets/images/mockup.png" alt="">
</div>
</div>
And then what i am currently trying to do is remove the class of active when I click on some text with the i.d of #search2. This is my whole jquery script so far:
$("#search2").click(function() {
var currentImage = $('.device.active');
var nextImage = currentImage.next();
currentImage.removeClass('active');
});
However this does not seem to remove the class of active and the image is still displayed? any ideas?
Your selection is done right and it is working for me (the active class is removed from that item). The problem must be somewhere else in your code.
Here is an alternative:
var activeDeviceIndex = 0;
$("#search2").click(function() {
var devicesContainer = $('.device');
$(devicesContainer[activeDeviceIndex]).removeClass('active');
activeDeviceIndex === devicesContainer.length - 1 ? activeDeviceIndex = 0 : activeDeviceIndex++;
$(devicesContainer[activeDeviceIndex]).addClass('active');
});
.device {
display: none;
}
.device.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-md-3">
<div class="device active">
<p>Device 1</p>
</div>
<div class="device">
<p>Device 2</p>
</div>
<div class="device">
<p>Device 3</p>
</div>
</div>
<button id="search2">click</button>
Check on the following, the id on the button to click should be search2 and not #search2, may be just typo stuffs.
after that update your code as follows
/**
*#description - gets the next image to slide, if the last image is the current image, it will loop the sliding
*#param {Element} current - the currently active image
*#param {Boolean} islooped - boolean value indicating if a looping just started
*/
var nextImage = function(current, islooped) {
var next = islooped? current : current.nextSibling;
while(next && next.nodeName.toLowerCase() !== 'div') {
next = next.nextSibling;
}
next = next? next : nextImage(current.parentNode.firstChild, true);
return next;
};
$('#search2').bind('click', function(event) {
var current = $('.device.active').removeClass('active').get(0);
var next = nextImage(current, false);
$(next).addClass('active');
});

Cutting down to 20 words with HTML content using JS and VueJS?

I am creating a news feed with VueJS and I have run into a bit of a problem with rendering the content. The API I am using sadly I am unable to change to suit my need properly at this time. The API gives me all the content already in HTML tags and it can also include images and lists and all the other basics. What I want to do is create a "read more" section which will render the first 20 words if just the text of the first "p" tag and stop there.
Does anyone know a quick and efficient way of doing this with JS?
My current display VueJS render is the following:
<div v-for="news_item in news_items">
<div v-bind:class="{ 'col-md-4': display}">
<div class="card">
<div class="header">
<h2>
{{news_item.title}} <small>{{news_item.subtitle}}</small>
</h2>
</div>
<div class="body" style="padding-top: 0">
<div class="row" style="margin-right: -20px; margin-left: -20px;">
<div class="col-md-12"
style="padding-left: 0px; padding-right: 0px;">
<img :src="news_item['thumbnail']"
class="img-responsive smaller-img" alt=""
style=" margin: 0 auto; max-height: 250px;">
</div>
</div>
<div class="row">
<div class="col-md-12">
<div v-html="news_item.content"></div>
</div>
</div>
</div>
</div>
</div>
</div>
This is the perfect time to use a directive:
https://v2.vuejs.org/v2/guide/custom-directive.html
See the codepen here: https://codepen.io/huntleth/pen/GOXaLo
Using the trim directive, you can change the content of the element. In the example above, it will show the first 5 words followed by an ellipsis.
If you're just after a pure js solution, this should do it:
var resultString = str.split(' ').slice(0, 20).join(" ");
You could use the trim directive and search the el for any p tags, and then change their content accordingly.
You don't appear to have tried anything yet, so I'll just give you these pointers. If you run into specific problems, ask again.
Make a component
The component should receive the html as a prop
The component should have a data item to control whether it is expanded
The component should have a computed that gets the first 20 words of the first paragraph tag. You can use textContent to get text from an HTML node.
The computed is the most likely part to pose a challenge. It will look something like this
blurb() {
const div = document.createElement('div');
div.innerHTML = this.content; // this.content is the prop
const firstP = div.querySelector('p');
const text = firstP.textContent;
const match = text.match(/(\S+\s*){0,20}/);
return match[0];
}
Rough implementation, Pure Js approach
document.getElementById("addContent").onclick = display;
document.getElementById("ellipsAnchor").onclick = hideEllipsis;
function display() {
document.getElementById("instruction").classList+= " hide";
let content = document.getElementById("inputbox").value;
if(content.length > 30) {
let sliced = content.slice(30);
let unsliced = content.substring(0,29);
let spantag = document.createElement("span");
spantag.className = "toReplace hide"
let text = document.createTextNode(sliced);
spantag.appendChild(text);
let spantag1 = document.createElement("span");
let text1 = document.createTextNode(unsliced);
spantag1.appendChild(text1);
let contentTag =document.getElementById("content");
contentTag.appendChild(spantag1)
contentTag.appendChild(spantag)
document.getElementById("ellipsis").classList -= "hide";
}
}
function hideEllipsis(){
document.getElementById("ellipsis").classList += " hide";
document.querySelectorAll("span.hide")[0].classList -= " hide"
}
.hide {
display : none;
}
<textarea type="text" id="inputbox"></textarea>
<button id="addContent">
Show content
</button>
<div id="content">
</div>
<div class="hide" id="ellipsis">
Read More..
</div>
<div id="instruction">
Type more than 30 characters and click show content
</div>
You can write a vue directive to solve this.
Set max-height to the div.
count the words and append "Read more.." link to the content.
Add a click event to 'read more' to expand the DIV to full height.
For example see this codepen
let handler = ""
Vue.directive("viewmore", {
inserted: function (el, binding){
let maxlines = binding.value
let lineheight = parseFloat(getComputedStyle(el).lineHeight)
let paddingtop = parseFloat(getComputedStyle(el).paddingTop)
let lines = (el.clientHeight) / lineheight ;
let maxheight = (lineheight * maxlines) + paddingtop + (lineheight/5)
if(lines>maxlines){
el.classList.add('vmore')
el.style.maxHeight = maxheight + 'px'
el.addEventListener('click', handler = ()=> {
el.style.maxHeight = ""
el.scrollIntoView({behavior: "smooth"})
el.removeEventListener('click', handler)
el.classList.remove('vmore')
})
}
},
unbind: function (el, binding) {
el.removeEventListener('click', handler)
handler = ""
}
});
https://codepen.io/dagalti/pen/vPOZaB .
it works based on the lines in the content.
Code : https://gist.github.com/dagalti/c8fc86cb791a51fe24e5dc647507c4a3
Expanding on the answers by tom_h and Roy J, here's what I'm using in my vue application to make the ellipsis clickable:
Vue.component("ellipsis", {
template: "#ellipsis-template",
props: ['content'],
data: function() {
return {
wordLength: 3, // default number of words to truncate
showAll: false
}
}
});
<script type="text/x-template" id="ellipsis-template">
<span v-if="content.split(' ').length>wordLength && showAll">{{content}}
(less)
</span>
<span v-else-if="content.split(' ').length>wordLength && !showAll">
{{content.split(" ").slice(0,wordLength).join(" ")}}
...
</span>
<span v-else>{{content}}</span>
</script>
To call it:
<ellipsis :content="someData"></ellipsis>

Filtering based on two conditions

I have eight cards with two parameters on each of them. The first parameter is year (2011, 2012, 2013, 2014), the second is category (studio, house, personal, commercial). It looks like this:
Studio 2011
House 2012
Commercial 2013
Personal 2012
Studio 2014
Commercial 2011
House 2014
Personal 2013
I need to sort them out, making needed cards bright, and not needed faded. By default all of them are bright. HTML:
<div class="card card-studio card-2011 card-bright">Studio 2011</div>
<div class="card card-house card-2012 card-bright">House 2012</div>
<div class="card card-commercial card-2013 card-bright">Commercial 2013</div>
<div class="card card-personal card-2012 card-bright">Personal 2012</div>
<div class="card card-studio card-2014 card-bright">Studio 2014</div>
<div class="card card-commercial card-2011 card-bright">Commercial 2011</div>
<div class="card card-house card-2014 card-bright">House 2014 </div>
<div class="card card-personal card-2013 card-bright">Personal 2013</div>
I add buttons with years:
2011
2012
2013
2014
When user clicks a year button, we take cards with needed year class and remove their "bright/faded" classes just in case. Then we add "bright" class to these cards. Then we take all the cards that do not have needed year and add them "faded" class (also removing previous classes just in case). And we also make the button underlined, and its siblings not underlined. It all looks like this:
$(".button").on("click", function(event){
event.preventDefault();
if($(this).hasClass("button-2011")){
$(".card-2011").removeClass("card-bright card-faded").addClass("card-bright");
$(".card").not(".card-2011").removeClass("card-bright card-faded").addClass("card-faded");
$(this).siblings().removeClass("button-active").end().addClass("button-active");
}
JSfiddle: https://jsfiddle.net/6vLzyowc/
Now it all seems simple, but trouble comes up when I try to add the second sorting condition, category.
On the one hand, I certainly need to do the same thing, as in the first case, i. e. make needed category bright, not needed faded:
if($(this).hasClass("button-house")){
$(".card-house").removeClass("card-bright card-faded").addClass("card-bright");
$(".card").not(".card-house").removeClass("card-bright card-faded").addClass("card-faded");
}
But it will make "bright" all cards with the needed category, and I also have the previous year sorting results. It seems that I need to sort them out first. So, I take the first year sorting results (i. e. "bright" cards) and make ones without needed category "faded":
if($(this).hasClass("button-house")){
$(".card-bright").not("card-house").addClass("card-faded");
}
It helps a little, but I still don't know how I can add the remaining cards with needed category now, so that both conditions are satisfied. So, how can I combine sorting previous sorting results and sorting all the items?
Fiddle with all the buttons: https://jsfiddle.net/hm1emr8p/
I think your approach is a bit over-complicated. The following works for any number of filters. The trick is to keep state of what is selected, and on any change just re-apply this state to the card-elements.
(function () {
var active = [];
$('.filter').each(function (idx, el) {
var $el = $(el);
active.push('');
$el.on('click', '.button', function () {
var $this = $(this);
active[idx] = $this.data('toggle');
$el.find('.button').removeClass('button-active');
$this.addClass('button-active');
update();
});
});
function update()
{
var a = active.join('');
if (a.length === 0) {
$('.card').removeClass('card-faded');
}
else {
$('.card').addClass('card-faded').filter(active.join('')).removeClass('card-faded');
}
}
})();
a {
text-decoration: none;
color: black;
}
.buttons {
margin-top: 40px;
}
.time {
margin-bottom: 20px;
}
.card-faded {
opacity: 0.3;
}
.button-active {
text-decoration: underline;
}
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
<div class="card card-2011 card-studio">Studio 2011</div>
<div class="card card-2012 card-house">House 2012</div>
<div class="card card-2013 card-commercial">Commercial 2013</div>
<div class="card card-2012 card-personal">Personal 2012</div>
<div class="card card-2014 card-studio">Studio 2014</div>
<div class="card card-2011 card-commercial">Commercial 2011</div>
<div class="card card-2014 card-house">House 2014 </div>
<div class="card card-2013 card-personal">Personal 2013</div>
<div class="buttons">
<div class="filter time">
<a class="button button-2011" data-toggle=".card-2011">2011</a>
<a class="button button-2012" data-toggle=".card-2012">2012</a>
<a class="button button-2013" data-toggle=".card-2013">2013</a>
<a class="button button-2014" data-toggle=".card-2014">2014</a>
<a class="button button-all button-active" data-toggle="">All time</a>
</div>
<div class="filter category">
<a class="button button-studio" data-toggle=".card-studio">Studio</a>
<a class="button button-house" data-toggle=".card-house">House</a>
<a class="button button-commercial" data-toggle=".card-commercial">Commercial</a>
<a class="button button-personal" data-toggle=".card-personal">Personal</a>
<a class="button button-all button-active" data-toggle="">All</a>
</div>
</div>
I suggest saving the selected category and the selected timespan in variables:
var lastCategory = '';
var lastYear = '';
In your case you can use data- attributes to store information like this:
2011
and:
Studio
And perform actions based on the value of the data element in your click handler:
$(".category > .button").on("click", function(event){
event.preventDefault();
var tmpCat = $(this).data('cat');
lastCategory = tmpCat;
$(".card").removeClass("card-faded");
if (tmpCat == 'all') {
if (lastYear == 'alltime') {
$(".card").addClass("card-faded");
} else {
$(".card-"+lastYear).addClass("card-faded");
}
} else {
if (lastYear == 'alltime') {
$(".card-" + tmpCat).addClass("card-faded");
} else {
$(".card-" + tmpCat + ".card-"+lastYear).addClass("card-faded");
}
}
$(this).siblings()
.removeClass("button-active")
.end()
.addClass("button-active");
});
$(".time > .button").on("click", function(event){
event.preventDefault();
var tmpYear = $(this).data('year');
lastYear = tmpYear;
$(".card").removeClass("card-faded");
if (tmpYear == 'alltime') {
if (lastCategory == 'all') {
$(".card").addClass("card-faded");
} else {
$(".card-" + lastCategory).addClass("card-faded");
}
} else {
if (lastCategory == 'all') {
$(".card-" + tmpYear).addClass("card-faded");
} else {
$(".card-" + lastCategory + ".card-"+tmpYear).addClass("card-faded");
}
}
$(this).siblings()
.removeClass("button-active")
.end()
.addClass("button-active");
});
There a zillion ways that lead to rome, this is not ideal, but try to avoid if (1) then, if (2) then, if (3) then, etc.... code. I forked your fiddle and made a working demo.

jquery .each() only doing last element

I am having problems with this function not running correctly... it only makes the last Element have the box appear.
NOTES: <aside> is position: fixed; and I do know this is not a "Proper" use of <article> tags, but it helps me to differentiate them for now.
HTML:
<aside class="character">
<div class="personHolder">
<div class="person"></div>
</div>
<div class="arrow_box"></div>
</aside>
<main class="main">
<section class="sections" id="Home">
<article class="article1">
<h1 class="sectionHeaders">Home</h1>
</article>
</section>
<section class="sections" id="About">
<article class="article2">
<h1 class="sectionHeaders">About Me</h1>
</article>
</section>
<section class="sections" id="Projects">
<article class="article3">
<h1 class="sectionHeaders">Projects</h1>
</article>
</section>
<section class="sections" id="Contact">
<article class="article3">
<h1 class="sectionHeaders">Contact Me</h1>
</article>
</section>
</main>
JavaScript/JQuery:
function checkElement() {
var article1 = $(".article1");
var article2 = $(".article2");
var article3 = $(".article3");
var article4 = $(".article4");
var arrowTop = 170;
var arrowBottom = 258;
var articles = [article1, article2, article3, article4];
$.each(articles, function(index, value) {
if(value.offset().top < arrowTop &&
value.offset().top + value.height() > arrowBottom) {
$(".arrow_box").show();
} else {
$(".arrow_box").hide();
}
});
}
The following is the best thing I can do to a Fiddle, as I cannot make the fiddle work correctly... (Sorry)
Free Website Host
I have tried the below before as well.
$("article").each(function() {
if(this.offset().top < arrowTop &&
this.offset().top +
this.height() > arrowBottom) {
$(".arrow_box").show();
} else {
$(".arrow_box").hide();
}
});
FINAL SOLUTION:
var showing = false;
$("article").each(function() {
if (showing) return;
if($(this).offset().top < arrowTop &&
$(this).offset().top +
$(this).height() > arrowBottom) {
$(".arrow_box").show();
showing = true;
} else {
$(".arrow_box").hide();
}
});
It seems like you are saying that each article has its own arrow box.
In your function, you will check the offset of all articles, but the $(".arrow_box") selector will be the same for all articles, so you will hide/show it only depending on the last articles offset.
I dont know your HTML tree, but try to change the selector to something like
value.closest(".arrow_box").show();
Update
You want to cancel the each() once you have found an article in range. This can be done like this for instance:
var showing = false;
$("article").each(function() {
if (showing) return;
if(this.offset().top < arrowTop &&
this.offset().top +
this.height() > arrowBottom) {
$(".arrow_box").show();
showing = true;
} else {
$(".arrow_box").hide();
}
});

Categories

Resources