I have implemented three star rating system based on popularity count in my website, but now my client wants to change colors of those three stars (default blue) to red, blue and green which shows the (degree of) popularity.
I've implemented this star rating system using CSS sprites, where I included two star images - golden and gray, in one sprite and displaying these using some logic. Works fine for one color, but how to implement three colours for each star?
HTML
<div class="star-box">
<li>
<span class="stars"><?php echo $position;?></span>
</li>
</div>
PHP
if( !isset($_SESSION['ranking']) || $_SESSION['ranking']['points'] <= 1000 ) {
if( !isset($_SESSION['ranking']['points']) || $_SESSION['ranking']['points'] == '' ) {
$position = '0px';
$position = 0.00;
} else {
$position = ($_SESSION['ranking']['points'] * 0.14).'px';
$position = 0.75;
}
$str1 = 'class="active" ';
$str1 .= ' style="background-position:'.$position.' 9px;"';
}
if( $_SESSION['ranking']['points'] > 1000 && $_SESSION['ranking']['points'] <= 5000 ) {
if( !isset($_SESSION['ranking']['points']) || $_SESSION['ranking']['points'] == '' ) {
$position = '0px';
$position = 0.00;
} else {
$position = ($_SESSION['ranking']['points']*0.035).'px';
$position = 1.40;
}
}
jQuery
$(function() {
$('span.stars').stars();
});
$.fn.stars = function() {
return $(this).each(function() {
// get the value
var val = parseFloat($(this).html());
// make sure that the value is in (0 - 5) range, multiply to get width
val = Math.round(val * 4) / 4;
var size = Math.max(0, (Math.min(5, val))) * 16;
// create stars holder
var $span = $('<span />').width(size);
// replace the numerical value with stars
$(this).html($span);
});
}
CSS
span.stars, span.stars span {
display: block;
background: url(../../images/stars.png) 0 -16px repeat-x;
width: 50px;
height: 20px;
text-indent: -9999px;
}
span.stars span {
background-position: 0 0;
}
SPRITE IMAGE :
You could use session variables etc to control your CSS directly by using a php/css file. You could set star color, sprite position, all based on logic.
Link to your css
<link rel='stylesheet' type='text/css' href='css/style.php' />
Your css/php document
<?php
header("Content-type: text/css; charset: UTF-8");
$CSSposition = $position;
?>
span.stars span {
background-position: <?php echo $CSSposition ?>;
}
Here's a link to php/css document tutorial click here
Check this tutorial on knockout they show how to do the star rating system which you can apply to your code http://learn.knockoutjs.com/#/?tutorial=custombindings
Related
I have a little generator, It generate a random phone numbers and here is my code.
<?php
limit_phone = 8; //limit phone number
$randomphone = substr(str_shuffle(str_repeat("0123456789", $limit_phone)), 0, $limit_phone); //random numbers
$randomphonecomp = array('010','011','012','015'); // company
$randomphonecomp1 = array_rand($randomphonecomp);
$phonefinaal = $randomphonecomp[$randomphonecomp1] . $randomphone;
echo $phonefinaal. "<br>";
?>
What I want is, when i run this file to work more than one time, means that i want this file to generate automatically with out stop until i stop the page from the browser
You can use a loop to generate specified number of phone numbers, Don't use an infinite loop, it will kill your browser and you will not able to stop the loop.
<?php
$total_numbers = 100;
$i=1;
while($i<=$total_numbers){
$limit_phone = 8; //limit phone number
$randomphone = substr(str_shuffle(str_repeat("0123456789", $limit_phone)), 0, $limit_phone); //random numbers
$randomphonecomp = array('010','011','012','015'); // company
$randomphonecomp1 = array_rand($randomphonecomp);
$phonefinaal = $randomphonecomp[$randomphonecomp1] . $randomphone;
echo $phonefinaal. "<br>";
$i++;
}
?>
As #bcperth said, you most likely need to generate phone numbers using Javascript in the page, it could be something like this:
var divNumbers = document.getElementById("numbers")
var btnStop = document.getElementById("stop")
function generate() {
var randomphone = ""
for(var i = 0; i < 8; ++i) randomphone += Math.floor(Math.random()*10)
var randomcomp = ['010', '011', '012', '015'][Math.floor(Math.random()*4)] + ""
divNumbers.innerHTML += randomcomp + randomphone + "<br>"
}
generate() // first generated number
var intervalGen = setInterval(generate, 2000) // others generated number
function stop() {
clearInterval(intervalGen)
}
btnStop.addEventListener("click", stop)
#stop {
border: 1px solid grey;
padding: 2px 5px;
cursor: pointer;
}
<span id="stop"> STOP </span>
<div id="numbers"></div>
Documentation:
setInterval() - Web APIs | MDN
Math.random() - JavaScript | MDN
Math.floor() - JavaScript | MDN
Let me try and explain myself, but my code below will probably do most of the talking. I want to loop through my data and insert a "row" div for every 6 images that are looped through. You can see from my code below how I am currently achieving this, but I know there is a better way.
I need to either check the loop in multiples of 6 to echo "row" and multiples of 6-1 (5, 11, etc) to echo the closing div tag, or is there way I can change my data into a collection of arrays containing 4 thumbnails each?
I will let the code do the talking now (I am using blade templating with laravel).
<div class="carousel-inner">
<?php
$i = 0;
$templatesInView = 6; ?>
#foreach ($templates as $template)
#if($i == 0 || $i % $templatesInView == 0)
<div class="row item #if($i==0){{{ 'active' }}}#endif">
#endif
<div class="col-sm-2">
<img src="{{{ asset($template->img) }}}" />
</div>
#if($i == 5 || $i == 11 || $i == 17 || $i == 15 || $i == (count($templates)-1))
</div>
#endif
<?php $i++; ?>
#endforeach
</div>
Edit - OK, I have just found array_chunk() which does exactly what I need, but it would be good to hear if there are any other alternatives.
One of the easiest ways of adding pages to a 'list' of things stored in an 'array' is to use the array_group_by_n function. This takes any array and using 'callbacks' will call functions at the appropriate times.
I supply some tested code that demonstrates this. It is based on your code.
I use PHP 5.3.18
The code generates a random number of 'images' (MyImage class) and then displays them in 'pages' of up to 6, as you request.
<?php session_start();
/*
* Using an array function called:
* array_group_by_n
*/
include 'function_array_group_by_n.php';
// ================ global data -- Only things you need to change ===========
$templates = array(); // array of images == you supply this
$templatesInView = 6; // max number of templates in the view
// --------------- end of stuff that you need to change -----------------------
// functions called by function array_group_by_n
// function to call at Group start
$beforeGroupStart =
function($firstRow) {
echo '<div class="row item"> <!-- start of template group -->';
echo "<p>Template Group Start: {$firstRow->getName()}</p>";
};
// function to call for every record in a group
$inGroup =
function($row, $rowNumber) {
echo '<div class="col-sm-2">';
echo '<p>LineNumber: ', $rowNumber, ' : img source: ', $row->getName(), '</p>';
echo '</div>';
};
// function to call at Group End
$afterGroupEnd =
function() {
echo '</div>';
echo '<p>Template Group End</p>';
};
// include 'Q22683444_test_data_setup.php';
// generateTestData(); // i need this
?>
<!-- --------------- style the output so you can see what is happening -------- -->
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Paging an Array</title>
<html>
<head>
<style>
.row {
background-color: yellow;
border: 4px solid green;
padding: 5px;
margin-top: 5px;
}
p {color: blue;}
.col-sm-2 {
background-color: white;
border: 2px solid red;
padding: 3px;
}
.carousel-inner {
background-color: grey;
border: 4px solid blue;
padding: 5px;
margin-top: 5px;
}
</style>
</head>
<body>
<h2>Random Template count is: <?php echo count($templates); ?></h2>
<div class="carousel-inner"> <!-- carousel start -->
<?php
// now process the array details...
$totalRows = array_group_by_n($templates, $templatesInView,
/* callable */ $beforeGroupStart,
/* callable */ $inGroup,
/* callable */ $afterGroupEnd
);
?>
</div> <!-- carousel end -->
<?php echo '<br />', "Total Images Processed was: ${totalRows}" ,'<br />'; ?>
</body>
</html>
<?php exit; // leave script ?>
<!-- ------------------ end of the processing ------------------------ -->
Obviously, you need the 'array_group_by_n' function details:
<?php
/*
* function: array_group_by_n
*
* Use: iterates over an array and calls user functions as explained below
*
* parameters:
*
* 1) array: the array to be grouped
*
* 2) integer: size of each group
*
* there are three 'callable' routines required
*
* a) before the group starts
* parameter passed: the first record of the group -- DO NOT PRINT IT!
* Use the contents if you have, say, title information
* in it.
*
* b) each row in the group
* parameters passed: 1) the value of the current array entry
* 2) the group entry number - zero based
*
* c) after the current group ends
* parameter passed: none
*
* #returns integer - count of rows processed
*/
function array_group_by_n(array $data = array(), $groupSize = 0,
/* callable */ $beforeGroup = null,
/* callable */ $inGroup = null,
/* callable */ $afterGroup = null)
{
$theIterator = new ArrayIterator($data);
$processedRows = 0;
$currentEntryNo = 0;
while ($theIterator->valid()) { // process the array
// start of group...
if ($groupSize >= 1) { // only called if required...
if (is_callable($beforeGroup)) { // and is valid routine
call_user_func($beforeGroup, $theIterator->current());
}
}
// initialize the current group
$currentEntryNo = 0;
/*
* process the group body
*/
do {
if (is_callable($inGroup)) { // is valid routine
call_user_func($inGroup,
$theIterator->current(),
$currentEntryNo);
}
$currentEntryNo++;
$processedRows++;
$theIterator->next(); // next entry or end of array
}
while ($theIterator->valid() && $currentEntryNo < $groupSize);
// end of group...
if ($groupSize >= 1) { // only called if required...
if (is_callable($afterGroup)) { // and is valid routine
call_user_func($afterGroup);
}
}
}
// all done -- go home
return $processedRows;
}
?>
For completeness i include the 'test generator' script.
<?php // ----------------- my test data -- ignore this --------------------
// test class - holds an 'image description'
class MyImage {
private $imageName = '';
public function __construct($imageIdx) {
$this->imageName = 'i am image with index: '. $imageIdx;
}
public function getName() {
return $this->imageName;
}
}
function generateTestData()
{
global $templates;
// ------------------------- start of test data --------------------------------
//
// test data -- array of image descriptions -- ensure count is defferent on each run
if (!isset($_SESSION['prevCount'])) {
$_SESSION['prevCount'] = -1;
}
do {
$randomCount = mt_rand(1, 20);
}
while ($randomCount == $_SESSION['prevCount']);
for ($i = 0; $i < $randomCount; $i++) { // fill $templates with test images
$templates[] = new MyImage($i);
}
// ------------------------- end of test data ----------------------------------
}
?>
I use the Sidebar Navigation Menu Professional for Magento by CODNITIVE and I am trying to make it expanded by default. Particularly I need a solution to make just the first list item expanded by default. I try to edit Navigation.php in app/code/community/codnitive/sidenav/block/:
$collapsibleClass = '';
if ($config->isCollapsible()) {
$collapsibleClass = ' collapsible';
}
// add collapsible arrow and wrraper
$arrow = '';
$extraStyle = '';
$collapsibleIconPosition = $config->getCollapsibleIconPosition();
if ($config->isCollapsible()) {
$width = $config->getCollapsibleIconType() === 'arrow' ? 8 : 16;
$height = 0;
$expanded = 0;
if ($hasActiveChildren) {
$width = $config->getCollapsibleIconType() === 'arrow' ? 8 : 16;
$height = 16;
}
if ($height == 0) {
$extraStyle = ' display:none;';
}
if ($height == 0 && $collapsibleIconPosition === 'left') {
$liMarginLeft += $width;
}
if ($this->isCategoryActive($category)) {
$expanded = 1;
}
$expanded = ' expanded="' . $expanded .'"';
$spanOnclick = 'onclick="Codnitive.expandMenu(this.parentNode)';
$spanClass = $config->getCollapsibleIconType() . '-' . $collapsibleIconPosition;
$arrow = '<span class="' . $spanClass . ' " ' . $spanOnclick . '" style="width: ' . $width . 'px; height: ' . $height . 'px;' . $extraStyle . '"></span>';
}
If I add this code to make the desired category expanded
if ($category->getId() == '35') {
$expanded = 1;
}
there appear two problems:
The category remains expanded even if another category is active.
The "plus" sign (showing that the category can be expanded) remains but it should be "minus". I guess $collapsibleIconPosition should be 'right'?
if ($height == 0 && $collapsibleIconPosition === 'left') {
$liMarginLeft += $width;
}
Try this, though i'm not sure which parent it's setting to block. I assume it's the first <li> tag above the a tag since the span tag isn't a parent
$( document ).ready(function() {
$('.nav-1').css( "display", "block" );
});
See if this is how you want it http://jsfiddle.net/6VSUm/
You want to execute that javascript anytime after (enough of) your HTML has loaded.
If your site uses jQuery, you can put it in a ready callback:
$(function(){
Codnitive.expand(document.getElementById('the-menu-parent-element-id'))
})
You can put it at the very end of your html document, or at least after all the navigation HTML code.
...
<script type="text/javascript" language="javascript">
Codnitive.expand(document.getElementById('the-menu-parent-element-id'))
</script>
</body>
Or you can put it in a onload callback. (warning: this might interfere with other javascript on your site) If there is an existing window.onload, it is safe to add it at the beginning or end of that function.
window.onload = function(){
Codnitive.expand(document.getElementById('the-menu-parent-element-id'))
}
The element you want to target is: <ul class="level0 collapsible" ...
It doesn't have a id currently, so you can't directly use getElementById().
One solution (not my favorite approach) would be to add an id
<ul id="start-open" class="level0 collapsible" ...
And then expand it:
Codnitive.expand(document.getElementById('start-open'))
I think the best solution would be to modify the HTML to do what expand would do to it:
<li class="level0 nav-1 first parent collapsible" style="margin-left: 0px;">
<span class="plus-right " onclick="Codnitive.expandMenu(this.parentNode)" style="width: 16px; height: 16px;background-position: right center"></span>
<a class="collapsible-wrapper collapse-name" onclick="Codnitive.expandMenu(this.parentNode);return false;" href="#"><span class="category_name">WANT TO BE EXPANDED BY DEFAULT</span></a>
<ul class="level0 collapsible" style="margin-left: 5px; padding-left: 10px;display: block" expanded="1">
<span class="plus-right"... gets the style="...;background-position: right center".
<ul class="level0"... gets expanded="1" and style="...;display:block"
If this doesn't work for you, it would be really helpful to see a live version of your code. (The fiddle, lacking JS and CSS isn't enough)
Never could have imagined that chrome would have been the browser giving me grief, but the slideshow for our new website does not function properly in some versions of Chrome.
The error occurs here:
"mainPicture.src = \''.$directory.$current_pic.'\'; setMarkerPos('.$i.')"
Claiming that I can't modify mainPicture, an id that doesn't exist.
Obviously, other browsers don't have a problem seeing this object.
All help is much appreciated!
.
You can find the page here.
Source code:
<?php
/********************************************************************
* GATHER IMAGES FROM IMAGE DIRECTORY *
********************************************************************/
// Define directory where images are stored
$directory = "../../images/slideshow/";
// Create blank array to store image names
$pic_array = array("");
$num_pics;
// Create number to define position of images in array
$counter = 0;
// Gather pictures from image directory
if(is_dir($directory))
{
// Open directory to view files
if($dh = opendir($directory))
{
// Continue while still files to view
while(($file = readdir($dh)) !== false)
{
// Stop if picture limit of 6 reached
if($counter == 6)
break;
// Gather if object found is file or directory
$file_check = filetype($directory.$file);
// If object is a file, add it to the slideshow
if ($file_check == "file")
{
$extension = substr($file, strpos($file, "."));
if ($extension == ".png" || $extension == ".jpg")
{
$pic_array[$counter] = $file;
$counter++;
}
}
}
}
}
// Determine number of pics gathered
$num_pics = count($pic_array);
?>
<html>
<head>
<link href="scripts/slideshow.css" rel="stylesheet" type="text/css">
<?php
/********************************************************************
* CONTROL BEHAVIORS OF SLIDESHOW *
********************************************************************/
?>
<!-- Begin script to control slideshow -->
<script type = "text/javascript">
var thumbTop = 450; // starting value of thumb.style.top (make sure multiple of increment)
var highestTop = 342; // highest point mask can be on screen ,-, (make sure multiple of increment)
var lowestTop = 450; // lowest point mask can be on screen ,_, (make sure multiple of increment)
var delay = 2; // speed in which slide up and down methods are called
var increment = 5; // value that thumbTop increments with each method call
var intervalUp; // interval for thumb upward movements
var intervalDown; // interval for thumb downward movements
function startThumbSlideUp()
{
window.clearInterval(intervalDown);
intervalUp = window.setInterval(thumbSlideUp,delay);
}
function startThumbSlideDown()
{
window.clearInterval(intervalUp);
intervalDown = window.setInterval(thumbSlideDown,delay);
}
function thumbSlideUp()
{
thumbTop -= increment;
if (thumbTop <= highestTop)
{
thumbTop = highestTop;
window.clearInterval(intervalUp);
}
else
thumbMask.style.top = thumbTop;
}
function thumbSlideDown()
{
// Added to fix issue where images would start from too large a height
if (thumbTop <= highestTop)
thumbTop = highestTop;
thumbTop += increment;
if (thumbTop >= lowestTop)
{
thumbTop = lowestTop;
window.clearInterval(intervalDown);
}
else
thumbMask.style.top = thumbTop;
}
// Move marker above image <pos>
function setMarkerPos(pos)
{
marker.style.left = 600 - (66 * (pos)) + 19;
}
</script>
</head>
<?php
/********************************************************************
* DISPLAY SLIDESHOW *
********************************************************************/
// Start body and make images unhighlightable
echo '<body onselectstart="return false" style="margin: 0px;">';
// Create base value to increment horizontal position of thumbnails
$curr_thumb_left = 595; // (ignore this comment) 660<width of image> - 66<width of thumb> - 10<space between side> // 660
// Create and display main (large) image and image thumbnails
echo '<div id="mask" onmouseout = "startThumbSlideDown()" onmouseover = "startThumbSlideUp();">
';
echo '<img src = "'.$directory.$pic_array[0].'" id = "mainPicture" height = "420" width = "660" style = "z-index: -1; position:absolute;"/>
';
echo '<div id="thumbMask" height="66" width="660" style="z-index: 1; top: 450px; position: absolute;">
';
echo '<img id="marker" src="images/marker.png" height="10" width="10" style="z-index: 2; top: 0px; position: absolute;" onload="setMarkerPos(0);"/>';
// Search through image array, then assign names to and display thumbnails
for ($i=0; $i < $num_pics; $i++)
{
// Point to pic in array
$current_pic = $pic_array[$i];
// Create and display image thumbnails
if ($current_pic !== "")
{
echo '<img src = "'.$directory.$current_pic.'" id = "thumb'.$i.'" height = "50" width = "50" style = "left:'.$curr_thumb_left.'px; top: 10px; border: 3px white solid; position: absolute;" onclick = "mainPicture.src = \''.$directory.$current_pic.'\'; setMarkerPos('.$i.')"/>
';
// Move left value to the left [50px width + (3px padding * 2 sides) + 10px space between = 66px]
$curr_thumb_left -= 66;
}
}
echo '</div>';
echo '</div>';
?>
</body>
</html>
Chrome doesn't make image elements available by just their "id" value; you have to use document.getElementById("mainPicture") to get a reference to the DOM element. That'll work in all browsers anyway, so it's safe to just code it that way.
You are attempting to alter the src of mainPicture as though it were a global variable:
mainPicture.src = '.....';
Try referencing mainPicture by its id instead:
document.getElementById('mainPicture').src = '......';
You're not actually setting what mainPicture is, other browsers must be guessing whereas Chrome is doing what it should. Change:
echo '<img src = "'.$directory.$current_pic.'" id = "thumb'.$i.'" height = "50" width = "50" style = "left:'.$curr_thumb_left.'px; top: 10px; border: 3px white solid; position: absolute;" onclick = "mainPicture.src = \''.$directory.$current_pic.'\'; setMarkerPos('.$i.')"/>
to
echo '<img src = "'.$directory.$current_pic.'" id = "thumb'.$i.'" height = "50" width = "50" style = "left:'.$curr_thumb_left.'px; top: 10px; border: 3px white solid; position: absolute;" onclick = "document.getElementById('mainPicture').src = \''.$directory.$current_pic.'\'; setMarkerPos('.$i.')"/>
$img = imagecreatefrompng("img/".$image);
$w = imagesx($img);
$h = imagesy($img);
$pixelcount = 0;
echo "<div id='container' style='width: {$w}px; height: {$h}px;'>\r\n";
for($y=0;$y<$h;$y++) {
for($x=0;$x<$w;$x++) {
$rgb = imagecolorat($img, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$alpha = (imagecolorat($img,$x,$y) & 0x7F000000) >> 24;
if($alpha == 127)
$newcolor = "transparent";
else
$newcolor = sprintf('#%02X%02X%02X', $r, $g, $b);
if(isset($prevcolor) && strcmp($newcolor, $prevcolor) != 0)
{
echo "<div style='background: {$prevcolor}; height: 1px; width: {$pixelcount}px; float: left;'></div>\r\n";
$pixelcount = 0;
}
$prevcolor = $newcolor;
$pixelcount++;
}
echo "<div style='background: {$prevcolor}; height: 1px; width: {$pixelcount}px; float: left;'></div>\r\n";
unset($prevcolor);
$pixelcount = 0;
}
echo "</div>\r\n";
Here's a link to the tool in its current form.
http://schnell.dreamhosters.com/folio/pixelread.php?image=link.png
Mousewheel up, I and +/= key zoom in. Mousewheel down, O and -/_ key zoom out. No need to focus on any particular element, the entire document registers a keystroke/mousewheel.
Edit - Thanks for the fix that that one problem, guys! Got a new one now though. If you go to the tool and attempt to blow it up by zooming in, the sprite just falls apart. If you leave it alone and do nothing, it looks fine. What's weird too is that you can't fix the picture by reseting the size, it will stay messed up until you refresh the page.
Edit2 - Found the source of the trouble.
function resize(width, height)
{
$('div#container').css('height', factor * height);
$('div#container').css('width', factor * width);
$('div#container > div').css('height', factor).css('width', function(i, val) { return parseInt(val * factor) + 'px'; });
$('div#container').css('margin-top', ($(window).height() - $('div#container').height())/2 + "px");
}
Width isn't getting multiplied by 'factor' for some reason. I'm trying to do it in such a way that jQuery does it to each and every child div, basing the new width off the old, without having to do a huge for loop or anything, but nothing I'm coming up with is working.
Edit3 - Finally got it working! I just stored the original lengths of each div as the 'id' attribute in each and then access that when it comes time to resize everything. Thanks to everyone who put up with this and stuck with me to see it through. I swear the resizing is smoother than before! :D
Your code isn't resetting the pixel count after each run of colour. I think you need this:
if(isset($prevcolor) && strcmp($hex, $prevcolor) != 0) {
echo "<div style='background: {$prevcolor}; height: 1px; width: {$pixelcount}px; float: left;'></div>\r\n";
$pixelcount = 0;
}
I believe that the problem lies in the fact that, in the inner loop, you never reset $pixelcount after you use it. Consequently, it's just an accumulation of the total pixels of the row, meaning that each time you print you get a progressively larger width.
Based on your description, you'd want to reset it when you switch colours:
if(isset($prevcolor) && strcmp($hex, $prevcolor) != 0) {
echo "<div style='background: {$prevcolor}; height: 1px; width: {$pixelcount}px; float: left;'></div>\r\n";
$pixelcount = 0; // Incremented back to 1 below
}
The resizing problem comes from the resize function, where width is now set inappropriately because the base width of each block is no longer 1:
var cssObj = {
'width' : factor, // This factor needs to be multiplied by the original width
'height' : factor
};
$('div#container > div').css(cssObj);
I'm sure there's a better way to do this, but you could get the width upfront:
$('div#container').css('margin-top',
($(window).height() - $('div#container').height())/2 + "px");
$('div#container > div').each(function() {
$(this).data('originalWidth', $(this).width());
});
...then in the resize function:
$('div#container > div')
.css('height', factor)
.css('width', function() {
return $(this).data('originalWidth') * factor;
});