Primefaces Galleria Set the image to display on pageload - javascript

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.

Related

Change javascript variable in seperate element

I run a WoW guild forum based on php (phpbb), javascript and html. Ever since long, Wowhead allows links to be posted to their item/spell IDs etc. The basic code to the Wowhead JS and it's variables is:
<script src="//static.wowhead.com/widgets/power.js"></script>
<script>var wowhead_tooltips = { "colorlinks": true, "iconizelinks": true, "renamelinks": true }</script>
There is an extension that puts this code in the footer of every page via a HTML file. Every Wowhead link posted will be converted in a link with a tooltip explaining what it links to. The '"renamelink": true' portion of the wowhead_tooltips variable makes it as such that any link of an item or spell is renamed to the exact name of what it is linked to.
The problem: when I generate custom URLs using a Wowhead link, ie:
Teleport
instead of displaying 'Teleport' with a tooltip of Blink, it will rename the entire URL to Blink with an icon, as described in the wowhead_tooltips variable.
What I want to achieve is:
Any direct URL to Wowhead should be converted into a renamed spell/item.
Any custom URL to Wowhead should be retain it's custom text, but retrieve the tooltip.
This should both be possible on a single page.
The best solution I have come up with is to add an 'if' function to var wowhead_tooltips based on class, then add the class to URLs:
<script>if ($('a').hasClass("wowrename")) { var wowhead_tooltips = { "colorlinks": true, "iconizelinks": true, "renamelinks": false } }</script>
<a class="wowrename" href="http://www.wowhead.com/spell=1953">Teleport</a>
This works, however, the problem with this solution is that once the script recognizes one URL with the class "wowrename" on the page it will stop renaming all links, meaning that custom URLs and direct URLs can't be mixed on a single page.
Any other solution I've tried, using IDs, defining different variables etc either don't work or come up with the same restriction.
Hence the question, is it possible to change Javascript variables (in this case "var wowhead_tooltips { "renamelinks": false}" per element (URL), based on id, class or anything else?
Direct link that gets renamed with tooltip and iccn.
Teleport
Custom link with tooltip and original text.
I've stored the original link text as a data attribute so we can restore it after it's been changed.
<a class="wowrename" href="http://www.wowhead.com/spell=1953" data-value="Teleport">Teleport</a>
Keep checking for when static.wowhead.com/widgets/power.js changes the last link text. Once changed, restore using the data-value value, remove the styling added that creates the icon and stop the timer.
$(function () {
//timmer
checkChanged = setInterval(function () {
// check for when the last link text has changed
var lastItem = $("a.wowrenameoff").last();
if (lastItem.text() !== lastItem.data('value')) {
$("a.wowrenameoff").each(function () {
//change value
$(this).text($(this).data('value'));
//remove icon
$(this).attr('style', '');
//stop timer
clearInterval(checkChanged);
});
}
i++;
}, 100);
});
This does cause the link icon to flicker on then off, but it is repeated after a page refresh.
JSFiddle demo
This is simple solution. It's not the best way.
var wowhead_tooltips = { "colorlinks": true, "iconizelinks": true, "renamelinks": true }
$('a').hover(function() {
if ($(this).hasClass('wowrename') {
wowhead_tooltips.renamelinks = true;
}
else {
wowhead_tooltips.renamelinks = false;
}
});
I don't know how exactly wowhead API works, but if wowhead_tooltips variable is loaded exactly in the moment when the user points the link with the mouse (without any timeout) - this can fail or randomly work/not work.
The reason can be that the javascript don't know which function to execute first.
I hope this will work. If it's not - comment I will think for another way.
You have to loop on all the links, like this:
$("a.wowrename").each(function() {
// some code
});

window interval - checking for element on page and then appending to it

I am trying to wrap some code around jQuery that will continually check for an element on a page and when that element is present, append a defined variable to it. in this case i'm looking for a specific div with a unique ID and trying to append a defined iframe. here's what i have.
window.myInterval = setInterval(function() {
$('#thankyou-container').append(iframehtml);
clearInterval(window.myInterval);
}
), 50);
UPDATE:
Here's the code that I'm trying to insert into the #thankyou-container but have it load after the page loads. The issue I'm having is that this ad code (below) only loads on the page when I refresh my browser. It's so weird that it doesn't display right away:
<script type="text/javascript">
vm_load({
"displayId": "12584",
"publisherId": "33927",
"campaign": "9380",
"maxResults": "3",
"areaofstudy":
JSON.parse(jQuery.cookie('CategorySubCategorySpecialty')).CATEGORIES[0].text.replace('Business','1').replace('Criminal Justice & Legal','3').replace('Education','5').replace('Fine Arts & Design','2').replace('Health & Medicine','8').replace('Liberal Arts & Humanities','5').replace('Math, Science & Engineering','9').replace('Public Affairs & Social Sciences','13').replace('Religious Studies','5').replace('Technology','9').replace('Vocational Training',''),
"md": "1"
});
</script>
jQuery is loaded on the page, and the javascript file that references the vm_load function is loaded prior to this code.
I think I need something that wraps around the code and tells it to load after the page is finished loading. Could that be the solution?
This should fix your problem...
window.myInterval = setInterval(function() {
var $container = $('#thankyou-container');
if ($container.length) {
clearInterval(window.myInterval);
$container.append(iframehtml);
}
), 50);
It will check that the element exists. If it doesn't, nothing happens. If it does then it clears the interval and does the append.
However, I'd recommend this approach instead...
function containerAppend() {
var $container = $('#thankyou-container');
if ($container.length) {
$container.append(iframehtml);
}
else {
setTimeout(containerAppend, 50);
}
}
containerAppend();
It's a little more convoluted, but it uses timeouts instead of intervals so that it takes into account anything that takes time. With the original method you could find the element search taking longer than 50ms, which could cause problems.

How does this animation work?

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.

force DOM redraw with javascript on demand

The title of the question expresses what I think is the ultimate question behind my particular case.
My case:
Inside a click handler, I want to make an image visible (a 'loading' animation) right before a busy function starts. Then I want to make it invisible again after the function has completed.
Instead of what I expected I realize that the image never becomes visible. I guess that this is due to the browser waiting for the handler to end, before it can do any redrawing (I am sure there are good performance reasons for that).
The code (also in this fiddle: http://jsfiddle.net/JLmh4/2/)
html:
<img id="kitty" src="http://placekitten.com/50/50" style="display:none">
<div>click to see the cat </div>
js:
$(document).ready(function(){
$('#enlace').click(function(){
var kitty = $('#kitty');
kitty.css('display','block');
// see: http://unixpapa.com/js/sleep.html
function sleepStupidly(usec)
{
var endtime= new Date().getTime() + usec;
while (new Date().getTime() < endtime)
;
}
// simulates bussy proccess, calling some function...
sleepStupidly(4000);
// when this triggers the img style do refresh!
// but not before
alert('now you do see it');
kitty.css('display','none');
});
});
I have added the alert call right after the sleepStupidly function to show that in that moment of rest, the browser does redraw, but not before. I innocently expected it to redraw right after setting the 'display' to 'block';
For the record, I have also tried appending html tags, or swapping css classes, instead of the image showing and hiding in this code. Same result.
After all my research I think that what I would need is the ability to force the browser to redraw and stop every other thing until then.
Is it possible? Is it possible in a crossbrowser way? Some plugin I wasn't able to find maybe...?
I thought that maybe something like 'jquery css callback' (as in this question: In JQuery, Is it possible to get callback function after setting new css rule?) would do the trick ... but that doesn't exist.
I have also tried to separte the showing, function call and hiding in different handlers for the same event ... but nothing. Also adding a setTimeout to delay the execution of the function (as recommended here: Force DOM refresh in JavaScript).
Thanks and I hope it also helps others.
javier
EDIT (after setting my preferred answer):
Just to further explain why I selected the window.setTimeout strategy.
In my real use case I have realized that in order to give the browser time enough to redraw the page, I had to give it about 1000 milliseconds (much more than the 50 for the fiddle example). This I believe is due to a deeper DOM tree (in fact, unnecessarily deep).
The setTimeout let approach lets you do that.
Use JQuery show and hide callbacks (or other way to display something like fadeIn/fadeOut).
http://jsfiddle.net/JLmh4/3/
$(document).ready(function () {
$('#enlace').click(function () {
var kitty = $('#kitty');
// see: http://unixpapa.com/js/sleep.html
function sleepStupidly(usec) {
var endtime = new Date().getTime() + usec;
while (new Date().getTime() < endtime);
}
kitty.show(function () {
// simulates bussy proccess, calling some function...
sleepStupidly(4000);
// when this triggers the img style do refresh!
// but not before
alert('now you do see it');
kitty.hide();
});
});
});
Use window.setTimeout() with some short unnoticeable delay to run slow function:
$(document).ready(function() {
$('#enlace').click(function() {
showImage();
window.setTimeout(function() {
sleepStupidly(4000);
alert('now you do see it');
hideImage();
}, 50);
});
});
Live demo
To force redraw, you can use offsetHeight or getComputedStyle().
var foo = window.getComputedStyle(el, null);
or
var bar = el.offsetHeight;
"el" being a DOM element
I do not know if this works in your case (as I have not tested it), but when manipulating CSS with JavaScript/jQuery it is sometimes necessary to force redrawing of a specific element to make changes take effect.
This is done by simply requesting a CSS property.
In your case, I would try putting a kitty.position().left; before the function call prior to messing with setTimeout.
What worked for me is setting the following:
$(element).css('display','none');
After that you can do whatever you want, and eventually you want to do:
$(element).css('display','block');

Change element from main page

On my https://getsatisfaction.com/gsfnmichelle/products page, there's a bread crumb trail that says "Products." I'm trying to change that to "Categories." I can get it to do that within the inspector, but when I put the code in the customization script (which is only the main page /gsfnmichelle on the platform I'm using), it doesn't work.
Even though I was able to get the correct element (jQuery('.crumb_link span');) and change it using ( jQuery('.crumb_link span').text('Categories');), I can't figure out how to change it when it's within another page (/products) besides the main one (/gsfnmichelle), since it's the only place where we can insert customization code.
I thought something like this would check for the page and change that element, but it doesn't work:
jQuery(document).ready(function () {
if (window.location.pathname =="/gsfnmichelle/products") {
jQuery('.crumb_link span').text('Categories');}
};
Then I tried to use an if statement to check for the right element, but that doesn't work either:
jQuery(document).ready(function () {
if (jQuery('.crumb_link span').text =='Products') {
jQuery('.crumb_link span').text('Categories');}
};
What am I missing?
You probably want to use either if (jQuery('.crumb_link span').text() == "Products") or jQuery('.crumb_link span:contains(Products)').text('Categories').
Your current condition will never be true.

Categories