Tag Cloud - need help

22 posts by 5 authors in: Forums > CMS Builder
Last Post: April 26, 2013   (RSS)

By dwellingproductions - March 20, 2013 - edited: March 21, 2013

Hey all!  One last tricky blog question from me.  I'm sooooo close on this it's killing me.  But, I'm also in way over my understanding level.  :-)

I'm trying to create a tag cloud from tags that are from a multi-editor section called "health_articles_content" stored in a field named "tags".  I want it to look like the sample at the bottom of the sidebar on this page: http://www.liviaglobal.com/health_articles_list.php

The code it should output is like this:

   <aside id="tags">
     <h3>Tags - Sample</h3>
     <a class="t7" href="">health</a>
     <a class="t3" href="">colon</a>
     <a class="t8" href="">livia ONE</a>
     <a class="t1" href="">oral</a>
     <a class="t2" href="">balance</a>
     <a class="t9" href="">digestion</a>
     <a class="t2" href="">bacteria</a>
     <a class="t6" href="">ingredients</a>
     <a class="t3" href="">liquid</a>
     <a class="t8" href="">organic</a>
     <a class="t2" href="">energy</a>
     <a class="t8" href="">benefits</a>
     <a class="t4" href="">natural</a>
     <a class="t3" href="">spray</a>
     <a class="t5" href="">pets</a>
     <a class="t3" href="">guarantee</a>
     <a class="t10" href="">probitics</a>
   </aside><!-- #tags -->

As you can see on the example page, I have managed to list the tag names and their usage counts using "showme".  I am also able to successfully limit the number of tags shown (kind of... as it's only displaying the first letter of each tag).

Ultimately. I'm going to limit the cloud to displaying about 15-20 visible tags (though I've limited it to less now while I'm testing) and there will be 10 font-size steps.  I was trying to incorporate the method on this site (http://www.stevenyork.com/tutorial/creating_accessible_tag_cloud_in_php_css_mysql) for adjusting the size of the fonts based on percentages of their usage within the multi-section (health_articles_content).

Here's where I'm stuck.

  1. I can't seem to call the values that I'm listing in the array "showme" commands.  I'm sure I need to assign those values to variables, but cannot figure out how.
  2.  For some reason, it's only displaying the first letter of each tag.  (I know this is something dumb I'm doing that's causing this.)  :-)
  3. I cannot figure out how to integrate the functions from the other site that handle the font sizing based on percentage of tag use.  I know I'm using the wrong variables and references; but, obviously, I'm not familiar enough with CMSB's inner-workings (or PHP, for that matter) to sort it out completely. 

I've uploaded my code so you can see the mess I've made of this.  :-)  Perhaps there's a better way to approach all of this.  I'm definitely open to alternate suggestions.  :-)

Thanks, in advance!

- Jeremy

For convenience, below is the current code from my uploaded file:

<?php

$tagsToCount = array();
$sectionsToField = array('health_articles_content' => 'tags'/*, 'testimonials_content' => 'tags'*/); //use additional if joining tags from multiple sections

foreach($sectionsToField as $sectionName => $fieldName) {

//get section records
$records = mysql_select($sectionName);

foreach ($records as $record) {
//turn field into an array of values
$tags = explode(",", @$record[$fieldName]);

// add tags to the count array
foreach ($tags as $tag) {
$tag = trim($tag);
if (!$tag) { continue; } // skip empty array values

if (array_key_exists($tag, $tagsToCount)) {
$tagsToCount[$tag]++; }
else {
$tagsToCount[$tag] = 1; }
}
}
}

showme($tagsToCount);


//extract tags from the array
$tags = array_keys($tagsToCount);

//randomize tags
shuffle($tags);


$maximumResults = 5;
$resultCount = 0;
?>
<?php foreach ($tags as $tag):?>
<?php echo $tag['']; ?>

<?php if (++$resultCount == $maximumResults) {
break;}
?>
  
<?php endforeach ?>

<?php showme($tags); ?>



<?php foreach ($tags as $tag): ?>
<?php echo $tag['']; ?>
<?php endforeach ?>

---------------------------

Dwelling Productions

www.dwellingproductions.com

Just FYI, I just changed my sample page to: http://www.liviaglobal.com/health_articles_list_test.php  

