Scrollable ul list up and down from links with classes - javascript

I want to scroll a news article list up and down depending on which buttons is clicked
I wanted to adapt this way of animating if possible:
function smoothAdd(id, text)
{
var el = $('#scroller' + id);
var h = el.height();
el.css({
height: h,
overflow: 'hidden'
});
var ulPaddingTop = parseInt(el.css('padding-top'));
var ulPaddingBottom = parseInt(el.css('padding-bottom'));
el.prepend('<li>' + text + '</li>');
var first = $('li:first', el);
var last = $('li:last', el);
var foh = first.outerHeight();
var heightDiff = foh - last.outerHeight();
var oldMarginTop = first.css('margin-top');
first.css({
marginTop: 0 - foh,
position: 'relative',
top: 0 - ulPaddingTop
});
last.css('position', 'relative');
el.animate({ height: h + heightDiff }, 1500)
first.animate({ top: 0 }, 250, function() {
first.animate({ marginTop: oldMarginTop }, 1000, function() {
last.animate({ top: ulPaddingBottom }, 250, function() {
last.remove();
el.css({
height: 'auto',
overflow: 'visible'
});
});
});
});
}
$('.scrollUp').click(function() {
smoothAdd('scrollUp', 'A new item');
});
Example here: http://www.fiveminuteargument.com/blog/scrolling-list
My HTML looks like this:
<ul id="scroller">
<li class="current"><span>/</span>News Article Title</li>
<li><span>/</span>News Article Title 2</li>
<li><span>/</span>News Article Title 3</li>
</ul>
<div class="btnWrap"><p>Scroll Up
Scroll Up</p></div>
Can anyone point me in the right direction?
Basically maintain the animation style but keep it as a defined UL as per a normal carousel.

Here : http://jsfiddle.net/sDedY/13/
I've written form scratch. as you notice I've added css directly in a css file, it's better than adding css via jquery, especially for future mainenance/ decorateion etc.., but I havent spent much time for different caluclations. This is a blueprint I guess, you can modify and make it much better, like make top and bottom combined to make the function small or things like that, i jsut dont have time anymore ... so again : redo the calculations based on css yourself and modify it !
EDIT : regarding variable height, you need to keep in mind that I haven't finalised the whole function. next step in coding this function would be auto-calculation of margin-top and top rather than manually entering them, which is pretty easy. all that's needed is to pass a variable to get the position and dimensions of li elements and then pass them to our code.

I've change a few lines of your code:
var el = $('#scroller' + id); to var el = $('#' + id);
and
smoothAdd('scrollUp', 'A new item'); to smoothAdd('scroller', 'A new item');
see http://jsfiddle.net/nCWAP/

I made a slightly simpler solution. Check it out here
You don't need to mess with absolute or relative position neither with top. The list has height as auto so it grows/shrinks according to the height of their li elements
EDIT
Now the height is automatically adjusted to show all items.
Also supports li elements of any height.

Related

JQuery - Position Popup in relative to button(s)

