jablonka.czprosek.czf

weathermap

Subversion Repositories:
[/] [HTML_ImageMap.class.php] - Rev 41 Go to most recent revision

Compare with Previous - Blame - Download


<?php
// Copyright Howard Jones, 2005 howie@thingy.com
// http://wotsit.thingy.com/haj/cacti/
// Released under the GNU Public License

// A simple port of the guts of Apache's mod_imap
// - if you have an image control in a form, it's not really defined what happens to USEMAP
//   attributes. They are allowed in HTML 4.0 and XHTML, but some testing shows that they're
//   basically ignored. So you need to use server-side imagemaps if you want to have a form
//   where you are choosing a verb from (for example) a <SELECT> and also specifying part of
//   an image with an IMAGE control.
//
//
class HTML_ImageMap_Area
{
        var $href;
        var $name;
        var $id;
        var $alt;
        var $extrahtml;

        function common_html()
        {
                $h = "";
                if($this->name != "")
                {
                        $h .= " alt=\"".$this->name."\" ";
                        $h .= " id=\"".$this->name."\" ";
                }
                if($this->href != "")
                {
                        $h .= " href=\"".$this->href."\" ";
                }
                if($this->extrahtml != "")
                {
                        $h .= " ".$this->extrahtml." ";
                }
                return $h;
        }

}

class HTML_ImageMap_Area_Polygon extends HTML_ImageMap_Area
{
        var $points = array();
        var $minx,$maxx,$miny,$maxy; // bounding box
        var $npoints;

        function asHTML()
        {
                foreach ($this->points as $point)
                {
                        $flatpoints[] = $point[0];
                        $flatpoints[] = $point[1];
                }
                $coordstring = join(",",$flatpoints);

                return '<area'.$this->common_html().' shape="poly" coords="'.$coordstring.'" />';
        }

        function asJSON()
        {
                $json = "{ shape:'poly', npoints:".$this->npoints.", name:'".$this->name."',";

                $xlist = '';
                $ylist = '';
                foreach ($this->points as $point)
                {
                        $xlist .= $point[0].",";
                        $ylist .= $point[1].",";
                }
                $xlist = rtrim($xlist,", ");
                $ylist = rtrim($ylist,", ");
                $json .= " x: [ $xlist ], y:[ $ylist ], minx: ".$this->minx.", miny: ".$this->miny.", maxx:".$this->maxx.", maxy:".$this->maxy."}";

                return($json);
        }

        function hitTest($x,$y)
        {
                $c = 0;
                // do the easy bounding-box test first.
                if( ($x < $this->minx) || ($x>$this->maxx) || ($y<$this->miny) || ($y>$this->maxy))
                {
                        return false;
                }

                // Algotithm from from
                // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html#The%20C%20Code
                for ($i = 0, $j = $this->npoints-1; $i < $this->npoints; $j = $i++)
                {
                        // print "Checking: $i, $j\n";
                        $x1 = $this->points[$i][0];
                        $y1 = $this->points[$i][1];
                        $x2 = $this->points[$j][0];
                        $y2 = $this->points[$j][1];

                        //  print "($x,$y) vs ($x1,$y1)-($x2,$y2)\n";

                        if (((($y1<=$y) && ($y<$y2)) || (($y2<=$y) && ($y<$y1))) &&
                                ($x < ($x2 - $x1) * ($y - $y1) / ($y2 - $y1) + $x1))
                        {
                                $c = !$c;
                        }
                }

                return ($c);
        }

        function HTML_ImageMap_Area_Polygon ( $name="", $href="",$coords)
        {
                $c = $coords[0];

                $this->name = $name;
                $this->href= $href;
                $this->npoints = count($c)/2;

                if( intval($this->npoints) != ($this->npoints))
                {
                        die("Odd number of points!");
                }

                for ($i=0; $i<count($c); $i+=2)
                {
                        $x = intval($c[$i]);
                        $y = intval($c[$i+1]);
                        $point = array($x,$y);
                        $xlist[] = $x; // these two are used to get the bounding box in a moment
                        $ylist[] = $y;
                        $this->points[] = $point;
                }

                $this->minx = min($xlist);
                $this->maxx = max($xlist);
                $this->miny = min($ylist);
                $this->maxy = max($ylist);

                //        print $this->asHTML()."\n";
        }

}

class HTML_ImageMap_Area_Rectangle extends HTML_ImageMap_Area
{
        var $x1,$x2,$y1,$y2;

        function HTML_ImageMap_Area_Rectangle ( $name="", $href="",$coords)
        {

                $c = $coords[0];

                $x1 = $c[0];
                $y1 = $c[1];
                $x2 = $c[2];
                $y2 = $c[3];

                // sort the points, so that the first is the top-left
                if($x1>$x2)
                {
                        $this->x1=$x2;
                        $this->x2=$x1;
                }
                else
                {
                        $this->x1=$x1;
                        $this->x2=$x2;
                }

                if($y1>$y2)
                {
                        $this->y1=$y2;
                        $this->y2=$y1;
                }
                else
                {
                        $this->y1=$y1;
                        $this->y2=$y2;
                }

                $this->name = $name;
                $this->href = $href;
        }

        function hitTest($x,$y)
        {
                return  ( ($x > $this->x1) && ($x < $this->x2) && ($y > $this->y1) && ($y < $this->y2) );
        }

