Textpattern | PHP Cross Reference | Content Management Systems |
Description: Collection of HTML widgets.
1 <?php 2 3 /* 4 * Textpattern Content Management System 5 * http://textpattern.com 6 * 7 * Copyright (C) 2016 The Textpattern Development Team 8 * 9 * This file is part of Textpattern. 10 * 11 * Textpattern is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation, version 2. 14 * 15 * Textpattern is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with Textpattern. If not, see <http://www.gnu.org/licenses/>. 22 */ 23 24 /** 25 * Collection of HTML widgets. 26 * 27 * @package HTML 28 */ 29 30 /** 31 * A tab character. 32 * 33 * @var string 34 */ 35 36 define("t", "\t"); 37 38 /** 39 * A line feed. 40 * 41 * @var string 42 */ 43 44 define("n", "\n"); 45 46 /** 47 * A self-closing HTML line-break tag. 48 * 49 * @var string 50 */ 51 52 define("br", "<br />"); 53 54 /** 55 * A non-breaking space as a HTML entity. 56 * 57 * @var string 58 */ 59 60 define("sp", " "); 61 62 /** 63 * An ampersand as a HTML entity. 64 * 65 * @var string 66 */ 67 68 define("a", "&"); 69 70 /** 71 * Renders the admin-side footer. 72 * 73 * The footer's default markup is provided by a theme. It can be further 74 * customised via the "admin_side > footer" pluggable UI callback event. 75 * 76 * In addition to the pluggable UI, this function also calls callback events 77 * "admin_side > main_content_end" and "admin_side > body_end". 78 */ 79 80 function end_page() 81 { 82 global $event, $app_mode, $theme, $textarray_script; 83 84 if ($app_mode != 'async' && $event != 'tag') { 85 callback_event('admin_side', 'main_content_end'); 86 echo n.'</main><!-- /txp-body -->'.n.'<footer class="txp-footer">'; 87 echo pluggable_ui('admin_side', 'footer', $theme->footer()); 88 callback_event('admin_side', 'body_end'); 89 90 gTxtScript(array( 91 'password_strength_0', 92 'password_strength_1', 93 'password_strength_2', 94 'password_strength_3', 95 'password_strength_4', 96 ), 97 array(), 98 array(array('admin', 'admin'), array('new_pass_form', 'change_pass')) 99 ); 100 101 echo script_js('vendors/dropbox/zxcvbn/zxcvbn.js', TEXTPATTERN_SCRIPT_URL, array(array('admin', 'admin'), array('new_pass_form', 'change_pass'))). 102 script_js('vendors/PrismJS/prism/prism.js', TEXTPATTERN_SCRIPT_URL). 103 script_js('textpattern.textarray = '.json_encode($textarray_script)). 104 n.'</footer><!-- /txp-footer -->'.n.'</body>'.n.'</html>'; 105 } 106 } 107 108 /** 109 * Renders the user interface for one head cell of columnar data. 110 * 111 * @param string $value Element text 112 * @param string $sort Sort criterion 113 * @param string $event Event name 114 * @param bool $is_link Include link to admin action in user interface according to the other params 115 * @param string $dir Sort direction, either "asc" or "desc" 116 * @param string $crit Search criterion 117 * @param string $method Search method 118 * @param string $class HTML "class" attribute applied to the resulting element 119 * @param string $step Step name 120 * @return string HTML 121 */ 122 123 function column_head($value, $sort = '', $event = '', $is_link = '', $dir = '', $crit = '', $method = '', $class = '', $step = 'list') 124 { 125 return column_multi_head(array(array( 126 'value' => $value, 127 'sort' => $sort, 128 'event' => $event, 129 'step' => $step, 130 'is_link' => $is_link, 131 'dir' => $dir, 132 'crit' => $crit, 133 'method' => $method, 134 )), $class); 135 } 136 137 /** 138 * Renders the user interface for multiple head cells of columnar data. 139 * 140 * @param array $head_items An array of hashed elements. Valid keys: 'value', 'sort', 'event', 'is_link', 'dir', 'crit', 'method' 141 * @param string $class HTML "class" attribute applied to the resulting element 142 * @return string HTML 143 */ 144 145 function column_multi_head($head_items, $class = '') 146 { 147 $o = ''; 148 $first_item = true; 149 150 foreach ($head_items as $item) { 151 if (empty($item)) { 152 continue; 153 } 154 155 extract(lAtts(array( 156 'value' => '', 157 'sort' => '', 158 'event' => '', 159 'step' => 'list', 160 'is_link' => '', 161 'dir' => '', 162 'crit' => '', 163 'method' => '', 164 ), $item)); 165 166 $o .= ($first_item) ? '' : ', '; 167 $first_item = false; 168 169 if ($is_link) { 170 $o .= href(gTxt($value), array( 171 'event' => $event, 172 'step' => $step, 173 'sort' => $sort, 174 'dir' => $dir, 175 'crit' => $crit, 176 'search_method' => $method, 177 ), array()); 178 } else { 179 $o .= gTxt($value); 180 } 181 } 182 183 return hCell($o, '', array( 184 'class' => $class, 185 'scope' => 'col', 186 )); 187 } 188 189 /** 190 * Renders a <th> element. 191 * 192 * @param string $text Cell text 193 * @param string $caption Is not used 194 * @param string|array $atts HTML attributes 195 * @return string HTML 196 */ 197 198 function hCell($text = '', $caption = '', $atts = '') 199 { 200 $text = ('' === $text) ? sp : $text; 201 202 return n.tag($text, 'th', $atts); 203 } 204 205 /** 206 * Renders a link invoking an admin-side action. 207 * 208 * @param string $event Event 209 * @param string $step Step 210 * @param string $linktext Link text 211 * @param string $class HTML class attribute for link 212 * @return string HTML 213 */ 214 215 function sLink($event, $step, $linktext, $class = '') 216 { 217 if ($linktext === '') { 218 $linktext = null; 219 } 220 221 return href($linktext, array( 222 'event' => $event, 223 'step' => $step, 224 ), array('class' => $class)); 225 } 226 227 /** 228 * Renders a link with two additional URL parameters. 229 * 230 * Renders a link invoking an admin-side action while taking up to two 231 * additional URL parameters. 232 * 233 * @param string $event Event 234 * @param string $step Step 235 * @param string $thing URL parameter key #1 236 * @param string $value URL parameter value #1 237 * @param string $linktext Link text 238 * @param string $thing2 URL parameter key #2 239 * @param string $val2 URL parameter value #2 240 * @param string $title Anchor title 241 * @param string $class HTML class attribute 242 * @return string HTML 243 */ 244 245 function eLink($event, $step, $thing, $value, $linktext, $thing2 = '', $val2 = '', $title = '', $class = '') 246 { 247 if ($title) { 248 $title = gTxt($title); 249 } 250 251 if ($linktext === '') { 252 $linktext = null; 253 } else { 254 $linktext = escape_title($linktext); 255 } 256 257 return href($linktext, array( 258 'event' => $event, 259 'step' => $step, 260 $thing => $value, 261 $thing2 => $val2, 262 '_txp_token' => form_token(), 263 ), array( 264 'class' => $class, 265 'title' => $title, 266 )); 267 } 268 269 /** 270 * Renders a link with one additional URL parameter. 271 * 272 * Renders an link invoking an admin-side action while taking up to one 273 * additional URL parameter. 274 * 275 * @param string $event Event 276 * @param string $step Step 277 * @param string $thing URL parameter key 278 * @param string $value URL parameter value 279 * @param string $class HTML class attribute 280 * @return string HTML 281 */ 282 283 function wLink($event, $step = '', $thing = '', $value = '', $class = '') 284 { 285 return href(sp.'!'.sp, array( 286 'event' => $event, 287 'step' => $step, 288 $thing => $value, 289 '_txp_token' => form_token(), 290 ), array('class' => $class)); 291 } 292 293 /** 294 * Renders a delete link. 295 * 296 * Renders a link invoking an admin-side "delete" action while taking up to two 297 * additional URL parameters. 298 * 299 * @param string $event Event 300 * @param string $step Step 301 * @param string $thing URL parameter key #1 302 * @param string $value URL parameter value #1 303 * @param string $verify Show an "Are you sure?" dialogue with this text 304 * @param string $thing2 URL parameter key #2 305 * @param string $thing2val URL parameter value #2 306 * @param bool $get If TRUE, uses GET request 307 * @param array $remember Convey URL parameters for page state. Member sequence is $page, $sort, $dir, $crit, $search_method 308 * @return string HTML 309 */ 310 311 function dLink($event, $step, $thing, $value, $verify = '', $thing2 = '', $thing2val = '', $get = '', $remember = null) 312 { 313 if ($remember) { 314 list($page, $sort, $dir, $crit, $search_method) = $remember; 315 } 316 317 if ($get) { 318 if ($verify) { 319 $verify = gTxt($verify); 320 } else { 321 $verify = gTxt('confirm_delete_popup'); 322 } 323 324 if ($remember) { 325 return href('×', array( 326 'event' => $event, 327 'step' => $step, 328 $thing => $value, 329 $thing2 => $thing2val, 330 '_txp_token' => form_token(), 331 'page' => $page, 332 'sort' => $sort, 333 'dir' => $dir, 334 'crit' => $crit, 335 'search_method' => $search_method, 336 ), array( 337 'class' => 'dlink destroy', 338 'title' => gTxt('delete'), 339 'data-verify' => $verify, 340 )); 341 } 342 343 return href('×', array( 344 'event' => $event, 345 'step' => $step, 346 $thing => $value, 347 $thing2 => $thing2val, 348 '_txp_token' => form_token(), 349 ), array( 350 'class' => 'dlink destroy', 351 'title' => gTxt('delete'), 352 'data-verify' => $verify, 353 )); 354 } 355 356 return join('', array( 357 n.'<form method="post" action="index.php" data-verify="'.gTxt('confirm_delete_popup').'">', 358 tag( 359 span(gTxt('delete'), array('class' => 'ui-icon ui-icon-close')), 360 'button', 361 array( 362 'class' => 'destroy', 363 'type' => 'submit', 364 'title' => gTxt('delete'), 365 'aria-label' => gTxt('delete'), 366 ) 367 ), 368 eInput($event). 369 sInput($step), 370 hInput($thing, $value), 371 ($thing2) ? hInput($thing2, $thing2val) : '', 372 ($remember) ? hInput('page', $page) : '', 373 ($remember) ? hInput('sort', $sort) : '', 374 ($remember) ? hInput('dir', $dir) : '', 375 ($remember) ? hInput('crit', $crit) : '', 376 ($remember) ? hInput('search_method', $search_method) : '', 377 tInput(), 378 n.'</form>', 379 )); 380 } 381 382 /** 383 * Renders an add link. 384 * 385 * This function can be used for invoking an admin-side "add" action while 386 * taking up to two additional URL parameters. 387 * 388 * @param string $event Event 389 * @param string $step Step 390 * @param string $thing URL parameter key #1 391 * @param string $value URL parameter value #1 392 * @param string $thing2 URL parameter key #2 393 * @param string $value2 URL parameter value #2 394 * @return string HTML 395 */ 396 397 function aLink($event, $step, $thing = '', $value = '', $thing2 = '', $value2 = '') 398 { 399 return href('+', array( 400 'event' => $event, 401 'step' => $step, 402 $thing => $value, 403 $thing2 => $value2, 404 '_txp_token' => form_token(), 405 ), array('class' => 'alink')); 406 } 407 408 /** 409 * Renders a link invoking an admin-side "previous/next article" action. 410 * 411 * @param string $name Link text 412 * @param string $event Event 413 * @param string $step Step 414 * @param int $id ID of target Textpattern object (article,...) 415 * @param string $title HTML title attribute 416 * @param string $rel HTML rel attribute 417 * @return string HTML 418 */ 419 420 function prevnext_link($name, $event, $step, $id, $title = '', $rel = '') 421 { 422 return href($name, array( 423 'event' => $event, 424 'step' => $step, 425 'ID' => $id, 426 ), array( 427 'class' => 'navlink', 428 'title' => $title, 429 'rel' => $rel, 430 )); 431 } 432 433 /** 434 * Renders a link invoking an admin-side "previous/next page" action. 435 * 436 * @param string $event Event 437 * @param int $page Target page number 438 * @param string $label Link text 439 * @param string $type Direction, either "prev" or "next" 440 * @param string $sort Sort field 441 * @param string $dir Sort direction, either "asc" or "desc" 442 * @param string $crit Search criterion 443 * @param string $search_method Search method 444 * @param string $step Step 445 * @return string HTML 446 */ 447 448 function PrevNextLink($event, $page, $label, $type, $sort = '', $dir = '', $crit = '', $search_method = '', $step = 'list') 449 { 450 $theClass = ($type === 'next') ? 'ui-icon-arrowthick-1-e' : 'ui-icon-arrowthick-1-w'; 451 return href(span( 452 $label, array('class' => 'ui-icon '.$theClass) 453 ), 454 array( 455 'event' => $event, 456 'step' => $step, 457 'page' => (int) $page, 458 'dir' => $dir, 459 'crit' => $crit, 460 'search_method' => $search_method, 461 ), array( 462 'rel' => $type, 463 'title' => $label, 464 'aria-label' => $label, 465 )); 466 } 467 468 /** 469 * Renders a page navigation form. 470 * 471 * @param string $event Event 472 * @param int $page Current page number 473 * @param int $numPages Total pages 474 * @param string $sort Sort criterion 475 * @param string $dir Sort direction, either "asc" or "desc" 476 * @param string $crit Search criterion 477 * @param string $search_method Search method 478 * @param int $total Total search term hit count [0] 479 * @param int $limit First visible search term hit number [0] 480 * @param string $step Step 481 * @param int $list Number of displayed page links discounting jump links, previous and next 482 * @return string HTML 483 */ 484 485 function nav_form($event, $page, $numPages, $sort = '', $dir = '', $crit = '', $search_method = '', $total = 0, $limit = 0, $step = 'list', $list = 5) 486 { 487 $out = array(); 488 489 if ($crit != '' && $total > 1) { 490 $out[] = announce( 491 gTxt('showing_search_results', array( 492 '{from}' => (($page - 1) * $limit) + 1, 493 '{to}' => min($total, $page * $limit), 494 '{total}' => $total, 495 )), 496 TEXTPATTERN_ANNOUNCE_REGULAR 497 ); 498 } 499 500 if ($numPages > 1) { 501 $nav = array(); 502 $list--; 503 $page = max(min($page, $numPages), 1); 504 $start = max(1, min($numPages - $list, $page - floor($list/2))); 505 $end = min($numPages, $start + $list); 506 507 $parameters = array( 508 'event' => $event, 509 'step' => $step, 510 'dir' => $dir, 511 'crit' => $crit, 512 'search_method' => $search_method, 513 ); 514 515 // Previous page. 516 if ($page > 1) { 517 $nav[] = n.PrevNextLink($event, $page - 1, gTxt('prev'), 'prev', $sort, $dir, $crit, $search_method, $step); 518 } else { 519 $nav[] = n.span( 520 span(gTxt('prev'), array( 521 'class' => 'ui-icon ui-icon-arrowthick-1-w', 522 )), 523 array( 524 'class' => 'disabled', 525 'aria-disabled' => 'true', 526 'aria-label' => gTxt('prev'), 527 ) 528 ); 529 } 530 531 532 $nav[] = form( 533 n.tag(gTxt('page'), 'label', array( 534 'for' => 'current-page', 535 )). 536 n.tag_void('input', array( 537 'class' => 'current-page', 538 'id' => 'current-page', 539 'name' => 'page', 540 'type' => 'text', 541 'size' => INPUT_XSMALL, 542 'inputmode' => 'numeric', 543 'pattern' => '[0-9]+', 544 'value' => $page, 545 )). 546 n.gTxt('of'). 547 n.span($numPages, array('class' => 'total-pages')). 548 eInput($event). 549 hInput('sort', $sort). 550 hInput('dir', $dir). 551 hInput('crit', $crit). 552 hInput('search_method', $search_method), 553 '', 554 '', 555 'get' 556 ); 557 558 // Next page. 559 if ($page < $numPages) { 560 $nav[] = n.PrevNextLink($event, $page + 1, gTxt('next'), 'next', $sort, $dir, $crit, $search_method, $step); 561 } else { 562 $nav[] = n.span( 563 span(gTxt('next'), array( 564 'class' => 'ui-icon ui-icon-arrowthick-1-e', 565 )), 566 array( 567 'class' => 'disabled', 568 'aria-disabled' => 'true', 569 'aria-label' => gTxt('next'), 570 ) 571 ); 572 } 573 574 $out[] = n.tag(join($nav).n, 'nav', array('class' => 'prev-next')); 575 } 576 577 return join('', $out); 578 } 579 580 /** 581 * Wraps a collapsible region and group structure around content. 582 * 583 * @param string $id HTML id attribute for the region wrapper and ARIA label 584 * @param string $content Content to wrap. If empty, only the outer wrapper will be rendered 585 * @param string $anchor_id HTML id attribute for the collapsible wrapper 586 * @param string $label L10n label name 587 * @param string $pane Pane reference for maintaining toggle state in prefs. Prefixed with 'pane_', suffixed with '_visible' 588 * @param string $class CSS class name to apply to wrapper 589 * @param string $help Help text item 590 * @return string HTML 591 * @since 4.6.0 592 */ 593 594 function wrapRegion($id, $content = '', $anchor_id = '', $label = '', $pane = '', $class = '', $help = '') 595 { 596 global $event; 597 $label = $label ? gTxt($label) : null; 598 599 if ($anchor_id && $pane) { 600 $visible = get_pref('pane_'.$pane.'_visible'); 601 $heading_class = 'txp-summary'.($visible ? ' expanded' : ''); 602 $display_state = array( 603 'class' => 'toggle', 604 'id' => $anchor_id, 605 'role' => 'group', 606 'style' => $visible ? 'display: block' : 'display: none', 607 ); 608 609 $label = href($label, '#'.$anchor_id, array( 610 'role' => 'button', 611 'data-txp-token' => md5($pane.$event.form_token().get_pref('blog_uid')), 612 'data-txp-pane' => $pane, 613 )); 614 615 $help = ''; 616 } else { 617 $heading_class = ''; 618 $display_state = array('role' => 'group'); 619 } 620 621 if ($content) { 622 $content = 623 hed($label.popHelp($help), 3, array( 624 'class' => $heading_class, 625 'id' => $id.'-label', 626 )). 627 n.tag($content.n, 'div', $display_state).n; 628 } 629 630 return n.tag($content, 'section', array( 631 'class' => trim('txp-details '.$class), 632 'id' => $id, 633 'aria-labelledby' => $content ? $id.'-label' : '', 634 )); 635 } 636 637 /** 638 * Wraps a region and group structure around content. 639 * 640 * @param string $name HTML id attribute for the group wrapper and ARIA label 641 * @param string $content Content to wrap 642 * @param string $label L10n label name 643 * @param string $class CSS class name to apply to wrapper 644 * @param string $help Help text item 645 * @return string HTML 646 * @see wrapRegion() 647 * @since 4.6.0 648 */ 649 650 function wrapGroup($id, $content, $label, $class = '', $help = '') 651 { 652 return wrapRegion($id, $content, '', $label, '', $class, $help); 653 } 654 655 /** 656 * Renders start of a layout <table> element. 657 * 658 * @return string HTML 659 * @deprecated in 4.4.0 660 */ 661 662 function startSkelTable() 663 { 664 return 665 '<table width="300" cellpadding="0" cellspacing="0" style="border:1px #ccc solid">'; 666 } 667 668 /** 669 * Renders start of a layout <table> element. 670 * 671 * @param string $id HTML id attribute 672 * @param string $align HTML align attribute 673 * @param string $class HTML class attribute 674 * @param int $p HTML cellpadding attribute 675 * @param int $w HTML width atttribute 676 * @return string HTML 677 * @example 678 * startTable(). 679 * tr(td('column') . td('column')). 680 * tr(td('column') . td('column')). 681 * endTable(); 682 */ 683 684 function startTable($id = '', $align = '', $class = '', $p = 0, $w = 0) 685 { 686 $atts = join_atts(array( 687 'class' => $class, 688 'id' => $id, 689 'cellpadding' => (int) $p, 690 'width' => (int) $w, 691 'align' => $align, 692 ), TEXTPATTERN_STRIP_EMPTY); 693 694 return n.'<table'.$atts.'>'; 695 } 696 697 /** 698 * Renders closing </table> tag. 699 * 700 * @return string HTML 701 */ 702 703 function endTable() 704 { 705 return n.'</table>'; 706 } 707 708 /** 709 * Renders <tr> elements from input parameters. 710 * 711 * Takes a list of arguments containing each making a row. 712 * 713 * @return string HTML 714 * @example 715 * stackRows( 716 * td('cell') . td('cell'), 717 * td('cell') . td('cell') 718 * ); 719 */ 720 721 function stackRows() 722 { 723 foreach (func_get_args() as $a) { 724 $o[] = tr($a); 725 } 726 727 return join('', $o); 728 } 729 730 /** 731 * Renders a <td> element. 732 * 733 * @param string $content Cell content 734 * @param int $width HTML width attribute 735 * @param string $class HTML class attribute 736 * @param string $id HTML id attribute 737 * @return string HTML 738 */ 739 740 function td($content = '', $width = null, $class = '', $id = '') 741 { 742 $opts = array( 743 'class' => $class, 744 'id' => $id, 745 ); 746 747 if (is_numeric($width)) { 748 $opts['width'] = (int) $width; 749 } 750 751 return tda($content, $opts); 752 } 753 754 /** 755 * Renders a <td> element with attributes. 756 * 757 * @param string $content Cell content 758 * @param string|array $atts Cell attributes 759 * @return string HTML 760 */ 761 762 function tda($content, $atts = '') 763 { 764 $content = ($content === '') ? sp : $content; 765 766 return n.tag($content, 'td', $atts); 767 } 768 769 /** 770 * Renders a <td> element with attributes. 771 * 772 * This function is identical to tda(). 773 * 774 * @param string $content Cell content 775 * @param string|array $atts Cell attributes 776 * @return string HTML 777 * @access private 778 * @see tda() 779 */ 780 781 function tdtl($content, $atts = '') 782 { 783 return tda($content, $atts); 784 } 785 786 /** 787 * Renders a <tr> element with attributes. 788 * 789 * @param string $content Row content 790 * @param string|array $atts Row attributes 791 * @return string HTML 792 */ 793 794 function tr($content, $atts = '') 795 { 796 return n.tag($content, 'tr', $atts); 797 } 798 799 /** 800 * Renders a <td> element with top/left text orientation, colspan and 801 * other attributes. 802 * 803 * @param string $content Cell content 804 * @param int $span Cell colspan attribute 805 * @param int $width Cell width attribute 806 * @param string $class Cell class attribute 807 * @return string HTML 808 */ 809 810 function tdcs($content, $span, $width = null, $class = '') 811 { 812 $opts = array( 813 'class' => $class, 814 'colspan' => (int) $span, 815 ); 816 817 if (is_numeric($width)) { 818 $opts['width'] = (int) $width; 819 } 820 821 return tda($content, $opts); 822 } 823 824 /** 825 * Renders a <td> element with a rowspan attribute. 826 * 827 * @param string $content Cell content 828 * @param int $span Cell rowspan attribute 829 * @param int $width Cell width attribute 830 * @param string $class Cell class attribute 831 * @return string HTML 832 */ 833 834 function tdrs($content, $span, $width = null, $class = '') 835 { 836 $opts = array( 837 'class' => $class, 838 'rowspan' => (int) $span, 839 ); 840 841 if (is_numeric($width)) { 842 $opts['width'] = (int) $width; 843 } 844 845 return tda($content, $opts); 846 } 847 848 /** 849 * Renders a form label inside a table cell. 850 * 851 * @param string $text Label text 852 * @param string $help Help text 853 * @param string $label_id HTML "for" attribute, i.e. id of corresponding form element 854 * @return string HTML 855 */ 856 857 function fLabelCell($text, $help = '', $label_id = '') 858 { 859 $cell = gTxt($text).' '.popHelp($help); 860 861 if ($label_id) { 862 $cell = tag($cell, 'label', array('for' => $label_id)); 863 } 864 865 return tda($cell, array('class' => 'cell-label')); 866 } 867 868 /** 869 * Renders a form input inside a table cell. 870 * 871 * @param string $name HTML name attribute 872 * @param string $var Input value 873 * @param int $tabindex HTML tabindex attribute 874 * @param int $size HTML size attribute 875 * @param bool $help TRUE to display help link 876 * @param string $id HTML id attribute 877 * @return string HTML 878 */ 879 880 function fInputCell($name, $var = '', $tabindex = 0, $size = 0, $help = false, $id = '') 881 { 882 $pop = ($help) ? popHelp($name) : ''; 883 884 return tda(fInput('text', $name, $var, '', '', '', $size, $tabindex, $id).$pop); 885 } 886 887 /** 888 * Renders a name-value input control with label. 889 * 890 * The rendered input can be customised via the 891 * '{$event}_ui > inputlabel.{$name}' pluggable UI callback event. 892 * 893 * @param string $name Input name 894 * @param string $input Complete input control widget 895 * @param string|array $label Label text | array (label text, HTML block to append to label) 896 * @param string|array $help Help text item | array(help text item, inline help text) 897 * @param string|array $atts Class name | attribute pairs to assign to container div 898 * @param string|array $wraptag_val Tag to wrap the value / label in, or empty to omit 899 * @return string HTML 900 * @example 901 * echo inputLabel('active', yesnoRadio('active'), 'Keep active?'); 902 */ 903 904 function inputLabel($name, $input, $label = '', $help = array(), $atts = array(), $wraptag_val = array('div', 'div')) 905 { 906 global $event; 907 908 $arguments = compact('name', 'input', 'label', 'help', 'atts', 'wraptag_val'); 909 910 $fallback_class = 'txp-form-field edit-'.str_replace('_', '-', $name); 911 $tools = ''; 912 913 if ($atts && is_string($atts)) { 914 $atts = array('class' => $atts); 915 } elseif (!$atts) { 916 $atts = array('class' => $fallback_class); 917 } elseif (is_array($atts) && !array_key_exists('class', $atts)) { 918 $atts['class'] = $fallback_class; 919 } 920 921 if (!is_array($help)) { 922 $help = array($help); 923 } 924 925 if (is_array($label)) { 926 if (isset($label[1])) { 927 $tools = (string) $label[1]; 928 } 929 930 $label = (string) $label[0]; 931 } 932 933 if (empty($help)) { 934 $help = array( 935 0 => '', 936 1 => '' 937 ); 938 } 939 940 $inlineHelp = (isset($help[1])) ? $help[1] : ''; 941 942 if ($label) { 943 $labelContent = tag(gTxt($label).popHelp($help[0]), 'label', array('for' => $name)).$tools; 944 } else { 945 $labelContent = gTxt($name).popHelp($help[0]).$tools; 946 } 947 948 if (!is_array($wraptag_val)) { 949 $wraptag_val = array($wraptag_val, $wraptag_val); 950 } 951 952 if ($wraptag_val[0]) { 953 $input = n.tag($input, $wraptag_val[0], array('class' => 'txp-form-field-value')); 954 } 955 956 if (isset($wraptag_val[1]) && $wraptag_val[1]) { 957 $labeltag = n.tag($labelContent, $wraptag_val[1], array('class' => 'txp-form-field-label')); 958 } else { 959 $labeltag = $labelContent; 960 } 961 962 $out = n.tag( 963 $labeltag. 964 fieldHelp($inlineHelp). 965 $input.n, 'div', $atts); 966 967 return pluggable_ui($event.'_ui', 'inputlabel.'.$name, $out, $arguments); 968 } 969 970 /** 971 * Renders anything as an XML element. 972 * 973 * @param string $content Enclosed content 974 * @param string $tag The tag without brackets 975 * @param string|array $atts The element's HTML attributes 976 * @return string HTML 977 * @example 978 * echo tag('Link text', 'a', array('href' => '#', 'class' => 'warning')); 979 */ 980 981 function tag($content, $tag, $atts = '') 982 { 983 return empty($tag) || $content === '' ? $content : '<'.$tag.join_atts($atts).'>'.$content.'</'.$tag.'>'; 984 } 985 986 /** 987 * Renders anything as a HTML void element. 988 * 989 * @param string $tag The tag without brackets 990 * @param string|array $atts HTML attributes 991 * @return string HTML 992 * @since 4.6.0 993 * @example 994 * echo tag_void('input', array('name' => 'name', 'type' => 'text')); 995 */ 996 997 function tag_void($tag, $atts = '') 998 { 999 return '<'.$tag.join_atts($atts).' />'; 1000 } 1001 1002 /** 1003 * Renders anything as a HTML start tag. 1004 * 1005 * @param string $tag The tag without brackets 1006 * @param string|array $atts HTML attributes 1007 * @return string A HTML start tag 1008 * @since 4.6.0 1009 * @example 1010 * echo tag_start('section', array('class' => 'myClass')); 1011 */ 1012 1013 function tag_start($tag, $atts = '') 1014 { 1015 return '<'.$tag.join_atts($atts).'>'; 1016 } 1017 1018 /** 1019 * Renders anything as a HTML end tag. 1020 * 1021 * @param string $tag The tag without brackets 1022 * @return string A HTML end tag 1023 * @since 4.6.0 1024 * @example 1025 * echo tag_end('section'); 1026 */ 1027 1028 function tag_end($tag) 1029 { 1030 return '</'.$tag.'>'; 1031 } 1032 1033 /** 1034 * Renders a <p> element. 1035 * 1036 * @param string $item Enclosed content 1037 * @param string|array $atts HTML attributes 1038 * @return string HTML 1039 * @example 1040 * echo graf('This a paragraph.'); 1041 */ 1042 1043 function graf($item, $atts = '') 1044 { 1045 return n.tag($item, 'p', $atts); 1046 } 1047 1048 /** 1049 * Renders a <hx> element. 1050 * 1051 * @param string $item The Enclosed content 1052 * @param int $level Heading level 1...6 1053 * @param string|array $atts HTML attributes 1054 * @return string HTML 1055 * @example 1056 * echo hed('Heading', 2); 1057 */ 1058 1059 function hed($item, $level, $atts = '') 1060 { 1061 return n.tag($item, 'h'.$level, $atts).n; 1062 } 1063 1064 /** 1065 * Renders an <a> element. 1066 * 1067 * @param string $item Enclosed content 1068 * @param string|array $href The link target 1069 * @param string|array $atts HTML attributes 1070 * @return string HTML 1071 */ 1072 1073 function href($item, $href, $atts = '') 1074 { 1075 if (is_array($atts)) { 1076 $atts['href'] = $href; 1077 } else { 1078 if (is_array($href)) { 1079 $href = join_qs($href); 1080 } 1081 1082 $atts .= ' href="'.$href.'"'; 1083 } 1084 1085 return tag($item, 'a', $atts); 1086 } 1087 1088 /** 1089 * Renders a <strong> element. 1090 * 1091 * @param string $item Enclosed content 1092 * @param string|array $atts HTML attributes 1093 * @return string HTML 1094 */ 1095 1096 function strong($item, $atts = '') 1097 { 1098 return tag($item, 'strong', $atts); 1099 } 1100 1101 /** 1102 * Renders a <span> element. 1103 * 1104 * @param string $item Enclosed content 1105 * @param string|array $atts HTML attributes 1106 * @return string HTML 1107 */ 1108 1109 function span($item, $atts = '') 1110 { 1111 return tag($item, 'span', $atts); 1112 } 1113 1114 /** 1115 * Renders a <pre> element. 1116 * 1117 * @param string $item The input string 1118 * @param string|array $atts HTML attributes 1119 * @return string HTML 1120 * @example 1121 * echo htmlPre('<?php echo "Hello World"; ?>'); 1122 */ 1123 1124 function htmlPre($item, $atts = '') 1125 { 1126 if (($item = tag($item, 'code')) === '') { 1127 $item = null; 1128 } 1129 1130 return tag($item, 'pre', $atts); 1131 } 1132 1133 /** 1134 * Renders a HTML comment (<!-- -->) element. 1135 * 1136 * @param string $item The input string 1137 * @return string HTML 1138 * @example 1139 * echo comment('Some HTML comment.'); 1140 */ 1141 1142 function comment($item) 1143 { 1144 return '<!-- '.str_replace('--', '- - ', $item).' -->'; 1145 } 1146 1147 /** 1148 * Renders a <small> element. 1149 * 1150 * @param string $item The input string 1151 * @param string|array $atts HTML attributes 1152 * @return string HTML 1153 */ 1154 1155 function small($item, $atts = '') 1156 { 1157 return tag($item, 'small', $atts); 1158 } 1159 1160 /** 1161 * Renders a table data row from an array of content => width pairs. 1162 * 1163 * @param array $array Array of content => width pairs 1164 * @param string|array $atts Table row atrributes 1165 * @return string A HTML table row 1166 */ 1167 1168 function assRow($array, $atts = '') 1169 { 1170 $out = array(); 1171 1172 foreach ($array as $value => $width) { 1173 $out[] = tda($value, array('width' => (int) $width)); 1174 } 1175 1176 return tr(join('', $out), $atts); 1177 } 1178 1179 /** 1180 * Renders a table head row from an array of strings. 1181 * 1182 * Takes an argument list of head text strings. i18n is applied to the strings. 1183 * 1184 * @return string HTML 1185 */ 1186 1187 function assHead() 1188 { 1189 $array = func_get_args(); 1190 $o = array(); 1191 1192 foreach ($array as $a) { 1193 $o[] = hCell(gTxt($a), '', ' scope="col"'); 1194 } 1195 1196 return tr(join('', $o)); 1197 } 1198 1199 /** 1200 * Renders the ubiquitious popup help button. 1201 * 1202 * The rendered link can be customised via a 'admin_help > {$help_var}' 1203 * pluggable UI callback event. 1204 * 1205 * @param string $help_var Help topic 1206 * @param int $width Popup window width 1207 * @param int $height Popup window height 1208 * @param string $class HTML class 1209 * @return string HTML 1210 */ 1211 1212 function popHelp($help_var, $width = 0, $height = 0, $class = 'pophelp') 1213 { 1214 if (!$help_var) { 1215 return ''; 1216 } 1217 1218 $ui = sp.href('i', HELP_URL.'?item='.urlencode($help_var).'&language='.urlencode(LANG), array( 1219 'class' => $class, 1220 'rel' => 'help', 1221 'target' => '_blank', 1222 'title' => gTxt('help'), 1223 'aria-label' => gTxt('help'), 1224 'role' => 'button', 1225 'onclick' => 'popWin(this.href, '.intval($width).', '.intval($height).'); return false;', 1226 )); 1227 1228 return pluggable_ui('admin_help', $help_var, $ui, compact('help_var', 'width', 'height', 'class')); 1229 } 1230 1231 /** 1232 * Renders inline help text. 1233 * 1234 * The help topic is the name of a string that can be found in txp_lang. 1235 * 1236 * The rendered link can be customised via a 'admin_help_field > {$help_var}' 1237 * pluggable UI callback event. 1238 * 1239 * @param string $help_var Help topic 1240 * @return string HTML 1241 */ 1242 1243 function fieldHelp($help_var) 1244 { 1245 if (!$help_var) { 1246 return ''; 1247 } 1248 1249 $help_text = gTxt($help_var); 1250 1251 // If rendered string is the same as the input string, either the l10n 1252 // doesn't exist or the string is missing from txp_lang. 1253 // Either way, no instruction text, no render. 1254 if ($help_var === $help_text) { 1255 return ''; 1256 } 1257 1258 $ui = n.tag($help_text, 'div', array('class' => 'txp-form-field-instructions')); 1259 1260 return pluggable_ui('admin_help_field', $help_var, $ui, compact('help_var', 'textile')); 1261 } 1262 1263 /** 1264 * Renders the ubiquitious popup help button with a little less visual noise. 1265 * 1266 * The rendered link can be customised via a 'admin_help > {$help_var}' 1267 * pluggable UI callback event. 1268 * 1269 * @param string $help_var Help topic 1270 * @param int $width Popup window width 1271 * @param int $height Popup window height 1272 * @return string HTML 1273 */ 1274 1275 function popHelpSubtle($help_var, $width = 0, $height = 0) 1276 { 1277 return popHelp($help_var, $width, $height, 'pophelpsubtle'); 1278 } 1279 1280 /** 1281 * Renders a link that opens a popup tag area. 1282 * 1283 * @param string $var Tag name 1284 * @param string $text Link text 1285 * @param array $atts Attributes to add to the link 1286 * @return string HTML 1287 */ 1288 1289 function popTag($var, $text, $atts = array()) 1290 { 1291 $opts = array( 1292 'event' => 'tag', 1293 'tag_name' => $var, 1294 ) + $atts; 1295 1296 return href($text, $opts, array( 1297 'class' => 'txp-tagbuilder-link', 1298 )); 1299 } 1300 1301 /** 1302 * Renders a list of tag builder links. 1303 * 1304 * @param string $type Tag type 1305 * @return string HTML 1306 */ 1307 1308 function popTagLinks($type) 1309 { 1310 global $event; 1311 1312 include txpath.'/lib/taglib.php'; 1313 1314 $arname = $type.'_tags'; 1315 1316 $out = array(); 1317 1318 foreach ($$arname as $a) { 1319 $out[] = tag(popTag($a, gTxt('tag_'.$a), array('panel' => $event, 'step' => 'build')), 'li'); 1320 } 1321 1322 return n.tag(n.join(n, $out).n, 'ul', array('class' => 'plain-list')); 1323 } 1324 1325 /** 1326 * Renders an admin-side message text. 1327 * 1328 * @param string $thing Subject 1329 * @param string $thething Predicate (strong) 1330 * @param string $action Object 1331 * @return string HTML 1332 */ 1333 1334 function messenger($thing, $thething = '', $action = '') 1335 { 1336 return gTxt($thing).' '.strong($thething).' '.gTxt($action); 1337 } 1338 1339 /** 1340 * Renders a multi-edit form listing editing methods. 1341 * 1342 * @param array $options array('value' => array( 'label' => '', 'html' => '' ),...) 1343 * @param string $event Event 1344 * @param string $step Step 1345 * @param int $page Page number 1346 * @param string $sort Column sorted by 1347 * @param string $dir Sorting direction 1348 * @param string $crit Search criterion 1349 * @param string $search_method Search method 1350 * @return string HTML 1351 * @example 1352 * echo form( 1353 * multi_edit(array( 1354 * 'feature' => array('label' => 'Feature', 'html' => yesnoRadio('is_featured', 1)), 1355 * 'delete' => array('label' => 'Delete'), 1356 * )) 1357 * ); 1358 */ 1359 1360 function multi_edit($options, $event = null, $step = null, $page = '', $sort = '', $dir = '', $crit = '', $search_method = '') 1361 { 1362 $html = $methods = array(); 1363 $methods[''] = gTxt('with_selected_option'); 1364 1365 if ($event === null) { 1366 global $event; 1367 } 1368 1369 if ($step === null) { 1370 $step = $event.'_multi_edit'; 1371 } 1372 1373 callback_event_ref($event.'_ui', 'multi_edit_options', 0, $options); 1374 1375 foreach ($options as $value => $option) { 1376 if (is_array($option)) { 1377 $methods[$value] = $option['label']; 1378 1379 if (isset($option['html'])) { 1380 $html[$value] = n.tag($option['html'], 'div', array( 1381 'class' => 'multi-option', 1382 'data-multi-option' => $value, 1383 )); 1384 } 1385 } else { 1386 $methods[$value] = $option; 1387 } 1388 } 1389 1390 return n.tag( 1391 selectInput('edit_method', $methods, ''). 1392 eInput($event). 1393 sInput($step). 1394 hInput('page', $page). 1395 ($sort ? hInput('sort', $sort).hInput('dir', $dir) : ''). 1396 ($crit !== '' ? hInput('crit', $crit).hInput('search_method', $search_method) : ''). 1397 join('', $html). 1398 fInput('submit', '', gTxt('go')), 'div', array('class' => 'multi-edit')); 1399 } 1400 1401 /** 1402 * Renders a widget to select various amounts to page lists by. 1403 * 1404 * The rendered options can be changed via a '{$event}_ui > pageby_values' 1405 * callback event. 1406 * 1407 * @param string $event Event 1408 * @param int $val Current setting 1409 * @param string|null $step Step 1410 * @return string HTML 1411 */ 1412 1413 function pageby_form($event, $val, $step = null) 1414 { 1415 $vals = array(15, 25, 50, 100); 1416 callback_event_ref($event.'_ui', 'pageby_values', 0, $vals); 1417 1418 if ($step === null) { 1419 $step = $event.'_change_pageby'; 1420 } 1421 1422 if (empty($val)) { 1423 $val = $vals[0]; 1424 } 1425 1426 $out = array(); 1427 1428 foreach ($vals as $qty) { 1429 if ($qty == $val) { 1430 $class = 'navlink-active'; 1431 $aria_pressed = 'true'; 1432 } else { 1433 $class = 'navlink'; 1434 $aria_pressed = 'false'; 1435 } 1436 1437 $out[] = href($qty, array( 1438 'event' => $event, 1439 'step' => $step, 1440 'qty' => $qty, 1441 '_txp_token' => form_token(), 1442 ), array( 1443 'class' => $class, 1444 'title' => gTxt('view_per_page', array('{page}' => $qty)), 1445 'aria-pressed' => $aria_pressed, 1446 'role' => 'button', 1447 )); 1448 } 1449 1450 return n.tag(join('', $out), 'div', array('class' => 'nav-tertiary pageby')); 1451 } 1452 1453 /** 1454 * Renders an upload form. 1455 * 1456 * The rendered form can be customised via the '{$event}_ui > upload_form' 1457 * pluggable UI callback event. 1458 * 1459 * @param string $label File name label. May be empty 1460 * @param string $pophelp Help item 1461 * @param string $step Step 1462 * @param string $event Event 1463 * @param string $id File id 1464 * @param int $max_file_size Maximum allowed file size 1465 * @param string $label_id HTML id attribute for the filename input element 1466 * @param string $class HTML class attribute for the form element 1467 * @param string|array $wraptag_val Tag to wrap the value / label in, or empty to omit 1468 * @return string HTML 1469 */ 1470 1471 function upload_form($label, $pophelp = '', $step, $event, $id = '', $max_file_size = 1000000, $label_id = '', $class = '', $wraptag_val = array('div', 'div')) 1472 { 1473 extract(gpsa(array( 1474 'page', 1475 'sort', 1476 'dir', 1477 'crit', 1478 'search_method', 1479 ))); 1480 1481 if (is_array($search_method)) { 1482 $search_method = join(',', $search_method); 1483 } 1484 1485 if (!$label_id) { 1486 $label_id = $event.'-upload'; 1487 } 1488 1489 if ($wraptag_val) { 1490 $wraptag_class = 'txp-form-field file-uploader'; 1491 } else { 1492 $wraptag_class = 'inline-file-uploader'; 1493 } 1494 1495 $argv = func_get_args(); 1496 1497 return pluggable_ui($event.'_ui', 'upload_form', 1498 n.tag( 1499 (!empty($max_file_size) ? hInput('MAX_FILE_SIZE', $max_file_size) : ''). 1500 eInput($event). 1501 sInput($step). 1502 hInput('id', $id). 1503 hInput('sort', $sort). 1504 hInput('dir', $dir). 1505 hInput('page', $page). 1506 hInput('search_method', $search_method). 1507 hInput('crit', $crit). 1508 inputLabel( 1509 $label_id, 1510 fInput('file', 'thefile', '', '', '', '', '', '', $label_id). 1511 fInput('submit', '', gTxt('upload')), 1512 $label, 1513 array($pophelp, 'instructions_'.$pophelp), 1514 $wraptag_class, 1515 $wraptag_val 1516 ). 1517 tInput().n, 1518 'form', array( 1519 'class' => 'upload-form'.($class ? ' '.trim($class) : ''), 1520 'method' => 'post', 1521 'enctype' => 'multipart/form-data', 1522 'action' => 'index.php', 1523 ) 1524 ), 1525 $argv); 1526 } 1527 1528 /** 1529 * Renders an admin-side search form. 1530 * 1531 * @param string $event Event 1532 * @param string $step Step 1533 * @param string $crit Search criterion 1534 * @param array $methods Valid search methods 1535 * @param string $method Actual search method 1536 * @param string $default_method Default search method 1537 * @return string HTML 1538 */ 1539 1540 function search_form($event, $step, $crit, $methods, $method, $default_method) 1541 { 1542 $method = ($method) ? $method : $default_method; 1543 1544 return form( 1545 graf( 1546 tag(gTxt('search'), 'label', array('for' => $event.'-search')). 1547 selectInput('search_method', $methods, $method, '', '', $event.'-search'). 1548 fInput('text', 'crit', $crit, 'input-medium', '', '', INPUT_MEDIUM). 1549 eInput($event). 1550 sInput($step). 1551 fInput('submit', 'search', gTxt('go')) 1552 ), '', '', 'get', 'search-form'); 1553 } 1554 1555 /** 1556 * Renders a dropdown for selecting Textfilter method preferences. 1557 * 1558 * @param string $name Element name 1559 * @param string $val Current value 1560 * @param string $id HTML id attribute for the select input element 1561 * @return string HTML 1562 */ 1563 1564 function pref_text($name, $val, $id = '') 1565 { 1566 $id = ($id) ? $id : $name; 1567 $vals = Txp::get('\Textpattern\Textfilter\Registry')->getMap(); 1568 1569 return selectInput($name, $vals, $val, '', '', $id); 1570 } 1571 1572 /** 1573 * Attaches a HTML fragment to a DOM node. 1574 * 1575 * @param string $id Target DOM node's id 1576 * @param string $content HTML fragment 1577 * @param string $noscript Noscript alternative 1578 * @param string $wraptag Wrapping HTML element 1579 * @param string $wraptagid Wrapping element's HTML id 1580 * @return string HTML/JS 1581 */ 1582 1583 function dom_attach($id, $content, $noscript = '', $wraptag = 'div', $wraptagid = '') 1584 { 1585 $id = escape_js($id); 1586 $content = escape_js($content); 1587 $wraptag = escape_js($wraptag); 1588 $wraptagid = escape_js($wraptagid); 1589 1590 $js = <<<EOF 1591 $(function () 1592 { 1593 $('#{$id}').append($('<{$wraptag} />').attr('id', '{$wraptagid}').html('{$content}')); 1594 }); 1595 EOF; 1596 1597 return script_js($js, (string) $noscript); 1598 } 1599 1600 /** 1601 * Renders a <:script> element. 1602 * 1603 * The $route parameter allows script_js() to be included in fixed page 1604 * locations (e.g. prior to the </body> tag) but to only render 1605 * its content if the event / step match. 1606 * 1607 * @param string $js JavaScript code 1608 * @param int|string $flags Flags TEXTPATTERN_SCRIPT_URL | TEXTPATTERN_SCRIPT_ATTACH_VERSION, or noscript alternative if a string 1609 * @param array $route Optional events/steps upon which to add the script 1610 * @return string HTML with embedded script element 1611 * @example 1612 * echo script_js('/js/script.js', TEXTPATTERN_SCRIPT_URL); 1613 */ 1614 1615 function script_js($js, $flags = '', $route = array()) 1616 { 1617 global $event, $step; 1618 1619 $targetEvent = empty($route[0]) ? null : (array)$route[0]; 1620 $targetStep = empty($route[1]) ? null : (array)$route[1]; 1621 1622 if (($targetEvent === null || in_array($event, $targetEvent)) && ($targetStep === null || in_array($step, $targetStep))) { 1623 if (is_int($flags)) { 1624 if ($flags & TEXTPATTERN_SCRIPT_URL) { 1625 if ($flags & TEXTPATTERN_SCRIPT_ATTACH_VERSION && strpos(txp_version, '-dev') === false) { 1626 $ext = pathinfo($js, PATHINFO_EXTENSION); 1627 1628 if ($ext) { 1629 $js = substr($js, 0, (strlen($ext) + 1) * -1); 1630 $ext = '.'.$ext; 1631 } 1632 1633 $js .= '.v'.txp_version.$ext; 1634 } 1635 1636 return n.tag(null, 'script', array('src' => $js)); 1637 } 1638 } 1639 1640 $js = preg_replace('#<(/?)(script)#i', '\\x3c$1$2', $js); 1641 1642 $out = n.tag(n.trim($js).n, 'script'); 1643 1644 if ($flags) { 1645 $out .= n.tag(n.trim($flags).n, 'noscript'); 1646 } 1647 1648 return $out; 1649 } 1650 1651 return ''; 1652 } 1653 1654 /** 1655 * Renders a "Details" toggle checkbox. 1656 * 1657 * @param string $classname Unique identfier. The cookie's name will be derived from this value 1658 * @param bool $form Create as a stand-along <form> element 1659 * @return string HTML 1660 */ 1661 1662 function toggle_box($classname, $form = false) 1663 { 1664 $name = 'cb_toggle_'.$classname; 1665 $id = escape_js($name); 1666 $class = escape_js($classname); 1667 1668 $out = checkbox($name, 1, cs('toggle_'.$classname), 0, $name). 1669 n.tag(gTxt('detail_toggle'), 'label', array('for' => $name)); 1670 1671 $js = <<<EOF 1672 $(function () 1673 { 1674 $('input') 1675 .filter(function () { 1676 if ($(this).attr('id') === '{$id}') { 1677 setClassDisplay('{$class}', $(this).is(':checked')); 1678 return true; 1679 } 1680 }) 1681 .change(function () { 1682 toggleClassRemember('{$class}'); 1683 }); 1684 }); 1685 EOF; 1686 1687 $out .= script_js($js); 1688 1689 if ($form) { 1690 return form($out); 1691 } 1692 1693 return $out; 1694 } 1695 1696 /** 1697 * Renders a checkbox to set/unset a browser cookie. 1698 * 1699 * @param string $classname Label text. The cookie's name will be derived from this value 1700 * @param bool $form Create as a stand-along <form> element 1701 * @return string HTML 1702 */ 1703 1704 function cookie_box($classname, $form = true) 1705 { 1706 $name = 'cb_'.$classname; 1707 $id = escape_js($name); 1708 $class = escape_js($classname); 1709 1710 if (cs('toggle_'.$classname)) { 1711 $value = 1; 1712 } else { 1713 $value = 0; 1714 } 1715 1716 $newvalue = 1 - $value; 1717 1718 $out = checkbox($name, 1, (bool) $value, 0, $name). 1719 n.tag(gTxt($classname), 'label', array('for' => $name)); 1720 1721 $js = <<<EOF 1722 $(function () 1723 { 1724 $('input') 1725 .filter(function () { 1726 if ($(this).attr('id') === '{$id}') { 1727 return true; 1728 } 1729 }) 1730 .change(function () { 1731 setClassRemember('{$class}', $newvalue); 1732 $(this).parents('form').submit(); 1733 }); 1734 }); 1735 EOF; 1736 1737 $out .= script_js($js); 1738 1739 if ($form) { 1740 if (serverSet('QUERY_STRING')) { 1741 $action = 'index.php?'.serverSet('QUERY_STRING'); 1742 } else { 1743 $action = 'index.php'; 1744 } 1745 1746 $out .= eInput(gps('event')).tInput(); 1747 1748 return tag($out, 'form', array( 1749 'class' => $name, 1750 'method' => 'post', 1751 'action' => $action, 1752 )); 1753 } 1754 1755 return $out; 1756 } 1757 1758 /** 1759 * Renders a <fieldset> element. 1760 * 1761 * @param string $content Enclosed content 1762 * @param string $legend Legend text 1763 * @param string $id HTML id attribute 1764 * @return string HTML 1765 */ 1766 1767 function fieldset($content, $legend = '', $id = '') 1768 { 1769 return tag(trim(tag($legend, 'legend').n.$content), 'fieldset', array('id' => $id)); 1770 } 1771 1772 /** 1773 * Renders a link element to hook up txpAsyncHref() with request parameters. 1774 * 1775 * See this function's JavaScript companion, txpAsyncHref(), in textpattern.js. 1776 * 1777 * @param string $item Link text 1778 * @param array $parms Request parameters; array keys are 'event', 'step', 'thing', 'property' 1779 * @param string|array $atts HTML attributes 1780 * @return string HTML 1781 * @since 4.5.0 1782 * @example 1783 * echo asyncHref('Disable', array( 1784 * 'event' => 'myEvent', 1785 * 'step' => 'myStep', 1786 * 'thing' => 'status', 1787 * 'property' => 'disable', 1788 * )); 1789 */ 1790 1791 function asyncHref($item, $parms, $atts = '') 1792 { 1793 global $event, $step; 1794 1795 $parms = lAtts(array( 1796 'event' => $event, 1797 'step' => $step, 1798 'thing' => '', 1799 'property' => '', 1800 ), $parms); 1801 1802 $class = $parms['step'].' async'; 1803 1804 if (is_array($atts)) { 1805 $atts['class'] = $class; 1806 } else { 1807 $atts .= ' class="'.txpspecialchars($class).'"'; 1808 } 1809 1810 return href($item, join_qs($parms), $atts); 1811 } 1812 1813 /** 1814 * Renders an array of items as a HTML list. 1815 * 1816 * This function is used for tag handler functions. Creates a HTML list markup 1817 * from an array of items. 1818 * 1819 * @param array $list 1820 * @param string $wraptag The HTML element 1821 * @param string $break The HTML break element 1822 * @param string $class Class applied to the wraptag 1823 * @param string $breakclass Class applied to break tag 1824 * @param string $atts HTML attributes applied to the wraptag 1825 * @param string $breakatts HTML attributes applied to the break tag 1826 * @param string $id HTML id applied to the wraptag 1827 * @return string HTML 1828 * @package HTML 1829 * @example 1830 * echo doWrap(array('item1', 'item2'), 'div', 'p'); 1831 */ 1832 1833 function doWrap($list, $wraptag, $break, $class = '', $breakclass = '', $atts = '', $breakatts = '', $id = '') 1834 { 1835 if (!$list) { 1836 return ''; 1837 } 1838 1839 if ($id) { 1840 $atts .= ' id="'.txpspecialchars($id).'"'; 1841 } 1842 1843 if ($class) { 1844 $atts .= ' class="'.txpspecialchars($class).'"'; 1845 } 1846 1847 if ($breakclass) { 1848 $breakatts .= ' class="'.txpspecialchars($breakclass).'"'; 1849 } 1850 1851 // Non-enclosing breaks. 1852 if (!preg_match('/^\w+$/', $break) or $break == 'br' or $break == 'hr') { 1853 if ($break == 'br' or $break == 'hr') { 1854 $break = "<$break $breakatts/>".n; 1855 } 1856 1857 return ($wraptag) ? tag(join($break, $list), $wraptag, $atts) : join($break, $list); 1858 } 1859 1860 return ($wraptag) 1861 ? tag(n.tag(join("</$break>".n."<{$break}{$breakatts}>", $list), $break, $breakatts).n, $wraptag, $atts) 1862 : tag(n.join("</$break>".n."<{$break}{$breakatts}>".n, $list).n, $break, $breakatts); 1863 } 1864 1865 /** 1866 * Renders anything as a HTML tag. 1867 * 1868 * Used for tag handler functions. 1869 * 1870 * If $content is empty, renders a self-closing tag. 1871 * 1872 * @param string $content The wrapped item 1873 * @param string $tag The HTML tag 1874 * @param string $class HTML class 1875 * @param string $atts HTML attributes 1876 * @param string $id HTML id 1877 * @return string HTML 1878 * @package HTML 1879 * @example 1880 * echo doTag('', 'meta', '', 'name="description" content="Some content"'); 1881 */ 1882 1883 function doTag($content, $tag, $class = '', $atts = '', $id = '') 1884 { 1885 if ($id) { 1886 $atts .= ' id="'.txpspecialchars($id).'"'; 1887 } 1888 1889 if ($class) { 1890 $atts .= ' class="'.txpspecialchars($class).'"'; 1891 } 1892 1893 if (!$tag) { 1894 return $content; 1895 } 1896 1897 return ($content) ? tag($content, $tag, $atts) : "<$tag $atts />"; 1898 } 1899 1900 /** 1901 * Renders a label. 1902 * 1903 * This function is mostly used for rendering headings in tag handler functions. 1904 * 1905 * If no $labeltag is given, label is separated from the content with 1906 * a <br>. 1907 * 1908 * @param string $label The label 1909 * @param string $labeltag The HTML element 1910 * @return string HTML 1911 * @package HTML 1912 * @example 1913 * echo doLabel('My label', 'h3'); 1914 */ 1915 1916 function doLabel($label = '', $labeltag = '') 1917 { 1918 if ($label) { 1919 return (empty($labeltag) ? $label.'<br />' : tag($label, $labeltag)); 1920 } 1921 1922 return ''; 1923 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title