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