        function asHTML()
        {
                $coordstring = join(",",array($this->x1,$this->y1,$this->x2,$this->y2));
                return '<area'.$this->common_html().' shape="rect" coords="'.$coordstring.'" />';

        }

        function asJSON()
        {
                $json = "{ shape:'rect', ";

                $json .= " x1:".$this->x1.", y1:".$this->y1.", x2:".$this->x2.", y2:".$this->y2.",name:'".$this->name."'}";

                return($json);
        }

}

class HTML_ImageMap_Area_Circle extends HTML_ImageMap_Area
{
        var $centx,$centy, $edgex, $edgey;

        function asHTML()
        {
                $coordstring = join(",",array($this->centx,$this->centy,$this->edgex,$this->edgey) );
                return '<area'.$this->common_html().' shape="circle" coords="'.$coordstring.'" />';
        }

        function hitTest($x,$y)
        {
                $radius1 = ($this->edgey - $this->centy) * ($this->edgey - $this->centy)
                        + ($this->edgex - $this->centx) * ($this->edgex - $this->centx);

                $radius2 = ($this->edgey - $y) * ($this->edgey - $y)
                        + ($this->edgex - $x) * ($this->edgex - $x);

                return ($radius2 <= $radius1);
        }

        function HTML_ImageMap_Area_Circle($name="", $href="",$coords)
        {
                $c = $coords[0];

                $this->name = $name;
                $this->href = $href;
                $this->centx = $c[0];
                $this->centy = $c[1];
                $this->edgex = $c[2];
                $this->edgey = $c[3];
        }
}

class HTML_ImageMap
{
        var $shapes;
        var $nshapes;
        var $name;

        function HTML_ImageMap($name="")
        {
                $this->Reset();
                $this->name = $name;
        }

        function Reset()
        {
                $this->shapes = array();
                $this->nshapes = 0;
                $this->name = "";
        }

        // add an element to the map - takes an array with the info, in a similar way to HTML_QuickForm
        function addArea($element)
        {
                if (is_object($element) && is_subclass_of($element, 'html_imagemap_area')) {
                        $elementObject = &$element;
                } else {
                        $args = func_get_args();
                        $className = "HTML_ImageMap_Area_".$element;
                        $elementObject =& new $className($args[1],$args[2],array_slice($args, 3));
                }

                $this->shapes[] =& $elementObject;
                $this->nshapes++;
                //      print $this->nshapes." shapes\n";
        }

        // do a hit-test based on the current map
        // - can be limited to only match elements whose names match the filter
        //   (e.g. pick a building, in a campus map)
        function hitTest($x,$y,$namefilter="")
        {
                $preg = '/'.$namefilter.'/';
                foreach ($this->shapes as $shape)
                {
                        if($shape->hitTest($x,$y))
                        {
                                if( ($namefilter == "") || ( preg_match($preg,$shape->name) ) )
                                {
                                        return $shape->name;
                                }
                        }
                }
                return false;
        }

        // update a property on all elements in the map that match a name
        // (use it for retro-actively adding in link information to a pre-built geometry before generating HTML)
        // returns the number of elements that were matched/changed
        function setProp($which, $what, $where)
        {

                $count = 0;
                for($i=0; $i<count($this->shapes); $i++)
                {
                        // this USED to be a substring match, but that broke some things
                        // and wasn't actually used as one anywhere.
                        if( ($where == "") || ( $this->shapes[$i]->name==$where) )
                        {
                                switch($which)
                                {
                                case 'href':
                                        $this->shapes[$i]->href= $what;
                                        break;
                                case 'extrahtml':
                                        $this->shapes[$i]->extrahtml= $what;
                                        break;
                                }
                                $count++;
                        }
                }
                return $count;
        }

        // Return the imagemap as an HTML client-side imagemap for inclusion in a page
        function asHTML()
        {
                $html = '<map';
                if($this->name != "")
                {
                        $html .= ' name="'.$this->name.'"';
                }
                $html .=">\n";
                foreach ($this->shapes as $shape)
                {
                        $html .= $shape->asHTML();
                        $html .= "\n";
                }
                $html .= "</map>\n";

                return $html;
        }

        function subJSON($namefilter="",$reverseorder=false)
        {
                $json = '';

                $preg = '/'.$namefilter.'/';
                foreach ($this->shapes as $shape)
                {
                        if( ($namefilter == "") || ( preg_match($preg,$shape->name) ))
                        {
                                if($reverseorder)
                                {
                                        $json = $shape->asJSON().",\n".$json;
                                }
                                else
                                {
                                        $json .= $shape->asJSON().",\n";
                                }
                        }
                }
                $json = rtrim($json,"\n, ");
                $json .= "\n";

                return $json;
        }

        // return HTML for a subset of the map, specified by the filter string
        // (suppose you want some partof your UI to have precedence over another part
        //  - the imagemap is checked from top-to-bottom in the HTML)
        function subHTML($namefilter="",$reverseorder=false)
        {
                $html = "";
                $preg = '/'.$namefilter.'/';

                foreach ($this->shapes as $shape)
                {
                        if( ($namefilter == "") || ( preg_match($preg,$shape->name) ))
                        {
                                if($reverseorder)
                                {
                                        $html = $shape->asHTML()."\n".$html;
                                }
                                else
                                {
                                        $html .= $shape->asHTML()."\n";
                                }

                        }
                }
                return $html;
        }

}
// vim:ts=4:sw=4:
?>

Powered by WebSVN 2.2.1