Location: PHPKode > scripts > Info Box > info-box/class_infobox.php
<?php
/*
* Filename.....: class_infobox.php
* Aufgabe......: Generate floating infobox tips as seen at http://www.knoppix.de
* Parameter....: none
* Erstellt am..: Dienstag, 1. März 2005
*       _  __      _ _
*  ||| | |/ /     (_) |        Wirtschaftsinformatiker IHK
* \. ./| ' / _ __  _| |_ ___   www.ingoknito.de
* - ^ -|  < | '_ \| | __/ _ \
* / - \| . \| | | | | || (_) | Peter Klauer
*  ||| |_|\_\_| |_|_|\__\___/  06131-651236
* mailto.......: hide@address.com
*
* Makes use of infobox.js (C) 2002 Klaus Knopper <hide@address.com>
* distributed under the GNU GENERAL PUBLIC LICENSE Version 2.
*
* The class generates screenreader friendly floating infoboxes.
* This class frees the programmer from the hazzle of thinking of
* a new name (which is never shown anywhere) for every single infobox.
* It collects all the infos straightforward into an array and generates
* the boxes at the end of the page.
* Transforms boxes to standard title attributes when switched off per cookie.
*
* Some error checking is done via $called_head and $called_generate.
*
* History:
* 2006-07-19: Bugfix: Had to rename infobox.dummy to infobox.html because IE wanted
*             to download it.
* 2006-07-18: Bugfix: <select> Problem solved: Infobox floated UNDER select boxes
*             in MSIE. This is fixed now with an <iframe>-hack submitted by
*             Oleg Baranovsky. Thank you, Mr. Baranovsky!
*             The new EMPTY file "infobox.dummy" is only used to prevent server
*             error messages when trying to read the src of the iframe.
* 2006-04-28: onoff(): global $_SERVER instead of global $PHP_SELF
* 2006-04-20: Bugfix from Mike White (mike [at] white [minus] home [dot] com)
*             for scrolled position in netscape and Mozilla
* 2005-03-25: Changed onoff() howto: Clean the resulting page code if infoboxes
*             are switched off by the user. Only infobox.js is included via
*             the <script> statement because of "setcookie"
* 2005-03-23: Changed onoff() link
* 2005-03-17: infobox::onoff corrected to infobox::onoff_onoff
* 2005-03-15: After a mouseclick on a infobox-link sometimes the mouseout-event
*             does not hide the infobox layer away. It stays visible at position
*             top=0, left=0. Giving the "infodiv" and div.infobox in infobox.css
*             a "left" position of -10000px moves it out of sight.
*             Head only holds js function showtip().
*             maketip(), getScrollXY() and SetCookie() have moved to infobox.js.
* 2005-03-13: New: onoff link for enhanced screenreader compatibility or "calmer"
*             pages switch infoboxes off using a cookie named "infobox"
* 2005-03-10: Generated HTML Code (strict!) did not validate because of
*             LANGUAGE=\"JavaScript\" in the <script> sections of infobox::head()
*             and infobox::generate()
* 2005-03-09: JS maketip() is also replaced when $replace_javascript is true.
*             Var $replace_showtip is renamed to $replace_javascript.
*             The new js function maketip() does not use many tables but 3 div sections.
*             Changed infobox.css to hold meaningful infobox classes that work.
* 2005-03-08: infobox::newtip() replaces </ with <\/ to have w3c-html-tidy-proof javascript code
*
*/

class infobox
{

  #
  # user vars
  #
  var $before = ''; // output this before a link is done
  var $after = ' '; // output this after a link is done
  var $showinfobox = true; // show them infoboxes, really?
  var $debug = false; // show debugging status line
  var $pathtoinfobox = ''; // path to infobox parts

  #
  # highlighting css class or inline style for infoboxed elements
  #
  var $class = '';
  var $style = '';

  var $onoff_linktext = 'InfoBox';
  var $onoff_onoff   = array( 'ON', 'OFF' );
  var $onoff_caption = 'Infobox';
  var $onoff_description = 'Switch infobox ';
  var $onoff_written = false;	// Flag for ScreenReader friendlyness
  var $onoff_days = 30; // Number of days for infobox cookie expiration

  var $lockx = -1; // any positive value including 0 will lock x position
  var $locky = -1; // any positive value including 0 will lock y position
  var $width = 250; // set IWIDTH of infobox

  ################################################################################
  # internal variables
  # starting from here the following vars should not be changed from
  #
  var $ib_arr = array(); // collects all the infoboxes
  var $counter = 0; // internal counter for the infoboxes
  var $last_tip = -1;
  #
  # error checking variables
  #
  var $called_head = 0;
  var $called_generate = 0;
  #
  ####################################################################eof internal

  /**
  * class constructor
  */
  function infobox()
  {
    if( isset( $_COOKIE['infobox'] ))
    {
      if( $this->debug) echo $_COOKIE['infobox'];

      $this->showinfobox = ( $_COOKIE['infobox'] == 'ON' );
    }
  }


  /**
  * inserts loading of infobox.js into head section of html page
  * inserts loading of infobox.css into head section of html page
  * replaces js function showtip() and sets var IWIDTH to infobox::width
  *
  * head() is to be called in the head section of the page
  *
  * @param string $pathtoinfobox = path to infobox.js and infobox.css
  * @return void
  **/
  function head($pathtoinfobox='')
  {

    $this->pathtoinfobox = $pathtoinfobox;

    if( $this->called_head > 0 )
    {
      $this->error('head(): Was already called '.$this->called_head++.' times.');
      return;
    }


    $this->onoff_description .= $this->onoff_onoff[ ($this->showinfobox*1) ];

    // There is SetCookie in it, we need it always!
    echo "
<SCRIPT TYPE=\"text/javascript\" SRC=\"$pathtoinfobox"."infobox.js\"></SCRIPT>
";

    if( $this->showinfobox )
    {

      echo "<link rel='Stylesheet' type='text/css' href='$pathtoinfobox"."infobox.css'>
";

      echo "
<SCRIPT TYPE=\"text/javascript\">
<!--
var IWIDTH=$this->width ; // set IWIDTH to infobox::width
";

      echo "function showtip(){

  // this function replaces the original infobox.js::showtip() which was loaded before
  // using getScrollXY() it is capable of respecting scrolled positions
  // knito - at - knito - dot - de 2005-03-03 http://www.ingoknito.de
  // iframe hack submitted by Oleg Baranovsky in July 2006

  var xy;
  xy = getScrollXY();
";

      if( $this->lockx == -1 )
      {
        echo "  idiv.left=(((x+IWIDTH+20)<winW)?x+12:x-IWIDTH-5)+xy[0]+px;
";
      }
      else
      {
        echo "  idiv.left=".$this->lockx."+px;
";
      }

      if( $this->locky == -1 )
      {
        // Code added 4/18/06 by Mike White
        echo "  y=y>window.innerHeight?window.innerHeight-(winH-y):y;
";
        // End code added
        echo "  idiv.top=(((y+90)<winH)?y+12: y-90)+xy[1]+px;
";
      }
      else
      {
        echo "  idiv.top=".$this->locky."+px;
";
      }


      echo "  idiv.visibility=ns4?\"show\":\"visible\";
";

   echo "
  /**
   * now we need to reposition the hidden iframe underneath our idiv
   * and resize it to the same size as idiv.
   * also set it up with z-index smaller than for idiv
   */
   if( ie4 || ie5 )
   {
      idivif=document.getElementById('infodivif');
      if (idivif)
      {
        idivif.style.width = idiv1.offsetWidth;
        idivif.style.height = idiv1.offsetHeight;
        idivif.style.top = idiv.top;
        idivif.style.left = idiv.left;
        idivif.style.visibility = 'visible';
      }
  }
";


      if( $this->debug)
      {
        echo "  window.status = 'winH: '+winH+ ' y: '+y+' xy[1]:'+xy[1]+' idiv.top:'+idiv.top;
        ";
      }

      echo "}
// -->
</script>
"; // end of echo the javascript functions

    } // showinfobox == true

    $this->called_head++;

  } // eof  head()


  /**
  * writes a hyperlink and fills an array and increases a static counter
  *
  * @param string $url = url where to go to
  * @param string $text = text (img) to click upon
  * @param string $caption = caption in infobox
  * @param string $description = descriptive text to appear in infobox
  * @param string $target = target window for hyperlink, empty by default
  * @return void
  **/
  function link( $url, $text, $caption, $description, $target='' )
  {

    $t = $target == '' ? '' : " target='$target'";
    echo $this->before;
    echo "<a href='$url'".$this->newtip($caption,$description)."$t>$text</a>";
    echo $this->after;

  } // eof link()


  /**
  * returns a string that contains onMouseOver and onMouseOut for a certain infobox
  * @param integer $number = number of the tip to output
  * @return string
  **/
  function thistip( $number )
  {
    $c = $this->class == '' ? '' : ' class="'.$this->class.'"';
    $s = $this->style == '' ? '' : ' style="'.$this->style.'"';

    $result = "$c$s onMouseOver=\"tip('infobox$number')\" onMouseOut=\"untip()\"";
    return $result;

  } // eof thistip()


  /**
  * generates a new infobox and
  * returns a string that contains onMouseOver and onMouseOut for this infobox
  * If you need quotes in $caption or $description always use
  * "double quotes".
  *
  * @param string $caption = caption of the infobox
  * @param string $description = descriptive text in body of infobox, may contain html code
  * @return string
  **/
  function newtip( $caption, $description )
  {


    $ok = true;
    $result = '';


    if( $this->debug )
    {
      $caption = '#'.$this->counter.': '.$caption;
    }

    if( ( $this->called_head == 0 ) and ($this->showinfobox ))
    {
      $this->error('newtip(): please call infobox::head() in the head-section of this page!');
      $ok = false;
    }

    if( ( $this->called_generate == 1 ) and ($this->showinfobox ))
    {
      $this->error( 'newtip(): please call infobox::generate() <b>after</b> all calls to infobox::link()');
      $ok = false;
    }


    if( $ok )
    {

      #
      # Generate screenreader friendly topmost onoff link unvisible to
      # normal browsers.
      #

      if( $this->last_tip == -1 )
      {
        $this->last_tip = 0; // no Stack overflow, please!
        echo "\n".'<div '.$this->unvisiblestyle().'>';
        $this->onoff('', true );
        echo '</div>';
      }

      $description = str_replace( "\n", ' ', $description );
      $description = str_replace( "\r", ' ', $description );

      if( $this->showinfobox )
      {
        // making it tidy proof 2005-03-08 knito
        $caption = str_replace('</','<\\/', $caption);
        $description = str_replace( '</','<\\/', $description);

        $this->ib_arr[$this->counter] = array( $caption, $description );
        $result = $this->thistip($this->counter);
        $this->last_tip = $this->counter;
        $this->counter++;
      }
      else
      {
        $caption = strip_tags( $caption );
        $description = strip_tags($description);

        $result = " title='$caption: $description' ";
      }
    }

    return $result;

  }	// eof newtip()


  /**
  * returns a string that contains onMouseOver and onMouseOut for the last created infobox
  * @return string
  **/
  function lasttip()
  {

    return $this->thistip($this->last_tip);

  } // eof lasttip()


  /**
  * Generate the div used for infobox,
  * generate all tips in a script section.
  * This script has to be called at the end of the body section
  * after all visible output to the page is done.
  * @return void
  **/
  function generate()
  {

    #if( !$this->showinfobox ) return;

    if( !$this->onoff_written )
    {
      echo "\n".'<div '.$this->unvisiblestyle().'>';
      $this->onoff('', true );
      echo '</div>';
    }

    if( ($this->last_tip == -1 ) and ($this->showinfobox))
    {
      $this->error( 'generate(): Please call all infobox::newtip()s/link()s before calling me!');
    }
    else
    {

      if( $this->showinfobox )
      {

        echo '<DIV ID="infodiv" STYLE="position:absolute; visibility:hidden; z-index:20; top:0px; left:-10000px;"></DIV>';

        #
        # workaround for MSIE to show hints over <select> items
        # Now we need to use the hidden <iframe> and show it underneath
        # our <div> layer in the showtip() function
        # As this is only for IE, we use a IE-ONLY comment construct
        #
        # ... it stops firefox from "shivering" when the iframe moves
        # ... and like that it may be always tidy proof!
        #
          echo '
        <!--[if IE]>
        <iframe id="infodivif" src="'.$this->pathtoinfobox.'infobox.html" scrolling="no" frameborder="0" style="position:absolute; top:0px; left:0px; visibility:hidden; z-index:19;"></iframe>
        <![endif]-->
        ';


        echo "
        <SCRIPT TYPE=\"text/javascript\">
        <!--
        ";
        for( $i = 0; $i < count( $this->ib_arr ); $i++ )
        {
          echo "maketip('infobox$i','".$this->ib_arr[$i][0]."', '".$this->ib_arr[$i][1]."');\n";
        }

        echo "// -->
        </SCRIPT>
        ";

      } // showinfobox == true

      $this->called_generate = 1;

    } // end of else $this->last_tip unlike -1

  } // eof generate()


  /**
  * return a style string for a div section to move it out of sight from normal browsers.
  * Screenreaders shall "display" it because the style attribute "visibility" is not set
  * to "hidden".
  *
  * @return string
  **/
  function unvisiblestyle()
  {
    return ' style="position:absolute; left:-10000px; top:0; height:0; width:0; overflow:hidden"';
  }


  /**
  * generate a link that sets a cookie to switch infoboxes on or off.
  * This link always has a infobox.
  *
  * @param string $url = $PHP_SELF per default
  * @param boolean $hidden = Hide this link away if set to true
  * @return void
  **/
  function onoff($url='', $hidden=false)
  {
    global $_SERVER;

    $PHP_SELF = $_SERVER['PHP_SELF'];

    if( $url == '' ) $url = $PHP_SELF;

    $newvalue = ($this->showinfobox==false) ? $this->onoff_onoff[0] :  $this->onoff_onoff[1];


    $title = $this->showinfobox ?
    ' title=\'ScreenReaders: Please set infobox to OFF. Cookies must be enabled.\'' : '';


    $expiring = date( 'D, d M Y H:i:s', mktime( date('h'), date('i'), 0, date('m'), (date( 'd')+$this->onoff_days) , date('Y'))). ' GMT';

    $mouse = $this->newtip($this->onoff_caption, $this->onoff_description ).$title;

    $style = $hidden  ? $this->unvisiblestyle()  : '';

    echo "<a $mouse $style href='$PHP_SELF' onclick='setCookie(\"infobox\", \"$newvalue\", \"$expiring\")'>".
    $this->onoff_linktext." $newvalue</a>";

    $this->onoff_written = true;
  }


  /**
  * internal error reporting function formats text to look ugly to be sure to be seen
  * @param string $message = descriptive text what error it was
  **/
  function error( $message )
  {

    echo '<div style="color:red;font-weight:bold;font-size:12pt;font-family:monospace">'.
    "infobox::$message</div>";

  } // eof error()
}
?>
Return current item: Info Box