(I have to go show the client the site's progress.)  :-)

- Jeremy

---------------------------

Dwelling Productions

www.dwellingproductions.com

Hi Jeremy, 

I've had a look at your code, and I think I have a solution:


<!-- "Working" tags Code STARTS HERE -->


<?php

$tagsToCount = array();
$sectionsToField = array('health_articles_content' => 'tags'/*, 'testimonials_content' => 'tags'*/); //use additional if joining tags from multiple sections

foreach($sectionsToField as $sectionName => $fieldName) {

//get section records
$records = mysql_select($sectionName);

foreach ($records as $record) {
//turn field into an array of values
$tags = explode(",", @$record[$fieldName]);

// add tags to the count array
foreach ($tags as $tag) {
$tag = trim($tag);
if (!$tag) { continue; } // skip empty array values
   if (array_key_exists($tag, $tagsToCount)) {
   $tagsToCount[$tag]++; }
   else {
   $tagsToCount[$tag] = 1; 
      }
  }
}
}

//PHP doesn't have a shuffle function built in that maintains keys, I found this function in the PHP documentation for the shuffle function.
function shuffle_assoc($list) { 
  if (!is_array($list)) return $list; 

  $keys = array_keys($list); 
  shuffle($keys); 
  $random = array(); 
  foreach ($keys as $key) { 
    $random[] = $list[$key]; 
  }
  return $random; 


showme($tagsToCount);
 ?>

<!-- I wasn't 100% sure what this part of the code was meant to do, so I've removed it. I think you only need to use the tagsToCount array -->

<!-- Tags - ATTEMPTING TO DISPLAY -->

       <aside id="tags">
         <h3>Tags</h3>
         <?php 
          $maximumResults = 6;
          $resultCount = 0;
          ?>
          <?php foreach ($tagsToCount as $key => $value): ?>
            <a class="t<?php echo $value; ?>" href="#_"><?php echo $key; ?></a>
            <?php if (++$resultCount == $maximumResults) { break;}?>
          <?php endforeach ?>
        </aside>

I think the main problem was that you were using the php shuffle function, which recreates the key of a function, so you were loosing your count values from the $sectionToField foreach loop. I've found an alternative function to shuffle that will keep the key values. 

I also removed these lines of code:


//extract tags from the array
$tags = array_keys($tagsToCount);

//randomize tags
shuffle($tags);


$maximumResults = 5;
$resultCount = 0;
?>
<?php foreach ($tags as $tag):?>
<?php echo $tag['']; ?>

<?php if (++$resultCount == $maximumResults) {
break;}
?>
  
<?php endforeach ?>

<?php showme($tags); ?>



<?php foreach ($tags as $tag): ?>
<?php echo $tag['']; ?>
<?php endforeach ?>

As I don't think they're necessary anymore.

So the final foreach loop is cycling through your $tagsToCount array, and using the count value as the id value, and using the key for the title.

Let me know if you have any questions.

Thanks!

Greg

Greg Thomas







PHP Programmer - interactivetools.com
Attachments:

ext_side_tags_001.php 6K

By davidcmsb - March 21, 2013

Hi dwellingproductions,

Checked out your page and the design looks great.

I want to do a tag cloud like that too.

Where did you get the software for it?  Do you have a link to it you can share?

Thanks,

David

00000000

Hi Greg!  That was a HUGE step in the right direction toward completing this.  Thank you, thank you!  :-)

I added additional code to convert the count value to percentages and that seems to be working, assigning CSS values based on a tag's percentage of usage (occurrences in the"tags" field).

After further testing, here are the final minor obstacles I need to overcome (in order of priority).

1. The whole thing breaks down if the user puts a comma at the end of their list of tags in the section editor.  For instance, this tag list works fine: "probiotics, health, digestion"   -  However, this list produces a plethora of errors: "probiotics, health, digestion,"  - That last comma is the culprit (though trailing spaces don't seem to be an issue).  In setting up the "tags" field, I only allowed lowercase letters, commas, and spaces... so no other characters should be an issue.  However, I need a way to remove a final comma if it exits.  I tried using this code:

$string = rtrim($string, ',');

Unfortunately, no variable I tried using (in the place of $string) would work.  I am also unsure of where to put it on the page.  I've tried just about every place possible, but likely with the wrong variables.  :-)

2. I only want the tag section to appear in the sidebar if there is at least one tag present of the field.  I tried using a standard "if" statement like so:

<?PHP if ($newsRecord['title']): ?> 
Title: <?PHP echo $newsRecord['title'] ?> 
<?PHP endif; ?>                            

I placed this around the tags section.  However, since my variable was off, I never got it working.  Typically, I don't have issues with this sort of thing.  But, I'm unsure as to what variable to use.

3. Curiously, it doesn't seem to be shuffling the tags, even with the new shuffle function.  Instead, it is taking the tags from the first record and then, adding to the tag list by going up through records in the order they were created and adding any unique (no yet listed) tags.  This one is not as important, but would still be a nice thing to get working.

I'm uploading the latest version of the code to this post..  Hopefully these are pretty straight-forward.  Thanks, again, for you assistance!

- Jeremy

---------------------------

Dwelling Productions

www.dwellingproductions.com
Attachments:

ext_side_tags_002.php 4K

Hi David!

I'm actually trying to create a custom tag cloud with CMS Builder (with the help of the good people of this forum and Interactive Tools).  :-)  As soon as it looks like it's all working properly, I'll post the code so you can use it as well.  Stay tuned!  :-)

- Jeremy

---------------------------

Dwelling Productions

www.dwellingproductions.com

By Jason - March 22, 2013

Hi Jeremy,

I've taken a look at the code that you and Greg were working on.

1) What are the errors that you get if a trailing comma is used?  When I looked at the code, I saw this line in the loop that tallies up the tags:

if (!$tag) { continue; } // skip empty array values

This will skip over any empty tags that could be caused by a trailing comma.  If you can give some extra information about what's happening we can take a closer look.

2)  You could wrap the entire tags section in an if statement that you will only enter if there's a value for $tagsToCount like this:

 <?php if ($tagsToCount): ?>
        <aside id="tags">
             <h3>Tags</h3>
         <?php     $maximumResults = 18;
                                $resultCount = 0;
                 ?>
                        <?php foreach ($tagsToCount as $key => $value): ?>
            <?php           
                            $ratio = (100 / $tagsToCount[$tag]) * $value; //get the number-of-tag-occurances as a percentage of the overall number 
                            $ratio =  round($ratio,-1); //round the number to the nearest 10 
                        ?>

                <a class="t<?php echo $ratio; ?>" href="#_"><?php echo $key; ?></a>
              <?php if (++$resultCount == $maximumResults) {    break;}?>
                        <?php endforeach ?>
        </aside>
 <?php endif ?>

