Log in

View Full Version : Can php do the same or similar to this js?



gwmbox
07-16-2010, 01:33 AM
Hi guys

I have had help getting some javascript together but I'd like to know if the same can be achieved via php rather than js.

The idea is to be able to wrap list items after every fifth list item, so if the list is something like


<ul id="mylist">
<li>Text1</li>
<li>Text2</li>
<li>Text3</li>
<li>Text4</li>
<li>Text5</li>
<li>Text6</li>
<li>Text7</li>
<li>Text8</li>
<li>Text9</li>
<li>Text10</li>
<li>Text11</li>
<li>Text12</li>
<li>Text13</li>
<li>Text14</li>
<li>Text15</li>
<li>Text16</li>
<li>Text17</li>
<li>Text18</li> (and up to a max of 20)
</ul>

The Text# in each list item will vary in length so it will not always be the same height as each other.

Then the result will be something like


Text1 Text6 Text11 Text16
Text2 Text7 Text12 Text17
Text3 Text8 Text13 Text18
Text4 Text9 Text14
Text5 Text10 Text15

Here is the javascript code I have;

The script assigns a unique ID to each list item and also calculates the height of column of list items (max of 5 items per column) and assigns a margin-top style to the next list item as a negative so that it brings that list item back to the top of the ul list area (as shown in the example above) It also calculates and identifies which of the 4 sets of 5 list items is the longest height and assigns that to a div so that any text after the list does not flow over the list items (it was an issue I had in chrome)



<script type="text/javascript">
/*<![CDATA[*/

var ul=document.getElementById('itemposts');
var div=document.getElementById('adverts');
var lis=ul.getElementsByTagName('LI');

for (var ary=[],h=0,lft=0,wdth=176,z0=0;z0<lis.length;z0++){
if (z0>0&&(z0)%5==0){
lis[z0].style.marginTop=-h+'px';
ary.push(h);
lft+=190;
h=0;
}
lis[z0].style.marginLeft=lft+'px';
lis[z0].style.width=wdth+'px';
h+=lis[z0].offsetHeight;
}
ary.push(h);
ary=ary.sort(function(a,b){ return b-a; });
div.style.height=ary[0]+'px';
/*]]>*/
</script>

So my question is with the list items being generated in the php file 'foreach' loop is there a way to achieve the same or similar as the above in php only?

Thanks

GW

djr33
07-16-2010, 02:06 AM
Sure. You just need two different loops at the same time: one is going trough all of them, and the other is counting from 1-5, then back to 0, up to 5, repeat.

Here's a rough example:
$count = 0;
foreach ($items as $item) {
echo $item;
$count++;
if ($count==5) {
echo '<br>';
$count = 0;
}
}

gwmbox
07-16-2010, 02:50 AM
Ok that's good to know, thanks.

So how does that do the calculation to determine heights of each list item and then the ul/div?

So the end result is something like this;


<ul id="mylist" height="LONGESTHEIGHTCOLUMNpx">
<li style="margin-left:0;width:180px;>Text1</li>
<li style="margin-left:0;width:180px;>Text2</li>
<li style="margin-left:0;width:180px;>Text3</li>
<li style="margin-left:0;width:180px;>Text4</li>
<li style="margin-left:0;width:180px;">Text5</li>
<li style="margin-left:190px;width:180px;margin-top:-TOTALHEIGHTOF1TO5px;">Text6</li>
<li style="margin-left:190px;width:180px;">Text7</li>
<li style="margin-left:190px;width:180px;">Text8</li>
<li style="margin-left:190px;width:180px;">Text9</li>
<li style="margin-left:190px;width:180px;">Text10</li>
<li style="margin-left:380px;width:180px;margin-top:-TOTALHEIGHTOF6TO10px;">Text11</li>
<li style="margin-left:380px;width:180px;">Text12</li>
<li style="margin-left:380px;width:180px;">Text13</li>
<li style="margin-left:380px;width:180px;">Text14</li>
<li style="margin-left:380px;width:180px;">Text15</li>
<li style="margin-left:570px;width:180px;margin-top:-TOTALHEIGHTOF11TO15px;">Text16</li>
<li style="margin-left:570px;width:180px;">Text17</li>
<li style="margin-left:570px;width:180px;">Text18</li> (and up to a max of 20)
</ul>