I'm trying to position a popup relative to its button or the button that is clicked with jquery. I'd like to position the popup in a way that doesn't cover up the button itself. Position it to the left, right, above or below the button that is clicked.
Now I know I can do this by writing more html popups and css but there got to be a way to dynamically use one div and position it with jquery. I tried using offsets and position (at one point) but I couldn't get it to work. Frankly, I'm very entry level with js and jquery so forgive my noobness.
Any help would be greatly appreciated!!
JS:
$('.trends').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>What trends could potentially drive growth in the U.S.?</p>');
/* if I add this and zero out the positioning via css the pop gets offset but its way far away from this parent.
var offset = $(this).offset();
$('.questions').css('left',offset.left);
$('.questions').css('top',offset.top);*/
});
$('.consumer').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>Even though we have low inflation, consumers are not increasing their spending. Why?</p>');
});
$('.industry').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>What factors drove crude oil prices to fall and which industries benefited?</p>');
});
$('.henn').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>MESSAGE FROM OUR PRESIDENT</p>');
var offset = $(this).offset();
$('.question').html('<p>What trends could potentially drive growth in the U.S.?</p>');
});
$('.equity').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>The U.S. stock market has been rising for more than six years. What do you see ahead for equities?</p>');
});
$('.balance').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>what does it look like for companies balance sheets?</p>');
});
$('.close').click(function (e) {
e.stopPropagation();
$(this).parent().hide();
$('.items').removeClass('no-effect');
});
jsFiddle
Create a separate function to display the question, which takes the clicked button and the question as parameters:
function showQuestion(button, question) {
var offset = button.offset();
$('.question').html(question);
$('.questions')
.fadeIn()
.css({
left: Math.min(offset.left, $(window).innerWidth()-$('.questions').outerWidth()),
top: offset.top + button.innerHeight()
});
}
Call it like this:
$('.trends').click(function () {
showQuestion(
$(this),
'<p>What trends could potentially drive growth in the U.S.?</p>'
);
});
Updated Fiddle
The css left calculation ensures that the question will always be on-screen.
Part of your problem was .filter being set to position: relative;.
If an absolute positioned element has a relative positioned parent the absolute element will be positioned in relation to the parent not the document.
If you remove that it gets a little easier to use .offset() to position the question:
Working Example
$('.trends').click(function () {
$('.questions').fadeIn();
$('.question').html('<p>What trends could potentially drive growth in the U.S.?</p>');
/* See change here*/
var offset = $(this).offset();
$('.questions').css('top', offset.top + $(this).height());
});
.filter {
width: 98.1481481481%;
float: left;
margin-left: 0.9259259259%;
margin-right: 0.9259259259%;
margin-bottom: 10px;
/*position: relative; see change here */
}
There's a $(...).position() function in jQuery that should help you out. I refactored your code a bit to avoid repeating lines, but the gist of it is:
function popup(jqBtn, question){
// mind that the .position does not account for borders etc.
var btn = $(jqBtn).parents('.buttons'),
posLeft = btn.position().left + btn.outerWidth(),
posTop = btn.position().top;
$('.questions').fadeIn();
$('.question').html(question);
$('.questions')
.appendTo(btn.parent())
.css('left', posLeft + 'px')
.css('top', posTop + 'px');
}
// a sample of binding a button to the popup() function
$('.trends').click(function () {
popup(this, '<p>What trends could potentially drive growth in the U.S.?</p>');
});
So the function re-appends the 'questions' div to have the same parent as the button. The button is found based on the element clicked, traversing up the structure to find an element of '.buttons' class. That might need adjusting if the structure gets more complex.
jsFiddle

Replacing a title with position fixed, with another title position fixed

