I'm building my first js/jQuery site and I've run into a hiccup. I'm trying to use both jScrollpane (Kelvin Luck) and scrollTo (Ariel Flesler) plugins in one script. If I comment one out, the other works. Are they mutually exclusive? Do I need to unbind functionality out of jScrollpane to remove a 'scrollTo' call conflict or something? (I have no idea how to do that).
I'm using jScrollPane 2beta11 and scrollTo 1.4.2. Here's my stripped-down code using both:
// JavaScript Document
$(document).ready(function() {
//jScrollPane Init
$('#scrollingDiv').jScrollPane({
});
//scrollTo Refresh
$('div.scroll-pane').scrollTo( 0 );
$.scrollTo( 0 );
//Buttons
var $scrollDiv = $('#scrollingDiv');
var next = 1;
$('#but-rt').click(function(){
$scrollDiv.stop().scrollTo( 'li:eq(1)', 800 );
next = next + 1;
});
});
I'm aware that jScrollPane has it's own scrollTo functionality, but I need scrollTo's jQuery Object selectors in my particular project. I know I've got my HTML/CSS lined up fine because each function works as long as the other is commented out.
(By the way, I plan on using "next" variable to increment scrollTo button once I figure out how... not related to my problem tho.)
Any help is much appreciated. Let me know if there's anything else I need to supply. Thanks!
-Patrick
See how to use ScrollTo functionality of JscrollPane from the following url,
http://jscrollpane.kelvinluck.com/scroll_to.html
Hope this will help you...
I too was trying to use both jScrollpane (Kelvin Luck) and scrollTo (Ariel Flesler) plugins in one script. I've come across an easy solution which doesn't even require Ariel Flesler's AWESOME Script, if you don't necessarily require animated scrolling.
I wanted to be able to scroll to a label in a list of items when the page loads.
Here's how i did it:
$(function()
//Declare the ID or ClassName of the Scroll Element
//and the ID or ClassName of the label to scroll to
MyList = $('#MyElementID OR .MyElementClassName');
MyLabel = $('#MyElementID OR .MyElementClassName');
// Initiate the Scrollpane
MyScroll = $(MyList).jScrollPane();
// Connect to the jScrollPaneAPI
jScrollPaneAPI = MyScroll.data('jsp');
// Get position co-ordinates of the Label
var MyLabelPosition = $(MyLabel).position();
// Convert position co-ordinates to an Integer
MyLabelPosition = Math.abs(MyLabelPosition.top);
// Scroll to the Label (0-x, vertical scrolling) :)
jScrollPaneAPI.scrollTo(0, MyLabelPosition-3, true);
});
There's a small bug with the exact positioning when a list gets longer,
will post a fix asap...
They are mutually exclusive because jScrollPane removes the real scrolling and replaces it with complex boxes-in-boxes being moved relative to each other via JS.
This is how I successfully mixed them -- I had a horizontal list of thumbnails; this code scrolled the thumbnails to the center:
Activated jScrollPane:
specialScrolling = $('#scrollingpart').jScrollPane();
In my serialScroll code, where I usually would call
$('#scrollingpart').trigger('goto', [pos]);
in my case, inside my
onBefore:function(e, elem, $pane, $items, pos)
I put code like this:
jScrollPaneAPI = specialScrolling.data('jsp');
//get the api to manipulate the special scrolling are
scrollpos=(Math.abs(parseInt($('.jspPane').css('left'), 10)));
//get where we are currently scrolled -- since this is a negative number,
//get the absolute value
var position = $('#scrollingpart .oneitem').eq(pos).position();
//get the relative offset location of the item we are targetting --
//note "pos" which is the index number for the items that you can access
//in serialScroll's onBefore:function
itempos=Math.abs(position.left);
//get just the x-axis location -- your layout might be different
jScrollPaneAPI.scrollBy(itempos-scrollpos-480, 0, true);
//the 480 worked for my layout; the key is to subtract the 2 values as above
Hope this helps someone out there!
This doesn't cater for all use cases (it only handles scrollToY and scrollToElement), but offers a consistent API so you can just use $( /* ... */ ).scrollTo( /* number or selector */ ) and it will work on any element, jScrollPane or native.
You could extend the method condition to cater for all the other jScrollPane methods by inferring the value passed in target though.
(function scrollPaneScrollTo(){
// Save the original scrollTo function
var $defaultScrollTo = $.fn.scrollTo;
// Replace it with a wrapper which detects whether the element
// is an instance of jScrollPane or not
$.fn.scrollTo = function $scrollToWrapper( target ) {
var $element = $( this ),
jscroll = $element.data( 'jsp' ),
args = [].slice.call( arguments, 0 ),
method = typeof target === 'number' ? 'scrollToY' : 'scrollToElement';
if ( jscroll ) {
return jscroll[ method ].call( $element, target, true );
}
else {
return $defaultScrollTo.apply( $element, args );
}
};
}();
Related
I've been coding my own dialog system for exercising and to be able to customize it as i want. Here is what i've done.
$(function(){
$.fn.window = function(attr){
var $self = this;
if(!attr)
attr = {};
$.extend({
autoOpen:false
}, attr);
/**
* Create the window by updating the current jQuery block
* And adding the required classes
*/
this.create= function(){
// Already created
if($self.hasClass('window-window'))
return;
$self.addClass('window-window');
// Creating the header and appending the title
var $windowHeader = $('<div class="window-header"></div>');
var $title = $self.attr('title');
$windowHeader.html($title);
$windowHeader.append('<div class="loading-item loading-item-footer round-loading25" ' +
'data-loading-item="window" style="display:none"></div>');
// Wrapping content in a window-content class
// So the window has the proper format
$self.children().wrapAll('<div class="window-content"></div>');
$self.prepend($windowHeader);
};
/**
* Open the window in a blackish div
* With the events to close it
*/
this.open = function(){
// Creating the background
var $backgroundDiv = $('<div></div>');
$backgroundDiv.addClass('window-background');
// Making it take the size of the page
$backgroundDiv.height($(window).height());
$backgroundDiv.width($(window).width());
$self.detach().appendTo($backgroundDiv);
// The window is hidden by default, showing it
$self.show();
$('html').prepend($backgroundDiv);
// Handling closing the window
$backgroundDiv.click(function(e){
var $target = $(e.target);
if(!$target.hasClass('window-background'))
return;
$self.hide();
$self.detach().appendTo('html');
$backgroundDiv.remove();
});
};
this.create();
if(attr.autoOpen){
this.open();
}
};
});
For now i have doubt about the fact that i'm putting the window out of his native block, in the end of the html document. I wish to put it back to his position but i have no idea yet how to do it. Any idea ?
First of all, you create a jQuery function, but you do it on document.ready $(...). You should just create it, otherwise the function will not be available for other code until document has loaded.
Then you want to insert the window in the same place as the original element, for that you have insertBefore and insertAfter in jQuery. You use prepend, but that inserts it as the first element of $self.
I would urge you to look at the method chaining of jQuery which may make your code much more readable. Instead of:
// Creating the background
var $backgroundDiv = $('<div></div>');
$backgroundDiv.addClass('window-background');
// Making it take the size of the page
$backgroundDiv.height($(window).height());
$backgroundDiv.width($(window).width());
use
// Creating the background
var $backgroundDiv = $('<div></div>')
.addClass('window-background')
// Making it take the size of the page
.css({
height:$(window).height(),
width:$(window).width()
});
for example.
You also use CSS classes to store information, like if something had been clicked or not. That may be OK, but consider that you may want change the CSS classes and suddenly the functionality of your code is strongly linked to the design. Maybe using .data() instead would be better, even if you add more code to also style your elements.
You use .wrap to take the original content and put it in the window. That may be what you wanted all along, but also take a look at https://api.jquery.com/clone/ which allows you to get the elements without removing them from their original source. Again, only if it works better for you.
As a last advice, use http://jsfiddle.net to share your working code, so other people may not only comment on it, but see it in action as well.
I have a function closeGeneralHelp which takes one parameter: idtag. The function is supposed to do the following:
a) slideUp the "Help" div,
b) slideDown a set of divs and then
c) scroll, jump, or otherwise go to a specific (but dynamically determined) other div of the set of divs that were exposed via the slideDown.
I have two classes of divs ("DivsToShow" and "DivToHide"). "DivsToShow" has a few other divs contained in it and each of those divs has a unique id (this is what idtag is).
Parts (a) and (b) work just fine. Scrolling to the specific (but dynamically determined) div seems to fail no matter what I try. Here is the code. Each /* */ comment block represents a separate, but failed (and flailing) attempt at making this work.
Any help on getting (c) to work? I am a JavaScript / jQuery infant. So any reasonably related advice / pointers are also appreciated.
function closeGeneralHelp(idtag){
$(".DivsToShow").slideDown("slow");
$(".DivToHide").slideUp("slow");
/* var divid = document.getElementById(idtag);
divid.style.display = 'block';
divid.scrollIntoView(true); */
/* document.getElementById(idtag).scrollIntoView();*/
/* $(window).scrollTo(idtag,800,{queue:true});*/
/* window.location.hash = idtag;*/
/* window.setTimeout(function() {window.scroll(0, findPos(idtag));}, 5);*/
}
Thank you!
You need a callback function, in this case after the slidedown is done:
$(".DivToHide").slideUp("slow");
$(".DivsToShow").slideDown("slow", function(){
var $ShownDiv = $(this);
// this is the callback of slidedown, after it is done, perform this:
$('html,body').scrollTop( $ShownDiv.scrollTop() );
// Or animated:
$('html,body').animate({scrollTop: $ShownDiv.scrollTop()}, 1000); // in ms
// Or more native JS
document.getElementById( $(ShownDiv)[0].id ).scrollIntoView();
});
If you have an old jQuery and cant upgrade, you might want to discard $("#someElement").scrollTop() in favor of $('#someElement').offset().top
Heyho,
I´am working on a project in my university and I´d like to use "Hammer.js".
I´ve downloaded the Carousel-Example and it works perfectly for me.
But I would like to start a the middle pane of my code and it´s not so simple I think.
It´s something like this:
http://img203.imageshack.us/img203/6326/schemeas.jpg
so Hammer.js starts always with the green screen. But I like to start with the yellow one.
I´ve added one swipe right to the init function but it looks horrible when the page is loading and could not be the goal ^^
I hope anyone of you have an idea how to solve my problem.
Try calling
carousel.showPane(1);
That will display the second pane instantly. You will want to put this near the bottom, right after where it says.
carousel.init();
If you're feeling adventurous you could try and make it automatically start with that pane as there's a variable inside the Carousel function called current_pane which is set to a default of 0 (the first pane). Altering this may work too but might require more code somewhere else. Experiment!
edit
NULL is right, it does animate it. Here's a more in depth method to set it without animation:
I found that the method responsible for changing which pane is showing was the setContainerOffset mthod which could be passed a variable to animate it. I previously told you to use showPane(2) but that then called
setContainerOffset(offset, true)
which caused the animation occur. What you should do instead is make a slightly different version of showPane...
this.setPane = function( index ) {
// between the bounds
index = Math.max(0, Math.min(index, pane_count-1));
current_pane = index;
var offset = -((100/pane_count)*current_pane);
setContainerOffset(offset, false);
};
You'll find it's almost identical to showPane except for the name and the fact that it calls setContainerOffset with animation: false. This will immediately show the pane of your choice and can be called using
carousel.setPane(index);
What I've done is added this to the init function so that it looks like this:
this.init = function() {
setPaneDimensions();
var c = this;
$(window).on("load resize orientationchange", function() {
setPaneDimensions();
c.setPane(current_pane);
//updateOffset();
})
};
Now you can change
var current_pane = 0;
to whatever you want and the carousel will always start with that pane when it's initialised! simple!
I've a scenario that requires me to detect animation stop of a periodically animated element and trigger a function. I've no control over the element's animation. The animation can be dynamic so I can't use clever setTimeout.
Long Story
The simplified form of the problem is that I'm using a third party jQuery sliding banners plugin that uses some obfuscated JavaScript to slide banners in and out. I'm in need of figuring out a hook on slideComplete sort of event, but all I have is an element id. Take this jsfiddle as an example and imagine that the javascript has been obfuscated. I need to trigger a function when the red box reaches the extremes and stops.
I'm aware of the :animated pseudo selector but I think it will need me to constantly poll the required element. I've gone through this, this, and this, but no avail. I've checked jquery promise but I couldn't figure out to use that in this scenario. This SO question is closest to my requirements but it has no answers.
P.S. Some more information that might be helpful:
The element isn't created by JavaScript, it is present on page load.
I've control over when to apply the plugin (that makes it periodically sliding banner) on the element
Most of the slideshow plugins I have used use changing classes at the end of the animation... You could extend the "addClass" method of jQuery to allow you to capture the class change as long as the plugin you use is using that method like it should:
(function($){
$.each(["addClass","removeClass"],function(i,methodname){
var oldmethod = $.fn[methodname];
$.fn[methodname] = function(){
oldmethod.apply( this, arguments );
this.trigger(methodname+"change");
return this;
}
});
})(jQuery);
I threw together a fiddle here
Even with obfuscated code you should be able to use this method to check how they are sending in the arguments to animate (I use the "options" object when I send arguments to animate usually) and wrap their callback function in an anonymous function that triggers an event...
like this fiddle
Here is the relevant block of script:
(function($){
$.each(["animate"],function(i,methodname){
var oldmethod = $.fn[methodname];
$.fn[methodname] = function(){
var args=arguments;
that=this;
var oldcall=args[2];
args[2]=function(){
oldcall();
console.log("slideFinish");
}
oldmethod.apply( this, args );
return this;
}
});
})(jQuery);
Well since you didn't give any indication as to what kind of animation is being done, I'm going to assume that its a horizontal/vertical translation, although I think this could be applied to other effects as well. Because I don't know how the animation is being accomplished, a setInterval evaluation would be the only way I can guess at how to do this.
var prevPos = 0;
var isAnimating = setInterval(function(){
if($(YOUROBJECT).css('top') == prevPos){
//logic here
}
else{
prevPos = $(YOUROBJECT).css('top');
}
},500);
That will evaluate the vertical position of the object every .5 seconds, and if the current vertical position is equal to the one taken .5 seconds ago, it will assume that animation has stopped and you can execute some code.
edit --
just noticed your jsfiddle had a horizontal translation, so the code for your jsfiddle is here http://jsfiddle.net/wZbNA/3/
Here is the example I'm looking to create...
Let's assume there are two divs, each containing some other HTML/Content (other divs). I would like to have one of these divs in the view on page load, and then after some number of seconds (let's say 5), scroll the second div onto the same place as the first div, and then repeating that process indefinitely until the user leaves the page.
The page and elements in question can be found at http://paysonfirstassembly.com/. I am attempting to animate the left sidebar with a class of dynamicPanel. There will be at least three of these divs, and they will nearly match up in content length.
I appreciate everybody's help. I am a very new client-side programmer and appreciate the respect that this community has with new developers.
Working demo of the following →
Here's a simple jQuery plugin I just made that will slide up the first div and place it at the end of the list. I've commented the code below to further explain so that this can just get you started and you can adjust it to your needs and learn about jQuery:
// the plugin declaration
$.fn.rotateEach = function ( opts ) {
// cache the element set
var $this = this,
// create some default options
defaults = {
delay: 5000
},
// pass the defaults to settings with any override options
settings = $.extend(defaults, opts),
// repeated rotation function
rotator = function ( $elems ) {
// slide up first element in set
$elems.eq(0).slideUp(500, function(){
// detach first element
var $eq0 = $elems.eq(0).detach();
// append it to wrapper
$elems.parent().append($eq0);
// fade it back in
$eq0.fadeIn();
// call rotator on reselection of elements
// since first element was moved to end
setTimeout(function(){ rotator( $( $elems.selector ) ); },
settings.delay);
});
};
// initial rotator call
setTimeout(function(){ rotator( $this ); }, settings.delay);
};
// invoke plugin
$('.dynPanelContent').rotateEach();
If you want to change the delay you can just pass it in as an option:
$('.dynPanelContent').rotateEach({ delay: 7500 }); // 7.5 seconds
Note: I also moved .dynPanelOpener and .dynPanelTitle within .dynPanelContent so that they're included in the animations.
See working example →