PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/baser/views/helpers/bc_form.php

https://github.com/hashing/basercms
PHP | 1226 lines | 778 code | 106 blank | 342 comment | 179 complexity | 43daa1e54bb45f4c29b2f70b1b8cbe56 MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. /* SVN FILE: $Id$ */
  3. /**
  4. * FormHelper 拡張クラス
  5. *
  6. * PHP versions 5
  7. *
  8. * baserCMS : Based Website Development Project <http://basercms.net>
  9. * Copyright 2008 - 2012, baserCMS Users Community <http://sites.google.com/site/baserusers/>
  10. *
  11. * @copyright Copyright 2008 - 2012, baserCMS Users Community
  12. * @link http://basercms.net baserCMS Project
  13. * @package baser.view.helpers
  14. * @since baserCMS v 0.1.0
  15. * @version $Revision$
  16. * @modifiedby $LastChangedBy$
  17. * @lastmodified $Date$
  18. * @license http://basercms.net/license/index.html
  19. */
  20. /**
  21. * Include files
  22. */
  23. App::import('Helper',array('Html', 'Form', BC_TIME_HELPER, BC_TEXT_HELPER, BC_CKEDITOR_HELPER));
  24. /**
  25. * FormHelper 拡張クラス
  26. *
  27. * @package baser.views.helpers
  28. */
  29. class BcFormHelper extends FormHelper {
  30. /**
  31. * ヘルパー
  32. *
  33. * @var array
  34. * @access public
  35. */
  36. var $helpers = array('Html', BC_TIME_HELPER, BC_TEXT_HELPER, 'Javascript', BC_CKEDITOR_HELPER);
  37. /**
  38. * sizeCounter用の関数読み込み可否
  39. *
  40. * @var boolean
  41. * @access public
  42. */
  43. var $sizeCounterFunctionLoaded = false;
  44. /**
  45. * 都道府県用のSELECTタグを表示する
  46. *
  47. * @param string $fieldName Name attribute of the SELECT
  48. * @param mixed $selected Selected option
  49. * @param array $attributes Array of HTML options for the opening SELECT element
  50. * @return string 都道府県用のSELECTタグ
  51. * @access public
  52. */
  53. function prefTag($fieldName, $selected = null, $attributes = array()) {
  54. $pref = $this->BcText->prefList();
  55. return $this->select($fieldName, $pref, $selected, $attributes, false);
  56. }
  57. /**
  58. * dateTime 拡張
  59. *
  60. * @param string $fieldName Prefix name for the SELECT element
  61. * @param string $dateFormat DMY, MDY, YMD or NONE.
  62. * @param string $timeFormat 12, 24, NONE
  63. * @param string $selected Option which is selected.
  64. * @param string $attributes array of Attributes
  65. * 'monthNames' If set and false numbers will be used for month select instead of text.
  66. * 'minYear' The lowest year to use in the year select
  67. * 'maxYear' The maximum year to use in the year select
  68. * 'interval' The interval for the minutes select. Defaults to 1
  69. * 'separator' The contents of the string between select elements. Defaults to '-'
  70. * @param boolean $showEmpty Whether or not to show an empty default value.
  71. * @return string The HTML formatted OPTION element
  72. * @access public
  73. */
  74. function dateTime($fieldName, $dateFormat = 'DMY', $timeFormat = '12', $selected = null, $attributes = array(), $showEmpty = true) {
  75. $year = $month = $day = $hour = $min = $meridian = null;
  76. if (empty($selected)) {
  77. $selected = $this->value($fieldName);
  78. }
  79. if ($selected === null && $showEmpty != true) {
  80. $selected = time();
  81. }
  82. if (!empty($selected)) {
  83. if (is_array($selected)) {
  84. extract($selected);
  85. } else {
  86. if (is_numeric($selected)) {
  87. $selected = strftime('%Y-%m-%d %H:%M:%S', $selected);
  88. }
  89. $meridian = 'am';
  90. $pos = strpos($selected, '-');
  91. if ($pos !== false) {
  92. $date = explode('-', $selected);
  93. $days = explode(' ', $date[2]);
  94. $day = $days[0];
  95. $month = $date[1];
  96. $year = $date[0];
  97. } else {
  98. $days[1] = $selected;
  99. }
  100. if ($timeFormat != 'NONE' && !empty($timeFormat)) {
  101. $time = explode(':', $days[1]);
  102. $check = str_replace(':', '', $days[1]);
  103. if (($check > 115959) && $timeFormat == '12') {
  104. $time[0] = $time[0] - 12;
  105. $meridian = 'pm';
  106. } elseif ($time[0] == '00' && $timeFormat == '12') {
  107. $time[0] = 12;
  108. } elseif ($time[0] > 12) {
  109. $meridian = 'pm';
  110. }
  111. if ($time[0] == 0 && $timeFormat == '12') {
  112. $time[0] = 12;
  113. }
  114. $hour = $time[0];
  115. $min = $time[1];
  116. }
  117. }
  118. }
  119. $elements = array('Day','Month','Year','Hour','Minute','Meridian');
  120. // >>> CUSTOMIZE MODIFY 2011/01/11 ryuring 日本対応
  121. /*$defaults = array(
  122. 'minYear' => null, 'maxYear' => null, 'separator' => '-',
  123. 'interval' => 1, 'monthNames' => true
  124. );*/
  125. // ---
  126. $defaults = array(
  127. 'minYear' => null, 'maxYear' => null, 'separator' => ' ',
  128. 'interval' => 1, 'monthNames' => ''
  129. );
  130. // <<<
  131. $attributes = array_merge($defaults, (array) $attributes);
  132. if (isset($attributes['minuteInterval'])) {
  133. $attributes['interval'] = $attributes['minuteInterval'];
  134. unset($attributes['minuteInterval']);
  135. }
  136. $minYear = $attributes['minYear'];
  137. $maxYear = $attributes['maxYear'];
  138. $separator = $attributes['separator'];
  139. $interval = $attributes['interval'];
  140. $monthNames = $attributes['monthNames'];
  141. $attributes = array_diff_key($attributes, $defaults);
  142. if (isset($attributes['id'])) {
  143. if (is_string($attributes['id'])) {
  144. // build out an array version
  145. foreach ($elements as $element) {
  146. $selectAttrName = 'select' . $element . 'Attr';
  147. ${$selectAttrName} = $attributes;
  148. ${$selectAttrName}['id'] = $attributes['id'] . $element;
  149. }
  150. } elseif (is_array($attributes['id'])) {
  151. // check for missing ones and build selectAttr for each element
  152. foreach ($elements as $element) {
  153. $selectAttrName = 'select' . $element . 'Attr';
  154. ${$selectAttrName} = $attributes;
  155. ${$selectAttrName}['id'] = $attributes['id'][strtolower($element)];
  156. }
  157. }
  158. } else {
  159. // build the selectAttrName with empty id's to pass
  160. foreach ($elements as $element) {
  161. $selectAttrName = 'select' . $element . 'Attr';
  162. ${$selectAttrName} = $attributes;
  163. }
  164. }
  165. $opt = '';
  166. if ($dateFormat != 'NONE') {
  167. $selects = array();
  168. foreach (preg_split('//', $dateFormat, -1, PREG_SPLIT_NO_EMPTY) as $char) {
  169. switch ($char) {
  170. // >>> CUSTOMIZE ADD 2011/01/11 ryuring 和暦対応
  171. case 'W':
  172. $selects[] = $this->wyear($fieldName, $minYear, $maxYear, $year, $selectYearAttr, $showEmpty)."年";
  173. break;
  174. // <<<
  175. case 'Y':
  176. // >>> CUSTOMIZE MODIFY 2011/01/11 ryuring 日本対応
  177. /*$selects[] = $this->year(
  178. $fieldName, $minYear, $maxYear, $year, $selectYearAttr, $showEmpty
  179. );*/
  180. // ---
  181. $suffix = (preg_match('/^W/', $dateFormat)) ? '年' : '';
  182. $selects[] = $this->year(
  183. $fieldName, $minYear, $maxYear, $year, $selectYearAttr, $showEmpty
  184. ).$suffix;
  185. // <<<
  186. break;
  187. case 'M':
  188. $selectMonthAttr['monthNames'] = $monthNames;
  189. // >>> CUSTOMIZE MODIFY 2011/01/11 ryuring 日本対応
  190. //$selects[] = $this->month($fieldName, $month, $selectMonthAttr, $showEmpty);
  191. // ---
  192. $suffix = (preg_match('/^W/', $dateFormat)) ? '月' : '';
  193. $selects[] = $this->month($fieldName, $month, $selectMonthAttr, $showEmpty).$suffix;
  194. // <<<
  195. break;
  196. case 'D':
  197. // >>> CUSTOMIZE MODIFY 2011/01/11 ryuring 日本対応
  198. //$selects[] = $this->day($fieldName, $day, $selectDayAttr, $showEmpty);
  199. // ---
  200. $suffix = (preg_match('/^W/', $dateFormat)) ? '日' : '';
  201. $selects[] = $this->day($fieldName, $day, $selectDayAttr, $showEmpty).$suffix;
  202. // <<<
  203. break;
  204. }
  205. }
  206. $opt = implode($separator, $selects);
  207. }
  208. if (!empty($interval) && $interval > 1 && !empty($min)) {
  209. $min = round($min * (1 / $interval)) * $interval;
  210. }
  211. $selectMinuteAttr['interval'] = $interval;
  212. switch ($timeFormat) {
  213. case '24':
  214. $opt .= $this->hour($fieldName, true, $hour, $selectHourAttr, $showEmpty) . ':' .
  215. $this->minute($fieldName, $min, $selectMinuteAttr, $showEmpty);
  216. break;
  217. case '12':
  218. $opt .= $this->hour($fieldName, false, $hour, $selectHourAttr, $showEmpty) . ':' .
  219. $this->minute($fieldName, $min, $selectMinuteAttr, $showEmpty) . ' ' .
  220. $this->meridian($fieldName, $meridian, $selectMeridianAttr, $showEmpty);
  221. break;
  222. case 'NONE':
  223. default:
  224. $opt .= '';
  225. break;
  226. }
  227. return $opt;
  228. }
  229. /**
  230. * 和暦年
  231. *
  232. * @param string $fieldName Prefix name for the SELECT element
  233. * @param integer $minYear First year in sequence
  234. * @param integer $maxYear Last year in sequence
  235. * @param string $selected Option which is selected.
  236. * @param array $attributes Attribute array for the select elements.
  237. * @param boolean $showEmpty Show/hide the empty select option
  238. * @return string
  239. */
  240. function wyear($fieldName, $minYear = null, $maxYear = null, $selected = null, $attributes = array(), $showEmpty = true) {
  241. if ((empty($selected) || $selected === true) && $value = $this->value($fieldName)) {
  242. if (is_array($value)) {
  243. extract($value);
  244. $selected = $year;
  245. } else {
  246. if (empty($value)) {
  247. if (!$showEmpty && !$maxYear) {
  248. $selected = 'now';
  249. } elseif (!$showEmpty && $maxYear && !$selected) {
  250. $selected = $maxYear;
  251. }
  252. } else {
  253. $selected = $value;
  254. }
  255. }
  256. }
  257. if (strlen($selected) > 4 || $selected === 'now') {
  258. $wareki = $this->BcTime->convertToWareki(date('Y-m-d', strtotime($selected)));
  259. $wareki = $this->BcTime->convertToWareki($this->value($fieldName));
  260. $w = $this->BcTime->wareki($wareki);
  261. $wyear = $this->BcTime->wyear($wareki);
  262. $selected = $w.'-'.$wyear;
  263. } elseif ($selected === false) {
  264. $selected = null;
  265. } elseif(strpos($selected, '-')===false) {
  266. $wareki = $this->BcTime->convertToWareki($this->value($fieldName));
  267. if($wareki) {
  268. $w = $this->BcTime->wareki($wareki);
  269. $wyear = $this->BcTime->wyear($wareki);
  270. $selected = $w.'-'.$wyear;
  271. } else {
  272. $selected = null;
  273. }
  274. }
  275. $yearOptions = array('min' => $minYear, 'max' => $maxYear);
  276. return $this->hidden($fieldName.".wareki", array('value'=>true)).
  277. $this->select(
  278. $fieldName . ".year", $this->__generateOptions('wyear', $yearOptions),
  279. $selected, $attributes, $showEmpty
  280. );
  281. }
  282. /**
  283. * コントロールソースを取得する
  284. * Model側でメソッドを用意しておく必要がある
  285. *
  286. * @param string $field フィールド名
  287. * @param array $options
  288. * @return array コントロールソース
  289. * @access public
  290. */
  291. function getControlSource($field,$options = array()) {
  292. $count = preg_match_all('/\./is',$field,$matches);
  293. if($count == 1) {
  294. list($modelName,$field) = explode('.',$field);
  295. } elseif ($count == 2){
  296. list($plugin,$modelName,$field) = explode('.',$field);
  297. $modelName = $plugin.'.'.$modelName;
  298. }
  299. if(empty($modelName)) {
  300. $modelName = $this->model();
  301. }
  302. if(ClassRegistry::isKeySet($modelName)){
  303. $model =& ClassRegistry::getObject($modelName);
  304. }else{
  305. $model =& ClassRegistry::init($modelName);
  306. }
  307. if($model) {
  308. return $model->getControlSource($field,$options);
  309. }else {
  310. return false;
  311. }
  312. }
  313. /**
  314. * モデルよりリストを生成する
  315. *
  316. * @param string $modelName
  317. * @param mixed $conditions
  318. * @param mixed $fields
  319. * @param mixed $order
  320. * @return mixed リストまたは、false
  321. * @access public
  322. */
  323. function generateList($modelName,$conditions = array(),$fields = array(),$order = array()) {
  324. $model =& ClassRegistry::getObject($modelName);
  325. if($fields) {
  326. list($idField,$displayField) = $fields;
  327. }else {
  328. $idField = 'id';
  329. $displayField = $model->getDisplayField();
  330. $fields = array($idField,$displayField);
  331. }
  332. $list = $model->find( 'all', array('conditions' => $conditions, 'fields' => $fields, 'order' => $order));
  333. if($list) {
  334. return Set::combine($list,"{n}.".$modelName.".".$idField,"{n}.".$modelName.".".$displayField);
  335. }else {
  336. return null;
  337. }
  338. }
  339. /**
  340. * JsonList
  341. *
  342. * @param string $field フィールド文字列
  343. * @param string $attributes
  344. * @return array 属性
  345. * @access public
  346. */
  347. function jsonList($field,$attributes) {
  348. am(array("imgSrc"=>"","ajaxAddAction"=>"","ajaxDelAction"=>""),$attributes);
  349. // JsonDb用Hiddenタグ
  350. $out = $this->hidden('Json.'.$field.'.db');
  351. // 追加テキストボックス
  352. $out .= $this->text('Json.'.$field.'.name');
  353. // 追加ボタン
  354. $out .= $this->button('追加',array('id'=>'btnAdd'.$field));
  355. // リスト表示用ビュー
  356. $out .= '<div id="Json'.$field.'View"></div>';
  357. // javascript
  358. $out .= '<script type="text/javascript"><!--'."\n".
  359. 'jQuery(function(){'."\n".
  360. 'var json_List = new JsonList({"dbId":"Json'.$field.'Db","viewId":"JsonTagView","addButtonId":"btnAdd'.$field.'",'."\n".
  361. '"deleteButtonType":"img","deleteButtonSrc":"'.$attributes['imgSrc'].'","deleteButtonRollOver":true,'."\n".
  362. '"ajaxAddAction":"'.$attributes['ajaxAddAction'].'",'."\n".
  363. '"ajaxDelAction":"'.$attributes['ajaxDelAction'].'"});'."\n".
  364. 'json_List.loadData();'."\n".
  365. '});'."\n".
  366. '//--></script>';
  367. return $out;
  368. }
  369. /**
  370. * カレンダーコントロール付きのテキストフィールド
  371. * jquery-ui-1.7.2 必須
  372. *
  373. * @param string フィールド文字列
  374. * @param array HTML属性
  375. * @return string html
  376. * @access public
  377. */
  378. function datepicker($fieldName, $attributes = array()) {
  379. if (!isset($attributes['value'])) {
  380. $value = $this->value($fieldName);
  381. }else {
  382. $value = $attributes['value'];
  383. }
  384. if($value) {
  385. $attributes['value'] = date('Y/m/d',strtotime($this->BcTime->format('Y/m/d',$value)));
  386. }else {
  387. unset($attributes['value']);
  388. }
  389. $this->setEntity($fieldName);
  390. $id = $this->domId($fieldName);
  391. // テキストボックス
  392. $input = $this->text($fieldName,$attributes);
  393. // javascript
  394. $script = <<< DOC_END
  395. <script type="text/javascript">
  396. <!--
  397. jQuery(function($){
  398. $("#{$id}").datepicker();
  399. });
  400. //-->
  401. </script>
  402. DOC_END;
  403. $out = $input."\n".$script;
  404. return $out;
  405. }
  406. /**
  407. * 日付カレンダーと時間フィールド
  408. *
  409. * @param string $fieldName
  410. * @param array $attributes
  411. * @return string
  412. * @access public
  413. */
  414. function dateTimePicker($fieldName, $attributes = array()) {
  415. $timeAttributes = array('size'=>8,'maxlength'=>8);
  416. if (!isset($attributes['value'])) {
  417. $value = $this->value($fieldName);
  418. }else {
  419. $value = $attributes['value'];
  420. unset($attributes['value']);
  421. }
  422. if($value && $value != '0000-00-00 00:00:00') {
  423. $dateValue = date('Y/m/d',strtotime($value));
  424. $timeValue = date('H:i:s',strtotime($value));
  425. $attributes['value']=$dateValue;
  426. $timeAttributes['value']=$timeValue;
  427. }
  428. $dateTag = $this->datepicker($fieldName.'_date', $attributes);
  429. $timeTag = $this->text($fieldName.'_time', $timeAttributes);
  430. $hiddenTag = $this->hidden($fieldName, array('value'=>$value));
  431. $domId = $this->domId();
  432. $_script = <<< DOC_END
  433. $(function(){
  434. $("#{$domId}Date").change({$domId}ChangeResultHandler);
  435. $("#{$domId}Time").change({$domId}ChangeResultHandler);
  436. function {$domId}ChangeResultHandler(){
  437. var value = $("#{$domId}Date").val().replace(/\//g, '-');
  438. if($("#{$domId}Time").val()) {
  439. value += ' '+$("#{$domId}Time").val();
  440. }
  441. $("#{$domId}").val(value);
  442. if(this.id.replace('{$domId}','') == 'Date') {
  443. if($("#{$domId}Date").val() && !$("#{$domId}Time").val()) {
  444. $("#{$domId}Time").val('00:00:00');
  445. }
  446. }
  447. }
  448. });
  449. DOC_END;
  450. $script = $this->Javascript->codeBlock($_script,array('inline'=>false));
  451. return $dateTag.$timeTag.$hiddenTag;
  452. }
  453. /**
  454. * Generates option lists for common <select /> menus
  455. *
  456. * @param string $name
  457. * @param array $options
  458. * @return array option lists
  459. * @access private
  460. */
  461. function __generateOptions($name, $options = array()) {
  462. if (!empty($this->options[$name])) {
  463. return $this->options[$name];
  464. }
  465. $data = array();
  466. switch ($name) {
  467. case 'minute':
  468. if (isset($options['interval'])) {
  469. $interval = $options['interval'];
  470. } else {
  471. $interval = 1;
  472. }
  473. $i = 0;
  474. while ($i < 60) {
  475. $data[$i] = sprintf('%02d', $i);
  476. $i += $interval;
  477. }
  478. break;
  479. case 'hour':
  480. for ($i = 1; $i <= 12; $i++) {
  481. $data[sprintf('%02d', $i)] = $i;
  482. }
  483. break;
  484. case 'hour24':
  485. for ($i = 0; $i <= 23; $i++) {
  486. $data[sprintf('%02d', $i)] = $i;
  487. }
  488. break;
  489. case 'meridian':
  490. $data = array('am' => 'am', 'pm' => 'pm');
  491. break;
  492. case 'day':
  493. $min = 1;
  494. $max = 31;
  495. if (isset($options['min'])) {
  496. $min = $options['min'];
  497. }
  498. if (isset($options['max'])) {
  499. $max = $options['max'];
  500. }
  501. for ($i = $min; $i <= $max; $i++) {
  502. $data[sprintf('%02d', $i)] = $i;
  503. }
  504. break;
  505. case 'month':
  506. if ($options['monthNames']) {
  507. $data['01'] = __('January', true);
  508. $data['02'] = __('February', true);
  509. $data['03'] = __('March', true);
  510. $data['04'] = __('April', true);
  511. $data['05'] = __('May', true);
  512. $data['06'] = __('June', true);
  513. $data['07'] = __('July', true);
  514. $data['08'] = __('August', true);
  515. $data['09'] = __('September', true);
  516. $data['10'] = __('October', true);
  517. $data['11'] = __('November', true);
  518. $data['12'] = __('December', true);
  519. } else {
  520. for ($m = 1; $m <= 12; $m++) {
  521. $data[sprintf("%02s", $m)] = strftime("%m", mktime(1, 1, 1, $m, 1, 1999));
  522. }
  523. }
  524. break;
  525. case 'year':
  526. $current = intval(date('Y'));
  527. if (!isset($options['min'])) {
  528. $min = $current - 20;
  529. } else {
  530. $min = $options['min'];
  531. }
  532. if (!isset($options['max'])) {
  533. $max = $current + 20;
  534. } else {
  535. $max = $options['max'];
  536. }
  537. if ($min > $max) {
  538. list($min, $max) = array($max, $min);
  539. }
  540. for ($i = $min; $i <= $max; $i++) {
  541. $data[$i] = $i;
  542. }
  543. $data = array_reverse($data, true);
  544. break;
  545. // >>> CUSTOMIZE ADD 2011/01/11 ryuring 和暦対応
  546. case 'wyear':
  547. $current = intval(date('Y'));
  548. if (!isset($options['min'])) {
  549. $min = $current - 20;
  550. } else {
  551. $min = $options['min'];
  552. }
  553. if (!isset($options['max'])) {
  554. $max = $current + 20;
  555. } else {
  556. $max = $options['max'];
  557. }
  558. if ($min > $max) {
  559. list($min, $max) = array($max, $min);
  560. }
  561. for ($i = $min; $i <= $max; $i++) {
  562. $wyears = $this->BcTime->convertToWarekiYear($i);
  563. if($wyears) {
  564. foreach($wyears as $value) {
  565. list($w,$year) = split('-', $value);
  566. $data[$value] = $this->BcTime->nengo($w).' '.$year;
  567. }
  568. }
  569. }
  570. $data = array_reverse($data, true);
  571. break;
  572. // <<<
  573. }
  574. $this->__options[$name] = $data;
  575. return $this->__options[$name];
  576. }
  577. /**
  578. * Creates a checkbox input widget.
  579. * MODIFIED 2008/10/24 egashira
  580. * hiddenタグを出力しないオプションを追加
  581. *
  582. * @param string $fieldNamem Name of a field, like this "Modelname.fieldname"
  583. * @param array $options Array of HTML attributes.
  584. * 'value' - the value of the checkbox
  585. * 'checked' - boolean indicate that this checkbox is checked.
  586. * @todo Right now, automatically setting the 'checked' value is dependent on whether or not the
  587. * checkbox is bound to a model. This should probably be re-evaluated in future versions.
  588. * @return string An HTML text input element
  589. * @access public
  590. */
  591. function checkbox($fieldName, $options = array()) {
  592. // CUSTOMIZE ADD 2011/05/07 ryuring
  593. // >>> hiddenをデフォルトオプションに追加
  594. $options = array_merge(array('hidden' => true), $options);
  595. $hidden = $options['hidden'];
  596. unset($options['hidden']);
  597. // <<<
  598. $options = $this->_initInputField($fieldName, $options);
  599. $value = current($this->value());
  600. if (!isset($options['value']) || empty($options['value'])) {
  601. $options['value'] = 1;
  602. } elseif (
  603. (!isset($options['checked']) && !empty($value) && $value === $options['value']) ||
  604. !empty($options['checked'])
  605. ) {
  606. $options['checked'] = 'checked';
  607. }
  608. // CUSTOMIZE MODIFY 2011/05/07 ryuring
  609. // >>> hiddenオプションがある場合のみ、hiddenタグを出力
  610. /*$hiddenOptions = array(
  611. 'id' => $options['id'] . '_', 'name' => $options['name'],
  612. 'value' => '0', 'secure' => false
  613. );
  614. if (isset($options['disabled']) && $options['disabled'] == true) {
  615. $hiddenOptions['disabled'] = 'disabled';
  616. }
  617. $output = $this->hidden($fieldName, $hiddenOptions);*/
  618. // ---
  619. if($hidden) {
  620. $hiddenOptions = array(
  621. 'id' => $options['id'] . '_', 'name' => $options['name'],
  622. 'value' => '0', 'secure' => false
  623. );
  624. if (isset($options['disabled']) && $options['disabled'] == true) {
  625. $hiddenOptions['disabled'] = 'disabled';
  626. }
  627. $output = $this->hidden($fieldName, $hiddenOptions);
  628. }else {
  629. $output='';
  630. }
  631. // <<<
  632. // CUSTOMIZE MODIFY 2011/05/07 ryuring
  633. // >>> label を追加
  634. /*return $this->output($output . sprintf(
  635. $this->Html->tags['checkbox'],
  636. $options['name'],
  637. $this->_parseAttributes($options, array('name'), null, ' ')
  638. ));*/
  639. // ---
  640. if(!empty($options['label'])) {
  641. $label = '&nbsp;'.parent::label($fieldName, $options['label']);
  642. }else {
  643. $label = '';
  644. }
  645. return $this->output($output . sprintf(
  646. $this->Html->tags['checkbox'],
  647. $options['name'],
  648. $this->_parseAttributes($options, array('name'), null, ' ')
  649. )).$label;
  650. // <<<
  651. }
  652. /**
  653. * Returns an array of formatted OPTION/OPTGROUP elements
  654. *
  655. * @return array
  656. * @access private
  657. */
  658. function __selectOptions($elements = array(), $selected = null, $parents = array(), $showParents = null, $attributes = array()) {
  659. $select = array();
  660. $attributes = array_merge(array('escape' => true, 'style' => null), $attributes);
  661. $selectedIsEmpty = ($selected === '' || $selected === null);
  662. $selectedIsArray = is_array($selected);
  663. foreach ($elements as $name => $title) {
  664. $htmlOptions = array();
  665. if (is_array($title) && (!isset($title['name']) || !isset($title['value']))) {
  666. if (!empty($name)) {
  667. if ($attributes['style'] === 'checkbox') {
  668. $select[] = $this->Html->tags['fieldsetend'];
  669. } else {
  670. $select[] = $this->Html->tags['optiongroupend'];
  671. }
  672. $parents[] = $name;
  673. }
  674. $select = array_merge($select, $this->__selectOptions(
  675. $title, $selected, $parents, $showParents, $attributes
  676. ));
  677. if (!empty($name)) {
  678. if ($attributes['style'] === 'checkbox') {
  679. $select[] = sprintf($this->Html->tags['fieldsetstart'], $name);
  680. } else {
  681. $select[] = sprintf($this->Html->tags['optiongroup'], $name, '');
  682. }
  683. }
  684. $name = null;
  685. } elseif (is_array($title)) {
  686. $htmlOptions = $title;
  687. $name = $title['value'];
  688. $title = $title['name'];
  689. unset($htmlOptions['name'], $htmlOptions['value']);
  690. }
  691. if ($name !== null) {
  692. if ((!$selectedIsEmpty && $selected == $name) || ($selectedIsArray && in_array($name, $selected))) {
  693. if ($attributes['style'] === 'checkbox') {
  694. $htmlOptions['checked'] = true;
  695. } else {
  696. $htmlOptions['selected'] = 'selected';
  697. }
  698. }
  699. if ($showParents || (!in_array($title, $parents))) {
  700. $title = ($attributes['escape']) ? h($title) : $title;
  701. if ($attributes['style'] === 'checkbox') {
  702. $htmlOptions['value'] = $name;
  703. $tagName = Inflector::camelize(
  704. $this->model() . '_' . $this->field().'_'.Inflector::underscore($name)
  705. );
  706. $htmlOptions['id'] = $tagName;
  707. $label = array('for' => $tagName);
  708. if (isset($htmlOptions['checked']) && $htmlOptions['checked'] === true) {
  709. $label['class'] = 'selected';
  710. }
  711. list($name) = array_values($this->__name());
  712. if (empty($attributes['class'])) {
  713. $attributes['class'] = 'checkbox';
  714. }
  715. $label = $this->label(null, $title, $label);
  716. $item = sprintf(
  717. $this->Html->tags['checkboxmultiple'], $name,
  718. $this->Html->_parseAttributes($htmlOptions)
  719. );
  720. // checkboxのdivを外せるオプションを追加
  721. if(isset($attributes['div']) && $attributes['div']===false) {
  722. $select[] = $item.$label;
  723. }else {
  724. $select[] = $this->Html->div($attributes['class'], $item . $label);
  725. }
  726. } else {
  727. $select[] = sprintf(
  728. $this->Html->tags['selectoption'],
  729. $name, $this->Html->_parseAttributes($htmlOptions), $title
  730. );
  731. }
  732. }
  733. }
  734. }
  735. return array_reverse($select, true);
  736. }
  737. /**
  738. * Returns a formatted SELECT element.
  739. * Attributes:
  740. *
  741. * - 'showParents' - If included in the array and set to true, an additional option element
  742. * will be added for the parent of each option group.
  743. * - 'multiple' - show a multiple select box. If set to 'checkbox' multiple checkboxes will be
  744. * created instead.
  745. *
  746. * @param string $fieldName Name attribute of the SELECT
  747. * @param array $options Array of the OPTION elements (as 'value'=>'Text' pairs) to be used in the
  748. * SELECT element
  749. * @param mixed $selected The option selected by default. If null, the default value
  750. * from POST data will be used when available.
  751. * @param array $attributes The HTML attributes of the select element.
  752. * @param mixed $showEmpty If true, the empty select option is shown. If a string,
  753. * that string is displayed as the empty element.
  754. * @return string Formatted SELECT element
  755. * @access public
  756. */
  757. function select($fieldName, $options = array(), $selected = null, $attributes = array(), $showEmpty = '') {
  758. $select = array();
  759. $showParents = false;
  760. $escapeOptions = true;
  761. $style = null;
  762. $tag = null;
  763. if (isset($attributes['escape'])) {
  764. $escapeOptions = $attributes['escape'];
  765. unset($attributes['escape']);
  766. }
  767. $attributes = $this->_initInputField($fieldName, array_merge(
  768. (array)$attributes, array('secure' => false)
  769. ));
  770. if (is_string($options) && isset($this->__options[$options])) {
  771. $options = $this->__generateOptions($options);
  772. } elseif (!is_array($options)) {
  773. $options = array();
  774. }
  775. if (isset($attributes['type'])) {
  776. unset($attributes['type']);
  777. }
  778. if (in_array('showParents', $attributes)) {
  779. $showParents = true;
  780. unset($attributes['showParents']);
  781. }
  782. if (!isset($selected)) {
  783. $selected = $attributes['value'];
  784. }
  785. if (isset($attributes) && array_key_exists('multiple', $attributes)) {
  786. $style = ($attributes['multiple'] === 'checkbox') ? 'checkbox' : null;
  787. $template = ($style) ? 'checkboxmultiplestart' : 'selectmultiplestart';
  788. $tag = $this->Html->tags[$template];
  789. // >>> CUSTOMIZE MODIFY 2011/01/21 ryuring
  790. // multiplecheckboxの場合にhiddenをつけないオプションを追加
  791. //$select[] = $this->hidden(null, array('value' => '', 'id' => null, 'secure' => false));
  792. // ---
  793. if(!isset($attributes['hidden']) || $attributes['hidden']!==false) {
  794. $select[] = $this->hidden(null, array('value' => '', 'id' => null, 'secure' => false));
  795. }
  796. // <<<
  797. } else {
  798. $tag = $this->Html->tags['selectstart'];
  799. }
  800. if (!empty($tag) || isset($template)) {
  801. $this->__secure();
  802. $select[] = sprintf($tag, $attributes['name'], $this->_parseAttributes(
  803. $attributes, array('name', 'value'))
  804. );
  805. }
  806. $emptyMulti = (
  807. $showEmpty !== null && $showEmpty !== false && !(
  808. empty($showEmpty) && (isset($attributes) &&
  809. array_key_exists('multiple', $attributes))
  810. )
  811. );
  812. if ($emptyMulti) {
  813. $showEmpty = ($showEmpty === true) ? '' : $showEmpty;
  814. $options = array_reverse($options, true);
  815. $options[''] = $showEmpty;
  816. $options = array_reverse($options, true);
  817. }
  818. // divを追加すぐ下の__selectOptionsのみで利用
  819. if(isset($attributes['div'])) {
  820. if($attributes['div']=='false') {
  821. $attributes['div'] = false;
  822. }
  823. $div = $attributes['div'];
  824. }else {
  825. $div = null;
  826. }
  827. $_select = $this->__selectOptions(
  828. array_reverse($options, true),
  829. $selected,
  830. array(),
  831. $showParents,
  832. array('escape' => $escapeOptions, 'style' => $style, 'div' => $div)
  833. );
  834. if(!empty($attributes['separator'])) {
  835. $separator = $attributes['separator']."\n";
  836. }else {
  837. $separator = "\n";
  838. }
  839. $select[] = implode($separator, $_select);
  840. $template = ($style == 'checkbox') ? 'checkboxmultipleend' : 'selectend';
  841. $select[] = $this->Html->tags[$template];
  842. // 解除ボタンを追加(jQuery必須)
  843. if(isset($attributes['multiple']) && $attributes['multiple'] === true) {
  844. list($model,$field) = explode(".",$fieldName);
  845. $tagName = Inflector::camelize($model . '_' . $field);
  846. $out = '<script type="text/javascript">';
  847. $out .= "jQuery(document).ready(function() {";
  848. $out .= "jQuery('#".$tagName."Clear').click(function(){";
  849. $out .= "jQuery('#".$tagName."').val('');";
  850. $out .= "});";
  851. $out .= "});";
  852. $out .= "</script>";
  853. $out .= '<input type="button" name="'.$tagName.'Clear" id="'.$tagName.'Clear" value=" 解 除 " />';
  854. return $this->output(implode("\n", $select))."<br />".$out;
  855. }else {
  856. return $this->output(implode("\n", $select));
  857. }
  858. }
  859. /**
  860. * 文字列保存用複数選択コントロール
  861. *
  862. * @param string $fieldName
  863. * @param array $options
  864. * @param mixed $selected
  865. * @param array $attributes
  866. * @param mixed $showEmpty
  867. * @return string
  868. * @access public
  869. */
  870. function selectText($fieldName, $options = array(), $selected = null, $attributes = array(), $showEmpty = '') {
  871. $_attributes = array('separator'=>'<br />','quotes'=>true);
  872. $attributes = Set::merge($_attributes,$attributes);
  873. $quotes = $attributes['quotes'];
  874. unset($attributes['quotes']);
  875. $_options = $this->_initInputField($fieldName, $options);
  876. if(empty($attributes['multiple'])) $attributes['multiple'] = 'checkbox';
  877. $id = $_options['id'];
  878. $_id = $_options['id'].'_';
  879. $name = $_options['name'];
  880. $out = '<div id="'.$_id.'">'.$this->select($fieldName.'_', $options, $selected, $attributes, $showEmpty).'</div>';
  881. $out .= $this->hidden($fieldName);
  882. $script = <<< DOC_END
  883. $(document).ready(function() {
  884. aryValue = $("#{$id}").val().replace(/\'/g,"").split(",");
  885. for(key in aryValue){
  886. var value = aryValue[key];
  887. $("#"+camelize("{$id}_"+value)).attr('checked',true);
  888. }
  889. $("#{$_id} input[type=checkbox]").change(function(){
  890. var aryValue = [];
  891. $("#{$_id} input[type=checkbox]").each(function(key,value){
  892. if($(this).attr('checked')){
  893. aryValue.push("'"+$(this).val()+"'");
  894. }
  895. });
  896. $("#{$id}").val(aryValue.join(','));
  897. });
  898. });
  899. DOC_END;
  900. $out .= $this->Javascript->codeBlock($script);
  901. return $out;
  902. }
  903. /**
  904. * Creates a hidden input field.
  905. *
  906. * @param string $fieldName Name of a field, in the form"Modelname.fieldname"
  907. * @param array $options Array of HTML attributes.
  908. * @return string
  909. * @access public
  910. */
  911. function hidden($fieldName, $options = array()) {
  912. $secure = true;
  913. if (isset($options['secure'])) {
  914. $secure = $options['secure'];
  915. unset($options['secure']);
  916. }
  917. // 2010/07/24 ryuring
  918. // セキュリティコンポーネントのトークン生成の仕様として、
  919. // ・hiddenタグ以外はフィールド情報のみ
  920. // ・hiddenタグはフィールド情報と値
  921. // をキーとして生成するようになっている。
  922. // その場合、生成の元のなる値は、multipleを想定されておらず、先頭の値のみとなるが
  923. // multiple な hiddenタグの場合、送信される値は配列で送信されるので値違いで認証がとおらない。
  924. // という事で、multiple の場合は、あくまでhiddenタグ以外のようにフィールド情報のみを
  925. // トークンのキーとする事で認証を通すようにする。
  926. // >>> ADD
  927. if(!empty($options['multiple'])){
  928. $secure = false;
  929. $this->__secure();
  930. }
  931. // <<<
  932. $options = $this->_initInputField($fieldName, array_merge(
  933. $options, array('secure' => false)
  934. ));
  935. $model = $this->model();
  936. if ($fieldName !== '_method' && $model !== '_Token' && $secure) {
  937. $this->__secure(null, '' . $options['value']);
  938. }
  939. // CUSTOMIZE 2010/07/24 ryuring
  940. // 配列用のhiddenタグを出力できるオプションを追加
  941. // CUSTOMIZE 2010/08/01 ryuring
  942. // class属性を指定できるようにした
  943. // CUSTOMIZE 2011/03/11 ryuring
  944. // multiple で送信する値が配列の添字となっていたので配列の値に変更した
  945. // >>> ADD
  946. $multiple = false;
  947. $value = '';
  948. if(!empty($options['multiple'])){
  949. $multiple = true;
  950. $tagType = 'hiddenmultiple';
  951. $options['id'] = null;
  952. if (!isset($options['value'])) {
  953. $value = $this->value($fieldName);
  954. }else {
  955. $value = $options['value'];
  956. }
  957. if(is_array($value) && !$value) {
  958. unset($options['value']);
  959. }
  960. unset($options['multiple']);
  961. } else {
  962. $tagType = 'hidden';
  963. }
  964. // <<<
  965. // >>> MODIFY
  966. /*return $this->output(sprintf(
  967. $this->Html->tags['hidden'],
  968. $options['name'],
  969. $this->_parseAttributes($options, array('name', 'class'), '', ' ')
  970. ));*/
  971. // ---
  972. if($multiple && is_array($value)) {
  973. $out = array();
  974. foreach($value as $_value) {
  975. $options['value'] = $_value;
  976. $out[] = $this->output(sprintf(
  977. $this->Html->tags[$tagType],
  978. $options['name'],
  979. $this->_parseAttributes($options, array('name'), '', ' ')
  980. ));
  981. }
  982. return implode("\n", $out);
  983. } else {
  984. return $this->output(sprintf(
  985. $this->Html->tags[$tagType],
  986. $options['name'],
  987. $this->_parseAttributes($options, array('name'), '', ' ')
  988. ));
  989. }
  990. // <<<
  991. }
  992. /**
  993. * CKEditorを出力する
  994. *
  995. * @param string $fieldName
  996. * @param array $options
  997. * @param array $editorOptions
  998. * @param array $styles
  999. * @return string
  1000. * @access public
  1001. */
  1002. function ckeditor($fieldName, $options = array(), $editorOptions = array(), $styles = array()) {
  1003. $_options = array('type'=>'textarea');
  1004. $options = am($_options,$options);
  1005. $method = $options['type'];
  1006. return $this->BcCkeditor->{$method}($fieldName, $options, $editorOptions, $styles, $this);
  1007. }
  1008. /**
  1009. * create
  1010. * フック用にラッピング
  1011. *
  1012. * @param array $model
  1013. * @param array $options
  1014. * @return string
  1015. * @access public
  1016. */
  1017. function create($model = null, $options = array()) {
  1018. $options = $this->executeHook('beforeFormCreate', $model, $options);
  1019. $out = parent::create($model, $options);
  1020. return $this->executeHook('afterFormCreate', $out);
  1021. }
  1022. /**
  1023. * end
  1024. * フック用にラッピング
  1025. *
  1026. * @param array $options
  1027. * @return string
  1028. * @access public
  1029. */
  1030. function end($options = null) {
  1031. $options = $this->executeHook('beforeFormEnd', $options);
  1032. $out = parent::end($options);
  1033. return $this->executeHook('afterFormEnd', $out);
  1034. }
  1035. /**
  1036. * Generates a form input element complete with label and wrapper div
  1037. *
  1038. * Options - See each field type method for more information. Any options that are part of
  1039. * $attributes or $options for the different type methods can be included in $options for input().
  1040. *
  1041. * - 'type' - Force the type of widget you want. e.g. ```type => 'select'```
  1042. * - 'label' - control the label
  1043. * - 'div' - control the wrapping div element
  1044. * - 'options' - for widgets that take options e.g. radio, select
  1045. * - 'error' - control the error message that is produced
  1046. *
  1047. * @param string $fieldName This should be "Modelname.fieldname"
  1048. * @param array $options Each type of input takes different options.
  1049. * @return string Completed form widget
  1050. */
  1051. function input($fieldName, $options = array()) {
  1052. $options = $this->executeHook('beforeFormInput', $fieldName, $options);
  1053. $type = '';
  1054. if(isset($options['type'])) {
  1055. $type = $options['type'];
  1056. }
  1057. if(!isset($options['div'])) {
  1058. $options['div'] = false;
  1059. }
  1060. if(!isset($options['error'])) {
  1061. $options['error'] = false;
  1062. }
  1063. switch($type) {
  1064. case 'text':
  1065. default :
  1066. if(!isset($options['label'])) {
  1067. $options['label'] = false;
  1068. }
  1069. break;
  1070. case 'radio':
  1071. if(!isset($options['legend'])) {
  1072. $options['legend'] = false;
  1073. }
  1074. if(!isset($options['separator'])) {
  1075. $options['separator'] = ' ';
  1076. }
  1077. break;
  1078. }
  1079. $out = parent::input($fieldName, $options);
  1080. /* カウンター */
  1081. if(!empty($options['counter'])) {
  1082. $domId = $this->domId($fieldName, $options);
  1083. $counter = '<span id="'.$domId.'Counter'.'" class="size-counter"></span>';
  1084. $script = '$("#'.$domId.'").keyup(countSize);$("#'.$domId.'").keyup();';
  1085. if(!$this->sizeCounterFunctionLoaded) {
  1086. $script .= <<< DOC_END
  1087. function countSize() {
  1088. var len = $(this).val().length;
  1089. var maxlen = $(this).attr('maxlength');
  1090. if(!maxlen || maxlen == -1){
  1091. maxlen = '-';
  1092. }
  1093. $("#"+$(this).attr('id')+'Counter').html(len+'/<small>'+maxlen+'</small>');
  1094. }
  1095. DOC_END;
  1096. $this->sizeCounterFunctionLoaded = true;
  1097. }
  1098. $out = $out.$counter.$this->Javascript->codeBlock($script);
  1099. }
  1100. return $this->executeHook('afterFormInput', $fieldName, $out);
  1101. }
  1102. /**
  1103. * 日付タグ
  1104. * 和暦実装
  1105. * TODO 未実装
  1106. */
  1107. /*function dateTime($fieldName, $dateFormat = 'DMY', $timeFormat = '12', $selected = null, $attributes = array(), $showEmpty = true) {
  1108. if($dateFormat == "WYMD"){
  1109. $this->options['month'] = $this->getWarekiMonthes();
  1110. $this->options['day'] = $this->getWarekiDays();
  1111. $this->options['year'] = $this->getWarekiYears($attributes['minYear'],$attributes['maxYear']);
  1112. $dateFormat = "YMD";
  1113. }
  1114. return parent::dateTime($fieldName, $dateFormat, $timeFormat, $selected, $attributes, $showEmpty);
  1115. }*/
  1116. }
  1117. ?>