HTML-EditableTable

 view release on metacpan or  search on metacpan

lib/HTML/EditableTable/Javascript.pm  view on Meta::CPAN

package HTML::EditableTable::Javascript;

use strict;
use warnings;

use Carp qw(confess);

=head1 NAME

HTML::EditableTable::Javascript

=head1 VERSION

Version 0.21

=cut

our $Version = '0.21';

my $javascriptDisplayCount = 0;

my %fieldParamJavascriptMap = (
  'tooltip' => \&jsToolTip,
  'drillDownTruncate' => \&jsExpandText,
  'jsClearColumnOnEdit' => \&jsClearColumnOnEdit,
    );

my %tableParamJavascriptMap = (
  'jsSortHeader' => \&jsSortHeader,
    );

my %formElementTypeJavascriptMap = (
  'calendar' => \&jsCalendar10Setup,
    );

=head1 SYNOPSIS

This class provides all of the javascript functionality supported in EditableTable.  It is designed so that the javascript code used can be easily overridden with local .js files  See the documetation in L<HTML::EditableTable> for guidance on extendi...

=cut

$|=1;

sub new {
  
  my $class = shift;
  my $parent = shift; # reference to parent EditableTable
  
  if (!$parent->isa('HTML::EditableTable')) { confess "parent is not an HTML::EditableTable"; }
  
  my $self= {};
  $self->{parent} = $parent;
  $self->{methods} = [];
  
  bless $self, $class;
    
  return $self;
}

sub setUid {
  my $uid = shift;
}
  
