javascript onclick, anonymous function - javascript

I am a beginning javascript programmer. I am trying to create something similar to Lightbox 2, but much simpler. The only reason why I want to do it from scratch on my own is so that I can learn. However, I've been stuck on the last critical part where it displays the image. I believe the problem lies where I try to use onclick with assignment to an anonymous function:elem[i].onclick = function (){liteBoxFocus(imgSource,imgTitle); return false;};
. If you run my code and try clicking on the google logo it'll bring up the yahoo logo and title instead of google's logo and title. However when you click on the yahoo logo it works fine so it seems that the anonymous function only holds for the last loop. Thanks in advance!!!
I have placed the entire CSS/JS/XHTML in one page for your convenience.
<html>
<head>
<title>Erik's Script</title>
<style type="text/css">
#liteBoxBg, #liteBox {
display: none;
}
#liteBoxBg {
background-color: #000000;
height: 100%;
width:100%;
margin:0px;
position: fixed;
left:0px;
top: 0px;
filter:alpha(opacity=80);
-moz-opacity:0.8;
-khtml-opacity: 0.8;
opacity: 0.8;
z-index: 40;
}
#liteBox {
background-color:#fff;
padding: 10px;
position:absolute;
top:10%;
border: 1px solid #ccc;
width:auto;
text-align:center;
z-index: 50;
}
</style>
<script type="text/javascript">
window.onload = start;
function start(){
var imgTitle = "No title";
var imgSource;
var elem = document.getElementsByTagName("a");
var i;
//Dynamically insert the DIV's to produce effect
var newDiv = document.createElement('div');
newDiv.setAttribute("id", "liteBox");
document.getElementsByTagName("body")[0].appendChild(newDiv);
newDiv = document.createElement('div');
newDiv.setAttribute("id", "liteBoxBg");
document.getElementsByTagName("body")[0].appendChild(newDiv);
//Check those anchors with rel=litebox
for(i = 0;i < elem.length;i++){
if(elem[i].rel == "litebox"){
imgSource = elem[i].href.toString();
imgTitle = elem[i].title;
elem[i].childNodes[0].style.border="0px solid #fff";
elem[i].onclick = function (){liteBoxFocus(imgSource,imgTitle); return false;};
}
}
//When foreground is clicked, close lite box
document.getElementById("liteBoxBg").onclick = liteBoxClose;
}
//Brings up the image with focus
function liteBoxFocus(source,title){
document.getElementById("liteBox").style.display = "block";
document.getElementById("liteBox").innerHTML = "<h1>" + title + "</h1>" +
"<img src='" + source + "'/><br />" +
"<a href='#' onclick='liteBoxClose();'><img src='images/litebox_close.gif' border='0' alt='close'/></a>";
document.getElementById("liteBoxBg").style.display = "block";
}
//closes lite box
function liteBoxClose(){
document.getElementById("liteBox").style.display = "none";
document.getElementById("liteBoxBg").style.display = "none";
return false;
}
</script>
</head>
<body>
<img src="http://www.google.com/intl/en_ALL/images/logo.gif" alt="" />
<a href="
http://www.barbariangroup.com/assets/users/bruce/images/0000/4121/yahoo_logo.jpg" rel="litebox" title="Yahooo Logo"><img src="
http://www.barbariangroup.com/assets/users/bruce/images/0000/4121/yahoo_logo.jpg" alt="" /></a>
</body>
</html>

Your event handlers form a closure that remember a "live" pointer to the variables in the enclosing scope. So when they are actually executed, they have the last value imgSource and imgTitle had.
Instead, you can use this pattern to localize the variable values. This will create copies of source and title inside getClickHandler each time it is called. The returned function hence remembers the values in that iteration of the loop.
//Check those anchors with rel=litebox
for(i = 0;i < elem.length;i++){
if(elem[i].rel == "litebox"){
imgSource = elem[i].href.toString();
imgTitle = elem[i].title;
elem[i].childNodes[0].style.border="0px solid #fff";
elem[i].onclick = getClickHandler(imgSource, imgTitle);
}
}
//Brings up the image with focus
function getClickHandler(source,title){
return function() {
document.getElementById("liteBox").style.display = "block";
document.getElementById("liteBox").innerHTML = "<h1>" + title + "</h1>" +
"<img src='" + source + "'/><br />" +
"<a href='#' onclick='liteBoxClose();'><img src='images/litebox_close.gif' border='0' alt='close'/></a>";
document.getElementById("liteBoxBg").style.display = "block";
}
}