So I have a node.js app using express and trying to do the following:
div(class="title")
h1(class="h1_title") example_title
My jQuery for this is as follows:
jQuery(function($) {
function fixDiv() {
var $cache = $('.title');
if ($(window).scrollTop() > 140)
$cache.css({'position': 'fixed', 'top': '10px'});
else
$cache.css({'position': 'relative', 'top': 'auto'});
}
$(window).scroll(fixDiv);
fixDiv();
});
So when I scroll the title will become fixed at the top of the page. Got this working, however! I have another title below this, the exact same code. But I'm trying to get my title to replace the previous one and become fixed.
So As your scrolling down through content, the title is always fixed but its just being updated with the title relevant to the content your viewing.
Can anyone help, I'd really appreciate it. I can't find anything which is what i'm exactly looking for and my knowledge is limited.
Thank you!
I see you were asking a lot of questions about that ... I'm gonna show you an example that maybe can helps.
With an structure like this:
<div class="title">TITLE</div>
<div class="cont"><h1>TITLE</h1></div>
<div class="cont"><h1>Content1</h1></div>
<div class="cont"><h1>Content2</h1></div>
<div class="cont"><h1>Content3</h1></div>
Where .title gonna be the fixed header you can use Jquery to change the value base on the h1 of the other containers.
$(window).scroll(function(){
$('.cont').each(function(){
var t = $(this).offset().top - 50,
tit = $(this).find('h1').text(),
h = $(this).height(),
ws = $(window).scrollTop();
if (t < ws && ws < (h+t)) {
$('.title').html(tit);
}
})
})
Check this CodePen Demo
Here is a really basic example: http://jsfiddle.net/jgxevwa6/1/ -- I didn't try to get the spacing perfect or anything.
You have your fixed class:
.fixed {
position: fixed;
top: 0;
}
And then the magic. Basically any time you scroll, it cycles through each block and determines which is in the viewport by using a basic scrolling model:
(function($) {
var utils = {
fixTitle: function(e) {
var top = e.currentTarget.scrollY;
$('div').each(function() {
var thistop = $(this).position().top;
if(top > thistop) {
$('.title').removeClass('fixed');
$(this).find('.title').addClass('fixed');
}
});
}
};
$(function() {
$(window).scroll(utils.fixTitle);
});
})(jQuery);
The javascript and CSS could be a little more accurate, but this gives you the basic gist of it.

parallax.js + js fadein/out = no joy after first <li>

I am using parallax.js to animate a series of elements on a homepage. I searched for code that would allow me to add a simple "slider" effect to the elements as well.
Everything seems to be working properly, except that after the first li, the parallax effect only works horizontally. On li #1, the element hovers as expected, following the mouse in every direction.
Here's a link to jsfiddle: http://jsfiddle.net/sdeviva/t6uwq/1/
Here's a link to the revised jsfiddle: http://jsfiddle.net/sdeviva/t6uwq/5/
var scene = document.getElementById('scene');
var parallax = new Parallax(scene);
var scene = document.getElementById('scene2');
var parallax = new Parallax(scene2);
(function($) {
$.fn.ezslide = function ( options ) {
var defaults = {
fadeIn : 1000,
fadeOut : 1000,
delay : 500
},
settings = $.extend( defaults, options ),
$this = this,
cur = 0,
fadeIt = function( which ) {
var li = $this.find('li');
cur = which = (which >= li.length) ? 0 : which;
li.fadeOut( settings.fadeOut );
li.eq( which )
.delay( settings.fadeOut )
.fadeIn( settings.fadeIn, function(){
setTimeout(function() {
cur++;
fadeIt( cur );
}, settings.delay);
});
};
fadeIt( cur );
};
$('ul.scene').ezslide({
fadeIn : 600,
fadeOut : 600,
delay : 3000
});
})(jQuery);
EDIT: I sort of fixed this. I don't really know what I'm doing, so there's probably a cleaner way. But, I realized that the parallax effect was only being applied once to the first list item. The script that makes each item fade in wasn't getting the benefit of the parallax.js script.
SO - I put each fading element into its own ul, with a unique id, and a shared class. By some miracle, this actually works. But let me know if there's a better way.
This is an interesting one. The issue is that the parallax code sets the very first layer to position: relative and all others to position: absolute. This has the effect of making the parent ul have the dimensions of only the first layer. This is normally fine, except that when you display any element other than the first, the first is hidden. This causes the ul to have 0 height. The parallax depends on the height of the scene, as a result no height means no vertical movement.
You can fix the issue by applying a fixed height to your ul:
#scene{
height: 128px;
}
http://jsfiddle.net/t6uwq/7/
You can find greater detail on the motion calculation in the documentation on github.

How to dynamically display position of a div on hover

