Commit 999a39d0 by Qiang Xue

Merge pull request #4855 from yiisoft/new-asset

[WIP] New asset management
parents 6526d7f9 bff8ca08
...@@ -39,6 +39,7 @@ addons: ...@@ -39,6 +39,7 @@ addons:
install: install:
- composer self-update && composer --version - composer self-update && composer --version
- composer global require "fxp/composer-asset-plugin:~1.0"
- export PATH="$HOME/.composer/vendor/bin:$PATH" - export PATH="$HOME/.composer/vendor/bin:$PATH"
# core framework: # core framework:
- composer install --prefer-dist - composer install --prefer-dist
......
{
"directory" : "vendor/bower"
}
...@@ -75,6 +75,7 @@ at [getcomposer.org](http://getcomposer.org/doc/00-intro.md#installation-nix). ...@@ -75,6 +75,7 @@ at [getcomposer.org](http://getcomposer.org/doc/00-intro.md#installation-nix).
You can then install the application using the following command: You can then install the application using the following command:
~~~ ~~~
php composer.phar global require "fxp/composer-asset-plugin:~1.0"
php composer.phar create-project --prefer-dist --stability=dev yiisoft/yii2-app-advanced advanced php composer.phar create-project --prefer-dist --stability=dev yiisoft/yii2-app-advanced advanced
~~~ ~~~
......
...@@ -17,8 +17,11 @@ class AppAsset extends AssetBundle ...@@ -17,8 +17,11 @@ class AppAsset extends AssetBundle
{ {
public $basePath = '@webroot'; public $basePath = '@webroot';
public $baseUrl = '@web'; public $baseUrl = '@web';
public $css = ['css/site.css']; public $css = [
public $js = []; 'css/site.css',
];
public $js = [
];
public $depends = [ public $depends = [
'yii\web\YiiAsset', 'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset', 'yii\bootstrap\BootstrapAsset',
......
{
"name": "yii2-advanced",
"version": "1.0.0",
"dependencies": {
},
"devDependencies": {
}
}
...@@ -27,5 +27,11 @@ ...@@ -27,5 +27,11 @@
}, },
"config": { "config": {
"process-timeout": 1800 "process-timeout": 1800
},
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
} }
} }
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
* 'setCookieValidationKey' => [ * 'setCookieValidationKey' => [
* // list of config files that need to be inserted with automatically generated cookie validation keys * // list of config files that need to be inserted with automatically generated cookie validation keys
* ], * ],
* 'createSymlink' => [
* // list of symlinks to be created. Keys are symlinks, and values are the targets.
* ],
* ], * ],
* ]; * ];
* ``` * ```
......
...@@ -193,3 +193,13 @@ function setCookieValidationKey($root, $paths) ...@@ -193,3 +193,13 @@ function setCookieValidationKey($root, $paths)
file_put_contents($file, $content); file_put_contents($file, $content);
} }
} }
function createSymlink($links)
{
foreach ($links as $link => $target) {
echo " symlink $target as $link\n";
if (!is_link($link)) {
symlink($target, $link);
}
}
}
{
"directory" : "vendor/bower"
}
...@@ -55,6 +55,7 @@ at [getcomposer.org](http://getcomposer.org/doc/00-intro.md#installation-nix). ...@@ -55,6 +55,7 @@ at [getcomposer.org](http://getcomposer.org/doc/00-intro.md#installation-nix).
You can then install this application template using the following command: You can then install this application template using the following command:
~~~ ~~~
php composer.phar global require "fxp/composer-asset-plugin:~1.0"
php composer.phar create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic basic php composer.phar create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic basic
~~~ ~~~
......
{
"name": "yii2-basic-app",
"version": "1.0.0",
"dependencies": {
},
"devDependencies": {
}
}
...@@ -45,6 +45,10 @@ ...@@ -45,6 +45,10 @@
"generateCookieValidationKey": [ "generateCookieValidationKey": [
"config/web.php" "config/web.php"
] ]
},
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
} }
} }
} }
{ {
"name": "yiisoft/yii2-dev", "name": "yiisoft/yii2-dev",
"description": "Yii PHP Framework Version 2 - Development Package", "description": "Yii PHP Framework Version 2 - Development Package",
"keywords": ["yii2", "framework"], "keywords": [
"yii2",
"framework"
],
"homepage": "http://www.yiiframework.com/", "homepage": "http://www.yiiframework.com/",
"type": "yii2-extension", "type": "yii2-extension",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
...@@ -76,7 +79,13 @@ ...@@ -76,7 +79,13 @@
"yiisoft/jquery": "~2.0 | ~1.10", "yiisoft/jquery": "~2.0 | ~1.10",
"yiisoft/jquery-pjax": "*", "yiisoft/jquery-pjax": "*",
"ezyang/htmlpurifier": "4.6.*", "ezyang/htmlpurifier": "4.6.*",
"cebe/markdown": "0.9.*" "cebe/markdown": "0.9.*",
"bower-asset/jquery": ">=1.8",
"bower-asset/jquery.inputmask": ">=3.0.0",
"bower-asset/punycode": ">=1.3.0",
"bower-asset/yii2-pjax": ">=2.0.0",
"bower-asset/bootstrap": ">=3.0.0",
"bower-asset/jquery.ui": ">=1.10.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "3.7.*", "phpunit/phpunit": "3.7.*",
...@@ -84,12 +93,10 @@ ...@@ -84,12 +93,10 @@
"smarty/smarty": "*", "smarty/smarty": "*",
"imagine/imagine": "v0.5.0", "imagine/imagine": "v0.5.0",
"swiftmailer/swiftmailer": "*", "swiftmailer/swiftmailer": "*",
"cebe/indent": "*", "cebe/indent": "*"
"fzaninotto/faker": "*"
}, },
"suggest": { "suggest": {
"phpdocumentor/reflection": "required by yii2-apidoc extension", "phpdocumentor/reflection": "required by yii2-apidoc extension",
"twbs/bootstrap": "required by yii2-bootstrap, yii2-debug, yii2-gii extension",
"ext-curl": "required by yii2-elasticsearch extension", "ext-curl": "required by yii2-elasticsearch extension",
"ext-mongo": "required by yii2-mongo extension", "ext-mongo": "required by yii2-mongo extension",
"ext-pdo": "required by yii2-sphinx extension", "ext-pdo": "required by yii2-sphinx extension",
...@@ -113,7 +120,7 @@ ...@@ -113,7 +120,7 @@
"yii\\elasticsearch\\": "extensions/elasticsearch/", "yii\\elasticsearch\\": "extensions/elasticsearch/",
"yii\\faker\\": "extensions/faker/", "yii\\faker\\": "extensions/faker/",
"yii\\gii\\": "extensions/gii/", "yii\\gii\\": "extensions/gii/",
"yii\\imagine\\" : "extensions/imagine/", "yii\\imagine\\": "extensions/imagine/",
"yii\\jui\\": "extensions/jui/", "yii\\jui\\": "extensions/jui/",
"yii\\mongodb\\": "extensions/mongodb/", "yii\\mongodb\\": "extensions/mongodb/",
"yii\\redis\\": "extensions/redis/", "yii\\redis\\": "extensions/redis/",
......
...@@ -106,10 +106,13 @@ Yii predefines a set of aliases to easily reference commonly used file paths and ...@@ -106,10 +106,13 @@ Yii predefines a set of aliases to easily reference commonly used file paths and
- `@yii`, the directory where the `BaseYii.php` file is located (also called the framework directory) - `@yii`, the directory where the `BaseYii.php` file is located (also called the framework directory)
- `@app`, the [[yii\base\Application::basePath|base path]] of the currently running application - `@app`, the [[yii\base\Application::basePath|base path]] of the currently running application
- `@runtime`, the [[yii\base\Application::runtimePath|runtime path]] of the currently running application - `@runtime`, the [[yii\base\Application::runtimePath|runtime path]] of the currently running application. Defaults to `@app/runtime`.
- `@vendor`, the [[yii\base\Application::vendorPath|Composer vendor directory]] - `@webroot`, the Web root directory of the currently running Web application. It is determined based on the directory
- `@webroot`, the Web root directory of the currently running Web application containing the entry script.
- `@web`, the base URL of the currently running Web application - `@web`, the base URL of the currently running Web application. It has the same value as [[yii\web\Request::baseUrl]].
- `@vendor`, the [[yii\base\Application::vendorPath|Composer vendor directory]]. Defaults to `@app/vendor`.
- `@bower`, the root directory that contains [bower packages](http://bower.io/). Defaults to `@vendor/bower`.
- `@npm`, the root directory that contains [npm packages](https://www.npmjs.org/). Defaults to `@vendor/npm`.
The `@yii` alias is defined when you include the `Yii.php` file in your [entry script](structure-entry-scripts.md). The rest of the aliases are defined in the application constructor when applying the application The `@yii` alias is defined when you include the `Yii.php` file in your [entry script](structure-entry-scripts.md). The rest of the aliases are defined in the application constructor when applying the application
[configuration](concept-configurations.md). [configuration](concept-configurations.md).
......
...@@ -30,7 +30,7 @@ instead of adding a new one. If you don't provide it, the JS code itself will be ...@@ -30,7 +30,7 @@ instead of adding a new one. If you don't provide it, the JS code itself will be
An external script can be added like the following: An external script can be added like the following:
```php ```php
$this->registerJsFile('http://example.com/js/main.js', [JqueryAsset::className()]); $this->registerJsFile('http://example.com/js/main.js', ['depends' => [JqueryAsset::className()]]);
``` ```
The arguments for [[yii\web\View::registerJsFile()|registerJsFile()]] are similar to those for The arguments for [[yii\web\View::registerJsFile()|registerJsFile()]] are similar to those for
...@@ -76,16 +76,19 @@ If you want to specify additional properties of the style tag, pass an array of ...@@ -76,16 +76,19 @@ If you want to specify additional properties of the style tag, pass an array of
If you need to make sure there's only a single style tag use fourth argument as was mentioned in meta tags description. If you need to make sure there's only a single style tag use fourth argument as was mentioned in meta tags description.
```php ```php
$this->registerCssFile("http://example.com/css/themes/black-and-white.css", [BootstrapAsset::className()], ['media' => 'print'], 'css-print-theme'); $this->registerCssFile("http://example.com/css/themes/black-and-white.css", [
'depends' => [BootstrapAsset::className()],
'media' => 'print',
], 'css-print-theme');
``` ```
The code above will add a link to CSS file to the head section of the page. The code above will add a link to CSS file to the head section of the page.
* The first argument specifies the CSS file to be registered. * The first argument specifies the CSS file to be registered.
* The second argument specifies that this CSS file depends on [[yii\bootstrap\BootstrapAsset|BootstrapAsset]], meaning it will be added * The second argument specifies the HTML attributes for the resulting `<link>` tag. The option `depends`
AFTER the CSS files in [[yii\bootstrap\BootstrapAsset|BootstrapAsset]]. Without this dependency specification, the relative order is specially handled. It specifies which asset bundles this CSS file depends on. In this case, the dependent
between this CSS file and the [[yii\bootstrap\BootstrapAsset|BootstrapAsset]] CSS files would be undefined. asset bundle is [[yii\bootstrap\BootstrapAsset|BootstrapAsset]]. This means the CSS file will be added
* The third argument specifies the attributes for the resulting `<link>` tag. *after* the CSS files in [[yii\bootstrap\BootstrapAsset|BootstrapAsset]].
* The last argument specifies an ID identifying this CSS file. If it is not provided, the URL of the CSS file will be * The last argument specifies an ID identifying this CSS file. If it is not provided, the URL of the CSS file will be
used instead. used instead.
......
...@@ -21,11 +21,14 @@ On Windows, you'll download and run [Composer-Setup.exe](https://getcomposer.org ...@@ -21,11 +21,14 @@ On Windows, you'll download and run [Composer-Setup.exe](https://getcomposer.org
Please refer to the [Composer Documentation](https://getcomposer.org/doc/) if you encounter any Please refer to the [Composer Documentation](https://getcomposer.org/doc/) if you encounter any
problems or want to learn more about Composer usage. problems or want to learn more about Composer usage.
With Composer installed, you can install Yii by running the following command under a Web-accessible folder: With Composer installed, you can install Yii by running the following commands under a Web-accessible folder:
composer global require "fxp/composer-asset-plugin:~1.0"
composer create-project --prefer-dist yiisoft/yii2-app-basic basic composer create-project --prefer-dist yiisoft/yii2-app-basic basic
The above command installs Yii in a directory named `basic`. The first command installs the [composer asset plugin](https://github.com/francoispluchino/composer-asset-plugin/)
which allows managing bower and npm package dependencies through composer. You only need to run this command
once for all. The second command installs Yii in a directory named `basic`.
> Tip: If you want to install the latest development version of Yii, you may use the following command, > Tip: If you want to install the latest development version of Yii, you may use the following command,
> which adds a [stability option](https://getcomposer.org/doc/04-schema.md#minimum-stability): > which adds a [stability option](https://getcomposer.org/doc/04-schema.md#minimum-stability):
......
...@@ -76,7 +76,7 @@ class can be placed anywhere but the convention for it is to be under `assets` d ...@@ -76,7 +76,7 @@ class can be placed anywhere but the convention for it is to be under `assets` d
Additionally you may specify `$jsOptions`, `$cssOptions` and `$publishOptions` that will be passed to Additionally you may specify `$jsOptions`, `$cssOptions` and `$publishOptions` that will be passed to
[[yii\web\View::registerJsFile()]], [[yii\web\View::registerCssFile()]] and [[yii\web\AssetManager::publish()]] [[yii\web\View::registerJsFile()]], [[yii\web\View::registerCssFile()]] and [[yii\web\AssetManager::publish()]]
respectively during registering and publising an asset. For more details on this see [Setting special options](#setting-special-options). respectively during registering and publishing an asset. For more details on this see [Setting special options](#setting-special-options).
[alias]: basics.md#path-aliases "Yii Path alias" [alias]: basics.md#path-aliases "Yii Path alias"
...@@ -89,16 +89,16 @@ following way: ...@@ -89,16 +89,16 @@ following way:
```php ```php
class LanguageAsset extends AssetBundle class LanguageAsset extends AssetBundle
{ {
public $language; public static $language;
public $sourcePath = '@app/assets/language'; public $sourcePath = '@app/assets/language';
public $js = [ public $js = [
]; ];
public function registerAssetFiles($view) public function init()
{ {
$language = $this->language ? $this->language : Yii::$app->language; parent::init();
$language = self::$language ? self::$language : Yii::$app->language;
$this->js[] = 'language-' . $language . '.js'; $this->js[] = 'language-' . $language . '.js';
parent::registerAssetFiles($view);
} }
} }
``` ```
...@@ -106,7 +106,8 @@ class LanguageAsset extends AssetBundle ...@@ -106,7 +106,8 @@ class LanguageAsset extends AssetBundle
In order to set language use the following code when registering an asset bundle in a view: In order to set language use the following code when registering an asset bundle in a view:
```php ```php
LanguageAsset::register($this)->language = $language; LanguageAsset::$language = $language;
LanguageAsset::register($this);
``` ```
......
...@@ -22,6 +22,7 @@ curl -sS http://getcomposer.org/installer | php ...@@ -22,6 +22,7 @@ curl -sS http://getcomposer.org/installer | php
You can then install the application using the following command: You can then install the application using the following command:
~~~ ~~~
php composer.phar global require "fxp/composer-asset-plugin:~1.0"
php composer.phar create-project --prefer-dist --stability=dev yiisoft/yii2-app-advanced /path/to/yii-application php composer.phar create-project --prefer-dist --stability=dev yiisoft/yii2-app-advanced /path/to/yii-application
~~~ ~~~
......
...@@ -48,5 +48,6 @@ Use the Template ...@@ -48,5 +48,6 @@ Use the Template
That's all that's required to create a new Yii application template. Now you can create projects using your template: That's all that's required to create a new Yii application template. Now you can create projects using your template:
``` ```
php composer.phar global require "fxp/composer-asset-plugin:~1.0"
php composer.phar create-project --prefer-dist --stability=dev mysoft/yii2-app-coolone new-project php composer.phar create-project --prefer-dist --stability=dev mysoft/yii2-app-coolone new-project
``` ```
...@@ -10,3 +10,6 @@ To add a new extension named `xyz` (must be in lower case), take the following s ...@@ -10,3 +10,6 @@ To add a new extension named `xyz` (must be in lower case), take the following s
* `LICENSE.md` * `LICENSE.md`
3. ask Qiang to create a subsplit for `xyz` and a composer package named `yii2-xyz`; 3. ask Qiang to create a subsplit for `xyz` and a composer package named `yii2-xyz`;
4. modify `/composer.json` and add `xyz` to the `replace` section; 4. modify `/composer.json` and add `xyz` to the `replace` section;
5. If an extension contains js/css files or depends on external bower packages:
* create `bower.json`
* ask Qiang to register a bower package with the name `yii2-xyz`
...@@ -17,7 +17,7 @@ use yii\web\AssetBundle; ...@@ -17,7 +17,7 @@ use yii\web\AssetBundle;
*/ */
class AuthChoiceAsset extends AssetBundle class AuthChoiceAsset extends AssetBundle
{ {
public $sourcePath = '@yii/authclient/assets'; public $sourcePath = '@vendor/yii2-authclient/assets';
public $js = [ public $js = [
'authchoice.js', 'authchoice.js',
]; ];
......
...@@ -17,8 +17,8 @@ use yii\web\AssetBundle; ...@@ -17,8 +17,8 @@ use yii\web\AssetBundle;
*/ */
class BootstrapAsset extends AssetBundle class BootstrapAsset extends AssetBundle
{ {
public $sourcePath = '@vendor/twbs/bootstrap/dist'; public $sourcePath = '@bower/bootstrap';
public $css = [ public $css = [
'css/bootstrap.css', 'dist/css/bootstrap.css',
]; ];
} }
...@@ -17,9 +17,9 @@ use yii\web\AssetBundle; ...@@ -17,9 +17,9 @@ use yii\web\AssetBundle;
*/ */
class BootstrapPluginAsset extends AssetBundle class BootstrapPluginAsset extends AssetBundle
{ {
public $sourcePath = '@vendor/twbs/bootstrap/dist'; public $sourcePath = '@bower/bootstrap';
public $js = [ public $js = [
'js/bootstrap.js', 'dist/js/bootstrap.js',
]; ];
public $depends = [ public $depends = [
'yii\web\JqueryAsset', 'yii\web\JqueryAsset',
......
...@@ -17,9 +17,9 @@ use yii\web\AssetBundle; ...@@ -17,9 +17,9 @@ use yii\web\AssetBundle;
*/ */
class BootstrapThemeAsset extends AssetBundle class BootstrapThemeAsset extends AssetBundle
{ {
public $sourcePath = '@vendor/twbs/bootstrap/dist'; public $sourcePath = '@bower/bootstrap';
public $css = [ public $css = [
'css/bootstrap-theme.css', 'dist/css/bootstrap-theme.css',
]; ];
public $depends = [ public $depends = [
'yii\bootstrap\BootstrapAsset', 'yii\bootstrap\BootstrapAsset',
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
], ],
"require": { "require": {
"yiisoft/yii2": "*", "yiisoft/yii2": "*",
"twbs/bootstrap": "3.2.* | 3.1.* | 3.0.*" "bower-asset/bootstrap": ">=3.0.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
......
...@@ -17,30 +17,17 @@ use yii\web\AssetBundle; ...@@ -17,30 +17,17 @@ use yii\web\AssetBundle;
*/ */
class GiiAsset extends AssetBundle class GiiAsset extends AssetBundle
{ {
/**
* @inheritdoc
*/
public $sourcePath = '@yii/gii/assets'; public $sourcePath = '@yii/gii/assets';
/**
* @inheritdoc
*/
public $css = [ public $css = [
'main.css', 'main.css',
'typeahead.js-bootstrap.css',
]; ];
/**
* @inheritdoc
*/
public $js = [ public $js = [
'gii.js', 'gii.js',
'typeahead.js',
]; ];
/**
* @inheritdoc
*/
public $depends = [ public $depends = [
'yii\web\YiiAsset', 'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset', 'yii\bootstrap\BootstrapAsset',
'yii\bootstrap\BootstrapPluginAsset', 'yii\bootstrap\BootstrapPluginAsset',
'yii\gii\TypeAheadAsset',
]; ];
} }
...@@ -5,21 +5,23 @@ ...@@ -5,21 +5,23 @@
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
namespace yii\jui; namespace yii\gii;
use yii\web\AssetBundle; use yii\web\AssetBundle;
/** /**
*
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
class ButtonAsset extends AssetBundle class TypeAheadAsset extends AssetBundle
{ {
public $sourcePath = '@yii/jui/assets'; public $sourcePath = '@bower/typeahead.js';
public $js = [ public $js = [
'jquery.ui.button.js', 'dist/typeahead.bundle.js',
]; ];
public $depends = [ public $depends = [
'yii\jui\CoreAsset', 'yii\bootstrap\BootstrapAsset',
'yii\bootstrap\BootstrapPluginAsset',
]; ];
} }
...@@ -125,7 +125,6 @@ body { ...@@ -125,7 +125,6 @@ body {
text-decoration: none; text-decoration: none;
} }
.Differences { .Differences {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
...@@ -214,10 +213,47 @@ body { ...@@ -214,10 +213,47 @@ body {
content: attr(data-line-number); content: attr(data-line-number);
} }
/* additional styles for typeahead.js-bootstrap.css */ /* additional styles for typeahead.js, adapted from http://twitter.github.io/typeahead.js/examples/ */
.twitter-typeahead { .twitter-typeahead {
display: block !important; display: block !important;
} }
.twitter-typeahead .tt-hint {
padding: 6px 12px !important; .tt-query {
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}
.tt-hint {
color: #999
}
.tt-dropdown-menu {
width: 422px;
margin-top: 2px;
padding: 8px 0;
background-color: #fff;
border: 1px solid #ccc;
border: 1px solid rgba(0, 0, 0, 0.2);
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
}
.tt-suggestion {
padding: 3px 20px;
font-size: 18px;
line-height: 24px;
}
.tt-suggestion.tt-cursor {
color: #fff;
background-color: #0097cf;
} }
.tt-suggestion p {
margin: 0;
}
/* always keep this link here when updating this file: https://github.com/jharding/typeahead.js-bootstrap.css */
.twitter-typeahead .tt-query,
.twitter-typeahead .tt-hint {
margin-bottom: 0;
}
.tt-dropdown-menu {
min-width: 160px;
margin-top: 2px;
padding: 5px 0;
background-color: #fff;
border: 1px solid #ccc;
border: 1px solid rgba(0,0,0,.2);
*border-right-width: 2px;
*border-bottom-width: 2px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
-webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
-moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
box-shadow: 0 5px 10px rgba(0,0,0,.2);
-webkit-background-clip: padding-box;
-moz-background-clip: padding;
background-clip: padding-box;
}
.tt-suggestion {
display: block;
padding: 3px 20px;
}
.tt-suggestion.tt-is-under-cursor {
color: #fff;
background-color: #0081c2;
background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
background-image: -o-linear-gradient(top, #0088cc, #0077b3);
background-image: linear-gradient(to bottom, #0088cc, #0077b3);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0)
}
.tt-suggestion.tt-is-under-cursor a {
color: #fff;
}
.tt-suggestion p {
margin: 0;
}
...@@ -64,7 +64,7 @@ class ActiveField extends \yii\widgets\ActiveField ...@@ -64,7 +64,7 @@ class ActiveField extends \yii\widgets\ActiveField
public function autoComplete($data) public function autoComplete($data)
{ {
static $counter = 0; static $counter = 0;
$this->inputOptions['class'] .= ' typeahead-' . (++$counter); $this->inputOptions['class'] .= ' typeahead typeahead-' . (++$counter);
foreach ($data as &$item) { foreach ($data as &$item) {
$item = ['word' => $item]; $item = ['word' => $item];
} }
......
...@@ -20,7 +20,8 @@ ...@@ -20,7 +20,8 @@
"require": { "require": {
"yiisoft/yii2": "*", "yiisoft/yii2": "*",
"yiisoft/yii2-bootstrap": "*", "yiisoft/yii2-bootstrap": "*",
"phpspec/php-diff": ">=1.0.2" "phpspec/php-diff": ">=1.0.2",
"bower-asset/typeahead.js": ">=0.10.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
......
...@@ -96,7 +96,7 @@ class Accordion extends Widget ...@@ -96,7 +96,7 @@ class Accordion extends Widget
echo Html::beginTag($tag, $options) . "\n"; echo Html::beginTag($tag, $options) . "\n";
echo $this->renderItems() . "\n"; echo $this->renderItems() . "\n";
echo Html::endTag($tag) . "\n"; echo Html::endTag($tag) . "\n";
$this->registerWidget('accordion', AccordionAsset::className()); $this->registerWidget('accordion');
} }
/** /**
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class AccordionAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.accordion.js',
];
public $depends = [
'yii\jui\CoreAsset',
'yii\jui\EffectAsset',
];
}
...@@ -47,7 +47,7 @@ class AutoComplete extends InputWidget ...@@ -47,7 +47,7 @@ class AutoComplete extends InputWidget
public function run() public function run()
{ {
echo $this->renderWidget(); echo $this->renderWidget();
$this->registerWidget('autocomplete', AutoCompleteAsset::className()); $this->registerWidget('autocomplete');
} }
/** /**
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class AutoCompleteAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.autocomplete.js',
];
public $depends = [
'yii\jui\CoreAsset',
'yii\jui\MenuAsset',
];
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class CoreAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.core.js',
'jquery.ui.widget.js',
'jquery.ui.position.js',
'jquery.ui.mouse.js',
];
public $depends = [
'yii\web\JqueryAsset',
];
}
...@@ -78,22 +78,26 @@ class DatePicker extends InputWidget ...@@ -78,22 +78,26 @@ class DatePicker extends InputWidget
public function run() public function run()
{ {
echo $this->renderWidget() . "\n"; echo $this->renderWidget() . "\n";
$containerID = $this->inline ? $this->containerOptions['id'] : $this->options['id']; $containerID = $this->inline ? $this->containerOptions['id'] : $this->options['id'];
$language = $this->language ? $this->language : Yii::$app->language; $language = $this->language ? $this->language : Yii::$app->language;
if ($language != 'en-US') { if ($language != 'en-US') {
$view = $this->getView(); $view = $this->getView();
DatePickerRegionalAsset::register($view); $bundle = DatePickerLanguageAsset::register($view);
if ($bundle->autoGenerate) {
$view->registerJsFile($bundle->baseUrl . "/ui/i18n/datepicker-$language.js", [
'depends' => [JuiAsset::className()],
]);
}
$options = Json::encode($this->clientOptions); $options = Json::encode($this->clientOptions);
$view->registerJs("$('#{$containerID}').datepicker($.extend({}, $.datepicker.regional['{$language}'], $options));"); $view->registerJs("$('#{$containerID}').datepicker($.extend({}, $.datepicker.regional['{$language}'], $options));");
$options = $this->clientOptions;
$this->clientOptions = false; // the datepicker js widget is already registered
$this->registerWidget('datepicker', DatePickerAsset::className(), $containerID);
$this->clientOptions = $options;
} else { } else {
$this->registerWidget('datepicker', DatePickerAsset::className(), $containerID); $this->registerClientOptions('datepicker', $containerID);
} }
$this->registerClientEvents('datepicker', $containerID);
JuiAsset::register($this->getView());
} }
/** /**
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class DatePickerAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.datepicker.js',
];
public $depends = [
'yii\jui\CoreAsset',
'yii\jui\EffectAsset',
];
}
...@@ -13,13 +13,19 @@ use yii\web\AssetBundle; ...@@ -13,13 +13,19 @@ use yii\web\AssetBundle;
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
class DatePickerRegionalAsset extends AssetBundle class DatePickerLanguageAsset extends AssetBundle
{ {
public $sourcePath = '@yii/jui/assets'; public $sourcePath = '@bower/jquery-ui';
public $js = [ /**
'jquery.ui.datepicker-i18n.js', * @var boolean whether to automatically generate the needed language js files.
]; * If this is true, the language js files will be determined based on the actual usage of [[DatePicker]]
* and its language settings. If this is false, you should explicitly specify the language js files via [[js]].
*/
public $autoGenerate = true;
/**
* @inheritdoc
*/
public $depends = [ public $depends = [
'yii\jui\DatePickerAsset', 'yii\jui\JuiAsset',
]; ];
} }
...@@ -47,6 +47,6 @@ class Dialog extends Widget ...@@ -47,6 +47,6 @@ class Dialog extends Widget
public function run() public function run()
{ {
echo Html::endTag('div') . "\n"; echo Html::endTag('div') . "\n";
$this->registerWidget('dialog', DialogAsset::className()); $this->registerWidget('dialog');
} }
} }
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class DialogAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.dialog.js',
];
public $depends = [
'yii\jui\CoreAsset',
'yii\jui\ButtonAsset',
'yii\jui\DraggableAsset',
'yii\jui\ResizableAsset',
];
}
...@@ -45,6 +45,6 @@ class Draggable extends Widget ...@@ -45,6 +45,6 @@ class Draggable extends Widget
public function run() public function run()
{ {
echo Html::endTag('div') . "\n"; echo Html::endTag('div') . "\n";
$this->registerWidget('draggable', DraggableAsset::className()); $this->registerWidget('draggable');
} }
} }
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class DraggableAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.draggable.js',
];
public $depends = [
'yii\jui\CoreAsset',
];
}
...@@ -45,6 +45,6 @@ class Droppable extends Widget ...@@ -45,6 +45,6 @@ class Droppable extends Widget
public function run() public function run()
{ {
echo Html::endTag('div') . "\n"; echo Html::endTag('div') . "\n";
$this->registerWidget('droppable', DroppableAsset::className()); $this->registerWidget('droppable');
} }
} }
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class DroppableAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.droppable.js',
];
public $depends = [
'yii\jui\DraggableAsset',
];
}
...@@ -13,11 +13,14 @@ use yii\web\AssetBundle; ...@@ -13,11 +13,14 @@ use yii\web\AssetBundle;
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
class EffectAsset extends AssetBundle class JuiAsset extends AssetBundle
{ {
public $sourcePath = '@yii/jui/assets'; public $sourcePath = '@bower/jquery-ui';
public $js = [ public $js = [
'jquery.ui.effect-all.js', 'jquery-ui.js',
];
public $css = [
'themes/smoothness/jquery-ui.css',
]; ];
public $depends = [ public $depends = [
'yii\web\JqueryAsset', 'yii\web\JqueryAsset',
......
...@@ -54,10 +54,7 @@ class Menu extends \yii\widgets\Menu ...@@ -54,10 +54,7 @@ class Menu extends \yii\widgets\Menu
parent::run(); parent::run();
$view = $this->getView(); $view = $this->getView();
MenuAsset::register($view); JuiAsset::register($view);
/* @var $themeAsset \yii\web\AssetBundle */
$themeAsset = Widget::$theme;
$themeAsset::register($view);
$id = $this->options['id']; $id = $this->options['id'];
if ($this->clientOptions !== false) { if ($this->clientOptions !== false) {
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class MenuAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.menu.js',
];
public $depends = [
'yii\jui\CoreAsset',
];
}
...@@ -55,6 +55,6 @@ class ProgressBar extends Widget ...@@ -55,6 +55,6 @@ class ProgressBar extends Widget
public function run() public function run()
{ {
echo Html::endTag('div') . "\n"; echo Html::endTag('div') . "\n";
$this->registerWidget('progressbar', ProgressBarAsset::className()); $this->registerWidget('progressbar');
} }
} }
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class ProgressBarAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.progressbar.js',
];
public $depends = [
'yii\jui\CoreAsset',
];
}
...@@ -47,6 +47,6 @@ class Resizable extends Widget ...@@ -47,6 +47,6 @@ class Resizable extends Widget
public function run() public function run()
{ {
echo Html::endTag('div') . "\n"; echo Html::endTag('div') . "\n";
$this->registerWidget('resizable', ResizableAsset::className()); $this->registerWidget('resizable');
} }
} }
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class ResizableAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.resizable.js',
];
public $depends = [
'yii\jui\CoreAsset',
];
}
...@@ -90,7 +90,7 @@ class Selectable extends Widget ...@@ -90,7 +90,7 @@ class Selectable extends Widget
echo Html::beginTag($tag, $options) . "\n"; echo Html::beginTag($tag, $options) . "\n";
echo $this->renderItems() . "\n"; echo $this->renderItems() . "\n";
echo Html::endTag($tag) . "\n"; echo Html::endTag($tag) . "\n";
$this->registerWidget('selectable', SelectableAsset::className()); $this->registerWidget('selectable');
} }
/** /**
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class SelectableAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.selectable.js',
];
public $depends = [
'yii\jui\CoreAsset',
];
}
...@@ -44,6 +44,6 @@ class Slider extends Widget ...@@ -44,6 +44,6 @@ class Slider extends Widget
public function run() public function run()
{ {
echo Html::tag('div', '', $this->options); echo Html::tag('div', '', $this->options);
$this->registerWidget('slider', SliderAsset::className()); $this->registerWidget('slider');
} }
} }
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class SliderAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.slider.js',
];
public $depends = [
'yii\jui\CoreAsset',
];
}
...@@ -93,6 +93,6 @@ class SliderInput extends InputWidget ...@@ -93,6 +93,6 @@ class SliderInput extends InputWidget
}'; }';
} }
$this->registerWidget('slider', SliderAsset::className(), $this->containerOptions['id']); $this->registerWidget('slider', $this->containerOptions['id']);
} }
} }
...@@ -99,7 +99,7 @@ class Sortable extends Widget ...@@ -99,7 +99,7 @@ class Sortable extends Widget
echo Html::beginTag($tag, $options) . "\n"; echo Html::beginTag($tag, $options) . "\n";
echo $this->renderItems() . "\n"; echo $this->renderItems() . "\n";
echo Html::endTag($tag) . "\n"; echo Html::endTag($tag) . "\n";
$this->registerWidget('sortable', SortableAsset::className()); $this->registerWidget('sortable');
} }
/** /**
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class SortableAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.sortable.js',
];
public $depends = [
'yii\jui\CoreAsset',
];
}
...@@ -51,7 +51,7 @@ class Spinner extends InputWidget ...@@ -51,7 +51,7 @@ class Spinner extends InputWidget
public function run() public function run()
{ {
echo $this->renderWidget(); echo $this->renderWidget();
$this->registerWidget('spinner', SpinnerAsset::className()); $this->registerWidget('spinner');
} }
/** /**
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class SpinnerAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.spinner.js',
];
public $depends = [
'yii\jui\CoreAsset',
'yii\jui\ButtonAsset',
];
}
...@@ -109,7 +109,7 @@ class Tabs extends Widget ...@@ -109,7 +109,7 @@ class Tabs extends Widget
echo Html::beginTag($tag, $options) . "\n"; echo Html::beginTag($tag, $options) . "\n";
echo $this->renderItems() . "\n"; echo $this->renderItems() . "\n";
echo Html::endTag($tag) . "\n"; echo Html::endTag($tag) . "\n";
$this->registerWidget('tabs', TabsAsset::className()); $this->registerWidget('tabs');
} }
/** /**
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class TabsAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.tabs.js',
];
public $depends = [
'yii\jui\CoreAsset',
'yii\jui\EffectAsset',
];
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class ThemeAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $css = [
'theme/jquery.ui.css',
];
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\jui;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class TooltipAsset extends AssetBundle
{
public $sourcePath = '@yii/jui/assets';
public $js = [
'jquery.ui.tooltip.js',
];
public $depends = [
'yii\jui\CoreAsset',
'yii\jui\EffectAsset',
];
}
...@@ -18,11 +18,6 @@ use yii\helpers\Json; ...@@ -18,11 +18,6 @@ use yii\helpers\Json;
class Widget extends \yii\base\Widget class Widget extends \yii\base\Widget
{ {
/** /**
* @var string the jQuery UI theme. This refers to an asset bundle class
* representing the JUI theme. The default theme is the official "Smoothness" theme.
*/
public static $theme = 'yii\jui\ThemeAsset';
/**
* @var array the HTML attributes for the widget container tag. * @var array the HTML attributes for the widget container tag.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered. * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/ */
...@@ -72,19 +67,6 @@ class Widget extends \yii\base\Widget ...@@ -72,19 +67,6 @@ class Widget extends \yii\base\Widget
} }
/** /**
* Registers a specific jQuery UI widget assets
* @param string $assetBundle the asset bundle for the widget
*/
protected function registerAssets($assetBundle)
{
/* @var $assetBundle \yii\web\AssetBundle */
$assetBundle::register($this->getView());
/* @var $themeAsset \yii\web\AssetBundle */
$themeAsset = static::$theme;
$themeAsset::register($this->getView());
}
/**
* Registers a specific jQuery UI widget options * Registers a specific jQuery UI widget options
* @param string $name the name of the jQuery UI widget * @param string $name the name of the jQuery UI widget
* @param string $id the ID of the widget * @param string $id the ID of the widget
...@@ -122,15 +104,14 @@ class Widget extends \yii\base\Widget ...@@ -122,15 +104,14 @@ class Widget extends \yii\base\Widget
/** /**
* Registers a specific jQuery UI widget asset bundle, initializes it with client options and registers related events * Registers a specific jQuery UI widget asset bundle, initializes it with client options and registers related events
* @param string $name the name of the jQuery UI widget * @param string $name the name of the jQuery UI widget
* @param string $assetBundle the asset bundle for the widget
* @param string $id the ID of the widget. If null, it will use the `id` value of [[options]]. * @param string $id the ID of the widget. If null, it will use the `id` value of [[options]].
*/ */
protected function registerWidget($name, $assetBundle, $id = null) protected function registerWidget($name, $id = null)
{ {
if ($id === null) { if ($id === null) {
$id = $this->options['id']; $id = $this->options['id'];
} }
$this->registerAssets($assetBundle); JuiAsset::register($this->getView());
$this->registerClientOptions($name, $id); $this->registerClientOptions($name, $id);
$this->registerClientEvents($name, $id); $this->registerClientEvents($name, $id);
} }
......
How to Upgrade JQuery UI
========================
To upgrade JQuery UI, use [JUI Download Builder](http://jqueryui.com/download/) and toggle all options.
Choose the `Smoothness` theme, download and unpack.
The following files are needed:
* UI Core: all JS files
* Interactions: all JS files
* Widgets: all JS files
* DatePicker I18N: only the combined file is needed, and it should be renamed as `jquery.ui.datepicker-i18n.js`
* Effects: only the combined file is needed, and it should be renamed as `jquery.ui.effect-all.js`
* Theme: Only the combined CSS file and the image files are needed. Rename the CSS file as `jquery.ui.css`.
/*!
* jQuery UI Core 1.10.3
* http://jqueryui.com
*
* Copyright 2013 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
* http://api.jqueryui.com/category/ui-core/
*/
(function( $, undefined ) {
var uuid = 0,
runiqueId = /^ui-id-\d+$/;
// $.ui might exist from components with no dependencies, e.g., $.ui.position
$.ui = $.ui || {};
$.extend( $.ui, {
version: "1.10.3",
keyCode: {
BACKSPACE: 8,
COMMA: 188,
DELETE: 46,
DOWN: 40,
END: 35,
ENTER: 13,
ESCAPE: 27,
HOME: 36,
LEFT: 37,
NUMPAD_ADD: 107,
NUMPAD_DECIMAL: 110,
NUMPAD_DIVIDE: 111,
NUMPAD_ENTER: 108,
NUMPAD_MULTIPLY: 106,
NUMPAD_SUBTRACT: 109,
PAGE_DOWN: 34,
PAGE_UP: 33,
PERIOD: 190,
RIGHT: 39,
SPACE: 32,
TAB: 9,
UP: 38
}
});
// plugins
$.fn.extend({
focus: (function( orig ) {
return function( delay, fn ) {
return typeof delay === "number" ?
this.each(function() {
var elem = this;
setTimeout(function() {
$( elem ).focus();
if ( fn ) {
fn.call( elem );
}
}, delay );
}) :
orig.apply( this, arguments );
};
})( $.fn.focus ),
scrollParent: function() {
var scrollParent;
if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
scrollParent = this.parents().filter(function() {
return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
}).eq(0);
} else {
scrollParent = this.parents().filter(function() {
return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
}).eq(0);
}
return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
},
zIndex: function( zIndex ) {
if ( zIndex !== undefined ) {
return this.css( "zIndex", zIndex );
}
if ( this.length ) {
var elem = $( this[ 0 ] ), position, value;
while ( elem.length && elem[ 0 ] !== document ) {
// Ignore z-index if position is set to a value where z-index is ignored by the browser
// This makes behavior of this function consistent across browsers
// WebKit always returns auto if the element is positioned
position = elem.css( "position" );
if ( position === "absolute" || position === "relative" || position === "fixed" ) {
// IE returns 0 when zIndex is not specified
// other browsers return a string
// we ignore the case of nested elements with an explicit value of 0
// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
value = parseInt( elem.css( "zIndex" ), 10 );
if ( !isNaN( value ) && value !== 0 ) {
return value;
}
}
elem = elem.parent();
}
}
return 0;
},
uniqueId: function() {
return this.each(function() {
if ( !this.id ) {
this.id = "ui-id-" + (++uuid);
}
});
},
removeUniqueId: function() {
return this.each(function() {
if ( runiqueId.test( this.id ) ) {
$( this ).removeAttr( "id" );
}
});
}
});
// selectors
function focusable( element, isTabIndexNotNaN ) {
var map, mapName, img,
nodeName = element.nodeName.toLowerCase();
if ( "area" === nodeName ) {
map = element.parentNode;
mapName = map.name;
if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
return false;
}
img = $( "img[usemap=#" + mapName + "]" )[0];
return !!img && visible( img );
}
return ( /input|select|textarea|button|object/.test( nodeName ) ?
!element.disabled :
"a" === nodeName ?
element.href || isTabIndexNotNaN :
isTabIndexNotNaN) &&
// the element and all of its ancestors must be visible
visible( element );
}
function visible( element ) {
return $.expr.filters.visible( element ) &&
!$( element ).parents().addBack().filter(function() {
return $.css( this, "visibility" ) === "hidden";
}).length;
}
$.extend( $.expr[ ":" ], {
data: $.expr.createPseudo ?
$.expr.createPseudo(function( dataName ) {
return function( elem ) {
return !!$.data( elem, dataName );
};
}) :
// support: jQuery <1.8
function( elem, i, match ) {
return !!$.data( elem, match[ 3 ] );
},
focusable: function( element ) {
return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
},
tabbable: function( element ) {
var tabIndex = $.attr( element, "tabindex" ),
isTabIndexNaN = isNaN( tabIndex );
return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
}
});
// support: jQuery <1.8
if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
$.each( [ "Width", "Height" ], function( i, name ) {
var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
type = name.toLowerCase(),
orig = {
innerWidth: $.fn.innerWidth,
innerHeight: $.fn.innerHeight,
outerWidth: $.fn.outerWidth,
outerHeight: $.fn.outerHeight
};
function reduce( elem, size, border, margin ) {
$.each( side, function() {
size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
if ( border ) {
size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
}
if ( margin ) {
size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
}
});
return size;
}
$.fn[ "inner" + name ] = function( size ) {
if ( size === undefined ) {
return orig[ "inner" + name ].call( this );
}
return this.each(function() {
$( this ).css( type, reduce( this, size ) + "px" );
});
};
$.fn[ "outer" + name] = function( size, margin ) {
if ( typeof size !== "number" ) {
return orig[ "outer" + name ].call( this, size );
}
return this.each(function() {
$( this).css( type, reduce( this, size, true, margin ) + "px" );
});
};
});
}
// support: jQuery <1.8
if ( !$.fn.addBack ) {
$.fn.addBack = function( selector ) {
return this.add( selector == null ?
this.prevObject : this.prevObject.filter( selector )
);
};
}
// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
$.fn.removeData = (function( removeData ) {
return function( key ) {
if ( arguments.length ) {
return removeData.call( this, $.camelCase( key ) );
} else {
return removeData.call( this );
}
};
})( $.fn.removeData );
}
// deprecated
$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
$.support.selectstart = "onselectstart" in document.createElement( "div" );
$.fn.extend({
disableSelection: function() {
return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
".ui-disableSelection", function( event ) {
event.preventDefault();
});
},
enableSelection: function() {
return this.unbind( ".ui-disableSelection" );
}
});
$.extend( $.ui, {
// $.ui.plugin is deprecated. Use $.widget() extensions instead.
plugin: {
add: function( module, option, set ) {
var i,
proto = $.ui[ module ].prototype;
for ( i in set ) {
proto.plugins[ i ] = proto.plugins[ i ] || [];
proto.plugins[ i ].push( [ option, set[ i ] ] );
}
},
call: function( instance, name, args ) {
var i,
set = instance.plugins[ name ];
if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
return;
}
for ( i = 0; i < set.length; i++ ) {
if ( instance.options[ set[ i ][ 0 ] ] ) {
set[ i ][ 1 ].apply( instance.element, args );
}
}
}
},
// only used by resizable
hasScroll: function( el, a ) {
//If overflow is hidden, the element might have extra content, but the user wants to hide it
if ( $( el ).css( "overflow" ) === "hidden") {
return false;
}
var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
has = false;
if ( el[ scroll ] > 0 ) {
return true;
}
// TODO: determine which cases actually cause this to happen
// if the element doesn't have the scroll set, see if it's possible to
// set the scroll
el[ scroll ] = 1;
has = ( el[ scroll ] > 0 );
el[ scroll ] = 0;
return has;
}
});
})( jQuery );
/*!
* jQuery UI Mouse 1.10.3
* http://jqueryui.com
*
* Copyright 2013 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
* http://api.jqueryui.com/mouse/
*
* Depends:
* jquery.ui.widget.js
*/
(function( $, undefined ) {
var mouseHandled = false;
$( document ).mouseup( function() {
mouseHandled = false;
});
$.widget("ui.mouse", {
version: "1.10.3",
options: {
cancel: "input,textarea,button,select,option",
distance: 1,
delay: 0
},
_mouseInit: function() {
var that = this;
this.element
.bind("mousedown."+this.widgetName, function(event) {
return that._mouseDown(event);
})
.bind("click."+this.widgetName, function(event) {
if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
$.removeData(event.target, that.widgetName + ".preventClickEvent");
event.stopImmediatePropagation();
return false;
}
});
this.started = false;
},
// TODO: make sure destroying one instance of mouse doesn't mess with
// other instances of mouse
_mouseDestroy: function() {
this.element.unbind("."+this.widgetName);
if ( this._mouseMoveDelegate ) {
$(document)
.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
}
},
_mouseDown: function(event) {
// don't let more than one widget handle mouseStart
if( mouseHandled ) { return; }
// we may have missed mouseup (out of window)
(this._mouseStarted && this._mouseUp(event));
this._mouseDownEvent = event;
var that = this,
btnIsLeft = (event.which === 1),
// event.target.nodeName works around a bug in IE 8 with
// disabled inputs (#7620)
elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
return true;
}
this.mouseDelayMet = !this.options.delay;
if (!this.mouseDelayMet) {
this._mouseDelayTimer = setTimeout(function() {
that.mouseDelayMet = true;
}, this.options.delay);
}
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
this._mouseStarted = (this._mouseStart(event) !== false);
if (!this._mouseStarted) {
event.preventDefault();
return true;
}
}
// Click event may never have fired (Gecko & Opera)
if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
$.removeData(event.target, this.widgetName + ".preventClickEvent");
}
// these delegates are required to keep context
this._mouseMoveDelegate = function(event) {
return that._mouseMove(event);
};
this._mouseUpDelegate = function(event) {
return that._mouseUp(event);
};
$(document)
.bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
.bind("mouseup."+this.widgetName, this._mouseUpDelegate);
event.preventDefault();
mouseHandled = true;
return true;
},
_mouseMove: function(event) {
// IE mouseup check - mouseup happened when mouse was out of window
if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
return this._mouseUp(event);
}
if (this._mouseStarted) {
this._mouseDrag(event);
return event.preventDefault();
}
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
this._mouseStarted =
(this._mouseStart(this._mouseDownEvent, event) !== false);
(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
}
return !this._mouseStarted;
},
_mouseUp: function(event) {
$(document)
.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
if (this._mouseStarted) {
this._mouseStarted = false;
if (event.target === this._mouseDownEvent.target) {
$.data(event.target, this.widgetName + ".preventClickEvent", true);
}
this._mouseStop(event);
}
return false;
},
_mouseDistanceMet: function(event) {
return (Math.max(
Math.abs(this._mouseDownEvent.pageX - event.pageX),
Math.abs(this._mouseDownEvent.pageY - event.pageY)
) >= this.options.distance
);
},
_mouseDelayMet: function(/* event */) {
return this.mouseDelayMet;
},
// These are placeholder methods, to be overriden by extending plugin
_mouseStart: function(/* event */) {},
_mouseDrag: function(/* event */) {},
_mouseStop: function(/* event */) {},
_mouseCapture: function(/* event */) { return true; }
});
})(jQuery);
/*!
* jQuery UI Progressbar 1.10.3
* http://jqueryui.com
*
* Copyright 2013 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
* http://api.jqueryui.com/progressbar/
*
* Depends:
* jquery.ui.core.js
* jquery.ui.widget.js
*/
(function( $, undefined ) {
$.widget( "ui.progressbar", {
version: "1.10.3",
options: {
max: 100,
value: 0,
change: null,
complete: null
},
min: 0,
_create: function() {
// Constrain initial value
this.oldValue = this.options.value = this._constrainedValue();
this.element
.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
.attr({
// Only set static values, aria-valuenow and aria-valuemax are
// set inside _refreshValue()
role: "progressbar",
"aria-valuemin": this.min
});
this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
.appendTo( this.element );
this._refreshValue();
},
_destroy: function() {
this.element
.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
.removeAttr( "role" )
.removeAttr( "aria-valuemin" )
.removeAttr( "aria-valuemax" )
.removeAttr( "aria-valuenow" );
this.valueDiv.remove();
},
value: function( newValue ) {
if ( newValue === undefined ) {
return this.options.value;
}
this.options.value = this._constrainedValue( newValue );
this._refreshValue();
},
_constrainedValue: function( newValue ) {
if ( newValue === undefined ) {
newValue = this.options.value;
}
this.indeterminate = newValue === false;
// sanitize value
if ( typeof newValue !== "number" ) {
newValue = 0;
}
return this.indeterminate ? false :
Math.min( this.options.max, Math.max( this.min, newValue ) );
},
_setOptions: function( options ) {
// Ensure "value" option is set after other values (like max)
var value = options.value;
delete options.value;
this._super( options );
this.options.value = this._constrainedValue( value );
this._refreshValue();
},
_setOption: function( key, value ) {
if ( key === "max" ) {
// Don't allow a max less than min
value = Math.max( this.min, value );
}
this._super( key, value );
},
_percentage: function() {
return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
},
_refreshValue: function() {
var value = this.options.value,
percentage = this._percentage();
this.valueDiv
.toggle( this.indeterminate || value > this.min )
.toggleClass( "ui-corner-right", value === this.options.max )
.width( percentage.toFixed(0) + "%" );
this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
if ( this.indeterminate ) {
this.element.removeAttr( "aria-valuenow" );
if ( !this.overlayDiv ) {
this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
}
} else {
this.element.attr({
"aria-valuemax": this.options.max,
"aria-valuenow": value
});
if ( this.overlayDiv ) {
this.overlayDiv.remove();
this.overlayDiv = null;
}
}
if ( this.oldValue !== value ) {
this.oldValue = value;
this._trigger( "change" );
}
if ( value === this.options.max ) {
this._trigger( "complete" );
}
}
});
})( jQuery );
/*!
* jQuery UI Selectable 1.10.3
* http://jqueryui.com
*
* Copyright 2013 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
* http://api.jqueryui.com/selectable/
*
* Depends:
* jquery.ui.core.js
* jquery.ui.mouse.js
* jquery.ui.widget.js
*/
(function( $, undefined ) {
$.widget("ui.selectable", $.ui.mouse, {
version: "1.10.3",
options: {
appendTo: "body",
autoRefresh: true,
distance: 0,
filter: "*",
tolerance: "touch",
// callbacks
selected: null,
selecting: null,
start: null,
stop: null,
unselected: null,
unselecting: null
},
_create: function() {
var selectees,
that = this;
this.element.addClass("ui-selectable");
this.dragged = false;
// cache selectee children based on filter
this.refresh = function() {
selectees = $(that.options.filter, that.element[0]);
selectees.addClass("ui-selectee");
selectees.each(function() {
var $this = $(this),
pos = $this.offset();
$.data(this, "selectable-item", {
element: this,
$element: $this,
left: pos.left,
top: pos.top,
right: pos.left + $this.outerWidth(),
bottom: pos.top + $this.outerHeight(),
startselected: false,
selected: $this.hasClass("ui-selected"),
selecting: $this.hasClass("ui-selecting"),
unselecting: $this.hasClass("ui-unselecting")
});
});
};
this.refresh();
this.selectees = selectees.addClass("ui-selectee");
this._mouseInit();
this.helper = $("<div class='ui-selectable-helper'></div>");
},
_destroy: function() {
this.selectees
.removeClass("ui-selectee")
.removeData("selectable-item");
this.element
.removeClass("ui-selectable ui-selectable-disabled");
this._mouseDestroy();
},
_mouseStart: function(event) {
var that = this,
options = this.options;
this.opos = [event.pageX, event.pageY];
if (this.options.disabled) {
return;
}
this.selectees = $(options.filter, this.element[0]);
this._trigger("start", event);
$(options.appendTo).append(this.helper);
// position helper (lasso)
this.helper.css({
"left": event.pageX,
"top": event.pageY,
"width": 0,
"height": 0
});
if (options.autoRefresh) {
this.refresh();
}
this.selectees.filter(".ui-selected").each(function() {
var selectee = $.data(this, "selectable-item");
selectee.startselected = true;
if (!event.metaKey && !event.ctrlKey) {
selectee.$element.removeClass("ui-selected");
selectee.selected = false;
selectee.$element.addClass("ui-unselecting");
selectee.unselecting = true;
// selectable UNSELECTING callback
that._trigger("unselecting", event, {
unselecting: selectee.element
});
}
});
$(event.target).parents().addBack().each(function() {
var doSelect,
selectee = $.data(this, "selectable-item");
if (selectee) {
doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
selectee.$element
.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
selectee.unselecting = !doSelect;
selectee.selecting = doSelect;
selectee.selected = doSelect;
// selectable (UN)SELECTING callback
if (doSelect) {
that._trigger("selecting", event, {
selecting: selectee.element
});
} else {
that._trigger("unselecting", event, {
unselecting: selectee.element
});
}
return false;
}
});
},
_mouseDrag: function(event) {
this.dragged = true;
if (this.options.disabled) {
return;
}
var tmp,
that = this,
options = this.options,
x1 = this.opos[0],
y1 = this.opos[1],
x2 = event.pageX,
y2 = event.pageY;
if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
this.selectees.each(function() {
var selectee = $.data(this, "selectable-item"),
hit = false;
//prevent helper from being selected if appendTo: selectable
if (!selectee || selectee.element === that.element[0]) {
return;
}
if (options.tolerance === "touch") {
hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
} else if (options.tolerance === "fit") {
hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
}
if (hit) {
// SELECT
if (selectee.selected) {
selectee.$element.removeClass("ui-selected");
selectee.selected = false;
}
if (selectee.unselecting) {
selectee.$element.removeClass("ui-unselecting");
selectee.unselecting = false;
}
if (!selectee.selecting) {
selectee.$element.addClass("ui-selecting");
selectee.selecting = true;
// selectable SELECTING callback
that._trigger("selecting", event, {
selecting: selectee.element
});
}
} else {
// UNSELECT
if (selectee.selecting) {
if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
selectee.$element.removeClass("ui-selecting");
selectee.selecting = false;
selectee.$element.addClass("ui-selected");
selectee.selected = true;
} else {
selectee.$element.removeClass("ui-selecting");
selectee.selecting = false;
if (selectee.startselected) {
selectee.$element.addClass("ui-unselecting");
selectee.unselecting = true;
}
// selectable UNSELECTING callback
that._trigger("unselecting", event, {
unselecting: selectee.element
});
}
}
if (selectee.selected) {
if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
selectee.$element.removeClass("ui-selected");
selectee.selected = false;
selectee.$element.addClass("ui-unselecting");
selectee.unselecting = true;
// selectable UNSELECTING callback
that._trigger("unselecting", event, {
unselecting: selectee.element
});
}
}
}
});
return false;
},
_mouseStop: function(event) {
var that = this;
this.dragged = false;
$(".ui-unselecting", this.element[0]).each(function() {
var selectee = $.data(this, "selectable-item");
selectee.$element.removeClass("ui-unselecting");
selectee.unselecting = false;
selectee.startselected = false;
that._trigger("unselected", event, {
unselected: selectee.element
});
});
$(".ui-selecting", this.element[0]).each(function() {
var selectee = $.data(this, "selectable-item");
selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
selectee.selecting = false;
selectee.selected = true;
selectee.startselected = true;
that._trigger("selected", event, {
selected: selectee.element
});
});
this._trigger("stop", event);
this.helper.remove();
return false;
}
});
})(jQuery);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment