PageRenderTime 164ms CodeModel.GetById 20ms RepoModel.GetById 3ms app.codeStats 0ms

/admincrud/extensions/bootstrap/widgets/input/TbInput.php

https://github.com/max-rautkin/yii-admincrud
PHP | 822 lines | 346 code | 108 blank | 368 comment | 49 complexity | 4ef4e2e9530d31eb3646dd2e5c57dc96 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /*## TbInput class file.
  3. *
  4. * @author Christoffer Niska <ChristofferNiska@gmail.com>
  5. * @copyright Copyright &copy; Christoffer Niska 2011-
  6. * @license [New BSD License](http://www.opensource.org/licenses/bsd-license.php)
  7. * @package bootstrap.widgets.input
  8. */
  9. /**
  10. * Bootstrap input widget.
  11. * Used for rendering inputs according to Bootstrap standards.
  12. */
  13. abstract class TbInput extends CInputWidget
  14. {
  15. // The different input types.
  16. const TYPE_CHECKBOX = 'checkbox';
  17. const TYPE_CHECKBOXLIST = 'checkboxlist';
  18. const TYPE_CHECKBOXLIST_INLINE = 'checkboxlist_inline';
  19. const TYPE_CHECKBOXGROUPSLIST = 'checkboxgroupslist';
  20. const TYPE_DROPDOWN = 'dropdownlist';
  21. const TYPE_FILE = 'filefield';
  22. const TYPE_PASSWORD = 'password';
  23. const TYPE_RADIO = 'radiobutton';
  24. const TYPE_RADIOLIST = 'radiobuttonlist';
  25. const TYPE_RADIOLIST_INLINE = 'radiobuttonlist_inline';
  26. const TYPE_RADIOBUTTONGROUPSLIST = 'radiobuttongroupslist';
  27. const TYPE_TEXTAREA = 'textarea';
  28. const TYPE_TEXT = 'text';
  29. const TYPE_MASKEDTEXT = 'maskedtextfield';
  30. const TYPE_CAPTCHA = 'captcha';
  31. const TYPE_UNEDITABLE = 'uneditable';
  32. const TYPE_DATEPICKER = 'datepicker';
  33. const TYPE_REDACTOR = 'redactor';
  34. const TYPE_MARKDOWNEDITOR = 'markdowneditor';
  35. const TYPE_HTML5EDITOR = 'wysihtml5';
  36. const TYPE_DATERANGEPICKER = 'daterangepicker';
  37. const TYPE_TOGGLEBUTTON = 'togglebutton';
  38. const TYPE_COLORPICKER = 'colorpicker';
  39. const TYPE_CKEDITOR = 'ckeditor';
  40. const TYPE_TIMEPICKER = 'timepicker';
  41. const TYPE_SELECT2 = 'select2';
  42. const TYPE_TYPEAHEAD = 'typeahead';
  43. const TYPE_NUMBER = 'numberfield';
  44. /**
  45. * @var TbActiveForm the associated form widget.
  46. */
  47. public $form;
  48. /**
  49. * @var string the input label text.
  50. */
  51. public $label;
  52. /**
  53. * @var string the input type.
  54. *
  55. * Following types are supported: checkbox, checkboxlist, dropdownlist, filefield, password,
  56. * radiobutton, radiobuttonlist, textarea, textfield, captcha and uneditable.
  57. */
  58. public $type;
  59. /**
  60. * @var array the data for list inputs.
  61. */
  62. public $data = array();
  63. /**
  64. * @var string text to prepend.
  65. */
  66. public $prependText;
  67. /**
  68. * @var string text to append.
  69. */
  70. public $appendText;
  71. /**
  72. * @var string the hint text.
  73. */
  74. public $hintText;
  75. /**
  76. * @var array label html attributes.
  77. */
  78. public $labelOptions = array();
  79. /**
  80. * @var array prepend html attributes.
  81. */
  82. public $prependOptions = array();
  83. /**
  84. * @var array append html attributes.
  85. */
  86. public $appendOptions = array();
  87. /**
  88. * @var array hint html attributes.
  89. */
  90. public $hintOptions = array();
  91. /**
  92. * @var array error html attributes.
  93. */
  94. public $errorOptions = array();
  95. /**
  96. * @var array captcha html attributes.
  97. */
  98. public $captchaOptions = array();
  99. /**
  100. * This property allows you to disable AJAX valiadtion for certain fields within a form.
  101. * @var boolean the value to be set as fourth parameter to {@link CActiveForm::error}.
  102. * @see http://www.yiiframework.com/doc/api/1.1/CActiveForm#error-detail
  103. */
  104. public $enableAjaxValidation = true;
  105. /**
  106. * This property allows you to disable client valiadtion for certain fields within a form.
  107. * @var boolean the value to be set as fifth parameter to {@link CActiveForm::error}.
  108. * @see http://www.yiiframework.com/doc/api/1.1/CActiveForm#error-detail
  109. */
  110. public $enableClientValidation = true;
  111. /**
  112. *### .init()
  113. *
  114. * Initializes the widget.
  115. *
  116. * @throws CException if the widget could not be initialized.
  117. */
  118. public function init()
  119. {
  120. if (!isset($this->form)) {
  121. throw new CException(__CLASS__ . ': Failed to initialize widget! Form is not set.');
  122. }
  123. if (!isset($this->model)) {
  124. throw new CException(__CLASS__ . ': Failed to initialize widget! Model is not set.');
  125. }
  126. if (!isset($this->type)) {
  127. throw new CException(__CLASS__ . ': Failed to initialize widget! Input type is not set.');
  128. }
  129. // todo: move this logic elsewhere, it doesn't belong here ...
  130. if ($this->type === self::TYPE_UNEDITABLE) {
  131. if (isset($this->htmlOptions['class'])) {
  132. $this->htmlOptions['class'] .= ' uneditable-input';
  133. } else {
  134. $this->htmlOptions['class'] = 'uneditable-input';
  135. }
  136. }
  137. $this->processHtmlOptions();
  138. }
  139. /**
  140. *### .processHtmlOptions()
  141. *
  142. * Processes the html options.
  143. */
  144. protected function processHtmlOptions()
  145. {
  146. if (isset($this->htmlOptions['label'])) {
  147. $this->label = $this->htmlOptions['label'];
  148. unset($this->htmlOptions['label']);
  149. }
  150. if (isset($this->htmlOptions['prepend'])) {
  151. $this->prependText = $this->htmlOptions['prepend'];
  152. unset($this->htmlOptions['prepend']);
  153. }
  154. if (isset($this->htmlOptions['append'])) {
  155. $this->appendText = $this->htmlOptions['append'];
  156. unset($this->htmlOptions['append']);
  157. }
  158. if (isset($this->htmlOptions['hint'])) {
  159. $this->hintText = $this->htmlOptions['hint'];
  160. unset($this->htmlOptions['hint']);
  161. }
  162. if (isset($this->htmlOptions['label'])) {
  163. $this->label = $this->htmlOptions['label'];
  164. unset($this->htmlOptions['label']);
  165. }
  166. if (isset($this->htmlOptions['labelOptions'])) {
  167. $this->labelOptions = $this->htmlOptions['labelOptions'];
  168. unset($this->htmlOptions['labelOptions']);
  169. }
  170. if (isset($this->htmlOptions['prependOptions'])) {
  171. $this->prependOptions = $this->htmlOptions['prependOptions'];
  172. unset($this->htmlOptions['prependOptions']);
  173. }
  174. if (isset($this->htmlOptions['appendOptions'])) {
  175. $this->appendOptions = $this->htmlOptions['appendOptions'];
  176. unset($this->htmlOptions['appendOptions']);
  177. }
  178. if (isset($this->htmlOptions['hintOptions'])) {
  179. $this->hintOptions = $this->htmlOptions['hintOptions'];
  180. unset($this->htmlOptions['hintOptions']);
  181. }
  182. if (isset($this->htmlOptions['errorOptions'])) {
  183. $this->errorOptions = $this->htmlOptions['errorOptions'];
  184. if (isset($this->htmlOptions['errorOptions']['enableAjaxValidation'])) {
  185. $this->enableAjaxValidation = (boolean)$this->htmlOptions['errorOptions']['enableAjaxValidation'];
  186. }
  187. if (isset($this->htmlOptions['errorOptions']['enableClientValidation'])) {
  188. $this->enableClientValidation = (boolean)$this->htmlOptions['errorOptions']['enableClientValidation'];
  189. }
  190. unset($this->htmlOptions['errorOptions']);
  191. }
  192. if (isset($this->htmlOptions['captchaOptions'])) {
  193. $this->captchaOptions = $this->htmlOptions['captchaOptions'];
  194. unset($this->htmlOptions['captchaOptions']);
  195. }
  196. }
  197. /**
  198. *### .run()
  199. *
  200. * Runs the widget.
  201. *
  202. * @throws CException if the widget type is invalid.
  203. */
  204. public function run()
  205. {
  206. switch ($this->type) {
  207. case self::TYPE_CHECKBOX:
  208. $this->checkBox();
  209. break;
  210. case self::TYPE_CHECKBOXLIST:
  211. $this->checkBoxList();
  212. break;
  213. case self::TYPE_CHECKBOXLIST_INLINE:
  214. $this->checkBoxListInline();
  215. break;
  216. case self::TYPE_CHECKBOXGROUPSLIST:
  217. $this->checkBoxGroupsList();
  218. break;
  219. case self::TYPE_DROPDOWN:
  220. $this->dropDownList();
  221. break;
  222. case self::TYPE_FILE:
  223. $this->fileField();
  224. break;
  225. case self::TYPE_PASSWORD:
  226. $this->passwordField();
  227. break;
  228. case self::TYPE_RADIO:
  229. $this->radioButton();
  230. break;
  231. case self::TYPE_RADIOLIST:
  232. $this->radioButtonList();
  233. break;
  234. case self::TYPE_RADIOLIST_INLINE:
  235. $this->radioButtonListInline();
  236. break;
  237. case self::TYPE_RADIOBUTTONGROUPSLIST:
  238. $this->radioButtonGroupsList();
  239. break;
  240. case self::TYPE_TEXTAREA:
  241. $this->textArea();
  242. break;
  243. case 'textfield': // backwards compatibility
  244. case self::TYPE_TEXT:
  245. $this->textField();
  246. break;
  247. case self::TYPE_MASKEDTEXT:
  248. $this->maskedTextField();
  249. break;
  250. case self::TYPE_CAPTCHA:
  251. $this->captcha();
  252. break;
  253. case self::TYPE_UNEDITABLE:
  254. $this->uneditableField();
  255. break;
  256. case self::TYPE_DATEPICKER:
  257. $this->datepickerField();
  258. break;
  259. case self::TYPE_REDACTOR:
  260. $this->redactorJs();
  261. break;
  262. case self::TYPE_MARKDOWNEDITOR:
  263. $this->markdownEditorJs();
  264. break;
  265. case self::TYPE_HTML5EDITOR:
  266. $this->html5Editor();
  267. break;
  268. case self::TYPE_DATERANGEPICKER:
  269. $this->dateRangeField();
  270. break;
  271. case self::TYPE_TOGGLEBUTTON:
  272. $this->toggleButton();
  273. break;
  274. case self::TYPE_COLORPICKER:
  275. $this->colorpickerField();
  276. break;
  277. case self::TYPE_CKEDITOR:
  278. $this->ckEditor();
  279. break;
  280. case self::TYPE_TIMEPICKER:
  281. $this->timepickerField();
  282. break;
  283. case self::TYPE_SELECT2:
  284. $this->select2Field();
  285. break;
  286. case self::TYPE_TYPEAHEAD:
  287. $this->typeAheadField();
  288. break;
  289. case self::TYPE_NUMBER:
  290. $this->numberField();
  291. break;
  292. default:
  293. throw new CException(__CLASS__ . ': Failed to run widget! Type is invalid.');
  294. }
  295. }
  296. /**
  297. *### .getLabel()
  298. *
  299. * Returns the label for the input.
  300. *
  301. * @return string the label
  302. */
  303. protected function getLabel()
  304. {
  305. if ($this->label !== false && !in_array($this->type, array('checkbox', 'radio')) && $this->hasModel()) {
  306. return $this->form->labelEx($this->model, $this->attribute, $this->labelOptions);
  307. } else if ($this->label !== null) {
  308. return $this->label;
  309. } else {
  310. return '';
  311. }
  312. }
  313. /**
  314. *### .getPrepend()
  315. *
  316. * Returns the prepend element for the input.
  317. *
  318. * @return string the element
  319. */
  320. protected function getPrepend()
  321. {
  322. if ($this->hasAddOn()) {
  323. $htmlOptions = $this->prependOptions;
  324. if (isset($htmlOptions['class'])) {
  325. $htmlOptions['class'] .= ' add-on';
  326. } else {
  327. $htmlOptions['class'] = 'add-on';
  328. }
  329. ob_start();
  330. echo '<div class="' . $this->getAddonCssClass() . '">';
  331. if (isset($this->prependText)) {
  332. if (isset($htmlOptions['isRaw']) && $htmlOptions['isRaw']) {
  333. echo $this->prependText;
  334. } else {
  335. echo CHtml::tag('span', $htmlOptions, $this->prependText);
  336. }
  337. }
  338. return ob_get_clean();
  339. } else {
  340. return '';
  341. }
  342. }
  343. /**
  344. *### .getAppend()
  345. *
  346. * Returns the append element for the input.
  347. *
  348. * @return string the element
  349. */
  350. protected function getAppend()
  351. {
  352. if ($this->hasAddOn()) {
  353. $htmlOptions = $this->appendOptions;
  354. if (isset($htmlOptions['class'])) {
  355. $htmlOptions['class'] .= ' add-on';
  356. } else {
  357. $htmlOptions['class'] = 'add-on';
  358. }
  359. ob_start();
  360. if (isset($this->appendText)) {
  361. if (isset($htmlOptions['isRaw']) && $htmlOptions['isRaw']) {
  362. echo $this->appendText;
  363. } else {
  364. echo CHtml::tag('span', $htmlOptions, $this->appendText);
  365. }
  366. }
  367. echo '</div>';
  368. return ob_get_clean();
  369. } else {
  370. return '';
  371. }
  372. }
  373. /**
  374. *### .getAppend()
  375. *
  376. * Returns the id that should be used for the specified attribute
  377. *
  378. * @param string $attribute the attribute
  379. *
  380. * @return string the id
  381. */
  382. protected function getAttributeId($attribute)
  383. {
  384. return isset($this->htmlOptions['id'])
  385. ? $this->htmlOptions['id']
  386. : CHtml::getIdByName(CHtml::resolveName($this->model, $attribute));
  387. }
  388. /**
  389. *### .getError()
  390. *
  391. * Returns the error text for the input.
  392. *
  393. * @return string the error text
  394. */
  395. protected function getError()
  396. {
  397. return $this->form->error(
  398. $this->model,
  399. $this->attribute,
  400. $this->errorOptions,
  401. $this->enableAjaxValidation,
  402. $this->enableClientValidation
  403. );
  404. }
  405. /**
  406. *### .getHint()
  407. *
  408. * Returns the hint text for the input.
  409. *
  410. * @return string the hint text
  411. */
  412. protected function getHint()
  413. {
  414. if (isset($this->hintText)) {
  415. $htmlOptions = $this->hintOptions;
  416. if (isset($htmlOptions['class'])) {
  417. $htmlOptions['class'] .= ' help-block';
  418. } else {
  419. $htmlOptions['class'] = 'help-block';
  420. }
  421. return CHtml::tag('p', $htmlOptions, $this->hintText);
  422. } else {
  423. return '';
  424. }
  425. }
  426. /**
  427. *### .getContainerCssClass()
  428. *
  429. * Returns the container CSS class for the input.
  430. *
  431. * @return string the CSS class
  432. */
  433. protected function getContainerCssClass()
  434. {
  435. $attribute = $this->attribute;
  436. return $this->model->hasErrors(CHtml::resolveName($this->model, $attribute)) ? CHtml::$errorCss : '';
  437. }
  438. /**
  439. *### .getAddonCssClass()
  440. *
  441. * Returns the input container CSS classes.
  442. *
  443. * @return string the CSS class
  444. */
  445. protected function getAddonCssClass()
  446. {
  447. $classes = array();
  448. if (isset($this->prependText)) {
  449. $classes[] = 'input-prepend';
  450. }
  451. if (isset($this->appendText)) {
  452. $classes[] = 'input-append';
  453. }
  454. return implode(' ', $classes);
  455. }
  456. /**
  457. *### .hasAddOn()
  458. *
  459. * Returns whether the input has an add-on (prepend and/or append).
  460. *
  461. * @return boolean the result
  462. */
  463. protected function hasAddOn()
  464. {
  465. return isset($this->prependText) || isset($this->appendText);
  466. }
  467. /**
  468. *### .checkBox()
  469. *
  470. * Renders a checkbox.
  471. *
  472. * @return string the rendered content
  473. * @abstract
  474. */
  475. abstract protected function checkBox();
  476. /**
  477. *### .toggleButton()
  478. *
  479. * Renders a toggle button.
  480. *
  481. * @return string the rendered content
  482. * @abstract
  483. */
  484. abstract protected function toggleButton();
  485. /**
  486. *### .checkBoxList()
  487. *
  488. * Renders a list of checkboxes.
  489. *
  490. * @return string the rendered content
  491. * @abstract
  492. */
  493. abstract protected function checkBoxList();
  494. /**
  495. *### .checkBoxListInline()
  496. *
  497. * Renders a list of inline checkboxes.
  498. *
  499. * @return string the rendered content
  500. * @abstract
  501. */
  502. abstract protected function checkBoxListInline();
  503. /**
  504. *### .checkBoxGroupsList()
  505. *
  506. * Renders a list of checkboxes using Button Groups.
  507. *
  508. * @return string the rendered content
  509. * @abstract
  510. */
  511. abstract protected function checkBoxGroupsList();
  512. /**
  513. *### .dropDownList()
  514. *
  515. * Renders a drop down list (select).
  516. *
  517. * @return string the rendered content
  518. * @abstract
  519. */
  520. abstract protected function dropDownList();
  521. /**
  522. *### .fileField()
  523. *
  524. * Renders a file field.
  525. *
  526. * @return string the rendered content
  527. * @abstract
  528. */
  529. abstract protected function fileField();
  530. /**
  531. *### .passwordField()
  532. *
  533. * Renders a password field.
  534. *
  535. * @return string the rendered content
  536. * @abstract
  537. */
  538. abstract protected function passwordField();
  539. /**
  540. *### .radioButton()
  541. *
  542. * Renders a radio button.
  543. *
  544. * @return string the rendered content
  545. * @abstract
  546. */
  547. abstract protected function radioButton();
  548. /**
  549. *### .radioButtonList()
  550. *
  551. * Renders a list of radio buttons.
  552. *
  553. * @return string the rendered content
  554. * @abstract
  555. */
  556. abstract protected function radioButtonList();
  557. /**
  558. *### .radioButtonListInline()
  559. *
  560. * Renders a list of inline radio buttons.
  561. *
  562. * @return string the rendered content
  563. * @abstract
  564. */
  565. abstract protected function radioButtonListInline();
  566. /**
  567. *### .radioButtonGroupsList()
  568. *
  569. * Renders a list of radio buttons using Button Groups.
  570. *
  571. * @return string the rendered content
  572. * @abstract
  573. */
  574. abstract protected function radioButtonGroupsList();
  575. /**
  576. *### .textArea()
  577. *
  578. * Renders a textarea.
  579. *
  580. * @return string the rendered content
  581. * @abstract
  582. */
  583. abstract protected function textArea();
  584. /**
  585. *### .textField()
  586. *
  587. * Renders a text field.
  588. *
  589. * @return string the rendered content
  590. * @abstract
  591. */
  592. abstract protected function textField();
  593. /**
  594. *### .maskedTextField()
  595. *
  596. * Renders a masked text field.
  597. *
  598. * @return string the rendered content
  599. * @abstract
  600. */
  601. abstract protected function maskedTextField();
  602. /**
  603. *### .captcha()
  604. *
  605. * Renders a CAPTCHA.
  606. *
  607. * @return string the rendered content
  608. * @abstract
  609. */
  610. abstract protected function captcha();
  611. /**
  612. *### .uneditableField()
  613. *
  614. * Renders an uneditable field.
  615. *
  616. * @return string the rendered content
  617. * @abstract
  618. */
  619. abstract protected function uneditableField();
  620. /**
  621. *### .datepicketField()
  622. *
  623. * Renders a datepicker field.
  624. *
  625. * @return string the rendered content
  626. * @abstract
  627. */
  628. abstract protected function datepickerField();
  629. /**
  630. *### .redactorJs()
  631. *
  632. * Renders a redactorJS wysiwyg field.
  633. *
  634. * @abstract
  635. * @return mixed
  636. */
  637. abstract protected function redactorJs();
  638. /**
  639. *### .markdownEditorJs()
  640. *
  641. * Renders a markdownEditorJS wysiwyg field.
  642. *
  643. * @abstract
  644. * @return mixed
  645. */
  646. abstract protected function markdownEditorJs();
  647. /**
  648. *### .ckEditor()
  649. *
  650. * Renders a bootstrap CKEditor wysiwyg editor.
  651. *
  652. * @abstract
  653. * @return mixed
  654. */
  655. abstract protected function ckEditor();
  656. /**
  657. *### .html5Editor()
  658. *
  659. * Renders a bootstrap wysihtml5 editor.
  660. *
  661. * @abstract
  662. * @return mixed
  663. */
  664. abstract protected function html5Editor();
  665. /**
  666. *### .dateRangeField()
  667. *
  668. * Renders a daterange picker field
  669. *
  670. * @abstract
  671. * @return mixed
  672. */
  673. abstract protected function dateRangeField();
  674. /**
  675. *### .colorpickerField()
  676. *
  677. * Renders a colorpicker field.
  678. *
  679. * @return string the rendered content
  680. * @abstract
  681. */
  682. abstract protected function colorpickerField();
  683. /**
  684. *### .timepickerField()
  685. *
  686. * Renders a timepicker field.
  687. *
  688. * @return string the rendered content
  689. * @abstract
  690. */
  691. abstract protected function timepickerField();
  692. /**
  693. *### .select2Field()
  694. *
  695. * Renders a select2 field.
  696. *
  697. * @return mixed
  698. */
  699. abstract protected function select2Field();
  700. /**
  701. * Renders a typeAhead field.
  702. * @return mixed
  703. */
  704. abstract protected function typeAheadField();
  705. /**
  706. *### . numberField()
  707. *
  708. * Renders a number field.
  709. *
  710. * @return string the rendered content
  711. * @abstract
  712. */
  713. abstract protected function numberField();
  714. }