sub htmlDisplay {

  my $self = shift;

  # for multiple table case, only print these once

  print "debug displayCount = $javascriptDisplayCount<br>";

  if (!$javascriptDisplayCount) {

    # table field-level javascript support

    my @potentialJSSupportParams = keys %fieldParamJavascriptMap;
    my @potentialJSSupportFormElementTypes = keys %formElementTypeJavascriptMap; 
    my @potentialJSSupportTableParams = keys %tableParamJavascriptMap;

    # table-param-level javascript

    foreach my $param (keys %{$self->{parent}}) {
      foreach my $potentialJSSupportTableParam (@potentialJSSupportTableParams) {
	
	if (my $mp = $tableParamJavascriptMap{$param}) {
	  print $self->$mp();
	}
      }
    }
    
    foreach my $tableField (@{$self->{parent}->{tableFields}}) {
      
      # form-element-based javascript

lib/HTML/EditableTable/Javascript.pm  view on Meta::CPAN

// character enumeration
String.forEach = function(string, block, context) {
	Array.forEach(string.split(""), function(chr, index) {
		block.call(context, chr, index, string);
	});
};

// globally resolve forEach enumeration
var forEach = function(object, block, context) {
	if (object) {
		var resolve = Object; // default
		if (object instanceof Function) {
			// functions have a "length" property
			resolve = Function;
		} else if (object.forEach instanceof Function) {
			// the object implements a custom forEach method so use that
			object.forEach(block, context);
			return;
		} else if (typeof object == "string") {
			// the object is a string
			resolve = String;
		} else if (typeof object.length == "number") {
			// the object is array-like
			resolve = Array;
		}
		resolve.forEach(object, block, context);
	}
};

END_JS

    $javascript .= "</script>";

    return $javascript;
}

sub jsAddData {

  my $self = shift;

  my $tableId = $self->{parent}->getTableId();
  
  my $javascript = "<script language='javascript' type='text/javascript'>\n";
  $javascript .= <<END_JS;

  var add_data_counter = 0;
  var row_counter = 1;

  function addData() {

    add_data_counter++;
    
    var newFieldsNode = document.getElementById('readroot_$tableId').cloneNode(true);
    newFieldsNode.id = '';
    var rowFields = newFieldsNode.childNodes;

    for (var i=0;i<rowFields.length;i++) {
      var theName = rowFields[i].name; 
      var theId = rowFields[i].id;

      // special handling for the jscalendar integration
      // using id here as div tag name attribute is not supported by FF

      if (theId == "jscalsetup_$tableId") {
	// change the name of the input and span
	
	var calFields = rowFields[i].childNodes;
 	
	// hidden input field

	calFields[0].name = calFields[0].name + '_-' + add_data_counter + '_-' + add_data_counter + '_-' + add_data_counter;
	calFields[0].id = calFields[0].name;

	// text display and trigger

	calFields[2].id = calFields[2].id + '_-' + add_data_counter + '_-' + add_data_counter + '_-' + add_data_counter;
       
	// call the calendar setup

	var calSetup = { inputField : calFields[0],
			 ifFormat : "%Y-%m-%d",
			 displayArea : calFields[2],
			 daFormat : "%Y-%m-%d",
			 cache : true    
                       };
 
	Calendar.setup(calSetup);     
      }
      else if (theName) {
 	rowFields[i].name = theName + '_-' + add_data_counter + '_-' + add_data_counter + '_-' + add_data_counter;
	rowFields[i].id = rowFields[i].name;
      }     
    }
    
    // add table cells and move the nodes into them

    var newrow = document.getElementById('addData').insertRow(row_counter);
    var fieldCount = 0;

    while(rowFields.length > 0) {
      var cell = newrow.insertCell(fieldCount++);
      // note that the following method modifies the collection
      cell.appendChild(rowFields[0]);
    }
  }
END_JS

  $javascript .= "</script>";
  return $javascript;
}

sub jsCalendar10Setup {

  my $self = shift;
  my $calendarDir = $self->{parent}->getCalendarDir();

  my $javascript = "<style type='text/css'>\@import url($calendarDir/calendar-win2k-1.css);</style>\n";
  $javascript .=  "<script type='text/javascript' src='$calendarDir/calendar.js'></script>\n";
  $javascript .=  "<script type='text/javascript' src='$calendarDir/lang/calendar-en.js'></script>\n";
  $javascript .=  "<script type='text/javascript' src='$calendarDir/calendar-setup.js'></script>\n";
  
  return $javascript;
}

sub jsToolTip {

  my $self = shift;

  my $javascript = "<script language='javascript' type='text/javascript'>\n";
  $javascript .= <<'END_JS';

  // from OReilly Javascript - The Definitive Guide

  // must put in body

  var Geometry = {};
  
  // IE
      
      if (window.screenLeft) {
	Geometry.getWindowX = function() { return window.screenLeft; };
	Geometry.getWindowY = function() { return window.screenTop; };
  }
  
  // Firefox
      
      else if (window.screenX) {
	Geometry.getWindowX = function() { return window.screenX; };
	Geometry.getWindowY = function() { return window.screenY; };
  }
  
  
  // all but IE
      
      if (window.innerWidth) {
	
	Geometry.getViewportWidth = function() { return window.innerWidth; };
	Geometry.getViewportHeight = function() { return window.innerHeight; };
	Geometry.getHorizontalScroll = function() { return window.pageXOffset; };
	Geometry.getVerticalScroll = function() { return window.pageYOffset; };
  }
  
  // IE 6 w DOCTYPE
      
      else if (document.documentElement && document.documentElement.clientWidth) {
	
	Geometry.getViewportWidth = function() { return document.documentElement.clientWidth; };
	Geometry.getViewportHeight = function() { return document.documentElement.clientHeight; };
	Geometry.getHorizontalScroll = function() { return document.documentElement.scrollLeft; };
	Geometry.getVerticalScroll = function() { return document.documentElement.scrollTop; };
  }
  
  // all other IE (not sure about 7)
      
      else {
	
	Geometry.getViewportWidth = function() { return document.body.clientWidth; };
	Geometry.getViewportHeight = function() { return document.body.clientHeight; };
	Geometry.getHorizontalScroll = function() { return document.body.scrollLeft; };
	Geometry.getVerticalScroll = function() { return document.body.scrollTop; };



( run in 1.340 second using v1.01-cache-2.11-cpan-39bf76dae61 )