Related

Show Hidden Text in DIV on Hover

The desired effect is to have hidden text within a table cell show the full text across the cell when user hovers the mouse cursor over the text. See link to problem diagram to see what I mean. The "solution" denotes the desired effect while "problem" denotes what the code is currently doing. Much appreciated for the assistance.
var jobSourceID = 'jobSource' + jobIndex;
jobSource.innerHTML = '<div id="' + jobSourceID + '">' + jobSourceValue + '</div>';
document.getElementById(jobSourceID).style.marginLeft = '3px';
document.getElementById(jobSourceID).style.maxWidth = '55px';
document.getElementById(jobSourceID).style.overflow = 'hidden';
document.getElementById(jobSourceID).style.textOverflow = 'ellipsis';
document.getElementById(jobSourceID).style.whiteSpace = 'nowrap';
document.getElementById(jobSourceID).addEventListener('mouseover', function () {
document.getElementById(jobSourceID).style.overflow = 'visible';
document.getElementById(jobSourceID).style.backgroundColor = '#555555';
});
document.getElementById(jobSourceID).addEventListener('mouseout', function () {
document.getElementById(jobSourceID).style.overflow = 'hidden';
document.getElementById(jobSourceID).style.backgroundColor = '';
});
You can set 'jobSourceID' width as auto on mouseover function.
document.getElementById(jobSourceID).style.width = "auto";
If your problem ist just the styling of the background, you can style a SPAN inside the DIV and hide this instead of only the text.
document.body.innerHTML = '<div id="' + jobSourceID + '"><span>' + jobSourceValue + '<span></div>';
document.getElementById(jobSourceID).style.marginLeft = '3px';
document.getElementById(jobSourceID).style.maxWidth = '55px';
document.getElementById(jobSourceID).style.overflow = 'hidden';
document.getElementById(jobSourceID).style.textOverflow = 'ellipsis';
document.getElementById(jobSourceID).style.whiteSpace = 'nowrap';
document.getElementById(jobSourceID).addEventListener('mouseover', function () {
document.getElementById(jobSourceID).style.overflow = 'visible';
document.getElementById(jobSourceID).children[0].style.backgroundColor = '#555555';
});
document.getElementById(jobSourceID).addEventListener('mouseout', function () {
document.getElementById(jobSourceID).style.overflow = 'hidden';
document.getElementById(jobSourceID).children[0].style.backgroundColor = '';
});
You can do it like this:
*{
padding:0;
margin: 0;
}
td{
overflow:hidden;
}
td div{
background-color: #ccc;
width:50px;
}
td:hover{
overflow: inherit
}
td:hover div{
width:100%;
}
<table>
<tr>
<td>
<div>
asadgshfdadgfhgdgjgsfgfadsfahgdafgerre
</div>
</td>
</tr>
</table>
After trying all the suggested solutions posted, I see that none of them solves the problem I described in my post diagram. However, I did some more searching and after googling "html tooltips" I found some good articles explaining the concept such that tooltips was the solution I needed. So I managed to get this problem fixed on my own to my satisfaction.

Javascript Can Push() and Pop() and Image Replacement Work within an Array

