I'm working with cookies to run or not run a jQuery animation someone else built:
$(function () {
$('div.transitional').click(function () {
$('div.intro').removeClass('hidden');
$('div.final').off('click');
});
ShowDiv($("div.transitional.hidden")[0]);
});
function ShowDiv(target) {
target = $(target);
target.removeClass('hidden');
target.delay(500).animate({
opacity: 1.0
}, 300, 'easeInExpo', function () {
ShowDiv($("div.transitional.hidden")[0]);
})
}
I have the cookie part working, but I'm confused about the anonymous function and the "ShowDiv" function.
What is each part doing?
Functionally, the animation makes visible a series of pictures, then the whole site. I want to skip the animation and just make the whole site visible (if cookies='visited'.) I'd like to do this without rewriting the animation script.
Here's a link: http://claytonsalem.com/bottlecap.
What happens now is if you have the cookie the animation doesn't run and everything is hidden.
That script only fades in elements, one after the other. If you want to skip that, use something like this in the anonymous function (which is also known as a DOM ready handler) :
$(function() {
$('div.transitional').click(function() {
$('div.intro').removeClass('hidden');
$('div.final').off('click');
});
if(cookies === "visited") //Assuming you already have the variable set.
ShowDiv($("div.transitional.hidden")[0]);
else
$("div.transitional.hidden").css('opacity', 1).removeClass('hidden')
});
I will focus on how it works:
$("div.transitional.hidden")
This would select ALL elements with div.transitional.hidden, placing them in a list.
By placing [0] in the selector, we are picking ONLY the first element in this list.
Then, when the script begins to run, this element is modified by target.removeClass('hidden'), which removes the hidden class.
When the scripts ends, it calls the $("div.transitional.hidden")[0] selector again, but this time it will not include the previously selected element (because it no longer has the hidden class).
That's why the script show images one after the other: it removes the hidden class and selects the next remaining element.
You might refer to Karl's answer on how to show your whole site.
Related
Can you apply effects such as fadeOut() to the function itself? or you have to target elements itself?
Here an example is it possible to do this.
$(document).ready(function() {
Intro();
function Intro() {
$("<p id='hide'>Can you add effect to the function or only for element such as hide to the id left of me!</p>").insertBefore("#placeholder")
}
$(Intro()).hide();
$("#hide").hide();
})
I do notice that if you comment out the $(Intro()).hide(); There nothing on screen. if you comment out the $("#hide").hide(); There is double of sentences, yet leave both alone and/or comment out, it will just leave it at one sentence as it should be.
https://jsfiddle.net/Necrorifter/x6hcswtb/21/
Here's a breakdown of what's happening in your code. On the line where you call Intro(), it's running your Intro function, which inserts your hide paragraph. Worth noting is that Intro() doesn't return anything, so the result if calling Intro() is undefined, though it does produce the side effect of inserting content into your page.
Therefore, when you call $(Intro()).hide() next, that's going to again cause your side effect, inserting the paragraph again, but effectively you're doing $(undefined).hide() after that, not what you want.
I believe what you really want is:
function Intro() {
return (
$("<p id='hide'>Can you add effect to the function or only for element such as hide to the id left of me!</p>")
.insertBefore("#placeholder")
);
}
const intro = Intro();
intro.hide();
^- Here, you're only calling Intro() once so the content is only inserted once, and you're returning the created element so something can be done with it later on.
I have a galleria object with x images and everytime I go to the page, the first image is displayed.
But I want to display maybe the second image, depending on a method return value.
I know that the displayed image has the value display: list-item, and all others have display: none, but I have no idea how to set it programmatically.
Any ideas apprechiated, Ralf!
You can achieve this by either of these approaches, depends on your needs:
First approach:
A manual selection after the page loads, for example like this:
xhtml
<p:galleria widgetVar="galleriaWV">
...
</p:galleria>
js
<script>
//<![CDATA[
function changeActiveIndex(widgetVar, index, reposition) {
if (widgetVar && index) {
widgetVar.select(index, reposition);
}
}
$(document).ready(function () {
setTimeout(function () {
changeActiveIndex(PF('galleriaWV'), 2, false);
}, 500);
});
//]]>
</script>
This approach will have the following result:
Selecting the third image (bat3.jpg,index = 2), you will notice that the user first sees the 0 activeIndex by default (bat1.jpg) then after a few milliseconds the select takes effect, that's due the call of setTimeout, the reason behind that call in the docuemnt.ready is to make sure the widgetVar is initialized before making the call, preventing having errors like undefined object, however it's tricky to reduce it, because setTimout can be inaccurate.
Second approach:
This approach would be to monkey patch the _render function, since it's called just once, at the init, this will make sure the image is selected instantly with no delay in the contrary of the first approach.
<script>
//<![CDATA[
function changeActiveIndex(index) {
var oldRender = PrimeFaces.widget.Galleria.prototype._render;
PrimeFaces.widget.Galleria.prototype._render = function () {
this.cfg.activeIndex = index;
oldRender.apply(this, []);
}
}
changeActiveIndex(2);// to get the active image from bean, replace 2 with #{beanName.intIndexOfActiveImage} for example
//]]>
</script>
To note here, in this approach, you are changing all the Galleria components included in that page, for example if you have two Galleria defined in the same final page, they all end up with the same active index, if you have that case, you can check the widgetVar name for equality and execute accordingly.
I would go with the second approach, as it seems more natural from a UX point of view.
I want to hide a spinner div once ALL elements are loaded and in position on my page. I put a fadeOut() function on my spinner div in the window.on('load', ..., but I can see the tab/page is still loading even though the elements/assets are not in the correct css position yet. How do I force the spinner div to remain until everything is in place, i.e. until the loading icon on the tab is finished spinning?
This is my code:
$(window).load(function() {
$('#spinner').fadeOut();
}
jQuery(document).ready(function($){
// Append the spinner div.
$("#spinner").append(spinner.el);
}
It sounds like you have a large volume of CSS and it is taking a long time for the browser to compute the style for each element after all content for the page has loaded. You could do some experiments using your timeout idea, and polling one or more elements on the page to see when the computed style matches the expected style. The last element to be assigned a computed style might vary at each page load, and/or by browser, so you would definitely need to test your method. The example below uses some information from the accepted answer here to poll an element for an expected style.
var expectedTop="5px";
function ready() {
$('#spinner').fadeOut();
}
function poll() {
var o = document.getElementById("pollElementId");
var comp = o.currentStyle || getComputedStyle(o,null);
if(comp.top==expectedTop) {
ready();
}
else {
setTimeout("poll()",500);
}
}
jQuery(document).ready(function($){
$("#spinner").append(spinner.el);
poll();
}
Here pollElementId is the id of an element in the DOM that we are positioning via CSS.
I build a small color-picker module. But it only opens up (and then works) when pickColor is called a second time. I also tried to wrap the _openColorPicker into a setTimeout but that didn't work either. In fact, the color-picker didn't show up at all when I did that.
What I found interesting is that the binding to the change event works, so the $ selector must have found the element already.
So I have two questions:
1) why is the picker only showing after the second call to _openColorPicker?
2) why didn't the picker open at all when I wrapper the _openColorPicker call in a setTimeout?
Edit: The _openColorPicker functions gets executed after the user has right-clicked into the document and then clicked on context-menu which is now showing.
Complete Code:
const ColorUtils = {
_initialized: false,
_openColorPicker: function () {
$('#color-picker').click();
},
pickColor: function (onChangeCallback, context) {
if (!this._initialized) {
$('<input/>').attr({
type: 'color',
id: 'color-picker',
display: 'hidden',
value: '#ffffff'
}).appendTo('#centralRow');
this._initialized = true;
$('#color-picker').on('change', onChangeCallback.bind(context));
}
this._openColorPicker();
// version with timeOut
const scope = this;
setTimeout(function () {
scope._openColorPicker();
}, 1000);
}
};
export default ColorUtils;
Above code is used like ColorUtils.pickColor(onColorPicked, this);
Check out this post. Looks like you can't trigger a click on an invisible color picker. That answer suggests giving the element an absolute position and placing it off screen, like so:
position:absolute;
left:-9999px;
top:-9999px;
I tried to replicate your case (for what I understood) : JSFIddle
I made some changes.
I moved the $('<input/>') in a property of the object ColorUtils and appended it to the DOM with absolute position and outside the screen.
(And also commented display:'hidden' because it's either display:none or visibility:hidden and as a CSS property, not Html attribute)
On right clic on the document I instantiate the picker (and register the callback + context) then add a button to the DOM to trigger the picker again.
Does it fulfill your requirements ?
I am working on some tabbed navigation for my website and I have an issue I'd like to fix.
I've been scrambling my head all day and getting nowhere. Would really appreciate some help.
Here be the code: http://jsfiddle.net/EghAt/
1) Notice when you click Tab 1 and then immediately click Tab 2, Tab 1 continues to loop out all the results.
I would prefer if this stopped looping Tab 1 results and just started looping Tab 2 results.
Is this possible?
How do I achieve this?
Many thanks for any pointers
You can stop the previous animation in this function of yours, by adding the .stop(true, true) you see in this revised function:
function fadeOutItems(ele, delay) {
var $$ = $(ele), $n = $$.next();
// Toggle the active class
$$.toggleClass('active');
// Ensure the next element exists and has the correct nodeType
// of an unordered list aka "UL"
if ($n.length && $n[0].nodeName === 'UL') {
$('li', $n).each(function(i) {
// Determine whether to use a fade effect or a very quick
// sliding effect
delay ? $(this).stop(true, true).delay(i * 400).fadeToggle('slow') : $(this).stop(true, true).slideToggle('fast');
});
}
}
Since you call this on both the currently active tab and the newly active tab, this should stop any animations underway on the currently active tab.
See the jQuery doc on .stop() for details.
In looking at this code further, I believe it does what you literally asked for in your question (it stops the previous tab looping and starts the next tab), but I'm not sure that's actually what you want because it leaves the items in a tab only partially expanded. If that's what you want, then this will do that.
If that's not what you want, then the code will have to be modified a bit further to not only stop the currently running animations, but to put all the items for the old tab into the same state.
As I suspected, you actually want more than you asked for (per your most recent comments). You want the previously items to be hidden, no matter what state they were in previously. You can do that with this code where I changed the slideToggle() to a slideUp(). You can't use any form of toggle if the animation hasn't started yet because toggle will go the wrong way (it just reverses the state). Instead, when hiding you have to use a definitive animation that ends with the item not visible. You can use this code where I used slideUp() but you could pick something different if you wanted:
// A helper function that allows multiple LI elements to be either
// faded in or out or slide toggled up and down
function fadeOutItems(ele, show) {
var $$ = $(ele), $n = $$.next();
// Toggle the active class
$$.toggleClass('active');
// Ensure the next element exists and has the correct nodeType
// of an unordered list aka "UL"
if ($n.length && $n[0].nodeName === 'UL') {
$('li', $n).each(function(i) {
// Determine whether to use a fade effect or a very quick
// sliding effect
show ? $(this).stop(true, true).delay(i * 400).fadeToggle('slow') : $(this).stop(true, true).slideUp('fast');
});
}
}
You can see that in action here: http://jsfiddle.net/jfriend00/rzd3N/.
The problem is here.
$(this).delay(i * 400).fadeToggle('slow')
You are giving a fede effect to each element at once, by increasing delay.
It's not easy to stop it this way. The correct way to do this is to call a function which will only fade an element at a time. Then this function will be executed again at a given time interval (400 in your case), and fade the next element.
This way, passing a variable to the function, for example stopExecuting=true, will stop the effects.
Take a look at setInterval and setTimeout to achieve this.