CHtml.php 111 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818
  1. <?php
  2. /**
  3. * CHtml class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CHtml is a static class that provides a collection of helper methods for creating HTML views.
  12. *
  13. * Nearly all of the methods in this class allow setting additional html attributes for the html
  14. * tags they generate. You can specify for example. 'class', 'style' or 'id' for an html element.
  15. * For example when using <code>array('class' => 'my-class', 'target' => '_blank')</code> as htmlOptions
  16. * it will result in the html attributes rendered like this: <code>class="my-class" target="_blank"</code>.
  17. *
  18. * @author Qiang Xue <qiang.xue@gmail.com>
  19. * @package system.web.helpers
  20. * @since 1.0
  21. */
  22. class CHtml
  23. {
  24. const ID_PREFIX='yt';
  25. /**
  26. * @var string the CSS class for displaying error summaries (see {@link errorSummary}).
  27. */
  28. public static $errorSummaryCss='errorSummary';
  29. /**
  30. * @var string the CSS class for displaying error messages (see {@link error}).
  31. */
  32. public static $errorMessageCss='errorMessage';
  33. /**
  34. * @var string the CSS class for highlighting error inputs. Form inputs will be appended
  35. * with this CSS class if they have input errors.
  36. */
  37. public static $errorCss='error';
  38. /**
  39. * @var string the tag name for the error container tag. Defaults to 'div'.
  40. * @since 1.1.13
  41. */
  42. public static $errorContainerTag='div';
  43. /**
  44. * @var string the CSS class for required labels. Defaults to 'required'.
  45. * @see label
  46. */
  47. public static $requiredCss='required';
  48. /**
  49. * @var string the HTML code to be prepended to the required label.
  50. * @see label
  51. */
  52. public static $beforeRequiredLabel='';
  53. /**
  54. * @var string the HTML code to be appended to the required label.
  55. * @see label
  56. */
  57. public static $afterRequiredLabel=' <span class="required">*</span>';
  58. /**
  59. * @var integer the counter for generating automatic input field names.
  60. */
  61. public static $count=0;
  62. /**
  63. * Sets the default style for attaching jQuery event handlers.
  64. *
  65. * If set to true (default), event handlers are delegated.
  66. * Event handlers are attached to the document body and can process events
  67. * from descendant elements that are added to the document at a later time.
  68. *
  69. * If set to false, event handlers are directly bound.
  70. * Event handlers are attached directly to the DOM element, that must already exist
  71. * on the page. Elements injected into the page at a later time will not be processed.
  72. *
  73. * You can override this setting for a particular element by setting the htmlOptions delegate attribute
  74. * (see {@link clientChange}).
  75. *
  76. * For more information about attaching jQuery event handler see {@link http://api.jquery.com/on/}
  77. * @since 1.1.9
  78. * @see clientChange
  79. */
  80. public static $liveEvents=true;
  81. /**
  82. * @var boolean whether to close single tags. Defaults to true. Can be set to false for HTML5.
  83. * @since 1.1.13
  84. */
  85. public static $closeSingleTags=true;
  86. /**
  87. * @var boolean whether to render special attributes value. Defaults to true. Can be set to false for HTML5.
  88. * @since 1.1.13
  89. */
  90. public static $renderSpecialAttributesValue=true;
  91. /**
  92. * @var callback the generator used in the {@link CHtml::modelName()} method.
  93. * @since 1.1.14
  94. */
  95. private static $_modelNameConverter;
  96. /**
  97. * Encodes special characters into HTML entities.
  98. * The {@link CApplication::charset application charset} will be used for encoding.
  99. * @param string $text data to be encoded
  100. * @return string the encoded data
  101. * @see http://www.php.net/manual/en/function.htmlspecialchars.php
  102. */
  103. public static function encode($text)
  104. {
  105. return htmlspecialchars($text,ENT_QUOTES,Yii::app()->charset);
  106. }
  107. /**
  108. * Decodes special HTML entities back to the corresponding characters.
  109. * This is the opposite of {@link encode()}.
  110. * @param string $text data to be decoded
  111. * @return string the decoded data
  112. * @see http://www.php.net/manual/en/function.htmlspecialchars-decode.php
  113. * @since 1.1.8
  114. */
  115. public static function decode($text)
  116. {
  117. return htmlspecialchars_decode($text,ENT_QUOTES);
  118. }
  119. /**
  120. * Encodes special characters in an array of strings into HTML entities.
  121. * Both the array keys and values will be encoded if needed.
  122. * If a value is an array, this method will also encode it recursively.
  123. * The {@link CApplication::charset application charset} will be used for encoding.
  124. * @param array $data data to be encoded
  125. * @return array the encoded data
  126. * @see http://www.php.net/manual/en/function.htmlspecialchars.php
  127. */
  128. public static function encodeArray($data)
  129. {
  130. $d=array();
  131. foreach($data as $key=>$value)
  132. {
  133. if(is_string($key))
  134. $key=htmlspecialchars($key,ENT_QUOTES,Yii::app()->charset);
  135. if(is_string($value))
  136. $value=htmlspecialchars($value,ENT_QUOTES,Yii::app()->charset);
  137. elseif(is_array($value))
  138. $value=self::encodeArray($value);
  139. $d[$key]=$value;
  140. }
  141. return $d;
  142. }
  143. /**
  144. * Generates an HTML element.
  145. * @param string $tag the tag name
  146. * @param array $htmlOptions the element attributes. The values will be HTML-encoded using {@link encode()}.
  147. * If an 'encode' attribute is given and its value is false,
  148. * the rest of the attribute values will NOT be HTML-encoded.
  149. * Since version 1.1.5, attributes whose value is null will not be rendered.
  150. * @param mixed $content the content to be enclosed between open and close element tags. It will not be HTML-encoded.
  151. * If false, it means there is no body content.
  152. * @param boolean $closeTag whether to generate the close tag.
  153. * @return string the generated HTML element tag
  154. */
  155. public static function tag($tag,$htmlOptions=array(),$content=false,$closeTag=true)
  156. {
  157. $html='<' . $tag . self::renderAttributes($htmlOptions);
  158. if($content===false)
  159. return $closeTag && self::$closeSingleTags ? $html.' />' : $html.'>';
  160. else
  161. return $closeTag ? $html.'>'.$content.'</'.$tag.'>' : $html.'>'.$content;
  162. }
  163. /**
  164. * Generates an open HTML element.
  165. * @param string $tag the tag name
  166. * @param array $htmlOptions the element attributes. The values will be HTML-encoded using {@link encode()}.
  167. * If an 'encode' attribute is given and its value is false,
  168. * the rest of the attribute values will NOT be HTML-encoded.
  169. * Since version 1.1.5, attributes whose value is null will not be rendered.
  170. * @return string the generated HTML element tag
  171. */
  172. public static function openTag($tag,$htmlOptions=array())
  173. {
  174. return '<' . $tag . self::renderAttributes($htmlOptions) . '>';
  175. }
  176. /**
  177. * Generates a close HTML element.
  178. * @param string $tag the tag name
  179. * @return string the generated HTML element tag
  180. */
  181. public static function closeTag($tag)
  182. {
  183. return '</'.$tag.'>';
  184. }
  185. /**
  186. * Encloses the given string within a CDATA tag.
  187. * @param string $text the string to be enclosed
  188. * @return string the CDATA tag with the enclosed content.
  189. */
  190. public static function cdata($text)
  191. {
  192. return '<![CDATA[' . $text . ']]>';
  193. }
  194. /**
  195. * Generates a meta tag that can be inserted in the head section of HTML page.
  196. * @param string $content content attribute of the meta tag
  197. * @param string $name name attribute of the meta tag. If null, the attribute will not be generated
  198. * @param string $httpEquiv http-equiv attribute of the meta tag. If null, the attribute will not be generated
  199. * @param array $options other options in name-value pairs (e.g. 'scheme', 'lang')
  200. * @return string the generated meta tag
  201. */
  202. public static function metaTag($content,$name=null,$httpEquiv=null,$options=array())
  203. {
  204. if($name!==null)
  205. $options['name']=$name;
  206. if($httpEquiv!==null)
  207. $options['http-equiv']=$httpEquiv;
  208. $options['content']=$content;
  209. return self::tag('meta',$options);
  210. }
  211. /**
  212. * Generates a link tag that can be inserted in the head section of HTML page.
  213. * Do not confuse this method with {@link link()}. The latter generates a hyperlink.
  214. * @param string $relation rel attribute of the link tag. If null, the attribute will not be generated.
  215. * @param string $type type attribute of the link tag. If null, the attribute will not be generated.
  216. * @param string $href href attribute of the link tag. If null, the attribute will not be generated.
  217. * @param string $media media attribute of the link tag. If null, the attribute will not be generated.
  218. * @param array $options other options in name-value pairs
  219. * @return string the generated link tag
  220. */
  221. public static function linkTag($relation=null,$type=null,$href=null,$media=null,$options=array())
  222. {
  223. if($relation!==null)
  224. $options['rel']=$relation;
  225. if($type!==null)
  226. $options['type']=$type;
  227. if($href!==null)
  228. $options['href']=$href;
  229. if($media!==null)
  230. $options['media']=$media;
  231. return self::tag('link',$options);
  232. }
  233. /**
  234. * Encloses the given CSS content with a CSS tag.
  235. * @param string $text the CSS content
  236. * @param string $media the media that this CSS should apply to.
  237. * @return string the CSS properly enclosed
  238. */
  239. public static function css($text,$media='')
  240. {
  241. if($media!=='')
  242. $media=' media="'.$media.'"';
  243. return "<style type=\"text/css\"{$media}>\n/*<![CDATA[*/\n{$text}\n/*]]>*/\n</style>";
  244. }
  245. /**
  246. * Registers a 'refresh' meta tag.
  247. * This method can be invoked anywhere in a view. It will register a 'refresh'
  248. * meta tag with {@link CClientScript} so that the page can be refreshed in
  249. * the specified seconds.
  250. * @param integer $seconds the number of seconds to wait before refreshing the page
  251. * @param string $url the URL to which the page should be redirected to. If empty, it means the current page.
  252. * @since 1.1.1
  253. */
  254. public static function refresh($seconds,$url='')
  255. {
  256. $content="$seconds";
  257. if($url!=='')
  258. $content.=';url='.self::normalizeUrl($url);
  259. Yii::app()->clientScript->registerMetaTag($content,null,'refresh');
  260. }
  261. /**
  262. * Links to the specified CSS file.
  263. * @param string $url the CSS URL
  264. * @param string $media the media that this CSS should apply to.
  265. * @return string the CSS link.
  266. */
  267. public static function cssFile($url,$media='')
  268. {
  269. return CHtml::linkTag('stylesheet','text/css',$url,$media!=='' ? $media : null);
  270. }
  271. /**
  272. * Encloses the given JavaScript within a script tag.
  273. * @param string $text the JavaScript to be enclosed
  274. * @param array $htmlOptions additional HTML attributes (see {@link tag})
  275. * @return string the enclosed JavaScript
  276. */
  277. public static function script($text,array $htmlOptions=array())
  278. {
  279. $defaultHtmlOptions=array(
  280. 'type'=>'text/javascript',
  281. );
  282. $htmlOptions=array_merge($defaultHtmlOptions,$htmlOptions);
  283. return self::tag('script',$htmlOptions,"\n/*<![CDATA[*/\n{$text}\n/*]]>*/\n");
  284. }
  285. /**
  286. * Includes a JavaScript file.
  287. * @param string $url URL for the JavaScript file
  288. * @param array $htmlOptions additional HTML attributes (see {@link tag})
  289. * @return string the JavaScript file tag
  290. */
  291. public static function scriptFile($url,array $htmlOptions=array())
  292. {
  293. $defaultHtmlOptions=array(
  294. 'type'=>'text/javascript',
  295. 'src'=>$url
  296. );
  297. $htmlOptions=array_merge($defaultHtmlOptions,$htmlOptions);
  298. return self::tag('script',$htmlOptions,'');
  299. }
  300. /**
  301. * Generates an opening form tag.
  302. * This is a shortcut to {@link beginForm}.
  303. * @param mixed $action the form action URL (see {@link normalizeUrl} for details about this parameter.)
  304. * @param string $method form method (e.g. post, get)
  305. * @param array $htmlOptions additional HTML attributes (see {@link tag}).
  306. * @return string the generated form tag.
  307. */
  308. public static function form($action='',$method='post',$htmlOptions=array())
  309. {
  310. return self::beginForm($action,$method,$htmlOptions);
  311. }
  312. /**
  313. * Generates an opening form tag.
  314. * Note, only the open tag is generated. A close tag should be placed manually
  315. * at the end of the form.
  316. * @param mixed $action the form action URL (see {@link normalizeUrl} for details about this parameter.)
  317. * @param string $method form method (e.g. post, get)
  318. * @param array $htmlOptions additional HTML attributes (see {@link tag}).
  319. * @return string the generated form tag.
  320. * @see endForm
  321. */
  322. public static function beginForm($action='',$method='post',$htmlOptions=array())
  323. {
  324. $htmlOptions['action']=$url=self::normalizeUrl($action);
  325. if(strcasecmp($method,'get')!==0 && strcasecmp($method,'post')!==0)
  326. {
  327. $customMethod=$method;
  328. $method='post';
  329. }
  330. else
  331. $customMethod=false;
  332. $htmlOptions['method']=$method;
  333. $form=self::tag('form',$htmlOptions,false,false);
  334. $hiddens=array();
  335. if(!strcasecmp($method,'get') && ($pos=strpos($url,'?'))!==false)
  336. {
  337. foreach(explode('&',substr($url,$pos+1)) as $pair)
  338. {
  339. if(($pos=strpos($pair,'='))!==false)
  340. $hiddens[]=self::hiddenField(urldecode(substr($pair,0,$pos)),urldecode(substr($pair,$pos+1)),array('id'=>false));
  341. else
  342. $hiddens[]=self::hiddenField(urldecode($pair),'',array('id'=>false));
  343. }
  344. }
  345. $request=Yii::app()->request;
  346. if($request->enableCsrfValidation && !strcasecmp($method,'post'))
  347. $hiddens[]=self::hiddenField($request->csrfTokenName,$request->getCsrfToken(),array('id'=>false));
  348. if($customMethod!==false)
  349. $hiddens[]=self::hiddenField('_method',$customMethod);
  350. if($hiddens!==array())
  351. $form.="\n".implode("\n",$hiddens);
  352. return $form;
  353. }
  354. /**
  355. * Generates a closing form tag.
  356. * @return string the generated tag
  357. * @see beginForm
  358. */
  359. public static function endForm()
  360. {
  361. return '</form>';
  362. }
  363. /**
  364. * Generates a stateful form tag.
  365. * A stateful form tag is similar to {@link form} except that it renders an additional
  366. * hidden field for storing persistent page states. You should use this method to generate
  367. * a form tag if you want to access persistent page states when the form is submitted.
  368. * @param mixed $action the form action URL (see {@link normalizeUrl} for details about this parameter.)
  369. * @param string $method form method (e.g. post, get)
  370. * @param array $htmlOptions additional HTML attributes (see {@link tag}).
  371. * @return string the generated form tag.
  372. */
  373. public static function statefulForm($action='',$method='post',$htmlOptions=array())
  374. {
  375. return self::form($action,$method,$htmlOptions)."\n".
  376. self::tag('div',array('style'=>'display:none'),self::pageStateField(''));
  377. }
  378. /**
  379. * Generates a hidden field for storing persistent page states.
  380. * This method is internally used by {@link statefulForm}.
  381. * @param string $value the persistent page states in serialized format
  382. * @return string the generated hidden field
  383. */
  384. public static function pageStateField($value)
  385. {
  386. return '<input type="hidden" name="'.CController::STATE_INPUT_NAME.'" value="'.$value.'" />';
  387. }
  388. /**
  389. * Generates a hyperlink tag.
  390. * @param string $text link body. It will NOT be HTML-encoded. Therefore you can pass in HTML code such as an image tag.
  391. * @param mixed $url a URL or an action route that can be used to create a URL.
  392. * See {@link normalizeUrl} for more details about how to specify this parameter.
  393. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  394. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  395. * @return string the generated hyperlink
  396. * @see normalizeUrl
  397. * @see clientChange
  398. */
  399. public static function link($text,$url='#',$htmlOptions=array())
  400. {
  401. if($url!=='')
  402. $htmlOptions['href']=self::normalizeUrl($url);
  403. self::clientChange('click',$htmlOptions);
  404. return self::tag('a',$htmlOptions,$text);
  405. }
  406. /**
  407. * Generates a mailto link.
  408. * @param string $text link body. It will NOT be HTML-encoded. Therefore you can pass in HTML code such as an image tag.
  409. * @param string $email email address. If this is empty, the first parameter (link body) will be treated as the email address.
  410. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  411. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  412. * @return string the generated mailto link
  413. * @see clientChange
  414. */
  415. public static function mailto($text,$email='',$htmlOptions=array())
  416. {
  417. if($email==='')
  418. $email=$text;
  419. return self::link($text,'mailto:'.$email,$htmlOptions);
  420. }
  421. /**
  422. * Generates an image tag.
  423. * @param string $src the image URL
  424. * @param string $alt the alternative text display
  425. * @param array $htmlOptions additional HTML attributes (see {@link tag}).
  426. * @return string the generated image tag
  427. */
  428. public static function image($src,$alt='',$htmlOptions=array())
  429. {
  430. $htmlOptions['src']=$src;
  431. $htmlOptions['alt']=$alt;
  432. return self::tag('img',$htmlOptions);
  433. }
  434. /**
  435. * Generates a button.
  436. * @param string $label the button label
  437. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  438. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  439. * @return string the generated button tag
  440. * @see clientChange
  441. */
  442. public static function button($label='button',$htmlOptions=array())
  443. {
  444. if(!isset($htmlOptions['name']))
  445. {
  446. if(!array_key_exists('name',$htmlOptions))
  447. $htmlOptions['name']=self::ID_PREFIX.self::$count++;
  448. }
  449. if(!isset($htmlOptions['type']))
  450. $htmlOptions['type']='button';
  451. if(!isset($htmlOptions['value']) && $htmlOptions['type']!='image')
  452. $htmlOptions['value']=$label;
  453. self::clientChange('click',$htmlOptions);
  454. return self::tag('input',$htmlOptions);
  455. }
  456. /**
  457. * Generates a button using HTML button tag.
  458. * This method is similar to {@link button} except that it generates a 'button'
  459. * tag instead of 'input' tag.
  460. * @param string $label the button label. Note that this value will be directly inserted in the button element
  461. * without being HTML-encoded.
  462. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  463. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  464. * @return string the generated button tag
  465. * @see clientChange
  466. */
  467. public static function htmlButton($label='button',$htmlOptions=array())
  468. {
  469. if(!isset($htmlOptions['name']))
  470. $htmlOptions['name']=self::ID_PREFIX.self::$count++;
  471. if(!isset($htmlOptions['type']))
  472. $htmlOptions['type']='button';
  473. self::clientChange('click',$htmlOptions);
  474. return self::tag('button',$htmlOptions,$label);
  475. }
  476. /**
  477. * Generates a submit button.
  478. * @param string $label the button label
  479. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  480. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  481. * @return string the generated button tag
  482. * @see clientChange
  483. */
  484. public static function submitButton($label='submit',$htmlOptions=array())
  485. {
  486. $htmlOptions['type']='submit';
  487. return self::button($label,$htmlOptions);
  488. }
  489. /**
  490. * Generates a reset button.
  491. * @param string $label the button label
  492. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  493. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  494. * @return string the generated button tag
  495. * @see clientChange
  496. */
  497. public static function resetButton($label='reset',$htmlOptions=array())
  498. {
  499. $htmlOptions['type']='reset';
  500. return self::button($label,$htmlOptions);
  501. }
  502. /**
  503. * Generates an image submit button.
  504. * @param string $src the image URL
  505. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  506. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  507. * @return string the generated button tag
  508. * @see clientChange
  509. */
  510. public static function imageButton($src,$htmlOptions=array())
  511. {
  512. $htmlOptions['src']=$src;
  513. $htmlOptions['type']='image';
  514. return self::button('submit',$htmlOptions);
  515. }
  516. /**
  517. * Generates a link submit button.
  518. * @param string $label the button label
  519. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  520. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  521. * @return string the generated button tag
  522. * @see clientChange
  523. */
  524. public static function linkButton($label='submit',$htmlOptions=array())
  525. {
  526. if(!isset($htmlOptions['submit']))
  527. $htmlOptions['submit']=isset($htmlOptions['href']) ? $htmlOptions['href'] : '';
  528. return self::link($label,'#',$htmlOptions);
  529. }
  530. /**
  531. * Generates a label tag.
  532. * @param string $label label text. Note, you should HTML-encode the text if needed.
  533. * @param string $for the ID of the HTML element that this label is associated with.
  534. * If this is false, the 'for' attribute for the label tag will not be rendered.
  535. * @param array $htmlOptions additional HTML attributes.
  536. * The following HTML option is recognized:
  537. * <ul>
  538. * <li>required: if this is set and is true, the label will be styled
  539. * with CSS class 'required' (customizable with CHtml::$requiredCss),
  540. * and be decorated with {@link CHtml::beforeRequiredLabel} and
  541. * {@link CHtml::afterRequiredLabel}.</li>
  542. * </ul>
  543. * @return string the generated label tag
  544. */
  545. public static function label($label,$for,$htmlOptions=array())
  546. {
  547. if($for===false)
  548. unset($htmlOptions['for']);
  549. else
  550. $htmlOptions['for']=$for;
  551. if(isset($htmlOptions['required']))
  552. {
  553. if($htmlOptions['required'])
  554. {
  555. if(isset($htmlOptions['class']))
  556. $htmlOptions['class'].=' '.self::$requiredCss;
  557. else
  558. $htmlOptions['class']=self::$requiredCss;
  559. $label=self::$beforeRequiredLabel.$label.self::$afterRequiredLabel;
  560. }
  561. unset($htmlOptions['required']);
  562. }
  563. return self::tag('label',$htmlOptions,$label);
  564. }
  565. /**
  566. * Generates a color picker field input.
  567. * @param string $name the input name
  568. * @param string $value the input value
  569. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  570. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  571. * @return string the generated input field
  572. * @see clientChange
  573. * @see inputField
  574. * @since 1.1.16
  575. */
  576. public static function colorField($name,$value='',$htmlOptions=array())
  577. {
  578. self::clientChange('change',$htmlOptions);
  579. return self::inputField('color',$name,$value,$htmlOptions);
  580. }
  581. /**
  582. * Generates a text field input.
  583. * @param string $name the input name
  584. * @param string $value the input value
  585. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  586. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  587. * @return string the generated input field
  588. * @see clientChange
  589. * @see inputField
  590. */
  591. public static function textField($name,$value='',$htmlOptions=array())
  592. {
  593. self::clientChange('change',$htmlOptions);
  594. return self::inputField('text',$name,$value,$htmlOptions);
  595. }
  596. /**
  597. * Generates a search field input.
  598. * @param string $name the input name
  599. * @param string $value the input value
  600. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  601. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  602. * @return string the generated input field
  603. * @see clientChange
  604. * @see inputField
  605. * @since 1.1.16
  606. */
  607. public static function searchField($name,$value='',$htmlOptions=array())
  608. {
  609. self::clientChange('change',$htmlOptions);
  610. return self::inputField('search',$name,$value,$htmlOptions);
  611. }
  612. /**
  613. * Generates a number field input.
  614. * @param string $name the input name
  615. * @param string $value the input value
  616. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  617. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  618. * @return string the generated input field
  619. * @see clientChange
  620. * @see inputField
  621. * @since 1.1.14
  622. */
  623. public static function numberField($name,$value='',$htmlOptions=array())
  624. {
  625. self::clientChange('change',$htmlOptions);
  626. return self::inputField('number',$name,$value,$htmlOptions);
  627. }
  628. /**
  629. * Generates a range field input.
  630. * @param string $name the input name
  631. * @param string $value the input value
  632. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  633. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  634. * @return string the generated input field
  635. * @see clientChange
  636. * @see inputField
  637. * @since 1.1.14
  638. */
  639. public static function rangeField($name,$value='',$htmlOptions=array())
  640. {
  641. self::clientChange('change',$htmlOptions);
  642. return self::inputField('range',$name,$value,$htmlOptions);
  643. }
  644. /**
  645. * Generates a date field input.
  646. * @param string $name the input name
  647. * @param string $value the input value
  648. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  649. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  650. * @return string the generated input field
  651. * @see clientChange
  652. * @see inputField
  653. * @since 1.1.14
  654. */
  655. public static function dateField($name,$value='',$htmlOptions=array())
  656. {
  657. self::clientChange('change',$htmlOptions);
  658. return self::inputField('date',$name,$value,$htmlOptions);
  659. }
  660. /**
  661. * Generates a time field input.
  662. * @param string $name the input name
  663. * @param string $value the input value
  664. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  665. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  666. * @return string the generated input field
  667. * @see clientChange
  668. * @see inputField
  669. * @since 1.1.14
  670. */
  671. public static function timeField($name,$value='',$htmlOptions=array())
  672. {
  673. self::clientChange('change',$htmlOptions);
  674. return self::inputField('time',$name,$value,$htmlOptions);
  675. }
  676. /**
  677. * Generates a datetime field input.
  678. * @param string $name the input name
  679. * @param string $value the input value
  680. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  681. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  682. * @return string the generated input field
  683. * @see clientChange
  684. * @see inputField
  685. * @since 1.1.16
  686. */
  687. public static function dateTimeField($name,$value='',$htmlOptions=array())
  688. {
  689. self::clientChange('change',$htmlOptions);
  690. return self::inputField('datetime',$name,$value,$htmlOptions);
  691. }
  692. /**
  693. * Generates a local datetime field input.
  694. * @param string $name the input name
  695. * @param string $value the input value
  696. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  697. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  698. * @return string the generated input field
  699. * @see clientChange
  700. * @see inputField
  701. * @since 1.1.16
  702. */
  703. public static function dateTimeLocalField($name,$value='',$htmlOptions=array())
  704. {
  705. self::clientChange('change',$htmlOptions);
  706. return self::inputField('datetime-local',$name,$value,$htmlOptions);
  707. }
  708. /**
  709. * Generates a week field input.
  710. * @param string $name the input name
  711. * @param string $value the input value
  712. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  713. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  714. * @return string the generated input field
  715. * @see clientChange
  716. * @see inputField
  717. * @since 1.1.16
  718. */
  719. public static function weekField($name,$value='',$htmlOptions=array())
  720. {
  721. self::clientChange('change',$htmlOptions);
  722. return self::inputField('week',$name,$value,$htmlOptions);
  723. }
  724. /**
  725. * Generates an email field input.
  726. * @param string $name the input name
  727. * @param string $value the input value
  728. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  729. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  730. * @return string the generated input field
  731. * @see clientChange
  732. * @see inputField
  733. * @since 1.1.14
  734. */
  735. public static function emailField($name,$value='',$htmlOptions=array())
  736. {
  737. self::clientChange('change',$htmlOptions);
  738. return self::inputField('email',$name,$value,$htmlOptions);
  739. }
  740. /**
  741. * Generates a telephone field input.
  742. * @param string $name the input name
  743. * @param string $value the input value
  744. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  745. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  746. * @return string the generated input field
  747. * @see clientChange
  748. * @see inputField
  749. * @since 1.1.14
  750. */
  751. public static function telField($name,$value='',$htmlOptions=array())
  752. {
  753. self::clientChange('change',$htmlOptions);
  754. return self::inputField('tel',$name,$value,$htmlOptions);
  755. }
  756. /**
  757. * Generates a URL field input.
  758. * @param string $name the input name
  759. * @param string $value the input value
  760. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  761. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  762. * @return string the generated input field
  763. * @see clientChange
  764. * @see inputField
  765. * @since 1.1.14
  766. */
  767. public static function urlField($name,$value='',$htmlOptions=array())
  768. {
  769. self::clientChange('change',$htmlOptions);
  770. return self::inputField('url',$name,$value,$htmlOptions);
  771. }
  772. /**
  773. * Generates a hidden input.
  774. * @param string $name the input name
  775. * @param string $value the input value
  776. * @param array $htmlOptions additional HTML attributes (see {@link tag}).
  777. * @return string the generated input field
  778. * @see inputField
  779. */
  780. public static function hiddenField($name,$value='',$htmlOptions=array())
  781. {
  782. return self::inputField('hidden',$name,$value,$htmlOptions);
  783. }
  784. /**
  785. * Generates a password field input.
  786. * @param string $name the input name
  787. * @param string $value the input value
  788. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  789. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  790. * @return string the generated input field
  791. * @see clientChange
  792. * @see inputField
  793. */
  794. public static function passwordField($name,$value='',$htmlOptions=array())
  795. {
  796. self::clientChange('change',$htmlOptions);
  797. return self::inputField('password',$name,$value,$htmlOptions);
  798. }
  799. /**
  800. * Generates a file input.
  801. * Note, you have to set the enclosing form's 'enctype' attribute to be 'multipart/form-data'.
  802. * After the form is submitted, the uploaded file information can be obtained via $_FILES[$name] (see
  803. * PHP documentation).
  804. * @param string $name the input name
  805. * @param string $value the input value
  806. * @param array $htmlOptions additional HTML attributes (see {@link tag}).
  807. * @return string the generated input field
  808. * @see inputField
  809. */
  810. public static function fileField($name,$value='',$htmlOptions=array())
  811. {
  812. return self::inputField('file',$name,$value,$htmlOptions);
  813. }
  814. /**
  815. * Generates a text area input.
  816. * @param string $name the input name
  817. * @param string $value the input value
  818. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  819. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  820. * @return string the generated text area
  821. * @see clientChange
  822. * @see inputField
  823. */
  824. public static function textArea($name,$value='',$htmlOptions=array())
  825. {
  826. $htmlOptions['name']=$name;
  827. if(!isset($htmlOptions['id']))
  828. $htmlOptions['id']=self::getIdByName($name);
  829. elseif($htmlOptions['id']===false)
  830. unset($htmlOptions['id']);
  831. self::clientChange('change',$htmlOptions);
  832. return self::tag('textarea',$htmlOptions,isset($htmlOptions['encode']) && !$htmlOptions['encode'] ? $value : self::encode($value));
  833. }
  834. /**
  835. * Generates a radio button.
  836. * @param string $name the input name
  837. * @param boolean $checked whether the radio button is checked
  838. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  839. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  840. * Since version 1.1.2, a special option named 'uncheckValue' is available that can be used to specify
  841. * the value returned when the radio button is not checked. When set, a hidden field is rendered so that
  842. * when the radio button is not checked, we can still obtain the posted uncheck value.
  843. * If 'uncheckValue' is not set or set to NULL, the hidden field will not be rendered.
  844. * @return string the generated radio button
  845. * @see clientChange
  846. * @see inputField
  847. */
  848. public static function radioButton($name,$checked=false,$htmlOptions=array())
  849. {
  850. if($checked)
  851. $htmlOptions['checked']='checked';
  852. else
  853. unset($htmlOptions['checked']);
  854. $value=isset($htmlOptions['value']) ? $htmlOptions['value'] : 1;
  855. self::clientChange('click',$htmlOptions);
  856. if(array_key_exists('uncheckValue',$htmlOptions))
  857. {
  858. $uncheck=$htmlOptions['uncheckValue'];
  859. unset($htmlOptions['uncheckValue']);
  860. }
  861. else
  862. $uncheck=null;
  863. if($uncheck!==null)
  864. {
  865. // add a hidden field so that if the radio button is not selected, it still submits a value
  866. if(isset($htmlOptions['id']) && $htmlOptions['id']!==false)
  867. $uncheckOptions=array('id'=>self::ID_PREFIX.$htmlOptions['id']);
  868. else
  869. $uncheckOptions=array('id'=>false);
  870. $hidden=self::hiddenField($name,$uncheck,$uncheckOptions);
  871. }
  872. else
  873. $hidden='';
  874. // add a hidden field so that if the radio button is not selected, it still submits a value
  875. return $hidden . self::inputField('radio',$name,$value,$htmlOptions);
  876. }
  877. /**
  878. * Generates a check box.
  879. * @param string $name the input name
  880. * @param boolean $checked whether the check box is checked
  881. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  882. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  883. * Since version 1.1.2, a special option named 'uncheckValue' is available that can be used to specify
  884. * the value returned when the checkbox is not checked. When set, a hidden field is rendered so that
  885. * when the checkbox is not checked, we can still obtain the posted uncheck value.
  886. * If 'uncheckValue' is not set or set to NULL, the hidden field will not be rendered.
  887. * @return string the generated check box
  888. * @see clientChange
  889. * @see inputField
  890. */
  891. public static function checkBox($name,$checked=false,$htmlOptions=array())
  892. {
  893. if($checked)
  894. $htmlOptions['checked']='checked';
  895. else
  896. unset($htmlOptions['checked']);
  897. $value=isset($htmlOptions['value']) ? $htmlOptions['value'] : 1;
  898. self::clientChange('click',$htmlOptions);
  899. if(array_key_exists('uncheckValue',$htmlOptions))
  900. {
  901. $uncheck=$htmlOptions['uncheckValue'];
  902. unset($htmlOptions['uncheckValue']);
  903. }
  904. else
  905. $uncheck=null;
  906. if($uncheck!==null)
  907. {
  908. // add a hidden field so that if the check box is not checked, it still submits a value
  909. if(isset($htmlOptions['id']) && $htmlOptions['id']!==false)
  910. $uncheckOptions=array('id'=>self::ID_PREFIX.$htmlOptions['id']);
  911. else
  912. $uncheckOptions=array('id'=>false);
  913. $hidden=self::hiddenField($name,$uncheck,$uncheckOptions);
  914. }
  915. else
  916. $hidden='';
  917. // add a hidden field so that if the check box is not checked, it still submits a value
  918. return $hidden . self::inputField('checkbox',$name,$value,$htmlOptions);
  919. }
  920. /**
  921. * Generates a drop down list.
  922. * @param string $name the input name
  923. * @param string $select the selected value
  924. * @param array $data data for generating the list options (value=>display).
  925. * You may use {@link listData} to generate this data.
  926. * Please refer to {@link listOptions} on how this data is used to generate the list options.
  927. * Note, the values and labels will be automatically HTML-encoded by this method.
  928. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  929. * attributes are recognized. See {@link clientChange} and {@link tag} for more details.
  930. * In addition, the following options are also supported specifically for dropdown list:
  931. * <ul>
  932. * <li>encode: boolean, specifies whether to encode the values. Defaults to true.</li>
  933. * <li>prompt: string, specifies the prompt text shown as the first list option. Its value is empty. Note, the prompt text will NOT be HTML-encoded.</li>
  934. * <li>empty: string, specifies the text corresponding to empty selection. Its value is empty.
  935. * The 'empty' option can also be an array of value-label pairs.
  936. * Each pair will be used to render a list option at the beginning. Note, the text label will NOT be HTML-encoded.</li>
  937. * <li>options: array, specifies additional attributes for each OPTION tag.
  938. * The array keys must be the option values, and the array values are the extra
  939. * OPTION tag attributes in the name-value pairs. For example,
  940. * <pre>
  941. * array(
  942. * 'value1'=>array('disabled'=>true,'label'=>'value 1'),
  943. * 'value2'=>array('label'=>'value 2'),
  944. * );
  945. * </pre>
  946. * </li>
  947. * </ul>
  948. * Since 1.1.13, a special option named 'unselectValue' is available. It can be used to set the value
  949. * that will be returned when no option is selected in multiple mode. When set, a hidden field is
  950. * rendered so that if no option is selected in multiple mode, we can still obtain the posted
  951. * unselect value. If 'unselectValue' is not set or set to NULL, the hidden field will not be rendered.
  952. * @return string the generated drop down list
  953. * @see clientChange
  954. * @see inputField
  955. * @see listData
  956. */
  957. public static function dropDownList($name,$select,$data,$htmlOptions=array())
  958. {
  959. $htmlOptions['name']=$name;
  960. if(!isset($htmlOptions['id']))
  961. $htmlOptions['id']=self::getIdByName($name);
  962. elseif($htmlOptions['id']===false)
  963. unset($htmlOptions['id']);
  964. self::clientChange('change',$htmlOptions);
  965. $options="\n".self::listOptions($select,$data,$htmlOptions);
  966. $hidden='';
  967. if(!empty($htmlOptions['multiple']))
  968. {
  969. if(substr($htmlOptions['name'],-2)!=='[]')
  970. $htmlOptions['name'].='[]';
  971. if(isset($htmlOptions['unselectValue']))
  972. {
  973. $hiddenOptions=isset($htmlOptions['id']) ? array('id'=>self::ID_PREFIX.$htmlOptions['id']) : array('id'=>false);
  974. $hidden=self::hiddenField(substr($htmlOptions['name'],0,-2),$htmlOptions['unselectValue'],$hiddenOptions);
  975. unset($htmlOptions['unselectValue']);
  976. }
  977. }
  978. // add a hidden field so that if the option is not selected, it still submits a value
  979. return $hidden . self::tag('select',$htmlOptions,$options);
  980. }
  981. /**
  982. * Generates a list box.
  983. * @param string $name the input name
  984. * @param mixed $select the selected value(s). This can be either a string for single selection or an array for multiple selections.
  985. * @param array $data data for generating the list options (value=>display)
  986. * You may use {@link listData} to generate this data.
  987. * Please refer to {@link listOptions} on how this data is used to generate the list options.
  988. * Note, the values and labels will be automatically HTML-encoded by this method.
  989. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  990. * attributes are also recognized. See {@link clientChange} and {@link tag} for more details.
  991. * In addition, the following options are also supported specifically for list box:
  992. * <ul>
  993. * <li>encode: boolean, specifies whether to encode the values. Defaults to true.</li>
  994. * <li>prompt: string, specifies the prompt text shown as the first list option. Its value is empty. Note, the prompt text will NOT be HTML-encoded.</li>
  995. * <li>empty: string, specifies the text corresponding to empty selection. Its value is empty.
  996. * The 'empty' option can also be an array of value-label pairs.
  997. * Each pair will be used to render a list option at the beginning. Note, the text label will NOT be HTML-encoded.</li>
  998. * <li>options: array, specifies additional attributes for each OPTION tag.
  999. * The array keys must be the option values, and the array values are the extra
  1000. * OPTION tag attributes in the name-value pairs. For example,
  1001. * <pre>
  1002. * array(
  1003. * 'value1'=>array('disabled'=>true,'label'=>'value 1'),
  1004. * 'value2'=>array('label'=>'value 2'),
  1005. * );
  1006. * </pre>
  1007. * </li>
  1008. * </ul>
  1009. * @return string the generated list box
  1010. * @see clientChange
  1011. * @see inputField
  1012. * @see listData
  1013. */
  1014. public static function listBox($name,$select,$data,$htmlOptions=array())
  1015. {
  1016. if(!isset($htmlOptions['size']))
  1017. $htmlOptions['size']=4;
  1018. if(!empty($htmlOptions['multiple']))
  1019. {
  1020. if(substr($name,-2)!=='[]')
  1021. $name.='[]';
  1022. }
  1023. return self::dropDownList($name,$select,$data,$htmlOptions);
  1024. }
  1025. /**
  1026. * Generates a check box list.
  1027. * A check box list allows multiple selection, like {@link listBox}.
  1028. * As a result, the corresponding POST value is an array.
  1029. * @param string $name name of the check box list. You can use this name to retrieve
  1030. * the selected value(s) once the form is submitted.
  1031. * @param mixed $select selection of the check boxes. This can be either a string
  1032. * for single selection or an array for multiple selections.
  1033. * @param array $data value-label pairs used to generate the check box list.
  1034. * Note, the values will be automatically HTML-encoded, while the labels will not.
  1035. * @param array $htmlOptions additional HTML options. The options will be applied to
  1036. * each checkbox input. The following special options are recognized:
  1037. * <ul>
  1038. * <li>template: string, specifies how each checkbox is rendered. Defaults
  1039. * to "{input} {label}", where "{input}" will be replaced by the generated
  1040. * check box input tag while "{label}" be replaced by the corresponding check box label,
  1041. * {beginLabel} will be replaced by &lt;label&gt; with labelOptions, {labelTitle} will be replaced
  1042. * by the corresponding check box label title and {endLabel} will be replaced by &lt;/label&gt;</li>
  1043. * <li>separator: string, specifies the string that separates the generated check boxes.</li>
  1044. * <li>checkAll: string, specifies the label for the "check all" checkbox.
  1045. * If this option is specified, a 'check all' checkbox will be displayed. Clicking on
  1046. * this checkbox will cause all checkboxes checked or unchecked.</li>
  1047. * <li>checkAllLast: boolean, specifies whether the 'check all' checkbox should be
  1048. * displayed at the end of the checkbox list. If this option is not set (default)
  1049. * or is false, the 'check all' checkbox will be displayed at the beginning of
  1050. * the checkbox list.</li>
  1051. * <li>labelOptions: array, specifies the additional HTML attributes to be rendered
  1052. * for every label tag in the list.</li>
  1053. * <li>container: string, specifies the checkboxes enclosing tag. Defaults to 'span'.
  1054. * If the value is an empty string, no enclosing tag will be generated</li>
  1055. * <li>baseID: string, specifies the base ID prefix to be used for checkboxes in the list.
  1056. * This option is available since version 1.1.13.</li>
  1057. * </ul>
  1058. * @return string the generated check box list
  1059. */
  1060. public static function checkBoxList($name,$select,$data,$htmlOptions=array())
  1061. {
  1062. $template=isset($htmlOptions['template'])?$htmlOptions['template']:'{input} {label}';
  1063. $separator=isset($htmlOptions['separator'])?$htmlOptions['separator']:self::tag('br');
  1064. $container=isset($htmlOptions['container'])?$htmlOptions['container']:'span';
  1065. unset($htmlOptions['template'],$htmlOptions['separator'],$htmlOptions['container']);
  1066. if(substr($name,-2)!=='[]')
  1067. $name.='[]';
  1068. if(isset($htmlOptions['checkAll']))
  1069. {
  1070. $checkAllLabel=$htmlOptions['checkAll'];
  1071. $checkAllLast=isset($htmlOptions['checkAllLast']) && $htmlOptions['checkAllLast'];
  1072. }
  1073. unset($htmlOptions['checkAll'],$htmlOptions['checkAllLast']);
  1074. $labelOptions=isset($htmlOptions['labelOptions'])?$htmlOptions['labelOptions']:array();
  1075. unset($htmlOptions['labelOptions']);
  1076. $items=array();
  1077. $baseID=isset($htmlOptions['baseID']) ? $htmlOptions['baseID'] : self::getIdByName($name);
  1078. unset($htmlOptions['baseID']);
  1079. $id=0;
  1080. $checkAll=true;
  1081. foreach($data as $value=>$labelTitle)
  1082. {
  1083. $checked=!is_array($select) && !strcmp($value,$select) || is_array($select) && in_array($value,$select);
  1084. $checkAll=$checkAll && $checked;
  1085. $htmlOptions['value']=$value;
  1086. $htmlOptions['id']=$baseID.'_'.$id++;
  1087. $option=self::checkBox($name,$checked,$htmlOptions);
  1088. $beginLabel=self::openTag('label',$labelOptions);
  1089. $label=self::label($labelTitle,$htmlOptions['id'],$labelOptions);
  1090. $endLabel=self::closeTag('label');
  1091. $items[]=strtr($template,array(
  1092. '{input}'=>$option,
  1093. '{beginLabel}'=>$beginLabel,
  1094. '{label}'=>$label,
  1095. '{labelTitle}'=>$labelTitle,
  1096. '{endLabel}'=>$endLabel,
  1097. ));
  1098. }
  1099. if(isset($checkAllLabel))
  1100. {
  1101. $htmlOptions['value']=1;
  1102. $htmlOptions['id']=$id=$baseID.'_all';
  1103. $option=self::checkBox($id,$checkAll,$htmlOptions);
  1104. $beginLabel=self::openTag('label',$labelOptions);
  1105. $label=self::label($checkAllLabel,$id,$labelOptions);
  1106. $endLabel=self::closeTag('label');
  1107. $item=strtr($template,array(
  1108. '{input}'=>$option,
  1109. '{beginLabel}'=>$beginLabel,
  1110. '{label}'=>$label,
  1111. '{labelTitle}'=>$checkAllLabel,
  1112. '{endLabel}'=>$endLabel,
  1113. ));
  1114. if($checkAllLast)
  1115. $items[]=$item;
  1116. else
  1117. array_unshift($items,$item);
  1118. $name=strtr($name,array('['=>'\\[',']'=>'\\]'));
  1119. $js=<<<EOD
  1120. jQuery('#$id').click(function() {
  1121. jQuery("input[name='$name']").prop('checked', this.checked);
  1122. });
  1123. jQuery("input[name='$name']").click(function() {
  1124. jQuery('#$id').prop('checked', !jQuery("input[name='$name']:not(:checked)").length);
  1125. });
  1126. jQuery('#$id').prop('checked', !jQuery("input[name='$name']:not(:checked)").length);
  1127. EOD;
  1128. $cs=Yii::app()->getClientScript();
  1129. $cs->registerCoreScript('jquery');
  1130. $cs->registerScript($id,$js);
  1131. }
  1132. if(empty($container))
  1133. return implode($separator,$items);
  1134. else
  1135. return self::tag($container,array('id'=>$baseID),implode($separator,$items));
  1136. }
  1137. /**
  1138. * Generates a radio button list.
  1139. * A radio button list is like a {@link checkBoxList check box list}, except that
  1140. * it only allows single selection.
  1141. * @param string $name name of the radio button list. You can use this name to retrieve
  1142. * the selected value(s) once the form is submitted.
  1143. * @param string $select selection of the radio buttons.
  1144. * @param array $data value-label pairs used to generate the radio button list.
  1145. * Note, the values will be automatically HTML-encoded, while the labels will not.
  1146. * @param array $htmlOptions additional HTML options. The options will be applied to
  1147. * each radio button input. The following special options are recognized:
  1148. * <ul>
  1149. * <li>template: string, specifies how each radio button is rendered. Defaults
  1150. * to "{input} {label}", where "{input}" will be replaced by the generated
  1151. * radio button input tag while "{label}" will be replaced by the corresponding radio button label,
  1152. * {beginLabel} will be replaced by &lt;label&gt; with labelOptions, {labelTitle} will be replaced
  1153. * by the corresponding radio button label title and {endLabel} will be replaced by &lt;/label&gt;</li>
  1154. * <li>separator: string, specifies the string that separates the generated radio buttons. Defaults to new line (<br/>).</li>
  1155. * <li>labelOptions: array, specifies the additional HTML attributes to be rendered
  1156. * for every label tag in the list.</li>
  1157. * <li>container: string, specifies the radio buttons enclosing tag. Defaults to 'span'.
  1158. * If the value is an empty string, no enclosing tag will be generated</li>
  1159. * <li>baseID: string, specifies the base ID prefix to be used for radio buttons in the list.
  1160. * This option is available since version 1.1.13.</li>
  1161. * <li>empty: string, specifies the text corresponding to empty selection. Its value is empty.
  1162. * The 'empty' option can also be an array of value-label pairs.
  1163. * Each pair will be used to render a radio button at the beginning. Note, the text label will NOT be HTML-encoded.
  1164. * This option is available since version 1.1.14.</li>
  1165. * </ul>
  1166. * @return string the generated radio button list
  1167. */
  1168. public static function radioButtonList($name,$select,$data,$htmlOptions=array())
  1169. {
  1170. $template=isset($htmlOptions['template'])?$htmlOptions['template']:'{input} {label}';
  1171. $separator=isset($htmlOptions['separator'])?$htmlOptions['separator']:self::tag('br');
  1172. $container=isset($htmlOptions['container'])?$htmlOptions['container']:'span';
  1173. unset($htmlOptions['template'],$htmlOptions['separator'],$htmlOptions['container']);
  1174. $labelOptions=isset($htmlOptions['labelOptions'])?$htmlOptions['labelOptions']:array();
  1175. unset($htmlOptions['labelOptions']);
  1176. if(isset($htmlOptions['empty']))
  1177. {
  1178. if(!is_array($htmlOptions['empty']))
  1179. $htmlOptions['empty']=array(''=>$htmlOptions['empty']);
  1180. $data=CMap::mergeArray($htmlOptions['empty'],$data);
  1181. unset($htmlOptions['empty']);
  1182. }
  1183. $items=array();
  1184. $baseID=isset($htmlOptions['baseID']) ? $htmlOptions['baseID'] : self::getIdByName($name);
  1185. unset($htmlOptions['baseID']);
  1186. $id=0;
  1187. foreach($data as $value=>$labelTitle)
  1188. {
  1189. $checked=!strcmp($value,$select);
  1190. $htmlOptions['value']=$value;
  1191. $htmlOptions['id']=$baseID.'_'.$id++;
  1192. $option=self::radioButton($name,$checked,$htmlOptions);
  1193. $beginLabel=self::openTag('label',$labelOptions);
  1194. $label=self::label($labelTitle,$htmlOptions['id'],$labelOptions);
  1195. $endLabel=self::closeTag('label');
  1196. $items[]=strtr($template,array(
  1197. '{input}'=>$option,
  1198. '{beginLabel}'=>$beginLabel,
  1199. '{label}'=>$label,
  1200. '{labelTitle}'=>$labelTitle,
  1201. '{endLabel}'=>$endLabel,
  1202. ));
  1203. }
  1204. if(empty($container))
  1205. return implode($separator,$items);
  1206. else
  1207. return self::tag($container,array('id'=>$baseID),implode($separator,$items));
  1208. }
  1209. /**
  1210. * Generates a link that can initiate AJAX requests.
  1211. * @param string $text the link body (it will NOT be HTML-encoded.)
  1212. * @param mixed $url the URL for the AJAX request. If empty, it is assumed to be the current URL. See {@link normalizeUrl} for more details.
  1213. * @param array $ajaxOptions AJAX options (see {@link ajax})
  1214. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1215. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1216. * @return string the generated link
  1217. * @see normalizeUrl
  1218. * @see ajax
  1219. */
  1220. public static function ajaxLink($text,$url,$ajaxOptions=array(),$htmlOptions=array())
  1221. {
  1222. if(!isset($htmlOptions['href']))
  1223. $htmlOptions['href']='#';
  1224. $ajaxOptions['url']=$url;
  1225. $htmlOptions['ajax']=$ajaxOptions;
  1226. self::clientChange('click',$htmlOptions);
  1227. return self::tag('a',$htmlOptions,$text);
  1228. }
  1229. /**
  1230. * Generates a push button that can initiate AJAX requests.
  1231. * @param string $label the button label
  1232. * @param mixed $url the URL for the AJAX request. If empty, it is assumed to be the current URL. See {@link normalizeUrl} for more details.
  1233. * @param array $ajaxOptions AJAX options (see {@link ajax})
  1234. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1235. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1236. * @return string the generated button
  1237. */
  1238. public static function ajaxButton($label,$url,$ajaxOptions=array(),$htmlOptions=array())
  1239. {
  1240. $ajaxOptions['url']=$url;
  1241. $htmlOptions['ajax']=$ajaxOptions;
  1242. return self::button($label,$htmlOptions);
  1243. }
  1244. /**
  1245. * Generates a push button that can submit the current form in POST method.
  1246. * @param string $label the button label
  1247. * @param mixed $url the URL for the AJAX request. If empty, it is assumed to be the current URL. See {@link normalizeUrl} for more details.
  1248. * @param array $ajaxOptions AJAX options (see {@link ajax})
  1249. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1250. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1251. * @return string the generated button
  1252. */
  1253. public static function ajaxSubmitButton($label,$url,$ajaxOptions=array(),$htmlOptions=array())
  1254. {
  1255. $ajaxOptions['type']='POST';
  1256. $htmlOptions['type']='submit';
  1257. return self::ajaxButton($label,$url,$ajaxOptions,$htmlOptions);
  1258. }
  1259. /**
  1260. * Generates the JavaScript that initiates an AJAX request.
  1261. * @param array $options AJAX options. The valid options are used in the form of jQuery.ajax([settings])
  1262. * as specified in the jQuery AJAX documentation.
  1263. * The following special options are added for convenience:
  1264. * <ul>
  1265. * <li>update: string, specifies the selector whose HTML content should be replaced
  1266. * by the AJAX request result.</li>
  1267. * <li>replace: string, specifies the selector whose target should be replaced
  1268. * by the AJAX request result.</li>
  1269. * </ul>
  1270. * Note, if you specify the 'success' option, the above options will be ignored.
  1271. * @return string the generated JavaScript
  1272. * @see http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings
  1273. */
  1274. public static function ajax($options)
  1275. {
  1276. Yii::app()->getClientScript()->registerCoreScript('jquery');
  1277. if(!isset($options['url']))
  1278. $options['url']=new CJavaScriptExpression('location.href');
  1279. else
  1280. $options['url']=self::normalizeUrl($options['url']);
  1281. if(!isset($options['cache']))
  1282. $options['cache']=false;
  1283. if(!isset($options['data']) && isset($options['type']))
  1284. $options['data']=new CJavaScriptExpression('jQuery(this).parents("form").serialize()');
  1285. foreach(array('beforeSend','complete','error','success') as $name)
  1286. {
  1287. if(isset($options[$name]) && !($options[$name] instanceof CJavaScriptExpression))
  1288. $options[$name]=new CJavaScriptExpression($options[$name]);
  1289. }
  1290. if(isset($options['update']))
  1291. {
  1292. if(!isset($options['success']))
  1293. $options['success']=new CJavaScriptExpression('function(html){jQuery("'.$options['update'].'").html(html)}');
  1294. unset($options['update']);
  1295. }
  1296. if(isset($options['replace']))
  1297. {
  1298. if(!isset($options['success']))
  1299. $options['success']=new CJavaScriptExpression('function(html){jQuery("'.$options['replace'].'").replaceWith(html)}');
  1300. unset($options['replace']);
  1301. }
  1302. return 'jQuery.ajax('.CJavaScript::encode($options).');';
  1303. }
  1304. /**
  1305. * Generates the URL for the published assets.
  1306. * @param string $path the path of the asset to be published
  1307. * @param boolean $hashByName whether the published directory should be named as the hashed basename.
  1308. * If false, the name will be the hashed dirname of the path being published.
  1309. * Defaults to false. Set true if the path being published is shared among
  1310. * different extensions.
  1311. * @return string the asset URL
  1312. */
  1313. public static function asset($path,$hashByName=false)
  1314. {
  1315. return Yii::app()->getAssetManager()->publish($path,$hashByName);
  1316. }
  1317. /**
  1318. * Normalizes the input parameter to be a valid URL.
  1319. *
  1320. * If the input parameter is an empty string, the currently requested URL will be returned.
  1321. *
  1322. * If the input parameter is a non-empty string, it is treated as a valid URL and will
  1323. * be returned without any change.
  1324. *
  1325. * If the input parameter is an array, it is treated as a controller route and a list of
  1326. * GET parameters, and the {@link CController::createUrl} method will be invoked to
  1327. * create a URL. In this case, the first array element refers to the controller route,
  1328. * and the rest key-value pairs refer to the additional GET parameters for the URL.
  1329. * For example, <code>array('post/list', 'page'=>3)</code> may be used to generate the URL
  1330. * <code>/index.php?r=post/list&page=3</code>.
  1331. *
  1332. * @param mixed $url the parameter to be used to generate a valid URL
  1333. * @return string the normalized URL
  1334. */
  1335. public static function normalizeUrl($url)
  1336. {
  1337. if(is_array($url))
  1338. {
  1339. if(isset($url[0]))
  1340. {
  1341. if(($c=Yii::app()->getController())!==null)
  1342. $url=$c->createUrl($url[0],array_splice($url,1));
  1343. else
  1344. $url=Yii::app()->createUrl($url[0],array_splice($url,1));
  1345. }
  1346. else
  1347. $url='';
  1348. }
  1349. return $url==='' ? Yii::app()->getRequest()->getUrl() : $url;
  1350. }
  1351. /**
  1352. * Generates an input HTML tag.
  1353. * This method generates an input HTML tag based on the given input name and value.
  1354. * @param string $type the input type (e.g. 'text', 'radio')
  1355. * @param string $name the input name
  1356. * @param string $value the input value
  1357. * @param array $htmlOptions additional HTML attributes for the HTML tag (see {@link tag}).
  1358. * @return string the generated input tag
  1359. */
  1360. protected static function inputField($type,$name,$value,$htmlOptions)
  1361. {
  1362. $htmlOptions['type']=$type;
  1363. $htmlOptions['value']=$value;
  1364. $htmlOptions['name']=$name;
  1365. if(!isset($htmlOptions['id']))
  1366. $htmlOptions['id']=self::getIdByName($name);
  1367. elseif($htmlOptions['id']===false)
  1368. unset($htmlOptions['id']);
  1369. return self::tag('input',$htmlOptions);
  1370. }
  1371. /**
  1372. * Generates a label tag for a model attribute.
  1373. * The label text is the attribute label and the label is associated with
  1374. * the input for the attribute (see {@link CModel::getAttributeLabel}.
  1375. * If the attribute has input error, the label's CSS class will be appended with {@link errorCss}.
  1376. * @param CModel $model the data model
  1377. * @param string $attribute the attribute
  1378. * @param array $htmlOptions additional HTML attributes. The following special options are recognized:
  1379. * <ul>
  1380. * <li>required: if this is set and is true, the label will be styled
  1381. * with CSS class 'required' (customizable with CHtml::$requiredCss),
  1382. * and be decorated with {@link CHtml::beforeRequiredLabel} and
  1383. * {@link CHtml::afterRequiredLabel}.</li>
  1384. * <li>label: this specifies the label to be displayed. If this is not set,
  1385. * {@link CModel::getAttributeLabel} will be called to get the label for display.
  1386. * If the label is specified as false, no label will be rendered.</li>
  1387. * </ul>
  1388. * @return string the generated label tag
  1389. */
  1390. public static function activeLabel($model,$attribute,$htmlOptions=array())
  1391. {
  1392. $inputName=self::resolveName($model,$attribute);
  1393. if(isset($htmlOptions['for']))
  1394. {
  1395. $for=$htmlOptions['for'];
  1396. unset($htmlOptions['for']);
  1397. }
  1398. else
  1399. $for=self::getIdByName($inputName);
  1400. if(isset($htmlOptions['label']))
  1401. {
  1402. if(($label=$htmlOptions['label'])===false)
  1403. return '';
  1404. unset($htmlOptions['label']);
  1405. }
  1406. else
  1407. $label=$model->getAttributeLabel($attribute);
  1408. if($model->hasErrors($attribute))
  1409. self::addErrorCss($htmlOptions);
  1410. return self::label($label,$for,$htmlOptions);
  1411. }
  1412. /**
  1413. * Generates a label tag for a model attribute.
  1414. * This is an enhanced version of {@link activeLabel}. It will render additional
  1415. * CSS class and mark when the attribute is required.
  1416. * In particular, it calls {@link CModel::isAttributeRequired} to determine
  1417. * if the attribute is required.
  1418. * If so, it will add a CSS class {@link CHtml::requiredCss} to the label,
  1419. * and decorate the label with {@link CHtml::beforeRequiredLabel} and
  1420. * {@link CHtml::afterRequiredLabel}.
  1421. * @param CModel $model the data model
  1422. * @param string $attribute the attribute
  1423. * @param array $htmlOptions additional HTML attributes.
  1424. * @return string the generated label tag
  1425. */
  1426. public static function activeLabelEx($model,$attribute,$htmlOptions=array())
  1427. {
  1428. $realAttribute=$attribute;
  1429. self::resolveName($model,$attribute); // strip off square brackets if any
  1430. $htmlOptions['required']=$model->isAttributeRequired($attribute);
  1431. return self::activeLabel($model,$realAttribute,$htmlOptions);
  1432. }
  1433. /**
  1434. * Generates a text field input for a model attribute.
  1435. * If the attribute has input error, the input field's CSS class will
  1436. * be appended with {@link errorCss}.
  1437. * @param CModel $model the data model
  1438. * @param string $attribute the attribute
  1439. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1440. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1441. * @return string the generated input field
  1442. * @see clientChange
  1443. * @see activeInputField
  1444. */
  1445. public static function activeTextField($model,$attribute,$htmlOptions=array())
  1446. {
  1447. self::resolveNameID($model,$attribute,$htmlOptions);
  1448. self::clientChange('change',$htmlOptions);
  1449. return self::activeInputField('text',$model,$attribute,$htmlOptions);
  1450. }
  1451. /**
  1452. * Generates a search field input for a model attribute.
  1453. * If the attribute has input error, the input field's CSS class will
  1454. * be appended with {@link errorCss}.
  1455. * @param CModel $model the data model
  1456. * @param string $attribute the attribute
  1457. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1458. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1459. * @return string the generated input field
  1460. * @see clientChange
  1461. * @see activeInputField
  1462. * @since 1.1.14
  1463. */
  1464. public static function activeSearchField($model,$attribute,$htmlOptions=array())
  1465. {
  1466. self::resolveNameID($model,$attribute,$htmlOptions);
  1467. self::clientChange('change',$htmlOptions);
  1468. return self::activeInputField('search',$model,$attribute,$htmlOptions);
  1469. }
  1470. /**
  1471. * Generates a url field input for a model attribute.
  1472. * If the attribute has input error, the input field's CSS class will
  1473. * be appended with {@link errorCss}.
  1474. * @param CModel $model the data model
  1475. * @param string $attribute the attribute
  1476. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1477. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1478. * @return string the generated input field
  1479. * @see clientChange
  1480. * @see activeInputField
  1481. * @since 1.1.11
  1482. */
  1483. public static function activeUrlField($model,$attribute,$htmlOptions=array())
  1484. {
  1485. self::resolveNameID($model,$attribute,$htmlOptions);
  1486. self::clientChange('change',$htmlOptions);
  1487. return self::activeInputField('url',$model,$attribute,$htmlOptions);
  1488. }
  1489. /**
  1490. * Generates an email field input for a model attribute.
  1491. * If the attribute has input error, the input field's CSS class will
  1492. * be appended with {@link errorCss}.
  1493. * @param CModel $model the data model
  1494. * @param string $attribute the attribute
  1495. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1496. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1497. * @return string the generated input field
  1498. * @see clientChange
  1499. * @see activeInputField
  1500. * @since 1.1.11
  1501. */
  1502. public static function activeEmailField($model,$attribute,$htmlOptions=array())
  1503. {
  1504. self::resolveNameID($model,$attribute,$htmlOptions);
  1505. self::clientChange('change',$htmlOptions);
  1506. return self::activeInputField('email',$model,$attribute,$htmlOptions);
  1507. }
  1508. /**
  1509. * Generates a number field input for a model attribute.
  1510. * If the attribute has input error, the input field's CSS class will
  1511. * be appended with {@link errorCss}.
  1512. * @param CModel $model the data model
  1513. * @param string $attribute the attribute
  1514. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1515. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1516. * @return string the generated input field
  1517. * @see clientChange
  1518. * @see activeInputField
  1519. * @since 1.1.11
  1520. */
  1521. public static function activeNumberField($model,$attribute,$htmlOptions=array())
  1522. {
  1523. self::resolveNameID($model,$attribute,$htmlOptions);
  1524. self::clientChange('change',$htmlOptions);
  1525. return self::activeInputField('number',$model,$attribute,$htmlOptions);
  1526. }
  1527. /**
  1528. * Generates a range field input for a model attribute.
  1529. * If the attribute has input error, the input field's CSS class will
  1530. * be appended with {@link errorCss}.
  1531. * @param CModel $model the data model
  1532. * @param string $attribute the attribute
  1533. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1534. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1535. * @return string the generated input field
  1536. * @see clientChange
  1537. * @see activeInputField
  1538. * @since 1.1.11
  1539. */
  1540. public static function activeRangeField($model,$attribute,$htmlOptions=array())
  1541. {
  1542. self::resolveNameID($model,$attribute,$htmlOptions);
  1543. self::clientChange('change',$htmlOptions);
  1544. return self::activeInputField('range',$model,$attribute,$htmlOptions);
  1545. }
  1546. /**
  1547. * Generates a date field input for a model attribute.
  1548. * If the attribute has input error, the input field's CSS class will
  1549. * be appended with {@link errorCss}.
  1550. * @param CModel $model the data model
  1551. * @param string $attribute the attribute
  1552. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1553. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1554. * @return string the generated input field
  1555. * @see clientChange
  1556. * @see activeInputField
  1557. * @since 1.1.11
  1558. */
  1559. public static function activeDateField($model,$attribute,$htmlOptions=array())
  1560. {
  1561. self::resolveNameID($model,$attribute,$htmlOptions);
  1562. self::clientChange('change',$htmlOptions);
  1563. return self::activeInputField('date',$model,$attribute,$htmlOptions);
  1564. }
  1565. /**
  1566. * Generates a time field input for a model attribute.
  1567. * If the attribute has input error, the input field's CSS class will
  1568. * be appended with {@link errorCss}.
  1569. * @param CModel $model the data model
  1570. * @param string $attribute the attribute
  1571. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1572. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1573. * @return string the generated input field
  1574. * @see clientChange
  1575. * @see activeInputField
  1576. * @since 1.1.14
  1577. */
  1578. public static function activeTimeField($model,$attribute,$htmlOptions=array())
  1579. {
  1580. self::resolveNameID($model,$attribute,$htmlOptions);
  1581. self::clientChange('change',$htmlOptions);
  1582. return self::activeInputField('time',$model,$attribute,$htmlOptions);
  1583. }
  1584. /**
  1585. * Generates a datetime field input for a model attribute.
  1586. * If the attribute has input error, the input field's CSS class will
  1587. * be appended with {@link errorCss}.
  1588. * @param CModel $model the data model
  1589. * @param string $attribute the attribute
  1590. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1591. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1592. * @return string the generated input field
  1593. * @see clientChange
  1594. * @see activeInputField
  1595. * @since 1.1.16
  1596. */
  1597. public static function activeDateTimeField($model,$attribute,$htmlOptions=array())
  1598. {
  1599. self::resolveNameID($model,$attribute,$htmlOptions);
  1600. self::clientChange('change',$htmlOptions);
  1601. return self::activeInputField('datetime',$model,$attribute,$htmlOptions);
  1602. }
  1603. /**
  1604. * Generates a datetime-local field input for a model attribute.
  1605. * If the attribute has input error, the input field's CSS class will
  1606. * be appended with {@link errorCss}.
  1607. * @param CModel $model the data model
  1608. * @param string $attribute the attribute
  1609. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1610. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1611. * @return string the generated input field
  1612. * @see clientChange
  1613. * @see activeInputField
  1614. * @since 1.1.16
  1615. */
  1616. public static function activeDateTimeLocalField($model,$attribute,$htmlOptions=array())
  1617. {
  1618. self::resolveNameID($model,$attribute,$htmlOptions);
  1619. self::clientChange('change',$htmlOptions);
  1620. return self::activeInputField('datetime-local',$model,$attribute,$htmlOptions);
  1621. }
  1622. /**
  1623. * Generates a week field input for a model attribute.
  1624. * If the attribute has input error, the input field's CSS class will
  1625. * be appended with {@link errorCss}.
  1626. * @param CModel $model the data model
  1627. * @param string $attribute the attribute
  1628. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1629. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1630. * @return string the generated input field
  1631. * @see clientChange
  1632. * @see activeInputField
  1633. * @since 1.1.16
  1634. */
  1635. public static function activeWeekField($model,$attribute,$htmlOptions=array())
  1636. {
  1637. self::resolveNameID($model,$attribute,$htmlOptions);
  1638. self::clientChange('change',$htmlOptions);
  1639. return self::activeInputField('week',$model,$attribute,$htmlOptions);
  1640. }
  1641. /**
  1642. * Generates a color picker field input for a model attribute.
  1643. * If the attribute has input error, the input field's CSS class will
  1644. * be appended with {@link errorCss}.
  1645. * @param CModel $model the data model
  1646. * @param string $attribute the attribute
  1647. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1648. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1649. * @return string the generated input field
  1650. * @see clientChange
  1651. * @see activeInputField
  1652. * @since 1.1.16
  1653. */
  1654. public static function activeColorField($model,$attribute,$htmlOptions=array())
  1655. {
  1656. self::resolveNameID($model,$attribute,$htmlOptions);
  1657. self::clientChange('change',$htmlOptions);
  1658. return self::activeInputField('color',$model,$attribute,$htmlOptions);
  1659. }
  1660. /**
  1661. * Generates a telephone field input for a model attribute.
  1662. * If the attribute has input error, the input field's CSS class will
  1663. * be appended with {@link errorCss}.
  1664. * @param CModel $model the data model
  1665. * @param string $attribute the attribute
  1666. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1667. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1668. * @return string the generated input field
  1669. * @see clientChange
  1670. * @see activeInputField
  1671. * @since 1.1.14
  1672. */
  1673. public static function activeTelField($model,$attribute,$htmlOptions=array())
  1674. {
  1675. self::resolveNameID($model,$attribute,$htmlOptions);
  1676. self::clientChange('change',$htmlOptions);
  1677. return self::activeInputField('tel',$model,$attribute,$htmlOptions);
  1678. }
  1679. /**
  1680. * Generates a hidden input for a model attribute.
  1681. * @param CModel $model the data model
  1682. * @param string $attribute the attribute
  1683. * @param array $htmlOptions additional HTML attributes.
  1684. * @return string the generated input field
  1685. * @see activeInputField
  1686. */
  1687. public static function activeHiddenField($model,$attribute,$htmlOptions=array())
  1688. {
  1689. self::resolveNameID($model,$attribute,$htmlOptions);
  1690. return self::activeInputField('hidden',$model,$attribute,$htmlOptions);
  1691. }
  1692. /**
  1693. * Generates a password field input for a model attribute.
  1694. * If the attribute has input error, the input field's CSS class will
  1695. * be appended with {@link errorCss}.
  1696. * @param CModel $model the data model
  1697. * @param string $attribute the attribute
  1698. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1699. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1700. * @return string the generated input field
  1701. * @see clientChange
  1702. * @see activeInputField
  1703. */
  1704. public static function activePasswordField($model,$attribute,$htmlOptions=array())
  1705. {
  1706. self::resolveNameID($model,$attribute,$htmlOptions);
  1707. self::clientChange('change',$htmlOptions);
  1708. return self::activeInputField('password',$model,$attribute,$htmlOptions);
  1709. }
  1710. /**
  1711. * Generates a text area input for a model attribute.
  1712. * If the attribute has input error, the input field's CSS class will
  1713. * be appended with {@link errorCss}.
  1714. * @param CModel $model the data model
  1715. * @param string $attribute the attribute
  1716. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1717. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1718. * @return string the generated text area
  1719. * @see clientChange
  1720. */
  1721. public static function activeTextArea($model,$attribute,$htmlOptions=array())
  1722. {
  1723. self::resolveNameID($model,$attribute,$htmlOptions);
  1724. self::clientChange('change',$htmlOptions);
  1725. if($model->hasErrors($attribute))
  1726. self::addErrorCss($htmlOptions);
  1727. if(isset($htmlOptions['value']))
  1728. {
  1729. $text=$htmlOptions['value'];
  1730. unset($htmlOptions['value']);
  1731. }
  1732. else
  1733. $text=self::resolveValue($model,$attribute);
  1734. return self::tag('textarea',$htmlOptions,isset($htmlOptions['encode']) && !$htmlOptions['encode'] ? $text : self::encode($text));
  1735. }
  1736. /**
  1737. * Generates a file input for a model attribute.
  1738. * Note, you have to set the enclosing form's 'enctype' attribute to be 'multipart/form-data'.
  1739. * After the form is submitted, the uploaded file information can be obtained via $_FILES (see
  1740. * PHP documentation).
  1741. * @param CModel $model the data model
  1742. * @param string $attribute the attribute
  1743. * @param array $htmlOptions additional HTML attributes (see {@link tag}).
  1744. * @return string the generated input field
  1745. * @see activeInputField
  1746. */
  1747. public static function activeFileField($model,$attribute,$htmlOptions=array())
  1748. {
  1749. self::resolveNameID($model,$attribute,$htmlOptions);
  1750. // add a hidden field so that if a model only has a file field, we can
  1751. // still use isset($_POST[$modelClass]) to detect if the input is submitted
  1752. $hiddenOptions=isset($htmlOptions['id']) ? array('id'=>self::ID_PREFIX.$htmlOptions['id']) : array('id'=>false);
  1753. return self::hiddenField($htmlOptions['name'],'',$hiddenOptions)
  1754. . self::activeInputField('file',$model,$attribute,$htmlOptions);
  1755. }
  1756. /**
  1757. * Generates a radio button for a model attribute.
  1758. * If the attribute has input error, the input field's CSS class will
  1759. * be appended with {@link errorCss}.
  1760. * @param CModel $model the data model
  1761. * @param string $attribute the attribute
  1762. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1763. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1764. * A special option named 'uncheckValue' is available that can be used to specify
  1765. * the value returned when the radio button is not checked. By default, this value is '0'.
  1766. * Internally, a hidden field is rendered so that when the radio button is not checked,
  1767. * we can still obtain the posted uncheck value.
  1768. * If 'uncheckValue' is set as NULL, the hidden field will not be rendered.
  1769. * @return string the generated radio button
  1770. * @see clientChange
  1771. * @see activeInputField
  1772. */
  1773. public static function activeRadioButton($model,$attribute,$htmlOptions=array())
  1774. {
  1775. self::resolveNameID($model,$attribute,$htmlOptions);
  1776. if(!isset($htmlOptions['value']))
  1777. $htmlOptions['value']=1;
  1778. if(!isset($htmlOptions['checked']) && self::resolveValue($model,$attribute)==$htmlOptions['value'])
  1779. $htmlOptions['checked']='checked';
  1780. self::clientChange('click',$htmlOptions);
  1781. if(array_key_exists('uncheckValue',$htmlOptions))
  1782. {
  1783. $uncheck=$htmlOptions['uncheckValue'];
  1784. unset($htmlOptions['uncheckValue']);
  1785. }
  1786. else
  1787. $uncheck='0';
  1788. $hiddenOptions=isset($htmlOptions['id']) ? array('id'=>self::ID_PREFIX.$htmlOptions['id']) : array('id'=>false);
  1789. $hidden=$uncheck!==null ? self::hiddenField($htmlOptions['name'],$uncheck,$hiddenOptions) : '';
  1790. // add a hidden field so that if the radio button is not selected, it still submits a value
  1791. return $hidden . self::activeInputField('radio',$model,$attribute,$htmlOptions);
  1792. }
  1793. /**
  1794. * Generates a check box for a model attribute.
  1795. * The attribute is assumed to take either true or false value.
  1796. * If the attribute has input error, the input field's CSS class will
  1797. * be appended with {@link errorCss}.
  1798. * @param CModel $model the data model
  1799. * @param string $attribute the attribute
  1800. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1801. * attributes are also recognized (see {@link clientChange} and {@link tag} for more details.)
  1802. * A special option named 'uncheckValue' is available that can be used to specify
  1803. * the value returned when the checkbox is not checked. By default, this value is '0'.
  1804. * Internally, a hidden field is rendered so that when the checkbox is not checked,
  1805. * we can still obtain the posted uncheck value.
  1806. * If 'uncheckValue' is set as NULL, the hidden field will not be rendered.
  1807. * @return string the generated check box
  1808. * @see clientChange
  1809. * @see activeInputField
  1810. */
  1811. public static function activeCheckBox($model,$attribute,$htmlOptions=array())
  1812. {
  1813. self::resolveNameID($model,$attribute,$htmlOptions);
  1814. if(!isset($htmlOptions['value']))
  1815. $htmlOptions['value']=1;
  1816. if(!isset($htmlOptions['checked']) && self::resolveValue($model,$attribute)==$htmlOptions['value'])
  1817. $htmlOptions['checked']='checked';
  1818. self::clientChange('click',$htmlOptions);
  1819. if(array_key_exists('uncheckValue',$htmlOptions))
  1820. {
  1821. $uncheck=$htmlOptions['uncheckValue'];
  1822. unset($htmlOptions['uncheckValue']);
  1823. }
  1824. else
  1825. $uncheck='0';
  1826. $hiddenOptions=isset($htmlOptions['id']) ? array('id'=>self::ID_PREFIX.$htmlOptions['id']) : array('id'=>false);
  1827. $hidden=$uncheck!==null ? self::hiddenField($htmlOptions['name'],$uncheck,$hiddenOptions) : '';
  1828. return $hidden . self::activeInputField('checkbox',$model,$attribute,$htmlOptions);
  1829. }
  1830. /**
  1831. * Generates a drop down list for a model attribute.
  1832. * If the attribute has input error, the input field's CSS class will
  1833. * be appended with {@link errorCss}.
  1834. * @param CModel $model the data model
  1835. * @param string $attribute the attribute
  1836. * @param array $data data for generating the list options (value=>display)
  1837. * You may use {@link listData} to generate this data.
  1838. * Please refer to {@link listOptions} on how this data is used to generate the list options.
  1839. * Note, the values and labels will be automatically HTML-encoded by this method.
  1840. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1841. * attributes are recognized. See {@link clientChange} and {@link tag} for more details.
  1842. * In addition, the following options are also supported:
  1843. * <ul>
  1844. * <li>encode: boolean, specifies whether to encode the values. Defaults to true.</li>
  1845. * <li>prompt: string, specifies the prompt text shown as the first list option. Its value is empty. Note, the prompt text will NOT be HTML-encoded.</li>
  1846. * <li>empty: string, specifies the text corresponding to empty selection. Its value is empty.
  1847. * The 'empty' option can also be an array of value-label pairs.
  1848. * Each pair will be used to render a list option at the beginning. Note, the text label will NOT be HTML-encoded.</li>
  1849. * <li>options: array, specifies additional attributes for each OPTION tag.
  1850. * The array keys must be the option values, and the array values are the extra
  1851. * OPTION tag attributes in the name-value pairs. For example,
  1852. * <pre>
  1853. * array(
  1854. * 'value1'=>array('disabled'=>true,'label'=>'value 1'),
  1855. * 'value2'=>array('label'=>'value 2'),
  1856. * );
  1857. * </pre>
  1858. * </li>
  1859. * </ul>
  1860. * Since 1.1.13, a special option named 'unselectValue' is available. It can be used to set the value
  1861. * that will be returned when no option is selected in multiple mode. When set, a hidden field is
  1862. * rendered so that if no option is selected in multiple mode, we can still obtain the posted
  1863. * unselect value. If 'unselectValue' is not set or set to NULL, the hidden field will not be rendered.
  1864. * @return string the generated drop down list
  1865. * @see clientChange
  1866. * @see listData
  1867. */
  1868. public static function activeDropDownList($model,$attribute,$data,$htmlOptions=array())
  1869. {
  1870. self::resolveNameID($model,$attribute,$htmlOptions);
  1871. $selection=self::resolveValue($model,$attribute);
  1872. $options="\n".self::listOptions($selection,$data,$htmlOptions);
  1873. self::clientChange('change',$htmlOptions);
  1874. if($model->hasErrors($attribute))
  1875. self::addErrorCss($htmlOptions);
  1876. $hidden='';
  1877. if(!empty($htmlOptions['multiple']))
  1878. {
  1879. if(substr($htmlOptions['name'],-2)!=='[]')
  1880. $htmlOptions['name'].='[]';
  1881. if(isset($htmlOptions['unselectValue']))
  1882. {
  1883. $hiddenOptions=isset($htmlOptions['id']) ? array('id'=>self::ID_PREFIX.$htmlOptions['id']) : array('id'=>false);
  1884. $hidden=self::hiddenField(substr($htmlOptions['name'],0,-2),$htmlOptions['unselectValue'],$hiddenOptions);
  1885. unset($htmlOptions['unselectValue']);
  1886. }
  1887. }
  1888. return $hidden . self::tag('select',$htmlOptions,$options);
  1889. }
  1890. /**
  1891. * Generates a list box for a model attribute.
  1892. * The model attribute value is used as the selection.
  1893. * If the attribute has input error, the input field's CSS class will
  1894. * be appended with {@link errorCss}.
  1895. * @param CModel $model the data model
  1896. * @param string $attribute the attribute
  1897. * @param array $data data for generating the list options (value=>display)
  1898. * You may use {@link listData} to generate this data.
  1899. * Please refer to {@link listOptions} on how this data is used to generate the list options.
  1900. * Note, the values and labels will be automatically HTML-encoded by this method.
  1901. * @param array $htmlOptions additional HTML attributes. Besides normal HTML attributes, a few special
  1902. * attributes are recognized. See {@link clientChange} and {@link tag} for more details.
  1903. * In addition, the following options are also supported:
  1904. * <ul>
  1905. * <li>encode: boolean, specifies whether to encode the values. Defaults to true.</li>
  1906. * <li>prompt: string, specifies the prompt text shown as the first list option. Its value is empty. Note, the prompt text will NOT be HTML-encoded.</li>
  1907. * <li>empty: string, specifies the text corresponding to empty selection. Its value is empty.
  1908. * The 'empty' option can also be an array of value-label pairs.
  1909. * Each pair will be used to render a list option at the beginning. Note, the text label will NOT be HTML-encoded.</li>
  1910. * <li>options: array, specifies additional attributes for each OPTION tag.
  1911. * The array keys must be the option values, and the array values are the extra
  1912. * OPTION tag attributes in the name-value pairs. For example,
  1913. * <pre>
  1914. * array(
  1915. * 'value1'=>array('disabled'=>true,'label'=>'value 1'),
  1916. * 'value2'=>array('label'=>'value 2'),
  1917. * );
  1918. * </pre>
  1919. * </li>
  1920. * </ul>
  1921. * @return string the generated list box
  1922. * @see clientChange
  1923. * @see listData
  1924. */
  1925. public static function activeListBox($model,$attribute,$data,$htmlOptions=array())
  1926. {
  1927. if(!isset($htmlOptions['size']))
  1928. $htmlOptions['size']=4;
  1929. return self::activeDropDownList($model,$attribute,$data,$htmlOptions);
  1930. }
  1931. /**
  1932. * Generates a check box list for a model attribute.
  1933. * The model attribute value is used as the selection.
  1934. * If the attribute has input error, the input field's CSS class will
  1935. * be appended with {@link errorCss}.
  1936. * Note that a check box list allows multiple selection, like {@link listBox}.
  1937. * As a result, the corresponding POST value is an array. In case no selection
  1938. * is made, the corresponding POST value is an empty string.
  1939. * @param CModel $model the data model
  1940. * @param string $attribute the attribute
  1941. * @param array $data value-label pairs used to generate the check box list.
  1942. * Note, the values will be automatically HTML-encoded, while the labels will not.
  1943. * @param array $htmlOptions additional HTML options. The options will be applied to
  1944. * each checkbox input. The following special options are recognized:
  1945. * <ul>
  1946. * <li>template: string, specifies how each checkbox is rendered. Defaults
  1947. * to "{input} {label}", where "{input}" will be replaced by the generated
  1948. * check box input tag while "{label}" will be replaced by the corresponding check box label.</li>
  1949. * <li>separator: string, specifies the string that separates the generated check boxes.</li>
  1950. * <li>checkAll: string, specifies the label for the "check all" checkbox.
  1951. * If this option is specified, a 'check all' checkbox will be displayed. Clicking on
  1952. * this checkbox will cause all checkboxes checked or unchecked.</li>
  1953. * <li>checkAllLast: boolean, specifies whether the 'check all' checkbox should be
  1954. * displayed at the end of the checkbox list. If this option is not set (default)
  1955. * or is false, the 'check all' checkbox will be displayed at the beginning of
  1956. * the checkbox list.</li>
  1957. * <li>encode: boolean, specifies whether to encode HTML-encode tag attributes and values. Defaults to true.</li>
  1958. * <li>labelOptions: array, specifies the additional HTML attributes to be rendered
  1959. * for every label tag in the list.</li>
  1960. * <li>container: string, specifies the checkboxes enclosing tag. Defaults to 'span'.
  1961. * If the value is an empty string, no enclosing tag will be generated</li>
  1962. * <li>baseID: string, specifies the base ID prefix to be used for checkboxes in the list.
  1963. * This option is available since version 1.1.13.</li>
  1964. * </ul>
  1965. * Since 1.1.7, a special option named 'uncheckValue' is available. It can be used to set the value
  1966. * that will be returned when the checkbox is not checked. By default, this value is ''.
  1967. * Internally, a hidden field is rendered so when the checkbox is not checked, we can still
  1968. * obtain the value. If 'uncheckValue' is set to NULL, there will be no hidden field rendered.
  1969. * @return string the generated check box list
  1970. * @see checkBoxList
  1971. */
  1972. public static function activeCheckBoxList($model,$attribute,$data,$htmlOptions=array())
  1973. {
  1974. self::resolveNameID($model,$attribute,$htmlOptions);
  1975. $selection=self::resolveValue($model,$attribute);
  1976. if($model->hasErrors($attribute))
  1977. self::addErrorCss($htmlOptions);
  1978. $name=$htmlOptions['name'];
  1979. unset($htmlOptions['name']);
  1980. if(array_key_exists('uncheckValue',$htmlOptions))
  1981. {
  1982. $uncheck=$htmlOptions['uncheckValue'];
  1983. unset($htmlOptions['uncheckValue']);
  1984. }
  1985. else
  1986. $uncheck='';
  1987. $hiddenOptions=isset($htmlOptions['id']) ? array('id'=>self::ID_PREFIX.$htmlOptions['id']) : array('id'=>false);
  1988. $hidden=$uncheck!==null ? self::hiddenField($name,$uncheck,$hiddenOptions) : '';
  1989. return $hidden . self::checkBoxList($name,$selection,$data,$htmlOptions);
  1990. }
  1991. /**
  1992. * Generates a radio button list for a model attribute.
  1993. * The model attribute value is used as the selection.
  1994. * If the attribute has input error, the input field's CSS class will
  1995. * be appended with {@link errorCss}.
  1996. * @param CModel $model the data model
  1997. * @param string $attribute the attribute
  1998. * @param array $data value-label pairs used to generate the radio button list.
  1999. * Note, the values will be automatically HTML-encoded, while the labels will not.
  2000. * @param array $htmlOptions additional HTML options. The options will be applied to
  2001. * each radio button input. The following special options are recognized:
  2002. * <ul>
  2003. * <li>template: string, specifies how each radio button is rendered. Defaults
  2004. * to "{input} {label}", where "{input}" will be replaced by the generated
  2005. * radio button input tag while "{label}" will be replaced by the corresponding radio button label,
  2006. * {beginLabel} will be replaced by &lt;label&gt; with labelOptions, {labelTitle} will be replaced
  2007. * by the corresponding radio button label title and {endLabel} will be replaced by &lt;/label&gt;</li>
  2008. * <li>separator: string, specifies the string that separates the generated radio buttons. Defaults to new line (<br/>).</li>
  2009. * <li>encode: boolean, specifies whether to encode HTML-encode tag attributes and values. Defaults to true.</li>
  2010. * <li>labelOptions: array, specifies the additional HTML attributes to be rendered
  2011. * for every label tag in the list.</li>
  2012. * <li>container: string, specifies the radio buttons enclosing tag. Defaults to 'span'.
  2013. * If the value is an empty string, no enclosing tag will be generated</li>
  2014. * <li>baseID: string, specifies the base ID prefix to be used for radio buttons in the list.
  2015. * This option is available since version 1.1.13.</li>
  2016. * <li>empty: string, specifies the text corresponding to empty selection. Its value is empty.
  2017. * The 'empty' option can also be an array of value-label pairs.
  2018. * Each pair will be used to render a radio button at the beginning. Note, the text label will NOT be HTML-encoded.
  2019. * This option is available since version 1.1.14.</li>
  2020. * </ul>
  2021. * Since version 1.1.7, a special option named 'uncheckValue' is available that can be used to specify the value
  2022. * returned when the radio button is not checked. By default, this value is ''. Internally, a hidden field is
  2023. * rendered so that when the radio button is not checked, we can still obtain the posted uncheck value.
  2024. * If 'uncheckValue' is set as NULL, the hidden field will not be rendered.
  2025. * @return string the generated radio button list
  2026. * @see radioButtonList
  2027. */
  2028. public static function activeRadioButtonList($model,$attribute,$data,$htmlOptions=array())
  2029. {
  2030. self::resolveNameID($model,$attribute,$htmlOptions);
  2031. $selection=self::resolveValue($model,$attribute);
  2032. if($model->hasErrors($attribute))
  2033. self::addErrorCss($htmlOptions);
  2034. $name=$htmlOptions['name'];
  2035. unset($htmlOptions['name']);
  2036. if(array_key_exists('uncheckValue',$htmlOptions))
  2037. {
  2038. $uncheck=$htmlOptions['uncheckValue'];
  2039. unset($htmlOptions['uncheckValue']);
  2040. }
  2041. else
  2042. $uncheck='';
  2043. $hiddenOptions=isset($htmlOptions['id']) ? array('id'=>self::ID_PREFIX.$htmlOptions['id']) : array('id'=>false);
  2044. $hidden=$uncheck!==null ? self::hiddenField($name,$uncheck,$hiddenOptions) : '';
  2045. return $hidden . self::radioButtonList($name,$selection,$data,$htmlOptions);
  2046. }
  2047. /**
  2048. * Displays a summary of validation errors for one or several models.
  2049. * @param mixed $model the models whose input errors are to be displayed. This can be either
  2050. * a single model or an array of models.
  2051. * @param string $header a piece of HTML code that appears in front of the errors
  2052. * @param string $footer a piece of HTML code that appears at the end of the errors
  2053. * @param array $htmlOptions additional HTML attributes to be rendered in the container div tag.
  2054. * A special option named 'firstError' is recognized, which when set true, will
  2055. * make the error summary to show only the first error message of each attribute.
  2056. * If this is not set or is false, all error messages will be displayed.
  2057. * This option has been available since version 1.1.3.
  2058. * @return string the error summary. Empty if no errors are found.
  2059. * @see CModel::getErrors
  2060. * @see errorSummaryCss
  2061. */
  2062. public static function errorSummary($model,$header=null,$footer=null,$htmlOptions=array())
  2063. {
  2064. $content='';
  2065. if(!is_array($model))
  2066. $model=array($model);
  2067. if(isset($htmlOptions['firstError']))
  2068. {
  2069. $firstError=$htmlOptions['firstError'];
  2070. unset($htmlOptions['firstError']);
  2071. }
  2072. else
  2073. $firstError=false;
  2074. foreach($model as $m)
  2075. {
  2076. foreach($m->getErrors() as $errors)
  2077. {
  2078. foreach($errors as $error)
  2079. {
  2080. if($error!='')
  2081. $content.="<li>$error</li>\n";
  2082. if($firstError)
  2083. break;
  2084. }
  2085. }
  2086. }
  2087. if($content!=='')
  2088. {
  2089. if($header===null)
  2090. $header='<p>'.Yii::t('yii','Please fix the following input errors:').'</p>';
  2091. if(!isset($htmlOptions['class']))
  2092. $htmlOptions['class']=self::$errorSummaryCss;
  2093. return self::tag('div',$htmlOptions,$header."\n<ul>\n$content</ul>".$footer);
  2094. }
  2095. else
  2096. return '';
  2097. }
  2098. /**
  2099. * Displays the first validation error for a model attribute.
  2100. * @param CModel $model the data model
  2101. * @param string $attribute the attribute name
  2102. * @param array $htmlOptions additional HTML attributes to be rendered in the container tag.
  2103. * @return string the error display. Empty if no errors are found.
  2104. * @see CModel::getErrors
  2105. * @see errorMessageCss
  2106. * @see $errorContainerTag
  2107. */
  2108. public static function error($model,$attribute,$htmlOptions=array())
  2109. {
  2110. self::resolveName($model,$attribute); // turn [a][b]attr into attr
  2111. $error=$model->getError($attribute);
  2112. if($error!='')
  2113. {
  2114. if(!isset($htmlOptions['class']))
  2115. $htmlOptions['class']=self::$errorMessageCss;
  2116. return self::tag(self::$errorContainerTag,$htmlOptions,$error);
  2117. }
  2118. else
  2119. return '';
  2120. }
  2121. /**
  2122. * Generates the data suitable for list-based HTML elements.
  2123. * The generated data can be used in {@link dropDownList}, {@link listBox}, {@link checkBoxList},
  2124. * {@link radioButtonList}, and their active-versions (such as {@link activeDropDownList}).
  2125. * Note, this method does not HTML-encode the generated data. You may call {@link encodeArray} to
  2126. * encode it if needed.
  2127. * Please refer to the {@link value} method on how to specify value field, text field and group field.
  2128. * You can also pass anonymous functions as second, third and fourth arguments which calculates
  2129. * text field value (PHP 5.3+ only) since 1.1.13. Your anonymous function should receive one argument,
  2130. * which is the model, the current &lt;option&gt; tag is generated from.
  2131. *
  2132. * <pre>
  2133. * CHtml::listData($posts,'id',function($post) {
  2134. * return CHtml::encode($post->title);
  2135. * });
  2136. * </pre>
  2137. *
  2138. * @param array $models a list of model objects. This parameter
  2139. * can also be an array of associative arrays (e.g. results of {@link CDbCommand::queryAll}).
  2140. * @param mixed $valueField the attribute name or anonymous function (PHP 5.3+) for list option values
  2141. * @param mixed $textField the attribute name or anonymous function (PHP 5.3+) for list option texts
  2142. * @param mixed $groupField the attribute name or anonymous function (PHP 5.3+) for list option group names. If empty, no group will be generated.
  2143. * @return array the list data that can be used in {@link dropDownList}, {@link listBox}, etc.
  2144. */
  2145. public static function listData($models,$valueField,$textField,$groupField='')
  2146. {
  2147. $listData=array();
  2148. if($groupField==='')
  2149. {
  2150. foreach($models as $model)
  2151. {
  2152. $value=self::value($model,$valueField);
  2153. $text=self::value($model,$textField);
  2154. $listData[$value]=$text;
  2155. }
  2156. }
  2157. else
  2158. {
  2159. foreach($models as $model)
  2160. {
  2161. $group=self::value($model,$groupField);
  2162. $value=self::value($model,$valueField);
  2163. $text=self::value($model,$textField);
  2164. if($group===null)
  2165. $listData[$value]=$text;
  2166. else
  2167. $listData[$group][$value]=$text;
  2168. }
  2169. }
  2170. return $listData;
  2171. }
  2172. /**
  2173. * Evaluates the value of the specified attribute for the given model.
  2174. * The attribute name can be given in a dot syntax. For example, if the attribute
  2175. * is "author.firstName", this method will return the value of "$model->author->firstName".
  2176. * A default value (passed as the last parameter) will be returned if the attribute does
  2177. * not exist or is broken in the middle (e.g. $model->author is null).
  2178. * The model can be either an object or an array. If the latter, the attribute is treated
  2179. * as a key of the array. For the example of "author.firstName", if would mean the array value
  2180. * "$model['author']['firstName']".
  2181. *
  2182. * Anonymous function could also be used for attribute calculation since 1.1.13
  2183. * ($attribute parameter; PHP 5.3+ only) as follows:
  2184. * <pre>
  2185. * $taskClosedSecondsAgo=CHtml::value($closedTask,function($model) {
  2186. * return time()-$model->closed_at;
  2187. * });
  2188. * </pre>
  2189. * Your anonymous function should receive one argument, which is the model, the current
  2190. * value is calculated from. This feature could be used together with the {@link listData}.
  2191. * Please refer to its documentation for more details.
  2192. *
  2193. * @param mixed $model the model. This can be either an object or an array.
  2194. * @param mixed $attribute the attribute name (use dot to concatenate multiple attributes)
  2195. * or anonymous function (PHP 5.3+). Remember that functions created by "create_function"
  2196. * are not supported by this method. Also note that numeric value is meaningless when
  2197. * first parameter is object typed.
  2198. * @param mixed $defaultValue the default value to return when the attribute does not exist.
  2199. * @return mixed the attribute value.
  2200. */
  2201. public static function value($model,$attribute,$defaultValue=null)
  2202. {
  2203. if(is_scalar($attribute) || $attribute===null)
  2204. foreach(explode('.',$attribute) as $name)
  2205. {
  2206. if(is_object($model) && isset($model->$name))
  2207. $model=$model->$name;
  2208. elseif(is_array($model) && isset($model[$name]))
  2209. $model=$model[$name];
  2210. else
  2211. return $defaultValue;
  2212. }
  2213. else
  2214. return call_user_func($attribute,$model);
  2215. return $model;
  2216. }
  2217. /**
  2218. * Generates a valid HTML ID based on name.
  2219. * @param string $name name from which to generate HTML ID
  2220. * @return string the ID generated based on name.
  2221. */
  2222. public static function getIdByName($name)
  2223. {
  2224. return str_replace(array('[]','][','[',']',' '),array('','_','_','','_'),$name);
  2225. }
  2226. /**
  2227. * Generates input field ID for a model attribute.
  2228. * @param CModel $model the data model
  2229. * @param string $attribute the attribute
  2230. * @return string the generated input field ID
  2231. */
  2232. public static function activeId($model,$attribute)
  2233. {
  2234. return self::getIdByName(self::activeName($model,$attribute));
  2235. }
  2236. /**
  2237. * Generates HTML name for given model.
  2238. * @see CHtml::setModelNameConverter()
  2239. * @param CModel|string $model the data model or the model class name
  2240. * @return string the generated HTML name value
  2241. * @since 1.1.14
  2242. */
  2243. public static function modelName($model)
  2244. {
  2245. if(is_callable(self::$_modelNameConverter))
  2246. return call_user_func(self::$_modelNameConverter,$model);
  2247. $className=is_object($model) ? get_class($model) : (string)$model;
  2248. return trim(str_replace('\\','_',$className),'_');
  2249. }
  2250. /**
  2251. * Set generator used in the {@link CHtml::modelName()} method. You can use the `null` value to restore default
  2252. * generator.
  2253. *
  2254. * @param callback|null $converter the new generator, the model or class name will be passed to the this callback
  2255. * and result must be a valid value for HTML name attribute.
  2256. * @throws CException if $converter isn't a valid callback
  2257. * @since 1.1.14
  2258. */
  2259. public static function setModelNameConverter($converter)
  2260. {
  2261. if(is_callable($converter))
  2262. self::$_modelNameConverter=$converter;
  2263. elseif($converter===null)
  2264. self::$_modelNameConverter=null;
  2265. else
  2266. throw new CException(Yii::t('yii','The $converter argument must be a valid callback or null.'));
  2267. }
  2268. /**
  2269. * Generates input field name for a model attribute.
  2270. * Unlike {@link resolveName}, this method does NOT modify the attribute name.
  2271. * @param CModel $model the data model
  2272. * @param string $attribute the attribute
  2273. * @return string the generated input field name
  2274. */
  2275. public static function activeName($model,$attribute)
  2276. {
  2277. $a=$attribute; // because the attribute name may be changed by resolveName
  2278. return self::resolveName($model,$a);
  2279. }
  2280. /**
  2281. * Generates an input HTML tag for a model attribute.
  2282. * This method generates an input HTML tag based on the given data model and attribute.
  2283. * If the attribute has input error, the input field's CSS class will
  2284. * be appended with {@link errorCss}.
  2285. * This enables highlighting the incorrect input.
  2286. * @param string $type the input type (e.g. 'text', 'radio')
  2287. * @param CModel $model the data model
  2288. * @param string $attribute the attribute
  2289. * @param array $htmlOptions additional HTML attributes for the HTML tag
  2290. * @return string the generated input tag
  2291. */
  2292. protected static function activeInputField($type,$model,$attribute,$htmlOptions)
  2293. {
  2294. $htmlOptions['type']=$type;
  2295. if($type==='text'||$type==='password'||$type==='color'||$type==='date'||$type==='datetime'||
  2296. $type==='datetime-local'||$type==='email'||$type==='month'||$type==='number'||$type==='range'||
  2297. $type==='search'||$type==='tel'||$type==='time'||$type==='url'||$type==='week')
  2298. {
  2299. if(!isset($htmlOptions['maxlength']))
  2300. {
  2301. foreach($model->getValidators($attribute) as $validator)
  2302. {
  2303. if($validator instanceof CStringValidator && $validator->max!==null)
  2304. {
  2305. $htmlOptions['maxlength']=$validator->max;
  2306. break;
  2307. }
  2308. }
  2309. }
  2310. elseif($htmlOptions['maxlength']===false)
  2311. unset($htmlOptions['maxlength']);
  2312. }
  2313. if($type==='file')
  2314. unset($htmlOptions['value']);
  2315. elseif(!isset($htmlOptions['value']))
  2316. $htmlOptions['value']=self::resolveValue($model,$attribute);
  2317. if($model->hasErrors($attribute))
  2318. self::addErrorCss($htmlOptions);
  2319. return self::tag('input',$htmlOptions);
  2320. }
  2321. /**
  2322. * Generates the list options.
  2323. * @param mixed $selection the selected value(s). This can be either a string for single selection or an array for multiple selections.
  2324. * @param array $listData the option data (see {@link listData})
  2325. * @param array $htmlOptions additional HTML attributes. The following two special attributes are recognized:
  2326. * <ul>
  2327. * <li>encode: boolean, specifies whether to encode the values. Defaults to true.</li>
  2328. * <li>prompt: string, specifies the prompt text shown as the first list option. Its value is empty. Note, the prompt text will NOT be HTML-encoded.</li>
  2329. * <li>empty: string, specifies the text corresponding to empty selection. Its value is empty.
  2330. * The 'empty' option can also be an array of value-label pairs.
  2331. * Each pair will be used to render a list option at the beginning. Note, the text label will NOT be HTML-encoded.</li>
  2332. * <li>options: array, specifies additional attributes for each OPTION tag.
  2333. * The array keys must be the option values, and the array values are the extra
  2334. * OPTION tag attributes in the name-value pairs. For example,
  2335. * <pre>
  2336. * array(
  2337. * 'value1'=>array('disabled'=>true,'label'=>'value 1'),
  2338. * 'value2'=>array('label'=>'value 2'),
  2339. * );
  2340. * </pre>
  2341. * </li>
  2342. * <li>key: string, specifies the name of key attribute of the selection object(s).
  2343. * This is used when the selection is represented in terms of objects. In this case,
  2344. * the property named by the key option of the objects will be treated as the actual selection value.
  2345. * This option defaults to 'primaryKey', meaning using the 'primaryKey' property value of the objects in the selection.
  2346. * This option has been available since version 1.1.3.</li>
  2347. * </ul>
  2348. * @return string the generated list options
  2349. */
  2350. public static function listOptions($selection,$listData,&$htmlOptions)
  2351. {
  2352. $raw=isset($htmlOptions['encode']) && !$htmlOptions['encode'];
  2353. $content='';
  2354. if(isset($htmlOptions['prompt']))
  2355. {
  2356. $content.='<option value="">'.strtr($htmlOptions['prompt'],array('<'=>'&lt;','>'=>'&gt;'))."</option>\n";
  2357. unset($htmlOptions['prompt']);
  2358. }
  2359. if(isset($htmlOptions['empty']))
  2360. {
  2361. if(!is_array($htmlOptions['empty']))
  2362. $htmlOptions['empty']=array(''=>$htmlOptions['empty']);
  2363. foreach($htmlOptions['empty'] as $value=>$label)
  2364. $content.='<option value="'.self::encode($value).'">'.strtr($label,array('<'=>'&lt;','>'=>'&gt;'))."</option>\n";
  2365. unset($htmlOptions['empty']);
  2366. }
  2367. if(isset($htmlOptions['options']))
  2368. {
  2369. $options=$htmlOptions['options'];
  2370. unset($htmlOptions['options']);
  2371. }
  2372. else
  2373. $options=array();
  2374. $key=isset($htmlOptions['key']) ? $htmlOptions['key'] : 'primaryKey';
  2375. if(is_array($selection))
  2376. {
  2377. foreach($selection as $i=>$item)
  2378. {
  2379. if(is_object($item))
  2380. $selection[$i]=$item->$key;
  2381. }
  2382. }
  2383. elseif(is_object($selection))
  2384. $selection=$selection->$key;
  2385. foreach($listData as $key=>$value)
  2386. {
  2387. if(is_array($value))
  2388. {
  2389. $content.='<optgroup label="'.($raw?$key : self::encode($key))."\">\n";
  2390. $dummy=array('options'=>$options);
  2391. if(isset($htmlOptions['encode']))
  2392. $dummy['encode']=$htmlOptions['encode'];
  2393. $content.=self::listOptions($selection,$value,$dummy);
  2394. $content.='</optgroup>'."\n";
  2395. }
  2396. else
  2397. {
  2398. $attributes=array('value'=>(string)$key,'encode'=>!$raw);
  2399. if(!is_array($selection) && !strcmp($key,$selection) || is_array($selection) && in_array($key,$selection))
  2400. $attributes['selected']='selected';
  2401. if(isset($options[$key]))
  2402. $attributes=array_merge($attributes,$options[$key]);
  2403. $content.=self::tag('option',$attributes,$raw?(string)$value : self::encode((string)$value))."\n";
  2404. }
  2405. }
  2406. unset($htmlOptions['key']);
  2407. return $content;
  2408. }
  2409. /**
  2410. * Generates the JavaScript with the specified client changes.
  2411. * @param string $event event name (without 'on')
  2412. * @param array $htmlOptions HTML attributes which may contain the following special attributes
  2413. * specifying the client change behaviors:
  2414. * <ul>
  2415. * <li>submit: string, specifies the URL to submit to. If the current element has a parent form, that form will be
  2416. * submitted, and if 'submit' is non-empty its value will replace the form's URL. If there is no parent form the
  2417. * data listed in 'params' will be submitted instead (via POST method), to the URL in 'submit' or the currently
  2418. * requested URL if 'submit' is empty. Please note that if the 'csrf' setting is true, the CSRF token will be
  2419. * included in the params too.</li>
  2420. * <li>params: array, name-value pairs that should be submitted together with the form. This is only used when 'submit' option is specified.</li>
  2421. * <li>csrf: boolean, whether a CSRF token should be automatically included in 'params' when {@link CHttpRequest::enableCsrfValidation} is true. Defaults to false.
  2422. * You may want to set this to be true if there is no enclosing form around this element.
  2423. * This option is meaningful only when 'submit' option is set.</li>
  2424. * <li>return: boolean, the return value of the javascript. Defaults to false, meaning that the execution of
  2425. * javascript would not cause the default behavior of the event.</li>
  2426. * <li>confirm: string, specifies the message that should show in a pop-up confirmation dialog.</li>
  2427. * <li>ajax: array, specifies the AJAX options (see {@link ajax}).</li>
  2428. * <li>live: boolean, whether the event handler should be delegated or directly bound.
  2429. * If not set, {@link liveEvents} will be used. This option has been available since version 1.1.11.</li>
  2430. * </ul>
  2431. * This parameter has been available since version 1.1.1.
  2432. */
  2433. protected static function clientChange($event,&$htmlOptions)
  2434. {
  2435. if(!isset($htmlOptions['submit']) && !isset($htmlOptions['confirm']) && !isset($htmlOptions['ajax']))
  2436. return;
  2437. if(isset($htmlOptions['live']))
  2438. {
  2439. $live=$htmlOptions['live'];
  2440. unset($htmlOptions['live']);
  2441. }
  2442. else
  2443. $live = self::$liveEvents;
  2444. if(isset($htmlOptions['return']) && $htmlOptions['return'])
  2445. $return='return true';
  2446. else
  2447. $return='return false';
  2448. if(isset($htmlOptions['on'.$event]))
  2449. {
  2450. $handler=trim($htmlOptions['on'.$event],';').';';
  2451. unset($htmlOptions['on'.$event]);
  2452. }
  2453. else
  2454. $handler='';
  2455. if(isset($htmlOptions['id']))
  2456. $id=$htmlOptions['id'];
  2457. else
  2458. $id=$htmlOptions['id']=isset($htmlOptions['name'])?$htmlOptions['name']:self::ID_PREFIX.self::$count++;
  2459. $cs=Yii::app()->getClientScript();
  2460. $cs->registerCoreScript('jquery');
  2461. if(isset($htmlOptions['submit']))
  2462. {
  2463. $cs->registerCoreScript('yii');
  2464. $request=Yii::app()->getRequest();
  2465. if($request->enableCsrfValidation && isset($htmlOptions['csrf']) && $htmlOptions['csrf'])
  2466. $htmlOptions['params'][$request->csrfTokenName]=$request->getCsrfToken();
  2467. if(isset($htmlOptions['params']))
  2468. $params=CJavaScript::encode($htmlOptions['params']);
  2469. else
  2470. $params='{}';
  2471. if($htmlOptions['submit']!=='')
  2472. $url=CJavaScript::quote(self::normalizeUrl($htmlOptions['submit']));
  2473. else
  2474. $url='';
  2475. $handler.="jQuery.yii.submitForm(this,'$url',$params);{$return};";
  2476. }
  2477. if(isset($htmlOptions['ajax']))
  2478. $handler.=self::ajax($htmlOptions['ajax'])."{$return};";
  2479. if(isset($htmlOptions['confirm']))
  2480. {
  2481. $confirm='confirm(\''.CJavaScript::quote($htmlOptions['confirm']).'\')';
  2482. if($handler!=='')
  2483. $handler="if($confirm) {".$handler."} else return false;";
  2484. else
  2485. $handler="return $confirm;";
  2486. }
  2487. if($live)
  2488. $cs->registerScript('Yii.CHtml.#' . $id,"jQuery('body').on('$event','#$id',function(){{$handler}});");
  2489. else
  2490. $cs->registerScript('Yii.CHtml.#' . $id,"jQuery('#$id').on('$event', function(){{$handler}});");
  2491. unset($htmlOptions['params'],$htmlOptions['submit'],$htmlOptions['ajax'],$htmlOptions['confirm'],$htmlOptions['return'],$htmlOptions['csrf']);
  2492. }
  2493. /**
  2494. * Generates input name and ID for a model attribute.
  2495. * This method will update the HTML options by setting appropriate 'name' and 'id' attributes.
  2496. * This method may also modify the attribute name if the name
  2497. * contains square brackets (mainly used in tabular input).
  2498. * @param CModel $model the data model
  2499. * @param string $attribute the attribute
  2500. * @param array $htmlOptions the HTML options
  2501. */
  2502. public static function resolveNameID($model,&$attribute,&$htmlOptions)
  2503. {
  2504. if(!isset($htmlOptions['name']))
  2505. $htmlOptions['name']=self::resolveName($model,$attribute);
  2506. if(!isset($htmlOptions['id']))
  2507. $htmlOptions['id']=self::getIdByName($htmlOptions['name']);
  2508. elseif($htmlOptions['id']===false)
  2509. unset($htmlOptions['id']);
  2510. }
  2511. /**
  2512. * Generates input name for a model attribute.
  2513. * Note, the attribute name may be modified after calling this method if the name
  2514. * contains square brackets (mainly used in tabular input) before the real attribute name.
  2515. * @param CModel $model the data model
  2516. * @param string $attribute the attribute
  2517. * @return string the input name
  2518. */
  2519. public static function resolveName($model,&$attribute)
  2520. {
  2521. $modelName=self::modelName($model);
  2522. if(($pos=strpos($attribute,'['))!==false)
  2523. {
  2524. if($pos!==0) // e.g. name[a][b]
  2525. return $modelName.'['.substr($attribute,0,$pos).']'.substr($attribute,$pos);
  2526. if(($pos=strrpos($attribute,']'))!==false && $pos!==strlen($attribute)-1) // e.g. [a][b]name
  2527. {
  2528. $sub=substr($attribute,0,$pos+1);
  2529. $attribute=substr($attribute,$pos+1);
  2530. return $modelName.$sub.'['.$attribute.']';
  2531. }
  2532. if(preg_match('/\](\w+\[.*)$/',$attribute,$matches))
  2533. {
  2534. $name=$modelName.'['.str_replace(']','][',trim(strtr($attribute,array(']['=>']','['=>']')),']')).']';
  2535. $attribute=$matches[1];
  2536. return $name;
  2537. }
  2538. }
  2539. return $modelName.'['.$attribute.']';
  2540. }
  2541. /**
  2542. * Evaluates the attribute value of the model.
  2543. * This method can recognize the attribute name written in array format.
  2544. * For example, if the attribute name is 'name[a][b]', the value "$model->name['a']['b']" will be returned.
  2545. * @param CModel $model the data model
  2546. * @param string $attribute the attribute name
  2547. * @return mixed the attribute value
  2548. * @since 1.1.3
  2549. */
  2550. public static function resolveValue($model,$attribute)
  2551. {
  2552. if(($pos=strpos($attribute,'['))!==false)
  2553. {
  2554. if($pos===0) // [a]name[b][c], should ignore [a]
  2555. {
  2556. if(preg_match('/\](\w+(\[.+)?)/',$attribute,$matches))
  2557. $attribute=$matches[1]; // we get: name[b][c]
  2558. if(($pos=strpos($attribute,'['))===false)
  2559. return $model->$attribute;
  2560. }
  2561. $name=substr($attribute,0,$pos);
  2562. $value=$model->$name;
  2563. foreach(explode('][',rtrim(substr($attribute,$pos+1),']')) as $id)
  2564. {
  2565. if((is_array($value) || $value instanceof ArrayAccess) && isset($value[$id]))
  2566. $value=$value[$id];
  2567. else
  2568. return null;
  2569. }
  2570. return $value;
  2571. }
  2572. else
  2573. return $model->$attribute;
  2574. }
  2575. /**
  2576. * Appends {@link errorCss} to the 'class' attribute.
  2577. * @param array $htmlOptions HTML options to be modified
  2578. */
  2579. protected static function addErrorCss(&$htmlOptions)
  2580. {
  2581. if(empty(self::$errorCss))
  2582. return;
  2583. if(isset($htmlOptions['class']))
  2584. $htmlOptions['class'].=' '.self::$errorCss;
  2585. else
  2586. $htmlOptions['class']=self::$errorCss;
  2587. }
  2588. /**
  2589. * Renders the HTML tag attributes.
  2590. * Since version 1.1.5, attributes whose value is null will not be rendered.
  2591. * Special attributes, such as 'checked', 'disabled', 'readonly', will be rendered
  2592. * properly based on their corresponding boolean value.
  2593. * @param array $htmlOptions attributes to be rendered
  2594. * @return string the rendering result
  2595. */
  2596. public static function renderAttributes($htmlOptions)
  2597. {
  2598. static $specialAttributes=array(
  2599. 'autofocus'=>1,
  2600. 'autoplay'=>1,
  2601. 'async'=>1,
  2602. 'checked'=>1,
  2603. 'controls'=>1,
  2604. 'declare'=>1,
  2605. 'default'=>1,
  2606. 'defer'=>1,
  2607. 'disabled'=>1,
  2608. 'formnovalidate'=>1,
  2609. 'hidden'=>1,
  2610. 'ismap'=>1,
  2611. 'itemscope'=>1,
  2612. 'loop'=>1,
  2613. 'multiple'=>1,
  2614. 'muted'=>1,
  2615. 'nohref'=>1,
  2616. 'noresize'=>1,
  2617. 'novalidate'=>1,
  2618. 'open'=>1,
  2619. 'readonly'=>1,
  2620. 'required'=>1,
  2621. 'reversed'=>1,
  2622. 'scoped'=>1,
  2623. 'seamless'=>1,
  2624. 'selected'=>1,
  2625. 'typemustmatch'=>1,
  2626. );
  2627. if($htmlOptions===array())
  2628. return '';
  2629. $html='';
  2630. if(isset($htmlOptions['encode']))
  2631. {
  2632. $raw=!$htmlOptions['encode'];
  2633. unset($htmlOptions['encode']);
  2634. }
  2635. else
  2636. $raw=false;
  2637. foreach($htmlOptions as $name=>$value)
  2638. {
  2639. if(isset($specialAttributes[$name]))
  2640. {
  2641. if($value===false && $name==='async') {
  2642. $html .= ' ' . $name.'="false"';
  2643. }
  2644. elseif($value)
  2645. {
  2646. $html .= ' ' . $name;
  2647. if(self::$renderSpecialAttributesValue)
  2648. $html .= '="' . $name . '"';
  2649. }
  2650. }
  2651. elseif($value!==null)
  2652. $html .= ' ' . $name . '="' . ($raw ? $value : self::encode($value)) . '"';
  2653. }
  2654. return $html;
  2655. }
  2656. }