Can Push() and Pop() and Image Replacement Work within an Array?
8th Gr math teacher attempting to create a slide show of question images that pop() and push() through an image array based on student responses. If the student answers correctly the question is popped, but if they answer incorrectly it is added to the end of the queue. Additionally, since deleting elements in the DOM is bad, I am replacing the current image's src and id with that of the next element in queue. The array is then popped and pushed along, but whenever I enter in the incorrect answer twice the same image appears.
I have moved the global variable that holds the array, domEls, inside of the function retrieveAnsForImage to force it to randomize the images in the array. When I do this, the images change correctly so I believe it is the push() and pop() commands.
I included a snippet that doesn't work here, but works like a champ in Notepad ++. I just took a crash course in Javascript, HTML and CSS last month on Codecademy, I am very new to this. Thank you for reading.
//Jquery
$(document).ready(function() {
$(function() {
$('img.card').on('contextmenu', function(e) {
e.preventDefault();
//alert(this.id);
openPrompt(this.id);
});
});
});
//Provide and Shuffle array function
function shuffleImgs() {
var imgArr = [
"image1",
"image2",
"image3",
"image4",
"image5",
"image6",
"image7",
"image8",
"image9"
];
var currentIndex = imgArr.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = imgArr[currentIndex];
imgArr[currentIndex] = imgArr[randomIndex];
imgArr[randomIndex] = temporaryValue;
}
alert("shuffle");
return imgArr;
}
function arrStack() {
var imgArr = shuffleImgs();
//Map over the array to create Dom elements
var domElements = imgArr.map(function (imgName, index) {
var cardDiv = document.createElement('div');
var cardImage = document.createElement('img');
//Add img id and class
cardImage.id = imgName;
cardImage.classList.add('card');
//Set img source
cardImage.src = `images/${imgName}.jpg`;
//Put it all together
cardDiv.appendChild(cardImage);
return cardDiv;
});
//this notation to call nested function for Global var stack
this.nDomElements = function () {
stackDomEl = domElements;
return stackDomEl;
}
//Display last element in array
//this notation to call the nested function from outside the function
this.nDisplayLastArr = function displayLastArr() {
var lastImgArr = domElements[domElements.length - 1];
//alert(lastImgArr);
//Append the elements to the DOM
var modal = document.querySelector('div.modal');
modal.appendChild(lastImgArr);
return lastImgArr; //Use brackets when your are returning more than one variable
}
}
//Function called from Jquery to open prompt to answer question
function openPrompt(imageId) {
var userAns = prompt("Please enter your answer below and click OK");
if (userAns == null || userAns == "") {
alert("User cancelled the prompt. Exit and please try again!");
}
else {
/*Vain hope that I can pass imageId from click event through the user prompt
to the answer checking function retrieveAnsForImage*/
retrieveAnsForImage(imageId, userAns); //out of scope?
}
}
//Global variable
func = new arrStack();
window.domEls = func.nDomElements();
//Compare user responses with the question image by use of the click image id
function retrieveAnsForImage(imageId, userAns) {
//Change these variables to the correct answer whenever this website is reused in other assignments
var ansImage1 = "1";
var ansImage2 = "2";
var ansImage3 = "3";
var ansImage4 = "4";
var ansImage5 = "5";
var ansImage6 = "6";
var ansImage7 = "7";
var ansImage8 = "8";
var ansImage9 = "9";
//Give students a second chance to retry a question
//var hintCounter = 0; //include a while statement above the if statements to allow students a retry
/*Compare user response with correct case answer and correct clicked image.
Students may enter the right answer for the wrong image hence the &&.
Images will always be refered to as image1, image2, etc.*/
if (userAns === ansImage1 && imageId === "image1") {
correctAns(imageId);
}
else if (userAns === ansImage2 && imageId === "image2") {
correctAns(imageId);
}
else if (userAns === ansImage3 && imageId === "image3") {
correctAns(imageId);
}
else if (userAns === ansImage4 && imageId === "image4") {
correctAns(imageId);
}
else if (userAns === ansImage5 && imageId === "image5") {
correctAns(imageId);
}
else if (userAns === ansImage6 && imageId === "image6") {
correctAns(imageId);
}
else if (userAns === ansImage7 && imageId === "image7") {
correctAns(imageId);
}
else if (userAns === ansImage8 && imageId === "image8") {
correctAns(imageId);
}
else if (userAns === ansImage9 && imageId === "image9") {
correctAns(imageId);
}
else {
window.alert("Incorrect Answer");
incorrectAns();
}
function correctAns(){
//Second to last element in array
var SecLastElArr = domEls[domEls.length - 2];
//Pull image id from second to last element in array
var nextImgId = SecLastElArr.querySelector("div > img").id;
//Pull image id from document
var imgId = document.querySelector("div > img").id;
//Student incorrect answer change im
document.getElementById(imgId).src = `images/${nextImgId}.jpg`;
document.getElementById(imgId).id = nextImgId;
domEls.pop();
//Think about when the array is completely gone
//while domEls.length !== 0;
}
function incorrectAns(){
//Last element in array
var LastElArr = domEls[domEls.length - 1];
//Second to last element in array
var SecLastElArr = domEls[domEls.length - 2];
//Pull image id from second to last element in array
var nextImgId = SecLastElArr.querySelector("div > img").id;
//Pull image id from document
var imgId = document.querySelector("div > img").id;
//Student incorrect answer change image src and id to next element in queue
document.getElementById(imgId).src = `images/${nextImgId}.jpg`;
document.getElementById(imgId).id = nextImgId;
//Remove last element in array
domEls.pop();
//move the last element to the first element in the array for another attempt
domEls.push(LastElArr);
alert(domEls.length);
}
}
function overlay() {
var el = document.getElementById("overlay");
el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
}
#overlay {
visibility: hidden;
position: absolute;
left: 0px;
top: 0px;
width:100%;
height:100%;
text-align:center;
z-index: 1000;
background-color: rgba(0,191, 255, 0.8);
}
#overlay div {
width:70%;
margin: 10% auto;
background-color: #fff;
border:1px solid #000;
padding:15px;
text-align: center;
}
body {
height:100%;
margin:0;
padding:0;
}
#close-img {
float: right;
clear: right;
width: 30px;
height: 30px;
bottom: 0;
right: 0;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
<span> "Left click to view any questions. Right click (two finger tap) to answer the question and claim the tile. Each player must claim 4 tiles to successfully complete the assignment."</span>
<link href="https://fonts.googleapis.com/css?family=Oswald:300,700|Varela+Round" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="Stack Rnd Temp.css">-->
<script type="text/javascript" src="Stack Rnd Temp.js"></script>
<script src="jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="StackRndTempjq.js"></script>
</head>
<body>
<div class="title">
<h1></h1>
</div>
<div id="gameboard"> <!--Container for all nine divs-->
<a href='#' onclick='overlay()'>Click here to show the overlay</a>
</div>
<div class="modal" id="overlay">
<p> "Right click to answer the question"</p>
<script>
func = new arrStack();
func.nDisplayLastArr();
</script>
<img src="images/close.png" id="close-img" onclick="overlay()">
</div>
</body>
</html>
Your issue is that pop removes the last element from the array while push adds the element to end of the array.
What you probably want to do is use shift to remove the the first element from the array and pop it back to the end if the answer is wrong.
Alternately, you could pop the last element and use unshift to insert back into the beginning of you want to work in the other direction.
Here's a quick mockup without images.
var currentTest = null;
function getTest() {
$('#answer').html("").hide();
if (tests.length > 0) {
currentTest = tests.shift(); // remove the first question
$('#question').fadeIn(450).html(currentTest.q);
return currentTest;
} else {
$('#answer').html("Finished").fadeIn(500);
$('#btnCorrect').unbind();
$('#btnWrong').unbind();
}
}
var tests = [];
for (var i = 0; i < 5; i++) {
var question = "Question " + i;
var answer = "Answer " + i;
tests.push({
q: question,
a: answer
});
}
$('#btnCorrect').click(function() {
$('#question').hide();
$('#answer').fadeIn(450).html("Correct!");
window.setTimeout(getTest, 750);
});
$('#btnWrong').click(function() {
$('#question').hide();
tests.push(currentTest); // put the question back in the array
$('#answer').fadeIn(450).html("Incorrect!");
window.setTimeout(getTest, 750);
});
$(document).ready(function() {
getTest();
})
* {
font-family: arial;
}
#panel {
height: 50px;
}
#answer {
border: 1px solid #cccccc;
background: #dedede;
width: 400px;
}
#question {
border: 1px solid #999999;
background: #dedede;
width: 400px;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<div id="panel">
<div id="answer"></div>
<div id="question"></div>
</div>
<input id="btnCorrect" value="Mock Correct Answer" type="button">
<input id="btnWrong" value="Mock Wrong Answer" type="button">
</body>
</html>