3)  It looks like the shuffle function isn't being called.  Try this before the if statement above:

<?php $tagsToCount = shuffle_assoc($tagsToCount); ?>

Hope this helps,

---------------------------------------------------
Jason Sauchuk - Project Manager
interactivetools.com

Hire me! Save time by getting our experts to help with your project.
http://www.interactivetools.com/consulting/

By Jason - March 22, 2013

Hi Jeremy,

It look like the issue is the variable $tag, which is a variable with an old value used in the code about.  Try something like this:

<?php $totalTagCount = array_sum($tagsToCount); ?>
<?php foreach ($tagsToCount as $key => $value): ?>
  <?php           
    $ratio =  (intval($value)/$totalTagCount) * 100;
    $ratio =  round($ratio,-1); //round the number to the nearest 10 
  ?>

Hope this helps

---------------------------------------------------
Jason Sauchuk - Project Manager
interactivetools.com

Hire me! Save time by getting our experts to help with your project.
http://www.interactivetools.com/consulting/

Hey Jason!

That's almost it.  The percentage-based font sizing isn't quite working as expected.  (Fonts that are most-used and should be much larger are still very small (though they are ever so slightly larger than other tags).  I've uploaded an image showing the change.  I was expecting it to look like the top example in the image (the way it used to work)... however, it looks like the bottom example now.  The most used tags (on a percentage basis) should be assigned to the largest fonts on my CSS font-size scale... but for some reason that is not quite happening.

The good news is that trailing commas no longer cause an error.  Woohoo!  :-)  Unfortunately, and strangely, the "shuffle_assoc" function is returning a list of numbers "0 1 2 3 4".

It's soooo close now.  :-)  Any ideas?  I really appreciate your assistance.

- Jeremy

---------------------------

Dwelling Productions

www.dwellingproductions.com
Attachments:

tags.jpg 27K