I'm trying to use jcarousel to build a container with multiple rows, I've tried a few things but have had no luck. Can anyone make any suggestions on how to create it?
This is .js code substitutions according to #Sike and a little additional of me, the height was not set dynamically, now it is.
var defaults = {
vertical: false,
rtl: false,
start: 1,
offset: 1,
size: null,
scroll: 3,
visible: null,
animation: 'normal',
easing: 'swing',
auto: 0,
wrap: null,
initCallback: null,
setupCallback: null,
reloadCallback: null,
itemLoadCallback: null,
itemFirstInCallback: null,
itemFirstOutCallback: null,
itemLastInCallback: null,
itemLastOutCallback: null,
itemVisibleInCallback: null,
itemVisibleOutCallback: null,
animationStepCallback: null,
buttonNextHTML: '<div></div>',
buttonPrevHTML: '<div></div>',
buttonNextEvent: 'click',
buttonPrevEvent: 'click',
buttonNextCallback: null,
buttonPrevCallback: null,
moduleWidth: null,
rows: null,
itemFallbackDimension: null
}, windowLoaded = false;
this.clip.addClass(this.className('jcarousel-clip')).css({
position: 'relative',
height: this.options.rows * this.options.moduleWidth
});
this.container.addClass(this.className('jcarousel-container')).css({
position: 'relative',
height: this.options.rows * this.options.moduleWidth
});
if (li.size() > 0) {
var moduleCount = li.size();
var wh = 0, j = this.options.offset;
wh = this.options.moduleWidth * Math.ceil(moduleCount / this.options.rows);
wh = wh + this.options.moduleWidth;
li.each(function() {
self.format(this, j++);
//wh += self.dimension(this, di);
});
this.list.css(this.wh, wh + 'px');
// Only set if not explicitly passed as option
if (!o || o.size === undefined) {
this.options.size = Math.ceil(li.size() / this.options.rows);
}
}
This is the call in using the static_sample.html of the code bundle in the download of jscarousel:
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('#mycarousel').jcarousel( {
scroll: 1,
moduleWidth: 75,
rows:2,
animation: 'slow'
});
});
</script>
In case you need to change the content of the carousel and reload the carousel you need to do this:
// Destroy contents of wrapper
$('.wrapper *').remove();
// Create UL list
$('.wrapper').append('<ul id="carousellist"></ul>')
// Load your items into the carousellist
for (var i = 0; i < 10; i++)
{
$('#carouselist').append('<li>Item ' + i + '</li>');
}
// Now apply carousel to list
jQuery('#carousellist').jcarousel({ // your config });
The carousel html definition needs to be like this:
<div class="wrapper">
<ul id="mycarousel0" class="jcarousel-skin-tango">
...<li></li>
</ul>
</div>
Thanks to Webcidentes
We have had to make a similar modifiaction. We do this by extending the default options, to include a rows value, and the width of each item (we call them modules) then divide the width by the number of rows.
Code added to jCarousel function...
Add to default options:
moduleWidth: null,
rows:null,
Then set when creating jCarousel:
$('.columns2.rows2 .mycarousel').jcarousel( {
scroll: 1,
moduleWidth: 290,
rows:2,
itemLoadCallback: tonyTest,
animation: 'slow'
});
The find and edit the lines in:
$.jcarousel = function(e, o) {
if (li.size() > 0) {
...
moduleCount = li.size();
wh = this.options.moduleWidth * Math.ceil( moduleCount / this.options.rows );
wh = wh + this.options.moduleWidth;
this.list.css(this.wh, wh + 'px');
// Only set if not explicitly passed as option
if (!o || o.size === undefined)
this.options.size = Math.ceil( li.size() / this.options.rows );
Hope this helps,
Tony Dillon
you might want to look at serialScroll or localScroll instead of jcarousel.
I found this post on Google Groups that has a working version for multiple rows. I have used this and it works great. http://groups.google.com/group/jquery-en/browse_thread/thread/2c7c4a86d19cadf9
I tried the above solutions and found changing the original jCarousel code to be troublesome - it introduced buggy behaviour for me because it didn't play nice with some of the features of jCarousel such as the continous looping etc.
I used another approach which works great and I thought others may benefit from it as well. It is the JS code I use to create the li items to support a jCarousel with multiple rows with elegant flow of items, i.e. fill horizontally, then vertically, then scrollpages:
123 | 789
456 | 0AB
It will add (value of var carouselRows) items to a single li and as such allows jCarousel to support multiple rows without modifying the original jCarousel code.
// Populate Album photos with support for multiple rows filling first columns, then rows, then pages
var carouselRows=3; // number of rows in the carousel
var carouselColumns=5 // number of columns per carousel page
var numItems=25; // the total number of items to display in jcarousel
for (var indexpage=0; indexpage<Math.ceil(numItems/(carouselRows*carouselColumns)); indexpage++) // for each carousel page
{
for (var indexcolumn = 0; indexcolumn<carouselColumns; indexcolumn++) // for each column on that carousel page
{
// handle cases with less columns than value of carouselColumns
if (indexcolumn<numItems-(indexpage*carouselRows*carouselColumns))
{
var li = document.createElement('li');
for (var indexrow = 0; indexrow < carouselRows; indexrow++) // for each row in that column
{
var indexitem = (indexpage*carouselRows*carouselColumns)+(indexrow*carouselColumns)+indexcolumn;
// handle cases where there is no item for the row below
if (indexitem<numItems)
{
var div = document.createElement('div'), img = document.createElement('img');
img.src = imagesArray[indexitem]; // replace this by your images source
div.appendChild(img);
li.appendChild(div);
}
}
$ul.append(li); // append to ul in the DOM
}
}
}
After this code has filled the ul with the li items jCarousel should be invoked.
Hope this helps someone.
Jonathan
If you need a quick solution for a fixed or one-off requirement that definitely doesn't involve changing core library code which may be updated from time to time, the following may suit. To turn the following six items into two rows on the carousel:
<div class="item">contents</div>
<div class="item">contents</div>
<div class="item">contents</div>
<div class="item">contents</div>
<div class="item">contents</div>
<div class="item">contents</div>
you can use a little JS to wrap the divs into LI groups of two then initialise the carousel. your scenario may allow you to do the grouping on the server isn't always possible. obviously you can extend this to however many rows you need.
var $pArr = $('div.item');
var pArrLen = $pArr.length;
for (var i = 0;i < pArrLen;i+=2){
$pArr.filter(':eq('+i+'),:eq('+(i+1)+')').wrapAll('<li />');
};
Related
I'm using scrollify to swap out fixed position components, and adding/removing classes to animate the transition. I have everything working as I'd like as you progress forward through the scroll, but when you scroll up to see a previous section, its not removing the previous class, and the previous section now animates in behind it.
I don't think the prev method will be of use, because it doesn't call the previous section your were at, only the previous section assuming you are always moving forward.
Here is my code below, you can move forward just fine, but trying to go backwards presents a problem as the new current section will load behind the previous one, and the previous one will still be visible.
jsfilddle here
var wrapper = $('.wrapper');
var currentPosition = 0;
$(wrapper).each(function(index) {
if (currentPosition != index) {
$(this).css('opacity', 0);
} else if (currentPosition == index) {
$(this).css('opacity', 1);
}
});
$(function() {
$.scrollify({
section: ".wrapper",
scrollSpeed: 700,
setHeights: false,
after: function(index, sections) {
var prevWrapper = $.scrollify.current().prev();
var currentWrapper = $.scrollify.current();
var nextWrapper = $.scrollify.current().next();
$(prevWrapper).removeClass('wrapper-enter').addClass('wrapper-leave');
$(currentWrapper).removeClass('wrapper-leave').addClass('wrapper-enter');
},
});
});
The issue is depending on scrolling up or down your "next" or "prev" may not actually be what you think so you are hiding classes incorrectly.
What you could do as scrollify doesn't have an option to detect scroll direction is to create a super quick variable that will detect if you are scrolling up or down. Then simply update your classes then in the after function.
$.scrollify({
section: ".wrapper",
scrollSpeed: 700,
setHeights: false,
after: function(index, sections) {
var prevWrapper = $.scrollify.current().prev();
var currentWrapper = $.scrollify.current();
var nextWrapper = $.scrollify.current().next();
let elem = null;
// Add wrapper-enter to current element.
$(currentWrapper).removeClass('wrapper-leave').addClass('wrapper-enter');
if(lastIndex < index) {
// Scolled down if lastIndex < index
elem = prevWrapper;
} else {
// Scrolled up if last index > index
elem = nextWrapper;
}
$(elem).removeClass('wrapper-enter').addClass('wrapper-leave');
lastIndex = index;
},
In the above I simply created a variable to track the last index.
Here is a working fiddle: https://jsfiddle.net/k1e6x79f/
I'm new to blessed, and have a listTable that doesn't seem to scroll its top line.
Any suggestions?
var blessed = require('blessed');
var screen = new blessed.Screen
// Function to create a bunch of sample data
function getData(start, count) {
var result = [];
for (var i=start; i < count; i++) {
var row = [ '', i+'', 'test' + i];
result.push(row);
}
return result;
}
// quit when q or Ctrl-q is pressed
screen.key(['q','C-q'], function() {
return process.exit(0);
});
// Create a table
var table = blessed.listtable({
parent: screen,
left: 0,
data: getData(0,100),
border: 'line',
align: 'center',
keys: true,
width: '90%',
height: '90%',
vi: false,
name:'table'
});
// Focus table, and render results to screen
table.focus();
screen.render();
The reason is that the first row acts as the header for the table and it stays in a fixed position for convenience.
You will probably need to make your own custom ListTable class if you do not want the header since it is currently not optional. It's fairly easy to do though, just remove the relevant bits from the existing class that reference the fixed header (see the commented out bits here).
I am using seiyria bootstrap slider in which tick labels are dynamic. Here you can see the ticks are correctly aligned but their labels are not.
following is the sample markup
<div class="container">
<div class="examples">
<div class='slider-example'>
<h3>Example 13:</h3>
<p>Using ticks.</p>
<div class="well">
<input id="ex13" type="text" data-slider-ticks="[100, 150, 180, 300, 400]" data-slider-ticks-labels='["$100", "$150", "$180", "$300", "$400"]' />
</div>
</div>
</div>
Here is a jsFiddle showing the issue
Here is an image to show the issue:
This is a limitation of the bootstrap-slider plugin in its official state (confirmed by the author in the comments below).
However, with some tweaking to the plugin, you could make it do what you want.
jsFiddle Example
Specifically, this is what I changed to achieve this effect:
I changed this CSS rule (you should really override the original rule for your specific container rather than changing the plugin CSS as I have done for simplicity sake):
.slider.slider-horizontal {
width: 100%; /*changed*/
height: 20px;
}
I added this default option to the plugin:
Slider.prototype = {
//....
defaultOptions: {
//...
modify_label_layout:false // added this option
},
//....
Then, I added these two functions to the plugin:
_modifyLabelOffset: function(){
var positions = [];
var $sliderContainer=$(this.element).prevAll('.slider');
var $ticks = $sliderContainer.find('.slider-tick');
var $labels = $sliderContainer.find('.slider-tick-label');
$sliderContainer.css('margin-bottom', '12px');
$ticks.each(function () {
var $this = $(this);
var tickWidth = $this.width();
var tickLeft = $this.position().left;
positions.push(tickLeft - (tickWidth))
});
$labels.each(function (i,e) {
var $this = $(this);
$this.css('width', 'auto');
$this.css('position', 'absolute');
$this.css('left', positions[i]+'px');
});
$this=this;
$( window ).resize(function() {
$this._delay(function(){
$this._modifyLabelOffset();
}, 500);
});
},
_delay: (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})(),
I changed the initialization of the plugin to this:
$("#ex13").slider({
ticks: [100, 150, 180, 300, 400],
ticks_labels: ['$100', '$150', '$180', '$300', '$400'],
ticks_snap_bounds: 30,
modify_label_layout:true // added this option to the plugin, if true the layout of the lables will be modified
}).slider('setValue', 0); // starts out at 5 for some reason, weird, for now , just set it manually to 0
Note that this is a bit of a hack and could undoubtedly be incorporated into the plugin in a better way. Also, I have ONLY tested this in chrome. It may not function correctly in other browsers but this shows proof of concept so Ill let you take it from there :)
Original Answer:
I believe this is a limitation of the bootstrap-slider plugin.
Note that if you use evenly spaced numbers like so:
data-slider-ticks="[100, 200, 300, 400, 500]"
the labels are correctly positioned. see this jsFiddle
The plugin will let you use small numbers relatively close together as you have done here but even their own example page displays issues with the layout when doing so:
I'm putting together a quick little status board that shows active and upcoming github issues.
I have them all pulled in and formatted as a simple list and found a nice jQuery plugin that cycles through each item as a sort of slideshow. However, it was requested that it show multiple issues at once to fill up the screen more.
So on each slide swap it would display, say 5 LI items at once versus just 1. And then swap to show the next 5 and so on.
HTML
...
<ul id="issue-list">
<li class="issue"></li>
...
<li class="issue"></li>
</ul>
...
<script type="text/javascript">
$(function() {
$('#issue-list').swapmyli({
swapTime: 900, // Speed of effect in animation
transitionTime: 700, // Speed of Transition of ul (height transformation)
time: 4000, // How long each slide will show
timer: 1, // Show (1) /Hide (0) the timer.
css: 0 // Apply plugin css on the list elements.
});
});
</script>
JS
(function(e) {
e.fn.swapmyli = function(t) {
function s() {
var e = i.parent().find(".timer span");
e.animate({
width: "100%"
}, r);
var n = i.find("li:first").outerHeight(true);
i.find("li:first").fadeOut(120);
i.animate({
height: n
}, t.transitionTime);
i.find("li").hide();
e.animate({
width: "0%"
}, 60);
i.find("li:first").remove().appendTo(i).fadeIn(t.swapTime)
}
var n = {
swapTime: 300,
transitionTime: 900,
time: 2e3,
timer: 1,
css: 1
};
var t = e.extend(n, t);
var r = t.time - t.swapTime;
var i = this;
i.wrap('<div class="swapmyli clearfix"></div>');
i.after('<div class="timer"><span></span></div><br class="clear" />');
e(window).load(function() {
var e = i.find("li:first").outerHeight(true);
i.height(e);
i.find("li").hide();
s()
});
if (t.timer == 0) {
i.parent().find(".timer").hide()
}
if (t.css == 0) {
i.parent().addClass("nocss")
}
setInterval(s, t.time)
}
})(jQuery)
I'm not sure if outerHeight() will function correctly with slice, but you may try changing these lines:
var n = i.find("li:first").outerHeight(true);
i.find("li:first").fadeOut(120);
To the following:
var n = i.find("li").slice(0, 4).outerHeight(true);
i.find("li").slice(0, 4).fadeOut(120);
That's sort of a quick answer, but hopefully you're catching my drift. Probably need to play around with it a little bit :)
The current plugin, shown below, scrolls the top-most div in a series of divs with the same class upwards, then removes it from the container, and appends it to the bottom of the series (within the container). This gives the illusion of a vertical slideshow.
$.fn.rotateEach = function ( opts ) {
var $this = this,
defaults = {
delay: 5000
},
settings = $.extend(defaults, opts),
rotator = function ($elems) {
$elems.eq(0).slideUp(500, function(){
var $eq0 = $elems.eq(0).detach();
$elems.parent().append($eq0);
$eq0.fadeIn();
setTimeout(function(){ rotator( $($elems.selector) ); },
settings.delay);
});
};
setTimeout(function(){ rotator( $this ); }, settings.delay);
};
$('.dynPanelContent').rotateEach();
However, if there are a large number of elements to scroll through, this would make for a VERY long page. As such, I am attempting to re-write this script so that it accepts a parameter which will determine how many elements to display. Any elements exceeding this number will be hidden until they are in the top 'x' number of elements. Here is an example of what I have attempted to implement.
$.fn.rotateEach = function (opts) {
var $this = this,
defaults = {
delay: 5000,
//Add a parameter named elementsShown, pass in a default value of 3
elementsShown: 3
},
settings = $.extend(defaults, opts),
rotator = function ($elems) {
//Hide the elements that are past the number to be shown
for (i = settings.elementsShown; i <= $elems.eq; i++) {
$elems.eq(i).hide();
}
$elems.eq(0).slideUp(500, function () {
var $eq0 = $elems.eq(0).detach();
var $eqN = $elems.eq(settings.elementsShown) - 1;
//Check & Show the element that is now within the show range
if ($elems.eq() == $eqN) {
$elems.eq($eqN).show('slow');
}
$elems.parent().append($eq0);
$eq0.fadeIn();
setTimeout(function () { rotator($($elems.selector)); },
settings.delay);
});
};
You can use simple CSS for this, mate.
If your elements are all of the same height (which your problem has to assume: if you are rotating a whole bunch of things dynamically, you won't want your page to change height), then you don't really need to use JavaScript for this at all. Just set the height of the container to what you want and hide the overflow. Then when you remove and append, everything appears to work. This won't take care of your dynamic configuration, though.
Improved plug-in: http://jsfiddle.net/morrison/tTJaM/
Notes:
Added support for showing X elements.
Added support for rotating only certain elements.
Added support for stopping the rotations:
Stop after X milliseconds.
Stop after X rotations.
overflow-y:hidden is added to container dynamically.
Simplified your detaching/attaching.
Known Issues:
Displaying X elements doesn't check for a maximum.