javascript array images link error

I'm trying to create a mini-book of images using a clip of code i found online which refreshes a set of predefined images onclick via a basic form button, however I can't figure out why the images i've specified in the array are not appearing in the div below. I've confirmed that the url addresses are correct path - but I must be doing something wrong with the linkage ? ?
<html>
<head>
<title></title>
<script>
var bookImages = new Array();
bookImages[0] = "fsheet1.jpg"
bookImages[1] = "fsheet2.jpg"
bookImages[2] = "fsheet3.jpg"
bookImages[3] = "fsheet4.jpg"
bookImages[4] = "fsheet5.jpg"
bookImages[5] = "fsheet6.jpg"
var i = 0
function updateImg() {
var i = i + 1;
var url = 'url(' + bookImages[i] + ')';
document.getElementById('bookImg').style.backgroundImage = url;
}
</script>
<style type="text/css">
#bookImg {
background-img: url();
background-repeat: no-repeat;
background-color: #CF23FA;
text-align: left;
width: 150px;
height: 200px;
margin-top: 10px;
margin-left: 15px;
}
</style>
</head>
<body>
<div id='bookImg'>
<form>
<input type="button" value=">" onClick="updateImg()">
</form>
</div>
</body>
</html>
The problem:
you are redifining i inside the function updateImg. Technically your function is equivalent to this:
function updateImg() {
var i; // redeclaring i (i is not initialised so the value is undefined)
i = i + 1; // undefined + 1
var url = 'url(' + bookImages[i] + ')'; // url(undefined)
document.getElementById('bookImg').style.backgroundImage = url;
}
The fix:
function updateImg() {
i = i + 1; // don't redeclare i just use the outer one (the one above)
var url = 'url(' + bookImages[i] + ')';
document.getElementById('bookImg').style.backgroundImage = url;
}
Note:
The above code will increment i without checking if it gone beyond the array boundaries (after 6 clicks i will be 7 and there is no image at index 7 in the array). If you want to go back to 0 when i reaches the end then replace i = i + 1; by i = (i + 1) % bookImages.length;!
Complete code:
<html>
<head>
<title></title>
<script>
// array litterals: a better way
var bookImages = [
"http://placehold.it/201x100",
"http://placehold.it/202x100",
"http://placehold.it/203x100",
"http://placehold.it/204x100",
"http://placehold.it/205x100",
"http://placehold.it/206x100"
];
var i = 0;
function updateImg() {
var url = 'url(' + bookImages[i] + ')';
document.getElementById('bookImg').style.backgroundImage = url;
i = (i + 1) % bookImages.length; // increment at the end
}
window.addEventListener("load", updateImg); // call it once the document is ready
</script>
<style type="text/css">
#bookImg {
background-repeat: no-repeat;
background-color: #CF23FA;
text-align: left;
width: 150px;
height: 200px;
margin-top: 10px;
margin-left: 15px;
}
</style>
</head>
<body>
<div id='bookImg'>
<form>
<input type="button" value=">" onClick="updateImg()">
</form>
</div>
</body>
</html>

