TinyURL. Шаг 3. Рендеринг интерфейса

Больше всего в программировании я не люблю писать интерфейсы, и именно поэтому мне нравится программировать под Web, где создание внешнего вида программы требует существенно меньше усилий, чем в десктопных приложениях. Да и при программировании под Windows я все чаще отдаю предпочтение HTML-интерфейсу

Впрочем, и в Web-приложениях не обходитсябез трудностей, особенно в тот момент, когда речь заходит о кроссбраузерности. Так как мои требования к внешнему видупрограммы невелики и в первую очередь меня интересует функциональность, в своих последних проектах я стал использовать рендер.

Рендер - это небольшая php-функция, которая на основе форматированной строки создает аскетичный, но достаточно удобный интерфейс, который выглядит примерно вот так.

Закладка1
Закладка2
Закладка1
Закладка2

Код, который требуется для вывода этих форм достаточно невелик и сводится к определению массива данных и вызву функции render()

  1.  
  2. $data = array(
  3. 'formid' => 'test',
  4. 'options' => ''
  5. .',:tab:Закладка1'
  6. .',field1'
  7. .',:splitter:Разделитель'
  8. .',cbox1:checkbox'
  9. .',rbtn1:radio:Опция1:Опция2:Опция3'
  10. .',:tab:Закладка2'
  11. .',text1:textarea'
  12. .',',
  13. 'notes' => array(
  14. 'field1' => 'Какое-то поле ввода',
  15. 'cbox1' => 'Можно поставить галочку ...',
  16. 'rbtn1' => '... или выбрать одно из значений',
  17. 'text1' => 'а можно и текст ввести'
  18. ),
  19. 'comments' => array(
  20. 'field1' => 'Подробное описание значения поля с примерами',
  21. )
  22. );
  23. echo '<div>';
  24. render($data);
  25. $data['activetab'] = 7;
  26. $data['formid'] = 'secondone';
  27. $data['values']['cbox1'] = 1;
  28. render($data);
  29. echo '</div>';
  30.  

