diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..59ea3d7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +# Ignore all test and documentation for archive +/.gitattributes export-ignore +/.gitignore export-ignore +/.scrutinizer.yml export-ignore +/.travis.yml export-ignore +/phpunit.xml.dist export-ignore +/tests export-ignore +/docs export-ignore \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..de4a392 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/vendor +/composer.lock diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2321510 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,47 @@ +language: php + +php: + - 5.4 + - 5.5 + - 5.6 + - 7.0 + - hhvm + - hhvm-nightly + +# run build against hhvm but allow them to fail +# http://docs.travis-ci.com/user/build-configuration/#Rows-That-are-Allowed-To-Fail +matrix: + fast_finish: true + allow_failures: + - php: hhvm-nightly + - php: 7.0 + +# faster builds on new travis setup not using sudo +sudo: false + +# cache vendor dirs +cache: + directories: + - $HOME/.composer/cache + +install: + - travis_retry composer self-update && composer --version + - travis_retry composer global require "fxp/composer-asset-plugin:1.0.0" + - export PATH="$HOME/.composer/vendor/bin:$PATH" + - travis_retry composer install --prefer-dist --no-interaction + +before_script: + - | + if [ $TRAVIS_PHP_VERSION = '5.6' ]; then + PHPUNIT_FLAGS="--coverage-clover=coverage.clover" + fi + +script: + - phpunit --verbose $PHPUNIT_FLAGS + +after_script: + - | + if [ $TRAVIS_PHP_VERSION = '5.6' ]; then + travis_retry wget https://scrutinizer-ci.com/ocular.phar + php ocular.phar code-coverage:upload --format=php-clover coverage.clover + fi diff --git a/ActiveField.php b/ActiveField.php index 2f72b28..3181a6c 100644 --- a/ActiveField.php +++ b/ActiveField.php @@ -201,6 +201,9 @@ class ActiveField extends \yii\widgets\ActiveField $this->template = $options['template']; unset($options['template']); } + if (isset($options['label'])) { + $this->parts['{labelTitle}'] = $options['label']; + } if ($this->form->layout === 'horizontal') { Html::addCssClass($this->wrapperOptions, $this->horizontalCssClasses['offset']); } @@ -223,6 +226,9 @@ class ActiveField extends \yii\widgets\ActiveField $this->template = $options['template']; unset($options['template']); } + if (isset($options['label'])) { + $this->parts['{labelTitle}'] = $options['label']; + } if ($this->form->layout === 'horizontal') { Html::addCssClass($this->wrapperOptions, $this->horizontalCssClasses['offset']); } @@ -381,6 +387,8 @@ class ActiveField extends \yii\widgets\ActiveField } $this->parts['{beginLabel}'] = Html::beginTag('label', $options); $this->parts['{endLabel}'] = Html::endTag('label'); - $this->parts['{labelTitle}'] = $label; + if (!isset($this->parts['{labelTitle}'])) { + $this->parts['{labelTitle}'] = $label; + } } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 1968bd6..569d6ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,10 @@ Yii Framework 2 bootstrap extension Change Log 2.0.4 under development ----------------------- +- Bug #18: `label` option ignored by `yii\bootstrap\Activefield::checkbox()` and `yii\bootstrap\Activefield::radio()` (mikehaertl) - Bug #5984: `yii\bootstrap\Activefield::checkbox()` caused browser to link label to the wrong input (cebe) - Enh #7633: Added `ActionColumn::$buttonOptions` for defining HTML options to be added to the default buttons (cebe) +- Enh: Added `Nav::$dropDownCaret` to allow customization of the dropdown caret symbol (cebe) 2.0.3 March 01, 2015 diff --git a/Nav.php b/Nav.php index e5d132f..498d86c 100644 --- a/Nav.php +++ b/Nav.php @@ -93,6 +93,12 @@ class Nav extends Widget * @see isItemActive */ public $params; + /** + * @var string this property allows you to customize the HTML which is used to generate the drop down caret symbol, + * which is displayed next to the button text to indicate the drop down functionality. + * Defaults to `null` which means `` will be used. To disable the caret, set this property to be an empty string. + */ + public $dropDownCaret; /** @@ -107,6 +113,9 @@ class Nav extends Widget if ($this->params === null) { $this->params = Yii::$app->request->getQueryParams(); } + if ($this->dropDownCaret === null) { + $this->dropDownCaret = Html::tag('b', '', ['class' => 'caret']); + } Html::addCssClass($this->options, 'nav'); } @@ -166,7 +175,9 @@ class Nav extends Widget $linkOptions['data-toggle'] = 'dropdown'; Html::addCssClass($options, 'dropdown'); Html::addCssClass($linkOptions, 'dropdown-toggle'); - $label .= ' ' . Html::tag('b', '', ['class' => 'caret']); + if ($this->dropDownCaret !== '') { + $label .= ' ' . $this->dropDownCaret; + } if (is_array($items)) { if ($this->activateItems) { $items = $this->isChildActive($items, $active); diff --git a/README.md b/README.md index 27cc5dc..d647349 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,17 @@ Twitter Bootstrap Extension for Yii 2 ===================================== -This is the Twitter Bootstrap extension for Yii 2. It encapsulates [Bootstrap](http://getbootstrap.com/) components +This is the Twitter Bootstrap extension for [Yii framework 2.0](http://www.yiiframework.com). It encapsulates [Bootstrap](http://getbootstrap.com/) components and plugins in terms of Yii widgets, and thus makes using Bootstrap components/plugins in Yii applications extremely easy. For license information check the [LICENSE](LICENSE.md)-file. +[![Latest Stable Version](https://poser.pugx.org/yiisoft/yii2-bootstrap/v/stable.png)](https://packagist.org/packages/yiisoft/yii2-bootstrap) +[![Total Downloads](https://poser.pugx.org/yiisoft/yii2-bootstrap/downloads.png)](https://packagist.org/packages/yiisoft/yii2-bootstrap) +[![Build Status](https://travis-ci.org/yiisoft/yii2-bootstrap.svg?branch=master)](https://travis-ci.org/yiisoft/yii2-bootstrap) + + Installation ------------ diff --git a/composer.json b/composer.json index 4a5da0d..fde1a87 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,10 @@ "extra": { "branch-alias": { "dev-master": "2.0.x-dev" + }, + "asset-installer-paths": { + "npm-asset-library": "vendor/npm", + "bower-asset-library": "vendor/bower" } } } diff --git a/docs/guide-ja/README.md b/docs/guide-ja/README.md new file mode 100644 index 0000000..2b8ae37 --- /dev/null +++ b/docs/guide-ja/README.md @@ -0,0 +1,27 @@ +Yii 2 Twitter Bootstrap エクステンション +======================================== + +このエクステンションは、マークアップとコンポーネントのフレームワーク [Bootstrap 3](http://getbootstrap.com/) ("Twitter Bootstrap" としても知られています) に対するサポートを提供します。 +Bootstrap は優れた、レスポンシブなフレームワークであり、クライアント側の開発プロセスを大いにスピードアップすることが出来るものです。 + +Bootstrap のコアは二つの部分によって表されます。 + +- CSS の基礎。例えば、グリッドレイアウトシステム、タイポグラフィ、ヘルパクラス、レスポンシブユーティリティなど。 +- そのまま使えるコンポーネント。フォーム、メニュー、ページネーション、モーダルボックス、タブなど。 + + +始めよう +-------- + +* [インストール](installation.md) +* [基本的な使用方法](basic-usage.md) + +使用方法 +-------- + +* [Yii ウィジェット](usage-widgets.md) + +追加のトピック +-------------- + +* [Bootstrap の .less ファイルを直接に使う](topics-less.md) diff --git a/docs/guide-ja/basic-usage.md b/docs/guide-ja/basic-usage.md new file mode 100644 index 0000000..7d183de --- /dev/null +++ b/docs/guide-ja/basic-usage.md @@ -0,0 +1,17 @@ +基本的な使用方法 +================ + +Yii は bootstrap の基礎を PHP コードでラップすることをしていません。 +なぜなら、この場合の HTML コードがそれ自体として非常にシンプルだからです。 +bootstrap の基礎を使用することに関する詳細は、[bootstrap ドキュメントウェブサイト](http://getbootstrap.com/css/) で見ることが出来ます。 +それでも、Yii はあなたのページに bootstrap のアセットをインクルードするための便利な方法を提供しています。 +`@app/assets` ディレクトリに配置されている `AppAsset.php` に一行を加えるだけで大丈夫です。 + +```php +public $depends = [ + 'yii\web\YiiAsset', + 'yii\bootstrap\BootstrapAsset', // この行です +]; +``` + +Yii のアセットマネージャによって bootstrap を使うと、必要に応じて、bootstrap のリソースを最小化したり、あなた自身のリソースと結合したりすることが出来ます。 diff --git a/docs/guide-ja/installation.md b/docs/guide-ja/installation.md new file mode 100644 index 0000000..b757da3 --- /dev/null +++ b/docs/guide-ja/installation.md @@ -0,0 +1,18 @@ +インストール +============ + +## Composer パッケージを取得する + +このエクステンションをインストールするのに推奨される方法は [composer](http://getcomposer.org/download/) によるものです。 + +下記のコマンドを実行してください。 + +``` +php composer.phar require --prefer-dist yiisoft/yii2-bootstrap +``` + +または、あなたの `composer.json` ファイルの `require` セクションに、下記を追加してください。 + +``` +"yiisoft/yii2-bootstrap": "~2.0.0" +``` diff --git a/docs/guide-ja/topics-less.md b/docs/guide-ja/topics-less.md new file mode 100644 index 0000000..2420061 --- /dev/null +++ b/docs/guide-ja/topics-less.md @@ -0,0 +1,16 @@ +Bootstrap の .less ファイルを直接に使う +======================================= + +あなたが [Bootstrap CSS をあなたの less ファイルに直接含める](http://getbootstrap.com/getting-started/#customizing) ことを望む場合は、オリジナルの CSS ファイルがロードされないように無効化する必要があります。 +[[yii\bootstrap\BootstrapAsset|BootstrapAsset]] の `css` プロパティを空に設定することによって、そうすることが出来ます。 +そのためには、`assetManager` [アプリケーションコンポーネント](https://github.com/yiisoft/yii2/blob/master/docs/guide-ja/structure-application-components.md) を以下のように構成します。 + +```php + 'assetManager' => [ + 'bundles' => [ + 'yii\bootstrap\BootstrapAsset' => [ + 'css' => [], + ] + ] + ] +``` diff --git a/docs/guide-ja/usage-widgets.md b/docs/guide-ja/usage-widgets.md new file mode 100644 index 0000000..1817349 --- /dev/null +++ b/docs/guide-ja/usage-widgets.md @@ -0,0 +1,19 @@ +Yii ウィジェット +================ + +複雑な bootstrap コンポーネントのほとんどは Yii ウィジェットでラップされて、より堅牢な構文を与えられ、フレームワークの諸機能と統合されています。 +全てのウィジェットは `\yii\bootstrap` 名前空間に属します。 + +- [[yii\bootstrap\ActiveForm|ActiveForm]] +- [[yii\bootstrap\Alert|Alert]] +- [[yii\bootstrap\Button|Button]] +- [[yii\bootstrap\ButtonDropdown|ButtonDropdown]] +- [[yii\bootstrap\ButtonGroup|ButtonGroup]] +- [[yii\bootstrap\Carousel|Carousel]] +- [[yii\bootstrap\Collapse|Collapse]] +- [[yii\bootstrap\Dropdown|Dropdown]] +- [[yii\bootstrap\Modal|Modal]] +- [[yii\bootstrap\Nav|Nav]] +- [[yii\bootstrap\NavBar|NavBar]] +- [[yii\bootstrap\Progress|Progress]] +- [[yii\bootstrap\Tabs|Tabs]] diff --git a/docs/guide/topics-less.md b/docs/guide/topics-less.md index b7522c9..173ed74 100644 --- a/docs/guide/topics-less.md +++ b/docs/guide/topics-less.md @@ -4,7 +4,7 @@ Using the .less files of Bootstrap directly If you want to include the [Bootstrap css directly in your less files](http://getbootstrap.com/getting-started/#customizing) you may need to disable the original bootstrap css files to be loaded. You can do this by setting the css property of the [[yii\bootstrap\BootstrapAsset|BootstrapAsset]] to be empty. -For this you need to configure the `assetManager` [application component](structure-application-components.md) as follows: +For this you need to configure the `assetManager` [application component](https://github.com/yiisoft/yii2/blob/master/docs/guide/structure-application-components.md) as follows: ```php 'assetManager' => [ diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..3a3db9f --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,13 @@ + + + + + ./tests + + + diff --git a/tests/ButtonDropdownTest.php b/tests/ButtonDropdownTest.php new file mode 100644 index 0000000..8b12dc0 --- /dev/null +++ b/tests/ButtonDropdownTest.php @@ -0,0 +1,31 @@ + [ + 'class' => $containerClass, + ], + 'label' => 'Action', + 'dropdown' => [ + 'items' => [ + ['label' => 'DropdownA', 'url' => '/'], + ['label' => 'DropdownB', 'url' => '#'], + ], + ], + ]); + + $this->assertContains("$containerClass btn-group", $out); + } +} diff --git a/tests/CollapseTest.php b/tests/CollapseTest.php new file mode 100644 index 0000000..30bdbec --- /dev/null +++ b/tests/CollapseTest.php @@ -0,0 +1,74 @@ + [ + [ + 'label' => 'Collapsible Group Item #1', + 'content' => 'test content1', + ], + [ + 'label' => '