img onclick fire js function only second click

On html page I have several images with <img onclick="povecaj();"
In fact, trying to make some kind of light-box.
First img click not work, second click fired function and any other img first click fired function. But after page loaded fist img click doesn't work...
function is next:
function povecaj() {
if (document.readyState === "complete") {
if ((screen.width > 801) || (screen.height > 801)) {
init();
}
else {
return;
}
}
}
function init() {
$(' .card-img img').click(function () {
var thediv = document.getElementById('displaybox');
var staza = $(this).attr('src')
var sl = document.getElementById('image');
thediv.style.display = "";
sl.innerHTML = '<img alt="2" id="imgID" src="' + staza + '"/>' + '<div class="alert-close" onclick = "zapri()" >X</div>'
thediv.innerHTML = '<table style="width:100%; height:100%;"><tbody><tr><td style="text-align: center; vertical-align:central; width:100%; height:100%"></td></tr></tbody></table>';
thediv.style.display = "block";
sl.style = "block";
});
}
I'm working in VS2012, using Chrome inspect too.. can't see errors..
searched, googled, can't find solution. Can somebody help?
If your images loading dynamically the DOM you must add a jquery event listener like this:
function init() {
$(class_of_parent_div).on('click', '.card-img img', function () {
var thediv = document.getElementById('displaybox');
var staza = $(this).attr('src')
var sl = document.getElementById('image');
thediv.style.display = "";
sl.innerHTML = '<img alt="2" id="imgID" src="' + staza + '"/>' + '<div class="alert-close" onclick = "zapri()" >X</div>'
thediv.innerHTML = '<table style="width:100%; height:100%;"><tbody><tr><td style="text-align: center; vertical-align:central; width:100%; height:100%"></td></tr></tbody></table>';
thediv.style.display = "block";
sl.style = "block";
});
}
And write the class of parent div class_of_parent_div

dropdown is in middle of page, should open list according to position