Теперь перейдем к самому важному и определим функцию render(), которая отрисовывает интерфейс. Функция может показаться громоздкой, но она в самом деле экономит кучу времени.

  1.  
  2. <?
  3. function render($data)
  4. {
  5. $activetab = 0;
  6. $formid = 'option';
  7.  
  8. $css = array(
  9. 'tabctrl' => 'render_tabctrl',
  10. 'tab' => 'render_tab',
  11. 'activetab' => 'render_activetab',
  12. 'tabbody' => 'render_tabbody',
  13. 'table' => 'render_table',
  14. 'td' => 'render_td',
  15. 'tdval' => 'render_tdval',
  16. 'name' => 'render_name',
  17. 'note' => 'render_note',
  18. 'comment' => 'render_comment',
  19. 'input' => 'render_input',
  20. 'textarea' => 'render_textarea',
  21. 'dummy' => ''
  22. );
  23.  
  24. extract($css, EXTR_PREFIX_ALL, 'css');
  25. extract($data, EXTR_OVERWRITE);
  26.  
  27. preg_match_all('#:tab:(.+),#imU', $options, $matches);
  28. $tabs = $matches[1];
  29. $curtab = 0;
  30. $tabcnt = count($tabs);
  31.  
  32. echo "<form method = post action = '' id = '{$formid}'>
  33. <input id = {$formid}activetab type = hidden>
  34. ";
  35.  
  36. if($tabcnt)
  37. {
  38. echo "<div class = '$css_tabctrl'>";
  39. for($i = 0; $i < $tabcnt; $i++)
  40. {
  41. echo "<div id='{$formid}tab{$i}ctrl' class='$css_tab'"
  42. ." onclick='{$formid}onTab($i);'>{$tabs[$i]}</div>\n";
  43. }
  44. echo "</div>\n";
  45. }
  46.  
  47. $settings = explode(',', $options);
  48. $cnt = count($settings);
  49. $istableopened = false;
  50.  
  51. for($i = 0; $i < $cnt; $i++)
  52. {
  53. if(strlen(trim($settings[$i])) == 0)
  54. {
  55. continue;
  56. }
  57. $data = explode(":", $settings[$i]);
  58. $datacnt = count($data);
  59.  
  60. $name = $data[0];
  61. $type = isset($data[1]) ? $data[1] : "input";
  62. $comment = isset($comments[$name]) ? $comments[$name] : '';
  63. $note = isset($notes[$name]) ? $notes[$name] : '';
  64. $value = isset($values[$name]) ? $values[$name] : '';
  65.  
  66. $control = '';
  67. switch($type)
  68. {
  69. case "input":
  70. if(strlen($name) > 0)
  71. {
  72. $control .=
  73. "<input name = '$name' id = '$name' class = '$css_input' value = '$value'>";
  74. }
  75. break;
  76. case "radio":
  77. if($value == '')
  78. {
  79. $value = 2;
  80. }
  81. for($j = 2; $j < $datacnt; $j++)
  82. {
  83. $checked = ($j == $value) ? 'checked' : '';
  84. $control .=
  85. "<input type = radio name = '$name' value = '$j' $checked> {$data[$j]}<br>";
  86. }
  87. break;
  88. case "splitter":
  89. $control .= "<p><b>{$data[2]}</b></p>";
  90. break;
  91. case "textarea":
  92. $control .=
  93. "<textarea name = '$name' id = '$name' class = '$css_textarea'>$value</textarea>";
  94. break;
  95. case "checkbox":
  96. $checked = ($value == 'on' || $value == 1) ? 'checked' : '';
  97. $control .= " <input id='$name' name='$name' type = 'hidden' value='$value'>";
  98. $control .=
  99. " <input id='{$name}_ctrl' name='{$name}_ctrl' type = 'checkbox' $checked "
  100. ."onChange = \\"document.getElementById('{$name}').value = "
  101. ."document.getElementById('{$name}_ctrl').checked ? 1 : 0;\\">";
  102. break;
  103. case "br":
  104. $control .= '<br>';
  105. break;
  106. case "ajax":
  107. $control .=
  108. ' '."<input type = button value = '{$data[2]}' id = '{$data[3]}'>".' ';
  109. break;
  110. case "tab":
  111. if($curtab)
  112. {
  113. $control .= "</div>\n";
  114. }
  115. $control .= "<div id = '{$formid}tab$curtab' style = 'display: none;'"
  116. . " class = '$css_tabbody'>\n";
  117. $curtab++;
  118. break;
  119. }// end switch
  120.  
  121. $tablestr = false;
  122. if($type == "splitter" || $type == "tab")
  123. {
  124. if($istableopened)
  125. {
  126. echo "</table>\n";
  127. }
  128. $istableopened = false;
  129. }
  130. elseif($type == "ajax" || $type == "br" )
  131. {
  132. ;
  133. }
  134. else
  135. {
  136. if(!$istableopened)
  137. {
  138. echo "\n<table class = '$css_table'>";
  139. $istableopened = true;
  140. }
  141. echo "<tr><td class = '$css_td'>";
  142. $tablestr = true;
  143. }
  144.  
  145. if(strlen($name) > 0)
  146. {
  147. echo "<span class='$css_name'>$name</span>"
  148. ."<span class = '$css_note'><br>$note</span>"
  149. ."<div class = '$css_comment'>$comment</div>";
  150. }
  151.  
  152. if($tablestr)
  153. {
  154. echo "<td class = '$css_tdval'>";
  155. }
  156. echo "$control";
  157. echo "\n";
  158. } // end for
  159.  
  160. if($istableopened)
  161. {
  162. echo "</table>\n";
  163. }
  164.  
  165. if($curtab)
  166. {
  167. echo "</div>\n";
  168. $activetab = min($activetab, $curtab - 1);
  169. }
  170. echo '</form>';
  171. if($curtab)
  172. {
  173. ?>
  174. <script>
  175. function <?echo $formid;?>onTab(newtab)
  176. {
  177. activetab = document.getElementById('<?echo $formid;?>activetab').value;
  178. oldtabname = '<?echo $formid;?>tab' + activetab;
  179. newtabname = '<?echo $formid;?>tab' + newtab;
  180. if(activetab != newtab)
  181. {
  182. if(activetab != -1)
  183. {
  184. document.getElementById(oldtabname).style.display = 'none';
  185. document.getElementById(oldtabname + 'ctrl').className
  186. = '<?echo $css_tab;?>';
  187. }
  188. document.getElementById(newtabname).style.display = '';
  189. document.getElementById(newtabname + 'ctrl').className
  190. = '<?echo $css_activetab;?>';
  191. document.getElementById('<?echo $formid;?>activetab').value = newtab;
  192. }
  193. }
  194. document.getElementById('<?echo $formid;?>activetab').value = -1;
  195. <?echo $formid;?>onTab(<?echo $activetab;?>);
  196. </script>
  197. <?
  198. }
  199. }
  200. ?>
  201.  

