├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── composer.json ├── phpunit.xml ├── spec ├── Codesleeve │ └── AssetPipeline │ │ ├── AssetPipelineServiceProviderSpec.php │ │ ├── AssetPipelineSpec.php │ │ ├── AssetSpec.php │ │ └── Filters │ │ ├── SassFilterSpec.php │ │ └── URLRewriteSpec.php └── fixtures │ ├── App.php │ ├── app │ └── assets │ │ ├── javascripts │ │ ├── application.js │ │ └── some.swf │ │ └── stylesheets │ │ └── application.css │ └── storage │ └── cache │ └── asset-pipeline │ ├── 33b3a8791be8f3493115c2394c4c16de │ └── 87691cbb3f442c28fbdeb2cebdc517c2 ├── src ├── Codesleeve │ └── AssetPipeline │ │ ├── Asset.php │ │ ├── AssetPipeline.php │ │ ├── AssetPipelineGlobalHelpers.php │ │ ├── AssetPipelineServiceProvider.php │ │ ├── Commands │ │ ├── AssetsCleanCommand.php │ │ ├── AssetsGenerateCommand.php │ │ └── AssetsSetupCommand.php │ │ ├── Composers │ │ ├── BaseComposer.php │ │ ├── ComposerInterface.php │ │ ├── ImageComposer.php │ │ ├── JavascriptComposer.php │ │ └── StylesheetComposer.php │ │ └── Filters │ │ ├── ClientCacheFilter.php │ │ ├── CoffeeScript.php │ │ ├── CssMinFilter.php │ │ ├── EnvironmentFilter.php │ │ ├── FilesNotCached.php │ │ ├── FilterHelper.php │ │ ├── JSMinPlusFilter.php │ │ ├── JST.php │ │ ├── LessphpFilter.php │ │ ├── MinifyCSS.php │ │ ├── MinifyHtml.php │ │ ├── MinifyJS.php │ │ ├── SassFilter.php │ │ └── URLRewrite.php ├── config │ └── config.php ├── controllers │ └── AssetPipelineController.php └── routes.php ├── structure ├── app │ └── assets │ │ ├── images │ │ └── readme.txt │ │ ├── javascripts │ │ └── application.js │ │ └── stylesheets │ │ └── application.css └── provider │ └── assets │ ├── javascripts │ └── jquery.min.js │ └── stylesheets │ └── readme.txt └── tests ├── .gitkeep ├── AssetPipelineTest.php └── fixtures ├── App.php └── app └── assets ├── javascripts ├── application.js └── some.swf └── stylesheets └── application.css /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /tests/fixtures/storage 3 | composer.phar 4 | composer.lock 5 | .DS_Store -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | 8 | before_script: 9 | - curl -s http://getcomposer.org/installer | php 10 | - php composer.phar install --dev 11 | 12 | script: vendor/bin/phpspec run -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 team@codesleeve.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Asset Pipeline (depreciated) 3 | 4 | The new Laravel 5 feature called [Elixir](http://laravel.com/docs/5.0/elixir) which runs on gulp should help you manage your assets. There are no plans (from us at Codesleeve) to continue development on this project to include L5 support. Asset pipeline will continue to accept community pull requests. Please feel free to contribute if you'd like. 5 | 6 | ## What is Asset Pipeline? 7 | 8 | For those of you familiar with Rails asset pipeline and sprockets, you will hopefully feel right at home using this package. 9 | 10 | For those of you unfamiliar with Rails asset pipeline and sprockets, I suggest reading [introduction to directives](#introduction-to-directives). 11 | 12 | ## Installation 13 | 14 | Begin by installing this package through Composer. Edit your project's `composer.json` file to require `codesleeve/asset-pipeline`. 15 | 16 | It might look something like: 17 | 18 | ```php 19 | "require": { 20 | "laravel/framework": "4.1.*", 21 | "codesleeve/asset-pipeline": "dev-master" 22 | } 23 | ``` 24 | 25 | Next, update Composer from the Terminal: 26 | 27 | ```php 28 | composer update 29 | ``` 30 | 31 | Once this operation completes, add the service provider. Open `app/config/app.php`, add the following items to the providers array. 32 | 33 | ```php 34 | 'Codesleeve\AssetPipeline\AssetPipelineServiceProvider', 35 | ``` 36 | 37 | Next optionally, ensure your environment is setup correctly because by default the asset pipeline will cache and and minify assets on a production environment. 38 | 39 | Inside `bootstrap/start.php` 40 | 41 | ```php 42 | $env = $app->detectEnvironment(array( 43 | 'local' => array('your-machine-name'), 44 | )); 45 | ``` 46 | 47 | Run the `artisan` command from the Terminal for the `assets:setup` command. This will create the default folder structure for you. 48 | 49 | ```php 50 | php artisan assets:setup 51 | ``` 52 | 53 | ## Usage 54 | 55 | Place these lines into your Laravel view/layout 56 | 57 | ```php 58 | 59 | 60 | ``` 61 | 62 | This will generate a listing of script and link tags for all the dependencies listed in `app/assets/application.js` and `app/assets/application.css`. 63 | 64 | #### Parameters 65 | 66 | If you'd like to control which manifest file you'd like to use and even put attributes on the tags. This follows the same pattern rails uses, so for example, if we have this: 67 | 68 | ```php 69 | 'bar']) ?> 70 | ``` 71 | 72 | and assuming `concat => array('production')` and we are on a production environment then this generates 73 | 74 | ```php 75 | 76 | ``` 77 | 78 | ## Introduction to Directives 79 | 80 | Let's open up the default javascript manifest file `app/assets/javascripts/application.js`. You should see something like 81 | 82 | ```javascript 83 | 84 | // 85 | //= require jquery 86 | //= require_tree . 87 | 88 | ``` 89 | 90 | This will bring in the file `/provider/assets/javascripts/jquery.min.js` and also all files and sub directories within in `/app/assets/javascripts` folder. 91 | 92 | This is how you control your dependencies. Simple right? 93 | 94 | #### Here is a list of directives you can use 95 | 96 | - **require** filename 97 | 98 | This brings in a specific asset file found within your `paths`. 99 | 100 | - **require_directory** some/directory 101 | 102 | This brings in assets only within some/directory (non-recursive). You can also use '.' and '..' to resolve paths relative to the manifest file itself. 103 | 104 | - **require_tree** some/directory 105 | 106 | Just like require_directory except it recursively brings in all sub directories and files. 107 | 108 | - **require_tree_df** some/directory 109 | 110 | This works just like require_tree but it includes directories first and files last where as 111 | require_tree brings in files first then directories. You might use this if you have dependencies 112 | inside of sub-directories that you want to include first before a file in that same directory. 113 | 114 | - **require_self** 115 | 116 | This brings in the manifest file itself as an asset. This is already done on `require_tree .` if the manifest file is within that directory. Where you might want to use this is when you have a manifest file that does like `require_tree subdir/` 117 | 118 | - **include** filename 119 | 120 | This brings in a specific asset file found within your `paths`. It differs from **require** though 121 | because if the file is not found then it does not throw an exception. 122 | 123 | - **stub** path 124 | 125 | Blacklists the given path. This can be a file or an entire directory. Note that once a path is blacklisted it will be ignored no matter how many times you try to included it. 126 | 127 | - **depend_on** filename 128 | 129 | Let asset pipeline know about a dependency not required through the manifest file. If file1 **depend_on** file2 then the local cache for file1 will be busted when file2 changes. This is very useful for when you are using `@import` in less. 130 | 131 | ## Configuration 132 | 133 | To create a custom package config for [configuration of the asset pipeline.](#configuration) run 134 | 135 | ```php 136 | php artisan config:publish codesleeve/asset-pipeline 137 | ``` 138 | 139 | ### routing array 140 | 141 | ```php 142 | 'routing' => array( 143 | 'prefix' => '/assets' 144 | ), 145 | ``` 146 | 147 | Sprockets parser also uses this to help generate the correct web path for our assets. It is also used by the asset pipeline for routing. 148 | 149 | 150 | ### paths 151 | 152 | ```php 153 | 'paths' => array( 154 | 'app/assets/javascripts', 155 | 'app/assets/stylesheets', 156 | 'app/assets/images', 157 | 'lib/assets/javascripts', 158 | 'lib/assets/stylesheets', 159 | 'lib/assets/images', 160 | 'provider/assets/javascripts', 161 | 'provider/assets/stylesheets', 162 | 'provider/assets/images' 163 | ), 164 | ``` 165 | 166 | These are the directories we search for files in. You can think of this like PATH environment variable on your OS. We search for files in the path order listed below. 167 | 168 | ### mimes 169 | 170 | ```php 171 | 'mimes' => array( 172 | 'javascripts' => array('.js', '.js.coffee', '.coffee', '.html', '.min.js'), 173 | 'stylesheets' => array('.css', '.css.less', '.css.scss', '.less', '.scss', '.min.css'), 174 | ), 175 | ``` 176 | 177 | In order to know which mime type to send back to the server we need to know if it is a javascript or stylesheet type. If the extension is not found below then we just return a regular download. You should include all extensions in your `filters` here or you will likely experience unexpected behavior. This should allow developers to mix javascript and css files in the same directory. 178 | 179 | ### filters 180 | 181 | ```php 182 | 'filters' => array( 183 | '.min.js' => array( 184 | 185 | ), 186 | '.min.css' => array( 187 | new Codesleeve\AssetPipeline\Filters\URLRewrite, 188 | ), 189 | '.js' => array( 190 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\JSMinPlusFilter, App::environment()), 191 | ), 192 | '.js.coffee' => array( 193 | new Codesleeve\AssetPipeline\Filters\CoffeeScript, 194 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\JSMinPlusFilter, App::environment()), 195 | ), 196 | '.coffee' => array( 197 | new Codesleeve\AssetPipeline\Filters\CoffeeScript, 198 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\JSMinPlusFilter, App::environment()), 199 | ), 200 | '.css' => array( 201 | new Codesleeve\AssetPipeline\Filters\URLRewrite, 202 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\CssMinFilter, App::environment()), 203 | ), 204 | '.css.less' => array( 205 | new Assetic\Filter\LessphpFilter, 206 | new Codesleeve\AssetPipeline\Filters\URLRewrite, 207 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\CssMinFilter, App::environment()), 208 | ), 209 | '.css.scss' => array( 210 | new Assetic\Filter\ScssphpFilter, 211 | new Codesleeve\AssetPipeline\Filters\URLRewrite, 212 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\CssMinFilter, App::environment()), 213 | ), 214 | '.less' => array( 215 | new Assetic\Filter\LessphpFilter, 216 | new Codesleeve\AssetPipeline\Filters\URLRewrite, 217 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\CssMinFilter, App::environment()), 218 | ), 219 | '.scss' => array( 220 | new Assetic\Filter\ScssphpFilter, 221 | new Codesleeve\AssetPipeline\Filters\URLRewrite, 222 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\CssMinFilter, App::environment()), 223 | ), 224 | '.html' => array( 225 | new Codesleeve\AssetPipeline\Filters\JST, 226 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\JSMinPlusFilter, App::environment()), 227 | ) 228 | ), 229 | ``` 230 | 231 | In order for a file to be included with sprockets, the extension needs to be listed here. We can also preprocess those extension types with Assetic Filters. 232 | 233 | ### cache 234 | 235 | ```php 236 | 'cache' => array(), // add 'production' here if you want to cache permanently 237 | ``` 238 | 239 | **By default we cache all files regardless of the environment.** 240 | 241 | However, we only cache manifest files when in production mode or whatever environments are supplied to `cache`. 242 | 243 | 244 | ### cache_server 245 | 246 | ```php 247 | 'cache_server' => new Assetic\Cache\FilesystemCache(App::make('path.storage') . '/cache/asset-pipeline'), 248 | ``` 249 | 250 | By default we use Assetic's FilesystemCache to handle caching but you can create your own [CacheInterface](https://github.com/kriswallsmith/assetic/blob/master/src/Assetic/Cache) if you want to handle caching differently. 251 | 252 | Caching is used here to speed up when developing locally and production as well. To get an idea of how this works, let's say you are dealing with 80 coffeescript files. You wouldn't want to run pre-compilation on all 80 files each time you load a page. Pipeline will cache all 80 coffeescript files so we only run pre-compilation if one of those files is changed. This makes your pages load faster in when developing. 253 | 254 | The only downside to this is if you change your Laravel environment or config for asset pipeline then you will need to clear your cache to see the changes reflected. 255 | 256 | If you want to clear your cache then run 257 | 258 | ```php 259 | php artisan assets:clean 260 | ``` 261 | 262 | This will clear the cached files `application.js` and `application.css` and all required files from within the manifest files. If you have other files you want cleaned then you can pass them as parameters via `-f` or `--file` 263 | 264 | ```php 265 | php artisan assets:clean -f interior/application.js -f exterior/application.js -f interior/application.css -f exterior/application.css 266 | ``` 267 | 268 | If you don't want to recursively remove cache files for a manifest file then you can pass the `--recursive=false` flag. 269 | 270 | **NOTE** If you are using the default configuration for pipeline you can remove your cached files in this directory 271 | 272 | ``` 273 | $ rm -f app/storage/cache/asset-pipeline/* 274 | ``` 275 | 276 | ### cache_client 277 | 278 | ```php 279 | 'cache_client' => new Codesleeve\AssetPipeline\Filters\ClientCacheFilter, 280 | ``` 281 | 282 | If you want to handle 304's and what not, to keep users from refetching your assets and saving your bandwidth you can use a cache_client driver that handles this. This doesn't handle assets on the server-side, use cache_server for that. 283 | 284 | Note that this needs to implement the interface 285 | 286 | Codesleeve\Sprockets\Interfaces\ClientCacheInterface 287 | 288 | or this won't work correctly. It is a wrapper class around your cache_server driver and also uses the AssetCache class to help access files `lastModifiedTime` because `Assetic\Cache\CacheInterface` doesn't give us this ability. 289 | 290 | ### concat 291 | 292 | ```php 293 | 'concat' => array('production', 'local') 294 | ``` 295 | 296 | This allows us to turn on the asset concatenation for the specific environments listed. For performance reasons, we recommend keeping this turned on except if you are trying to troubleshoot an javascript issue. 297 | 298 | 299 | ### directives 300 | 301 | ```php 302 | 'directives' => array( 303 | 'require ' => new Codesleeve\Sprockets\Directives\RequireFile, 304 | 'require_directory ' => new Codesleeve\Sprockets\Directives\RequireDirectory, 305 | 'require_tree ' => new Codesleeve\Sprockets\Directives\RequireTree, 306 | 'require_tree_df ' => new Codesleeve\Sprockets\Directives\RequireTreeDf, 307 | 'require_self' => new Codesleeve\Sprockets\Directives\RequireSelf, 308 | 'include ' => new Codesleeve\Sprockets\Directives\IncludeFile, 309 | 'stub ' => new Codesleeve\Sprockets\Directives\Stub, 310 | 'depend_on ' => new Codesleeve\Sprockets\Directives\DependOn, 311 | ), 312 | ``` 313 | 314 | These are the directives we try to process inside of manifest files. This allows you to swap out, add new, modify existing directives for your pipeline setup. 315 | 316 | 317 | ### javascript_include_tag 318 | 319 | ```php 320 | 'javascript_include_tag' => new Codesleeve\AssetPipeline\Composers\JavascriptComposer, 321 | ``` 322 | 323 | When you do `` this composer class will be invoked. This allows you to compose your own javascript tags if you want to modify how javascript tags are printed. 324 | 325 | 326 | ### stylesheet_link_tag 327 | 328 | ```php 329 | 'stylesheet_link_tag' => new Codesleeve\AssetPipeline\Composers\StylesheetComposer, 330 | ``` 331 | 332 | When you do `` this composer class will be invoked. This allows you to compose your own stylesheet tags if you want to modify how stylesheet tags are printed. 333 | 334 | 335 | ### controller_action 336 | 337 | ```php 338 | 'controller_action' => '\Codesleeve\AssetPipeline\AssetPipelineController@file', 339 | ``` 340 | 341 | This is the controller action the pipeline routes all incoming requests to. If you ever want to swap this out for your own implementation you can edit this. This allows you to completely control how assets are being served to the browser. 342 | 343 | 344 | ### sprockets_filter 345 | 346 | ```php 347 | 'sprockets_filter' => '\Codesleeve\Sprockets\SprocketsFilter', 348 | ``` 349 | 350 | When concatenation is turned on, all assets fetched from the sprockets generator are filtered through this filter class. This allows us to modify the sprockets filter if we need to behave differently. 351 | 352 | 353 | ## FAQ 354 | 355 | ### Can I modify the asset pipeline config at runtime? 356 | 357 | You can listen to `asset.pipeline.boot` event and this will pass the pipeline object to you for any changes you might want to make. 358 | 359 | ```php 360 | Event::listen('asset.pipeline.boot', function($pipeline) { 361 | $config = $pipeline->getConfig(); 362 | 363 | $config['paths'][] = 'some/special/javascripts'; 364 | $config['paths'][] = 'some/special/stylesheets'; 365 | 366 | $config['mimes']['javascripts'][] = '.foo.bar'; 367 | 368 | $config['filters']['.foo.bar'] = array( 369 | new My\Special\Filter 370 | ); 371 | 372 | $pipeline->setConfig($config); 373 | }); 374 | ``` 375 | 376 | This code registers two new paths and creates a new extension called .foo.bar that is filtered with `My\Special\Filter`. Using the event listener allows us to extend the functionality of the asset pipeline in separate packages. 377 | 378 | ### Can I do Javascript Templates (JST) 379 | 380 | Yes. Out of the box you can use .html files somewhere within your `app/assets/javascripts` folder and you will be given a JST array on your front end javascript that contains the html page. If you want a different extension (i.e. jst.hbs) you will need to bring that in. 381 | 382 | ### Can I do images, fonts, and other files? 383 | 384 | Files that are not in the `mime` and `filters` array of our configuration will be treated as regular files. You can still access them via web urls, but they will trigger a `Response::download` instead of being served as javascript or stylesheet files. 385 | 386 | ### Can I do conditional includes? 387 | 388 | There is no built-in mechanism to conditionally include assets via the asset pipeline. One technique I use is to namespace my html page in my layout view. I create a View::share that always contains the current route for me. 389 | 390 | ```html 391 | 392 | ``` 393 | 394 | This allows me to prefix my css with the route. So if I only wanted a blue background on the home page I could do something like this. 395 | 396 | ```css 397 | html.home.index body { 398 | background-color: blue; 399 | } 400 | ``` 401 | 402 | If you are trying to conditionally include javascript on a page, I recommend the use of bindings. Create specific scripts that will only be run when certain data attributes or class names are found. 403 | 404 | ```js 405 | $('[data-foo]').each(function() 406 | { 407 | console.log('only run when we find data-foo="" attribute'); 408 | }); 409 | ``` 410 | 411 | And so if we have an element like this it will run 412 | 413 | ```html 414 | Hey there 415 | ``` 416 | 417 | If you find yourself having issues with conditionally including assets your best bet may be to break apart your manifest files into sections that make sense for your application. For example, if your application is silo'ed into admin section and user section then it probably makes sense to have a separate manifest file for each section. 418 | 419 | ### Can I hook in my own packages for asset pipeline? 420 | 421 | Yes. By using the event listener `asset.pipeline.boot` you can intercept the pipeline object and modify the configuration array to your own will. But remember with great power comes great responsibility. Here is an example, 422 | 423 | ```php 424 | 425 | Event::listen('asset.pipeline.boot', function($pipeline) 426 | { 427 | $config = $pipeline->getConfig(); 428 | $config['directives']['awesome_directive'] = new MyAwesomeDirective; 429 | $pipeline->setConfig($config); 430 | }); 431 | 432 | ``` 433 | So what does MyAwesomeDirective look like? That is entirely up to you. 434 | 435 | ```php 436 | class MyAwesomeDirective extends Codesleeve\Sprockets\Directives\RequireFile 437 | { 438 | public function process($param) 439 | { 440 | $files = array(); 441 | 442 | if (App::environment() === 'local' && $param == 'foobar') 443 | { 444 | // do chicken dance and add some files to array 445 | // also, this needs to be an absolute path to file 446 | $files[] = __DIR__ . '/chicken/dance.js'; 447 | } 448 | 449 | return $files; 450 | } 451 | } 452 | ``` 453 | 454 | ### Can I use nginx 455 | 456 | You may have to configure nginx. The files are not in `/assets/` so you will likely get a 404. Thus you need to tell nginx to route the request through `index.php` if the file is not found. This can be accomplished with something like this: 457 | 458 | ```js 459 | location ~ ^/(assets)/{ 460 | try_files $uri $uri/ /index.php?$args; 461 | expires max; 462 | add_header Cache-Control public; 463 | } 464 | ``` 465 | 466 | ### Can I use an older version of asset pipeline 467 | 468 | The asset pipeline has been re-factored to be smarter, cleaner, better. However, with that brought along breaking changes because things work differently. So if you have older existing projects that were pointing to `dev-master`, you should probably find a tag version that works for you. If it just recently broke, try the latest tag minus 1. Also, I typically push out my changes to `dev-testing`. 469 | 470 | 471 | ### Can I do image optimization? 472 | 473 | The asset pipeline doesn't do this for you. However, there is nothing stopping you from handling image optimization via a separate script and then including those optimized images through asset pipeline. 474 | 475 | For more information [check out this issue](https://github.com/CodeSleeve/asset-pipeline/issues/128). 476 | 477 | 478 | ### How does caching work? 479 | 480 | For performance reasons, all files are cached using the `cache_server` driver in asset pipeline's configuration file. This is done so you don't have to pre-compile 100's of coffeescript and less/sass files each time you reload the page and fetch assets. However, this can cause confusion sometimes, for example, if you update a [filter](#filters) in the asset pipeline config and then refresh the page and things are still be cached. In this case you should [manually clear the cache](#cache_server). 481 | 482 | When your environment matches an environment found in the configured [cache](#cache) array then assets will be permanently cached until manually cleared using `assets:clean`. By default this used to be `production`, however due to the frustration and confusion many developers were having this was removed. So if you want to use caching on your server you need to opt-in and edit your configuration file. 483 | 484 | ## License 485 | 486 | The codesleeve asset pipeline is open-source software licensed under the [MIT license](http://opensource.org/licenses/MIT) 487 | 488 | ## Support 489 | 490 | Before you do a pull request for a new feature please place in a proposal request. For bug fixes, please place in issues to track those, even if you fix the bug yourself and submit a pull request. All pull requests go to `dev-testing` before `dev-master`. 491 | 492 | We use Travis CI for testing which you can see at: https://travis-ci.org/CodeSleeve/asset-pipeline 493 | 494 | *Enjoy!* And have a nice day! 495 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "codesleeve/asset-pipeline", 3 | "description": "A very simple and easy to use asset pipeline for laravel 4.", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Kelt Dockins", 8 | "email": "kelt@dockins.org" 9 | } 10 | ], 11 | "require": { 12 | "php": ">=5.3.0", 13 | "illuminate/support": "~4.0|~5.0", 14 | "codesleeve/sprockets": "v2.1.0", 15 | "leafo/lessphp": "v0.4.0", 16 | "coffeescript/coffeescript": "1.3.1", 17 | "nitra/php-min": "@dev", 18 | "leafo/scssphp": "0.0.9", 19 | "richthegeek/phpsass": "2014-03-20", 20 | "ext-fileinfo": "*" 21 | }, 22 | "require-dev": { 23 | "laravel/framework": "4.*", 24 | "phpspec/phpspec": "2.0.*@dev" 25 | }, 26 | "autoload": { 27 | "classmap": [ 28 | "src/controllers" 29 | ], 30 | "psr-0": { 31 | "Codesleeve\\AssetPipeline": "src/" 32 | } 33 | }, 34 | "minimum-stability": "dev" 35 | } 36 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests/ 16 | 17 | 18 | -------------------------------------------------------------------------------- /spec/Codesleeve/AssetPipeline/AssetPipelineServiceProviderSpec.php: -------------------------------------------------------------------------------- 1 | beConstructedWith($app); 13 | $this->shouldHaveType('Codesleeve\AssetPipeline\AssetPipelineServiceProvider'); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /spec/Codesleeve/AssetPipeline/AssetPipelineSpec.php: -------------------------------------------------------------------------------- 1 | beADoubleOf('Codesleeve\AssetPipeline\Composers\JavascriptComposer'); 16 | $cssComposer->beADoubleOf('Codesleeve\AssetPipeline\Composers\StylesheetComposer'); 17 | 18 | $parser->beADoubleOf('Codesleeve\Sprockets\SprocketsParser'); 19 | $generator->beADoubleOf('Codesleeve\Sprockets\SprocketsGenerator'); 20 | 21 | $this->beConstructedWith($parser, $generator); 22 | $this->shouldHaveType('Codesleeve\AssetPipeline\AssetPipeline'); 23 | } 24 | } 25 | /* 26 | 27 | function it_can_run_javascript_include_tag($parser, $jsComposer) 28 | { 29 | $absolutePaths = array('/absolute/file1'); 30 | $webPaths = array('/assets/file1'); 31 | $attributes = array('attribute'); 32 | 33 | $parser->javascriptFiles('application')->willReturn($absolutePaths); 34 | $parser->absolutePathToWebPath($absolutePaths[0])->willReturn($webPaths[0]); 35 | 36 | $parser->get('config')->willReturn(array('javascript_include_tag' => $jsComposer)); 37 | 38 | $jsComposer->process($webPaths, $absolutePaths, $attributes)->willReturn('good'); 39 | 40 | $this->javascriptIncludeTag('application', $attributes)->shouldBeEqualTo('good'); 41 | } 42 | 43 | function it_can_run_stylesheet_include_tag($parser, $cssComposer) 44 | { 45 | $absolutePaths = array('/absolute/file1'); 46 | $webPaths = array('/assets/file1'); 47 | $attributes = array('attribute'); 48 | 49 | $parser->stylesheetFiles('application')->willReturn($absolutePaths); 50 | $parser->absolutePathToWebPath($absolutePaths[0])->willReturn($webPaths[0]); 51 | 52 | $parser->get('config')->willReturn(array('stylesheet_link_tag' => $cssComposer)); 53 | 54 | $cssComposer->process($webPaths, $absolutePaths, $attributes)->willReturn('good'); 55 | 56 | $this->stylesheetLinkTag('application', $attributes)->shouldBeEqualTo('good'); 57 | } 58 | 59 | function it_can_tell_me_if_a_file_is_javascript_mime_type($parser) 60 | { 61 | $parser->stylesheetFiles('application')->willReturn($absolutePaths); 62 | 63 | $this->isJavascript('application.js')->shouldBeTrue(); 64 | } 65 | } 66 | 67 | 68 | public function testIsJavascript() 69 | { 70 | $this->assertNotNull($this->pipeline->isJavascript('application.js')); 71 | $this->assertNull($this->pipeline->isJavascript('some.swf')); 72 | $this->assertNull($this->pipeline->isJavascript('application.css')); 73 | } 74 | 75 | public function testIsStylesheet() 76 | { 77 | $this->assertNull($this->pipeline->isStylesheet('application.js')); 78 | $this->assertNull($this->pipeline->isStylesheet('some.swf')); 79 | $this->assertNotNull($this->pipeline->isStylesheet('application.css')); 80 | } 81 | 82 | public function testIsFile() 83 | { 84 | $this->assertNotNull($this->pipeline->isFile('application.js')); 85 | $this->assertNotNull($this->pipeline->isFile('some.swf')); 86 | $this->assertNotNull($this->pipeline->isFile('application.css')); 87 | } 88 | 89 | public function testJavascript() 90 | { 91 | $output = $this->pipeline->javascript("{$this->base}/app/assets/javascripts/application.js"); 92 | $this->assertNotEmpty($output); 93 | } 94 | 95 | public function testStylesheet() 96 | { 97 | $output = $this->pipeline->stylesheet("{$this->base}/app/assets/stylesheets/application.css"); 98 | $this->assertNotEmpty($output); 99 | } 100 | 101 | public function testFile() 102 | { 103 | $output = $this->pipeline->file('some.swf'); 104 | $this->assertEquals($output, "{$this->base}/app/assets/javascripts/some.swf"); 105 | } 106 | 107 | public function testRegisterAssetPipelineFilters() 108 | { 109 | $output = $this->pipeline->registerAssetPipelineFilters(); 110 | $this->assertEquals($output, $this->pipeline); 111 | } 112 | } 113 | 114 | 115 | /** 116 | * I could just mock Parser and Generator, but I am doing acceptance 117 | * testing here, and I want to also check our *REAL* config.php file 118 | * for errors. 119 | function it_can_use_the_real_world_config() 120 | { 121 | $jsComposer->beADoubleOf('Codesleeve\AssetPipeline\Composers\JavascriptComposer'); 122 | $cssComposer->beADoubleOf('Codesleeve\AssetPipeline\Composers\StylesheetComposer'); 123 | 124 | $base = __DIR__ . '/../../..'; 125 | require $base . '/spec/fixtures/App.php'; 126 | 127 | $config = include $base . '/src/config/config.php'; 128 | $config['base_path'] = $base; 129 | $config['environment'] = "local"; 130 | $config['javascript_include_tag'] = $jsComposer; 131 | $config['stylesheet_link_tag'] = $cssComposer; 132 | 133 | $parser = new SprocketsParser($config); 134 | $generator = new SprocketsGenerator($config); 135 | 136 | $this->beConstructedWith($parser, $generator); 137 | $this->shouldHaveType('Codesleeve\AssetPipeline\AssetPipeline'); 138 | } 139 | 140 | 141 | 142 | */ -------------------------------------------------------------------------------- /spec/Codesleeve/AssetPipeline/AssetSpec.php: -------------------------------------------------------------------------------- 1 | shouldHaveType('Codesleeve\AssetPipeline\Asset'); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /spec/Codesleeve/AssetPipeline/Filters/SassFilterSpec.php: -------------------------------------------------------------------------------- 1 | shouldHaveType('Codesleeve\AssetPipeline\Filters\SassFilter'); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /spec/Codesleeve/AssetPipeline/Filters/URLRewriteSpec.php: -------------------------------------------------------------------------------- 1 | shouldHaveType('Codesleeve\AssetPipeline\Filters\URLRewrite'); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /spec/fixtures/App.php: -------------------------------------------------------------------------------- 1 | parser = $parser; 26 | $this->generator = $generator; 27 | } 28 | 29 | /** 30 | * Create javascript include tag(s) 31 | * 32 | * @param string $filename 33 | * @param array $attributes 34 | * @return string 35 | */ 36 | public function javascriptIncludeTag($filename, $attributes) 37 | { 38 | $webPaths = array(); 39 | $absolutePaths = $this->parser->javascriptFiles($filename); 40 | 41 | foreach ($absolutePaths as $absolutePath) 42 | { 43 | $webPaths[] = $this->parser->absolutePathToWebPath($absolutePath); 44 | } 45 | 46 | $config = $this->getConfig(); 47 | $composer = $config['javascript_include_tag']; 48 | 49 | return $composer->process($webPaths, $absolutePaths, $attributes); 50 | } 51 | 52 | /** 53 | * Create stylesheet link tag(s) 54 | * 55 | * @param string $filename 56 | * @param array $attributes 57 | * @return string 58 | */ 59 | public function stylesheetLinkTag($filename, $attributes) 60 | { 61 | $webPaths = array(); 62 | $absolutePaths = $this->parser->stylesheetFiles($filename); 63 | 64 | foreach ($absolutePaths as $absolutePath) 65 | { 66 | $webPaths[] = $this->parser->absolutePathToWebPath($absolutePath); 67 | } 68 | 69 | $config = $this->getConfig(); 70 | $composer = $config['stylesheet_link_tag']; 71 | 72 | return $composer->process($webPaths, $absolutePaths, $attributes); 73 | } 74 | 75 | /** 76 | * Create image tag 77 | * 78 | * @param string $filename 79 | * @param array $attributes 80 | * @return string 81 | */ 82 | public function imageTag($filename, $attributes) 83 | { 84 | $absolutePath = $this->file($filename); 85 | $webPath = $this->parser->absolutePathToWebPath($absolutePath); 86 | 87 | $config = $this->getConfig(); 88 | $composer = $config['image_tag']; 89 | 90 | return $composer->process(array($webPath), array($absolutePath), $attributes); 91 | } 92 | 93 | /** 94 | * Is this asset a javascript type? 95 | * 96 | * @param string $filename 97 | * @return boolean 98 | */ 99 | public function isJavascript($filename) 100 | { 101 | return $this->parser->absoluteJavascriptPath($filename); 102 | } 103 | 104 | /** 105 | * Is this filename a stylesheet type? 106 | * 107 | * @param string $filename 108 | * @return boolean 109 | */ 110 | public function isStylesheet($filename) 111 | { 112 | return $this->parser->absoluteStylesheetPath($filename); 113 | } 114 | 115 | /** 116 | * Is this filename any type of file? 117 | * 118 | * @param string $filename 119 | * @return boolean 120 | */ 121 | public function isFile($filename) 122 | { 123 | $absolutePath = $this->parser->absoluteFilePath($filename); 124 | 125 | return file_exists($absolutePath) && is_file($absolutePath) ? $absolutePath : null; 126 | } 127 | 128 | /** 129 | * Return the javascript associated with this path 130 | * 131 | * @param string $path 132 | * @return string 133 | */ 134 | public function javascript($absolutePath) 135 | { 136 | return $this->generator->javascript($absolutePath); 137 | } 138 | 139 | /** 140 | * Return the stylesheet associated with this path 141 | * 142 | * @param string $absolutePath 143 | * @return string 144 | */ 145 | public function stylesheet($absolutePath) 146 | { 147 | return $this->generator->stylesheet($absolutePath); 148 | } 149 | 150 | /** 151 | * Return the file download associated with this path 152 | * 153 | * @param string $path 154 | * @return string | null 155 | */ 156 | public function file($path) 157 | { 158 | return $this->isFile($path); 159 | } 160 | 161 | /** 162 | * Get the config array 163 | * 164 | * @return array 165 | */ 166 | public function getConfig() 167 | { 168 | return $this->parser->config; 169 | } 170 | 171 | /** 172 | * Set the config array 173 | * 174 | * @param array $config 175 | */ 176 | public function setConfig(array $config) 177 | { 178 | $this->parser->config = $config; 179 | $this->generator->config = $config; 180 | $this->registerAssetPipelineFilters(); 181 | } 182 | 183 | /** 184 | * Get the generator 185 | * 186 | * @return Sprockets\Generator 187 | */ 188 | public function getGenerator() 189 | { 190 | return $this->generator; 191 | } 192 | 193 | /** 194 | * Set the generator 195 | * 196 | * @param Sprockets\Generator $generator 197 | */ 198 | public function setGenerator($generator) 199 | { 200 | $this->generator = $generator; 201 | } 202 | 203 | /** 204 | * Get the parser 205 | * 206 | * @return Sprockets\Parser 207 | */ 208 | public function getParser() 209 | { 210 | return $this->parser; 211 | } 212 | 213 | /** 214 | * Set the parser 215 | * 216 | * @param Sprockets\Parser $parser 217 | */ 218 | public function setParser($parser) 219 | { 220 | $this->parser = $parser; 221 | } 222 | 223 | /** 224 | * This calls a method on every filter we have to pass 225 | * in the current pipeline if that method exists 226 | * 227 | * @return void 228 | */ 229 | public function registerAssetPipelineFilters() 230 | { 231 | foreach ($this->parser->config['filters'] as $filters) 232 | { 233 | foreach ($filters as $filter) 234 | { 235 | if (method_exists($filter, 'setAssetPipeline')) 236 | { 237 | $filter->setAssetPipeline($this); 238 | } 239 | } 240 | } 241 | 242 | foreach ($this->generator->config['filters'] as $filters) 243 | { 244 | foreach ($filters as $filter) 245 | { 246 | if (method_exists($filter, 'setAssetPipeline')) 247 | { 248 | $filter->setAssetPipeline($this); 249 | } 250 | } 251 | } 252 | 253 | return $this; 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/AssetPipelineGlobalHelpers.php: -------------------------------------------------------------------------------- 1 | stylesheetLinkTag($file, $attributes); 8 | } 9 | } 10 | 11 | if (!function_exists('javascript_include_tag')) 12 | { 13 | function javascript_include_tag($file = 'application', $attributes = array()) 14 | { 15 | return App::make('asset')->javascriptIncludeTag($file, $attributes); 16 | } 17 | } 18 | 19 | if (!function_exists('javascriptIncludeTag')) 20 | { 21 | function javascriptIncludeTag($file = 'application', $attributes = array()) 22 | { 23 | return App::make('asset')->javascriptIncludeTag($file, $attributes); 24 | } 25 | } 26 | 27 | if (!function_exists('stylesheetLinkTag')) 28 | { 29 | function stylesheetLinkTag($file = 'application', $attributes = array()) 30 | { 31 | return App::make('asset')->stylesheetLinkTag($file, $attributes); 32 | } 33 | } 34 | 35 | if (!function_exists('imageTag')) 36 | { 37 | function imageTag($file, $attributes = array()) 38 | { 39 | return App::make('asset')->imageTag($file, $attributes); 40 | } 41 | } 42 | 43 | if (!function_exists('image_tag')) 44 | { 45 | function image_tag($file = 'application', $attributes = array()) 46 | { 47 | return App::make('asset')->imageTag($file, $attributes); 48 | } 49 | } -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/AssetPipelineServiceProvider.php: -------------------------------------------------------------------------------- 1 | package('codesleeve/asset-pipeline'); 24 | 25 | include_once __DIR__.'/AssetPipelineGlobalHelpers.php'; 26 | 27 | $this->app['asset'] = $this->app->share(function($app) 28 | { 29 | $config = $app->config->get('asset-pipeline::config'); 30 | $config['base_path'] = base_path(); 31 | $config['environment'] = $app['env']; 32 | 33 | $parser = new SprocketsParser($config); 34 | $generator = new SprocketsGenerator($config); 35 | 36 | $pipeline = new AssetPipeline($parser, $generator); 37 | 38 | // let other packages hook into pipeline configuration 39 | $app['events']->fire('asset.pipeline.boot', $pipeline); 40 | 41 | return $pipeline->registerAssetPipelineFilters(); 42 | }); 43 | 44 | $this->app['assets.setup'] = $this->app->share(function($app) 45 | { 46 | return new Commands\AssetsSetupCommand; 47 | }); 48 | 49 | $this->app['assets.clean'] = $this->app->share(function($app) 50 | { 51 | return new Commands\AssetsCleanCommand; 52 | }); 53 | 54 | $this->app['assets.generate'] = $this->app->share(function($app) 55 | { 56 | return new Commands\AssetsGenerateCommand; 57 | }); 58 | 59 | $this->commands('assets.setup'); 60 | $this->commands('assets.clean'); 61 | $this->commands('assets.generate'); 62 | } 63 | 64 | /** 65 | * Boot the service provider. 66 | * 67 | * @return void 68 | */ 69 | public function boot() 70 | { 71 | include __DIR__.'/../../routes.php'; 72 | 73 | $this->registerBladeExtensions(); 74 | } 75 | 76 | /** 77 | * Register custom blade extensions 78 | * - @stylesheets() 79 | * - @javascripts() 80 | * 81 | * @return void 82 | */ 83 | protected function registerBladeExtensions() 84 | { 85 | $blade = $this->app['view']->getEngineResolver()->resolve('blade')->getCompiler(); 86 | 87 | $blade->extend(function($value, $compiler) 88 | { 89 | $matcher = $compiler->createMatcher('javascripts'); 90 | 91 | return preg_replace($matcher, '$1', $value); 92 | }); 93 | 94 | $blade->extend(function($value, $compiler) 95 | { 96 | $matcher = $compiler->createMatcher('stylesheets'); 97 | 98 | return preg_replace($matcher, '$1', $value); 99 | }); 100 | } 101 | 102 | /** 103 | * Get the services provided by the provider. 104 | * 105 | * @return array 106 | */ 107 | public function provides() 108 | { 109 | return array(); 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Commands/AssetsCleanCommand.php: -------------------------------------------------------------------------------- 1 | asset = \App::make('asset'); 31 | 32 | // force concatenation off, so we can get 33 | // a big list of all the files required 34 | // in this manifest file 35 | $config = $this->asset->getConfig(); 36 | $config['concat'] = array(); 37 | $this->asset->setConfig($config); 38 | } 39 | 40 | /** 41 | * Execute the console command. 42 | * 43 | * @return void 44 | */ 45 | public function fire() 46 | { 47 | $recursive = $this->option('recursive') === true; 48 | $this->verbose = $this->option('verbose') === true; 49 | 50 | $files = $this->option('file'); 51 | 52 | foreach ($files as $file) 53 | { 54 | $this->removeAssetCache($file, $recursive); 55 | } 56 | 57 | $this->line('codesleeve/asset-pipeline cache cleared!'); 58 | $this->line('Cache will be re-built on next page request.'); 59 | } 60 | 61 | /** 62 | * Removes the AssetCache for this file 63 | * 64 | * @param [type] $file [description] 65 | * @param [type] $recursive [description] 66 | * @return [type] [description] 67 | */ 68 | protected function removeAssetCache($file, $recursive) 69 | { 70 | $files = $this->asset->isJavascript($file) ? $this->asset->getParser()->javascriptFiles($file) : $this->asset->getParser()->stylesheetFiles($file); 71 | 72 | array_push($files, $this->asset->getParser()->absoluteFilePath($file)); 73 | 74 | foreach ($files as $file) 75 | { 76 | $removed = $this->asset->getGenerator()->cachedFile($file)->remove(); 77 | 78 | if ($removed === false) { 79 | $this->writeln(PHP_EOL . " failed to find/remove cache for {$file}"); 80 | } 81 | } 82 | } 83 | 84 | /** 85 | * Output messages to the user if verbose is on 86 | * 87 | * @param `[type] $message [description] 88 | * @return [type] [description] 89 | */ 90 | protected function writeln($message) 91 | { 92 | if ($this->verbose) 93 | { 94 | echo $message . PHP_EOL; 95 | } 96 | } 97 | 98 | /** 99 | * Get the console command options. 100 | * 101 | * @return array 102 | */ 103 | protected function getOptions() 104 | { 105 | return array( 106 | array('file', 'f', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'This is files that will have the assets cleaned.', array('application.js', 'application.css')), 107 | array('recursive', 'r', InputOption::VALUE_OPTIONAL, 'Should we recursively remove all cached files the manifest requires? Default is true', true), 108 | // array('verbose', 'v', InputOption::VALUE_OPTIONAL, 'Should we be extra noisy? Default is false', false), 109 | ); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Commands/AssetsGenerateCommand.php: -------------------------------------------------------------------------------- 1 | getConfig(); 37 | $config['environment'] = $this->option('env') ? : 'production'; 38 | $asset->setConfig($config); 39 | 40 | $generator = new StaticFilesGenerator($asset->getGenerator()); 41 | 42 | $generated = $generator->generate(public_path($config['routing']['prefix'])); 43 | 44 | foreach ($generated as $file) { 45 | $this->line($file); 46 | } 47 | 48 | $this->line('codesleeve\asset-pipeline assets generated! :)'); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Commands/AssetsSetupCommand.php: -------------------------------------------------------------------------------- 1 | line('codesleeve\asset-pipeline creating initial directory structure and copying some general purpose assets over'); 34 | 35 | $this->xcopy(realpath($structure), realpath($base)); 36 | 37 | $this->line(''); 38 | $this->line('codesleeve\asset-pipeline completed directory setup'); 39 | } 40 | 41 | private function xcopy($source, $dest) 42 | { 43 | $base = base_path(); 44 | foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) { 45 | if ($item->isDir()) { 46 | if (!is_dir($dest . '/' . $iterator->getSubPathName())) { 47 | mkdir($dest . '/' . $iterator->getSubPathName()); 48 | } 49 | } else { 50 | copy($item, $dest . '/' . $iterator->getSubPathName()); 51 | $this->line(' Copying -> ' . str_replace($base, '', $dest . '/' . $iterator->getSubPathName())); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Composers/BaseComposer.php: -------------------------------------------------------------------------------- 1 | $value) 16 | { 17 | $text .= "{$name}=\"{$value}\" "; 18 | } 19 | 20 | $text = rtrim($text); 21 | 22 | return $text; 23 | } 24 | } -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Composers/ComposerInterface.php: -------------------------------------------------------------------------------- 1 | attributesArrayToText($attributes); 17 | 18 | foreach ($paths as $path) 19 | { 20 | print "" . PHP_EOL; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Composers/JavascriptComposer.php: -------------------------------------------------------------------------------- 1 | attributesArrayToText($attributes); 17 | 18 | foreach ($paths as $path) 19 | { 20 | print "" . PHP_EOL; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Composers/StylesheetComposer.php: -------------------------------------------------------------------------------- 1 | attributesArrayToText($attributes); 17 | 18 | foreach ($paths as $path) 19 | { 20 | print "" . PHP_EOL; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Filters/ClientCacheFilter.php: -------------------------------------------------------------------------------- 1 | cache; 32 | } 33 | 34 | /** 35 | * Allows us to delegate the cache driver to this client cache 36 | * 37 | * @param CacheInterface $driver 38 | */ 39 | public function setServerCache(CacheInterface $cache) 40 | { 41 | $this->cache = $cache; 42 | } 43 | 44 | /** 45 | * Allows us to know our parent asset cache so we can do stuff like 46 | * last modified time 47 | * 48 | * @return AssetCache 49 | */ 50 | public function getAssetCache() 51 | { 52 | return $this->asset; 53 | } 54 | 55 | /** 56 | * Allows us to set our parent asset cache (from asset pipeline) 57 | * so we can do stuff like last modified time 58 | * 59 | * @param AssetInterface $cache 60 | */ 61 | public function setAssetCache(AssetInterface $asset) 62 | { 63 | $this->asset = $asset; 64 | } 65 | 66 | /** 67 | * Proxy the $cache has to see if this asset has been cached yet or not 68 | * 69 | * @param string $key 70 | * @return boolean 71 | */ 72 | public function has($key) 73 | { 74 | return $this->cache->has($key); 75 | } 76 | 77 | /** 78 | * If we make it here then we have a cached version of this asset 79 | * found in the underlying $cache driver. So we will check the 80 | * header HTTP_IF_MODIFIED_SINCE and if that is not less than 81 | * the last time we cached ($lastModified) then we will exit 82 | * with 304 header. 83 | * 84 | * @param string $key 85 | * @return string 86 | */ 87 | public function get($key) 88 | { 89 | $lastModified = $this->getLastTimeModified($key); 90 | $modifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : 0; 91 | 92 | header('Last-Modified: '. $lastModified); 93 | 94 | if ($modifiedSince >= $lastModified) 95 | { 96 | header('HTTP/1.0 304 Not Modified'); 97 | exit; 98 | } 99 | 100 | return $this->cache->get($key); 101 | } 102 | 103 | /** 104 | * Proxy set to use the underlying cache driver 105 | * 106 | * @param string $key 107 | * @param string $value 108 | */ 109 | public function set($key, $value) 110 | { 111 | return $this->cache->set($key, $value); 112 | } 113 | 114 | /** 115 | * Remove this key from session and also remove it from 116 | * underlying cache driver 117 | * 118 | * @param string $key 119 | * @return string 120 | */ 121 | public function remove($key) 122 | { 123 | return $this->cache->remove($key); 124 | } 125 | 126 | /** 127 | * Store the last time this file was modified (which we don't know) 128 | * so we just use the current datetime. We will store this date in 129 | * $_SESSION so that next time we run we can re-use the datetime we 130 | * first picked so that our cache isn't busted each time. 131 | * 132 | * @param string $key 133 | * @return string 134 | */ 135 | private function getLastTimeModified($key) 136 | { 137 | return filemtime($this->asset->getSourceRoot() . '/' . $this->asset->getSourcePath()); 138 | } 139 | 140 | } -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Filters/CoffeeScript.php: -------------------------------------------------------------------------------- 1 | config = $config; 14 | } 15 | 16 | public function filterLoad(AssetInterface $asset) 17 | { 18 | 19 | } 20 | 21 | public function filterDump(AssetInterface $asset) 22 | { 23 | $content = $asset->getContent(); 24 | 25 | $config = array_merge( array( 'filename' => $asset->getSourcePath() ), $this->config ); 26 | 27 | $content = Compiler::compile($content, $config); 28 | 29 | $asset->setContent($content); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Filters/CssMinFilter.php: -------------------------------------------------------------------------------- 1 | setContent(\CssMin::minify($asset->getContent())); 16 | } 17 | } -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Filters/EnvironmentFilter.php: -------------------------------------------------------------------------------- 1 | filter = $filter; 15 | $this->environment = $environment; 16 | $this->environments = !is_array($environments) ? explode(',', $environments) : $environments; 17 | } 18 | 19 | public function filterLoad(AssetInterface $asset) 20 | { 21 | if ($this->shouldApplyFilter()) { 22 | $this->filter->filterLoad($asset); 23 | } 24 | } 25 | 26 | public function filterDump(AssetInterface $asset) 27 | { 28 | if ($this->shouldApplyFilter()) { 29 | $this->filter->filterDump($asset); 30 | } 31 | } 32 | 33 | protected function shouldApplyFilter() 34 | { 35 | return in_array($this->environment, $this->environments); 36 | } 37 | } -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Filters/FilesNotCached.php: -------------------------------------------------------------------------------- 1 | forwardSlashes($absolutePath); 22 | 23 | if (!is_array($basePath)) 24 | { 25 | list($changed, $newPath) = $this->_getRelativePath($basePath, $absolutePath); 26 | return $newPath; 27 | } 28 | 29 | foreach ($basePath as $path) 30 | { 31 | list($changed, $newPath) = $this->_getRelativePath($path, $absolutePath); 32 | 33 | if ($changed) return $newPath; 34 | } 35 | 36 | return reset($basePath); 37 | } 38 | 39 | public function fileExists($filename) 40 | { 41 | $parsed = parse_url($filename); 42 | $queryless = isset($parsed['path']) ? $parsed['path'] : $filename; 43 | 44 | return (file_exists($filename) && is_file($filename)) || (file_exists($queryless) && is_file($queryless)); 45 | } 46 | 47 | private function _getRelativePath($basePath, $absolutePath) 48 | { 49 | $pos = strpos($absolutePath, $basePath); 50 | 51 | if ($pos !== false) 52 | { 53 | $start = strlen($basePath) + $pos; 54 | $end = strlen($absolutePath) - $start; 55 | $path = substr($absolutePath, $start, $end); 56 | return array(true, $path); 57 | } 58 | 59 | return array(false, $absolutePath); 60 | } 61 | 62 | /** 63 | * Swap out any back slashes with forward slashes for 64 | * windows compatability 65 | * 66 | * @param string $filename 67 | * @return string 68 | */ 69 | private function forwardSlashes($filename) 70 | { 71 | return str_replace('\\', '/', $filename); 72 | } 73 | } -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Filters/JSMinPlusFilter.php: -------------------------------------------------------------------------------- 1 | setContent(\JSMinPlus::minify($asset->getContent()) . ';'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Filters/JST.php: -------------------------------------------------------------------------------- 1 | basePath = $basePath; 11 | } 12 | 13 | public function filterLoad(AssetInterface $asset) 14 | { 15 | // do nothing when asset is loaded 16 | } 17 | 18 | public function filterDump(AssetInterface $asset) 19 | { 20 | $relativePath = $this->getRelativePath($this->basePath, $asset->getSourceRoot() . '/'); 21 | $filename = pathinfo($asset->getSourcePath(), PATHINFO_FILENAME); 22 | 23 | $content = str_replace('"', '\\"', $asset->getContent()); 24 | $content = preg_replace("/[\r?\n]+/", "", $content); 25 | 26 | $jst = 'JST = (typeof JST === "undefined") ? JST = {} : JST;' . PHP_EOL; 27 | $jst .= 'JST["' . $relativePath . $filename . '"] = "'; 28 | $jst .= $content; 29 | $jst .= '";' . PHP_EOL; 30 | 31 | $asset->setContent($jst); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Filters/LessphpFilter.php: -------------------------------------------------------------------------------- 1 | environments = !is_array($environments) ? array($environments) : $environments; 11 | $this->env = $env; 12 | } 13 | 14 | public function filterLoad(AssetInterface $asset) 15 | { 16 | 17 | } 18 | 19 | public function filterDump(AssetInterface $asset) 20 | { 21 | if (in_array($this->env, $this->environments)) { 22 | $asset->setContent(\CssMin::minify($asset->getContent())); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Filters/MinifyHtml.php: -------------------------------------------------------------------------------- 1 | environments = !is_array($environments) ? array($environments) : $environments; 11 | $this->env = $env; 12 | } 13 | 14 | public function filterLoad(AssetInterface $asset) 15 | { 16 | 17 | } 18 | 19 | public function filterDump(AssetInterface $asset) 20 | { 21 | if (in_array($this->env, $this->environments)) { 22 | $asset->setContent(preg_replace(array('/ {2,}/', '/|\t|(?:\r?\n[ \t]*)+/s'), array(' ',''), $asset->getContent())); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Filters/MinifyJS.php: -------------------------------------------------------------------------------- 1 | environments = !is_array($environments) ? array($environments) : $environments; 11 | $this->env = $env; 12 | } 13 | 14 | public function filterLoad(AssetInterface $asset) 15 | { 16 | 17 | } 18 | 19 | public function filterDump(AssetInterface $asset) 20 | { 21 | if (in_array($this->env, $this->environments)) { 22 | $asset->setContent(\JSMinPlus::minify($asset->getContent()) . ';'); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Filters/SassFilter.php: -------------------------------------------------------------------------------- 1 | getSourceRoot() . '/' . $asset->getSourcePath(); 18 | 19 | $options = array( 20 | 'style'=>'expanded', 21 | ); 22 | 23 | $sass = new SassParser($options); 24 | 25 | $parsed = $sass->toCss($file); 26 | 27 | $asset->setContent($parsed); 28 | } 29 | } -------------------------------------------------------------------------------- /src/Codesleeve/AssetPipeline/Filters/URLRewrite.php: -------------------------------------------------------------------------------- 1 | baseurl = $baseurl; 13 | $this->prefix = $prefix; 14 | $this->paths = $paths; 15 | } 16 | 17 | public function setAssetPipeline($pipeline) 18 | { 19 | $config = $pipeline->getConfig(); 20 | $this->paths = $config['paths']; 21 | } 22 | 23 | public function filterLoad(AssetInterface $asset) 24 | { 25 | // do nothing when this is loaded... 26 | } 27 | 28 | public function filterDump(AssetInterface $asset) 29 | { 30 | $this->root = $asset->getSourceRoot() . '/'; 31 | $this->file = $asset->getSourcePath(); 32 | $this->base = $this->getRelativePath($this->paths, $this->root); 33 | 34 | $content = $this->filterReferences($asset->getContent(), array($this, 'url_matcher')); 35 | $asset->setContent($content); 36 | } 37 | 38 | /** 39 | * My attempt at rewriting CSS urls. I am looking for all url tags and 40 | * then I am going to try and resolve the correct absolute path from 41 | * those urls. If the file actually exists then we are good, else I just 42 | * leave the thing alone. 43 | * 44 | * @param [type] $matches [description] 45 | * @return [type] [description] 46 | */ 47 | public function url_matcher($matches) 48 | { 49 | list($changed, $newurl) = $this->relative_match($matches['url']); 50 | if ($changed) { 51 | return str_replace($matches['url'], $newurl, $matches[0]); 52 | } 53 | 54 | list($changed, $newurl) = $this->found_file_match($matches['url']); 55 | if ($changed) { 56 | return str_replace($matches['url'], $newurl, $matches[0]); 57 | } 58 | 59 | return $matches[0]; 60 | } 61 | 62 | /** 63 | * Search for cases like url(../fonts/blah.eot) 64 | * 65 | * @param string $url 66 | * @return array(bool, string) 67 | */ 68 | public function relative_match($url) 69 | { 70 | $changed = false; 71 | $base = $this->base; 72 | $root = $this->root; 73 | 74 | while (0 === strpos($url, '../') && 2 <= substr_count($base, '/')) 75 | { 76 | $changed = true; 77 | $base = substr($base, 0, strrpos(rtrim($base, '/'), '/') + 1); 78 | $root = substr($root, 0, strrpos(rtrim($root, '/'), '/') + 1); 79 | $url = substr($url, 3); 80 | } 81 | 82 | if (!$changed || !$this->fileExists($root . $url)) { 83 | return array(false, $url); 84 | } 85 | 86 | return array(true, $this->baseurl . $this->prefix . $base . $url); 87 | } 88 | 89 | /** 90 | * Search for the case where we might be concatenating 91 | * and so long as the url doesn't start with a '/' we 92 | * will see if there is a file relative to this directory. 93 | * 94 | * @param string $url 95 | * @return array(bool, string) 96 | */ 97 | public function found_file_match($url) 98 | { 99 | if ($url[0] != '/' && $this->fileExists($this->root . $url)) { 100 | return array(true, $this->baseurl . $this->prefix . $this->base . $url); 101 | } 102 | 103 | return array(false, $url); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/config/config.php: -------------------------------------------------------------------------------- 1 | array( 28 | 'prefix' => '/assets' 29 | ), 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | paths 34 | |-------------------------------------------------------------------------- 35 | | 36 | | These are the directories we search for files in. 37 | | 38 | | NOTE that the '.' in require_tree . is relative to where the manifest file 39 | | (i.e. app/assets/javascripts/application.js) is located 40 | | 41 | */ 42 | 'paths' => array( 43 | 'app/assets/javascripts', 44 | 'app/assets/stylesheets', 45 | 'app/assets/images', 46 | 'lib/assets/javascripts', 47 | 'lib/assets/stylesheets', 48 | 'lib/assets/images', 49 | 'provider/assets/javascripts', 50 | 'provider/assets/stylesheets', 51 | 'provider/assets/images' 52 | ), 53 | 54 | /* 55 | |-------------------------------------------------------------------------- 56 | | mimes 57 | |-------------------------------------------------------------------------- 58 | | 59 | | In order to know which mime type to send back to the server 60 | | we need to know if it is a javascript or stylesheet type. If 61 | | the extension is not found below then we just return a regular 62 | | download. 63 | | 64 | */ 65 | 'mimes' => array( 66 | 'javascripts' => array('.js', '.js.coffee', '.coffee', '.html', '.min.js'), 67 | 'stylesheets' => array('.css', '.css.less', '.css.sass', '.css.scss', '.less', '.sass', '.scss', '.min.css'), 68 | ), 69 | 70 | /* 71 | |-------------------------------------------------------------------------- 72 | | filters 73 | |-------------------------------------------------------------------------- 74 | | 75 | | In order for a file to be included with sprockets, it needs to be listed 76 | | here and we can also do any preprocessing on files with the extension if 77 | | we choose to. 78 | | 79 | */ 80 | 'filters' => array( 81 | '.min.js' => array( 82 | 83 | ), 84 | '.min.css' => array( 85 | new Codesleeve\AssetPipeline\Filters\URLRewrite(App::make('url')->to('/')), 86 | ), 87 | '.js' => array( 88 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\JSMinPlusFilter, App::environment()), 89 | ), 90 | '.js.coffee' => array( 91 | new Codesleeve\AssetPipeline\Filters\CoffeeScript, 92 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\JSMinPlusFilter, App::environment()), 93 | ), 94 | '.coffee' => array( 95 | new Codesleeve\AssetPipeline\Filters\CoffeeScript, 96 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\JSMinPlusFilter, App::environment()), 97 | ), 98 | '.css' => array( 99 | new Codesleeve\AssetPipeline\Filters\URLRewrite(App::make('url')->to('/')), 100 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\CssMinFilter, App::environment()), 101 | ), 102 | '.css.less' => array( 103 | new Codesleeve\AssetPipeline\Filters\LessphpFilter, 104 | new Codesleeve\AssetPipeline\Filters\URLRewrite(App::make('url')->to('/')), 105 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\CssMinFilter, App::environment()), 106 | ), 107 | '.css.sass' => array( 108 | new Codesleeve\AssetPipeline\Filters\SassFilter, 109 | new Codesleeve\AssetPipeline\Filters\URLRewrite(App::make('url')->to('/')), 110 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\CssMinFilter, App::environment()), 111 | ), 112 | '.css.scss' => array( 113 | new Assetic\Filter\ScssphpFilter, 114 | new Codesleeve\AssetPipeline\Filters\URLRewrite(App::make('url')->to('/')), 115 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\CssMinFilter, App::environment()), 116 | ), 117 | '.less' => array( 118 | new Codesleeve\AssetPipeline\Filters\LessphpFilter, 119 | new Codesleeve\AssetPipeline\Filters\URLRewrite(App::make('url')->to('/')), 120 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\CssMinFilter, App::environment()), 121 | ), 122 | '.sass' => array( 123 | new Codesleeve\AssetPipeline\Filters\SassFilter, 124 | new Codesleeve\AssetPipeline\Filters\URLRewrite(App::make('url')->to('/')), 125 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\CssMinFilter, App::environment()), 126 | ), 127 | '.scss' => array( 128 | new Assetic\Filter\ScssphpFilter, 129 | new Codesleeve\AssetPipeline\Filters\URLRewrite(App::make('url')->to('/')), 130 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\CssMinFilter, App::environment()), 131 | ), 132 | '.html' => array( 133 | new Codesleeve\AssetPipeline\Filters\JST, 134 | new EnvironmentFilter(new Codesleeve\AssetPipeline\Filters\JSMinPlusFilter, App::environment()), 135 | ) 136 | ), 137 | 138 | /* 139 | |-------------------------------------------------------------------------- 140 | | cache 141 | |-------------------------------------------------------------------------- 142 | | 143 | | By default we cache assets on production environment permanently. We also cache 144 | | all files using the `cache_server` driver below but the cache is busted anytime 145 | | those files are modified. On production we will cache and the only way to bust 146 | | the cache is to delete files from app/storage/cache/asset-pipeline or run a 147 | | command php artisan assets:clean -f somefilename.js -f application.css ... 148 | | 149 | */ 150 | 'cache' => array('production'), 151 | 152 | /* 153 | |-------------------------------------------------------------------------- 154 | | cache_server 155 | |-------------------------------------------------------------------------- 156 | | 157 | | You can create your own CacheInterface if the filesystem cache is not up to 158 | | your standards. This is for caching asset files on the server-side. 159 | | 160 | | Please note that caching is used on **ALL** environments always. This is done 161 | | to increase performance of the pipeline. Cached files will be busted when the 162 | | file changes. 163 | | 164 | | However, manifest files are regenerated (not cached) when the environment is 165 | | not found within the 'cache' array. This lets you develop on local and still 166 | | utilize caching, so you don't have to regenerate all precompiled files while 167 | | developing on your assets. 168 | | 169 | | See more in CacheInterface.php at 170 | | 171 | | https://github.com/kriswallsmith/assetic/blob/master/src/Assetic/Cache 172 | | 173 | | 174 | */ 175 | 'cache_server' => new Assetic\Cache\FilesystemCache(App::make('path.storage') . '/cache/asset-pipeline'), 176 | 177 | /* 178 | |-------------------------------------------------------------------------- 179 | | cache_client 180 | |-------------------------------------------------------------------------- 181 | | 182 | | If you want to handle 304's and what not, to keep users from refetching 183 | | your assets and saving your bandwidth you can use a cache_client driver 184 | | that handles this. This doesn't handle assets on the server-side, use 185 | | cache_server for that. This only works when the current environment is 186 | | listed within `cache` 187 | | 188 | | Note that this needs to implement the interface 189 | | 190 | | Codesleeve\Sprockets\Interfaces\ClientCacheInterface 191 | | 192 | | or this won't work correctly. It is a wrapper class around your cache_server 193 | | driver and also uses the AssetCache class to help access files. 194 | | 195 | */ 196 | 'cache_client' => new Codesleeve\AssetPipeline\Filters\ClientCacheFilter, 197 | 198 | /* 199 | |-------------------------------------------------------------------------- 200 | | concat 201 | |-------------------------------------------------------------------------- 202 | | 203 | | This allows us to turn on the asset concatenation for specific 204 | | environments listed below. You can turn off local environment if 205 | | you are trying to troubleshoot, but you will likely have better 206 | | performance if you leave concat on (except if you are doing a lot 207 | | of minification stuff on each page refresh) 208 | | 209 | */ 210 | 'concat' => array('production', 'local'), 211 | 212 | /* 213 | |-------------------------------------------------------------------------- 214 | | directives 215 | |-------------------------------------------------------------------------- 216 | | 217 | | This allows us to turn completely control which directives are used 218 | | for the sprockets parser that asset pipeline uses to parse manifest files. 219 | | 220 | | It is probably safe just to leave this alone unless you are familiar with 221 | | what is actually going on here. 222 | | 223 | */ 224 | 'directives' => array( 225 | 'require ' => new Codesleeve\Sprockets\Directives\RequireFile, 226 | 'require_directory ' => new Codesleeve\Sprockets\Directives\RequireDirectory, 227 | 'require_tree ' => new Codesleeve\Sprockets\Directives\RequireTree, 228 | 'require_tree_df ' => new Codesleeve\Sprockets\Directives\RequireTreeDf, 229 | 'require_self' => new Codesleeve\Sprockets\Directives\RequireSelf, 230 | 'include ' => new Codesleeve\Sprockets\Directives\IncludeFile, 231 | 'include_directory ' => new Codesleeve\Sprockets\Directives\IncludeDirectory, 232 | 'include_tree ' => new Codesleeve\Sprockets\Directives\IncludeTree, 233 | 'stub ' => new Codesleeve\Sprockets\Directives\Stub, 234 | 'depend_on ' => new Codesleeve\Sprockets\Directives\DependOn, 235 | ), 236 | 237 | /* 238 | |-------------------------------------------------------------------------- 239 | | javascript_include_tag 240 | |-------------------------------------------------------------------------- 241 | | 242 | | This allows us to completely control how the javascript_include_tag function 243 | | works for asset pipeline. 244 | | 245 | | It is probably safe just to leave this alone unless you are familiar with 246 | | what is actually going on here. 247 | | 248 | */ 249 | 'javascript_include_tag' => new Codesleeve\AssetPipeline\Composers\JavascriptComposer, 250 | 251 | /* 252 | |-------------------------------------------------------------------------- 253 | | stylesheet_link_tag 254 | |-------------------------------------------------------------------------- 255 | | 256 | | This allows us to completely control how the stylesheet_link_tag function 257 | | works for asset pipeline. 258 | | 259 | | It is probably safe just to leave this alone unless you are familiar with 260 | | what is actually going on here. 261 | | 262 | */ 263 | 'stylesheet_link_tag' => new Codesleeve\AssetPipeline\Composers\StylesheetComposer, 264 | 265 | /* 266 | |-------------------------------------------------------------------------- 267 | | image_tag 268 | |-------------------------------------------------------------------------- 269 | | 270 | | This allows us to completely control how the image_tag function 271 | | works for asset pipeline. 272 | | 273 | | It is probably safe just to leave this alone unless you are familiar with 274 | | what is actually going on here. 275 | | 276 | */ 277 | 'image_tag' => new Codesleeve\AssetPipeline\Composers\ImageComposer, 278 | 279 | /* 280 | |-------------------------------------------------------------------------- 281 | | controller_action 282 | |-------------------------------------------------------------------------- 283 | | 284 | | Asset pipeline will route all requests through the controller action 285 | | listed here. This allows us to completely control how the controller 286 | | should behave for incoming requests for assets. 287 | | 288 | | It is probably safe just to leave this alone unless you are familiar with 289 | | what is actually going on here. 290 | | 291 | */ 292 | 'controller_action' => '\Codesleeve\AssetPipeline\AssetPipelineController@file', 293 | 294 | /* 295 | |-------------------------------------------------------------------------- 296 | | sprockets_filter 297 | |-------------------------------------------------------------------------- 298 | | 299 | | When concatenation is turned on, when an asset is fetched from the sprockets 300 | | generator it is filtered through this filter class named below. This allows us 301 | | to modify the sprockets filter if we need to behave differently. 302 | | 303 | | It is probably safe just to leave this alone unless you are familiar with 304 | | what is actually going on here. 305 | | 306 | */ 307 | 'sprockets_filter' => '\Codesleeve\Sprockets\SprocketsFilter', 308 | 309 | /* 310 | |-------------------------------------------------------------------------- 311 | | sprockets_filter 312 | |-------------------------------------------------------------------------- 313 | | 314 | | When concatenation is turned on, assets are filtered via SprocketsFilter 315 | | and we can do global filters on the resulting dump file. This would be 316 | | useful if you wanted to apply a filter to all javascript or stylesheet files 317 | | like minification. Out of the box we don't have any filters here. Add at 318 | | your own risk. I don't put minification filters here because the minify 319 | | doesn't always work perfectly and can bjork your entire concatenated 320 | | javascript or stylesheet file if it messes up. 321 | | 322 | | It is probably safe just to leave this alone unless you are familiar with 323 | | what is actually going on here. 324 | | 325 | */ 326 | 'sprockets_filters' => array( 327 | 'javascripts' => array(), 328 | 'stylesheets' => array(), 329 | ), 330 | 331 | ); 332 | -------------------------------------------------------------------------------- /src/controllers/AssetPipelineController.php: -------------------------------------------------------------------------------- 1 | javascript($absolutePath); 18 | } 19 | 20 | $absolutePath = Asset::isStylesheet($path); 21 | if ($absolutePath) { 22 | return $this->stylesheet($absolutePath); 23 | } 24 | 25 | $absolutePath = Asset::isFile($path); 26 | if ($absolutePath) 27 | { 28 | $this->clientCacheForFile($absolutePath); 29 | return new BinaryFileResponse($absolutePath, 200); 30 | } 31 | 32 | App::abort(404); 33 | } 34 | 35 | /* 36 | * Returns a javascript file for the given path. 37 | * 38 | * @return \Illuminate\Support\Facades\Response 39 | */ 40 | private function javascript($path) 41 | { 42 | $response = Response::make(Asset::javascript($path), 200); 43 | 44 | $response->header('Content-Type', 'application/javascript'); 45 | 46 | return $response; 47 | } 48 | 49 | /** 50 | * Returns css for the given path 51 | * 52 | * @return \Illuminate\Support\Facades\Response 53 | */ 54 | private function stylesheet($path) 55 | { 56 | $response = Response::make(Asset::stylesheet($path), 200); 57 | 58 | $response->header('Content-Type', 'text/css'); 59 | 60 | return $response; 61 | } 62 | 63 | /** 64 | * Client cache regular files that are not 65 | * javascript or stylesheets files 66 | * 67 | * @param string $path 68 | * @return void 69 | */ 70 | private function clientCacheForFile($path) 71 | { 72 | $lastModified = filemtime($path); 73 | 74 | if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified) 75 | { 76 | header('HTTP/1.0 304 Not Modified'); 77 | exit; 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /src/routes.php: -------------------------------------------------------------------------------- 1 | where('path', '(?!\.\.)(.*)'); 8 | }); -------------------------------------------------------------------------------- /structure/app/assets/images/readme.txt: -------------------------------------------------------------------------------- 1 | If you place an image here called foobar.png then you can access that image by going to http:///assets/foobar.png -------------------------------------------------------------------------------- /structure/app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear in whatever order it 8 | // gets included (e.g. say you have require_tree . then the code will appear after all the directories 9 | // but before any files alphabetically greater than 'application.js' 10 | // 11 | // The available directives right now are require, require_directory, and require_tree 12 | // 13 | //= require jquery 14 | //= require_tree . -------------------------------------------------------------------------------- /structure/app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any Css/Less files within this directory, lib/assets/javascripts, vendor/assets/javascripts, 6 | * can be referenced here using a relative path. 7 | * 8 | * It's not advisable to add code directly here, but if you do, it'll appear in whatever order it 9 | * gets included (e.g. say you have require_tree . then the code will appear after all the directories 10 | * but before any files alphabetically greater than 'application.css' 11 | * 12 | *= require_tree . 13 | */ -------------------------------------------------------------------------------- /structure/provider/assets/javascripts/jquery.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license 2 | //@ sourceMappingURL=jquery-1.10.2.min.map 3 | */ 4 | (function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
a",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="
t
",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t 5 | }({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
","
"]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); 6 | u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("