Collapsible Group Item #2

', + 'content' => '

test content2

', + 'contentOptions' => [ + 'class' => 'testContentOptions2' + ], + 'options' => [ + 'class' => 'testClass2', + 'id' => 'testId2' + ], + 'encode' => true + ], + [ + 'label' => '

Collapsible Group Item #3

', + 'content' => '

test content3

', + 'contentOptions' => [ + 'class' => 'testContentOptions3' + ], + 'options' => [ + 'class' => 'testClass3', + 'id' => 'testId3' + ], + 'encode' => false + ], + [ + 'label' => '

Collapsible Group Item #4

', + 'content' => '

test content4

', + ], + ] + ]); + + $this->assertEqualsWithoutLE(<< +

Collapsible Group Item #1 +

+
test content1
+
+

<h1>Collapsible Group Item #2</h1> +

+

test content2

+
+

Collapsible Group Item #3

+

+

test content3

+
+

<h1>Collapsible Group Item #4</h1> +

+

test content4

+
+ + +HTML + , $output); + } +} diff --git a/tests/DropdownTest.php b/tests/DropdownTest.php new file mode 100644 index 0000000..ef284e6 --- /dev/null +++ b/tests/DropdownTest.php @@ -0,0 +1,50 @@ + [ + [ + 'label' => 'Page1', + 'content' => 'Page1', + ], + [ + 'label' => 'Dropdown1', + 'items' => [ + ['label' => 'Page2', 'content' => 'Page2'], + ['label' => 'Page3', 'content' => 'Page3'], + ] + ], + [ + 'label' => 'Dropdown2', + 'visible' => false, + 'items' => [ + ['label' => 'Page4', 'content' => 'Page4'], + ['label' => 'Page5', 'content' => 'Page5'], + ] + ] + ] + ] + ); + + $expected = << + +EXPECTED; + + $this->assertEqualsWithoutLE($expected, $out); + } +} diff --git a/tests/NavTest.php b/tests/NavTest.php new file mode 100644 index 0000000..3fad720 --- /dev/null +++ b/tests/NavTest.php @@ -0,0 +1,50 @@ + [ + [ + 'label' => 'Page1', + 'content' => 'Page1', + ], + [ + 'label' => 'Dropdown1', + 'items' => [ + ['label' => 'Page2', 'content' => 'Page2'], + ['label' => 'Page3', 'content' => 'Page3'], + ] + ], + [ + 'label' => 'Dropdown2', + 'visible' => false, + 'items' => [ + ['label' => 'Page4', 'content' => 'Page4'], + ['label' => 'Page5', 'content' => 'Page5'], + ] + ] + ] + ] + ); + + $expected = <<
  • Page1
  • + +EXPECTED; + + $this->assertEqualsWithoutLE($expected, $out); + } +} diff --git a/tests/TabsTest.php b/tests/TabsTest.php new file mode 100644 index 0000000..18e39c7 --- /dev/null +++ b/tests/TabsTest.php @@ -0,0 +1,74 @@ + [ + [ + 'label' => 'Page1', 'content' => 'Page1', + ], + [ + 'label' => 'Dropdown1', + 'items' => [ + ['label' => 'Page2', 'content' => 'Page2'], + ['label' => 'Page3', 'content' => 'Page3'], + ] + ], + [ + 'label' => 'Dropdown2', + 'items' => [ + ['label' => 'Page4', 'content' => 'Page4'], + ['label' => 'Page5', 'content' => 'Page5'], + ] + ] + ] + ]); + + $page1 = 'w0-tab0'; + $page2 = 'w0-dd1-tab0'; + $page3 = 'w0-dd1-tab1'; + $page4 = 'w0-dd2-tab0'; + $page5 = 'w0-dd2-tab1'; + + $shouldContain = [ + 'w0', // nav widget container + "#$page1", // Page1 + + 'w1', // Dropdown1 + "$page2", // Page2 + "$page3", // Page3 + + + 'w2', // Dropdown2 + "#$page4", // Page4 + "#$page5", // Page5 + + // containers + "id=\"$page1\"", + "id=\"$page2\"", + "id=\"$page3\"", + "id=\"$page4\"", + "id=\"$page5\"", + ]; + + foreach ($shouldContain as $string) { + $this->assertContains($string, $out); + } + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..95cf330 --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,83 @@ +mockWebApplication(); + } + + /** + * Clean up after test. + * By default the application created with [[mockApplication]] will be destroyed. + */ + protected function tearDown() + { + parent::tearDown(); + $this->destroyApplication(); + } + + /** + * Populates Yii::$app with a new application + * The application will be destroyed on tearDown() automatically. + * @param array $config The application configuration, if needed + * @param string $appClass name of the application class to create + */ + protected function mockApplication($config = [], $appClass = '\yii\console\Application') + { + new $appClass(ArrayHelper::merge([ + 'id' => 'testapp', + 'basePath' => __DIR__, + 'vendorPath' => dirname(__DIR__) . '/vendor', + ], $config)); + } + + protected function mockWebApplication($config = [], $appClass = '\yii\web\Application') + { + new $appClass(ArrayHelper::merge([ + 'id' => 'testapp', + 'basePath' => __DIR__, + 'vendorPath' => dirname(__DIR__) . '/vendor', + 'components' => [ + 'request' => [ + 'cookieValidationKey' => 'wefJDF8sfdsfSDefwqdxj9oq', + 'scriptFile' => __DIR__ .'/index.php', + 'scriptUrl' => '/index.php', + ], + ] + ], $config)); + } + + /** + * Destroys application in Yii::$app by setting it to null. + */ + protected function destroyApplication() + { + Yii::$app = null; + Yii::$container = new Container(); + } + + /** + * Asserting two strings equality ignoring line endings + * + * @param string $expected + * @param string $actual + */ + public function assertEqualsWithoutLE($expected, $actual) + { + $expected = str_replace("\r\n", "\n", $expected); + $actual = str_replace("\r\n", "\n", $actual); + + $this->assertEquals($expected, $actual); + } +} diff --git a/tests/assets/.gitignore b/tests/assets/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/tests/assets/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..0eb9a9b --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,15 @@ +