Multiple random images per page, without repeat - javascript

So, I need to display 2 or 3 different images in a website, as simple parallax dividers for content.
I have an array of 4 images, so I'll be able to randomize without repeat them in the same page, althoug the random won't be that noticeable.
I've been lurking this for a while, and found these
Random Image Display, Without Repeat, with Javascript
<script language="javascript">
var imagesArray = [
'images/img-1.jpg',
'images/img-2.jpg',
'images/img-3.jpg',
'images/img-4.jpg',
'images/img-5.jpg',
];
var usedImages = {};
var usedImagesCount = 0;
function displayImage() {
var num = Math.floor(Math.random() * (imagesArray.length));
if (!usedImages[num]) {
document.canvas.src = imagesArray[num];
usedImages[num] = true;
usedImagesCount++;
if (usedImagesCount === imagesArray.length) {
usedImagesCount = 0;
usedImages = {};
}
} else {
displayImage();
}
}
</script>
(this was created to exhibit the image upon a click on a button, as it follows
<input onclick="displayImage();" type=button value="Click Here">
I tried to adapt it to my need, but the call on my page din't produce any results)
https://www.daniweb.com/programming/web-development/threads/266181/random-imageslinks-without-repeating
(this one, I couldn't quite understand why, but I wasn't able to apply the solution. not sure if it's the code or the way of calling the image that's wrong...)
http://www.utopiamechanicus.com/article/not-so-random-image-rotation-in-php-for-html-the-sequel/
<?php
// rotate images randomly but w/o dups on same page - format:
// <img src='rotate.php?i=0'> - rotate image #0 - use 'i=1'
// for second, etc
// (c) 2004 David Pankhurst - use freely, but please leave in my credit
$images = array(// list of files to rotate - add as needed
"img1.gif",
"img2.gif",
"img3.gif",
"img4.gif",
"img5.gif");
$total = count($images);
$secondsFixed = 10; // seconds to keep list the same
$seedValue = (int) (time() / $secondsFixed);
srand($seedValue);
for ($i = 0; $i < $total; ++$i) { // shuffle list 'randomly'
$r = rand(0, $total - 1);
$temp = $images[$i];
$images[$i] = $images[$r];
$images[$r] = $temp;
}
$index = (int) ($_GET['i']); // image index passed in
$i = $index % $total; // make sure index always in bounds
$file = $images[$i];
header("Location: $file"); // and pass file reference back
?>
(this one was supposed to work calling through:
<img src='mysite.com/rotate.php?i=0'>
but the images are still repeating themselves sometimes)
They didn't work for me, so I decided to start a new topic, because I'm really newbie (actually, I don't know writing nothing at all) at javascript, and can't figure out what's the best approach. I understood it would be something like randomize the items, assign each of them a position (a number, a character, a [i], etc), and then call for it in my php page. Could you guys please help me?

Not sure is that you want but this will give you randomized images (without repeat) on a page, every time different ones:
<?php
$img = array('img1.png', 'img2.png', 'img3.png', 'img4.png', 'img5.png', 'img6.png');
shuffle($img);
for($i=0; $i<3; $i++){
print '<img src="'.$img[$i].'"><br>';
}
?>
If you want to receive one image per call, one of the possible solutions is to use session:
image.php:
<?php
session_start();
function getImage() {
$img = array('img1.png', 'img2.png', 'img3.png', 'img4.png', 'img5.png');
shuffle($img);
foreach($img as $key => $val) {
if (!is_array($_SESSION['img'])) {
return $val;
} elseif (count($_SESSION['img']) >= count($img)) {
$_SESSION['img'] = array();
}
if (is_array($_SESSION['img']) && !in_array($val, $_SESSION['img'])) {
return $val;
}
}
}
?>
page.php:
<?php
include 'image.php';
for ($i = 0; $i < 3; $i++) {
$currImg = getImage();
$_SESSION['img'][] = $currImg;
echo $currImg . '<br>';
}
?>
All displayed images are stored into SESSION variable. When all images are displayed, this SESSION var is reset and will start a new cycle.

Related

Display random Images in product category page

I'm trying to show random images/video in product category pages. Every category page will display their own set of images.
I did it in the typical rookie way by adding in every product category page with their own respective set of images. Is there a way that I can use hooks to do it at functions.php for ease of maintenance?
var total_images = 7;
var image1 = document.getElementById('banner1');
var image2 = document.getElementById('banner2');
var image3 = document.getElementById('banner3');
var random_numbers = [];
var random_number;
var random_img = [];
random_img[0] = '<img src="banner1.jpeg">';
random_img[1] = '<img src="banner2.jpeg">';
random_img[2] = '<img src="banner3.jpeg">';
random_img[3] = '<img src="banner4.jpeg">';
random_img[4] = '<img src="banner5.jpeg">';
random_img[5] = '<img src="banner6.jpeg">';
random_img[6] = '<img src="banner7.jpeg">';
while(random_numbers.length < 3){
random_number = Math.floor((Math.random() * total_images));
if(random_numbers.indexOf(random_number) < 0){
random_numbers.push(random_number);
}
}
image1.innerHTML = random_img[random_numbers[0]];
image2.innerHTML = random_img[random_numbers[1]];
image3.innerHTML = random_img[random_numbers[2]];
The easy way - Install ACF plugin and create your fields - https://prnt.sc/1yek9zy .
For image field select image url. Duplucate Banner 1 as many banners you want and setup Location rules to taxonomy product category - https://prnt.sc/1yekgys
Then go to a product category and add your images and urls - https://prnt.sc/1yeklpf
If you have ACF pro go with repeater field instead. Its more dynamic and you can add as many banners you want per product category.
Use this visual hook guide to change where you want the banners to be showed - https://www.businessbloomer.com/woocommerce-visual-hook-guide-archiveshopcat-page/
function woo_category_banners() {
$term = get_queried_object();
$banners = get_field('banners', $term->taxonomy . '_' . $term->term_id);
if($banners):
echo '<div class="banners">';
foreach($banners as $k => $banner):
$banner_data = $banners[$k];
echo '<div class="banner"><img src="'.$banner_data['banner_image'].'"></div>';
endforeach;
echo '</div>';
endif;
}
add_action('woocommerce_before_shop_loop','woo_category_banners',40);
I have developed something similar in the past, but not in javascript, it was all php code.
I had added a new banner field in the categories with ACF (only one, you would have many), and then on the category page I would show that banner or, recursively, the father's banner, until I found one.
You would have multiple image fields, and you would extract one at random, maybe it can be useful to you.
In any case, the hook to use is: woocommerce_before_main_content action.
add_action('woocommerce_before_main_content','bannertop');
function bannertop() {recursebanner('banner_top','bannertop');}
function recursebanner($type,$class) {
if ( is_tax( 'product_cat' ) ) {
$term = get_queried_object();
$banner = get_field('banner_top', $term);
if ($banner) {
echo '<div class="'.$class.'">';
echo $banner;
echo '</div>';
} else {
// no banner defined, parse ancestors
$cat_ancestors = get_ancestors( $term->term_id, 'product_cat' );
foreach ($cat_ancestors as $cat_ancestor) {
$termancestor = get_term($cat_ancestor);
$banner = get_field($type, $termancestor);
if ($banner) {
echo '<div class="'.$class.'">';
echo $banner;
echo '</div>';
break;
}
}
}
}
}
If you want to use javascript instead, you have to add it in your js file in the child theme, and call the script for example like this:
$ (function () {
// your code
});

Javascript in functions.php

I cant seem to get the following code to work;
function add_js_functions(){
$gpls_woo_rfq_cart =
gpls_woo_rfq_get_item(gpls_woo_rfq_cart_tran_key() . '_' . 'gpls_woo_rfq_cart');
if(is_array($gpls_woo_rfq_cart)){
$count = count($gpls_woo_rfq_cart);
}else{
$count = 0;
}
?>
<script type="text/javascript">
var getQuoteIcon = document.getElementsByClassName("icon-account");
if(1 != 0) {
getQuoteIcon[0].style.display = "none";
}
</script>
<?php }
add_action('init','add_js_functions');
The php above the script stores a variable from the quote form on the number of items in the form.
I tried the javascript by itself and its seemed to work but its not working in the functions file.
At the moment im using (1 != 0) to make sure its true and to hide the item so I know the JS works, what will happen afterwards is this will become;
if (<?php $count != 0 ?>) {
//rest of the JS here
}
So that when the page loads, if the form is empty of items then this icon will be hidden (it starts off as inline-block and i dont know how to change this).
I think you want your php to be <?php echo $count != 0 ?>.
Your PHP is executed server-side, and Javascript client side, the two don't communicate by passing variables between the two. In order to get your PHP variable into your Javascript, you need to echo it.
It looks like you are loading the JS too soon and the element you are targeting isn't available yet.
Use add_action('wp_footer') to load the JS in the footer.
function add_js_functions(){
$gpls_woo_rfq_cart =
gpls_woo_rfq_get_item(gpls_woo_rfq_cart_tran_key() . '_' . 'gpls_woo_rfq_cart');
if(is_array($gpls_woo_rfq_cart)){
$count = count($gpls_woo_rfq_cart);
}else{
$count = 0;
}
?>
<script type="text/javascript">
var getQuoteIcon = document.getElementsByClassName("icon-account");
if(1 != 0) {
getQuoteIcon[0].style.display = "none";
}
</script>
<?php }
add_action('wp_footer','add_js_functions');

Use file_get_contents() and implode() to pass array to javascript not working

I am developing a simple image gallery which shows images and related caption.
All images are inside a directory and caption in another (as single files). A php script lists all files in both directories and pass arrays to a javascript wich change image and caption when the user press a button.
[...]
for($x = 2; $x < $lenght; $x++) {
$filesi[$x] = $imgdirectory."/".$lsi[$x];
}
for($x = 2; $x < $lenght; $x++) {
$filename = $capdirectory."/".$lsc[$x];
$filesc[$x] = file_get_contents($filename);
}
//Create array for JS
$captions = '["' . implode('", "', $filesc). '"]';
$images = '["' . implode('", "', $filesi). '"]';
?>
<script>
var captions = <?php echo $captions; ?>;
var images = <?php echo $images; ?>;
[...]
Images work properly and I can also print caption's file name instead of caption
i.e.
$filesc[$x] = $filename;
but when I use "file_get_contents()" to read file the gallery stops working.
If I echo $captions and manually set $captions with the very same output
e.g.
$captions='["first caption","second caption", "..."]';
the gallery works properly, so the array should be properly formatted...
Thank you in advance
SOLUTION
I was creating an array with two empty elements (0,1) in order to avoid ./ and ../ in file list, so I have added a +2 to the lsi index.
for($x = 0; $x < $lenght-2; $x++) {
$filesi[$x] = $imgdirectory."/".$lsi[$x+2];
}
In addition I have used json_encode, as suggested, instead of manual json encodig. The output seems to be the same but now the gallery works!
var images = <?php echo json_encode($filesi); ?>;
In JS you have to escape new lines in strings like this:
var multilineString = "this is\
just an example";
Maybe try to use trim() and str_replace() if you don't want to make it easier with json_encode().
UPDATE
Then I was wrong. Did you know that you can push items to arrays with just $array[] = 'item';?

Why doesn't this JavaScript function calculate correctly when the site is first loaded, but works fine afterwards?

I am working on a site that generates notation for a random musical rhythm based on some user-selected parameters. It does this by using an ajax call, which returns a random set of <img> elements that represent different notes. I have a function that is designed to scale the rhythm to fit in the screen, regardless of it's actual size.
The function is triggered after a successful ajax call, which is triggered by a click event on a button.
My problem is that the function does not work as desired when running the first time the page is loaded.
After the function runs for the first time, the height attribute of all of the <img> elements is somehow set to 0.
However, the function works great if I run the it again (by clicking the button). It also works fine after a page refresh.
Also, I do not have this issue in IE11, only Chrome (I haven't tested other browsers yet).
I have tried wrapping the code in both $(window).load() and $(document).ready() event handlers, but this didn't help.
The site in action can be found at http://www.rhythmrandomizer.com
Any help would be greatly appreciated!
Below is the relevant code:
Event handler for the button:
$("#randomize").click(function(){
//get general options from form
var timeSignature = $("#timeSignature").val();
var phraseLength = $("#phraseLength").val();
//get note options from form
var checked = [];
$("#noteOptions :checked").each(function() {
checked.push($(this).val());
});
//alert user and exit function if nothing is selected
if (checked.length < 1) {
alert("Please select at least one note value");
return;
}
//format note option ids into a delimited string
var noteOptions = "";
for (var i=0; i < checked.length; i++) {
noteOptions += checked[i] + "a";
}
//remove the final comma and space
noteOptions = noteOptions.substr(0, noteOptions.length - 1);
//ajax call
$.ajax("randomize.php", {
data : {
timeSignature : timeSignature,
phraseLength : phraseLength,
noteOptions : noteOptions
},
type : "GET",
success : function(response) {
$("#rhythm").html(response);
scaleRhythm();
},
error : function(xhr, status, errorThrown) {
console.log(status + " | " + errorThrown);
}
});
});
The php file that returns the rhythm notation:
<?php
//MySQL connection variables
$hostname = 'localhost';
$user = ini_get('mysqli.default_user');
$pw = ini_get('mysqli.default_pw');
$database = 'rhytxfpd_rhythmrandomizer';
//Connect to database
try {
$db = new PDO('mysql:host=' . $hostname . ';dbname=' . $database,$user,$pw);
} catch(PDOException $e) {
echo $e->getMessage();
die();
}
//Get values from GET
$timeSignature = $_GET['timeSignature'];
$phraseLength = $_GET['phraseLength'];
$noteOptString = $_GET['noteOptions'];
//Split up note options string
$noteOptions = explode('a', $noteOptString);
//Create sql query
$sql = 'SELECT
noteName,
noteValue,
noteGraphic
FROM
notes
WHERE';
//append noteOptions as WHERE clauses
foreach ($noteOptions as $opt) {
$sql = $sql . ' noteGroupID = ' . $opt . ' OR';
}
//remove final " OR"
$sql = substr($sql, 0, strlen($sql) - 3);
//query the database and get all results as an array
/* This will return a table with the name, graphic, and value of
* the notes that the user selected prior to submitting the form
*/
$stmt = $db->query($sql);
$result = $stmt->fetchAll();
//Get the total number of options selected
$numOpts = count($result);
/***************************/
/** BEGIN PRINTING RHYTHM **/
/***************************/
//div to begin the first measure
echo '<div class="measure" id="m1' . $measure . '">';
//Print time signature
echo '<img class="note" src="notes/' . $timeSignature . '.png" title="time signature ' .
$timeSignature . '/4" alt="time signature ' . $timeSignature . '/4"/>';
//Prints as many measures as indicated by the phrase length selection
$measure = 1;
while ($measure <= $phraseLength) {
//begin a new div for other measures.
if ($measure != 1) {
echo '<div class="measure" id="m' . $measure . '">';
}
//Prints random measure according to time signature
$beats = 0;
while ($beats < $timeSignature) {
//Generate a random number
$random = rand(0, $numOpts - 1);
//Get the random note from results
$note = $result[$random];
//Continues if chosen note will not fit in the measure
if ($beats + $note['noteValue'] > $timeSignature) {
continue;
}
//Prints random note
echo '<img class="note" src="notes/' . $note['noteGraphic'] . '.png" title="' .
$note['noteName'] . '" alt="' . $note['noteName'] . '"/>';
//Adds random note's value to total number of beats
$beats += $note['noteValue'];
//$beats++;
}
//If last measure
if ($measure == $phraseLength) {
echo '<img class="note" src="notes/1.png" title="double barline" alt="double barline"/>';
echo '</div>';
} else {
echo '<img class="note" src=notes/b.png title="barline" alt="barline"/>';
echo '</div>';
}
//Increment to next measure
$measure++;
}
The scaleRhythm() function:
function scaleRhythm() {
//Get width of rhythm at full resolution
var rhythmWidth = $("#rhythm").width();
//Get current screen/window width
var screenWidth = window.innerWidth;
//Compute ratio between curren screen and window widths
var ratio = screenWidth / rhythmWidth;
//Multiply img note height by ratio, then by 90% to provide some
//breathing room on either side of the rhythm
var newHeight = (400 * ratio) * .9;
//Set img note height to new height or 300px, whichever is smaller
if (newHeight < 300) {
$(".note").css("height",newHeight);
//code to center rhythm horizontally
$("#rhythm").css("margin-top",(300-newHeight)/2);
} else {
$(".note").css("height",300);
$("#rhythm").css("margin-top",0);
}
}
Add this javascript to your <script></script>:
$(function(){ $("#randomize").click(); });
This will cause your page to run the function that populates your random elements then (at the end of that function) run the scale function.
I tested it by running it on your page in the chrome console and it worked.
If you put a breakpoint in the scaleRhythm function you'll notice on page load it's not being run. You've defined the function but it is not being called on page load. In fact none of the code you want run (ie: the ajax call) gets called until the first click happens. So what you need to do is trigger the click event on the button like JRulle said.
$("#randomize").click();
Okay so here is your issue.
The first time you click the button, var rhythmWidth = $("#rhythm").width(); evaluates to "0" because it is empty.
Which causes these subsequent functions to be "0" as well:
var ratio = screenWidth / rhythmWidth;
var newHeight = (400 * ratio) * .9;
I would edit your function to be like so:
var rhythmWidth = $("#rhythm").width();
if (rhythmWidth == 0) { rhythmWidth = 10; } //assign some reasonable value here
since your function does not support a rhythmWidth of "0"

show result from PDO query every 10 seconds

Not sure if this is possible but here goes, I have a basic PDO query that stores the results in a array.
<?php
// configuration
$dbtype = "";
$dbhost = "";
$dbname = "";
$dbuser = "";
$dbpass = "";
// database connection
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
$title = 'PHP AJAX';
// query
$sql = "SELECT * FROM thankyou";
$q = $conn->prepare($sql);
$q->execute(array($title));
$q->setFetchMode(PDO::FETCH_BOTH);
// fetch
while($r = $q->fetch()){
echo"<br>";
print_r ($r);
}
?>
Now the bit I can't get my head around, I have also never used JavaScript. Can I rotate through the results to show one at a time for 5-10 seconds then show another? It can be random or in order, I'm not fussed. I found this, which works, but can't figure out how to get the array into it. I am aware one is client side and one is server side.
<script type="text/javascript">
var rotatingTextElement;
var rotatingText = new Array();
var ctr = 0;
function initRotateText() {
rotatingTextElement = document.getElementById("textToChange");
rotatingText[0] = rotatingTextElement.innerHTML; // store the content that's already on the page
rotatingText[1] = "need to write PDO array here";
setInterval(rotateText, 5000);
}
function rotateText() {
ctr++;
if(ctr >= rotatingText.length) {
ctr = 0;
}
rotatingTextElement.innerHTML = rotatingText[ctr];
}
window.onload = initRotateText;
</script>
and this is were the results are shown
<span id="textToChange">this is were the result is displayed</span>
If I need to do it a totally different way, it's not a problem if someone can point me in the correct direction.
If you're not so familiar with JavaScript, I also suggest using some JS library for the task. In fact, Prototype.js has a class exactly for this purpose: http://prototypejs.org/doc/latest/ajax/Ajax/PeriodicalUpdater/index.html
A working example: http://www.tutorialspoint.com/prototype/prototype_ajax_periodicalupdater.htm
i decided to use AJAX to call a seprate PHP page in the end and works fine this is the updated page.
<script type="text/javascript">
$(function() {
getStatus();
});
function getStatus() {
$('div#status').load('thankyou.php')//Thankyou being the page the query is on
setTimeout("getStatus()",5000);//refreshes every 5 seconds
}
</script>
The query itself is a standard PDO
$query = $db->query("SELECT * FROM `thankyou` ORDER BY RAND() LIMIT 1
Thanks for the pointers all.

Categories

Resources