Для того, чтобы получить показанный выше результат осталось лишь определить таблицу стилей

  1.  
  2. .render_comment
  3. {
  4. font-size: 70%; margin-top: 4px; color: #666;
  5. }
  6.  
  7. .render_note
  8. {
  9. font-size: 90%
  10. }
  11.  
  12. .render_table
  13. {
  14. border-collapse: collapse;
  15. }
  16.  
  17. .render_td, .render_tdval
  18. {
  19. border: 1px solid #bbb;
  20. text-align: justify;
  21. padding: 3px;
  22. padding-bottom: 8px;
  23. vertical-align: top;
  24. font-size: 90%;
  25. width: 400px;
  26. }
  27.  
  28. .render_tdval
  29. {
  30. padding-top: 10px;
  31. width: 400px;
  32. }
  33.  
  34. .render_tabctrl
  35. {
  36. padding-left: 8px;
  37. width: 100%;
  38. /* http://www.sitepoint.com/blogs/2005/02/26/simple-clearing-of-floats/ */
  39. overflow: auto;
  40. }
  41.  
  42. .render_tab
  43. {
  44. float: left;
  45. border: 1px solid gray;
  46. padding: 10px;
  47. font-weight: bold;
  48. margin: 1px;
  49. cursor: pointer;
  50. background: white;
  51. border-bottom: 1px solid gray;
  52. }
  53.  
  54. .render_activetab
  55. {
  56. float: left;
  57. border: 1px solid gray;
  58. padding: 10px;
  59. font-weight: bold;
  60. margin: 1px;
  61. cursor: pointer;
  62. background: #f8f8ff;
  63. border-bottom: 1px solid #f8f8ff;
  64. }
  65.  
  66. .render_tabbody
  67. {
  68. border: 1px solid gray;
  69. padding: 3px;
  70. padding-top: 10px;
  71. margin-top: -2px;
  72. background: #f8f8ff;
  73. }
  74.  
  75. .render_name
  76. {
  77. font-size:80%;
  78. margin-top:-10px;
  79. display:block;
  80. background-color:#fff;
  81. color:#444;
  82. float:left;
  83. padding: 1px;
  84. padding-left: 10px;
  85. padding-right: 10px;
  86. position: relative;
  87. z-index: 1;
  88. border: 1px solid #aaa;
  89. }
  90.  
  91. .render_input
  92. {
  93. width: 400px;
  94. }
  95.  
  96. .render_textarea
  97. {
  98. width: 400px;
  99. height: 10em;
  100. }
  101.  

Для работы с формой осталось навесить на нее обрабтчики, но об этом мы поговорим в следующий раз.

Читайте в блоге

TinyURL. Шаг 2. Кодирование и декодирование ссылки
TinyURL. Шаг за шагом. Шаг 1
PHP. Сохранение массива в файл
PHP. Преобразование таблицы в картинку. Создание информеров.
Повторное экранирование кавычек в PHP

Комментарии:

Войдите на сайт, чтобы оставить комментарий