PageRenderTime 68ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/Html.class.php

https://github.com/athill/PHP-HTML_Generator
PHP | 1138 lines | 819 code | 94 blank | 225 comment | 268 complexity | 8e23294990443c9d1d640a4612b7a7e0 MD5 | raw file
  1. <?php
  2. /*
  3. Copyright 2012 andy hill
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. */
  14. /**
  15. * HTML generating interface
  16. *
  17. * @author andy hill 1 2009-2014
  18. * @version 3.2
  19. *
  20. */
  21. require_once('Xml.class.php');
  22. class Html extends Xml {
  23. private static $instance;
  24. var $js = array();
  25. var $jsInline = false;
  26. /**
  27. * constructor
  28. */
  29. function __construct() {
  30. $GLOBALS['site']['webroot'] = (array_key_exists('site', $GLOBALS) &&
  31. array_key_exists('webroot', $GLOBALS['site'])) ?
  32. $GLOBALS['site']['webroot'] :
  33. '';
  34. }
  35. public static function singleton() {
  36. if (!isset(self::$instance)) {
  37. $c = __CLASS__;
  38. self::$instance = new $c;
  39. }
  40. return self::$instance;
  41. }
  42. public function __clone() {
  43. trigger_error('Clone is not allowed.', E_USER_ERROR);
  44. }
  45. function __call($name, $args) {
  46. $emptyTags = explode(',', "area,base,br,col,hr,img,input,keygen,link,meta,param,source,track");
  47. $nonemptyTags = explode(',', "a,abbr,address,article,aside,audio,b,bdi,bdo,blockquote,body,canvas,caption,cite,code,colgroup," .
  48. "command,datalist,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6," .
  49. "head,header,hgroup,html,i,iframe,ins,kbd,label,legend,li,map,mark,menu,meter,nav,noscript,object,ol,optgroup,option," .
  50. "output,p,pre,progress,q,rp,rt,ruby,s,samp,script,section,select,span,strong,style,sub,summary,sup,table,tbody," .
  51. "td,textarea,tfoot,th,thead,time,title,tr,u,ul,var,video,wbr");
  52. $indentTags = explode(',', "datalist,div,dl,fieldset,footer,header,nav,ol,section,select,tr,ul");
  53. $command = substr($name, 0, 1);
  54. $tag = substr($name, 1);
  55. //echo 'command: '. $command . ' tag: ' . $tag . ' in array?'. in_array($tag, $nonemptyTags);
  56. ////empty tag
  57. if (in_array($name, $emptyTags) && $name != 'col') {
  58. $atts = count($args) > 0 ? $args[0] : '';
  59. $this->tag($name, $atts);
  60. ////input tag
  61. } else if (in_array($name, explode(',', "radio,checkbox,hidden,submit,button,reset,number,month,intext,date,color,datetime,".
  62. "inemail,range,search,tel,time,url,week"))) {
  63. $fieldname = $args[0];
  64. $value = count($args) >= 2 ? $args[1] : '';
  65. $atts = count($args) >= 3 ? $args[2] : '';
  66. if ($name == 'date') {
  67. $atts = $this->addClass($this->fixAtts($atts), "datepicker");
  68. if (strpos("size=", $atts) === false) $atts .= ' size="15"';
  69. }
  70. $pos = strpos('in', $name);
  71. if ($pos == 0) $name = str_replace('in', '', $name);
  72. $this->input($name, $fieldname, $value, $atts);
  73. ////open/close tag
  74. } else if (in_array($name, $nonemptyTags)) {
  75. // $this->tbr('nonempty');
  76. $content = $args[0];
  77. $atts = count($args) >= 2 ? $args[1] : '';
  78. $inline = !preg_match('/\n/', $content);
  79. $this->tag($name, $atts, $content, $inline, false);
  80. ////open tag
  81. } else if ($command == 'o' && in_array($tag, $nonemptyTags)) {
  82. $atts = count($args) > 0 ? $args[0] : '';
  83. $indent = in_array($tag, $indentTags);
  84. // echo $indent;
  85. $this->otag($tag, $atts, $indent);
  86. ////close tag
  87. } else if ($command == 'c' && in_array($tag, $nonemptyTags)) {
  88. $comment = count($args) > 0 ? $args[0] : '';
  89. $indent = in_array($tag, $indentTags);
  90. $this->ctag($tag, $indent, $comment);
  91. ////close/open tag
  92. } else if (substr($name, 0, 2) == 'co' && in_array(substr($name, 2), $nonemptyTags)) {
  93. $tag = substr($name, 2);
  94. $indent = in_array($tag, $indentTags);
  95. $atts = count($args) > 0 ? $args[0] : '';
  96. $this->ctag($tag, $indent);
  97. $this->otag($tag, $atts, $indent);
  98. } else {
  99. parent::__call($name, $args);
  100. }
  101. }
  102. // public function rtn($fn, $args) {
  103. // $this->startBuffer();
  104. // $this->__call($fn, $args);
  105. // return $this->endBuffer();
  106. // }
  107. //// Adds webroot to local link if not already there
  108. private function fixLink($link) {
  109. global $site;
  110. $startsWithSlash = substr($link, 0, 1) == "/";
  111. $webrootNonempty = strlen($site['webroot']);
  112. $noWebrootInLink = $webrootNonempty && strpos($link, $site['webroot']) !== 0;
  113. $link = ($startsWithSlash && $webrootNonempty && $noWebrootInLink) ?
  114. $site['webroot'] . $link :
  115. $link;
  116. // $this->tbr('webroot: '.$startsWithSlash.'|'.$webrootNonempty.'|'.$noWebrootInLink);
  117. return $link;
  118. }
  119. // print array
  120. function pa($array) {
  121. $this->opre();
  122. print_r($array);
  123. $this->cpre();
  124. }
  125. //// rather than output tag to screen, return it as a string
  126. //// $str = $h->rtn('img', array('src', 'alt'));
  127. public function rtn($methodName, $args=array()) {
  128. if ($methodName == "rtn") die("Recursion fail");
  129. if (!method_exists($this, $methodName)) die("Bad method name");
  130. if ($methodName == "startBuffer" || $methodName == "endBuffer") die("Bad method start/endBuffer");
  131. try {
  132. $this->startBuffer();
  133. call_user_func_array(array($this, $methodName), $args);
  134. return trim($this->endBuffer());
  135. } catch (Exception $e) {
  136. die("Unspecified error in rtn");
  137. }
  138. }
  139. /*****
  140. * Document Tags
  141. ******************/
  142. public function ohtml($title, $includes= array(), $options=array()) {
  143. $this->tnl('<!DOCTYPE html>');
  144. $this->otag("html", 'lang="en"', false);
  145. $this->otag("head");
  146. $this->tag("title", '', $title, true, false);
  147. $defaults = array(
  148. 'description' => "",
  149. 'keywords' => "",
  150. 'author' => "",
  151. 'copyright' => date('Y'). '',
  152. 'icon'=>'',
  153. 'compatible'=>'IE=edge,chrome=1',
  154. 'viewport'=>'width=device-width',
  155. 'charset'=>'uft-8'
  156. );
  157. $options = $this->extend($defaults, $options);
  158. $this->tag("meta", 'charset="'.$options['charset'].'"');
  159. $this->tag("meta", 'http-equiv="X-UA-Compatible" content="'.$options['compatible'].'"');
  160. $metas = array('keywords', 'description', 'author', 'copyright', 'viewport');
  161. foreach ($metas as $meta) {
  162. if ($options[$meta] != '') {
  163. $this->tag('meta', 'name="'.$meta.'" content="'.$options[$meta].'"');
  164. }
  165. }
  166. if ($options['icon'] != '') {
  167. $this->tag("link", 'rel="icon" href="'.$options['icon'].'"');
  168. $this->tag("link", 'rel="shortcut icon" href="'.$options['icon'].'"');
  169. }
  170. for ($i = 0; $i < count($includes); $i++) {
  171. $filenameParts = explode('.', $includes[$i]);
  172. $ext = end($filenameParts);
  173. if ($ext === "js") {
  174. $this->scriptfile($includes[$i]);
  175. } else {
  176. $this->stylesheet($includes[$i]);
  177. }
  178. }
  179. }
  180. public function body($atts="") {
  181. $atts = $this->fixAtts($atts);
  182. if ($this->strictIndent) $this->tabs--;
  183. $this->ctag('head');
  184. $this->otag('body', $this->fixAtts($atts));
  185. }
  186. public function chtml() {
  187. if(!$this->jsInline){
  188. for($i=0;$i<sizeof($this->js);$i++) {
  189. if($this->js[$i]['type']=='file'){
  190. $this->scriptfile($this->js[$i]['value'],true);
  191. } else {
  192. if ($i==0 || $this->js[$i-1]['type']=='file'){
  193. $this->oscript(true);
  194. }
  195. $this->tnl($this->js[$i]['value']);
  196. if ($i == sizeof($this->js)-1 || $this->js[$i+1]['type']=='file') {
  197. $this->cscript(true);
  198. }
  199. }
  200. }
  201. }
  202. $this->ctag('body');
  203. $this->ctag("html");
  204. }
  205. /********************
  206. * General Tags
  207. **********************/
  208. public function br($count=1) {
  209. for ($i = 0; $i < $count; $i++) {
  210. $this->tag('br');
  211. }
  212. // $this->tnl(str_repeat("<br />", $count));
  213. }
  214. ////Links
  215. public function a($href, $display="", $atts="") {
  216. if ($display == "") $display = $href;
  217. $this->tnl('<a href="'.$this->fixLink($href).'"'.$this->fixAtts($atts).'>'.$display.'</a>');
  218. }
  219. ////name
  220. public function name($name, $content="", $atts='') {
  221. $atts = 'name="'.$name.'" id="'.$name.'"'.$this->fixAtts($atts);
  222. //$this->tag("a", $atts, $content, true);
  223. $this->tnl('<a '.$atts.'>'.$content.'</a>');
  224. }
  225. ////img
  226. public function img($src, $alt, $atts="") {
  227. $atts = $this->fixAtts($atts);
  228. $this->tnl('<img src="' . $this->fixLink($src) . '" alt="' . $alt . '"'.$atts.'/>');
  229. }
  230. ///////Javascript
  231. public function scriptfile($files,$inline='') {
  232. if ($inline == '') $inline = $this->jsInline;
  233. if (!is_array($files)) $files = array($files);
  234. foreach ($files as $file) {
  235. if($inline) {
  236. $this->tag('script', 'src="'.$this->fixLink($file).'"', '', true, false);
  237. } else {
  238. $this->js[] = array('type'=>'file','value'=>$file);
  239. }
  240. }
  241. }
  242. public function script($js,$inline='') {
  243. if ($inline == '') $inline = $this->jsInline;
  244. if($inline){
  245. $this->oscript(true);
  246. //add XHTML comments
  247. $this->tnl(trim($js));
  248. //if ($js[count($js)] != "\n") $this->wo("\n");
  249. $this->cscript(true);
  250. } else {
  251. $this->js[] = array('type'=>'script','value'=>$js);
  252. }
  253. }
  254. /***
  255. * Opens a script tag
  256. */
  257. public function oscript($inline='') {
  258. if ($inline == '') $inline = $this->jsInline;
  259. if($inline){
  260. $this->otag('script', array('type'=>'text/javascript'));
  261. $this->tnl("//<![CDATA[");
  262. } else {
  263. $this->startBuffer();
  264. }
  265. }
  266. /***
  267. * Closes a script tag
  268. */
  269. public function cscript($inline='') {
  270. if ($inline == '') $inline = $this->jsInline;
  271. if($inline){
  272. $this->tnl("//]]>");
  273. $this->ctag('script');
  274. } else {
  275. $this->js[] = array('type'=>'script','value'=>$this->endBuffer());
  276. }
  277. }
  278. /***
  279. * opens a style tag
  280. */
  281. public function ostyle() {
  282. $this->otag('style', array('type'=>'text/css'));
  283. $this->tnl("<!--");
  284. }
  285. /***
  286. * Generates style declarations based on an array of {match}->{rules}
  287. * TODO: wtf??
  288. */
  289. public function style($styles) {
  290. $this->ostyle();
  291. foreach ($styles as $style) {
  292. $this->tnl($style);
  293. }
  294. $this->cstyle();
  295. }
  296. /***
  297. * closes a style tag
  298. */
  299. public function cstyle() {
  300. $this->tnl("-->");
  301. $this->ctag('style');
  302. }
  303. /***
  304. * Generates stylesheet link tag(s)
  305. */
  306. public function stylesheet($sheets) {
  307. if (!is_array($sheets)) $sheets = array($sheets);
  308. foreach ($sheets as $sheet) {
  309. //if (substr($sheet, 0, 1) == "/") $sheet = $GLOBALS['site']['webroot'] . $sheet;
  310. $this->tnl('<link rel="stylesheet" type="text/css" href="'.$this->fixLink($sheet).'" />');
  311. }
  312. }
  313. /***
  314. * generates a JavaScript alert
  315. */
  316. public function alert($content) {
  317. $this->script('alert("'.$content.'");');
  318. }
  319. /***
  320. * Geerates an HTML comment
  321. */
  322. public function comment($content) {
  323. $this->tnl("<!-- ".$content." -->");
  324. }
  325. /**
  326. * Creates header tag
  327. * @param level int required header level 1-6
  328. * @param content string required content of header
  329. * @param atts string default="" additional attributes
  330. */
  331. public function h($level, $content, $atts='') {
  332. // tnl('<h#level##atts#>#content#</h#level#>');
  333. $this->tag('h'.$level, $atts, $content, true);
  334. }
  335. /**
  336. * Opens a table
  337. * @param atts string default="" additional attributes
  338. * @param rowAtts string default="" additional attributes
  339. * @param cols string default="" list of column widths which will generate <col width="X" /> tags
  340. */
  341. public function otable($atts='', $rowAtts='', $cols='') {
  342. $this->otabletr($atts, $rowAtts, $cols);
  343. }
  344. public function otabletr($atts='', $rowAtts='', $cols='') {
  345. $this->otag('table', $atts);
  346. if ($cols != "") {
  347. ////TODO WHY WON'T THIS WORK?
  348. //$cols = explode(',' $cols);
  349. foreach ($cols as $col) {
  350. $this->tag('col', array('width'=>$col));
  351. }
  352. }
  353. $this->otag('tbody');
  354. $this->otag('tr', $rowAtts, true);
  355. }
  356. public function corow($atts='') {
  357. $this->ctag('tr', true);
  358. $this->otag('tr', $atts, true);
  359. }
  360. /**
  361. * Closes a table
  362. */
  363. public function ctrtable() {
  364. $this->ctag('tr', true);
  365. $this->ctag('tbody');
  366. $this->ctag('table');
  367. }
  368. public function ctable() {
  369. $this->ctrtable();
  370. }
  371. /**
  372. * Evaluates contents of a table cell
  373. */
  374. public function evaltd($eval, $atts='') {
  375. $this->otag('td', $atts);
  376. eval($eval);
  377. $this->ctag('td');
  378. }
  379. public function simpleTable($options=array()) {
  380. $defaults = array(
  381. 'headers'=>array(),
  382. 'data'=>array(),
  383. 'atts'=>'',
  384. 'caption'=>''
  385. );
  386. $options = $this->extend($defaults, $options);
  387. if (!is_array($options['headers'])) $options['headers'] = explode(',', $options['headers']);
  388. $this->otag('table', $options['atts']);
  389. ////caption
  390. if ($options['caption'] != '') {
  391. $this->tag('caption', '', $options['caption'], true, false);
  392. }
  393. ////headers
  394. if (count($options['headers']) > 0) {
  395. $this->otag('thead');
  396. $this->otag('tr', '', true);
  397. foreach ($options['headers'] as $header) {
  398. $this->tag('th', '', $header, true, false);
  399. }
  400. $this->ctag('tr', true);
  401. $this->ctag('thead');
  402. }
  403. ////data
  404. $this->otag('tbody');
  405. foreach ($options['data'] as $row) {
  406. $this->otag('tr', '', true);
  407. foreach ($row as $cell) {
  408. $this->tag('td', '', $cell, true, false);
  409. }
  410. $this->ctag('tr', true);
  411. }
  412. $this->ctag('tbody');
  413. $this->ctag('table');
  414. }
  415. /********************************************
  416. * List Functions
  417. **********************************************/
  418. /**
  419. * Creates a list of $listType (ul or ol) with list items defined by $listItemArray
  420. */
  421. public function liArray($listType, $listItemArray, $atts="",$liAtts=array()) {
  422. if (!$listType === "ul" && !$listType == "ol") $listType = "ul";
  423. $this->otag($listType, $atts);
  424. for ($i = 0; $i < count($listItemArray); $i++) {
  425. $liAttr = (array_key_exists($i, $liAtts)) ? $liAtts[$i] : '';
  426. if (is_array($listItemArray[$i])) {
  427. if (array_key_exists('children', $listItemArray[$i])) {
  428. $this->otag('li');
  429. $this->tnl($listItemArray[$i]['content']);
  430. $this->liArray($listType, $listItemArray[$i]['children']);
  431. $this->ctag('li');
  432. } else {
  433. $this->tag("li", $liAttr, $listItemArray[$i]['content'], true);
  434. }
  435. } else {
  436. $this->tag("li", $liAttr, $listItemArray[$i], true);
  437. }
  438. }
  439. $this->ctag($listType);
  440. }
  441. ////Takes an array of link structs and generates an unordered list
  442. ////Links take form of href,display, and optional atts
  443. public function linkList($links, $ulAtts="") {
  444. //$liAtts = array();
  445. $this->otag("ul", $ulAtts, true);
  446. //print_r($links);
  447. for ($i = 0; $i < count($links); $i++) {
  448. $atts = "";
  449. //print_r($links[$i]);
  450. if (array_key_exists("atts", $links[$i])) $atts = $links[$i]['atts'];
  451. $this->startBuffer();
  452. $this->a($links[$i]['href'], $links[$i]['display'], $atts);
  453. $link = $this->endBuffer();
  454. $liAtts = (array_key_exists("liAtts", $links[$i])) ? $links[$i]['liAtts'] : '';
  455. if (array_key_exists("children", $links[$i])) {
  456. $this->otag("li", $liAtts, false);
  457. $this->tnl(trim($link));
  458. $this->linkList($links[$i]['children']);
  459. $this->ctag("li", false);
  460. } else {
  461. $this->tag("li", $liAtts, trim($link), true);
  462. }
  463. //$links[$i] = trim($this->endBuffer());
  464. }
  465. //print_r($links);
  466. //$this->liArray("ul", $links, $ulAtts, $liAtts);
  467. $this->ctag("ul", true);
  468. }
  469. /*************************
  470. * Deprecated
  471. ************************/
  472. function listArray($type, $items, $listAtts="", $itemsAtts=array()) {
  473. //$itemsAtts = $this->fixAtts($atts);
  474. $this->otag($type, $listAtts);
  475. for ($i = 0; $i < count($items); $i++) {
  476. $atts = (array_key_exists($i, $itemsAtts)) ?
  477. $this->fixAtts($itemsAtts[$i]) :
  478. "";
  479. $this->tag("li", $atts, $items[$i]);
  480. }
  481. $this->ctag($type);
  482. }
  483. /*********************************************
  484. * Form functions *
  485. *********************************************/
  486. public function editor($name, $content='', $options=array()) {
  487. if (count($options) > 0) {
  488. $this->script("var conf = utils.editorManager.conf(".json_encode($options)."); ".
  489. "alert(utils.printObj(conf)); tinyMCE.init(utils.editorManager.conf(".json_encode($options)."));");
  490. }
  491. //$this->script('alert(utils.printObj(utils.editorManager.conf()));');
  492. $this->textarea($name, $content, 'class="editor"');
  493. }
  494. function formTable($config) {
  495. $defaults = array(
  496. 'atts'=>'',
  497. 'type'=>'checkbox',
  498. 'upper_left_label'=>'&nbsp;',
  499. 'headers'=>array(),
  500. 'subheaders'=>array(),
  501. 'rows'=>array(),
  502. 'sideLabelAtts'=>'class="side-header"',
  503. 'mode'=>'form',
  504. 'useLabelAsValue'=>false,
  505. 'debug'=>false
  506. );
  507. //print_r($config['rows']);
  508. $config = $this->extend($defaults, $config);
  509. //// Set Up
  510. $arrays = explode(',', 'headers,subheaders,rows');
  511. foreach ($arrays as $array) {
  512. foreach ($config[$array] as $i => $value) {
  513. if (!is_array($value)) {
  514. $val = explode('|', $value);
  515. $config[$array][$i] = array('id'=>$val[0]);
  516. $config[$array][$i]['label'] = (count($val) >= 2) ? $val[1] : $val[0];
  517. if (count($val) >= 3) $config[$array][$i]['type'] = $val[2];
  518. }
  519. }
  520. }
  521. $colspan = '';
  522. if (count($config['subheaders']) > 0) {
  523. $colspan = ' colspan="'.count($config['subheaders'])/count($config['headers']).'"';
  524. }
  525. //// Start rendering
  526. $this->otable($config['atts']);
  527. $this->th($config['upper_left_label']);
  528. foreach ($config['headers'] as $header) {
  529. $this->th($header['label'], $colspan);
  530. }
  531. if ($config['type'] == 'radio' && $config['mode'] == 'form') {
  532. $this->th('Clear');
  533. }
  534. if (count($config['subheaders']) > 0) {
  535. $this->corow();
  536. $this->th('&nbsp;');
  537. foreach ($config['subheaders'] as $subheader) {
  538. $this->th($subheader['label']);
  539. }
  540. if ($config['type'] == 'radio' && $config['mode'] == 'form') {
  541. $this->th('&nbsp;');
  542. }
  543. }
  544. $allvalues = array();
  545. foreach ($config['rows'] as $row) {
  546. $atts = ' ';
  547. $name = '';
  548. $type = $config['type'];
  549. $this->corow();
  550. $headers = count($config['subheaders']) ? $config['subheaders'] : $config['headers'];
  551. if (array_key_exists('atts', $row)) {
  552. $atts = $row['atts'];
  553. }
  554. ////set up colspans
  555. $labelAtts = (array_key_exists('labelAtts', $row)) ?
  556. $labelAtts = $row['labelAtts'] :
  557. $config['sideLabelAtts'];
  558. if (array_key_exists('colspan', $row) && is_array($row['colspan'])) {
  559. list($start, $end) = explode('-', $row['colspan']['span']);
  560. $spans = array();
  561. $spanning = false;
  562. if ($start == '[label]') {
  563. $labelAtts .= ' colspan="'. (count($headers) + 1).'" class="colspan"';
  564. $spans[] = '[label]';
  565. }
  566. foreach ($headers as $header) {
  567. if ($header['id'] == $start || $start == '[label]') $spanning = true;
  568. if ($spanning) $spans[] = $header['id'];
  569. if ($header['id'] == $end) break;
  570. }
  571. }
  572. $this->th($row['label'], $labelAtts);
  573. $allvalues[$row['id']] = array();
  574. ///////Loop through headers
  575. foreach ($headers as $index => $header) {
  576. $thisAtts = $atts;
  577. $type = (array_key_exists('type', $header)) ? $header['type'] : $config['type'];
  578. $type = (array_key_exists('type', $row)) ? $row['type'] : $type;
  579. if (array_key_exists('format', $header) && $header['format'] != '') {
  580. $thisAtts = ($header['format'] == 'none') ? '' : 'class="'.$header['format'].'"';
  581. }
  582. $name = $header['id'];
  583. if (array_key_exists('colspan', $row) && in_array($name, $spans)) {
  584. if ($name == $spans[0]) {
  585. $content = (array_key_exists('content', $row['colspan'])) ?
  586. $row['colspan']['content'] :
  587. '&nbsp;';
  588. $this->td($content, 'colspan="'.count($spans).'" class="colspan"');
  589. }
  590. } else {
  591. $this->otd();
  592. //$this->tnl($type);
  593. if ($config['debug']) $this->tnl($row['id'].'_'.$name);
  594. if ($type == 'text') {
  595. $value = '';
  596. $functionAtts = '';
  597. if (array_key_exists('values', $row)) {
  598. ////function for entire row
  599. if (array_key_exists('func', $row['values'])) {
  600. ////Make shortcuts explicit
  601. $func = $row['values'];
  602. foreach ($func['cells'] as $i => $cell) {
  603. if (!strpos($cell, '_')) {
  604. $func['cells'][$i] .= '_'.$name;
  605. }
  606. }
  607. $value = $this->formTableFunction($func, $allvalues);
  608. $functionAtts = ' class="function-target" data-function="'.$func['func'].'" data-values="'.implode(',', $func['cells']).'"';
  609. } else if (count($row['values']) > $index) {
  610. $cell = $row['values'][$index];
  611. ////function for cell
  612. if (is_array($cell) && array_key_exists('func', $cell)) {
  613. foreach ($cell['cells'] as $i => $c) {
  614. if (!strpos($c, '_')) {
  615. $cell['cells'][$i] .= '_'.$name;
  616. }
  617. }
  618. $value = $this->formTableFunction($cell, $allvalues);
  619. $functionAtts = ' class="function-target" data-function="'.$cell['func'].'" data-values="'.implode(',', $cell['cells']).'"';
  620. ////Value is in cell
  621. } else {
  622. $value = $cell;
  623. }
  624. }
  625. }
  626. $thisAtts = $this->combineClassAtts($thisAtts.$functionAtts);
  627. // $this->tbr($config['type']);
  628. if ($config['mode'] == 'view') {
  629. $this->span($value, $thisAtts.' id="'.$row['id'].'_'.$name.'"');
  630. } else {
  631. $this->input($type, $row['id'].'_'.$name, $value, $thisAtts);
  632. }
  633. ////radio/checkbox
  634. } else {
  635. $thisAtts = $atts.' id="'.$row['id'].'_'.$name.'"';
  636. $viewValue = '';
  637. if (array_key_exists('selected', $row) && in_array($name, $row['selected'])) {
  638. $thisAtts .= ' checked="checked"';
  639. $viewValue = 'X';
  640. }
  641. $value = ($config['useLabelAsValue']) ? $header['label'] : $row['id'];
  642. if ($config['mode'] == 'view') {
  643. $this->span($viewValue, $thisAtts);
  644. } else {
  645. $this->input($type, $row['id'].'[]', $value, $thisAtts);
  646. }
  647. }
  648. $value = preg_replace('/[$%]/', '', $value);
  649. $allvalues[$row['id']][$name] = $value;
  650. $this->ctd();
  651. }
  652. }
  653. if ($config['type'] == 'radio' && $config['mode'] == 'form') {
  654. $this->otd();
  655. $this->input('button', 'clear-'.$row['id'], 'Clear', 'class="clear-radio"');
  656. $this->ctd();
  657. }
  658. }
  659. $this->ctable();
  660. // $this->pa($allvalues);
  661. }
  662. private function formTableFunction($def, $allvalues) {
  663. $func = $def['func'];
  664. $cells = $def['cells'];
  665. // $this->pa($cells);
  666. $value = '';
  667. foreach ($cells as $i => $cellid) {
  668. // $this->tbr('value: '.$cellid);
  669. list($qid, $hid) = explode('_', $cellid);
  670. $cell = '';
  671. if (array_key_exists($qid, $allvalues) && array_key_exists($hid, $allvalues[$qid])) {
  672. $cell = $this->clearNumFormatting($allvalues[$qid][$hid]);
  673. }
  674. //$this->tbr($cellid.' |'.$cell.'| '.$value);
  675. if ($value == '' && is_numeric($cell)) {
  676. $value = $cell;
  677. } else if (is_numeric($cell)) {
  678. if ($func == 'sum') {
  679. $value += $cell;
  680. } else if ($func == 'product') {
  681. $value *= $cell;
  682. } else if ($func == 'difference') {
  683. $value -= $cell;
  684. } else if ($func == 'quotient' && $cell != 0) {
  685. $value /= $cell;
  686. }
  687. }
  688. //$this->tbr('<strong>'.$value.'</strong>');
  689. }
  690. return is_numeric($value) ? number_format($value) : '';
  691. }
  692. function clearNumFormatting($num) {
  693. return str_replace(',', '', trim($num));
  694. }
  695. /**
  696. * Returns defined value of field in struct or empty string
  697. */
  698. public function getValue($field, $defaultVal='', $struct=array()) {
  699. ////If third argument provided, use that struct
  700. if (count($struct) > 0 && array_key_exists($field, $struct)) {
  701. return $struct[$field];
  702. ///check both URL and Form scopes
  703. } else {
  704. if (array_key_exists($field, $_POST)) return $_POST[$field];
  705. if (array_key_exists($field, $_GET)) return $_GET[$field];
  706. }
  707. return $defaultVal;
  708. }
  709. /**
  710. * Opens a form
  711. * @param method string default="post" additional attributes
  712. * @param atts string default="" additional attributes
  713. */
  714. public function oform($action, $method='post', $atts='') {
  715. $atts = 'action="'.$action.'" method="'.$method.'"'.$this->fixAtts($atts);
  716. $this->otag('form', $atts);
  717. }
  718. /**
  719. * Alias for getValue
  720. */
  721. public function getVal($field, $defaultVal='', $struct=array()) {
  722. return $this->getValue($field, $defaultVal, $struct);
  723. }
  724. /**
  725. * Opens a fieldset and legend tag
  726. */
  727. public function ofieldset($legend='', $atts='', $legendAtts='') {
  728. $this->otag('fieldset', $atts, true);
  729. if ($legend != '') {
  730. $this->tag('legend', $legendAtts, $legend, true, false);
  731. }
  732. }
  733. /**
  734. * Creates a label
  735. */
  736. public function label($id, $content, $atts='') {
  737. $atts = 'for="'.$id.'"' . $this->fixAtts($atts);
  738. $this->tag('label', $atts, $content, true, false);
  739. }
  740. /**
  741. * Creates an input
  742. */
  743. public function input($type, $name, $value='', $atts='') {
  744. $atts = $this->fixAtts($atts);
  745. $addAtts = ' type="'.$type.'" name="'.$name.'"';
  746. if ($value != '') $addAtts .= ' value="'.$value.'"';
  747. $atts = $addAtts . $atts;
  748. $atts = $this->CheckId($name, $atts);
  749. $this->tag('input', $atts);
  750. }
  751. /**
  752. * Creates a text area
  753. */
  754. public function textarea($name, $value='', $atts='', $rows=5, $cols=60) {
  755. $atts = ' name="'.$name.'" rows="'.$rows.'" cols="'.$cols.'"' . $this->fixAtts($atts);
  756. $atts = $this->checkId($name, $atts);
  757. $this->tag('textarea', $atts, $value, true, false);
  758. }
  759. public function checkId($name, $atts) {
  760. if (strpos($atts, "id=") === false) $atts = ' id="'.$name.'"' . $this->fixAtts($atts);
  761. return $atts;
  762. }
  763. /**
  764. * Creates a select dropdown
  765. */
  766. public function select($name, $options, $selected='', $atts='',
  767. $empty=false, $optionClassList='') {
  768. $atts = ' name="'.$name.'"' . $this->fixAtts($atts);
  769. $atts = $this->checkId($name, $atts);
  770. $this->otag('select', $atts, true);
  771. if ($empty) $this->tag('option', 'value=""', '', true, false);
  772. $this->renderOptions($options, $selected, $atts);
  773. $this->ctag('select', true);
  774. }
  775. public function datalist($name, $options, $selected='', $atts='',
  776. $empty=false, $optionClassList='') {
  777. $this->tag('input', 'type="text" list=".'.$name.'" id="'.$name.'_text"', '', true);
  778. //$atts = $this->checkId($name, $atts);
  779. $this->otag('datalist', $atts, true);
  780. if ($empty) $this->tag('option', 'value=""', '', true, false);
  781. $this->renderOptions($options, $selected, $atts);
  782. $this->ctag('datalist', true);
  783. }
  784. private function renderOptions($options, $selected='', $atts='', $optionClassList='') {
  785. $value="";
  786. $display="";
  787. $optionClass="";
  788. $selectIt="";
  789. $selected = explode(',', $selected);
  790. foreach ($options as $option) {
  791. if (strpos($option, "|") !== false) {
  792. if ($option == "|") {
  793. $value = "";
  794. $display = "";
  795. } else {
  796. if (substr($option, 0, 1) == "|") {
  797. $value = "";
  798. $display = substr($option, 1);
  799. } else if (substr($option, -1) == "|") {
  800. $value = substr($option, 0, -1);
  801. $display = "";
  802. } else {
  803. list($value, $display) = explode('|', $option);
  804. }
  805. }
  806. } else {
  807. $value = $option;
  808. $display = $value;
  809. }
  810. if ($optionClassList != "") {
  811. $optionClassList = explose(',', $optionClassList);
  812. if ($i < count($optionClassList)) {
  813. $optionClass=' class="'.$optionClassList[$i].'"';
  814. } else {
  815. $optionClass="";
  816. }
  817. }
  818. $selectIt = (in_array($value, $selected)) ? ' selected="selected"' : '';
  819. //$selectIt = (ListFindNoCase(selected, value)) ? ' selected="selected"': "";
  820. $optAtts = 'value="'.$value.'"'.$selectIt.$optionClass;
  821. $this->tag('option', $optAtts, $display, true, false);
  822. }
  823. }
  824. /**
  825. * Created 11/29/2006 by Andy Hill
  826. * Assuming file in question sets SES.hasCalendar to true in Directory Settings, creates a popUp Calendar
  827. * the value of which will be submitted as "fieldname"
  828. */
  829. public function calendar($name, $value='', $atts='') {
  830. $atts = $this->addClass($this->fixAtts($atts), "datepicker");
  831. if (strpos("size=", $atts) === false) $atts .= ' size="15"';
  832. $this->input('text', $name, $value, $atts);
  833. }
  834. public function choicegrid($Arguments, $openContainer = TRUE) {
  835. $i = 0;
  836. $tempArr = array();
  837. $Args = array();
  838. $defaults = array('type' => "checkbox",
  839. 'ids' => array(),
  840. 'selected' => array(),
  841. 'labelfirst' => false,
  842. 'attsAll' => "",
  843. 'atts' => array(),
  844. 'labelAttsAll' => "",
  845. 'labelAtts' => array(),
  846. 'container' => "none",
  847. 'containerAtts' => true,
  848. 'closeContainer' => true,
  849. 'numCols' => 0,
  850. 'selectall' => false,
  851. 'selectallInitState' => "select",
  852. 'textfields'=>array(),
  853. 'labelClass'=>''
  854. );
  855. $name = $this->reqArgs("name", $Arguments); ////REQUIRED string - form name of checkbox set
  856. $vals = $this->reqArgs("vals", $Arguments); ////REQUIRED list - values for checkboxes/radoibuttons
  857. //print_r($vals);
  858. $Args = $this->extend($defaults, $Arguments);
  859. //print_r($Args);
  860. foreach ($Args as $arg => $value) {
  861. $$arg = $value;
  862. }
  863. $hasAtts = count($atts) > 0;
  864. //print_r($Args);
  865. //echo "?".$labelClass."?</br>";
  866. //print_r($Arguments['selected']);
  867. //if (ListLen(labels) != ListLen(vals)) Request.utils.throw("Error in choicegrid. vals and labels not same length");
  868. if (count($ids) != 0 && count($vals) != count($ids)) {
  869. echo "<script type='text/javascript'>alert('Error in choicegrid. vals and atts not same length')</script>";
  870. }
  871. //echo '<br>'.$hasAtts." ".count($vals)." ".count($atts);
  872. /*if ($hasAtts && count($vals) != count($atts)) {
  873. echo "<script type='text/javascript'>alert('Error in choicegrid. vals and atts not same length')</script>";
  874. }*/
  875. if (strtolower($selectallInitState) == "deselect") $selectClass .= " deselect";
  876. if ($selectall) $containerAtts = $this->combineClassAtts($containerAtts.' class="'.$selectClass.'"');
  877. if ($container == "table") $this->otable($containerAtts);
  878. else if ($container == "div" || ($container == "none" && $selectall)) $this->odiv($containerAtts);
  879. for ($i = 0; $i < count($vals); $i++) {
  880. //echo "<br>";
  881. // $this->br();
  882. if ($container == "table") $this->otd();
  883. $value = $vals[$i];
  884. $labl = $value;
  885. $tempArr = explode("|", $value);
  886. if (count($tempArr) == 2) {
  887. $labl = $tempArr[1];
  888. $value = $tempArr[0];
  889. }
  890. $id = $name."_".$value;
  891. if (count($ids) > 0) {
  892. $id = $ids[$i];
  893. }
  894. $lblAtt = $labelClass;// 'class="'.$labelClass.'"';
  895. //echo "1?".$lblAtt."?</br>";
  896. if (count($labelAtts) > $i) $lblAtt .= $this->fixAtts($labelAtts[$i]);
  897. $lblAtt .= $this->fixAtts($labelAttsAll);
  898. if ($labelfirst) $lblAtt .= $this->fixAtts($labelClass/*'class="'.$labelClass.'"'*/);
  899. //echo "2?".$lblAtt."?"."</br>";
  900. $lblAtt = $this->combineClassAtts($lblAtt);
  901. //echo "3?".$lblAtt."?</br>";
  902. if ($labelfirst) $this->label($id, $labl, $lblAtt);
  903. //echo "<br>Value: ".$value." Selected: ";
  904. //print_r($selected);
  905. // echo "<br>".in_array("dummy", $selected);
  906. if (in_array($value, $selected) != FALSE) {
  907. $attributes = ' checked="checked"';
  908. } else {
  909. // $this->tbr("not found: ".$value);
  910. $attributes = "";
  911. }
  912. if ($hasAtts) $attributes .= $this->fixAtts($atts[$i]);
  913. if (strlen($attsAll)) $attributes .= $this->fixAtts($attsAll);
  914. $attributes = $this->combineClassAtts($attributes);
  915. //if (id != value)
  916. $attributes .= $this->fixAtts('id="'.$id.'"');
  917. // $this->tbr($attributes);
  918. $this->input($type, $name, $value, $attributes);
  919. if (!$labelfirst) $this->label($id, $labl, $lblAtt);
  920. //$this->tbr($labl);
  921. //$this->pa($textfields);
  922. if (array_key_exists($labl, $textfields) || array_key_exists($labl.'|area', $textfields)) {
  923. if (array_key_exists($labl, $textfields)) {
  924. $this->intext($id.'_text', $textfields[$labl]);
  925. } else {
  926. $this->textarea($id.'_text', $textfields[$labl.'|area'], 'class="cdsAutoGrow" style="vertical-align: top;"', 1, 60);
  927. }
  928. }
  929. if ($container == "table") $this->ctd();
  930. if ($numCols > 0 && (($i+1) % $numCols) == 0 && $i < count($vals)) {
  931. // $this->tbr($numCols.'|'.$i);
  932. if ($container == "table") $this->cotr();
  933. else $this->br();
  934. }
  935. }
  936. if ($container == "table" && $closeContainer) $this->ctable();
  937. else if (($container == "div" || ($container == "none" && $selectall)) && $closeContainer) $this->cdiv();
  938. }
  939. /**
  940. * Created by Andy Hill: 11/2005
  941. * Converts email to ASCII representations to discourage harvesting
  942. * @param addr string default="SES-Tech@indiana.edu" Email address to obfuscate
  943. * @param display string default=addr Text to be displayed on screen (also obfuscated if the same as email)
  944. **/
  945. public function email($addr, $display='') {
  946. $email = "";
  947. for ($i = 0; $i < strlen($addr); $i++) {
  948. $email = $email . "&#" . ord(substr($addr, $i, 1)) . ";";
  949. }
  950. if ($display == '') $display = $email;
  951. $mailto2 = "";
  952. $mailto = "mailto:";
  953. for ($i = 0; $i < strlen($mailto); $i++) {
  954. $mailto2 = $mailto2 . "&#" . ord(substr($mailto, $i, 1)) . ";";
  955. }
  956. $this->a($mailto2.$email, $display);
  957. }
  958. public function reqArgs($arg, $Arguments) {
  959. if (!array_key_exists($arg, $Arguments)) {
  960. $this->alert("required argument: '".$arg."' missing");
  961. //echo "<script type='text/javascript'>alert('Required argument '".$arg." missing.)</script>";
  962. }
  963. return $Arguments[$arg];
  964. }
  965. ////Overrides struct defaults with options
  966. public function extend($defaults, $Args) {
  967. $a = array();
  968. foreach ($defaults as $key => $value) {
  969. $a[$key] = array_key_exists($key, $Args) ? $Args[$key] : $value;
  970. }
  971. return $a;
  972. }
  973. public function addClass($atts, $class) {
  974. if (strpos($atts, "class=") === false) {
  975. //$this->tbr("in func". $atts . ' class="'.$class.'"');
  976. if (strlen($atts) > 0) return $atts . ' class="'.$class.'"';
  977. else return $atts . 'class="'.$class.'"';
  978. } else {
  979. $regex = '\s?class="([^"]+)"';
  980. $classes = preg_replace("/.*".$regex.".*/", "\\1", $atts);
  981. $pre = preg_replace("/(.*)".$regex.".*/", "\\1", $atts);
  982. $post = preg_replace("/.*".$regex."(.*)/", "\\2", $atts);
  983. //$this->tbr("here1".$pre);
  984. //$this->tbr($classes);
  985. //$this->tbr($post);
  986. return $pre . ' class="'.$classes . " ". $class . '"' . $post;
  987. }
  988. }
  989. public function combineClassAtts($atts) {
  990. $i = 0;
  991. $matches = array();
  992. $re = '/\s?class\s*=\s*"[^"]+"/';
  993. preg_match_all($re, $atts, $matches);
  994. if (count($matches) > 0) {
  995. $classes = array();
  996. $countMatches = count($matches[0]);
  997. for ($i = 0; $i < $countMatches; $i++) {
  998. $classes[$i] = preg_replace('/\s?class\s*=\s*"([^"]+)"/', "$1", $matches[0][$i]);
  999. }
  1000. $atts = preg_replace($re, "", $atts);
  1001. $classes = array_unique($classes);
  1002. if (count($classes)) {
  1003. $atts = $atts . ' class="'.implode(' ', $classes).'"';
  1004. }
  1005. }
  1006. return $atts;
  1007. }
  1008. public function dictionaryGrid($defns, $atts="") {
  1009. $this->odiv('class="dictionary-grid"'.$atts);
  1010. for ($i = 0; $i < count($defns); $i++) {
  1011. $defn = $defns[$i];
  1012. $this->odiv('class="row"');
  1013. $this->div($defn['left'].":", 'class="row-left"');
  1014. $this->div($defn['right'], 'class="row-right"');
  1015. $this->cdiv(); ////close row
  1016. }
  1017. $this->cdiv();
  1018. }
  1019. /*****
  1020. * HTML Templates
  1021. ******/
  1022. //// interpolate a string from a template
  1023. public function tint($str) {
  1024. $this->tnl('<%= '.$str.' %>');
  1025. }
  1026. //// escape a string from a template
  1027. public function tesc($str) {
  1028. $this->tnl('<%- '.$str.' %>');
  1029. }
  1030. //// evaluate a string from a template
  1031. public function tevl($str) {
  1032. $this->tnl('<% '.$str.' %>');
  1033. }
  1034. public function tblock($head, $blockfn) {
  1035. $this->tevl($head.' {');
  1036. $blockfn();
  1037. $this->tevl('}');
  1038. }
  1039. }
  1040. ?>