Tag Cloud - need help

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

By Jason - March 22, 2013

Hi Jeremy,

I think I found it.  We are missing a $key value in the shuffle function.  Try this change:

function shuffle_assoc($list) { 
  if (!is_array($list)) return $list; 

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

That should do it!

---------------------------------------------------
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 davidcmsb - March 23, 2013

This looks great.  I'd love to know how to create a tag cloud using CMSB.

Could you please post in one clear "how to" post all the steps and code to implement the tag cloud in CMSB.

Thanks very much,

David

Hi Jason (and Greg)!  :-)

Thank you so much for all your input on this!  It is working exactly as intended now!  Phew!  :-)

The more I think about (and test) this, I'm starting to feel that my choice of using straight percentages may not have been the best way to go.  It is not often that a tag is used 50% or more of the time.  And, if it is, it doesn't leave many percentage points left for the other tags, so you end up with perhaps one or two larger tags, and then a bunch of smaller tags.  There are just not that many percentage points to go around.  I could have skipped the rounding step, but then you'd have to deal with a ton of CSS styles to define.

I'm thinking I might mess around with using straight tabulation to determine frequency, then the top most used tag would be assigned the largest possible font-size.  Then, the next most used tag would be assigned the second largest font-size, and so on (up to as many tags as you wish to allow).  Or, even better, ranges of font-sizes, determined by percentages of the total tags to be displayed (and assigned to each tag in order of frequency) could be used to determine which CSS style each was assigned to.  (Just thinking out loud here... and probably not making much sense.)  :-)

Anyway, I'll keep fiddling.  But, at least I have something that works and can be used right now.  And, again, I can't thank you guys enough.

@DavidCMSB - In just a couple days, I'll post a complete commented script for this "percentage-based" tag cloud.  It works great!  But, as I stated above, I think it can be even better implemented (now that I've had a chance to really see it working).  Hopefully I, or someone else, and improve on this even more.  I think having a solid, easy-to-use tag cloud feature, designed with CMSB in mind is a huge benefit to those wanting to add that to their sites.  In the future, another cool idea would be to generate a tag cloud automatically based on search terms used with a site's search feature.  That could be pretty handy too.  :-)

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

Dwelling Productions

www.dwellingproductions.com

By davidcmsb - March 24, 2013

Thank you.  That'll be great.  Great work. 

00000000

By dwellingproductions - March 29, 2013 - edited: March 30, 2013

OK.  For anyone interested, I'm posting the final code for my tag cloud written specifically for use with CMS Builder (and thanks to all the help from the Interactive Tools team getting the trickiest parts working).  

To see a sample of how it looks the way I implemented it, see the attached JPEG image.  I now believe there may be a better way to approach this whole thing (as I mention in my post here: http://www.interactivetools.com/forum/forum-posts.php?postNum=2230008#post2230008); however, this version still works well and is still a completely valid tag cloud method.  

Anyway, here's the code.  This example is set up in CMSB with a multi-section called "blog_content", a field for the tags called "tags", a viewer page called "blog.php", and a list page called "blog_list.php" .  You'll need to change the items in red to match your CMSB configuration:

<style>
/*** tags style ***/
#tags a{
color: #777;
font:normal 13px/26px Segoeui, Arial, Verdana, serif;
text-decoration: none
}
#tags a:hover{
color: #444;
}
/*** TAGS - 10 font-size steps ***/
#tags a.t0{font-size: 11px}
#tags a.t10{font-size: 12px}
#tags a.t20{font-size: 16px}
#tags a.t30{font-size: 20px}
#tags a.t40{font-size: 20px}
#tags a.t50{font-size: 24px}
#tags a.t60{font-size: 24px}
#tags a.t70{font-size: 27px}
#tags a.t80{font-size: 27px}
#tags a.t90{font-size: 27px}
#tags a.t100{font-size: 27px}
</style>



<?php