I have a dropdown which is in the middle of the page. It always opens the list downwards, as it should be. Now, we have to implement it in a way that whenever the browser screen size is changed, & the dropdown box does not have enough space to open the list, it should open the list upwards.
Please let me know, if more details are required.
code :
HTML For DropDown List/Picker :
<div id="pick-container" class="wGridPx_30 hPrefixPx_2 hSuffixPx_2 outer ">
<label id="pick-label" class="input hPrefixPx_1">
<span id="pick-guide">Start typing EID, first or last name</span>
<input id="peoplepick" type="text" class="wGridPx_29" />
</label>
</div>
javascript :
if( $("div#people-picker-container").length == 0 ) {
$("#peoplepick").parent().append("<div id='people-picker-container' class='ui-picker-container'></div>");
//Set the desired height for dropdown
$("#people-picker-container").css({'max-height':'260px'});
}
Adding the list :
var people = $.parseJSON(data.d);
$("#people-picker-container").html(null);
$.each(people, function (index, item) {
//For image handler (ashx) please contact 'acn.ppl.plumbers' team to get code and access rights
var person = "<div class='ui-person-item'><input type='hidden' name='eid' value=" + item.EnterpriseId + " /> " +
"<div class='ui-person-img'><img src='/services/PhotoProvider.ashx?id=" + item.EnterpriseId + "'/></div>" +
"<div class='ui-person-info'>" +
"<span>" + item.DisplayName + "</span>" +
"<div class='ui-person-desc'>" + item.DisplayText + "</div>" +
"</div>" +
"</div>";
$("#people-picker-container").append(person);
CSS :
.ui-picker-container{
position:absolute;
border:1px solid #afafaf;
background-color:#fff;
overflow-y: auto;
overflow-x: hidden;
padding-right: 20px;
z-index:100;}
.ui-picker-dropup{
bottom: 18%;
}
.ie7 .ui-picker-container {
margin-top:21px;
margin-left:-240px;
}
.ui-person-item{
width:auto;
position:relative;
min-height:48px;
margin:8px 0;
background-color:#fff;
word-wrap:break-word;
cursor:pointer;
z-index:110;
}
.ui-person-img{
width:48px;
height:48px;
overflow:hidden;
position:absolute;
left:10px;
}
.ui-person-img img{
width:100%;
}
.ui-person-info{
min-width:100px;
position:absolute;
left:80px;
width:69%;
}
.ui-person-desc{
font:1em Arial;
color:#808080;
}
.hidden{
display:none;
}
.ui-person-info span {
color:#000;
font-style:normal;
left:auto;
height:auto;
top:auto;
z-index:auto;
cursor:pointer;
}
I am trying to add class - .ui-picker-dropup when screen size changes, but this is not working with all the scrren sizes, & not able to figure out how to dynamically calulate the bottom %. is there any other way to do this?
I was using this way, but this is absolutely incorrect :
//Calulate the size of scrren
var screenHight = $(window).height();
var screenWidth = $(window).width();
var pickerPosition = { left: 0, top: 0 };
var picker = document.getElementById('pick-container');
pickerPosition = picker.getBoundingClientRect();
var xPicker = pickerPosition.left;
var ypicker = pickerPosition.top;
alert(" ypicker " + ypicker);
if(ypicker != 288){
$("#people-picker-container" ).addClass( "ui-picker-dropup");}
A designer friend of mine asked me this question for something she was working on and pointed me to your unanswered question. I'll summarize the solution I gave to her at this codepen..
I wrote the solution as a basic jQuery plugin that will add a class to the element when it approaches within a buffered amount of the bottom of the page or beyond. This should provide the flexibility to change the direction of the dropdown list when the element has a special class.
USAGE
$('#target').bottomFeeder();
// or with options
$('#target').bottomFeeder({
buffer: 100, // buffer is the distance from the bottom of the page that the class is added
className: 'bottom' // class name to be added
});
PLUGIN
$.fn.bottomFeeder = (function(){
var lastScrollTop = $(window).scrollTop(),
delta = 5, // every 5px scroll
winH = 0,
observees = [];
var checkPosition = function(obj){
var el = $(obj.el),
top = el.offset().top;
if((top + obj.config.buffer) > (lastScrollTop + winH))
el.addClass(obj.config.className);
else
el.removeClass(obj.config.className);
};
$(window).on('scroll', function(){
// nothing to do
if(observees.length === 0) return;
var st = $(this).scrollTop();
// scroll was less than the delta
if(Math.abs(lastScrollTop - st) <= delta)
return;
// update shared variables
winH = $(window).outerHeight();
lastScrollTop = st;
for(var i = 0; i < observees.length; i++){
checkPosition(observees[i]);
}
});
return function(config){
config = config || { buffer: 50, className: 'bottom' };
observees.push({ el: this, config: config });
};
})();

Categories