Hi i am creating a website in wordpress,where i am using javascript to display a description div on hover a list of elements but my problem is according to screen size the description div must vary its position in order to display the content completely.I am not sure that i expressed my query clearly could anyone suggest me how can i get this.
jQuery:
(function($) {
$(document).ready( function() {
$('#linkcat-4 .xoxo li:nth-child(1)').mouseover(function(e) {
$('#text1').css(
'visibility' , 'visible'
);
$('#linkcat-4 .xoxo li:nth-child(1)').mouseout(function(e) {
$('#text1').css(
'visibility' , 'hidden'
);
});
});
});
})(jQuery);
HTML:
<ul class="xoxo blogroll">
<li>Admirality</li>
<li>Banking</li>
<li>Commercial</li>
<li>Contract</li>
<li>test</li>
<li>Corporate</li>
</ul>
<div class="desc-text" id="text1" style="visibility: hidden;">
<p>We represent protection and indemnity clubs that provide insurance
for many of the ships coming to Guyana. We deal with all the familiar
problems encountered by ships, both contentious and non-contentious,
including arrests arising from accidents and claims for wages and damaged
cargo. We advise masters, obtain surveys, note protests, negotiate
settlements and advise on or deal with stowaways and medical emergencies.
Our admiralty practice is the largest in Guyana.
</p>
</div>
CSS:
.desc-text {
position: absolute;
top: 12%;
left: 50%;
}
#text1 {
visibility:hidden;
background:#f1f1f1;
padding: 15px;
width: 150px;
}
You need to check the window.innerHeight and window.innerWidth properties before setting the top and left of your popup div. Here is a fiddle to get you started.
The important part is inside the .hover() call:
$( function() {
pop = $("#popup");
$(".item").hover( function() {
row = $(this);
pop.html(row.data("extra"))
.css("top", (function(r) {
if(r.offset().top > window.innerHeight - pop.height())
return window.innerHeight - pop.height();
else
return r.offset().top;
})(row))
.css("left", (function(r) {
if(r.offset().left + r.width() > window.innerWidth - pop.width())
return window.innerWidth - pop.width();
else
return r.offset().left + r.width();
})(row))
.show();
}, function() {
pop.hide();
});
});
Basically, .hover() takes two functions, one for mouseover and one for mouseout. On mouseout, I just hide the popup. On mouseover, I fill the popup div with content (here coming from the item's data-extra attribute, but it could come from anywhere) then decide where to put it based on the location of the item and the window bounds.
Hope that helps. Leave a comment if you need more.
Update
So, the short answer is to make your content fit a normal browser window. I have to maximize my browser to be able to see everything in that popup. It seems like important information, too. So maybe it deserves its own page? These are opinions, not facts, so I'll move on to the latest version of the fiddle which you can more easily look at here.
There were changes to make everywhere, in the CSS, HTML, and Javascript, to make this work. Probably the biggest issue is visibility:hidden. There might be a way to get jQuery to work with that, but I just use the default display:none, which is what .show() and .hide() toggle.
New css
#text1
{
display:none;
background:#f1f1f1;
padding: 15px;
width: 150px;
}
And I needed to wrap your ul with a div of id linkcat-4. Now for the new js. The most interesting change is that I realized we need to take the div's padding into account. Since the padding parameter applies to all sides, we actually need to double the padding and add that to our offset from the window bounds:
New javascript
(function($) {
$(document).ready( function() {
var pop = $("#text1");
$('#linkcat-4 .xoxo li:nth-child(1)').hover(function(e) {
var row = $(this);
pop.html(row.data("extra"))
.css("top", (function(r) {
if(r.offset().top > window.innerHeight - pop.height())
return window.innerHeight - pop.height() - parseInt(pop.css("padding"))*2;
else
return r.offset().top;
})(row))
.css("left", (function(r) {
if(r.offset().left + r.width() > window.innerWidth - pop.width())
return window.innerWidth - pop.width() - parseInt(pop.css("padding"))*2;
else
return r.offset().left + r.width();
})(row))
.show();
},
function(e) {
pop.hide();
});
});
})(jQuery);
Let me know if that works.

JQuery UI sortable in a scrollable container - scroll position "jumps" when sorting

Please check this almost identical question first: jQuery Sortable List - scroll bar jumps up when sorting
I have exactly the same problem, only that I tried all the suggested solutions there with no luck
Here is the way to reproduce
create a sortable list
have it scrollable
scroll down
reorder items
scroll position "jumps" up
Here is the code (see also in JSFiddle)
Html
<ul id="panel" class="scroll">
<li class="content" style="background-color:red">item1</li>
<li class="content" style="background-color:green">item2</li>
<li class="content" style="background-color:blue">item3</li>
<li class="content" style="background-color:gray">item4</li>
<li class="content" style="background-color:yellow">item5</li>
</ul>​
JavaScript
$(function() {
$("#panel").sortable({
items: ".content",
forcePlaceholderSize: true
}).disableSelection();
$(".content").disableSelection();
});​
CSS
.scroll{
overflow: scroll;
border:1px solid red;
height: 200px;
width: 150px;
}
.content{
height: 50px;
width: 100%;
}
​
Here is the code (in JSFiddle) after trying the notion of the accepted answer (with no luck)
I can try to understand why it happens (list get's "shortened" for a quick second), but all attempts to use placeholders or helpers to avoid it didn't work either. I feel I tried almost any permutation of the "scrollable" options with no luck
Browsers I tried
IE9, Firefox 10.0.1, and Chrome 17
JQuery versions
core 1.7.1, UI v 1.8.17
Am I doing something wrong? Is there a solution? Could it be a bug?
If you modifiy your CSS for the .scroll element by adding:
position:relative;
That should resolve this issue.
Adding overflow-y:scroll to the sortable list even without the height property solved it for me. It only shows a disabled scrollbar, but that's okay.
아래로 스크롤 할때 는 이런식으로 하면 됩니다.
var cY = -1;
var base = 0;
$("").sortable({
sort: function(event, ui) {
var nextCY = event.pageY;
if(cY - nextCY < -10){
if(event.clientY + ui.helper.outerHeight(true) - 20 > document.body.clientHeight) {
base = base === 0 ? event.clientY : base;
var move = event.clientY - base;
var curScrollY = $(document).scrollTop();
$(document).scrollTop(curScrollY + move+3);
base = event.clientY;
}
}
},
// .....
});
Seems like jQuery UI 1.9.2 solved the issue.
If you are unable to change the library, there's a workaround including a simple scroll bar operation. The idea is simple:
Keep the previous scroll position every time you scroll.
Set scroll back to the previous position when you start dragging your element.
Here you go;
var lastScrollPosition = 0; //variables defined in upper scope
var tempScrollPosition = 0;
window.onscroll = function () { // Up to you requirement you may change it to another elemnet e.g $("#YourPanel").onscroll
clearTimeout($.data(this, 'scrollTimer'));
$.data(this, 'scrollTimer', setTimeout(function () {
tempScrollPosition = lastScrollPosition; // Scrolls don't change from position a to b. They cover some numbers between a and b during the change to create a smooth sliding visual. That's why we pick the previous scroll position with a timer of 250ms.
}, 250));
lastScrollPosition = $(document).scrollTop(); // Up to you requirement you may change it to another elemnet e.g $("#YourPanel").onscroll
};
$("#YourSortablePanel").sortable({
start: function (event, ui) {
$(document).scrollTop(tempScrollPosition);
}
});
This is caused by the height of the container changing when sorting (just before the placeholder is created)
The problem is well described and answered in this stack overflow : https://stackoverflow.com/a/32477389/2604980
For me this sortable options were working if you don't want to remove overflow css from body:
start(e, ui) {
if (fixOffset) ui.item.css('transform', `translateY(${document.body.scrollTop}px)`);
fixOffset = true;
},
change(e, ui) {
ui.item.css('transform', `translateY(${document.body.scrollTop}px)`);
},
stop(e, ui) {
ui.item.css('transform', 'translateY(0)');
},

Categories