$tagsToCount = array();
$sectionsToField = array('blog_content' => 'tags'/*, 'blog2_content' => 'tags'*/); //to draw tags from multiple sections remove php comment tags and add as shown, otherwise you can delete everything between and including these: /* */


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, but this version does.
function shuffle_assoc($list) { 
  if (!is_array($list)) return $list; 

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


 ?>


<!-- DISPLAY TAGS -->
<?php $tagsToCount = shuffle_assoc($tagsToCount); ?>
 <?php if ($tagsToCount): ?>
        <aside id="tags">
     <h3>Tags</h3>
         <?php  $maximumResults = 18;
                $resultCount = 0;
         ?>
           <?php $totalTagCount = array_sum($tagsToCount); ?>
           <?php foreach ($tagsToCount as $key => $value): ?>
           <?php           
             $ratio =  (intval($value)/$totalTagCount) * 100; //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="blog_list.php?tags_keyword=<?php echo $key;?>"><?php echo $key; ?></a>
             <?php if (++$resultCount == $maximumResults) { break;}?>
           <?php endforeach ?>
        </aside>
 <?php endif ?>

For a quick sample of how this could look in use on your page, you can add the following html:

<!-- Tags - SAMPLE -->

      <aside id="tags">
     <h3>Tags - Sample</h3>
     <a class="t7" href="">design</a>
     <a class="t3" href="">color</a>
     <a class="t8" href="">web design</a>
     <a class="t1" href="">computer</a>
     <a class="t2" href="">ecommerce</a>
     <a class="t9" href="">php</a>
     <a class="t2" href="">html</a>
     <a class="t6" href="">code</a>
     <a class="t3" href="">logos</a>
     <a class="t8" href="">letterhead</a>
     <a class="t2" href="">branding</a>
     <a class="t8" href="">print</a>
     <a class="t4" href="">web</a>
     <a class="t3" href="">freelance</a>
     <a class="t5" href="">business</a>
     <a class="t3" href="">store</a>
     <a class="t10" href="">internet</a>
      </aside><!-- #tags -->

Well, that's it!  Have fun!  If anyone chooses to modify it in the way I suggest in my previous forum post, I'd love to know and see what you come up with.

All the best!

- Jeremy

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

Dwelling Productions

www.dwellingproductions.com
Attachments:

sample.jpg 19K

By davidcmsb - March 29, 2013

Awesome, congratulations and thank you for posting the code.

David

000000

Oops... I just realized I failed to figure out how to link to articles containing the tags.  Hopefully someone at I.T. will read this.  :-)

Now that the tags are displaying correctly, how do I make each tag link to a page that will display a list of any article(s) designated with that tag in the article's tag list?

Thanks, in advance!

- Jeremy

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

Dwelling Productions

www.dwellingproductions.com

By Jason - March 29, 2013

Hi Jeremy,

How you can approach this depends on how you've set up your listpage.  The easiest way to go about this, is to put your tag into the URL and let getRecords do the search for you.

For example:

<a class="t<?php echo $ratio; ?>" href="blogList.php?tags_keyword=<?php echo $key;?>"><?php echo $key; ?></a>

Hope this helps get you started.

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

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

Thanks so much Jason!  That was it!   :-)

OK... I've updated the code above so that it is now complete with the proper linking in place.

- Jeremy

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

Dwelling Productions

www.dwellingproductions.com

Hey all!

Well, I made some additional changes to the way this tag cloud works and I'm much happier with it now.  Before, it worked as a straight percentage, but this resulted in little to no larger font sizes.  This new version gives a better overview of tag usage and better distributes font sizes among the top-used tags.  A random display is made of only the designated number of the top-used tags.  Anyway, just thought I'd post my results with this new method in case anyone can use it in the future.  Enjoy!  :-)

(This code is based on having set up a CMS Builder multi-section called "blog_content" with a field called "tags".  You will have to edit the information in red if changing these section and field names.)

<?php
$tagsToCount = array();
$sectionsToField = array('blog_content' => 'tags'/*, 'blog2_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, but this version does.
function shuffle_assoc($list) { 
  if (!is_array($list)) return $list; 

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


 ?>


<?php /* DISPLAY TAGS */ ?>
<?php

 $tagsToCount = shuffle_assoc($tagsToCount); ?>
 <?php if ($tagsToCount): ?>
        <aside id="tags">
     <h3>Tags</h3>
         <?php  $maximumResults = 18;
$resultCount = 0;
 ?>
<?php $totalTagCount = array_sum($tagsToCount); ?>

<?php
$min_size = 10; //smallest font size
$max_size = 27; //largest font size
$minimum_count = min(array_values($tagsToCount));
$maximum_count = max(array_values($tagsToCount));
$spread = $maximum_count - $minimum_count;
if($spread == 0) {
$spread = 1;
}

    arsort($tagsToCount);
            $tagsToCount = array_slice($tagsToCount, 0, 17);
            $tagsToCount = shuffle_assoc($tagsToCount);
foreach ($tagsToCount as $key => $value): ?>
<?php           
$size = $min_size + ($value - $minimum_count) * ($max_size - $min_size) / $spread;

?>
<a style="font-size: <?php echo floor($size)?>px;" href="../blog_list.php?tags_keyword=<?php echo $key;?>" title='Articles: <?php echo $value; ?>'><?php echo $key; ?></a>
              <?php if (++$resultCount == $maximumResults) { break;}?>
  <?php endforeach ?>
        </aside>
 <?php endif ?>

- Jeremy

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

Dwelling Productions

www.dwellingproductions.com