Thanks

GW

djr33
07-16-2010, 02:55 AM
It doesn't.

I guess you can do something like this:

$count = 0;
$level = 1;
foreach ($items as $item) {
echo $item;
echo 180*$level; //this is the new value
$count++;
if ($count==5) {
$level++;
echo '<br>';
$count = 0;
}
}


However, I'd recommend creating a new list for each and offsetting the list column, not the list items. But this works too.

djr33
07-16-2010, 03:14 AM
$count = 0;
$level = 0;
$out = ''; //set blank to start
foreach ($texts as $text) {
$count++;
if ($count==5) {
$level++;
$count = 0;
}
$out .= '<li style="margin-left:'.(190*$level).'px;width:180px;">'.$text.'</li>';
}
echo '<ul id="mylist" height="'.(190*$level).'px">';
echo $out;
echo '</ul>';

I don't understand the "height" requirements for every 5th item. Can you explain?

gwmbox
07-16-2010, 03:20 AM
The height is so that the list items line up at the top so it represents columns. In the JS this was done by setting the 6th, 11th and 16th items to a negative margin-top.

It also needs to work out from the columns what is the longest column and then assign that value to the ul, this is to ensure that the text underneath does not float over the list items (this was to get around a chrome issue I had.

Now also keep in mind there may be times where there is as little as two or three items so only one column will show, and hence the calculations other than the ul max height will not be done.

Does that make any more sense to you?

Cheers

GW

djr33
07-16-2010, 04:07 AM
Now I know how the height attributes work, and that makes sense.
However, I don't understand how we know the height of each item.

There is also a bigger problem I just realized:

Javascript is able to use the current page and change it, after it has loaded.

PHP does not do this. PHP modifies text then outputs text to the browser.
This means that PHP doesn't do things like "find element by ID" then "loop through all of it's sub-elements".
You could try an xml parser, but that's going to get complicated.

PHP is designed to work with data, not html, and then generate html as output (not input). This means you can work with a database or text file or type directly into the variables.

In my code above $texts is a variable that should be an array of all the list items you want to use. But how would we get this?


Actually, in this case, it may be simpler to use JS. It's possible to use PHP, but it would require changing the system.


When I first read this, I thought you already had a PHP system setup and you just needed to create the same sort of loop. The loop part is easy to convert, but now we also need to change how the data is stored in the first place.

gwmbox
07-16-2010, 04:49 AM
Ok thanks for your time Daniel, I will tinker with the JS I have and see if I can get that working as I need. The biggest issue is styles between chrome vs IE vs Firefox vc Opera etc. I am also aware many have javascript turned off or have some form of block script installed.

The php that this is being used to create the content is from data pulled from a mysql db and then inserted, but like you said changing styles on the fly is probably best done by js based on your comments.

Thanks

GW

djr33
07-16-2010, 05:01 AM
Oh, so PHP is generating the page. If that's the case, then using PHP is a good idea. It just needs to be integrated with the original PHP code so they work together, rather than using this as an afterthought.

Can you post the PHP code relevant to generating this menu? It probably doesn't need to be the whole page, just the mysql query through the output.

It should be easy enough to integrate.

The only problem that still remains then is working out the height. However, I expect we can find some other way to space them rather than having to calculate that. Alternatively, you could specify a height such as 20px if that works for your needs. Since the text size might change, that may be a problem, so I hope we find a better way.

gwmbox
07-16-2010, 05:13 AM
Ok here is a section of the php code that is dealing with the lists I am wanting to use it for



<ul id="itemposts">
<?php
if ($resultSearch){
foreach ( $resultSearch as $row ){
$idPost=$row['idPost'];
$postType=$row['type'];
$postTypeName=getTypeName($postType);
$postTitle=$row['title'];
$postLocation=$row['idLocation'];
$postPlace=$row['place'];
$postPrice=$row['price'];
$postDesc= substr(strip_tags(html_entity_decode($row['description'], ENT_QUOTES, CHARSET)), 0, 160);
$category=$row['category'];//real category name
$fcategory=$row['fcategory'];//friendly name category
$idCategoryParent=$row['idCategoryParent'];
$fCategoryParent=$row['parent'];
$postImage=$row['image'];
$postPassword=$row['password'];
$postPhone=$row['phone'];
$insertDate=setDate($row['insertDate']);
$postUrl=itemURL($idPost,$fcategory,$postTypeName,$postTitle,$fCategoryParent);
if ($row["hasImages"]==1){
$postImage=getPostImages($idPost,$insertDate,true,false);
}
else $postImage=getPostImages(true,true,true,true);//there's no image
?>
<li><a title="<?php echo $postTitle." in ".$category;?>" href="<?php echo SITE_URL.$postUrl;?>" rel="bookmark" class="postlink"><span class="post-title"><?php echo $postTitle;?></span> <span class="post-desc"><?php echo $postDesc;?></span> <?php if ($postPrice==0){ echo '<span class="post-price-free">FREE</span>';} else { echo '<span class="post-price">'.getPrice($postPrice).'</span>';} ?>, <span class="post-place"><?php echo $postPlace.", ".getLocationName($postLocation); ?>.</span> <span class="post-phone"><?php if ($postPhone!=""){?><?php echo _("Ph");?>: <?php echo formatPhone($postPhone); ?><?php }?></span> <span class="post-date"><?php echo $insertDate;?></span></a><br /><span class="advicons"><?php if ($row["hasImages"]==1){?><a class="picture" href="#thumb"><img src="<?php echo SITE_URL.'/themes/'.DEFAULT_THEME;?>/images/icon-photo.png" width="16" height="16" alt="picture" /><span><img title="<?php echo $postTitle." in ".$category;?>" alt="<?php echo $postTitle." in ".$category;?>" src="<?php echo $postImage;?>" class="post-img" /><br /><?php echo $postTitle." in ".$category;?></span></a><?php }?><a title="Contact the owner of this advert" href="<?php echo SITE_URL.$postUrl;?>" rel="bookmark" class="postlink"><img src="<?php echo SITE_URL.'/themes/'.DEFAULT_THEME;?>/images/icon-contact.png" width="16" height="16" alt="Contact the owner of this advert" /></a><a href="<?php echo SITE_URL."/".contactURL();?>?subject=<?php echo _("Advert Report:");?> <?php echo $itemName." (".$idItem.")";?>" title="Report this advert"><img src="<?php echo SITE_URL.'/themes/'.DEFAULT_THEME;?>/images/icon-report.png" width="16" height="16" alt="Report this advert" /></a></span>
<?php if(isset($_SESSION['admin'])){?>
<br /><a href="<?php echo SITE_URL;?>/manage/?post=<?php echo $idPost;?>&amp;pwd=<?php echo $postPassword;?>&amp;action=edit">
<?php echo _("Edit");?></a><?php echo SEPARATOR;?>
<a onClick="return confirm('<?php echo _("Deactivate");?>?');" href="<?php echo SITE_URL;?>/manage/?post=<?php echo $idPost;?>&amp;pwd=<?php echo $postPassword;?>&amp;action=deactivate">
<?php echo _("Deactivate");?></a><?php echo SEPARATOR;?>
<a onClick="return confirm('<?php echo _("Spam");?>?');" href="<?php echo SITE_URL;?>/manage/?post=<?php echo $idPost;?>&amp;pwd=<?php echo $postPassword;?>&amp;action=spam">
<?php echo _("Spam");?></a><?php echo SEPARATOR;?>
<a onClick="return confirm('<?php echo _("Delete");?>?');" href="<?php echo SITE_URL;?>/manage/?post=<?php echo $idPost;?>&amp;pwd=<?php echo $postPassword;?>&amp;action=delete">
<?php echo _("Delete");?></a>
<?php }?>
</li>


<?php
}
}//end if check there's results
else echo "<p>"._("Nothing found")."</p>";
?>

</ul>

And this is the related section for the mysql



$query="SELECT p.idPost,p.title,p.description,p.insertDate,p.place,p.idLocation,c.Name category,c.friendlyName fcategory,c.idCategoryParent,p.type,p.price,p.password,p.phone,p.hasImages,
(select friendlyName from ".TABLE_PREFIX."categories where idCategory=c.idCategoryParent limit 1) parent
FROM ".TABLE_PREFIX."posts p
inner join ".TABLE_PREFIX."categories c
on c.idCategory=p.idCategory
where p.isAvailable=1 and p.isConfirmed=1 $filter
order by $order $limit";
//echo $query;
$resultSearch=$ocdb->getRows($query);


Does that help or do you need more info?

djr33
07-16-2010, 05:45 AM
Ah, that's some very complex PHP. Object oriented MySQL... intereting. But I don't think the MySQL matters in this case, luckily.

I will now try to integrate the two functions...

Unfortunately I can't test this since it's your database and your php system. So I'll just give you the code that should work, and we'll see...

<?php
if ($resultSearch){
$count = 0;
$level = 0;
$out = ''; //set blank to start
foreach ( $resultSearch as $row ){
$count++;
if ($count==5) {
$level++;
$count = 0;
}
ob_start();
$idPost=$row['idPost'];
$postType=$row['type'];
$postTypeName=getTypeName($postType);
$postTitle=$row['title'];
$postLocation=$row['idLocation'];
$postPlace=$row['place'];
$postPrice=$row['price'];
$postDesc= substr(strip_tags(html_entity_decode($row['description'], ENT_QUOTES, CHARSET)), 0, 160);
$category=$row['category'];//real category name
$fcategory=$row['fcategory'];//friendly name category
$idCategoryParent=$row['idCategoryParent'];
$fCategoryParent=$row['parent'];
$postImage=$row['image'];
$postPassword=$row['password'];
$postPhone=$row['phone'];
$insertDate=setDate($row['insertDate']);
$postUrl=itemURL($idPost,$fcategory,$postTypeName,$postTitle,$fCategoryParent);
if ($row["hasImages"]==1){
$postImage=getPostImages($idPost,$insertDate,true,false);
}
else $postImage=getPostImages(true,true,true,true);//there's no image
?>
<a title="<?php echo $postTitle." in ".$category;?>" href="<?php echo SITE_URL.$postUrl;?>" rel="bookmark" class="postlink"><span class="post-title"><?php echo $postTitle;?></span> <span class="post-desc"><?php echo $postDesc;?></span> <?php if ($postPrice==0){ echo '<span class="post-price-free">FREE</span>';} else { echo '<span class="post-price">'.getPrice($postPrice).'</span>';} ?>, <span class="post-place"><?php echo $postPlace.", ".getLocationName($postLocation); ?>.</span> <span class="post-phone"><?php if ($postPhone!=""){?><?php echo _("Ph");?>: <?php echo formatPhone($postPhone); ?><?php }?></span> <span class="post-date"><?php echo $insertDate;?></span></a><br /><span class="advicons"><?php if ($row["hasImages"]==1){?><a class="picture" href="#thumb"><img src="<?php echo SITE_URL.'/themes/'.DEFAULT_THEME;?>/images/icon-photo.png" width="16" height="16" alt="picture" /><span><img title="<?php echo $postTitle." in ".$category;?>" alt="<?php echo $postTitle." in ".$category;?>" src="<?php echo $postImage;?>" class="post-img" /><br /><?php echo $postTitle." in ".$category;?></span></a><?php }?><a title="Contact the owner of this advert" href="<?php echo SITE_URL.$postUrl;?>" rel="bookmark" class="postlink"><img src="<?php echo SITE_URL.'/themes/'.DEFAULT_THEME;?>/images/icon-contact.png" width="16" height="16" alt="Contact the owner of this advert" /></a><a href="<?php echo SITE_URL."/".contactURL();?>?subject=<?php echo _("Advert Report:");?> <?php echo $itemName." (".$idItem.")";?>" title="Report this advert"><img src="<?php echo SITE_URL.'/themes/'.DEFAULT_THEME;?>/images/icon-report.png" width="16" height="16" alt="Report this advert" /></a></span>
<?php if(isset($_SESSION['admin'])){?>
<br /><a href="<?php echo SITE_URL;?>/manage/?post=<?php echo $idPost;?>&amp;pwd=<?php echo $postPassword;?>&amp;action=edit">
<?php echo _("Edit");?></a><?php echo SEPARATOR;?>
<a onClick="return confirm('<?php echo _("Deactivate");?>?');" href="<?php echo SITE_URL;?>/manage/?post=<?php echo $idPost;?>&amp;pwd=<?php echo $postPassword;?>&amp;action=deactivate">
<?php echo _("Deactivate");?></a><?php echo SEPARATOR;?>
<a onClick="return confirm('<?php echo _("Spam");?>?');" href="<?php echo SITE_URL;?>/manage/?post=<?php echo $idPost;?>&amp;pwd=<?php echo $postPassword;?>&amp;action=spam">
<?php echo _("Spam");?></a><?php echo SEPARATOR;?>
<a onClick="return confirm('<?php echo _("Delete");?>?');" href="<?php echo SITE_URL;?>/manage/?post=<?php echo $idPost;?>&amp;pwd=<?php echo $postPassword;?>&amp;action=delete">
<?php echo _("Delete");?></a>
<?php } ?>
<?php
$out .= '<li style="margin-left:'.(190*$level).'px;width:180px;">'.ob_get_contents().'</li>';
ob_end_clean();
}
echo '<ul id="itemposts" height="'.(50*($level>1?5:$count)).'px">';
echo $out;
echo '</ul>';
}//end if check there's results
else echo "<p>"._("Nothing found")."</p>";
?>


I believe that will work. It still doesn't deal with the height well, but I set it to assume the height is 50px per item. I know that isn't right yet, but that's a start and we can look at it again.

For your information, since that code was so horribly complex, I didn't want to risk a typo in attempting to avoid the echos (since there are about 50 in there) and I wanted to output that only after doing the math. So I used an output buffer. It's a little less efficient, but it will work. I didn't want to mess up the template by trying to change that, so I hope the output buffer works fine, and it should.

Also, I tried to minimally change the existing code and I intentionally added mine without tabs. This gives us a quick way to visually reference both kinds of code.

So let me know what happens when you run that code.

I may not have too much time over the weekend to check it out, but I'll try to get a chance.

gwmbox
07-16-2010, 06:18 AM
OK that works as far as adding the relevant margins and widths to each column of list items but the height of each list item is needed to then work out how to move the next column up to the same level as the previous rows start. This was done with a negative px number in the JS.

So if we can work out how to define the height of each list item and assign a height value, we can then add up the first 5 list items and then apply that height to the next item as a negative margin-top value. The same applies for the next five and so. The totals for each column would need to be 'buffered' or similar and then the highest of the columns height in px's is applied to the opening ul.

We can assign the style of 16px line-height to each li item but the number of lines in a 180px wide list item will vary from 16px (1 line) up to 160px (10 lines (approx))

This might be a case of having to implement both php and JS to get it working.

Cheers

GW

djr33
07-16-2010, 07:46 PM
Yes, I have no idea how that would work. PHP does not know how the browser will render the font and how large it would be.
So this means that you probably would be better using Javascript here, or as I said, splitting it into several smaller lists or making them all "float:up", by which I mean that you could create some complex css that would do that in a similar way to "float:left".