├── CHANGELOG.md
├── LICENSE.md
├── Makefile
├── README.md
├── composer.json
└── src
├── Accordion.php
├── AutoComplete.php
├── DatePicker.php
├── DatePickerLanguageAsset.php
├── Dialog.php
├── Draggable.php
├── Droppable.php
├── InputWidget.php
├── JuiAsset.php
├── Menu.php
├── ProgressBar.php
├── Resizable.php
├── Selectable.php
├── Slider.php
├── SliderInput.php
├── Sortable.php
├── Spinner.php
├── Tabs.php
└── Widget.php
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Yii Framework 2 jui extension Change Log
2 | ========================================
3 |
4 | 2.0.8 under development
5 | -----------------------
6 |
7 | - no changes in this release.
8 |
9 |
10 | 2.0.7 November 25, 2017
11 | -----------------------
12 |
13 | - Bug #45: Fixed missing close icon in `yii\jui\Dialog` (mtangoo)
14 | - Bug #46: `yii\jui\Selectable` add support for `begin()`, `end()` widget methods (fdezmc)
15 | - Enh #56: Use `jQuery` instead of `$` in generated code to avoid conflicts (samdark)
16 | - Chg #55: `yii\jui\AutoComplete::run()` now returns output instead of echoing it (unlimix)
17 | - Chg #72: Updated jQueryUI dependency to use `1.12.1` as minimum version (samdark)
18 |
19 |
20 | 2.0.6 July 22, 2016
21 | -----------------------
22 |
23 | - Bug #36: `yii\jui\Draggable` was using wrong event names (samdark)
24 | - Bug #41: `yii\jui\Droppable` and `yii\jui\Resizable` were using wrong event names (samdark)
25 |
26 |
27 | 2.0.5 March 17, 2016
28 | --------------------
29 |
30 | - Bug #8607: `yii\jui\Spinner` was using wrong event names (samdark)
31 |
32 |
33 | 2.0.4 May 10, 2015
34 | ------------------
35 |
36 | - Bug #6: When using `DatePicker` translations, asset was registered without timestamp when asset manager `$appendTimestamp` was enabled (samdark)
37 | - Bug (CVE-2015-3397): Using `Json::htmlEncode()` for safer JSON data encoding in HTML code (samdark, Tomasz Tokarski)
38 |
39 |
40 | 2.0.3 March 01, 2015
41 | --------------------
42 |
43 | - Enh #7127: `name` or `model` and `attribute` are no longer required properties of `yii\jui\InputWidget` (nirvana-msu, cebe)
44 |
45 |
46 | 2.0.2 January 11, 2015
47 | ----------------------
48 |
49 | - Enh #6570: Datepicker now uses fallback to find language files, e.g. application language is `de-DE` and the translation files does not exists, it will use `de` instead (cebe)
50 | - Enh #6471: Datepicker will now show an empty field when value is an empty string (cebe)
51 |
52 |
53 | 2.0.1 December 07, 2014
54 | -----------------------
55 |
56 | - no changes in this release.
57 |
58 |
59 | 2.0.0 October 12, 2014
60 | ----------------------
61 |
62 | - no changes in this release.
63 |
64 |
65 | 2.0.0-rc September 27, 2014
66 | ---------------------------
67 |
68 | - Chg #1551: Jui datepicker has a new property `$dateFormat` which is used to set the clientOption `dateFormat`.
69 | The new property does not use the datepicker formatting syntax anymore but uses the same as the `yii\i18n\Formatter`
70 | class which is the ICU syntax for date formatting, you have to adjust all your DatePicker widgets to use
71 | the new property instead of setting the dateFormat in the clientOptions (cebe)
72 |
73 |
74 | 2.0.0-beta April 13, 2014
75 | -------------------------
76 |
77 | - Bug #1550: fixed the issue that JUI input widgets did not property input IDs. (qiangxue)
78 | - Bug #2514: Jui sortable clientEvents were not working because of wrong naming assumptions. (cebe)
79 | - Enh #2573: Jui datepicker now uses the current application language by default. (andy5)
80 |
81 | 2.0.0-alpha, December 1, 2013
82 | -----------------------------
83 |
84 | - Initial release.
85 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com)
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the
13 | distribution.
14 | * Neither the name of Yii Software LLC nor the names of its
15 | contributors may be used to endorse or promote products derived
16 | from this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 | POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 |
2 | # default versions to test against
3 | # these can be overridden by setting the environment variables in the shell
4 | PHP_VERSION=php-5.6.8
5 | YII_VERSION=dev-master
6 |
7 | # ensure all the configuration variables above are in environment of the shell commands below
8 | export
9 |
10 | help:
11 | @echo "make test - run phpunit tests using a docker environment"
12 | # @echo "make clean - stop docker and remove container"
13 |
14 | test: docker-php
15 | composer require "yiisoft/yii2:${YII_VERSION}" --prefer-dist
16 | composer install --prefer-dist
17 | docker run --rm=true -v $(shell pwd):/opt/test yiitest/php:${PHP_VERSION} phpunit --verbose --color
18 |
19 | docker-php: dockerfiles
20 | cd tests/docker/php && sh build.sh
21 |
22 | dockerfiles:
23 | test -d tests/docker || git clone https://github.com/cebe/jenkins-test-docker tests/docker
24 | cd tests/docker && git checkout -- . && git pull
25 | mkdir -p tests/dockerids
26 |
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
JUI Extension for Yii 2
6 |
7 |
8 |
9 | This is the JQuery UI extension for [Yii framework 2.0](https://www.yiiframework.com). It encapsulates [JQuery UI widgets](https://jqueryui.com/) as Yii widgets,
10 | and makes using JQuery UI widgets in Yii applications extremely easy.
11 |
12 | For license information check the [LICENSE](LICENSE.md)-file.
13 |
14 | Documentation is at [docs/guide/README.md](docs/guide/README.md).
15 |
16 | [](https://packagist.org/packages/yiisoft/yii2-jui)
17 | [](https://packagist.org/packages/yiisoft/yii2-jui)
18 | [](https://github.com/yiisoft/yii2-jui/actions)
19 |
20 | Installation
21 | ------------
22 |
23 | The preferred way to install this extension is through [composer](https://getcomposer.org/download/).
24 |
25 | Either run
26 |
27 | ```
28 | php composer.phar require --prefer-dist yiisoft/yii2-jui
29 | ```
30 |
31 | or add
32 |
33 | ```
34 | "yiisoft/yii2-jui": "~2.0.0"
35 | ```
36 |
37 | to the require section of your `composer.json` file.
38 |
39 | Usage
40 | -----
41 |
42 | The following
43 | single line of code in a view file would render a [JQuery UI DatePicker](https://api.jqueryui.com/datepicker/) widget:
44 |
45 | ```php
46 | = yii\jui\DatePicker::widget(['name' => 'attributeName']) ?>
47 | ```
48 |
49 | Configuring the Jquery UI options should be done using the clientOptions attribute:
50 |
51 | ```php
52 | = yii\jui\DatePicker::widget(['name' => 'attributeName', 'clientOptions' => ['defaultDate' => '2014-01-01']]) ?>
53 | ```
54 |
55 | If you want to use the JUI widget in an ActiveForm, it can be done like this:
56 |
57 | ```php
58 | = $form->field($model,'attributeName')->widget(DatePicker::className(),['clientOptions' => ['defaultDate' => '2014-01-01']]) ?>
59 | ```
60 |
61 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "yiisoft/yii2-jui",
3 | "description": "The Jquery UI extension for the Yii framework",
4 | "keywords": ["yii2", "Jquery UI"],
5 | "type": "yii2-extension",
6 | "license": "BSD-3-Clause",
7 | "support": {
8 | "issues": "https://github.com/yiisoft/yii2-jui/issues",
9 | "forum": "https://www.yiiframework.com/forum/",
10 | "wiki": "https://www.yiiframework.com/wiki/",
11 | "irc": "ircs://irc.libera.chat:6697/yii",
12 | "source": "https://github.com/yiisoft/yii2-jui"
13 | },
14 | "authors": [
15 | {
16 | "name": "Qiang Xue",
17 | "email": "qiang.xue@gmail.com"
18 | },
19 | {
20 | "name": "Alexander Kochetov",
21 | "email": "creocoder@gmail.com"
22 | },
23 | {
24 | "name": "Carsten Brandt",
25 | "email": "mail@cebe.cc"
26 | },
27 | {
28 | "name": "Alexander Makarov",
29 | "email": "sam@rmcreative.ru"
30 | }
31 | ],
32 | "require": {
33 | "yiisoft/yii2": "~2.0.4",
34 | "bower-asset/jquery-ui": "~1.12.1"
35 | },
36 | "require-dev": {
37 | "cweagans/composer-patches": "^1.7",
38 | "phpunit/phpunit": "4.8.34"
39 | },
40 | "repositories": [
41 | {
42 | "type": "composer",
43 | "url": "https://asset-packagist.org"
44 | }
45 | ],
46 | "autoload": {
47 | "psr-4": {
48 | "yii\\jui\\": "src"
49 | }
50 | },
51 | "extra": {
52 | "branch-alias": {
53 | "dev-master": "2.0.x-dev"
54 | },
55 | "composer-exit-on-patch-failure": true,
56 | "patches": {
57 | "phpunit/phpunit-mock-objects": {
58 | "Fix PHP 7 and 8 compatibility": "https://yiisoft.github.io/phpunit-patches/phpunit_mock_objects.patch"
59 | },
60 | "phpunit/phpunit": {
61 | "Fix PHP 7 compatibility": "https://yiisoft.github.io/phpunit-patches/phpunit_php7.patch",
62 | "Fix PHP 8 compatibility": "https://yiisoft.github.io/phpunit-patches/phpunit_php8.patch"
63 | }
64 | }
65 | },
66 | "config": {
67 | "allow-plugins": {
68 | "cweagans/composer-patches": true,
69 | "yiisoft/yii2-composer": true
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/Accordion.php:
--------------------------------------------------------------------------------
1 | [
22 | * [
23 | * 'header' => 'Section 1',
24 | * 'content' => 'Mauris mauris ante, blandit et, ultrices a, suscipit eget...',
25 | * ],
26 | * [
27 | * 'header' => 'Section 2',
28 | * 'headerOptions' => ['tag' => 'h3'],
29 | * 'content' => 'Sed non urna. Phasellus eu ligula. Vestibulum sit amet purus...',
30 | * 'options' => ['tag' => 'div'],
31 | * ],
32 | * ],
33 | * 'options' => ['tag' => 'div'],
34 | * 'itemOptions' => ['tag' => 'div'],
35 | * 'headerOptions' => ['tag' => 'h3'],
36 | * 'clientOptions' => ['collapsible' => false],
37 | * ]);
38 | * ```
39 | *
40 | * @see https://api.jqueryui.com/accordion/
41 | * @author Alexander Kochetov
42 | * @since 2.0
43 | */
44 | class Accordion extends Widget
45 | {
46 | /**
47 | * @var array the HTML attributes for the widget container tag. The following special options are recognized:
48 | *
49 | * - tag: string, defaults to "div", the tag name of the container tag of this widget
50 | *
51 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
52 | */
53 | public $options = [];
54 | /**
55 | * @var array list of collapsible items. Each item can be an array of the following structure:
56 | *
57 | * ~~~
58 | * [
59 | * 'header' => 'Item header',
60 | * 'content' => 'Item content',
61 | * // the HTML attributes of the item header container tag. This will overwrite "headerOptions".
62 | * 'headerOptions' => [],
63 | * // the HTML attributes of the item container tag. This will overwrite "itemOptions".
64 | * 'options' => [],
65 | * ]
66 | * ~~~
67 | */
68 | public $items = [];
69 | /**
70 | * @var array list of HTML attributes for the item container tags. This will be overwritten
71 | * by the "options" set in individual [[items]]. The following special options are recognized:
72 | *
73 | * - tag: string, defaults to "div", the tag name of the item container tags.
74 | *
75 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
76 | */
77 | public $itemOptions = [];
78 | /**
79 | * @var array list of HTML attributes for the item header container tags. This will be overwritten
80 | * by the "headerOptions" set in individual [[items]]. The following special options are recognized:
81 | *
82 | * - tag: string, defaults to "h3", the tag name of the item container tags.
83 | *
84 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
85 | */
86 | public $headerOptions = [];
87 |
88 |
89 | /**
90 | * Renders the widget.
91 | */
92 | public function run()
93 | {
94 | $options = $this->options;
95 | $tag = ArrayHelper::remove($options, 'tag', 'div');
96 | echo Html::beginTag($tag, $options) . "\n";
97 | echo $this->renderItems() . "\n";
98 | echo Html::endTag($tag) . "\n";
99 | $this->registerWidget('accordion');
100 | }
101 |
102 | /**
103 | * Renders collapsible items as specified on [[items]].
104 | * @return string the rendering result.
105 | * @throws InvalidConfigException.
106 | */
107 | protected function renderItems()
108 | {
109 | $items = [];
110 | foreach ($this->items as $item) {
111 | if (!array_key_exists('header', $item)) {
112 | throw new InvalidConfigException("The 'header' option is required.");
113 | }
114 | if (!array_key_exists('content', $item)) {
115 | throw new InvalidConfigException("The 'content' option is required.");
116 | }
117 | $headerOptions = array_merge($this->headerOptions, ArrayHelper::getValue($item, 'headerOptions', []));
118 | $headerTag = ArrayHelper::remove($headerOptions, 'tag', 'h3');
119 | $items[] = Html::tag($headerTag, $item['header'], $headerOptions);
120 | $options = array_merge($this->itemOptions, ArrayHelper::getValue($item, 'options', []));
121 | $tag = ArrayHelper::remove($options, 'tag', 'div');
122 | $items[] = Html::tag($tag, $item['content'], $options);
123 | }
124 |
125 | return implode("\n", $items);
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/AutoComplete.php:
--------------------------------------------------------------------------------
1 | $model,
20 | * 'attribute' => 'country',
21 | * 'clientOptions' => [
22 | * 'source' => ['USA', 'RUS'],
23 | * ],
24 | * ]);
25 | * ```
26 | *
27 | * The following example will use the name property instead:
28 | *
29 | * ```php
30 | * echo AutoComplete::widget([
31 | * 'name' => 'country',
32 | * 'clientOptions' => [
33 | * 'source' => ['USA', 'RUS'],
34 | * ],
35 | * ]);
36 | * ```
37 | *
38 | * You can also use this widget in an [[yii\widgets\ActiveForm|ActiveForm]] using the [[yii\widgets\ActiveField::widget()|widget()]]
39 | * method, for example like this:
40 | *
41 | * ```php
42 | * = $form->field($model, 'from_date')->widget(\yii\jui\AutoComplete::classname(), [
43 | * 'clientOptions' => [
44 | * 'source' => ['USA', 'RUS'],
45 | * ],
46 | * ]) ?>
47 | * ```
48 | *
49 | * @see https://api.jqueryui.com/autocomplete/
50 | * @author Alexander Kochetov
51 | * @since 2.0
52 | */
53 | class AutoComplete extends InputWidget
54 | {
55 | /**
56 | * {@inheritdoc}
57 | */
58 | public function run()
59 | {
60 | $this->registerWidget('autocomplete');
61 | return $this->renderWidget();
62 | }
63 |
64 | /**
65 | * Renders the AutoComplete widget.
66 | * @return string the rendering result.
67 | */
68 | public function renderWidget()
69 | {
70 | if ($this->hasModel()) {
71 | return Html::activeTextInput($this->model, $this->attribute, $this->options);
72 | }
73 | return Html::textInput($this->name, $this->value, $this->options);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/DatePicker.php:
--------------------------------------------------------------------------------
1 | $model,
24 | * 'attribute' => 'from_date',
25 | * //'language' => 'ru',
26 | * //'dateFormat' => 'yyyy-MM-dd',
27 | * ]);
28 | * ```
29 | *
30 | * The following example will use the name property instead:
31 | *
32 | * ```php
33 | * echo DatePicker::widget([
34 | * 'name' => 'from_date',
35 | * 'value' => $value,
36 | * //'language' => 'ru',
37 | * //'dateFormat' => 'yyyy-MM-dd',
38 | * ]);
39 | * ```
40 | *
41 | * You can also use this widget in an [[\yii\widgets\ActiveForm|ActiveForm]] using the [[\yii\widgets\ActiveField::widget()|widget()]]
42 | * method, for example like this:
43 | *
44 | * ```php
45 | * = $form->field($model, 'from_date')->widget(\yii\jui\DatePicker::className(), [
46 | * //'language' => 'ru',
47 | * //'dateFormat' => 'yyyy-MM-dd',
48 | * ]) ?>
49 | * ```
50 | *
51 | * Note that and empty string (`''`) and `null` will result in an empty text field while `0` will be
52 | * interpreted as a UNIX timestamp and result in a date displayed as `1970-01-01`.
53 | * It is recommended to add a
54 | * validation filter in your model that sets the value to `null` in case when no date has been entered:
55 | *
56 | * ```php
57 | * [['from_date'], 'default', 'value' => null],
58 | * ```
59 | *
60 | * @see https://api.jqueryui.com/datepicker/
61 | * @author Alexander Kochetov
62 | * @author Carsten Brandt
63 | * @since 2.0
64 | */
65 | class DatePicker extends InputWidget
66 | {
67 | /**
68 | * @var string the locale ID (e.g. 'fr', 'de', 'en-GB') for the language to be used by the date picker.
69 | * If this property is empty, then the current application language will be used.
70 | *
71 | * Since version 2.0.2 a fallback is used if the application language includes a locale part (e.g. `de-DE`) and the language
72 | * file does not exist, it will fall back to using `de`.
73 | */
74 | public $language;
75 | /**
76 | * @var boolean If true, shows the widget as an inline calendar and the input as a hidden field.
77 | */
78 | public $inline = false;
79 | /**
80 | * @var array the HTML attributes for the container tag. This is only used when [[inline]] is true.
81 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
82 | */
83 | public $containerOptions = [];
84 | /**
85 | * @var string the format string to be used for formatting the date value. This option will be used
86 | * to populate the [[clientOptions|clientOption]] `dateFormat`.
87 | * The value can be one of "short", "medium", "long", or "full", which represents a preset format of different lengths.
88 | *
89 | * It can also be a custom format as specified in the [ICU manual](https://unicode-org.github.io/icu/userguide/format_parse/datetime/#datetime-format-syntax).
90 | * Alternatively this can be a string prefixed with `php:` representing a format that can be recognized by the
91 | * PHP [date()](https://php.net/manual/de/function.date.php)-function.
92 | *
93 | * For example:
94 | *
95 | * ```php
96 | * 'MM/dd/yyyy' // date in ICU format
97 | * 'php:m/d/Y' // the same date in PHP format
98 | * ```
99 | *
100 | * If not set the default value will be taken from `Yii::$app->formatter->dateFormat`.
101 | */
102 | public $dateFormat;
103 | /**
104 | * @var string the model attribute that this widget is associated with.
105 | * The value of the attribute will be converted using [[\yii\i18n\Formatter::asDate()|`Yii::$app->formatter->asDate()`]]
106 | * with the [[dateFormat]] if it is not null.
107 | */
108 | public $attribute;
109 | /**
110 | * @var string the input value.
111 | * This value will be converted using [[\yii\i18n\Formatter::asDate()|`Yii::$app->formatter->asDate()`]]
112 | * with the [[dateFormat]] if it is not null.
113 | */
114 | public $value;
115 |
116 |
117 | /**
118 | * {@inheritdoc}
119 | */
120 | public function init()
121 | {
122 | parent::init();
123 | if ($this->inline && !isset($this->containerOptions['id'])) {
124 | $this->containerOptions['id'] = $this->options['id'] . '-container';
125 | }
126 | if ($this->dateFormat === null) {
127 | $this->dateFormat = Yii::$app->formatter->dateFormat;
128 | }
129 | }
130 |
131 | /**
132 | * Renders the widget.
133 | */
134 | public function run()
135 | {
136 | echo $this->renderWidget() . "\n";
137 |
138 | $containerID = $this->inline ? $this->containerOptions['id'] : $this->options['id'];
139 | $language = $this->language ? $this->language : Yii::$app->language;
140 |
141 | if (strncmp($this->dateFormat, 'php:', 4) === 0) {
142 | $this->clientOptions['dateFormat'] = FormatConverter::convertDatePhpToJui(substr($this->dateFormat, 4));
143 | } else {
144 | $this->clientOptions['dateFormat'] = FormatConverter::convertDateIcuToJui($this->dateFormat, 'date', $language);
145 | }
146 |
147 | if ($language !== 'en-US') {
148 | $view = $this->getView();
149 | $assetBundle = DatePickerLanguageAsset::register($view);
150 | $assetBundle->language = $language;
151 | $options = Json::htmlEncode($this->clientOptions);
152 | $language = Html::encode($language);
153 | $view->registerJs("jQuery('#{$containerID}').datepicker($.extend({}, $.datepicker.regional['{$language}'], $options));");
154 | } else {
155 | $this->registerClientOptions('datepicker', $containerID);
156 | }
157 |
158 | $this->registerClientEvents('datepicker', $containerID);
159 | JuiAsset::register($this->getView());
160 | }
161 |
162 | /**
163 | * Renders the DatePicker widget.
164 | * @return string the rendering result.
165 | */
166 | protected function renderWidget()
167 | {
168 | $contents = [];
169 |
170 | // get formatted date value
171 | if ($this->hasModel()) {
172 | $value = Html::getAttributeValue($this->model, $this->attribute);
173 | } else {
174 | $value = $this->value;
175 | }
176 | if ($value !== null && $value !== '') {
177 | // format value according to dateFormat
178 | try {
179 | $value = Yii::$app->formatter->asDate($value, $this->dateFormat);
180 | } catch(InvalidParamException $e) {
181 | // ignore exception and keep original value if it is not a valid date
182 | }
183 | }
184 | $options = $this->options;
185 | $options['value'] = $value;
186 |
187 | if ($this->inline === false) {
188 | // render a text input
189 | if ($this->hasModel()) {
190 | $contents[] = Html::activeTextInput($this->model, $this->attribute, $options);
191 | } else {
192 | $contents[] = Html::textInput($this->name, $value, $options);
193 | }
194 | } else {
195 | // render an inline date picker with hidden input
196 | if ($this->hasModel()) {
197 | $contents[] = Html::activeHiddenInput($this->model, $this->attribute, $options);
198 | } else {
199 | $contents[] = Html::hiddenInput($this->name, $value, $options);
200 | }
201 | $this->clientOptions['defaultDate'] = $value;
202 | $this->clientOptions['altField'] = '#' . $this->options['id'];
203 | $contents[] = Html::tag('div', null, $this->containerOptions);
204 | }
205 |
206 | return implode("\n", $contents);
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/src/DatePickerLanguageAsset.php:
--------------------------------------------------------------------------------
1 |
15 | * @since 2.0
16 | */
17 | class DatePickerLanguageAsset extends AssetBundle
18 | {
19 | /**
20 | * {@inheritdoc}
21 | */
22 | public $sourcePath = '@bower/jquery-ui';
23 | /**
24 | * @var boolean whether to automatically generate the needed language js files.
25 | * If this is true, the language js files will be determined based on the actual usage of [[DatePicker]]
26 | * and its language settings. If this is false, you should explicitly specify the language js files via [[js]].
27 | */
28 | public $autoGenerate = true;
29 | /**
30 | * @var string language to register translation file for
31 | */
32 | public $language;
33 | /**
34 | * {@inheritdoc}
35 | */
36 | public $depends = [
37 | 'yii\jui\JuiAsset',
38 | ];
39 |
40 |
41 | /**
42 | * {@inheritdoc}
43 | */
44 | public function registerAssetFiles($view)
45 | {
46 | if ($this->autoGenerate) {
47 | $language = $this->language;
48 | $fallbackLanguage = substr($this->language, 0, 2);
49 | if ($fallbackLanguage !== $this->language && !file_exists(Yii::getAlias($this->sourcePath . "/ui/i18n/datepicker-{$language}.js"))) {
50 | $language = $fallbackLanguage;
51 | }
52 | $this->js[] = "ui/i18n/datepicker-$language.js";
53 | }
54 | parent::registerAssetFiles($view);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Dialog.php:
--------------------------------------------------------------------------------
1 | [
20 | * 'modal' => true,
21 | * ],
22 | * ]);
23 | *
24 | * echo 'Dialog contents here...';
25 | *
26 | * Dialog::end();
27 | * ```
28 | *
29 | * @see https://api.jqueryui.com/dialog/
30 | * @author Alexander Kochetov
31 | * @since 2.0
32 | */
33 | class Dialog extends Widget
34 | {
35 | /**
36 | * Initializes the widget.
37 | */
38 | public function init()
39 | {
40 | parent::init();
41 | echo Html::beginTag('div', $this->options) . "\n";
42 |
43 | //Fix for closing icon (x) not showing up in dialog
44 | $this->getView()->registerJs("
45 | if ($.fn.button) {
46 | var bootstrapButton = $.fn.button.noConflict();
47 | $.fn.bootstrapBtn = bootstrapButton;
48 | }",
49 | \yii\web\View::POS_READY
50 | );
51 | }
52 |
53 | /**
54 | * Renders the widget.
55 | */
56 | public function run()
57 | {
58 | echo Html::endTag('div') . "\n";
59 | $this->registerWidget('dialog');
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Draggable.php:
--------------------------------------------------------------------------------
1 | ['grid' => [50, 20]],
20 | * ]);
21 | *
22 | * echo 'Draggable contents here...';
23 | *
24 | * Draggable::end();
25 | * ```
26 | *
27 | * @see https://api.jqueryui.com/draggable/
28 | * @author Alexander Kochetov
29 | * @since 2.0
30 | */
31 | class Draggable extends Widget
32 | {
33 | /**
34 | * {@inheritdoc}
35 | */
36 | protected $clientEventMap = [
37 | 'create' => 'dragcreate',
38 | 'drag' => 'drag',
39 | 'stop' => 'dragstop',
40 | 'start' => 'dragstart',
41 | ];
42 |
43 |
44 | /**
45 | * Initializes the widget.
46 | */
47 | public function init()
48 | {
49 | parent::init();
50 | echo Html::beginTag('div', $this->options) . "\n";
51 | }
52 |
53 | /**
54 | * Renders the widget.
55 | */
56 | public function run()
57 | {
58 | echo Html::endTag('div') . "\n";
59 | $this->registerWidget('draggable');
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Droppable.php:
--------------------------------------------------------------------------------
1 | ['accept' => '.special'],
20 | * ]);
21 | *
22 | * echo 'Droppable body here...';
23 | *
24 | * Droppable::end();
25 | * ```
26 | *
27 | * @see https://api.jqueryui.com/droppable/
28 | * @author Alexander Kochetov
29 | * @since 2.0
30 | */
31 | class Droppable extends Widget
32 | {
33 | /**
34 | * {@inheritdoc}
35 | */
36 | protected $clientEventMap = [
37 | 'activate' => 'dropactivate',
38 | 'create' => 'dropcreate',
39 | 'deactivate' => 'dropdeactivate',
40 | 'drop' => 'drop',
41 | 'out' => 'dropout',
42 | 'over' => 'dropover',
43 | ];
44 |
45 |
46 | /**
47 | * Initializes the widget.
48 | */
49 | public function init()
50 | {
51 | parent::init();
52 | echo Html::beginTag('div', $this->options) . "\n";
53 | }
54 |
55 | /**
56 | * Renders the widget.
57 | */
58 | public function run()
59 | {
60 | echo Html::endTag('div') . "\n";
61 | $this->registerWidget('droppable');
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/InputWidget.php:
--------------------------------------------------------------------------------
1 | field($model, 'from_date')->widget('WidgetClassName', [
21 | * // configure additional widget properties here
22 | * ]) ?>
23 | * ```
24 | *
25 | * @author Alexander Kochetov
26 | * @since 2.0
27 | */
28 | class InputWidget extends Widget
29 | {
30 | /**
31 | * @var Model the data model that this widget is associated with.
32 | */
33 | public $model;
34 | /**
35 | * @var string the model attribute that this widget is associated with.
36 | */
37 | public $attribute;
38 | /**
39 | * @var string the input name. This must be set if [[model]] and [[attribute]] are not set.
40 | */
41 | public $name;
42 | /**
43 | * @var string the input value.
44 | */
45 | public $value;
46 |
47 |
48 | /**
49 | * Initializes the widget.
50 | * If you override this method, make sure you call the parent implementation first.
51 | */
52 | public function init()
53 | {
54 | if ($this->hasModel() && !isset($this->options['id'])) {
55 | $this->options['id'] = Html::getInputId($this->model, $this->attribute);
56 | }
57 | parent::init();
58 | }
59 |
60 | /**
61 | * @return bool whether this widget is associated with a data model.
62 | */
63 | protected function hasModel()
64 | {
65 | return $this->model instanceof Model && $this->attribute !== null;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/JuiAsset.php:
--------------------------------------------------------------------------------
1 |
14 | * @since 2.0
15 | */
16 | class JuiAsset extends AssetBundle
17 | {
18 | /**
19 | * {@inheritdoc}
20 | */
21 | public $sourcePath = '@bower/jquery-ui';
22 | /**
23 | * {@inheritdoc}
24 | */
25 | public $js = [
26 | 'jquery-ui.js',
27 | ];
28 | /**
29 | * {@inheritdoc}
30 | */
31 | public $css = [
32 | 'themes/smoothness/jquery-ui.css',
33 | ];
34 | /**
35 | * {@inheritdoc}
36 | */
37 | public $depends = [
38 | 'yii\web\JqueryAsset',
39 | ];
40 | }
41 |
--------------------------------------------------------------------------------
/src/Menu.php:
--------------------------------------------------------------------------------
1 |
17 | * @since 2.0
18 | */
19 | class Menu extends \yii\widgets\Menu
20 | {
21 | /**
22 | * @var array the options for the underlying jQuery UI widget.
23 | * Please refer to the corresponding jQuery UI widget Web page for possible options.
24 | * For example, [this page](https://api.jqueryui.com/accordion/) shows
25 | * how to use the "Accordion" widget and the supported options (e.g. "header").
26 | */
27 | public $clientOptions = [];
28 | /**
29 | * @var array the event handlers for the underlying jQuery UI widget.
30 | * Please refer to the corresponding jQuery UI widget Web page for possible events.
31 | * For example, [this page](https://api.jqueryui.com/accordion/) shows
32 | * how to use the "Accordion" widget and the supported events (e.g. "create").
33 | */
34 | public $clientEvents = [];
35 |
36 |
37 | /**
38 | * Initializes the widget.
39 | * If you override this method, make sure you call the parent implementation first.
40 | */
41 | public function init()
42 | {
43 | parent::init();
44 | if (!isset($this->options['id'])) {
45 | $this->options['id'] = $this->getId();
46 | }
47 | }
48 |
49 | /**
50 | * Renders the widget.
51 | */
52 | public function run()
53 | {
54 | parent::run();
55 |
56 | $view = $this->getView();
57 | JuiAsset::register($view);
58 |
59 | $id = $this->options['id'];
60 | if ($this->clientOptions !== false) {
61 | $options = empty($this->clientOptions) ? '' : Json::htmlEncode($this->clientOptions);
62 | $js = "jQuery('#$id').menu($options);";
63 | $view->registerJs($js);
64 | }
65 |
66 | if (!empty($this->clientEvents)) {
67 | $js = [];
68 | foreach ($this->clientEvents as $event => $handler) {
69 | $js[] = "jQuery('#$id').on('menu$event', $handler);";
70 | }
71 | $view->registerJs(implode("\n", $js));
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/ProgressBar.php:
--------------------------------------------------------------------------------
1 | [
20 | * 'value' => 75,
21 | * ],
22 | * ]);
23 | * ```
24 | *
25 | * The following example will show the content enclosed between the [[begin()]]
26 | * and [[end()]] calls within the widget container:
27 | *
28 | * ~~~php
29 | * ProgressBar::begin([
30 | * 'clientOptions' => ['value' => 75],
31 | * ]);
32 | *
33 | * echo 'Loading...
';
34 | *
35 | * ProgressBar::end();
36 | * ~~~
37 | * @see https://api.jqueryui.com/progressbar/
38 | * @author Alexander Kochetov
39 | * @since 2.0
40 | */
41 | class ProgressBar extends Widget
42 | {
43 | /**
44 | * Initializes the widget.
45 | */
46 | public function init()
47 | {
48 | parent::init();
49 | echo Html::beginTag('div', $this->options) . "\n";
50 | }
51 |
52 | /**
53 | * Renders the widget.
54 | */
55 | public function run()
56 | {
57 | echo Html::endTag('div') . "\n";
58 | $this->registerWidget('progressbar');
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/Resizable.php:
--------------------------------------------------------------------------------
1 | [
20 | * 'grid' => [20, 10],
21 | * ],
22 | * ]);
23 | *
24 | * echo 'Resizable contents here...';
25 | *
26 | * Resizable::end();
27 | * ```
28 | *
29 | * @see https://api.jqueryui.com/resizable/
30 | * @author Alexander Kochetov
31 | * @since 2.0
32 | */
33 | class Resizable extends Widget
34 | {
35 | /**
36 | * {@inheritdoc}
37 | */
38 | protected $clientEventMap = [
39 | 'create' => 'resizecreate',
40 | 'resize' => 'resize',
41 | 'start' => 'resizestart',
42 | 'stop' => 'resizestop',
43 | ];
44 |
45 |
46 | /**
47 | * Initializes the widget.
48 | */
49 | public function init()
50 | {
51 | parent::init();
52 | echo Html::beginTag('div', $this->options) . "\n";
53 | }
54 |
55 | /**
56 | * Renders the widget.
57 | */
58 | public function run()
59 | {
60 | echo Html::endTag('div') . "\n";
61 | $this->registerWidget('resizable');
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Selectable.php:
--------------------------------------------------------------------------------
1 | [
22 | * 'Item 1',
23 | * [
24 | * 'content' => 'Item2',
25 | * ],
26 | * [
27 | * 'content' => 'Item3',
28 | * 'options' => [
29 | * 'tag' => 'li',
30 | * ],
31 | * ],
32 | * ],
33 | * 'options' => [
34 | * 'tag' => 'ul',
35 | * ],
36 | * 'itemOptions' => [
37 | * 'tag' => 'li',
38 | * ],
39 | * 'clientOptions' => [
40 | * 'tolerance' => 'fit',
41 | * ],
42 | * ]);
43 | * ```
44 | *
45 | * Selectable in begin mode.
46 | *
47 | * ```php
48 | * Selectable::begin([
49 | * 'clientOptions' => [
50 | * 'filter' => 'my-selectable-item',
51 | * 'tolerance' => 'touch',
52 | * ],
53 | * ]);
54 | * ```
55 | *
56 | * - Item 1
57 | * - Item 2
58 | * - Item 3
59 | * - Item 4
60 | *
61 | *
62 | *
63 | *
Another item
64 | *
65 | *
66 | *
67 | * ```php
68 | * Selectable::end();
69 | * ```
70 | *
71 | * @see https://api.jqueryui.com/selectable/
72 | * @author Alexander Kochetov
73 | * @since 2.0
74 | */
75 | class Selectable extends Widget
76 | {
77 | const MODE_DEFAULT = 'MODE_DEFAULT';
78 | const MODE_BEGIN = 'MODE_BEGIN';
79 |
80 | /**
81 | * @var string the mode used to render the widget.
82 | */
83 | public $mode = self::MODE_DEFAULT;
84 | /**
85 | * @var array the HTML attributes for the widget container tag. The following special options are recognized:
86 | *
87 | * - tag: string, defaults to "ul", the tag name of the container tag of this widget.
88 | *
89 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
90 | */
91 | public $options = [];
92 | /**
93 | * @var array list of selectable items. Each item can be a string representing the item content
94 | * or an array of the following structure:
95 | *
96 | * ```php
97 | * [
98 | * 'content' => 'item content',
99 | * // the HTML attributes of the item container tag. This will overwrite "itemOptions".
100 | * 'options' => [],
101 | * ]
102 | * ```
103 | */
104 | public $items = [];
105 | /**
106 | * @var array list of HTML attributes for the item container tags. This will be overwritten
107 | * by the "options" set in individual [[items]]. The following special options are recognized:
108 | *
109 | * - tag: string, defaults to "li", the tag name of the item container tags.
110 | *
111 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
112 | */
113 | public $itemOptions = [];
114 |
115 |
116 | /**
117 | * Begins a widget.
118 | * This method creates an instance of the calling class setting the MODE_BEGIN mode. Any item between
119 | * [[begin()]] and [[end()]] which match the filter attribute, will be selectable.
120 | * It will apply the configuration
121 | * to the created instance. A matching [[end()]] call should be called later.
122 | * As some widgets may use output buffering, the [[end()]] call should be made in the same view
123 | * to avoid breaking the nesting of output buffers.
124 | * @param array $config name-value pairs that will be used to initialize the object properties
125 | * @return static the newly created widget instance
126 | * @see end()
127 | */
128 | public static function begin($config = []) {
129 | $config['mode'] = self::MODE_BEGIN;
130 | parent::begin($config);
131 | }
132 |
133 | /**
134 | * Initializes the widget.
135 | */
136 | public function init()
137 | {
138 | parent::init();
139 | if ($this->mode === self::MODE_BEGIN) {
140 | echo Html::beginTag('div', $this->options) . "\n";
141 | }
142 | }
143 |
144 | /**
145 | * Renders the widget.
146 | */
147 | public function run()
148 | {
149 | if ($this->mode === self::MODE_BEGIN) {
150 | echo Html::endTag('div') . "\n";
151 | } else {
152 | $options = $this->options;
153 | $tag = ArrayHelper::remove($options, 'tag', 'ul');
154 | echo Html::beginTag($tag, $options) . "\n";
155 | echo $this->renderItems() . "\n";
156 | echo Html::endTag($tag) . "\n";
157 | }
158 |
159 | $this->registerWidget('selectable');
160 | }
161 |
162 | /**
163 | * Renders selectable items as specified on [[items]].
164 | * @return string the rendering result.
165 | * @throws InvalidConfigException.
166 | */
167 | public function renderItems()
168 | {
169 | $items = [];
170 | foreach ($this->items as $item) {
171 | $options = $this->itemOptions;
172 | $tag = ArrayHelper::remove($options, 'tag', 'li');
173 | if (is_array($item)) {
174 | if (!array_key_exists('content', $item)) {
175 | throw new InvalidConfigException("The 'content' option is required.");
176 | }
177 | $options = array_merge($options, ArrayHelper::getValue($item, 'options', []));
178 | $tag = ArrayHelper::remove($options, 'tag', $tag);
179 | $items[] = Html::tag($tag, $item['content'], $options);
180 | } else {
181 | $items[] = Html::tag($tag, $item, $options);
182 | }
183 | }
184 | return implode("\n", $items);
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/src/Slider.php:
--------------------------------------------------------------------------------
1 | [
18 | * 'min' => 1,
19 | * 'max' => 10,
20 | * ],
21 | * ]);
22 | * ```
23 | *
24 | * @see https://api.jqueryui.com/slider/
25 | * @author Alexander Makarov
26 | * @since 2.0
27 | */
28 | class Slider extends Widget
29 | {
30 | /**
31 | * @inheritDoc
32 | */
33 | protected $clientEventMap = [
34 | 'change' => 'slidechange',
35 | 'create' => 'slidecreate',
36 | 'slide' => 'slide',
37 | 'start' => 'slidestart',
38 | 'stop' => 'slidestop',
39 | ];
40 |
41 |
42 | /**
43 | * Executes the widget.
44 | */
45 | public function run()
46 | {
47 | echo Html::tag('div', '', $this->options);
48 | $this->registerWidget('slider');
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/SliderInput.php:
--------------------------------------------------------------------------------
1 | $model,
20 | * 'attribute' => 'amount',
21 | * 'clientOptions' => [
22 | * 'min' => 1,
23 | * 'max' => 10,
24 | * ],
25 | * ]);
26 | * ```
27 | *
28 | * The following example will use the name property instead:
29 | *
30 | * ```
31 | * echo SliderInput::widget([
32 | * 'name' => 'amount',
33 | * 'clientOptions' => [
34 | * 'min' => 1,
35 | * 'max' => 10,
36 | * ],
37 | * ]);
38 | * ```
39 | *
40 | * You can also use this widget in an [[yii\widgets\ActiveForm|ActiveForm]] using the [[yii\widgets\ActiveField::widget()|widget()]]
41 | * method, for example like this:
42 | *
43 | * ```php
44 | * = $form->field($model, 'from_date')->widget(\yii\jui\SliderInput::classname(), [
45 | * 'clientOptions' => [
46 | * 'min' => 1,
47 | * 'max' => 10,
48 | * ],
49 | * ]) ?>
50 | * ```
51 | *
52 | * @see https://api.jqueryui.com/slider/
53 | * @author Alexander Makarov
54 | * @since 2.0
55 | */
56 | class SliderInput extends InputWidget
57 | {
58 | /**
59 | * @var array the HTML attributes for the container tag.
60 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
61 | */
62 | public $containerOptions = [];
63 |
64 | /**
65 | * @inheritDoc
66 | */
67 | protected $clientEventMap = [
68 | 'change' => 'slidechange',
69 | 'create' => 'slidecreate',
70 | 'slide' => 'slide',
71 | 'start' => 'slidestart',
72 | 'stop' => 'slidestop',
73 | ];
74 |
75 |
76 | /**
77 | * {@inheritdoc}
78 | */
79 | public function init()
80 | {
81 | parent::init();
82 | if (!isset($this->containerOptions['id'])) {
83 | $this->containerOptions['id'] = $this->options['id'] . '-container';
84 | }
85 | }
86 |
87 | /**
88 | * Executes the widget.
89 | */
90 | public function run()
91 | {
92 | echo Html::tag('div', '', $this->containerOptions);
93 |
94 | if ($this->hasModel()) {
95 | echo Html::activeHiddenInput($this->model, $this->attribute, $this->options);
96 | $this->clientOptions['value'] = Html::getAttributeValue($this->model, $this->attribute);
97 | } else {
98 | echo Html::hiddenInput($this->name, $this->value, $this->options);
99 | $this->clientOptions['value'] = $this->value;
100 | }
101 |
102 | if (!isset($this->clientEvents['slide'])) {
103 | $this->clientEvents['slide'] = 'function (event, ui) {
104 | jQuery("#' . $this->options['id'] . '").val(ui.value);
105 | }';
106 | }
107 |
108 | $this->registerWidget('slider', $this->containerOptions['id']);
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/Sortable.php:
--------------------------------------------------------------------------------
1 | [
22 | * 'Item 1',
23 | * ['content' => 'Item2'],
24 | * [
25 | * 'content' => 'Item3',
26 | * 'options' => ['tag' => 'li'],
27 | * ],
28 | * ],
29 | * 'options' => ['tag' => 'ul'],
30 | * 'itemOptions' => ['tag' => 'li'],
31 | * 'clientOptions' => ['cursor' => 'move'],
32 | * ]);
33 | * ```
34 | *
35 | * @see https://api.jqueryui.com/sortable/
36 | * @author Alexander Kochetov
37 | * @since 2.0
38 | */
39 | class Sortable extends Widget
40 | {
41 | /**
42 | * @var array the HTML attributes for the widget container tag. The following special options are recognized:
43 | *
44 | * - tag: string, defaults to "ul", the tag name of the container tag of this widget.
45 | *
46 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
47 | */
48 | public $options = [];
49 | /**
50 | * @var array list of sortable items. Each item can be a string representing the item content
51 | * or an array of the following structure:
52 | *
53 | * ```php
54 | * [
55 | * 'content' => 'item content',
56 | * // the HTML attributes of the item container tag. This will overwrite "itemOptions".
57 | * 'options' => [],
58 | * ]
59 | * ```
60 | */
61 | public $items = [];
62 | /**
63 | * @var array list of HTML attributes for the item container tags. This will be overwritten
64 | * by the "options" set in individual [[items]]. The following special options are recognized:
65 | *
66 | * - tag: string, defaults to "li", the tag name of the item container tags.
67 | *
68 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
69 | */
70 | public $itemOptions = [];
71 |
72 | /**
73 | * {@inheritdoc}
74 | */
75 | protected $clientEventMap = [
76 | 'activate' => 'sortactivate',
77 | 'beforeStop' => 'sortbeforestop',
78 | 'change' => 'sortchange',
79 | 'create' => 'sortcreate',
80 | 'deactivate' => 'sortdeactivate',
81 | 'out' => 'sortout',
82 | 'over' => 'sortover',
83 | 'receive' => 'sortreceive',
84 | 'remove' => 'sortremove',
85 | 'sort' => 'sort',
86 | 'start' => 'sortstart',
87 | 'stop' => 'sortstop',
88 | 'update' => 'sortupdate',
89 | ];
90 |
91 |
92 | /**
93 | * Renders the widget.
94 | */
95 | public function run()
96 | {
97 | $options = $this->options;
98 | $tag = ArrayHelper::remove($options, 'tag', 'ul');
99 | echo Html::beginTag($tag, $options) . "\n";
100 | echo $this->renderItems() . "\n";
101 | echo Html::endTag($tag) . "\n";
102 | $this->registerWidget('sortable');
103 | }
104 |
105 | /**
106 | * Renders sortable items as specified on [[items]].
107 | * @return string the rendering result.
108 | * @throws InvalidConfigException.
109 | */
110 | public function renderItems()
111 | {
112 | $items = [];
113 | foreach ($this->items as $item) {
114 | $options = $this->itemOptions;
115 | $tag = ArrayHelper::remove($options, 'tag', 'li');
116 | if (is_array($item)) {
117 | if (!isset($item['content'])) {
118 | throw new InvalidConfigException("The 'content' option is required.");
119 | }
120 | $options = array_merge($options, ArrayHelper::getValue($item, 'options', []));
121 | $tag = ArrayHelper::remove($options, 'tag', $tag);
122 | $items[] = Html::tag($tag, $item['content'], $options);
123 | } else {
124 | $items[] = Html::tag($tag, $item, $options);
125 | }
126 | }
127 |
128 | return implode("\n", $items);
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/src/Spinner.php:
--------------------------------------------------------------------------------
1 | $model,
20 | * 'attribute' => 'country',
21 | * 'clientOptions' => ['step' => 2],
22 | * ]);
23 | * ```
24 | *
25 | * The following example will use the name property instead:
26 | *
27 | * ```php
28 | * echo Spinner::widget([
29 | * 'name' => 'country',
30 | * 'clientOptions' => ['step' => 2],
31 | * ]);
32 | * ```
33 | *
34 | * You can also use this widget in an [[yii\widgets\ActiveForm|ActiveForm]] using the [[yii\widgets\ActiveField::widget()|widget()]]
35 | * method, for example like this:
36 | *
37 | * ```php
38 | * = $form->field($model, 'from_date')->widget(\yii\jui\Spinner::classname(), [
39 | * 'clientOptions' => ['step' => 2],
40 | * ]) ?>
41 | * ```
42 | *
43 | * @see https://api.jqueryui.com/spinner/
44 | * @author Alexander Kochetov
45 | * @since 2.0
46 | */
47 | class Spinner extends InputWidget
48 | {
49 | /**
50 | * @inheritDoc
51 | */
52 | protected $clientEventMap = [
53 | 'spin' => 'spin',
54 | 'change' => 'spinchange',
55 | 'create' => 'spincreate',
56 | 'start' => 'spinstart',
57 | 'stop' => 'spinstop'
58 | ];
59 |
60 |
61 | /**
62 | * Renders the widget.
63 | */
64 | public function run()
65 | {
66 | echo $this->renderWidget();
67 | $this->registerWidget('spinner');
68 | }
69 |
70 | /**
71 | * Renders the Spinner widget.
72 | * @return string the rendering result.
73 | */
74 | public function renderWidget()
75 | {
76 | if ($this->hasModel()) {
77 | return Html::activeTextInput($this->model, $this->attribute, $this->options);
78 | }
79 | return Html::textInput($this->name, $this->value, $this->options);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/Tabs.php:
--------------------------------------------------------------------------------
1 | [
23 | * [
24 | * 'label' => 'Tab one',
25 | * 'content' => 'Mauris mauris ante, blandit et, ultrices a, suscipit eget...',
26 | * ],
27 | * [
28 | * 'label' => 'Tab two',
29 | * 'content' => 'Sed non urna. Phasellus eu ligula. Vestibulum sit amet purus...',
30 | * 'options' => ['tag' => 'div'],
31 | * 'headerOptions' => ['class' => 'my-class'],
32 | * ],
33 | * [
34 | * 'label' => 'Tab with custom id',
35 | * 'content' => 'Morbi tincidunt, dui sit amet facilisis feugiat...',
36 | * 'options' => ['id' => 'my-tab'],
37 | * ],
38 | * [
39 | * 'label' => 'Ajax tab',
40 | * 'url' => ['ajax/content'],
41 | * ],
42 | * ],
43 | * 'options' => ['tag' => 'div'],
44 | * 'itemOptions' => ['tag' => 'div'],
45 | * 'headerOptions' => ['class' => 'my-class'],
46 | * 'clientOptions' => ['collapsible' => false],
47 | * ]);
48 | * ```
49 | *
50 | * @see https://api.jqueryui.com/tabs/
51 | * @author Alexander Kochetov
52 | * @since 2.0
53 | */
54 | class Tabs extends Widget
55 | {
56 | /**
57 | * @var array the HTML attributes for the widget container tag. The following special options are recognized:
58 | *
59 | * - tag: string, defaults to "div", the tag name of the container tag of this widget.
60 | *
61 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
62 | */
63 | public $options = [];
64 | /**
65 | * @var array list of tab items. Each item can be an array of the following structure:
66 | *
67 | * - label: string, required, specifies the header link label. When [[encodeLabels]] is true, the label
68 | * will be HTML-encoded.
69 | * - content: string, the content to show when corresponding tab is clicked. Can be omitted if url is specified.
70 | * - url: mixed, mixed, optional, the url to load tab contents via AJAX. It is required if no content is specified.
71 | * - template: string, optional, the header link template to render the header link. If none specified
72 | * [[linkTemplate]] will be used instead.
73 | * - options: array, optional, the HTML attributes of the header.
74 | * - headerOptions: array, optional, the HTML attributes for the header container tag.
75 | */
76 | public $items = [];
77 | /**
78 | * @var array list of HTML attributes for the item container tags. This will be overwritten
79 | * by the "options" set in individual [[items]]. The following special options are recognized:
80 | *
81 | * - tag: string, defaults to "div", the tag name of the item container tags.
82 | *
83 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
84 | */
85 | public $itemOptions = [];
86 | /**
87 | * @var array list of HTML attributes for the header container tags. This will be overwritten
88 | * by the "headerOptions" set in individual [[items]].
89 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
90 | */
91 | public $headerOptions = [];
92 | /**
93 | * @var string the default header template to render the link.
94 | */
95 | public $linkTemplate = '{label}';
96 | /**
97 | * @var boolean whether the labels for header items should be HTML-encoded.
98 | */
99 | public $encodeLabels = true;
100 |
101 |
102 | /**
103 | * Renders the widget.
104 | */
105 | public function run()
106 | {
107 | $options = $this->options;
108 | $tag = ArrayHelper::remove($options, 'tag', 'div');
109 | $out = Html::beginTag($tag, $options) . "\n";
110 | $out .= $this->renderItems() . "\n";
111 | $out .= Html::endTag($tag) . "\n";
112 |
113 | $this->registerWidget('tabs');
114 |
115 | return $out;
116 | }
117 |
118 | /**
119 | * Renders tab items as specified on [[items]].
120 | * @return string the rendering result.
121 | * @throws InvalidConfigException.
122 | */
123 | protected function renderItems()
124 | {
125 | $headers = [];
126 | $items = [];
127 | foreach ($this->items as $n => $item) {
128 | if (!isset($item['label'])) {
129 | throw new InvalidConfigException("The 'label' option is required.");
130 | }
131 | if (isset($item['url'])) {
132 | $url = Url::to($item['url']);
133 | } else {
134 | if (!array_key_exists('content', $item)) {
135 | throw new InvalidConfigException("Either the 'content' or 'url' option is required.");
136 | }
137 | $options = array_merge($this->itemOptions, ArrayHelper::getValue($item, 'options', []));
138 | $tag = ArrayHelper::remove($options, 'tag', 'div');
139 | if (!isset($options['id'])) {
140 | $options['id'] = $this->options['id'] . '-tab' . $n;
141 | }
142 | $url = '#' . $options['id'];
143 | $items[] = Html::tag($tag, $item['content'], $options);
144 | }
145 | $headerOptions = array_merge($this->headerOptions, ArrayHelper::getValue($item, 'headerOptions', []));
146 | $template = ArrayHelper::getValue($item, 'template', $this->linkTemplate);
147 | $headers[] = Html::tag('li', strtr($template, [
148 | '{label}' => $this->encodeLabels ? Html::encode($item['label']) : $item['label'],
149 | '{url}' => $url,
150 | ]), $headerOptions);
151 | }
152 |
153 | return Html::tag('ul', implode("\n", $headers)) . "\n" . implode("\n", $items);
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/src/Widget.php:
--------------------------------------------------------------------------------
1 |
16 | * @since 2.0
17 | */
18 | class Widget extends \yii\base\Widget
19 | {
20 | /**
21 | * @var array the HTML attributes for the widget container tag.
22 | * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
23 | */
24 | public $options = [];
25 | /**
26 | * @var array the options for the underlying jQuery UI widget.
27 | * Please refer to the corresponding jQuery UI widget Web page for possible options.
28 | * For example, [this page](https://api.jqueryui.com/accordion/) shows
29 | * how to use the "Accordion" widget and the supported options (e.g. "header").
30 | */
31 | public $clientOptions = [];
32 | /**
33 | * @var array the event handlers for the underlying jQuery UI widget.
34 | * Please refer to the corresponding jQuery UI widget Web page for possible events.
35 | * For example, [this page](https://api.jqueryui.com/accordion/) shows
36 | * how to use the "Accordion" widget and the supported events (e.g. "create").
37 | * Keys are the event names and values are javascript code that is passed to the `.on()` function
38 | * as the event handler.
39 | *
40 | * For example you could write the following in your widget configuration:
41 | *
42 | * ```php
43 | * 'clientEvents' => [
44 | * 'change' => 'function () { alert('event "change" occured.'); }'
45 | * ],
46 | * ```
47 | */
48 | public $clientEvents = [];
49 |
50 | /**
51 | * @var array event names mapped to what should be specified in `.on()`.
52 | * If empty, it is assumed that event passed to clientEvents is prefixed with widget name.
53 | */
54 | protected $clientEventMap = [];
55 |
56 |
57 | /**
58 | * Initializes the widget.
59 | * If you override this method, make sure you call the parent implementation first.
60 | */
61 | public function init()
62 | {
63 | parent::init();
64 | if (!isset($this->options['id'])) {
65 | $this->options['id'] = $this->getId();
66 | }
67 | }
68 |
69 | /**
70 | * Registers a specific jQuery UI widget options
71 | * @param string $name the name of the jQuery UI widget
72 | * @param string $id the ID of the widget
73 | */
74 | protected function registerClientOptions($name, $id)
75 | {
76 | if ($this->clientOptions !== false) {
77 | $options = empty($this->clientOptions) ? '' : Json::htmlEncode($this->clientOptions);
78 | $js = "jQuery('#$id').$name($options);";
79 | $this->getView()->registerJs($js);
80 | }
81 | }
82 |
83 | /**
84 | * Registers a specific jQuery UI widget events
85 | * @param string $name the name of the jQuery UI widget
86 | * @param string $id the ID of the widget
87 | */
88 | protected function registerClientEvents($name, $id)
89 | {
90 | if (!empty($this->clientEvents)) {
91 | $js = [];
92 | foreach ($this->clientEvents as $event => $handler) {
93 | if (isset($this->clientEventMap[$event])) {
94 | $eventName = $this->clientEventMap[$event];
95 | } else {
96 | $eventName = strtolower($name . $event);
97 | }
98 | $js[] = "jQuery('#$id').on('$eventName', $handler);";
99 | }
100 | $this->getView()->registerJs(implode("\n", $js));
101 | }
102 | }
103 |
104 | /**
105 | * Registers a specific jQuery UI widget asset bundle, initializes it with client options and registers related events
106 | * @param string $name the name of the jQuery UI widget
107 | * @param string $id the ID of the widget. If null, it will use the `id` value of [[options]].
108 | */
109 | protected function registerWidget($name, $id = null)
110 | {
111 | if ($id === null) {
112 | $id = $this->options['id'];
113 | }
114 | JuiAsset::register($this->getView());
115 | $this->registerClientEvents($name, $id);
116 | $this->registerClientOptions($name, $id);
117 | }
118 | }
119 |
--------------------------------------------------------------------------------