Showing preview only (706K chars total). Download the full file or copy to clipboard to get everything.
Repository: newagebegins/BattleCity
Branch: master
Commit: d4d5fc164b2c
Files: 175
Total size: 662.9 KB
Directory structure:
gitextract_lf6w0ydf/
├── .gitignore
├── BattleCity.html
├── LICENSE
├── README.md
├── SpecRunner.html
├── css/
│ └── BattleCity.css
├── lib/
│ ├── Stats.js
│ ├── jasmine-1.2.0/
│ │ ├── MIT.LICENSE
│ │ ├── jasmine-html.js
│ │ ├── jasmine.css
│ │ └── jasmine.js
│ └── jquery-1.7.2.js
├── sound/
│ ├── bullet_hit_1.ogg
│ ├── bullet_hit_2.ogg
│ ├── bullet_shot.ogg
│ ├── explosion_1.ogg
│ ├── explosion_2.ogg
│ ├── game_over.ogg
│ ├── pause.ogg
│ ├── powerup_appear.ogg
│ ├── powerup_pick.ogg
│ ├── stage_start.ogg
│ └── statistics_1.ogg
├── spec/
│ ├── AITankControllerContainerSpec.js
│ ├── AITankControllerFactorySpec.js
│ ├── AITankControllerSpec.js
│ ├── AnimationSpec.js
│ ├── BaseExplosionFactorySpec.js
│ ├── BaseExplosionSpec.js
│ ├── BaseSpec.js
│ ├── BaseWallBuilderSpec.js
│ ├── BrickWallSpec.js
│ ├── BuilderSpec.js
│ ├── BulletExplosionFactorySpec.js
│ ├── BulletFactorySpec.js
│ ├── BulletSpec.js
│ ├── CollisionDetectorSpec.js
│ ├── ConstructionMenuItemSpec.js
│ ├── CursorControllerSpec.js
│ ├── CursorSpec.js
│ ├── CurtainSpec.js
│ ├── DelaySpec.js
│ ├── EnemyFactorySpec.js
│ ├── EventManagerSpec.js
│ ├── ExplosionSpec.js
│ ├── FreezeTimerSpec.js
│ ├── MainMenuControllerSpec.js
│ ├── MainMenuSceneSpec.js
│ ├── MainMenuSpec.js
│ ├── MoveFnSpec.js
│ ├── OnePlayerMenuItemSpec.js
│ ├── PainterSpec.js
│ ├── PauseListenerSpec.js
│ ├── PauseSpec.js
│ ├── PlayerTankControllerFactorySpec.js
│ ├── PlayerTankFactorySpec.js
│ ├── PointSpec.js
│ ├── PointsFactorySpec.js
│ ├── PointsSpec.js
│ ├── PowerUpFactorySpec.js
│ ├── PowerUpHandlerSpec.js
│ ├── PowerUpSpec.js
│ ├── RandomSpec.js
│ ├── RectSpec.js
│ ├── SceneManagerSpec.js
│ ├── ScriptSpec.js
│ ├── ShovelHandlerSpec.js
│ ├── SpriteContainerSpec.js
│ ├── SpriteControllerSpec.js
│ ├── SpriteSerializerSpec.js
│ ├── SpriteSpec.js
│ ├── SteelWallSpec.js
│ ├── StructureManagerSpec.js
│ ├── TankColorSpec.js
│ ├── TankControllerSpec.js
│ ├── TankExplosionFactorySpec.js
│ ├── TankExplosionSpec.js
│ ├── TankSpec.js
│ ├── TankStateAppearingSpec.js
│ ├── TankStateInvincibleSpec.js
│ ├── TankStateNormalSpec.js
│ ├── UpdaterSpec.js
│ ├── UtilsSpec.js
│ └── WallSpec.js
└── src/
├── AITankController.js
├── AITankControllerContainer.js
├── AITankControllerFactory.js
├── Animation.js
├── Base.js
├── BaseExplosion.js
├── BaseExplosionFactory.js
├── BaseWallBuilder.js
├── BlinkTimer.js
├── BrickWall.js
├── BrickWallFactory.js
├── Builder.js
├── Bullet.js
├── BulletExplosion.js
├── BulletExplosionFactory.js
├── BulletFactory.js
├── CollisionDetector.js
├── Construction.js
├── ConstructionMenuItem.js
├── Cursor.js
├── CursorController.js
├── Curtain.js
├── Delay.js
├── EnemyFactory.js
├── EnemyFactoryView.js
├── EventManager.js
├── Explosion.js
├── FPSCounter.js
├── FreezeTimer.js
├── GameOverMessage.js
├── GameOverScene.js
├── GameScene.js
├── Gamefield.js
├── Globals.js
├── ImageManager.js
├── Keyboard.js
├── Level.js
├── LivesView.js
├── LoadingScene.js
├── MainMenu.js
├── MainMenuController.js
├── MainMenuCursor.js
├── MainMenuCursorView.js
├── MainMenuItem.js
├── MainMenuScene.js
├── MainMenuView.js
├── MoveFn.js
├── OnePlayerMenuItem.js
├── Painter.js
├── Pause.js
├── PauseListener.js
├── Player.js
├── PlayerTankControllerFactory.js
├── PlayerTankFactory.js
├── Point.js
├── Points.js
├── PointsFactory.js
├── PowerUp.js
├── PowerUpFactory.js
├── PowerUpHandler.js
├── Random.js
├── Rect.js
├── SceneManager.js
├── Script.js
├── ShovelHandler.js
├── SoundManager.js
├── Sprite.js
├── SpriteContainer.js
├── SpriteController.js
├── SpriteSerializer.js
├── SpriteSerializerController.js
├── StageMessage.js
├── StageStatisticsPoints.js
├── StageStatisticsScene.js
├── Stages.js
├── SteelWall.js
├── SteelWallFactory.js
├── StructureManager.js
├── Tank.js
├── TankColor.js
├── TankController.js
├── TankExplosion.js
├── TankExplosionFactory.js
├── TankStateAppearing.js
├── TankStateInvincible.js
├── TankStateNormal.js
├── Trees.js
├── Updater.js
├── Utils.js
├── Wall.js
└── Water.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
/nbproject/
/NOTES.txt
================================================
FILE: BattleCity.html
================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Battle City</title>
<link rel="stylesheet" type="text/css" href="css/BattleCity.css" />
<script type="text/javascript" src="lib/jquery-1.7.2.js"></script>
<script type="text/javascript" src="src/Utils.js"></script>
<script type="text/javascript" src="src/Point.js"></script>
<script type="text/javascript" src="src/Rect.js"></script>
<script type="text/javascript" src="src/Sprite.js"></script>
<script type="text/javascript" src="src/Tank.js"></script>
<script type="text/javascript" src="src/Wall.js"></script>
<script type="text/javascript" src="src/SpriteContainer.js"></script>
<script type="text/javascript" src="src/CollisionDetector.js"></script>
<script type="text/javascript" src="src/EventManager.js"></script>
<script type="text/javascript" src="src/SpriteController.js"></script>
<script type="text/javascript" src="src/TankController.js"></script>
<script type="text/javascript" src="src/Keyboard.js"></script>
<script type="text/javascript" src="src/BulletFactory.js"></script>
<script type="text/javascript" src="src/Bullet.js"></script>
<script type="text/javascript" src="src/Painter.js"></script>
<script type="text/javascript" src="src/Updater.js"></script>
<script type="text/javascript" src="src/BulletExplosionFactory.js"></script>
<script type="text/javascript" src="src/Explosion.js"></script>
<script type="text/javascript" src="src/BulletExplosion.js"></script>
<script type="text/javascript" src="src/BrickWall.js"></script>
<script type="text/javascript" src="src/SteelWall.js"></script>
<script type="text/javascript" src="src/Cursor.js"></script>
<script type="text/javascript" src="src/BlinkTimer.js"></script>
<script type="text/javascript" src="src/CursorController.js"></script>
<script type="text/javascript" src="src/Builder.js"></script>
<script type="text/javascript" src="src/StructureManager.js"></script>
<script type="text/javascript" src="src/BrickWallFactory.js"></script>
<script type="text/javascript" src="src/SteelWallFactory.js"></script>
<script type="text/javascript" src="src/Globals.js"></script>
<script type="text/javascript" src="src/SpriteSerializer.js"></script>
<script type="text/javascript" src="src/Base.js"></script>
<script type="text/javascript" src="src/TankStateAppearing.js"></script>
<script type="text/javascript" src="src/TankStateNormal.js"></script>
<script type="text/javascript" src="src/TankStateInvincible.js"></script>
<script type="text/javascript" src="src/AITankController.js"></script>
<script type="text/javascript" src="src/Random.js"></script>
<script type="text/javascript" src="src/AITankControllerFactory.js"></script>
<script type="text/javascript" src="src/AITankControllerContainer.js"></script>
<script type="text/javascript" src="src/EnemyFactory.js"></script>
<script type="text/javascript" src="src/Animation.js"></script>
<script type="text/javascript" src="src/TankExplosionFactory.js"></script>
<script type="text/javascript" src="src/TankExplosion.js"></script>
<script type="text/javascript" src="src/PointsFactory.js"></script>
<script type="text/javascript" src="src/Points.js"></script>
<script type="text/javascript" src="src/PlayerTankFactory.js"></script>
<script type="text/javascript" src="src/PlayerTankControllerFactory.js"></script>
<script type="text/javascript" src="src/PowerUpFactory.js"></script>
<script type="text/javascript" src="src/PowerUp.js"></script>
<script type="text/javascript" src="src/PowerUpHandler.js"></script>
<script type="text/javascript" src="src/FreezeTimer.js"></script>
<script type="text/javascript" src="src/BaseWallBuilder.js"></script>
<script type="text/javascript" src="src/ShovelHandler.js"></script>
<script type="text/javascript" src="src/Pause.js"></script>
<script type="text/javascript" src="src/PauseListener.js"></script>
<script type="text/javascript" src="src/BaseExplosionFactory.js"></script>
<script type="text/javascript" src="src/BaseExplosion.js"></script>
<script type="text/javascript" src="src/TankColor.js"></script>
<script type="text/javascript" src="src/SceneManager.js"></script>
<script type="text/javascript" src="src/MainMenuScene.js"></script>
<script type="text/javascript" src="src/MainMenuItem.js"></script>
<script type="text/javascript" src="src/OnePlayerMenuItem.js"></script>
<script type="text/javascript" src="src/ConstructionMenuItem.js"></script>
<script type="text/javascript" src="src/MainMenu.js"></script>
<script type="text/javascript" src="src/MainMenuController.js"></script>
<script type="text/javascript" src="src/MainMenuView.js"></script>
<script type="text/javascript" src="src/MainMenuCursor.js"></script>
<script type="text/javascript" src="src/MainMenuCursorView.js"></script>
<script type="text/javascript" src="src/Gamefield.js"></script>
<script type="text/javascript" src="src/Level.js"></script>
<script type="text/javascript" src="src/EnemyFactoryView.js"></script>
<script type="text/javascript" src="src/LivesView.js"></script>
<script type="text/javascript" src="src/MainMenuView.js"></script>
<script type="text/javascript" src="src/Curtain.js"></script>
<script type="text/javascript" src="src/Script.js"></script>
<script type="text/javascript" src="src/Delay.js"></script>
<script type="text/javascript" src="src/GameScene.js"></script>
<script type="text/javascript" src="src/StageMessage.js"></script>
<script type="text/javascript" src="src/Stages.js"></script>
<script type="text/javascript" src="src/MoveFn.js"></script>
<script type="text/javascript" src="src/GameOverMessage.js"></script>
<script type="text/javascript" src="src/StageStatisticsScene.js"></script>
<script type="text/javascript" src="src/GameOverScene.js"></script>
<script type="text/javascript" src="src/Player.js"></script>
<script type="text/javascript" src="src/StageStatisticsPoints.js"></script>
<script type="text/javascript" src="src/Trees.js"></script>
<script type="text/javascript" src="src/Water.js"></script>
<script type="text/javascript" src="src/LoadingScene.js"></script>
<script type="text/javascript" src="lib/Stats.js"></script>
<script type="text/javascript" src="src/FPSCounter.js"></script>
<script type="text/javascript" src="src/ImageManager.js"></script>
<script type="text/javascript" src="src/Construction.js"></script>
<script type="text/javascript" src="src/SpriteSerializerController.js"></script>
<script type="text/javascript" src="src/SpriteSerializer.js"></script>
<script type="text/javascript" src="src/SoundManager.js"></script>
<script type="text/javascript">
$(function () {
var FPS = 50;
var CANVAS_ID = 'canvas';
var ctx = createCanvasContext();
ctx.font = "16px prstart"
var eventManager = new EventManager();
var keyboard = new Keyboard(eventManager);
var sceneManager = new SceneManager(eventManager);
sceneManager.toLoadingScene();
setInterval(gameLoop, 1000 / FPS);
function gameLoop() {
keyboard.fireEvents();
sceneManager.update();
sceneManager.draw(ctx);
}
function createCanvasContext() {
$('<canvas id="' + CANVAS_ID + '" width="' + Globals.CANVAS_WIDTH + '" height="' + Globals.CANVAS_HEIGHT + '"></canvas>').prependTo('#main');
var canvas = document.getElementById(CANVAS_ID);
return canvas.getContext('2d');
};
});
</script>
</head>
<body>
<div id="main">
<div id="help">
<p>CONTROLS:</p>
<table>
<tr>
<td><img src="images/Nintendo-Dpad-Neutral.png" alt="" /></td>
<td>ARROWS</td>
</tr>
<tr>
<td><img src="images/Nintendo-Button-A.png" alt="" />,<img src="images/Nintendo-Button-B.png" alt="" /></td>
<td>SPACE</td>
</tr>
<tr>
<td><img src="images/Nintendo-Button-Start.png" alt="" /></td>
<td>ENTER</td>
</tr>
<tr>
<td><img src="images/Nintendo-Button-Select.png" alt="" /></td>
<td>CTRL</td>
</tr>
</table>
</div>
</div>
</body>
</html>
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021 Vyacheslav Rachek
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:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
================================================
FILE: README.md
================================================
JavaScript/HTML5 remake of the Famicom "Battle City" game
=====================================================
[Play](http://newagebegins.github.io/BattleCity/BattleCity.html)
[Run tests](http://newagebegins.github.io/BattleCity/SpecRunner.html)
The code was written with TDD (Test-Driven Development) methodology.

================================================
FILE: SpecRunner.html
================================================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Spec Runner</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-1.2.0/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-1.2.0/jasmine.css">
<script type="text/javascript" src="lib/jasmine-1.2.0/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-1.2.0/jasmine-html.js"></script>
<!-- spec files -->
<script type="text/javascript" src="spec/TankSpec.js"></script>
<script type="text/javascript" src="spec/PointSpec.js"></script>
<script type="text/javascript" src="spec/RectSpec.js"></script>
<script type="text/javascript" src="spec/CollisionDetectorSpec.js"></script>
<script type="text/javascript" src="spec/EventManagerSpec.js"></script>
<script type="text/javascript" src="spec/SpriteControllerSpec.js"></script>
<script type="text/javascript" src="spec/TankControllerSpec.js"></script>
<script type="text/javascript" src="spec/BulletFactorySpec.js"></script>
<script type="text/javascript" src="spec/SpriteSpec.js"></script>
<script type="text/javascript" src="spec/BulletSpec.js"></script>
<script type="text/javascript" src="spec/UtilsSpec.js"></script>
<script type="text/javascript" src="spec/PainterSpec.js"></script>
<script type="text/javascript" src="spec/SpriteContainerSpec.js"></script>
<script type="text/javascript" src="spec/UpdaterSpec.js"></script>
<script type="text/javascript" src="spec/BulletExplosionFactorySpec.js"></script>
<script type="text/javascript" src="spec/ExplosionSpec.js"></script>
<script type="text/javascript" src="spec/WallSpec.js"></script>
<script type="text/javascript" src="spec/BrickWallSpec.js"></script>
<script type="text/javascript" src="spec/CursorSpec.js"></script>
<script type="text/javascript" src="spec/CursorControllerSpec.js"></script>
<script type="text/javascript" src="spec/BuilderSpec.js"></script>
<script type="text/javascript" src="spec/StructureManagerSpec.js"></script>
<script type="text/javascript" src="spec/SpriteSerializerSpec.js"></script>
<script type="text/javascript" src="spec/SteelWallSpec.js"></script>
<script type="text/javascript" src="spec/BaseSpec.js"></script>
<script type="text/javascript" src="spec/TankStateAppearingSpec.js"></script>
<script type="text/javascript" src="spec/TankStateNormalSpec.js"></script>
<script type="text/javascript" src="spec/TankStateInvincibleSpec.js"></script>
<script type="text/javascript" src="spec/AITankControllerSpec.js"></script>
<script type="text/javascript" src="spec/RandomSpec.js"></script>
<script type="text/javascript" src="spec/AITankControllerFactorySpec.js"></script>
<script type="text/javascript" src="spec/AITankControllerContainerSpec.js"></script>
<script type="text/javascript" src="spec/EnemyFactorySpec.js"></script>
<script type="text/javascript" src="spec/AnimationSpec.js"></script>
<script type="text/javascript" src="spec/TankExplosionFactorySpec.js"></script>
<script type="text/javascript" src="spec/TankExplosionSpec.js"></script>
<script type="text/javascript" src="spec/PointsFactorySpec.js"></script>
<script type="text/javascript" src="spec/PointsSpec.js"></script>
<script type="text/javascript" src="spec/PlayerTankFactorySpec.js"></script>
<script type="text/javascript" src="spec/PlayerTankControllerFactorySpec.js"></script>
<script type="text/javascript" src="spec/PowerUpFactorySpec.js"></script>
<script type="text/javascript" src="spec/PowerUpSpec.js"></script>
<script type="text/javascript" src="spec/PowerUpHandlerSpec.js"></script>
<script type="text/javascript" src="spec/FreezeTimerSpec.js"></script>
<script type="text/javascript" src="spec/BaseWallBuilderSpec.js"></script>
<script type="text/javascript" src="spec/ShovelHandlerSpec.js"></script>
<script type="text/javascript" src="spec/PauseSpec.js"></script>
<script type="text/javascript" src="spec/PauseListenerSpec.js"></script>
<script type="text/javascript" src="spec/BaseExplosionFactorySpec.js"></script>
<script type="text/javascript" src="spec/BaseExplosionSpec.js"></script>
<script type="text/javascript" src="spec/TankColorSpec.js"></script>
<script type="text/javascript" src="spec/SceneManagerSpec.js"></script>
<script type="text/javascript" src="spec/MainMenuSceneSpec.js"></script>
<script type="text/javascript" src="spec/OnePlayerMenuItemSpec.js"></script>
<script type="text/javascript" src="spec/ConstructionMenuItemSpec.js"></script>
<script type="text/javascript" src="spec/MainMenuSpec.js"></script>
<script type="text/javascript" src="spec/MainMenuControllerSpec.js"></script>
<script type="text/javascript" src="spec/CurtainSpec.js"></script>
<script type="text/javascript" src="spec/ScriptSpec.js"></script>
<script type="text/javascript" src="spec/DelaySpec.js"></script>
<script type="text/javascript" src="spec/MoveFnSpec.js"></script>
<!-- source files -->
<script type="text/javascript" src="src/Utils.js"></script>
<script type="text/javascript" src="src/Point.js"></script>
<script type="text/javascript" src="src/Rect.js"></script>
<script type="text/javascript" src="src/Sprite.js"></script>
<script type="text/javascript" src="src/Tank.js"></script>
<script type="text/javascript" src="src/Wall.js"></script>
<script type="text/javascript" src="src/SpriteContainer.js"></script>
<script type="text/javascript" src="src/CollisionDetector.js"></script>
<script type="text/javascript" src="src/EventManager.js"></script>
<script type="text/javascript" src="src/SpriteController.js"></script>
<script type="text/javascript" src="src/TankController.js"></script>
<script type="text/javascript" src="src/Keyboard.js"></script>
<script type="text/javascript" src="src/BulletFactory.js"></script>
<script type="text/javascript" src="src/Bullet.js"></script>
<script type="text/javascript" src="src/Painter.js"></script>
<script type="text/javascript" src="src/Updater.js"></script>
<script type="text/javascript" src="src/BulletExplosionFactory.js"></script>
<script type="text/javascript" src="src/Explosion.js"></script>
<script type="text/javascript" src="src/BulletExplosion.js"></script>
<script type="text/javascript" src="src/BrickWall.js"></script>
<script type="text/javascript" src="src/SteelWall.js"></script>
<script type="text/javascript" src="src/Cursor.js"></script>
<script type="text/javascript" src="src/BlinkTimer.js"></script>
<script type="text/javascript" src="src/CursorController.js"></script>
<script type="text/javascript" src="src/Builder.js"></script>
<script type="text/javascript" src="src/StructureManager.js"></script>
<script type="text/javascript" src="src/BrickWallFactory.js"></script>
<script type="text/javascript" src="src/SteelWallFactory.js"></script>
<script type="text/javascript" src="src/Globals.js"></script>
<script type="text/javascript" src="src/SpriteSerializer.js"></script>
<script type="text/javascript" src="src/Base.js"></script>
<script type="text/javascript" src="src/TankStateAppearing.js"></script>
<script type="text/javascript" src="src/TankStateNormal.js"></script>
<script type="text/javascript" src="src/TankStateInvincible.js"></script>
<script type="text/javascript" src="src/AITankController.js"></script>
<script type="text/javascript" src="src/Random.js"></script>
<script type="text/javascript" src="src/AITankControllerFactory.js"></script>
<script type="text/javascript" src="src/AITankControllerContainer.js"></script>
<script type="text/javascript" src="src/EnemyFactory.js"></script>
<script type="text/javascript" src="src/Animation.js"></script>
<script type="text/javascript" src="src/TankExplosionFactory.js"></script>
<script type="text/javascript" src="src/TankExplosion.js"></script>
<script type="text/javascript" src="src/PointsFactory.js"></script>
<script type="text/javascript" src="src/Points.js"></script>
<script type="text/javascript" src="src/PlayerTankFactory.js"></script>
<script type="text/javascript" src="src/PlayerTankControllerFactory.js"></script>
<script type="text/javascript" src="src/PowerUpFactory.js"></script>
<script type="text/javascript" src="src/PowerUp.js"></script>
<script type="text/javascript" src="src/PowerUpHandler.js"></script>
<script type="text/javascript" src="src/FreezeTimer.js"></script>
<script type="text/javascript" src="src/BaseWallBuilder.js"></script>
<script type="text/javascript" src="src/ShovelHandler.js"></script>
<script type="text/javascript" src="src/Pause.js"></script>
<script type="text/javascript" src="src/PauseListener.js"></script>
<script type="text/javascript" src="src/BaseExplosionFactory.js"></script>
<script type="text/javascript" src="src/BaseExplosion.js"></script>
<script type="text/javascript" src="src/TankColor.js"></script>
<script type="text/javascript" src="src/SceneManager.js"></script>
<script type="text/javascript" src="src/MainMenuScene.js"></script>
<script type="text/javascript" src="src/MainMenuItem.js"></script>
<script type="text/javascript" src="src/OnePlayerMenuItem.js"></script>
<script type="text/javascript" src="src/ConstructionMenuItem.js"></script>
<script type="text/javascript" src="src/MainMenu.js"></script>
<script type="text/javascript" src="src/MainMenuController.js"></script>
<script type="text/javascript" src="src/MainMenuView.js"></script>
<script type="text/javascript" src="src/MainMenuCursor.js"></script>
<script type="text/javascript" src="src/MainMenuCursorView.js"></script>
<script type="text/javascript" src="src/Gamefield.js"></script>
<script type="text/javascript" src="src/Level.js"></script>
<script type="text/javascript" src="src/EnemyFactoryView.js"></script>
<script type="text/javascript" src="src/LivesView.js"></script>
<script type="text/javascript" src="src/MainMenuView.js"></script>
<script type="text/javascript" src="src/Curtain.js"></script>
<script type="text/javascript" src="src/Script.js"></script>
<script type="text/javascript" src="src/Delay.js"></script>
<script type="text/javascript" src="src/MoveFn.js"></script>
<script type="text/javascript" src="src/Trees.js"></script>
<script type="text/javascript" src="src/Water.js"></script>
<script type="text/javascript">
var SoundManager = (function() {
return {
play: function () {}
};
})();
</script>
<script type="text/javascript">
(function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function(spec) {
return htmlReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
</script>
</head>
<body>
</body>
</html>
================================================
FILE: css/BattleCity.css
================================================
@font-face {
font-family: prstart;
src: url('../fonts/prstart.ttf');
}
body {
font-family: prstart;
font-size: 16px;
background-color: black;
margin-top: 30px;
}
#main {
margin: 0 auto;
width: 512px;
color: white;
}
#help {
border-top: 4px solid white;
margin-top: 10px;
padding-top: 7px;
}
#help img {
vertical-align: middle;
}
#help td {
padding-left: 1em;
}
================================================
FILE: lib/Stats.js
================================================
/**
* @author mrdoob / http://mrdoob.com/
*/
var Stats = function () {
var startTime = Date.now(), prevTime = startTime;
var ms = 0, msMin = 1000, msMax = 0;
var fps = 0, fpsMin = 1000, fpsMax = 0;
var frames = 0, mode = 0;
var container = document.createElement( 'div' );
container.id = 'stats';
container.addEventListener( 'mousedown', function ( event ) { event.preventDefault(); setMode( ++ mode % 2 ) }, false );
container.style.cssText = 'width:80px;opacity:0.9;cursor:pointer';
var fpsDiv = document.createElement( 'div' );
fpsDiv.id = 'fps';
fpsDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#002';
container.appendChild( fpsDiv );
var fpsText = document.createElement( 'div' );
fpsText.id = 'fpsText';
fpsText.style.cssText = 'color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
fpsText.innerHTML = 'FPS';
fpsDiv.appendChild( fpsText );
var fpsGraph = document.createElement( 'div' );
fpsGraph.id = 'fpsGraph';
fpsGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0ff';
fpsDiv.appendChild( fpsGraph );
while ( fpsGraph.children.length < 74 ) {
var bar = document.createElement( 'span' );
bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#113';
fpsGraph.appendChild( bar );
}
var msDiv = document.createElement( 'div' );
msDiv.id = 'ms';
msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;display:none';
container.appendChild( msDiv );
var msText = document.createElement( 'div' );
msText.id = 'msText';
msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
msText.innerHTML = 'MS';
msDiv.appendChild( msText );
var msGraph = document.createElement( 'div' );
msGraph.id = 'msGraph';
msGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0f0';
msDiv.appendChild( msGraph );
while ( msGraph.children.length < 74 ) {
var bar = document.createElement( 'span' );
bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#131';
msGraph.appendChild( bar );
}
var setMode = function ( value ) {
mode = value;
switch ( mode ) {
case 0:
fpsDiv.style.display = 'block';
msDiv.style.display = 'none';
break;
case 1:
fpsDiv.style.display = 'none';
msDiv.style.display = 'block';
break;
}
}
var updateGraph = function ( dom, value ) {
var child = dom.appendChild( dom.firstChild );
child.style.height = value + 'px';
}
return {
domElement: container,
setMode: setMode,
begin: function () {
startTime = Date.now();
},
end: function () {
var time = Date.now();
ms = time - startTime;
msMin = Math.min( msMin, ms );
msMax = Math.max( msMax, ms );
msText.textContent = ms + ' MS (' + msMin + '-' + msMax + ')';
updateGraph( msGraph, Math.min( 30, 30 - ( ms / 200 ) * 30 ) );
frames ++;
if ( time > prevTime + 1000 ) {
fps = Math.round( ( frames * 1000 ) / ( time - prevTime ) );
fpsMin = Math.min( fpsMin, fps );
fpsMax = Math.max( fpsMax, fps );
fpsText.textContent = fps + ' FPS (' + fpsMin + '-' + fpsMax + ')';
updateGraph( fpsGraph, Math.min( 30, 30 - ( fps / 100 ) * 30 ) );
prevTime = time;
frames = 0;
}
return time;
},
update: function () {
startTime = this.end();
}
}
};
================================================
FILE: lib/jasmine-1.2.0/MIT.LICENSE
================================================
Copyright (c) 2008-2011 Pivotal Labs
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:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
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.
================================================
FILE: lib/jasmine-1.2.0/jasmine-html.js
================================================
jasmine.HtmlReporterHelpers = {};
jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) {
var el = document.createElement(type);
for (var i = 2; i < arguments.length; i++) {
var child = arguments[i];
if (typeof child === 'string') {
el.appendChild(document.createTextNode(child));
} else {
if (child) {
el.appendChild(child);
}
}
}
for (var attr in attrs) {
if (attr == "className") {
el[attr] = attrs[attr];
} else {
el.setAttribute(attr, attrs[attr]);
}
}
return el;
};
jasmine.HtmlReporterHelpers.getSpecStatus = function(child) {
var results = child.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.skipped) {
status = 'skipped';
}
return status;
};
jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) {
var parentDiv = this.dom.summary;
var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite';
var parent = child[parentSuite];
if (parent) {
if (typeof this.views.suites[parent.id] == 'undefined') {
this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views);
}
parentDiv = this.views.suites[parent.id].element;
}
parentDiv.appendChild(childElement);
};
jasmine.HtmlReporterHelpers.addHelpers = function(ctor) {
for(var fn in jasmine.HtmlReporterHelpers) {
ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn];
}
};
jasmine.HtmlReporter = function(_doc) {
var self = this;
var doc = _doc || window.document;
var reporterView;
var dom = {};
// Jasmine Reporter Public Interface
self.logRunningSpecs = false;
self.reportRunnerStarting = function(runner) {
var specs = runner.specs() || [];
if (specs.length == 0) {
return;
}
createReporterDom(runner.env.versionString());
doc.body.appendChild(dom.reporter);
reporterView = new jasmine.HtmlReporter.ReporterView(dom);
reporterView.addSpecs(specs, self.specFilter);
};
self.reportRunnerResults = function(runner) {
reporterView && reporterView.complete();
};
self.reportSuiteResults = function(suite) {
reporterView.suiteComplete(suite);
};
self.reportSpecStarting = function(spec) {
if (self.logRunningSpecs) {
self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
}
};
self.reportSpecResults = function(spec) {
reporterView.specComplete(spec);
};
self.log = function() {
var console = jasmine.getGlobal().console;
if (console && console.log) {
if (console.log.apply) {
console.log.apply(console, arguments);
} else {
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
}
}
};
self.specFilter = function(spec) {
if (!focusedSpecName()) {
return true;
}
return spec.getFullName().indexOf(focusedSpecName()) === 0;
};
return self;
function focusedSpecName() {
var specName;
(function memoizeFocusedSpec() {
if (specName) {
return;
}
var paramMap = [];
var params = doc.location.search.substring(1).split('&');
for (var i = 0; i < params.length; i++) {
var p = params[i].split('=');
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
}
specName = paramMap.spec;
})();
return specName;
}
function createReporterDom(version) {
dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' },
dom.banner = self.createDom('div', { className: 'banner' },
self.createDom('span', { className: 'title' }, "Jasmine "),
self.createDom('span', { className: 'version' }, version)),
dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
dom.alert = self.createDom('div', {className: 'alert'}),
dom.results = self.createDom('div', {className: 'results'},
dom.summary = self.createDom('div', { className: 'summary' }),
dom.details = self.createDom('div', { id: 'details' }))
);
}
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporter.ReporterView = function(dom) {
this.startedAt = new Date();
this.runningSpecCount = 0;
this.completeSpecCount = 0;
this.passedCount = 0;
this.failedCount = 0;
this.skippedCount = 0;
this.createResultsMenu = function() {
this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'},
this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'),
' | ',
this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing'));
this.summaryMenuItem.onclick = function() {
dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, '');
};
this.detailsMenuItem.onclick = function() {
showDetails();
};
};
this.addSpecs = function(specs, specFilter) {
this.totalSpecCount = specs.length;
this.views = {
specs: {},
suites: {}
};
for (var i = 0; i < specs.length; i++) {
var spec = specs[i];
this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views);
if (specFilter(spec)) {
this.runningSpecCount++;
}
}
};
this.specComplete = function(spec) {
this.completeSpecCount++;
if (isUndefined(this.views.specs[spec.id])) {
this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom);
}
var specView = this.views.specs[spec.id];
switch (specView.status()) {
case 'passed':
this.passedCount++;
break;
case 'failed':
this.failedCount++;
break;
case 'skipped':
this.skippedCount++;
break;
}
specView.refresh();
this.refresh();
};
this.suiteComplete = function(suite) {
var suiteView = this.views.suites[suite.id];
if (isUndefined(suiteView)) {
return;
}
suiteView.refresh();
};
this.refresh = function() {
if (isUndefined(this.resultsMenu)) {
this.createResultsMenu();
}
// currently running UI
if (isUndefined(this.runningAlert)) {
this.runningAlert = this.createDom('a', {href: "?", className: "runningAlert bar"});
dom.alert.appendChild(this.runningAlert);
}
this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
// skipped specs UI
if (isUndefined(this.skippedAlert)) {
this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"});
}
this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
if (this.skippedCount === 1 && isDefined(dom.alert)) {
dom.alert.appendChild(this.skippedAlert);
}
// passing specs UI
if (isUndefined(this.passedAlert)) {
this.passedAlert = this.createDom('span', {href: "?", className: "passingAlert bar"});
}
this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);
// failing specs UI
if (isUndefined(this.failedAlert)) {
this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"});
}
this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount);
if (this.failedCount === 1 && isDefined(dom.alert)) {
dom.alert.appendChild(this.failedAlert);
dom.alert.appendChild(this.resultsMenu);
}
// summary info
this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount);
this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
};
this.complete = function() {
dom.alert.removeChild(this.runningAlert);
this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
if (this.failedCount === 0) {
dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount)));
} else {
showDetails();
}
dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"));
};
return this;
function showDetails() {
if (dom.reporter.className.search(/showDetails/) === -1) {
dom.reporter.className += " showDetails";
}
}
function isUndefined(obj) {
return typeof obj === 'undefined';
}
function isDefined(obj) {
return !isUndefined(obj);
}
function specPluralizedFor(count) {
var str = count + " spec";
if (count > 1) {
str += "s"
}
return str;
}
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView);
jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
this.spec = spec;
this.dom = dom;
this.views = views;
this.symbol = this.createDom('li', { className: 'pending' });
this.dom.symbolSummary.appendChild(this.symbol);
this.summary = this.createDom('div', { className: 'specSummary' },
this.createDom('a', {
className: 'description',
href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
title: this.spec.getFullName()
}, this.spec.description)
);
this.detail = this.createDom('div', { className: 'specDetail' },
this.createDom('a', {
className: 'description',
href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
title: this.spec.getFullName()
}, this.spec.getFullName())
);
};
jasmine.HtmlReporter.SpecView.prototype.status = function() {
return this.getSpecStatus(this.spec);
};
jasmine.HtmlReporter.SpecView.prototype.refresh = function() {
this.symbol.className = this.status();
switch (this.status()) {
case 'skipped':
break;
case 'passed':
this.appendSummaryToSuiteDiv();
break;
case 'failed':
this.appendSummaryToSuiteDiv();
this.appendFailureDetail();
break;
}
};
jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() {
this.summary.className += ' ' + this.status();
this.appendToSummary(this.spec, this.summary);
};
jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() {
this.detail.className += ' ' + this.status();
var resultItems = this.spec.results().getItems();
var messagesDiv = this.createDom('div', { className: 'messages' });
for (var i = 0; i < resultItems.length; i++) {
var result = resultItems[i];
if (result.type == 'log') {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
} else if (result.type == 'expect' && result.passed && !result.passed()) {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
if (result.trace.stack) {
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
}
}
}
if (messagesDiv.childNodes.length > 0) {
this.detail.appendChild(messagesDiv);
this.dom.details.appendChild(this.detail);
}
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) {
this.suite = suite;
this.dom = dom;
this.views = views;
this.element = this.createDom('div', { className: 'suite' },
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(this.suite.getFullName()) }, this.suite.description)
);
this.appendToSummary(this.suite, this.element);
};
jasmine.HtmlReporter.SuiteView.prototype.status = function() {
return this.getSpecStatus(this.suite);
};
jasmine.HtmlReporter.SuiteView.prototype.refresh = function() {
this.element.className += " " + this.status();
};
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView);
/* @deprecated Use jasmine.HtmlReporter instead
*/
jasmine.TrivialReporter = function(doc) {
this.document = doc || document;
this.suiteDivs = {};
this.logRunningSpecs = false;
};
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
var el = document.createElement(type);
for (var i = 2; i < arguments.length; i++) {
var child = arguments[i];
if (typeof child === 'string') {
el.appendChild(document.createTextNode(child));
} else {
if (child) { el.appendChild(child); }
}
}
for (var attr in attrs) {
if (attr == "className") {
el[attr] = attrs[attr];
} else {
el.setAttribute(attr, attrs[attr]);
}
}
return el;
};
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
var showPassed, showSkipped;
this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' },
this.createDom('div', { className: 'banner' },
this.createDom('div', { className: 'logo' },
this.createDom('span', { className: 'title' }, "Jasmine"),
this.createDom('span', { className: 'version' }, runner.env.versionString())),
this.createDom('div', { className: 'options' },
"Show ",
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
)
),
this.runnerDiv = this.createDom('div', { className: 'runner running' },
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
);
this.document.body.appendChild(this.outerDiv);
var suites = runner.suites();
for (var i = 0; i < suites.length; i++) {
var suite = suites[i];
var suiteDiv = this.createDom('div', { className: 'suite' },
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
this.suiteDivs[suite.id] = suiteDiv;
var parentDiv = this.outerDiv;
if (suite.parentSuite) {
parentDiv = this.suiteDivs[suite.parentSuite.id];
}
parentDiv.appendChild(suiteDiv);
}
this.startedAt = new Date();
var self = this;
showPassed.onclick = function(evt) {
if (showPassed.checked) {
self.outerDiv.className += ' show-passed';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
}
};
showSkipped.onclick = function(evt) {
if (showSkipped.checked) {
self.outerDiv.className += ' show-skipped';
} else {
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
}
};
};
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
var results = runner.results();
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
this.runnerDiv.setAttribute("class", className);
//do it twice for IE
this.runnerDiv.setAttribute("className", className);
var specs = runner.specs();
var specCount = 0;
for (var i = 0; i < specs.length; i++) {
if (this.specFilter(specs[i])) {
specCount++;
}
}
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
};
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
var results = suite.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.totalCount === 0) { // todo: change this to check results.skipped
status = 'skipped';
}
this.suiteDivs[suite.id].className += " " + status;
};
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
if (this.logRunningSpecs) {
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
}
};
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
var results = spec.results();
var status = results.passed() ? 'passed' : 'failed';
if (results.skipped) {
status = 'skipped';
}
var specDiv = this.createDom('div', { className: 'spec ' + status },
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
this.createDom('a', {
className: 'description',
href: '?spec=' + encodeURIComponent(spec.getFullName()),
title: spec.getFullName()
}, spec.description));
var resultItems = results.getItems();
var messagesDiv = this.createDom('div', { className: 'messages' });
for (var i = 0; i < resultItems.length; i++) {
var result = resultItems[i];
if (result.type == 'log') {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
} else if (result.type == 'expect' && result.passed && !result.passed()) {
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
if (result.trace.stack) {
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
}
}
}
if (messagesDiv.childNodes.length > 0) {
specDiv.appendChild(messagesDiv);
}
this.suiteDivs[spec.suite.id].appendChild(specDiv);
};
jasmine.TrivialReporter.prototype.log = function() {
var console = jasmine.getGlobal().console;
if (console && console.log) {
if (console.log.apply) {
console.log.apply(console, arguments);
} else {
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
}
}
};
jasmine.TrivialReporter.prototype.getLocation = function() {
return this.document.location;
};
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
var paramMap = {};
var params = this.getLocation().search.substring(1).split('&');
for (var i = 0; i < params.length; i++) {
var p = params[i].split('=');
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
}
if (!paramMap.spec) {
return true;
}
return spec.getFullName().indexOf(paramMap.spec) === 0;
};
================================================
FILE: lib/jasmine-1.2.0/jasmine.css
================================================
body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
#HTMLReporter a { text-decoration: none; }
#HTMLReporter a:hover { text-decoration: underline; }
#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
#HTMLReporter #jasmine_content { position: fixed; right: 100%; }
#HTMLReporter .version { color: #aaaaaa; }
#HTMLReporter .banner { margin-top: 14px; }
#HTMLReporter .duration { color: #aaaaaa; float: right; }
#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
#HTMLReporter .symbolSummary li.passed { font-size: 14px; }
#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
#HTMLReporter .symbolSummary li.failed { line-height: 9px; }
#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
#HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
#HTMLReporter .symbolSummary li.pending { line-height: 11px; }
#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
#HTMLReporter .runningAlert { background-color: #666666; }
#HTMLReporter .skippedAlert { background-color: #aaaaaa; }
#HTMLReporter .skippedAlert:first-child { background-color: #333333; }
#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; }
#HTMLReporter .passingAlert { background-color: #a6b779; }
#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; }
#HTMLReporter .failingAlert { background-color: #cf867e; }
#HTMLReporter .failingAlert:first-child { background-color: #b03911; }
#HTMLReporter .results { margin-top: 14px; }
#HTMLReporter #details { display: none; }
#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; }
#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
#HTMLReporter.showDetails .summary { display: none; }
#HTMLReporter.showDetails #details { display: block; }
#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
#HTMLReporter .summary { margin-top: 14px; }
#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; }
#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; }
#HTMLReporter .summary .specSummary.failed a { color: #b03911; }
#HTMLReporter .description + .suite { margin-top: 0; }
#HTMLReporter .suite { margin-top: 14px; }
#HTMLReporter .suite a { color: #333333; }
#HTMLReporter #details .specDetail { margin-bottom: 28px; }
#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; }
#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; }
#HTMLReporter .resultMessage span.result { display: block; }
#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ }
#TrivialReporter a:visited, #TrivialReporter a { color: #303; }
#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; }
#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; }
#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; }
#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; }
#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; }
#TrivialReporter .runner.running { background-color: yellow; }
#TrivialReporter .options { text-align: right; font-size: .8em; }
#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; }
#TrivialReporter .suite .suite { margin: 5px; }
#TrivialReporter .suite.passed { background-color: #dfd; }
#TrivialReporter .suite.failed { background-color: #fdd; }
#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; }
#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; }
#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; }
#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; }
#TrivialReporter .spec.skipped { background-color: #bbb; }
#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; }
#TrivialReporter .passed { background-color: #cfc; display: none; }
#TrivialReporter .failed { background-color: #fbb; }
#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; }
#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; }
#TrivialReporter .resultMessage .mismatch { color: black; }
#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; }
#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; }
#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; }
#TrivialReporter #jasmine_content { position: fixed; right: 100%; }
#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; }
================================================
FILE: lib/jasmine-1.2.0/jasmine.js
================================================
var isCommonJS = typeof window == "undefined";
/**
* Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
*
* @namespace
*/
var jasmine = {};
if (isCommonJS) exports.jasmine = jasmine;
/**
* @private
*/
jasmine.unimplementedMethod_ = function() {
throw new Error("unimplemented method");
};
/**
* Use <code>jasmine.undefined</code> instead of <code>undefined</code>, since <code>undefined</code> is just
* a plain old variable and may be redefined by somebody else.
*
* @private
*/
jasmine.undefined = jasmine.___undefined___;
/**
* Show diagnostic messages in the console if set to true
*
*/
jasmine.VERBOSE = false;
/**
* Default interval in milliseconds for event loop yields (e.g. to allow network activity or to refresh the screen with the HTML-based runner). Small values here may result in slow test running. Zero means no updates until all tests have completed.
*
*/
jasmine.DEFAULT_UPDATE_INTERVAL = 250;
/**
* Default timeout interval in milliseconds for waitsFor() blocks.
*/
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
jasmine.getGlobal = function() {
function getGlobal() {
return this;
}
return getGlobal();
};
/**
* Allows for bound functions to be compared. Internal use only.
*
* @ignore
* @private
* @param base {Object} bound 'this' for the function
* @param name {Function} function to find
*/
jasmine.bindOriginal_ = function(base, name) {
var original = base[name];
if (original.apply) {
return function() {
return original.apply(base, arguments);
};
} else {
// IE support
return jasmine.getGlobal()[name];
}
};
jasmine.setTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'setTimeout');
jasmine.clearTimeout = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearTimeout');
jasmine.setInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'setInterval');
jasmine.clearInterval = jasmine.bindOriginal_(jasmine.getGlobal(), 'clearInterval');
jasmine.MessageResult = function(values) {
this.type = 'log';
this.values = values;
this.trace = new Error(); // todo: test better
};
jasmine.MessageResult.prototype.toString = function() {
var text = "";
for (var i = 0; i < this.values.length; i++) {
if (i > 0) text += " ";
if (jasmine.isString_(this.values[i])) {
text += this.values[i];
} else {
text += jasmine.pp(this.values[i]);
}
}
return text;
};
jasmine.ExpectationResult = function(params) {
this.type = 'expect';
this.matcherName = params.matcherName;
this.passed_ = params.passed;
this.expected = params.expected;
this.actual = params.actual;
this.message = this.passed_ ? 'Passed.' : params.message;
var trace = (params.trace || new Error(this.message));
this.trace = this.passed_ ? '' : trace;
};
jasmine.ExpectationResult.prototype.toString = function () {
return this.message;
};
jasmine.ExpectationResult.prototype.passed = function () {
return this.passed_;
};
/**
* Getter for the Jasmine environment. Ensures one gets created
*/
jasmine.getEnv = function() {
var env = jasmine.currentEnv_ = jasmine.currentEnv_ || new jasmine.Env();
return env;
};
/**
* @ignore
* @private
* @param value
* @returns {Boolean}
*/
jasmine.isArray_ = function(value) {
return jasmine.isA_("Array", value);
};
/**
* @ignore
* @private
* @param value
* @returns {Boolean}
*/
jasmine.isString_ = function(value) {
return jasmine.isA_("String", value);
};
/**
* @ignore
* @private
* @param value
* @returns {Boolean}
*/
jasmine.isNumber_ = function(value) {
return jasmine.isA_("Number", value);
};
/**
* @ignore
* @private
* @param {String} typeName
* @param value
* @returns {Boolean}
*/
jasmine.isA_ = function(typeName, value) {
return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
};
/**
* Pretty printer for expecations. Takes any object and turns it into a human-readable string.
*
* @param value {Object} an object to be outputted
* @returns {String}
*/
jasmine.pp = function(value) {
var stringPrettyPrinter = new jasmine.StringPrettyPrinter();
stringPrettyPrinter.format(value);
return stringPrettyPrinter.string;
};
/**
* Returns true if the object is a DOM Node.
*
* @param {Object} obj object to check
* @returns {Boolean}
*/
jasmine.isDomNode = function(obj) {
return obj.nodeType > 0;
};
/**
* Returns a matchable 'generic' object of the class type. For use in expecations of type when values don't matter.
*
* @example
* // don't care about which function is passed in, as long as it's a function
* expect(mySpy).toHaveBeenCalledWith(jasmine.any(Function));
*
* @param {Class} clazz
* @returns matchable object of the type clazz
*/
jasmine.any = function(clazz) {
return new jasmine.Matchers.Any(clazz);
};
/**
* Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the
* attributes on the object.
*
* @example
* // don't care about any other attributes than foo.
* expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"});
*
* @param sample {Object} sample
* @returns matchable object for the sample
*/
jasmine.objectContaining = function (sample) {
return new jasmine.Matchers.ObjectContaining(sample);
};
/**
* Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
*
* Spies should be created in test setup, before expectations. They can then be checked, using the standard Jasmine
* expectation syntax. Spies can be checked if they were called or not and what the calling params were.
*
* A Spy has the following fields: wasCalled, callCount, mostRecentCall, and argsForCall (see docs).
*
* Spies are torn down at the end of every spec.
*
* Note: Do <b>not</b> call new jasmine.Spy() directly - a spy must be created using spyOn, jasmine.createSpy or jasmine.createSpyObj.
*
* @example
* // a stub
* var myStub = jasmine.createSpy('myStub'); // can be used anywhere
*
* // spy example
* var foo = {
* not: function(bool) { return !bool; }
* }
*
* // actual foo.not will not be called, execution stops
* spyOn(foo, 'not');
// foo.not spied upon, execution will continue to implementation
* spyOn(foo, 'not').andCallThrough();
*
* // fake example
* var foo = {
* not: function(bool) { return !bool; }
* }
*
* // foo.not(val) will return val
* spyOn(foo, 'not').andCallFake(function(value) {return value;});
*
* // mock example
* foo.not(7 == 7);
* expect(foo.not).toHaveBeenCalled();
* expect(foo.not).toHaveBeenCalledWith(true);
*
* @constructor
* @see spyOn, jasmine.createSpy, jasmine.createSpyObj
* @param {String} name
*/
jasmine.Spy = function(name) {
/**
* The name of the spy, if provided.
*/
this.identity = name || 'unknown';
/**
* Is this Object a spy?
*/
this.isSpy = true;
/**
* The actual function this spy stubs.
*/
this.plan = function() {
};
/**
* Tracking of the most recent call to the spy.
* @example
* var mySpy = jasmine.createSpy('foo');
* mySpy(1, 2);
* mySpy.mostRecentCall.args = [1, 2];
*/
this.mostRecentCall = {};
/**
* Holds arguments for each call to the spy, indexed by call count
* @example
* var mySpy = jasmine.createSpy('foo');
* mySpy(1, 2);
* mySpy(7, 8);
* mySpy.mostRecentCall.args = [7, 8];
* mySpy.argsForCall[0] = [1, 2];
* mySpy.argsForCall[1] = [7, 8];
*/
this.argsForCall = [];
this.calls = [];
};
/**
* Tells a spy to call through to the actual implemenatation.
*
* @example
* var foo = {
* bar: function() { // do some stuff }
* }
*
* // defining a spy on an existing property: foo.bar
* spyOn(foo, 'bar').andCallThrough();
*/
jasmine.Spy.prototype.andCallThrough = function() {
this.plan = this.originalValue;
return this;
};
/**
* For setting the return value of a spy.
*
* @example
* // defining a spy from scratch: foo() returns 'baz'
* var foo = jasmine.createSpy('spy on foo').andReturn('baz');
*
* // defining a spy on an existing property: foo.bar() returns 'baz'
* spyOn(foo, 'bar').andReturn('baz');
*
* @param {Object} value
*/
jasmine.Spy.prototype.andReturn = function(value) {
this.plan = function() {
return value;
};
return this;
};
/**
* For throwing an exception when a spy is called.
*
* @example
* // defining a spy from scratch: foo() throws an exception w/ message 'ouch'
* var foo = jasmine.createSpy('spy on foo').andThrow('baz');
*
* // defining a spy on an existing property: foo.bar() throws an exception w/ message 'ouch'
* spyOn(foo, 'bar').andThrow('baz');
*
* @param {String} exceptionMsg
*/
jasmine.Spy.prototype.andThrow = function(exceptionMsg) {
this.plan = function() {
throw exceptionMsg;
};
return this;
};
/**
* Calls an alternate implementation when a spy is called.
*
* @example
* var baz = function() {
* // do some stuff, return something
* }
* // defining a spy from scratch: foo() calls the function baz
* var foo = jasmine.createSpy('spy on foo').andCall(baz);
*
* // defining a spy on an existing property: foo.bar() calls an anonymnous function
* spyOn(foo, 'bar').andCall(function() { return 'baz';} );
*
* @param {Function} fakeFunc
*/
jasmine.Spy.prototype.andCallFake = function(fakeFunc) {
this.plan = fakeFunc;
return this;
};
/**
* Resets all of a spy's the tracking variables so that it can be used again.
*
* @example
* spyOn(foo, 'bar');
*
* foo.bar();
*
* expect(foo.bar.callCount).toEqual(1);
*
* foo.bar.reset();
*
* expect(foo.bar.callCount).toEqual(0);
*/
jasmine.Spy.prototype.reset = function() {
this.wasCalled = false;
this.callCount = 0;
this.argsForCall = [];
this.calls = [];
this.mostRecentCall = {};
};
jasmine.createSpy = function(name) {
var spyObj = function() {
spyObj.wasCalled = true;
spyObj.callCount++;
var args = jasmine.util.argsToArray(arguments);
spyObj.mostRecentCall.object = this;
spyObj.mostRecentCall.args = args;
spyObj.argsForCall.push(args);
spyObj.calls.push({object: this, args: args});
return spyObj.plan.apply(this, arguments);
};
var spy = new jasmine.Spy(name);
for (var prop in spy) {
spyObj[prop] = spy[prop];
}
spyObj.reset();
return spyObj;
};
/**
* Determines whether an object is a spy.
*
* @param {jasmine.Spy|Object} putativeSpy
* @returns {Boolean}
*/
jasmine.isSpy = function(putativeSpy) {
return putativeSpy && putativeSpy.isSpy;
};
/**
* Creates a more complicated spy: an Object that has every property a function that is a spy. Used for stubbing something
* large in one call.
*
* @param {String} baseName name of spy class
* @param {Array} methodNames array of names of methods to make spies
*/
jasmine.createSpyObj = function(baseName, methodNames) {
if (!jasmine.isArray_(methodNames) || methodNames.length === 0) {
throw new Error('createSpyObj requires a non-empty array of method names to create spies for');
}
var obj = {};
for (var i = 0; i < methodNames.length; i++) {
obj[methodNames[i]] = jasmine.createSpy(baseName + '.' + methodNames[i]);
}
return obj;
};
/**
* All parameters are pretty-printed and concatenated together, then written to the current spec's output.
*
* Be careful not to leave calls to <code>jasmine.log</code> in production code.
*/
jasmine.log = function() {
var spec = jasmine.getEnv().currentSpec;
spec.log.apply(spec, arguments);
};
/**
* Function that installs a spy on an existing object's method name. Used within a Spec to create a spy.
*
* @example
* // spy example
* var foo = {
* not: function(bool) { return !bool; }
* }
* spyOn(foo, 'not'); // actual foo.not will not be called, execution stops
*
* @see jasmine.createSpy
* @param obj
* @param methodName
* @returns a Jasmine spy that can be chained with all spy methods
*/
var spyOn = function(obj, methodName) {
return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
};
if (isCommonJS) exports.spyOn = spyOn;
/**
* Creates a Jasmine spec that will be added to the current suite.
*
* // TODO: pending tests
*
* @example
* it('should be true', function() {
* expect(true).toEqual(true);
* });
*
* @param {String} desc description of this specification
* @param {Function} func defines the preconditions and expectations of the spec
*/
var it = function(desc, func) {
return jasmine.getEnv().it(desc, func);
};
if (isCommonJS) exports.it = it;
/**
* Creates a <em>disabled</em> Jasmine spec.
*
* A convenience method that allows existing specs to be disabled temporarily during development.
*
* @param {String} desc description of this specification
* @param {Function} func defines the preconditions and expectations of the spec
*/
var xit = function(desc, func) {
return jasmine.getEnv().xit(desc, func);
};
if (isCommonJS) exports.xit = xit;
/**
* Starts a chain for a Jasmine expectation.
*
* It is passed an Object that is the actual value and should chain to one of the many
* jasmine.Matchers functions.
*
* @param {Object} actual Actual value to test against and expected value
*/
var expect = function(actual) {
return jasmine.getEnv().currentSpec.expect(actual);
};
if (isCommonJS) exports.expect = expect;
/**
* Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
*
* @param {Function} func Function that defines part of a jasmine spec.
*/
var runs = function(func) {
jasmine.getEnv().currentSpec.runs(func);
};
if (isCommonJS) exports.runs = runs;
/**
* Waits a fixed time period before moving to the next block.
*
* @deprecated Use waitsFor() instead
* @param {Number} timeout milliseconds to wait
*/
var waits = function(timeout) {
jasmine.getEnv().currentSpec.waits(timeout);
};
if (isCommonJS) exports.waits = waits;
/**
* Waits for the latchFunction to return true before proceeding to the next block.
*
* @param {Function} latchFunction
* @param {String} optional_timeoutMessage
* @param {Number} optional_timeout
*/
var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
};
if (isCommonJS) exports.waitsFor = waitsFor;
/**
* A function that is called before each spec in a suite.
*
* Used for spec setup, including validating assumptions.
*
* @param {Function} beforeEachFunction
*/
var beforeEach = function(beforeEachFunction) {
jasmine.getEnv().beforeEach(beforeEachFunction);
};
if (isCommonJS) exports.beforeEach = beforeEach;
/**
* A function that is called after each spec in a suite.
*
* Used for restoring any state that is hijacked during spec execution.
*
* @param {Function} afterEachFunction
*/
var afterEach = function(afterEachFunction) {
jasmine.getEnv().afterEach(afterEachFunction);
};
if (isCommonJS) exports.afterEach = afterEach;
/**
* Defines a suite of specifications.
*
* Stores the description and all defined specs in the Jasmine environment as one suite of specs. Variables declared
* are accessible by calls to beforeEach, it, and afterEach. Describe blocks can be nested, allowing for specialization
* of setup in some tests.
*
* @example
* // TODO: a simple suite
*
* // TODO: a simple suite with a nested describe block
*
* @param {String} description A string, usually the class under test.
* @param {Function} specDefinitions function that defines several specs.
*/
var describe = function(description, specDefinitions) {
return jasmine.getEnv().describe(description, specDefinitions);
};
if (isCommonJS) exports.describe = describe;
/**
* Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
*
* @param {String} description A string, usually the class under test.
* @param {Function} specDefinitions function that defines several specs.
*/
var xdescribe = function(description, specDefinitions) {
return jasmine.getEnv().xdescribe(description, specDefinitions);
};
if (isCommonJS) exports.xdescribe = xdescribe;
// Provide the XMLHttpRequest class for IE 5.x-6.x:
jasmine.XmlHttpRequest = (typeof XMLHttpRequest == "undefined") ? function() {
function tryIt(f) {
try {
return f();
} catch(e) {
}
return null;
}
var xhr = tryIt(function() {
return new ActiveXObject("Msxml2.XMLHTTP.6.0");
}) ||
tryIt(function() {
return new ActiveXObject("Msxml2.XMLHTTP.3.0");
}) ||
tryIt(function() {
return new ActiveXObject("Msxml2.XMLHTTP");
}) ||
tryIt(function() {
return new ActiveXObject("Microsoft.XMLHTTP");
});
if (!xhr) throw new Error("This browser does not support XMLHttpRequest.");
return xhr;
} : XMLHttpRequest;
/**
* @namespace
*/
jasmine.util = {};
/**
* Declare that a child class inherit it's prototype from the parent class.
*
* @private
* @param {Function} childClass
* @param {Function} parentClass
*/
jasmine.util.inherit = function(childClass, parentClass) {
/**
* @private
*/
var subclass = function() {
};
subclass.prototype = parentClass.prototype;
childClass.prototype = new subclass();
};
jasmine.util.formatException = function(e) {
var lineNumber;
if (e.line) {
lineNumber = e.line;
}
else if (e.lineNumber) {
lineNumber = e.lineNumber;
}
var file;
if (e.sourceURL) {
file = e.sourceURL;
}
else if (e.fileName) {
file = e.fileName;
}
var message = (e.name && e.message) ? (e.name + ': ' + e.message) : e.toString();
if (file && lineNumber) {
message += ' in ' + file + ' (line ' + lineNumber + ')';
}
return message;
};
jasmine.util.htmlEscape = function(str) {
if (!str) return str;
return str.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>');
};
jasmine.util.argsToArray = function(args) {
var arrayOfArgs = [];
for (var i = 0; i < args.length; i++) arrayOfArgs.push(args[i]);
return arrayOfArgs;
};
jasmine.util.extend = function(destination, source) {
for (var property in source) destination[property] = source[property];
return destination;
};
/**
* Environment for Jasmine
*
* @constructor
*/
jasmine.Env = function() {
this.currentSpec = null;
this.currentSuite = null;
this.currentRunner_ = new jasmine.Runner(this);
this.reporter = new jasmine.MultiReporter();
this.updateInterval = jasmine.DEFAULT_UPDATE_INTERVAL;
this.defaultTimeoutInterval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
this.lastUpdate = 0;
this.specFilter = function() {
return true;
};
this.nextSpecId_ = 0;
this.nextSuiteId_ = 0;
this.equalityTesters_ = [];
// wrap matchers
this.matchersClass = function() {
jasmine.Matchers.apply(this, arguments);
};
jasmine.util.inherit(this.matchersClass, jasmine.Matchers);
jasmine.Matchers.wrapInto_(jasmine.Matchers.prototype, this.matchersClass);
};
jasmine.Env.prototype.setTimeout = jasmine.setTimeout;
jasmine.Env.prototype.clearTimeout = jasmine.clearTimeout;
jasmine.Env.prototype.setInterval = jasmine.setInterval;
jasmine.Env.prototype.clearInterval = jasmine.clearInterval;
/**
* @returns an object containing jasmine version build info, if set.
*/
jasmine.Env.prototype.version = function () {
if (jasmine.version_) {
return jasmine.version_;
} else {
throw new Error('Version not set');
}
};
/**
* @returns string containing jasmine version build info, if set.
*/
jasmine.Env.prototype.versionString = function() {
if (!jasmine.version_) {
return "version unknown";
}
var version = this.version();
var versionString = version.major + "." + version.minor + "." + version.build;
if (version.release_candidate) {
versionString += ".rc" + version.release_candidate;
}
versionString += " revision " + version.revision;
return versionString;
};
/**
* @returns a sequential integer starting at 0
*/
jasmine.Env.prototype.nextSpecId = function () {
return this.nextSpecId_++;
};
/**
* @returns a sequential integer starting at 0
*/
jasmine.Env.prototype.nextSuiteId = function () {
return this.nextSuiteId_++;
};
/**
* Register a reporter to receive status updates from Jasmine.
* @param {jasmine.Reporter} reporter An object which will receive status updates.
*/
jasmine.Env.prototype.addReporter = function(reporter) {
this.reporter.addReporter(reporter);
};
jasmine.Env.prototype.execute = function() {
this.currentRunner_.execute();
};
jasmine.Env.prototype.describe = function(description, specDefinitions) {
var suite = new jasmine.Suite(this, description, specDefinitions, this.currentSuite);
var parentSuite = this.currentSuite;
if (parentSuite) {
parentSuite.add(suite);
} else {
this.currentRunner_.add(suite);
}
this.currentSuite = suite;
var declarationError = null;
try {
specDefinitions.call(suite);
} catch(e) {
declarationError = e;
}
if (declarationError) {
this.it("encountered a declaration exception", function() {
throw declarationError;
});
}
this.currentSuite = parentSuite;
return suite;
};
jasmine.Env.prototype.beforeEach = function(beforeEachFunction) {
if (this.currentSuite) {
this.currentSuite.beforeEach(beforeEachFunction);
} else {
this.currentRunner_.beforeEach(beforeEachFunction);
}
};
jasmine.Env.prototype.currentRunner = function () {
return this.currentRunner_;
};
jasmine.Env.prototype.afterEach = function(afterEachFunction) {
if (this.currentSuite) {
this.currentSuite.afterEach(afterEachFunction);
} else {
this.currentRunner_.afterEach(afterEachFunction);
}
};
jasmine.Env.prototype.xdescribe = function(desc, specDefinitions) {
return {
execute: function() {
}
};
};
jasmine.Env.prototype.it = function(description, func) {
var spec = new jasmine.Spec(this, this.currentSuite, description);
this.currentSuite.add(spec);
this.currentSpec = spec;
if (func) {
spec.runs(func);
}
return spec;
};
jasmine.Env.prototype.xit = function(desc, func) {
return {
id: this.nextSpecId(),
runs: function() {
}
};
};
jasmine.Env.prototype.compareObjects_ = function(a, b, mismatchKeys, mismatchValues) {
if (a.__Jasmine_been_here_before__ === b && b.__Jasmine_been_here_before__ === a) {
return true;
}
a.__Jasmine_been_here_before__ = b;
b.__Jasmine_been_here_before__ = a;
var hasKey = function(obj, keyName) {
return obj !== null && obj[keyName] !== jasmine.undefined;
};
for (var property in b) {
if (!hasKey(a, property) && hasKey(b, property)) {
mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
}
}
for (property in a) {
if (!hasKey(b, property) && hasKey(a, property)) {
mismatchKeys.push("expected missing key '" + property + "', but present in actual.");
}
}
for (property in b) {
if (property == '__Jasmine_been_here_before__') continue;
if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues)) {
mismatchValues.push("'" + property + "' was '" + (b[property] ? jasmine.util.htmlEscape(b[property].toString()) : b[property]) + "' in expected, but was '" + (a[property] ? jasmine.util.htmlEscape(a[property].toString()) : a[property]) + "' in actual.");
}
}
if (jasmine.isArray_(a) && jasmine.isArray_(b) && a.length != b.length) {
mismatchValues.push("arrays were not the same length");
}
delete a.__Jasmine_been_here_before__;
delete b.__Jasmine_been_here_before__;
return (mismatchKeys.length === 0 && mismatchValues.length === 0);
};
jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
mismatchKeys = mismatchKeys || [];
mismatchValues = mismatchValues || [];
for (var i = 0; i < this.equalityTesters_.length; i++) {
var equalityTester = this.equalityTesters_[i];
var result = equalityTester(a, b, this, mismatchKeys, mismatchValues);
if (result !== jasmine.undefined) return result;
}
if (a === b) return true;
if (a === jasmine.undefined || a === null || b === jasmine.undefined || b === null) {
return (a == jasmine.undefined && b == jasmine.undefined);
}
if (jasmine.isDomNode(a) && jasmine.isDomNode(b)) {
return a === b;
}
if (a instanceof Date && b instanceof Date) {
return a.getTime() == b.getTime();
}
if (a.jasmineMatches) {
return a.jasmineMatches(b);
}
if (b.jasmineMatches) {
return b.jasmineMatches(a);
}
if (a instanceof jasmine.Matchers.ObjectContaining) {
return a.matches(b);
}
if (b instanceof jasmine.Matchers.ObjectContaining) {
return b.matches(a);
}
if (jasmine.isString_(a) && jasmine.isString_(b)) {
return (a == b);
}
if (jasmine.isNumber_(a) && jasmine.isNumber_(b)) {
return (a == b);
}
if (typeof a === "object" && typeof b === "object") {
return this.compareObjects_(a, b, mismatchKeys, mismatchValues);
}
//Straight check
return (a === b);
};
jasmine.Env.prototype.contains_ = function(haystack, needle) {
if (jasmine.isArray_(haystack)) {
for (var i = 0; i < haystack.length; i++) {
if (this.equals_(haystack[i], needle)) return true;
}
return false;
}
return haystack.indexOf(needle) >= 0;
};
jasmine.Env.prototype.addEqualityTester = function(equalityTester) {
this.equalityTesters_.push(equalityTester);
};
/** No-op base class for Jasmine reporters.
*
* @constructor
*/
jasmine.Reporter = function() {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.reportRunnerStarting = function(runner) {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.reportRunnerResults = function(runner) {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.reportSuiteResults = function(suite) {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.reportSpecStarting = function(spec) {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.reportSpecResults = function(spec) {
};
//noinspection JSUnusedLocalSymbols
jasmine.Reporter.prototype.log = function(str) {
};
/**
* Blocks are functions with executable code that make up a spec.
*
* @constructor
* @param {jasmine.Env} env
* @param {Function} func
* @param {jasmine.Spec} spec
*/
jasmine.Block = function(env, func, spec) {
this.env = env;
this.func = func;
this.spec = spec;
};
jasmine.Block.prototype.execute = function(onComplete) {
try {
this.func.apply(this.spec);
} catch (e) {
this.spec.fail(e);
}
onComplete();
};
/** JavaScript API reporter.
*
* @constructor
*/
jasmine.JsApiReporter = function() {
this.started = false;
this.finished = false;
this.suites_ = [];
this.results_ = {};
};
jasmine.JsApiReporter.prototype.reportRunnerStarting = function(runner) {
this.started = true;
var suites = runner.topLevelSuites();
for (var i = 0; i < suites.length; i++) {
var suite = suites[i];
this.suites_.push(this.summarize_(suite));
}
};
jasmine.JsApiReporter.prototype.suites = function() {
return this.suites_;
};
jasmine.JsApiReporter.prototype.summarize_ = function(suiteOrSpec) {
var isSuite = suiteOrSpec instanceof jasmine.Suite;
var summary = {
id: suiteOrSpec.id,
name: suiteOrSpec.description,
type: isSuite ? 'suite' : 'spec',
children: []
};
if (isSuite) {
var children = suiteOrSpec.children();
for (var i = 0; i < children.length; i++) {
summary.children.push(this.summarize_(children[i]));
}
}
return summary;
};
jasmine.JsApiReporter.prototype.results = function() {
return this.results_;
};
jasmine.JsApiReporter.prototype.resultsForSpec = function(specId) {
return this.results_[specId];
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.reportRunnerResults = function(runner) {
this.finished = true;
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.reportSuiteResults = function(suite) {
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.reportSpecResults = function(spec) {
this.results_[spec.id] = {
messages: spec.results().getItems(),
result: spec.results().failedCount > 0 ? "failed" : "passed"
};
};
//noinspection JSUnusedLocalSymbols
jasmine.JsApiReporter.prototype.log = function(str) {
};
jasmine.JsApiReporter.prototype.resultsForSpecs = function(specIds){
var results = {};
for (var i = 0; i < specIds.length; i++) {
var specId = specIds[i];
results[specId] = this.summarizeResult_(this.results_[specId]);
}
return results;
};
jasmine.JsApiReporter.prototype.summarizeResult_ = function(result){
var summaryMessages = [];
var messagesLength = result.messages.length;
for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
var resultMessage = result.messages[messageIndex];
summaryMessages.push({
text: resultMessage.type == 'log' ? resultMessage.toString() : jasmine.undefined,
passed: resultMessage.passed ? resultMessage.passed() : true,
type: resultMessage.type,
message: resultMessage.message,
trace: {
stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
}
});
}
return {
result : result.result,
messages : summaryMessages
};
};
/**
* @constructor
* @param {jasmine.Env} env
* @param actual
* @param {jasmine.Spec} spec
*/
jasmine.Matchers = function(env, actual, spec, opt_isNot) {
this.env = env;
this.actual = actual;
this.spec = spec;
this.isNot = opt_isNot || false;
this.reportWasCalled_ = false;
};
// todo: @deprecated as of Jasmine 0.11, remove soon [xw]
jasmine.Matchers.pp = function(str) {
throw new Error("jasmine.Matchers.pp() is no longer supported, please use jasmine.pp() instead!");
};
// todo: @deprecated Deprecated as of Jasmine 0.10. Rewrite your custom matchers to return true or false. [xw]
jasmine.Matchers.prototype.report = function(result, failing_message, details) {
throw new Error("As of jasmine 0.11, custom matchers must be implemented differently -- please see jasmine docs");
};
jasmine.Matchers.wrapInto_ = function(prototype, matchersClass) {
for (var methodName in prototype) {
if (methodName == 'report') continue;
var orig = prototype[methodName];
matchersClass.prototype[methodName] = jasmine.Matchers.matcherFn_(methodName, orig);
}
};
jasmine.Matchers.matcherFn_ = function(matcherName, matcherFunction) {
return function() {
var matcherArgs = jasmine.util.argsToArray(arguments);
var result = matcherFunction.apply(this, arguments);
if (this.isNot) {
result = !result;
}
if (this.reportWasCalled_) return result;
var message;
if (!result) {
if (this.message) {
message = this.message.apply(this, arguments);
if (jasmine.isArray_(message)) {
message = message[this.isNot ? 1 : 0];
}
} else {
var englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); });
message = "Expected " + jasmine.pp(this.actual) + (this.isNot ? " not " : " ") + englishyPredicate;
if (matcherArgs.length > 0) {
for (var i = 0; i < matcherArgs.length; i++) {
if (i > 0) message += ",";
message += " " + jasmine.pp(matcherArgs[i]);
}
}
message += ".";
}
}
var expectationResult = new jasmine.ExpectationResult({
matcherName: matcherName,
passed: result,
expected: matcherArgs.length > 1 ? matcherArgs : matcherArgs[0],
actual: this.actual,
message: message
});
this.spec.addMatcherResult(expectationResult);
return jasmine.undefined;
};
};
/**
* toBe: compares the actual to the expected using ===
* @param expected
*/
jasmine.Matchers.prototype.toBe = function(expected) {
return this.actual === expected;
};
/**
* toNotBe: compares the actual to the expected using !==
* @param expected
* @deprecated as of 1.0. Use not.toBe() instead.
*/
jasmine.Matchers.prototype.toNotBe = function(expected) {
return this.actual !== expected;
};
/**
* toEqual: compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc.
*
* @param expected
*/
jasmine.Matchers.prototype.toEqual = function(expected) {
return this.env.equals_(this.actual, expected);
};
/**
* toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
* @param expected
* @deprecated as of 1.0. Use not.toEqual() instead.
*/
jasmine.Matchers.prototype.toNotEqual = function(expected) {
return !this.env.equals_(this.actual, expected);
};
/**
* Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes
* a pattern or a String.
*
* @param expected
*/
jasmine.Matchers.prototype.toMatch = function(expected) {
return new RegExp(expected).test(this.actual);
};
/**
* Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch
* @param expected
* @deprecated as of 1.0. Use not.toMatch() instead.
*/
jasmine.Matchers.prototype.toNotMatch = function(expected) {
return !(new RegExp(expected).test(this.actual));
};
/**
* Matcher that compares the actual to jasmine.undefined.
*/
jasmine.Matchers.prototype.toBeDefined = function() {
return (this.actual !== jasmine.undefined);
};
/**
* Matcher that compares the actual to jasmine.undefined.
*/
jasmine.Matchers.prototype.toBeUndefined = function() {
return (this.actual === jasmine.undefined);
};
/**
* Matcher that compares the actual to null.
*/
jasmine.Matchers.prototype.toBeNull = function() {
return (this.actual === null);
};
/**
* Matcher that boolean not-nots the actual.
*/
jasmine.Matchers.prototype.toBeTruthy = function() {
return !!this.actual;
};
/**
* Matcher that boolean nots the actual.
*/
jasmine.Matchers.prototype.toBeFalsy = function() {
return !this.actual;
};
/**
* Matcher that checks to see if the actual, a Jasmine spy, was called.
*/
jasmine.Matchers.prototype.toHaveBeenCalled = function() {
if (arguments.length > 0) {
throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith');
}
if (!jasmine.isSpy(this.actual)) {
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function() {
return [
"Expected spy " + this.actual.identity + " to have been called.",
"Expected spy " + this.actual.identity + " not to have been called."
];
};
return this.actual.wasCalled;
};
/** @deprecated Use expect(xxx).toHaveBeenCalled() instead */
jasmine.Matchers.prototype.wasCalled = jasmine.Matchers.prototype.toHaveBeenCalled;
/**
* Matcher that checks to see if the actual, a Jasmine spy, was not called.
*
* @deprecated Use expect(xxx).not.toHaveBeenCalled() instead
*/
jasmine.Matchers.prototype.wasNotCalled = function() {
if (arguments.length > 0) {
throw new Error('wasNotCalled does not take arguments');
}
if (!jasmine.isSpy(this.actual)) {
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function() {
return [
"Expected spy " + this.actual.identity + " to not have been called.",
"Expected spy " + this.actual.identity + " to have been called."
];
};
return !this.actual.wasCalled;
};
/**
* Matcher that checks to see if the actual, a Jasmine spy, was called with a set of parameters.
*
* @example
*
*/
jasmine.Matchers.prototype.toHaveBeenCalledWith = function() {
var expectedArgs = jasmine.util.argsToArray(arguments);
if (!jasmine.isSpy(this.actual)) {
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function() {
if (this.actual.callCount === 0) {
// todo: what should the failure message for .not.toHaveBeenCalledWith() be? is this right? test better. [xw]
return [
"Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but it was never called.",
"Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but it was."
];
} else {
return [
"Expected spy " + this.actual.identity + " to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall),
"Expected spy " + this.actual.identity + " not to have been called with " + jasmine.pp(expectedArgs) + " but was called with " + jasmine.pp(this.actual.argsForCall)
];
}
};
return this.env.contains_(this.actual.argsForCall, expectedArgs);
};
/** @deprecated Use expect(xxx).toHaveBeenCalledWith() instead */
jasmine.Matchers.prototype.wasCalledWith = jasmine.Matchers.prototype.toHaveBeenCalledWith;
/** @deprecated Use expect(xxx).not.toHaveBeenCalledWith() instead */
jasmine.Matchers.prototype.wasNotCalledWith = function() {
var expectedArgs = jasmine.util.argsToArray(arguments);
if (!jasmine.isSpy(this.actual)) {
throw new Error('Expected a spy, but got ' + jasmine.pp(this.actual) + '.');
}
this.message = function() {
return [
"Expected spy not to have been called with " + jasmine.pp(expectedArgs) + " but it was",
"Expected spy to have been called with " + jasmine.pp(expectedArgs) + " but it was"
];
};
return !this.env.contains_(this.actual.argsForCall, expectedArgs);
};
/**
* Matcher that checks that the expected item is an element in the actual Array.
*
* @param {Object} expected
*/
jasmine.Matchers.prototype.toContain = function(expected) {
return this.env.contains_(this.actual, expected);
};
/**
* Matcher that checks that the expected item is NOT an element in the actual Array.
*
* @param {Object} expected
* @deprecated as of 1.0. Use not.toContain() instead.
*/
jasmine.Matchers.prototype.toNotContain = function(expected) {
return !this.env.contains_(this.actual, expected);
};
jasmine.Matchers.prototype.toBeLessThan = function(expected) {
return this.actual < expected;
};
jasmine.Matchers.prototype.toBeGreaterThan = function(expected) {
return this.actual > expected;
};
/**
* Matcher that checks that the expected item is equal to the actual item
* up to a given level of decimal precision (default 2).
*
* @param {Number} expected
* @param {Number} precision
*/
jasmine.Matchers.prototype.toBeCloseTo = function(expected, precision) {
if (!(precision === 0)) {
precision = precision || 2;
}
var multiplier = Math.pow(10, precision);
var actual = Math.round(this.actual * multiplier);
expected = Math.round(expected * multiplier);
return expected == actual;
};
/**
* Matcher that checks that the expected exception was thrown by the actual.
*
* @param {String} expected
*/
jasmine.Matchers.prototype.toThrow = function(expected) {
var result = false;
var exception;
if (typeof this.actual != 'function') {
throw new Error('Actual is not a function');
}
try {
this.actual();
} catch (e) {
exception = e;
}
if (exception) {
result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected));
}
var not = this.isNot ? "not " : "";
this.message = function() {
if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
return ["Expected function " + not + "to throw", expected ? expected.message || expected : "an exception", ", but it threw", exception.message || exception].join(' ');
} else {
return "Expected function to throw an exception.";
}
};
return result;
};
jasmine.Matchers.Any = function(expectedClass) {
this.expectedClass = expectedClass;
};
jasmine.Matchers.Any.prototype.jasmineMatches = function(other) {
if (this.expectedClass == String) {
return typeof other == 'string' || other instanceof String;
}
if (this.expectedClass == Number) {
return typeof other == 'number' || other instanceof Number;
}
if (this.expectedClass == Function) {
return typeof other == 'function' || other instanceof Function;
}
if (this.expectedClass == Object) {
return typeof other == 'object';
}
return other instanceof this.expectedClass;
};
jasmine.Matchers.Any.prototype.jasmineToString = function() {
return '<jasmine.any(' + this.expectedClass + ')>';
};
jasmine.Matchers.ObjectContaining = function (sample) {
this.sample = sample;
};
jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
mismatchKeys = mismatchKeys || [];
mismatchValues = mismatchValues || [];
var env = jasmine.getEnv();
var hasKey = function(obj, keyName) {
return obj != null && obj[keyName] !== jasmine.undefined;
};
for (var property in this.sample) {
if (!hasKey(other, property) && hasKey(this.sample, property)) {
mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
}
else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) {
mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual.");
}
}
return (mismatchKeys.length === 0 && mismatchValues.length === 0);
};
jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
return "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>";
};
// Mock setTimeout, clearTimeout
// Contributed by Pivotal Computer Systems, www.pivotalsf.com
jasmine.FakeTimer = function() {
this.reset();
var self = this;
self.setTimeout = function(funcToCall, millis) {
self.timeoutsMade++;
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, false);
return self.timeoutsMade;
};
self.setInterval = function(funcToCall, millis) {
self.timeoutsMade++;
self.scheduleFunction(self.timeoutsMade, funcToCall, millis, true);
return self.timeoutsMade;
};
self.clearTimeout = function(timeoutKey) {
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
};
self.clearInterval = function(timeoutKey) {
self.scheduledFunctions[timeoutKey] = jasmine.undefined;
};
};
jasmine.FakeTimer.prototype.reset = function() {
this.timeoutsMade = 0;
this.scheduledFunctions = {};
this.nowMillis = 0;
};
jasmine.FakeTimer.prototype.tick = function(millis) {
var oldMillis = this.nowMillis;
var newMillis = oldMillis + millis;
this.runFunctionsWithinRange(oldMillis, newMillis);
this.nowMillis = newMillis;
};
jasmine.FakeTimer.prototype.runFunctionsWithinRange = function(oldMillis, nowMillis) {
var scheduledFunc;
var funcsToRun = [];
for (var timeoutKey in this.scheduledFunctions) {
scheduledFunc = this.scheduledFunctions[timeoutKey];
if (scheduledFunc != jasmine.undefined &&
scheduledFunc.runAtMillis >= oldMillis &&
scheduledFunc.runAtMillis <= nowMillis) {
funcsToRun.push(scheduledFunc);
this.scheduledFunctions[timeoutKey] = jasmine.undefined;
}
}
if (funcsToRun.length > 0) {
funcsToRun.sort(function(a, b) {
return a.runAtMillis - b.runAtMillis;
});
for (var i = 0; i < funcsToRun.length; ++i) {
try {
var funcToRun = funcsToRun[i];
this.nowMillis = funcToRun.runAtMillis;
funcToRun.funcToCall();
if (funcToRun.recurring) {
this.scheduleFunction(funcToRun.timeoutKey,
funcToRun.funcToCall,
funcToRun.millis,
true);
}
} catch(e) {
}
}
this.runFunctionsWithinRange(oldMillis, nowMillis);
}
};
jasmine.FakeTimer.prototype.scheduleFunction = function(timeoutKey, funcToCall, millis, recurring) {
this.scheduledFunctions[timeoutKey] = {
runAtMillis: this.nowMillis + millis,
funcToCall: funcToCall,
recurring: recurring,
timeoutKey: timeoutKey,
millis: millis
};
};
/**
* @namespace
*/
jasmine.Clock = {
defaultFakeTimer: new jasmine.FakeTimer(),
reset: function() {
jasmine.Clock.assertInstalled();
jasmine.Clock.defaultFakeTimer.reset();
},
tick: function(millis) {
jasmine.Clock.assertInstalled();
jasmine.Clock.defaultFakeTimer.tick(millis);
},
runFunctionsWithinRange: function(oldMillis, nowMillis) {
jasmine.Clock.defaultFakeTimer.runFunctionsWithinRange(oldMillis, nowMillis);
},
scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
jasmine.Clock.defaultFakeTimer.scheduleFunction(timeoutKey, funcToCall, millis, recurring);
},
useMock: function() {
if (!jasmine.Clock.isInstalled()) {
var spec = jasmine.getEnv().currentSpec;
spec.after(jasmine.Clock.uninstallMock);
jasmine.Clock.installMock();
}
},
installMock: function() {
jasmine.Clock.installed = jasmine.Clock.defaultFakeTimer;
},
uninstallMock: function() {
jasmine.Clock.assertInstalled();
jasmine.Clock.installed = jasmine.Clock.real;
},
real: {
setTimeout: jasmine.getGlobal().setTimeout,
clearTimeout: jasmine.getGlobal().clearTimeout,
setInterval: jasmine.getGlobal().setInterval,
clearInterval: jasmine.getGlobal().clearInterval
},
assertInstalled: function() {
if (!jasmine.Clock.isInstalled()) {
throw new Error("Mock clock is not installed, use jasmine.Clock.useMock()");
}
},
isInstalled: function() {
return jasmine.Clock.installed == jasmine.Clock.defaultFakeTimer;
},
installed: null
};
jasmine.Clock.installed = jasmine.Clock.real;
//else for IE support
jasmine.getGlobal().setTimeout = function(funcToCall, millis) {
if (jasmine.Clock.installed.setTimeout.apply) {
return jasmine.Clock.installed.setTimeout.apply(this, arguments);
} else {
return jasmine.Clock.installed.setTimeout(funcToCall, millis);
}
};
jasmine.getGlobal().setInterval = function(funcToCall, millis) {
if (jasmine.Clock.installed.setInterval.apply) {
return jasmine.Clock.installed.setInterval.apply(this, arguments);
} else {
return jasmine.Clock.installed.setInterval(funcToCall, millis);
}
};
jasmine.getGlobal().clearTimeout = function(timeoutKey) {
if (jasmine.Clock.installed.clearTimeout.apply) {
return jasmine.Clock.installed.clearTimeout.apply(this, arguments);
} else {
return jasmine.Clock.installed.clearTimeout(timeoutKey);
}
};
jasmine.getGlobal().clearInterval = function(timeoutKey) {
if (jasmine.Clock.installed.clearTimeout.apply) {
return jasmine.Clock.installed.clearInterval.apply(this, arguments);
} else {
return jasmine.Clock.installed.clearInterval(timeoutKey);
}
};
/**
* @constructor
*/
jasmine.MultiReporter = function() {
this.subReporters_ = [];
};
jasmine.util.inherit(jasmine.MultiReporter, jasmine.Reporter);
jasmine.MultiReporter.prototype.addReporter = function(reporter) {
this.subReporters_.push(reporter);
};
(function() {
var functionNames = [
"reportRunnerStarting",
"reportRunnerResults",
"reportSuiteResults",
"reportSpecStarting",
"reportSpecResults",
"log"
];
for (var i = 0; i < functionNames.length; i++) {
var functionName = functionNames[i];
jasmine.MultiReporter.prototype[functionName] = (function(functionName) {
return function() {
for (var j = 0; j < this.subReporters_.length; j++) {
var subReporter = this.subReporters_[j];
if (subReporter[functionName]) {
subReporter[functionName].apply(subReporter, arguments);
}
}
};
})(functionName);
}
})();
/**
* Holds results for a set of Jasmine spec. Allows for the results array to hold another jasmine.NestedResults
*
* @constructor
*/
jasmine.NestedResults = function() {
/**
* The total count of results
*/
this.totalCount = 0;
/**
* Number of passed results
*/
this.passedCount = 0;
/**
* Number of failed results
*/
this.failedCount = 0;
/**
* Was this suite/spec skipped?
*/
this.skipped = false;
/**
* @ignore
*/
this.items_ = [];
};
/**
* Roll up the result counts.
*
* @param result
*/
jasmine.NestedResults.prototype.rollupCounts = function(result) {
this.totalCount += result.totalCount;
this.passedCount += result.passedCount;
this.failedCount += result.failedCount;
};
/**
* Adds a log message.
* @param values Array of message parts which will be concatenated later.
*/
jasmine.NestedResults.prototype.log = function(values) {
this.items_.push(new jasmine.MessageResult(values));
};
/**
* Getter for the results: message & results.
*/
jasmine.NestedResults.prototype.getItems = function() {
return this.items_;
};
/**
* Adds a result, tracking counts (total, passed, & failed)
* @param {jasmine.ExpectationResult|jasmine.NestedResults} result
*/
jasmine.NestedResults.prototype.addResult = function(result) {
if (result.type != 'log') {
if (result.items_) {
this.rollupCounts(result);
} else {
this.totalCount++;
if (result.passed()) {
this.passedCount++;
} else {
this.failedCount++;
}
}
}
this.items_.push(result);
};
/**
* @returns {Boolean} True if <b>everything</b> below passed
*/
jasmine.NestedResults.prototype.passed = function() {
return this.passedCount === this.totalCount;
};
/**
* Base class for pretty printing for expectation results.
*/
jasmine.PrettyPrinter = function() {
this.ppNestLevel_ = 0;
};
/**
* Formats a value in a nice, human-readable string.
*
* @param value
*/
jasmine.PrettyPrinter.prototype.format = function(value) {
if (this.ppNestLevel_ > 40) {
throw new Error('jasmine.PrettyPrinter: format() nested too deeply!');
}
this.ppNestLevel_++;
try {
if (value === jasmine.undefined) {
this.emitScalar('undefined');
} else if (value === null) {
this.emitScalar('null');
} else if (value === jasmine.getGlobal()) {
this.emitScalar('<global>');
} else if (value.jasmineToString) {
this.emitScalar(value.jasmineToString());
} else if (typeof value === 'string') {
this.emitString(value);
} else if (jasmine.isSpy(value)) {
this.emitScalar("spy on " + value.identity);
} else if (value instanceof RegExp) {
this.emitScalar(value.toString());
} else if (typeof value === 'function') {
this.emitScalar('Function');
} else if (typeof value.nodeType === 'number') {
this.emitScalar('HTMLNode');
} else if (value instanceof Date) {
this.emitScalar('Date(' + value + ')');
} else if (value.__Jasmine_been_here_before__) {
this.emitScalar('<circular reference: ' + (jasmine.isArray_(value) ? 'Array' : 'Object') + '>');
} else if (jasmine.isArray_(value) || typeof value == 'object') {
value.__Jasmine_been_here_before__ = true;
if (jasmine.isArray_(value)) {
this.emitArray(value);
} else {
this.emitObject(value);
}
delete value.__Jasmine_been_here_before__;
} else {
this.emitScalar(value.toString());
}
} finally {
this.ppNestLevel_--;
}
};
jasmine.PrettyPrinter.prototype.iterateObject = function(obj, fn) {
for (var property in obj) {
if (property == '__Jasmine_been_here_before__') continue;
fn(property, obj.__lookupGetter__ ? (obj.__lookupGetter__(property) !== jasmine.undefined &&
obj.__lookupGetter__(property) !== null) : false);
}
};
jasmine.PrettyPrinter.prototype.emitArray = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitObject = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitScalar = jasmine.unimplementedMethod_;
jasmine.PrettyPrinter.prototype.emitString = jasmine.unimplementedMethod_;
jasmine.StringPrettyPrinter = function() {
jasmine.PrettyPrinter.call(this);
this.string = '';
};
jasmine.util.inherit(jasmine.StringPrettyPrinter, jasmine.PrettyPrinter);
jasmine.StringPrettyPrinter.prototype.emitScalar = function(value) {
this.append(value);
};
jasmine.StringPrettyPrinter.prototype.emitString = function(value) {
this.append("'" + value + "'");
};
jasmine.StringPrettyPrinter.prototype.emitArray = function(array) {
this.append('[ ');
for (var i = 0; i < array.length; i++) {
if (i > 0) {
this.append(', ');
}
this.format(array[i]);
}
this.append(' ]');
};
jasmine.StringPrettyPrinter.prototype.emitObject = function(obj) {
var self = this;
this.append('{ ');
var first = true;
this.iterateObject(obj, function(property, isGetter) {
if (first) {
first = false;
} else {
self.append(', ');
}
self.append(property);
self.append(' : ');
if (isGetter) {
self.append('<getter>');
} else {
self.format(obj[property]);
}
});
this.append(' }');
};
jasmine.StringPrettyPrinter.prototype.append = function(value) {
this.string += value;
};
jasmine.Queue = function(env) {
this.env = env;
this.blocks = [];
this.running = false;
this.index = 0;
this.offset = 0;
this.abort = false;
};
jasmine.Queue.prototype.addBefore = function(block) {
this.blocks.unshift(block);
};
jasmine.Queue.prototype.add = function(block) {
this.blocks.push(block);
};
jasmine.Queue.prototype.insertNext = function(block) {
this.blocks.splice((this.index + this.offset + 1), 0, block);
this.offset++;
};
jasmine.Queue.prototype.start = function(onComplete) {
this.running = true;
this.onComplete = onComplete;
this.next_();
};
jasmine.Queue.prototype.isRunning = function() {
return this.running;
};
jasmine.Queue.LOOP_DONT_RECURSE = true;
jasmine.Queue.prototype.next_ = function() {
var self = this;
var goAgain = true;
while (goAgain) {
goAgain = false;
if (self.index < self.blocks.length && !this.abort) {
var calledSynchronously = true;
var completedSynchronously = false;
var onComplete = function () {
if (jasmine.Queue.LOOP_DONT_RECURSE && calledSynchronously) {
completedSynchronously = true;
return;
}
if (self.blocks[self.index].abort) {
self.abort = true;
}
self.offset = 0;
self.index++;
var now = new Date().getTime();
if (self.env.updateInterval && now - self.env.lastUpdate > self.env.updateInterval) {
self.env.lastUpdate = now;
self.env.setTimeout(function() {
self.next_();
}, 0);
} else {
if (jasmine.Queue.LOOP_DONT_RECURSE && completedSynchronously) {
goAgain = true;
} else {
self.next_();
}
}
};
self.blocks[self.index].execute(onComplete);
calledSynchronously = false;
if (completedSynchronously) {
onComplete();
}
} else {
self.running = false;
if (self.onComplete) {
self.onComplete();
}
}
}
};
jasmine.Queue.prototype.results = function() {
var results = new jasmine.NestedResults();
for (var i = 0; i < this.blocks.length; i++) {
if (this.blocks[i].results) {
results.addResult(this.blocks[i].results());
}
}
return results;
};
/**
* Runner
*
* @constructor
* @param {jasmine.Env} env
*/
jasmine.Runner = function(env) {
var self = this;
self.env = env;
self.queue = new jasmine.Queue(env);
self.before_ = [];
self.after_ = [];
self.suites_ = [];
};
jasmine.Runner.prototype.execute = function() {
var self = this;
if (self.env.reporter.reportRunnerStarting) {
self.env.reporter.reportRunnerStarting(this);
}
self.queue.start(function () {
self.finishCallback();
});
};
jasmine.Runner.prototype.beforeEach = function(beforeEachFunction) {
beforeEachFunction.typeName = 'beforeEach';
this.before_.splice(0,0,beforeEachFunction);
};
jasmine.Runner.prototype.afterEach = function(afterEachFunction) {
afterEachFunction.typeName = 'afterEach';
this.after_.splice(0,0,afterEachFunction);
};
jasmine.Runner.prototype.finishCallback = function() {
this.env.reporter.reportRunnerResults(this);
};
jasmine.Runner.prototype.addSuite = function(suite) {
this.suites_.push(suite);
};
jasmine.Runner.prototype.add = function(block) {
if (block instanceof jasmine.Suite) {
this.addSuite(block);
}
this.queue.add(block);
};
jasmine.Runner.prototype.specs = function () {
var suites = this.suites();
var specs = [];
for (var i = 0; i < suites.length; i++) {
specs = specs.concat(suites[i].specs());
}
return specs;
};
jasmine.Runner.prototype.suites = function() {
return this.suites_;
};
jasmine.Runner.prototype.topLevelSuites = function() {
var topLevelSuites = [];
for (var i = 0; i < this.suites_.length; i++) {
if (!this.suites_[i].parentSuite) {
topLevelSuites.push(this.suites_[i]);
}
}
return topLevelSuites;
};
jasmine.Runner.prototype.results = function() {
return this.queue.results();
};
/**
* Internal representation of a Jasmine specification, or test.
*
* @constructor
* @param {jasmine.Env} env
* @param {jasmine.Suite} suite
* @param {String} description
*/
jasmine.Spec = function(env, suite, description) {
if (!env) {
throw new Error('jasmine.Env() required');
}
if (!suite) {
throw new Error('jasmine.Suite() required');
}
var spec = this;
spec.id = env.nextSpecId ? env.nextSpecId() : null;
spec.env = env;
spec.suite = suite;
spec.description = description;
spec.queue = new jasmine.Queue(env);
spec.afterCallbacks = [];
spec.spies_ = [];
spec.results_ = new jasmine.NestedResults();
spec.results_.description = description;
spec.matchersClass = null;
};
jasmine.Spec.prototype.getFullName = function() {
return this.suite.getFullName() + ' ' + this.description + '.';
};
jasmine.Spec.prototype.results = function() {
return this.results_;
};
/**
* All parameters are pretty-printed and concatenated together, then written to the spec's output.
*
* Be careful not to leave calls to <code>jasmine.log</code> in production code.
*/
jasmine.Spec.prototype.log = function() {
return this.results_.log(arguments);
};
jasmine.Spec.prototype.runs = function (func) {
var block = new jasmine.Block(this.env, func, this);
this.addToQueue(block);
return this;
};
jasmine.Spec.prototype.addToQueue = function (block) {
if (this.queue.isRunning()) {
this.queue.insertNext(block);
} else {
this.queue.add(block);
}
};
/**
* @param {jasmine.ExpectationResult} result
*/
jasmine.Spec.prototype.addMatcherResult = function(result) {
this.results_.addResult(result);
};
jasmine.Spec.prototype.expect = function(actual) {
var positive = new (this.getMatchersClass_())(this.env, actual, this);
positive.not = new (this.getMatchersClass_())(this.env, actual, this, true);
return positive;
};
/**
* Waits a fixed time period before moving to the next block.
*
* @deprecated Use waitsFor() instead
* @param {Number} timeout milliseconds to wait
*/
jasmine.Spec.prototype.waits = function(timeout) {
var waitsFunc = new jasmine.WaitsBlock(this.env, timeout, this);
this.addToQueue(waitsFunc);
return this;
};
/**
* Waits for the latchFunction to return true before proceeding to the next block.
*
* @param {Function} latchFunction
* @param {String} optional_timeoutMessage
* @param {Number} optional_timeout
*/
jasmine.Spec.prototype.waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
var latchFunction_ = null;
var optional_timeoutMessage_ = null;
var optional_timeout_ = null;
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
switch (typeof arg) {
case 'function':
latchFunction_ = arg;
break;
case 'string':
optional_timeoutMessage_ = arg;
break;
case 'number':
optional_timeout_ = arg;
break;
}
}
var waitsForFunc = new jasmine.WaitsForBlock(this.env, optional_timeout_, latchFunction_, optional_timeoutMessage_, this);
this.addToQueue(waitsForFunc);
return this;
};
jasmine.Spec.prototype.fail = function (e) {
var expectationResult = new jasmine.ExpectationResult({
passed: false,
message: e ? jasmine.util.formatException(e) : 'Exception',
trace: { stack: e.stack }
});
this.results_.addResult(expectationResult);
};
jasmine.Spec.prototype.getMatchersClass_ = function() {
return this.matchersClass || this.env.matchersClass;
};
jasmine.Spec.prototype.addMatchers = function(matchersPrototype) {
var parent = this.getMatchersClass_();
var newMatchersClass = function() {
parent.apply(this, arguments);
};
jasmine.util.inherit(newMatchersClass, parent);
jasmine.Matchers.wrapInto_(matchersPrototype, newMatchersClass);
this.matchersClass = newMatchersClass;
};
jasmine.Spec.prototype.finishCallback = function() {
this.env.reporter.reportSpecResults(this);
};
jasmine.Spec.prototype.finish = function(onComplete) {
this.removeAllSpies();
this.finishCallback();
if (onComplete) {
onComplete();
}
};
jasmine.Spec.prototype.after = function(doAfter) {
if (this.queue.isRunning()) {
this.queue.add(new jasmine.Block(this.env, doAfter, this));
} else {
this.afterCallbacks.unshift(doAfter);
}
};
jasmine.Spec.prototype.execute = function(onComplete) {
var spec = this;
if (!spec.env.specFilter(spec)) {
spec.results_.skipped = true;
spec.finish(onComplete);
return;
}
this.env.reporter.reportSpecStarting(this);
spec.env.currentSpec = spec;
spec.addBeforesAndAftersToQueue();
spec.queue.start(function () {
spec.finish(onComplete);
});
};
jasmine.Spec.prototype.addBeforesAndAftersToQueue = function() {
var runner = this.env.currentRunner();
var i;
for (var suite = this.suite; suite; suite = suite.parentSuite) {
for (i = 0; i < suite.before_.length; i++) {
this.queue.addBefore(new jasmine.Block(this.env, suite.before_[i], this));
}
}
for (i = 0; i < runner.before_.length; i++) {
this.queue.addBefore(new jasmine.Block(this.env, runner.before_[i], this));
}
for (i = 0; i < this.afterCallbacks.length; i++) {
this.queue.add(new jasmine.Block(this.env, this.afterCallbacks[i], this));
}
for (suite = this.suite; suite; suite = suite.parentSuite) {
for (i = 0; i < suite.after_.length; i++) {
this.queue.add(new jasmine.Block(this.env, suite.after_[i], this));
}
}
for (i = 0; i < runner.after_.length; i++) {
this.queue.add(new jasmine.Block(this.env, runner.after_[i], this));
}
};
jasmine.Spec.prototype.explodes = function() {
throw 'explodes function should not have been called';
};
jasmine.Spec.prototype.spyOn = function(obj, methodName, ignoreMethodDoesntExist) {
if (obj == jasmine.undefined) {
throw "spyOn could not find an object to spy upon for " + methodName + "()";
}
if (!ignoreMethodDoesntExist && obj[methodName] === jasmine.undefined) {
throw methodName + '() method does not exist';
}
if (!ignoreMethodDoesntExist && obj[methodName] && obj[methodName].isSpy) {
throw new Error(methodName + ' has already been spied upon');
}
var spyObj = jasmine.createSpy(methodName);
this.spies_.push(spyObj);
spyObj.baseObj = obj;
spyObj.methodName = methodName;
spyObj.originalValue = obj[methodName];
obj[methodName] = spyObj;
return spyObj;
};
jasmine.Spec.prototype.removeAllSpies = function() {
for (var i = 0; i < this.spies_.length; i++) {
var spy = this.spies_[i];
spy.baseObj[spy.methodName] = spy.originalValue;
}
this.spies_ = [];
};
/**
* Internal representation of a Jasmine suite.
*
* @constructor
* @param {jasmine.Env} env
* @param {String} description
* @param {Function} specDefinitions
* @param {jasmine.Suite} parentSuite
*/
jasmine.Suite = function(env, description, specDefinitions, parentSuite) {
var self = this;
self.id = env.nextSuiteId ? env.nextSuiteId() : null;
self.description = description;
self.queue = new jasmine.Queue(env);
self.parentSuite = parentSuite;
self.env = env;
self.before_ = [];
self.after_ = [];
self.children_ = [];
self.suites_ = [];
self.specs_ = [];
};
jasmine.Suite.prototype.getFullName = function() {
var fullName = this.description;
for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) {
fullName = parentSuite.description + ' ' + fullName;
}
return fullName;
};
jasmine.Suite.prototype.finish = function(onComplete) {
this.env.reporter.reportSuiteResults(this);
this.finished = true;
if (typeof(onComplete) == 'function') {
onComplete();
}
};
jasmine.Suite.prototype.beforeEach = function(beforeEachFunction) {
beforeEachFunction.typeName = 'beforeEach';
this.before_.unshift(beforeEachFunction);
};
jasmine.Suite.prototype.afterEach = function(afterEachFunction) {
afterEachFunction.typeName = 'afterEach';
this.after_.unshift(afterEachFunction);
};
jasmine.Suite.prototype.results = function() {
return this.queue.results();
};
jasmine.Suite.prototype.add = function(suiteOrSpec) {
this.children_.push(suiteOrSpec);
if (suiteOrSpec instanceof jasmine.Suite) {
this.suites_.push(suiteOrSpec);
this.env.currentRunner().addSuite(suiteOrSpec);
} else {
this.specs_.push(suiteOrSpec);
}
this.queue.add(suiteOrSpec);
};
jasmine.Suite.prototype.specs = function() {
return this.specs_;
};
jasmine.Suite.prototype.suites = function() {
return this.suites_;
};
jasmine.Suite.prototype.children = function() {
return this.children_;
};
jasmine.Suite.prototype.execute = function(onComplete) {
var self = this;
this.queue.start(function () {
self.finish(onComplete);
});
};
jasmine.WaitsBlock = function(env, timeout, spec) {
this.timeout = timeout;
jasmine.Block.call(this, env, null, spec);
};
jasmine.util.inherit(jasmine.WaitsBlock, jasmine.Block);
jasmine.WaitsBlock.prototype.execute = function (onComplete) {
if (jasmine.VERBOSE) {
this.env.reporter.log('>> Jasmine waiting for ' + this.timeout + ' ms...');
}
this.env.setTimeout(function () {
onComplete();
}, this.timeout);
};
/**
* A block which waits for some condition to become true, with timeout.
*
* @constructor
* @extends jasmine.Block
* @param {jasmine.Env} env The Jasmine environment.
* @param {Number} timeout The maximum time in milliseconds to wait for the condition to become true.
* @param {Function} latchFunction A function which returns true when the desired condition has been met.
* @param {String} message The message to display if the desired condition hasn't been met within the given time period.
* @param {jasmine.Spec} spec The Jasmine spec.
*/
jasmine.WaitsForBlock = function(env, timeout, latchFunction, message, spec) {
this.timeout = timeout || env.defaultTimeoutInterval;
this.latchFunction = latchFunction;
this.message = message;
this.totalTimeSpentWaitingForLatch = 0;
jasmine.Block.call(this, env, null, spec);
};
jasmine.util.inherit(jasmine.WaitsForBlock, jasmine.Block);
jasmine.WaitsForBlock.TIMEOUT_INCREMENT = 10;
jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
if (jasmine.VERBOSE) {
this.env.reporter.log('>> Jasmine waiting for ' + (this.message || 'something to happen'));
}
var latchFunctionResult;
try {
latchFunctionResult = this.latchFunction.apply(this.spec);
} catch (e) {
this.spec.fail(e);
onComplete();
return;
}
if (latchFunctionResult) {
onComplete();
} else if (this.totalTimeSpentWaitingForLatch >= this.timeout) {
var message = 'timed out after ' + this.timeout + ' msec waiting for ' + (this.message || 'something to happen');
this.spec.fail({
name: 'timeout',
message: message
});
this.abort = true;
onComplete();
} else {
this.totalTimeSpentWaitingForLatch += jasmine.WaitsForBlock.TIMEOUT_INCREMENT;
var self = this;
this.env.setTimeout(function() {
self.execute(onComplete);
}, jasmine.WaitsForBlock.TIMEOUT_INCREMENT);
}
};
jasmine.version_= {
"major": 1,
"minor": 2,
"build": 0,
"revision": 1337005947
};
================================================
FILE: lib/jquery-1.7.2.js
================================================
/*!
* jQuery JavaScript Library v1.7.2
* http://jquery.com/
*
* Copyright 2011, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2011, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Wed Mar 21 12:46:34 2012 -0700
*/
(function( window, undefined ) {
// Use the correct document accordingly with window argument (sandbox)
var document = window.document,
navigator = window.navigator,
location = window.location;
var jQuery = (function() {
// Define a local copy of jQuery
var jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
},
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,
// Map over the $ in case of overwrite
_$ = window.$,
// A central reference to the root jQuery(document)
rootjQuery,
// A simple way to check for HTML strings or ID strings
// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
// Check if a string has a non-whitespace character in it
rnotwhite = /\S/,
// Used for trimming whitespace
trimLeft = /^\s+/,
trimRight = /\s+$/,
// Match a standalone tag
rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
// JSON RegExp
rvalidchars = /^[\],:{}\s]*$/,
rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
// Useragent RegExp
rwebkit = /(webkit)[ \/]([\w.]+)/,
ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
rmsie = /(msie) ([\w.]+)/,
rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
// Matches dashed string for camelizing
rdashAlpha = /-([a-z]|[0-9])/ig,
rmsPrefix = /^-ms-/,
// Used by jQuery.camelCase as callback to replace()
fcamelCase = function( all, letter ) {
return ( letter + "" ).toUpperCase();
},
// Keep a UserAgent string for use with jQuery.browser
userAgent = navigator.userAgent,
// For matching the engine and version of the browser
browserMatch,
// The deferred used on DOM ready
readyList,
// The ready event handler
DOMContentLoaded,
// Save a reference to some core methods
toString = Object.prototype.toString,
hasOwn = Object.prototype.hasOwnProperty,
push = Array.prototype.push,
slice = Array.prototype.slice,
trim = String.prototype.trim,
indexOf = Array.prototype.indexOf,
// [[Class]] -> type pairs
class2type = {};
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ) {
var match, elem, ret, doc;
// Handle $(""), $(null), or $(undefined)
if ( !selector ) {
return this;
}
// Handle $(DOMElement)
if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
}
// The body element only exists once, optimize finding it
if ( selector === "body" && !context && document.body ) {
this.context = document;
this[0] = document.body;
this.selector = selector;
this.length = 1;
return this;
}
// Handle HTML strings
if ( typeof selector === "string" ) {
// Are we dealing with HTML string or an ID?
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [ null, selector, null ];
} else {
match = quickExpr.exec( selector );
}
// Verify a match, and that no context was specified for #id
if ( match && (match[1] || !context) ) {
// HANDLE: $(html) -> $(array)
if ( match[1] ) {
context = context instanceof jQuery ? context[0] : context;
doc = ( context ? context.ownerDocument || context : document );
// If a single string is passed in and it's a single tag
// just do a createElement and skip the rest
ret = rsingleTag.exec( selector );
if ( ret ) {
if ( jQuery.isPlainObject( context ) ) {
selector = [ document.createElement( ret[1] ) ];
jQuery.fn.attr.call( selector, context, true );
} else {
selector = [ doc.createElement( ret[1] ) ];
}
} else {
ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
}
return jQuery.merge( this, selector );
// HANDLE: $("#id")
} else {
elem = document.getElementById( match[2] );
// Check parentNode to catch when Blackberry 4.6 returns
// nodes that are no longer in the document #6963
if ( elem && elem.parentNode ) {
// Handle the case where IE and Opera return items
// by name instead of ID
if ( elem.id !== match[2] ) {
return rootjQuery.find( selector );
}
// Otherwise, we inject the element directly into the jQuery object
this.length = 1;
this[0] = elem;
}
this.context = document;
this.selector = selector;
return this;
}
// HANDLE: $(expr, $(...))
} else if ( !context || context.jquery ) {
return ( context || rootjQuery ).find( selector );
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
return this.constructor( context ).find( selector );
}
// HANDLE: $(function)
// Shortcut for document ready
} else if ( jQuery.isFunction( selector ) ) {
return rootjQuery.ready( selector );
}
if ( selector.selector !== undefined ) {
this.selector = selector.selector;
this.context = selector.context;
}
return jQuery.makeArray( selector, this );
},
// Start with an empty selector
selector: "",
// The current version of jQuery being used
jquery: "1.7.2",
// The default length of a jQuery object is 0
length: 0,
// The number of elements contained in the matched element set
size: function() {
return this.length;
},
toArray: function() {
return slice.call( this, 0 );
},
// Get the Nth element in the matched element set OR
// Get the whole matched element set as a clean array
get: function( num ) {
return num == null ?
// Return a 'clean' array
this.toArray() :
// Return just the object
( num < 0 ? this[ this.length + num ] : this[ num ] );
},
// Take an array of elements and push it onto the stack
// (returning the new matched element set)
pushStack: function( elems, name, selector ) {
// Build a new jQuery matched element set
var ret = this.constructor();
if ( jQuery.isArray( elems ) ) {
push.apply( ret, elems );
} else {
jQuery.merge( ret, elems );
}
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context;
if ( name === "find" ) {
ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
} else if ( name ) {
ret.selector = this.selector + "." + name + "(" + selector + ")";
}
// Return the newly-formed element set
return ret;
},
// Execute a callback for every element in the matched set.
// (You can seed the arguments with an array of args, but this is
// only used internally.)
each: function( callback, args ) {
return jQuery.each( this, callback, args );
},
ready: function( fn ) {
// Attach the listeners
jQuery.bindReady();
// Add the callback
readyList.add( fn );
return this;
},
eq: function( i ) {
i = +i;
return i === -1 ?
this.slice( i ) :
this.slice( i, i + 1 );
},
first: function() {
return this.eq( 0 );
},
last: function() {
return this.eq( -1 );
},
slice: function() {
return this.pushStack( slice.apply( this, arguments ),
"slice", slice.call(arguments).join(",") );
},
map: function( callback ) {
return this.pushStack( jQuery.map(this, function( elem, i ) {
return callback.call( elem, i, elem );
}));
},
end: function() {
return this.prevObject || this.constructor(null);
},
// For internal use only.
// Behaves like an Array's method, not like a jQuery method.
push: push,
sort: [].sort,
splice: [].splice
};
// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;
jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
// extend jQuery itself if only one argument is passed
if ( length === i ) {
target = this;
--i;
}
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) {
continue;
}
// Recurse if we're merging plain objects or arrays
if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
if ( copyIsArray ) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
target[ name ] = jQuery.extend( deep, clone, copy );
// Don't bring in undefined values
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};
jQuery.extend({
noConflict: function( deep ) {
if ( window.$ === jQuery ) {
window.$ = _$;
}
if ( deep && window.jQuery === jQuery ) {
window.jQuery = _jQuery;
}
return jQuery;
},
// Is the DOM ready to be used? Set to true once it occurs.
isReady: false,
// A counter to track how many items to wait for before
// the ready event fires. See #6781
readyWait: 1,
// Hold (or release) the ready event
holdReady: function( hold ) {
if ( hold ) {
jQuery.readyWait++;
} else {
jQuery.ready( true );
}
},
// Handle when the DOM is ready
ready: function( wait ) {
// Either a released hold or an DOMready/load event and not yet ready
if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if ( !document.body ) {
return setTimeout( jQuery.ready, 1 );
}
// Remember that the DOM is ready
jQuery.isReady = true;
// If a normal DOM Ready event fired, decrement, and wait if need be
if ( wait !== true && --jQuery.readyWait > 0 ) {
return;
}
// If there are functions bound, to execute
readyList.fireWith( document, [ jQuery ] );
// Trigger any bound ready events
if ( jQuery.fn.trigger ) {
jQuery( document ).trigger( "ready" ).off( "ready" );
}
}
},
bindReady: function() {
if ( readyList ) {
return;
}
readyList = jQuery.Callbacks( "once memory" );
// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
if ( document.readyState === "complete" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
return setTimeout( jQuery.ready, 1 );
}
// Mozilla, Opera and webkit nightlies currently support this event
if ( document.addEventListener ) {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
// A fallback to window.onload, that will always work
window.addEventListener( "load", jQuery.ready, false );
// If IE event model is used
} else if ( document.attachEvent ) {
// ensure firing before onload,
// maybe late but safe also for iframes
document.attachEvent( "onreadystatechange", DOMContentLoaded );
// A fallback to window.onload, that will always work
window.attachEvent( "onload", jQuery.ready );
// If IE and not a frame
// continually check to see if the document is ready
var toplevel = false;
try {
toplevel = window.frameElement == null;
} catch(e) {}
if ( document.documentElement.doScroll && toplevel ) {
doScrollCheck();
}
}
},
// See test/unit/core.js for details concerning isFunction.
// Since version 1.3, DOM methods and functions like alert
// aren't supported. They return false on IE (#2968).
isFunction: function( obj ) {
return jQuery.type(obj) === "function";
},
isArray: Array.isArray || function( obj ) {
return jQuery.type(obj) === "array";
},
isWindow: function( obj ) {
return obj != null && obj == obj.window;
},
isNumeric: function( obj ) {
return !isNaN( parseFloat(obj) ) && isFinite( obj );
},
type: function( obj ) {
return obj == null ?
String( obj ) :
class2type[ toString.call(obj) ] || "object";
},
isPlainObject: function( obj ) {
// Must be an Object.
// Because of IE, we also have to check the presence of the constructor property.
// Make sure that DOM nodes and window objects don't pass through, as well
if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
return false;
}
try {
// Not own constructor property must be Object
if ( obj.constructor &&
!hasOwn.call(obj, "constructor") &&
!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
return false;
}
} catch ( e ) {
// IE8,9 Will throw exceptions on certain host objects #9897
return false;
}
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
var key;
for ( key in obj ) {}
return key === undefined || hasOwn.call( obj, key );
},
isEmptyObject: function( obj ) {
for ( var name in obj ) {
return false;
}
return true;
},
error: function( msg ) {
throw new Error( msg );
},
parseJSON: function( data ) {
if ( typeof data !== "string" || !data ) {
return null;
}
// Make sure leading/trailing whitespace is removed (IE can't handle it)
data = jQuery.trim( data );
// Attempt to parse using the native JSON parser first
if ( window.JSON && window.JSON.parse ) {
return window.JSON.parse( data );
}
// Make sure the incoming data is actual JSON
// Logic borrowed from http://json.org/json2.js
if ( rvalidchars.test( data.replace( rvalidescape, "@" )
.replace( rvalidtokens, "]" )
.replace( rvalidbraces, "")) ) {
return ( new Function( "return " + data ) )();
}
jQuery.error( "Invalid JSON: " + data );
},
// Cross-browser xml parsing
parseXML: function( data ) {
if ( typeof data !== "string" || !data ) {
return null;
}
var xml, tmp;
try {
if ( window.DOMParser ) { // Standard
tmp = new DOMParser();
xml = tmp.parseFromString( data , "text/xml" );
} else { // IE
xml = new ActiveXObject( "Microsoft.XMLDOM" );
xml.async = "false";
xml.loadXML( data );
}
} catch( e ) {
xml = undefined;
}
if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
jQuery.error( "Invalid XML: " + data );
}
return xml;
},
noop: function() {},
// Evaluates a script in a global context
// Workarounds based on findings by Jim Driscoll
// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
globalEval: function( data ) {
if ( data && rnotwhite.test( data ) ) {
// We use execScript on Internet Explorer
// We use an anonymous function so that context is window
// rather than jQuery in Firefox
( window.execScript || function( data ) {
window[ "eval" ].call( window, data );
} )( data );
}
},
// Convert dashed to camelCase; used by the css and data modules
// Microsoft forgot to hump their vendor prefix (#9572)
camelCase: function( string ) {
return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
},
nodeName: function( elem, name ) {
return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
},
// args is for internal usage only
each: function( object, callback, args ) {
var name, i = 0,
length = object.length,
isObj = length === undefined || jQuery.isFunction( object );
if ( args ) {
if ( isObj ) {
for ( name in object ) {
if ( callback.apply( object[ name ], args ) === false ) {
break;
}
}
} else {
for ( ; i < length; ) {
if ( callback.apply( object[ i++ ], args ) === false ) {
break;
}
}
}
// A special, fast, case for the most common use of each
} else {
if ( isObj ) {
for ( name in object ) {
if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
break;
}
}
} else {
for ( ; i < length; ) {
if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
break;
}
}
}
}
return object;
},
// Use native String.trim function wherever possible
trim: trim ?
function( text ) {
return text == null ?
"" :
trim.call( text );
} :
// Otherwise use our own trimming functionality
function( text ) {
return text == null ?
"" :
text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
},
// results is for internal usage only
makeArray: function( array, results ) {
var ret = results || [];
if ( array != null ) {
// The window, strings (and functions) also have 'length'
// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
var type = jQuery.type( array );
if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
push.call( ret, array );
} else {
jQuery.merge( ret, array );
}
}
return ret;
},
inArray: function( elem, array, i ) {
var len;
if ( array ) {
if ( indexOf ) {
return indexOf.call( array, elem, i );
}
len = array.length;
i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
for ( ; i < len; i++ ) {
// Skip accessing in sparse arrays
if ( i in array && array[ i ] === elem ) {
return i;
}
}
}
return -1;
},
merge: function( first, second ) {
var i = first.length,
j = 0;
if ( typeof second.length === "number" ) {
for ( var l = second.length; j < l; j++ ) {
first[ i++ ] = second[ j ];
}
} else {
while ( second[j] !== undefined ) {
first[ i++ ] = second[ j++ ];
}
}
first.length = i;
return first;
},
grep: function( elems, callback, inv ) {
var ret = [], retVal;
inv = !!inv;
// Go through the array, only saving the items
// that pass the validator function
for ( var i = 0, length = elems.length; i < length; i++ ) {
retVal = !!callback( elems[ i ], i );
if ( inv !== retVal ) {
ret.push( elems[ i ] );
}
}
return ret;
},
// arg is for internal usage only
map: function( elems, callback, arg ) {
var value, key, ret = [],
i = 0,
length = elems.length,
// jquery objects are treated as arrays
isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
// Go through the array, translating each of the items to their
if ( isArray ) {
for ( ; i < length; i++ ) {
value = callback( elems[ i ], i, arg );
if ( value != null ) {
ret[ ret.length ] = value;
}
}
// Go through every key on the object,
} else {
for ( key in elems ) {
value = callback( elems[ key ], key, arg );
if ( value != null ) {
ret[ ret.length ] = value;
}
}
}
// Flatten any nested arrays
return ret.concat.apply( [], ret );
},
// A global GUID counter for objects
guid: 1,
// Bind a function to a context, optionally partially applying any
// arguments.
proxy: function( fn, context ) {
if ( typeof context === "string" ) {
var tmp = fn[ context ];
context = fn;
fn = tmp;
}
// Quick check to determine if target is callable, in the spec
// this throws a TypeError, but we will just return undefined.
if ( !jQuery.isFunction( fn ) ) {
return undefined;
}
// Simulated bind
var args = slice.call( arguments, 2 ),
proxy = function() {
return fn.apply( context, args.concat( slice.call( arguments ) ) );
};
// Set the guid of unique handler to the same of original handler, so it can be removed
proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
return proxy;
},
// Mutifunctional method to get and set values to a collection
// The value/s can optionally be executed if it's a function
access: function( elems, fn, key, value, chainable, emptyGet, pass ) {
var exec,
bulk = key == null,
i = 0,
length = elems.length;
// Sets many values
if ( key && typeof key === "object" ) {
for ( i in key ) {
jQuery.access( elems, fn, i, key[i], 1, emptyGet, value );
}
chainable = 1;
// Sets one value
} else if ( value !== undefined ) {
// Optionally, function values get executed if exec is true
exec = pass === undefined && jQuery.isFunction( value );
if ( bulk ) {
// Bulk operations only iterate when executing function values
if ( exec ) {
exec = fn;
fn = function( elem, key, value ) {
return exec.call( jQuery( elem ), value );
};
// Otherwise they run against the entire set
} else {
fn.call( elems, value );
fn = null;
}
}
if ( fn ) {
for (; i < length; i++ ) {
fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
}
}
chainable = 1;
}
return chainable ?
elems :
// Gets
bulk ?
fn.call( elems ) :
length ? fn( elems[0], key ) : emptyGet;
},
now: function() {
return ( new Date() ).getTime();
},
// Use of jQuery.browser is frowned upon.
// More details: http://docs.jquery.com/Utilities/jQuery.browser
uaMatch: function( ua ) {
ua = ua.toLowerCase();
var match = rwebkit.exec( ua ) ||
ropera.exec( ua ) ||
rmsie.exec( ua ) ||
ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
[];
return { browser: match[1] || "", version: match[2] || "0" };
},
sub: function() {
function jQuerySub( selector, context ) {
return new jQuerySub.fn.init( selector, context );
}
jQuery.extend( true, jQuerySub, this );
jQuerySub.superclass = this;
jQuerySub.fn = jQuerySub.prototype = this();
jQuerySub.fn.constructor = jQuerySub;
jQuerySub.sub = this.sub;
jQuerySub.fn.init = function init( selector, context ) {
if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
context = jQuerySub( context );
}
return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
};
jQuerySub.fn.init.prototype = jQuerySub.fn;
var rootjQuerySub = jQuerySub(document);
return jQuerySub;
},
browser: {}
});
// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
});
browserMatch = jQuery.uaMatch( userAgent );
if ( browserMatch.browser ) {
jQuery.browser[ browserMatch.browser ] = true;
jQuery.browser.version = browserMatch.version;
}
// Deprecated, use jQuery.browser.webkit instead
if ( jQuery.browser.webkit ) {
jQuery.browser.safari = true;
}
// IE doesn't match non-breaking spaces with \s
if ( rnotwhite.test( "\xA0" ) ) {
trimLeft = /^[\s\xA0]+/;
trimRight = /[\s\xA0]+$/;
}
// All jQuery objects should point back to these
rootjQuery = jQuery(document);
// Cleanup functions for the document ready method
if ( document.addEventListener ) {
DOMContentLoaded = function() {
document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
jQuery.ready();
};
} else if ( document.attachEvent ) {
DOMContentLoaded = function() {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange", DOMContentLoaded );
jQuery.ready();
}
};
}
// The DOM ready check for Internet Explorer
function doScrollCheck() {
if ( jQuery.isReady ) {
return;
}
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch(e) {
setTimeout( doScrollCheck, 1 );
return;
}
// and execute any waiting functions
jQuery.ready();
}
return jQuery;
})();
// String to Object flags format cache
var flagsCache = {};
// Convert String-formatted flags into Object-formatted ones and store in cache
function createFlags( flags ) {
var object = flagsCache[ flags ] = {},
i, length;
flags = flags.split( /\s+/ );
for ( i = 0, length = flags.length; i < length; i++ ) {
object[ flags[i] ] = true;
}
return object;
}
/*
* Create a callback list using the following parameters:
*
* flags: an optional list of space-separated flags that will change how
* the callback list behaves
*
* By default a callback list will act like an event callback list and can be
* "fired" multiple times.
*
* Possible flags:
*
* once: will ensure the callback list can only be fired once (like a Deferred)
*
* memory: will keep track of previous values and will call any callback added
* after the list has been fired right away with the latest "memorized"
* values (like a Deferred)
*
* unique: will ensure a callback can only be added once (no duplicate in the list)
*
* stopOnFalse: interrupt callings when a callback returns false
*
*/
jQuery.Callbacks = function( flags ) {
// Convert flags from String-formatted to Object-formatted
// (we check in cache first)
flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
var // Actual callback list
list = [],
// Stack of fire calls for repeatable lists
stack = [],
// Last fire value (for non-forgettable lists)
memory,
// Flag to know if list was already fired
fired,
// Flag to know if list is currently firing
firing,
// First callback to fire (used internally by add and fireWith)
firingStart,
// End of the loop when firing
firingLength,
// Index of currently firing callback (modified by remove if needed)
firingIndex,
// Add one or several callbacks to the list
add = function( args ) {
var i,
length,
elem,
type,
actual;
for ( i = 0, length = args.length; i < length; i++ ) {
elem = args[ i ];
type = jQuery.type( elem );
if ( type === "array" ) {
// Inspect recursively
add( elem );
} else if ( type === "function" ) {
// Add if not in unique mode and callback is not in
if ( !flags.unique || !self.has( elem ) ) {
list.push( elem );
}
}
}
},
// Fire callbacks
fire = function( context, args ) {
args = args || [];
memory = !flags.memory || [ context, args ];
fired = true;
firing = true;
firingIndex = firingStart || 0;
firingStart = 0;
firingLength = list.length;
for ( ; list && firingIndex < firingLength; firingIndex++ ) {
if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
memory = true; // Mark as halted
break;
}
}
firing = false;
if ( list ) {
if ( !flags.once ) {
if ( stack && stack.length ) {
memory = stack.shift();
self.fireWith( memory[ 0 ], memory[ 1 ] );
}
} else if ( memory === true ) {
self.disable();
} else {
list = [];
}
}
},
// Actual Callbacks object
self = {
// Add a callback or a collection of callbacks to the list
add: function() {
if ( list ) {
var length = list.length;
add( arguments );
// Do we need to add the callbacks to the
// current firing batch?
if ( firing ) {
firingLength = list.length;
// With memory, if we're not firing then
// we should call right away, unless previous
// firing was halted (stopOnFalse)
} else if ( memory && memory !== true ) {
firingStart = length;
fire( memory[ 0 ], memory[ 1 ] );
}
}
return this;
},
// Remove a callback from the list
remove: function() {
if ( list ) {
var args = arguments,
argIndex = 0,
argLength = args.length;
for ( ; argIndex < argLength ; argIndex++ ) {
for ( var i = 0; i < list.length; i++ ) {
if ( args[ argIndex ] === list[ i ] ) {
// Handle firingIndex and firingLength
if ( firing ) {
if ( i <= firingLength ) {
firingLength--;
if ( i <= firingIndex ) {
firingIndex--;
}
}
}
// Remove the element
list.splice( i--, 1 );
// If we have some unicity property then
// we only need to do this once
if ( flags.unique ) {
break;
}
}
}
}
}
return this;
},
// Control if a given callback is in the list
has: function( fn ) {
if ( list ) {
var i = 0,
length = list.length;
for ( ; i < length; i++ ) {
if ( fn === list[ i ] ) {
return true;
}
}
}
return false;
},
// Remove all callbacks from the list
empty: function() {
list = [];
return this;
},
// Have the list do nothing anymore
disable: function() {
list = stack = memory = undefined;
return this;
},
// Is it disabled?
disabled: function() {
return !list;
},
// Lock the list in its current state
lock: function() {
stack = undefined;
if ( !memory || memory === true ) {
self.disable();
}
return this;
},
// Is it locked?
locked: function() {
return !stack;
},
// Call all callbacks with the given context and arguments
fireWith: function( context, args ) {
if ( stack ) {
if ( firing ) {
if ( !flags.once ) {
stack.push( [ context, args ] );
}
} else if ( !( flags.once && memory ) ) {
fire( context, args );
}
}
return this;
},
// Call all the callbacks with the given arguments
fire: function() {
self.fireWith( this, arguments );
return this;
},
// To know if the callbacks have already been called at least once
fired: function() {
return !!fired;
}
};
return self;
};
var // Static reference to slice
sliceDeferred = [].slice;
jQuery.extend({
Deferred: function( func ) {
var doneList = jQuery.Callbacks( "once memory" ),
failList = jQuery.Callbacks( "once memory" ),
progressList = jQuery.Callbacks( "memory" ),
state = "pending",
lists = {
resolve: doneList,
reject: failList,
notify: progressList
},
promise = {
done: doneList.add,
fail: failList.add,
progress: progressList.add,
state: function() {
return state;
},
// Deprecated
isResolved: doneList.fired,
isRejected: failList.fired,
then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
return this;
},
always: function() {
deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
return this;
},
pipe: function( fnDone, fnFail, fnProgress ) {
return jQuery.Deferred(function( newDefer ) {
jQuery.each( {
done: [ fnDone, "resolve" ],
fail: [ fnFail, "reject" ],
progress: [ fnProgress, "notify" ]
}, function( handler, data ) {
var fn = data[ 0 ],
action = data[ 1 ],
returned;
if ( jQuery.isFunction( fn ) ) {
deferred[ handler ](function() {
returned = fn.apply( this, arguments );
if ( returned && jQuery.isFunction( returned.promise ) ) {
returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
} else {
newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
}
});
} else {
deferred[ handler ]( newDefer[ action ] );
}
});
}).promise();
},
// Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object
promise: function( obj ) {
if ( obj == null ) {
obj = promise;
} else {
for ( var key in promise ) {
obj[ key ] = promise[ key ];
}
}
return obj;
}
},
deferred = promise.promise({}),
key;
for ( key in lists ) {
deferred[ key ] = lists[ key ].fire;
deferred[ key + "With" ] = lists[ key ].fireWith;
}
// Handle state
deferred.done( function() {
state = "resolved";
}, failList.disable, progressList.lock ).fail( function() {
state = "rejected";
}, doneList.disable, progressList.lock );
// Call given func if any
if ( func ) {
func.call( deferred, deferred );
}
// All done!
return deferred;
},
// Deferred helper
when: function( firstParam ) {
var args = sliceDeferred.call( arguments, 0 ),
i = 0,
length = args.length,
pValues = new Array( length ),
count = length,
pCount = length,
deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
firstParam :
jQuery.Deferred(),
promise = deferred.promise();
function resolveFunc( i ) {
return function( value ) {
args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
if ( !( --count ) ) {
deferred.resolveWith( deferred, args );
}
};
}
function progressFunc( i ) {
return function( value ) {
pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
deferred.notifyWith( promise, pValues );
};
}
if ( length > 1 ) {
for ( ; i < length; i++ ) {
if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
} else {
--count;
}
}
if ( !count ) {
deferred.resolveWith( deferred, args );
}
} else if ( deferred !== firstParam ) {
deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
}
return promise;
}
});
jQuery.support = (function() {
var support,
all,
a,
select,
opt,
input,
fragment,
tds,
events,
eventName,
i,
isSupported,
div = document.createElement( "div" ),
documentElement = document.documentElement;
// Preliminary tests
div.setAttribute("className", "t");
div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
all = div.getElementsByTagName( "*" );
a = div.getElementsByTagName( "a" )[ 0 ];
// Can't get basic test support
if ( !all || !all.length || !a ) {
return {};
}
// First batch of supports tests
select = document.createElement( "select" );
opt = select.appendChild( document.createElement("option") );
input = div.getElementsByTagName( "input" )[ 0 ];
support = {
// IE strips leading whitespace when .innerHTML is used
leadingWhitespace: ( div.firstChild.nodeType === 3 ),
// Make sure that tbody elements aren't automatically inserted
// IE will insert them into empty tables
tbody: !div.getElementsByTagName("tbody").length,
// Make sure that link elements get serialized correctly by innerHTML
// This requires a wrapper element in IE
htmlSerialize: !!div.getElementsByTagName("link").length,
// Get the style information from getAttribute
// (IE uses .cssText instead)
style: /top/.test( a.getAttribute("style") ),
// Make sure that URLs aren't manipulated
// (IE normalizes it by default)
hrefNormalized: ( a.getAttribute("href") === "/a" ),
// Make sure that element opacity exists
// (IE uses filter instead)
// Use a regex to work around a WebKit issue. See #5145
opacity: /^0.55/.test( a.style.opacity ),
// Verify style float existence
// (IE uses styleFloat instead of cssFloat)
cssFloat: !!a.style.cssFloat,
// Make sure that if no value is specified for a checkbox
// that it defaults to "on".
// (WebKit defaults to "" instead)
checkOn: ( input.value === "on" ),
// Make sure that a selected-by-default option has a working selected property.
// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
optSelected: opt.selected,
// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
getSetAttribute: div.className !== "t",
// Tests for enctype support on a form(#6743)
enctype: !!document.createElement("form").enctype,
// Makes sure cloning an html5 element does not cause problems
// Where outerHTML is undefined, this still works
html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
// Will be defined later
submitBubbles: true,
changeBubbles: true,
focusinBubbles: false,
deleteExpando: true,
noCloneEvent: true,
inlineBlockNeedsLayout: false,
shrinkWrapBlocks: false,
reliableMarginRight: true,
pixelMargin: true
};
// jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead
jQuery.boxModel = support.boxModel = (document.compatMode === "CSS1Compat");
// Make sure checked status is properly cloned
input.checked = true;
support.noCloneChecked = input.cloneNode( true ).checked;
// Make sure that the options inside disabled selects aren't marked as disabled
// (WebKit marks them as disabled)
select.disabled = true;
support.optDisabled = !opt.disabled;
// Test to see if it's possible to delete an expando from an element
// Fails in Internet Explorer
try {
delete div.test;
} catch( e ) {
support.deleteExpando = false;
}
if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
div.attachEvent( "onclick", function() {
// Cloning a node shouldn't copy over any
// bound event handlers (IE does this)
support.noCloneEvent = false;
});
div.cloneNode( true ).fireEvent( "onclick" );
}
// Check if a radio maintains its value
// after being appended to the DOM
input = document.createElement("input");
input.value = "t";
input.setAttribute("type", "radio");
support.radioValue = input.value === "t";
input.setAttribute("checked", "checked");
// #11217 - WebKit loses check when the name is after the checked attribute
input.setAttribute( "name", "t" );
div.appendChild( input );
fragment = document.createDocumentFragment();
fragment.appendChild( div.lastChild );
// WebKit doesn't clone checked state correctly in fragments
support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
// Check if a disconnected checkbox will retain its checked
// value of true after appended to the DOM (IE6/7)
support.appendChecked = input.checked;
fragment.removeChild( input );
fragment.appendChild( div );
// Technique from Juriy Zaytsev
// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
// We only care about the case where non-standard event systems
// are used, namely in IE. Short-circuiting here helps us to
// avoid an eval call (in setAttribute) which can cause CSP
// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
if ( div.attachEvent ) {
for ( i in {
submit: 1,
change: 1,
focusin: 1
}) {
eventName = "on" + i;
isSupported = ( eventName in div );
if ( !isSupported ) {
div.setAttribute( eventName, "return;" );
isSupported = ( typeof div[ eventName ] === "function" );
}
support[ i + "Bubbles" ] = isSupported;
}
}
fragment.removeChild( div );
// Null elements to avoid leaks in IE
fragment = select = opt = div = input = null;
// Run tests that need a body at doc ready
jQuery(function() {
var container, outer, inner, table, td, offsetSupport,
marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight,
paddingMarginBorderVisibility, paddingMarginBorder,
body = document.getElementsByTagName("body")[0];
if ( !body ) {
// Return for frameset docs that don't have a body
return;
}
conMarginTop = 1;
paddingMarginBorder = "padding:0;margin:0;border:";
positionTopLeftWidthHeight = "position:absolute;top:0;left:0;width:1px;height:1px;";
paddingMarginBorderVisibility = paddingMarginBorder + "0;visibility:hidden;";
style = "style='" + positionTopLeftWidthHeight + paddingMarginBorder + "5px solid #000;";
html = "<div " + style + "display:block;'><div style='" + paddingMarginBorder + "0;display:block;overflow:hidden;'></div></div>" +
"<table " + style + "' cellpadding='0' cellspacing='0'>" +
"<tr><td></td></tr></table>";
container = document.createElement("div");
container.style.cssText = paddingMarginBorderVisibility + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
body.insertBefore( container, body.firstChild );
// Construct the test element
div = document.createElement("div");
container.appendChild( div );
// Check if table cells still have offsetWidth/Height when they are set
// to display:none and there are still other visible table cells in a
// table row; if so, offsetWidth/Height are not reliable for use when
// determining if an element has been hidden directly using
// display:none (it is still safe to use offsets if a parent element is
// hidden; don safety goggles and see bug #4512 for more information).
// (only IE 8 fails this test)
div.innerHTML = "<table><tr><td style='" + paddingMarginBorder + "0;display:none'></td><td>t</td></tr></table>";
tds = div.getElementsByTagName( "td" );
isSupported = ( tds[ 0 ].offsetHeight === 0 );
tds[ 0 ].style.display = "";
tds[ 1 ].style.display = "none";
// Check if empty table cells still have offsetWidth/Height
// (IE <= 8 fail this test)
support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
// Check if div with explicit width and no margin-right incorrectly
// gets computed margin-right based on width of container. For more
// info see bug #3333
// Fails in WebKit before Feb 2011 nightlies
// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
if ( window.getComputedStyle ) {
div.innerHTML = "";
marginDiv = document.createElement( "div" );
marginDiv.style.width = "0";
marginDiv.style.marginRight = "0";
div.style.width = "2px";
div.appendChild( marginDiv );
support.reliableMarginRight =
( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
}
if ( typeof div.style.zoom !== "undefined" ) {
// Check if natively block-level elements act like inline-block
// elements when setting their display to 'inline' and giving
// them layout
// (IE < 8 does this)
div.innerHTML = "";
div.style.width = div.style.padding = "1px";
div.style.border = 0;
div.style.overflow = "hidden";
div.style.display = "inline";
div.style.zoom = 1;
support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
// Check if elements with layout shrink-wrap their children
// (IE 6 does this)
div.style.display = "block";
div.style.overflow = "visible";
div.innerHTML = "<div style='width:5px;'></div>";
support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
}
div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility;
div.innerHTML = html;
outer = div.firstChild;
inner = outer.firstChild;
td = outer.nextSibling.firstChild.firstChild;
offsetSupport = {
doesNotAddBorder: ( inner.offsetTop !== 5 ),
doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
};
inner.style.position = "fixed";
inner.style.top = "20px";
// safari subtracts parent border width here which is 5px
offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
inner.style.position = inner.style.top = "";
outer.style.overflow = "hidden";
outer.style.position = "relative";
offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
if ( window.getComputedStyle ) {
div.style.marginTop = "1%";
support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%";
}
if ( typeof container.style.zoom !== "undefined" ) {
container.style.zoom = 1;
}
body.removeChild( container );
marginDiv = div = container = null;
jQuery.extend( support, offsetSupport );
});
return support;
})();
var rbrace = /^(?:\{.*\}|\[.*\])$/,
rmultiDash = /([A-Z])/g;
jQuery.extend({
cache: {},
// Please use with caution
uuid: 0,
// Unique for each copy of jQuery on the page
// Non-digits removed to match rinlinejQuery
expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
// The following elements throw uncatchable exceptions if you
// attempt to add expando properties to them.
noData: {
"embed": true,
// Ban all objects except for Flash (which handle expandos)
"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
"applet": true
},
hasData: function( elem ) {
elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
return !!elem && !isEmptyDataObject( elem );
},
data: function( elem, name, data, pvt /* Internal Use Only */ ) {
if ( !jQuery.acceptData( elem ) ) {
return;
}
var privateCache, thisCache, ret,
internalKey = jQuery.expando,
getByName = typeof name === "string",
// We have to handle DOM nodes and JS objects differently because IE6-7
// can't GC object references properly across the DOM-JS boundary
isNode = elem.nodeType,
// Only DOM nodes need the global jQuery cache; JS object data is
// attached directly to the object so GC can occur automatically
cache = isNode ? jQuery.cache : elem,
// Only defining an ID for JS objects if its cache already exists allows
// the code to shortcut on the same path as a DOM node with no cache
id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
isEvents = name === "events";
// Avoid doing any more work than we need to when trying to get data on an
// object that has no data at all
if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
return;
}
if ( !id ) {
// Only DOM nodes need a new unique ID for each element since their data
// ends up in the global cache
if ( isNode ) {
elem[ internalKey ] = id = ++jQuery.uuid;
} else {
id = internalKey;
}
}
if ( !cache[ id ] ) {
cache[ id ] = {};
// Avoids exposing jQuery metadata on plain JS objects when the object
// is serialized using JSON.stringify
if ( !isNode ) {
cache[ id ].toJSON = jQuery.noop;
}
}
// An object can be passed to jQuery.data instead of a key/value pair; this gets
// shallow copied over onto the existing cache
if ( typeof name === "object" || typeof name === "function" ) {
if ( pvt ) {
cache[ id ] = jQuery.extend( cache[ id ], name );
} else {
cache[ id ].data = jQuery.extend( cache[ id ].data, name );
}
}
privateCache = thisCache = cache[ id ];
// jQuery data() is stored in a separate object inside the object's internal data
// cache in order to avoid key collisions between internal data and user-defined
// data.
if ( !pvt ) {
if ( !thisCache.data ) {
thisCache.data = {};
}
thisCache = thisCache.data;
}
if ( data !== undefined ) {
thisCache[ jQuery.camelCase( name ) ] = data;
}
// Users should not attempt to inspect the internal events object using jQuery.data,
// it is undocumented and subject to change. But does anyone listen? No.
if ( isEvents && !thisCache[ name ] ) {
return privateCache.events;
}
// Check for both converted-to-camel and non-converted data property names
// If a data property was specified
if ( getByName ) {
// First Try to find as-is property data
ret = thisCache[ name ];
// Test for null|undefined property data
if ( ret == null ) {
// Try to find the camelCased property
ret = thisCache[ jQuery.camelCase( name ) ];
}
} else {
ret = thisCache;
}
return ret;
},
removeData: function( elem, name, pvt /* Internal Use Only */ ) {
if ( !jQuery.acceptData( elem ) ) {
return;
}
var thisCache, i, l,
// Reference to internal data cache key
internalKey = jQuery.expando,
isNode = elem.nodeType,
// See jQuery.data for more information
cache = isNode ? jQuery.cache : elem,
// See jQuery.data for more information
id = isNode ? elem[ internalKey ] : internalKey;
// If there is already no cache entry for this object, there is no
// purpose in continuing
if ( !cache[ id ] ) {
return;
}
if ( name ) {
thisCache = pvt ? cache[ id ] : cache[ id ].data;
if ( thisCache ) {
// Support array or space separated string names for data keys
if ( !jQuery.isArray( name ) ) {
// try the string as a key before any manipulation
if ( name in thisCache ) {
name = [ name ];
} else {
// split the camel cased version by spaces unless a key with the spaces exists
name = jQuery.camelCase( name );
if ( name in thisCache ) {
name = [ name ];
} else {
name = name.split( " " );
}
}
}
for ( i = 0, l = name.length; i < l; i++ ) {
delete thisCache[ name[i] ];
}
// If there is no data left in the cache, we want to continue
// and let the cache object itself get destroyed
if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
return;
}
}
}
// See jQuery.data for more information
if ( !pvt ) {
delete cache[ id ].data;
// Don't destroy the parent cache unless the internal data object
// had been the only thing left in it
if ( !isEmptyDataObject(cache[ id ]) ) {
return;
}
}
// Browsers that fail expando deletion also refuse to delete expandos on
// the window, but it will allow it on all other JS objects; other browsers
// don't care
// Ensure that `cache` is not a window object #10080
if ( jQuery.support.deleteExpando || !cache.setInterval ) {
delete cache[ id ];
} else {
cache[ id ] = null;
}
// We destroyed the cache and need to eliminate the expando on the node to avoid
// false lookups in the cache for entries that no longer exist
if ( isNode ) {
// IE does not allow us to delete expando properties from nodes,
// nor does it have a removeAttribute function on Document nodes;
// we must handle all of these cases
if ( jQuery.support.deleteExpando ) {
delete elem[ internalKey ];
} else if ( elem.removeAttribute ) {
elem.removeAttribute( internalKey );
} else {
elem[ internalKey ] = null;
}
}
},
// For internal use only.
_data: function( elem, name, data ) {
return jQuery.data( elem, name, data, true );
},
// A method for determining if a DOM node can handle the data expando
acceptData: function( elem ) {
if ( elem.nodeName ) {
var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
if ( match ) {
return !(match === true || elem.getAttribute("classid") !== match);
}
}
return true;
}
});
jQuery.fn.extend({
data: function( key, value ) {
var parts, part, attr, name, l,
elem = this[0],
i = 0,
data = null;
// Gets all values
if ( key === undefined ) {
if ( this.length ) {
data = jQuery.data( elem );
if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
attr = elem.attributes;
for ( l = attr.length; i < l; i++ ) {
name = attr[i].name;
if ( name.indexOf( "data-" ) === 0 ) {
name = jQuery.camelCase( name.substring(5) );
dataAttr( elem, name, data[ name ] );
}
}
jQuery._data( elem, "parsedAttrs", true );
}
}
return data;
}
// Sets multiple values
if ( typeof key === "object" ) {
return this.each(function() {
jQuery.data( this, key );
});
}
parts = key.split( ".", 2 );
parts[1] = parts[1] ? "." + parts[1] : "";
part = parts[1] + "!";
return jQuery.access( this, function( value ) {
if ( value === undefined ) {
data = this.triggerHandler( "getData" + part, [ parts[0] ] );
// Try to fetch any internally stored data first
if ( data === undefined && elem ) {
data = jQuery.data( elem, key );
data = dataAttr( elem, key, data );
}
return data === undefined && parts[1] ?
this.data( parts[0] ) :
data;
}
parts[1] = value;
this.each(function() {
var self = jQuery( this );
self.triggerHandler( "setData" + part, parts );
jQuery.data( this, key, value );
self.triggerHandler( "changeData" + part, parts );
});
}, null, value, arguments.length > 1, null, false );
},
removeData: function( key ) {
return this.each(function() {
jQuery.removeData( this, key );
});
}
});
function dataAttr( elem, key, data ) {
// If nothing was found internally, try to fetch any
// data from the HTML5 data-* attribute
if ( data === undefined && elem.nodeType === 1 ) {
var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
data = elem.getAttribute( name );
if ( typeof data === "string" ) {
try {
data = data === "true" ? true :
data === "false" ? false :
data === "null" ? null :
jQuery.isNumeric( data ) ? +data :
rbrace.test( data ) ? jQuery.parseJSON( data ) :
data;
} catch( e ) {}
// Make sure we set the data so it isn't changed later
jQuery.data( elem, key, data );
} else {
data = undefined;
}
}
return data;
}
// checks a cache object for emptiness
function isEmptyDataObject( obj ) {
for ( var name in obj ) {
// if the public data object is empty, the private is still empty
if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
continue;
}
if ( name !== "toJSON" ) {
return false;
}
}
return true;
}
function handleQueueMarkDefer( elem, type, src ) {
var deferDataKey = type + "defer",
queueDataKey = type + "queue",
markDataKey = type + "mark",
defer = jQuery._data( elem, deferDataKey );
if ( defer &&
( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
// Give room for hard-coded callbacks to fire first
// and eventually mark/queue something else on the element
setTimeout( function() {
if ( !jQuery._data( elem, queueDataKey ) &&
!jQuery._data( elem, markDataKey ) ) {
jQuery.removeData( elem, deferDataKey, true );
defer.fire();
}
}, 0 );
}
}
jQuery.extend({
_mark: function( elem, type ) {
if ( elem ) {
type = ( type || "fx" ) + "mark";
jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
}
},
_unmark: function( force, elem, type ) {
if ( force !== true ) {
type = elem;
elem = force;
force = false;
}
if ( elem ) {
type = type || "fx";
var key = type + "mark",
count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
if ( count ) {
jQuery._data( elem, key, count );
} else {
jQuery.removeData( elem, key, true );
handleQueueMarkDefer( elem, type, "mark" );
}
}
},
queue: function( elem, type, data ) {
var q;
if ( elem ) {
type = ( type || "fx" ) + "queue";
q = jQuery._data( elem, type );
// Speed up dequeue by getting out quickly if this is just a lookup
if ( data ) {
if ( !q || jQuery.isArray(data) ) {
q = jQuery._data( elem, type, jQuery.makeArray(data) );
} else {
q.push( data );
}
}
return q || [];
}
},
dequeue: function( elem, type ) {
type = type || "fx";
var queue = jQuery.queue( elem, type ),
fn = queue.shift(),
hooks = {};
// If the fx queue is dequeued, always remove the progress sentinel
if ( fn === "inprogress" ) {
fn = queue.shift();
}
if ( fn ) {
// Add a progress sentinel to prevent the fx queue from being
// automatically dequeued
if ( type === "fx" ) {
queue.unshift( "inprogress" );
}
jQuery._data( elem, type + ".run", hooks );
fn.call( elem, function() {
jQuery.dequeue( elem, type );
}, hooks );
}
if ( !queue.length ) {
jQuery.removeData( elem, type + "queue " + type + ".run", true );
handleQueueMarkDefer( elem, type, "queue" );
}
}
});
jQuery.fn.extend({
queue: function( type, data ) {
var setter = 2;
if ( typeof type !== "string" ) {
data = type;
type = "fx";
setter--;
}
if ( arguments.length < setter ) {
return jQuery.queue( this[0], type );
}
return data === undefined ?
this :
this.each(function() {
var queue = jQuery.queue( this, type, data );
if ( type === "fx" && queue[0] !== "inprogress" ) {
jQuery.dequeue( this, type );
}
});
},
dequeue: function( type ) {
return this.each(function() {
jQuery.dequeue( this, type );
});
},
// Based off of the plugin by Clint Helfers, with permission.
// http://blindsignals.com/index.php/2009/07/jquery-delay/
delay: function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
type = type || "fx";
return this.queue( type, function( next, hooks ) {
var timeout = setTimeout( next, time );
hooks.stop = function() {
clearTimeout( timeout );
};
});
},
clearQueue: function( type ) {
return this.queue( type || "fx", [] );
},
// Get a promise resolved when queues of a certain type
// are emptied (fx is the type by default)
promise: function( type, object ) {
if ( typeof type !== "string" ) {
object = type;
type = undefined;
}
type = type || "fx";
var defer = jQuery.Deferred(),
elements = this,
i = elements.length,
count = 1,
deferDataKey = type + "defer",
queueDataKey = type + "queue",
markDataKey = type + "mark",
tmp;
function resolve() {
if ( !( --count ) ) {
defer.resolveWith( elements, [ elements ] );
}
}
while( i-- ) {
if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
count++;
tmp.add( resolve );
}
}
resolve();
return defer.promise( object );
}
});
var rclass = /[\n\t\r]/g,
rspace = /\s+/,
rreturn = /\r/g,
rtype = /^(?:button|input)$/i,
rfocusable = /^(?:button|input|object|select|textarea)$/i,
rclickable = /^a(?:rea)?$/i,
rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
getSetAttribute = jQuery.support.getSetAttribute,
nodeHook, boolHook, fixSpecified;
jQuery.fn.extend({
attr: function( name, value ) {
return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
},
removeAttr: function( name ) {
return this.each(function() {
jQuery.removeAttr( this, name );
});
},
prop: function( name, value ) {
return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
},
removeProp: function( name ) {
name = jQuery.propFix[ name ] || name;
return this.each(function() {
// try/catch handles cases where IE balks (such as removing a property on window)
try {
this[ name ] = undefined;
delete this[ name ];
} catch( e ) {}
});
},
addClass: function( value ) {
var classNames, i, l, elem,
setClass, c, cl;
if ( jQuery.isFunction( value ) ) {
return this.each(function( j ) {
jQuery( this ).addClass( value.call(this, j, this.className) );
});
}
if ( value && typeof value === "string" ) {
classNames = value.split( rspace );
for ( i = 0, l = this.length; i < l; i++ ) {
elem = this[ i ];
if ( elem.nodeType === 1 ) {
if ( !elem.className && classNames.length === 1 ) {
elem.className = value;
} else {
setClass = " " + elem.className + " ";
for ( c = 0, cl = classNames.length; c < cl; c++ ) {
if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
setClass += classNames[ c ] + " ";
}
}
elem.className = jQuery.trim( setClass );
}
}
}
}
return this;
},
removeClass: function( value ) {
var classNames, i, l, elem, className, c, cl;
if ( jQuery.isFunction( value ) ) {
return this.each(function( j ) {
jQuery( this ).removeClass( value.call(this, j, this.className) );
});
}
if ( (value && typeof value === "string") || value === undefined ) {
classNames = ( value || "" ).split( rspace );
for ( i = 0, l = this.length; i < l; i++ ) {
elem = this[ i ];
if ( elem.nodeType === 1 && elem.className ) {
if ( value ) {
className = (" " + elem.className + " ").replace( rclass, " " );
for ( c = 0, cl = classNames.length; c < cl; c++ ) {
className = className.replace(" " + classNames[ c ] + " ", " ");
}
elem.className = jQuery.trim( className );
} else {
elem.className = "";
}
}
}
}
return this;
},
toggleClass: function( value, stateVal ) {
var type = typeof value,
isBool = typeof stateVal === "boolean";
if ( jQuery.isFunction( value ) ) {
return this.each(function( i ) {
jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
});
}
return this.each(function() {
if ( type === "string" ) {
// toggle individual class names
var className,
i = 0,
self = jQuery( this ),
state = stateVal,
classNames = value.split( rspace );
while ( (className = classNames[ i++ ]) ) {
// check each className given, space seperated list
state = isBool ? state : !self.hasClass( className );
self[ state ? "addClass" : "removeClass" ]( className );
}
} else if ( type === "undefined" || type === "boolean" ) {
if ( this.className ) {
// store className if set
jQuery._data( this, "__className__", this.className );
}
// toggle whole className
this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
}
});
},
hasClass: function( selector ) {
var className = " " + selector + " ",
i = 0,
l = this.length;
for ( ; i < l; i++ ) {
if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
return true;
}
}
return false;
},
val: function( value ) {
var hooks, ret, isFunction,
elem = this[0];
if ( !arguments.length ) {
if ( elem ) {
hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
return ret;
}
ret = elem.value;
return typeof ret === "string" ?
// handle most common string cases
ret.replace(rreturn, "") :
// handle cases where value is null/undef or number
ret == null ? "" : ret;
}
return;
}
isFunction = jQuery.isFunction( value );
return this.each(function( i ) {
var self = jQuery(this), val;
if ( this.nodeType !== 1 ) {
return;
}
if ( isFunction ) {
val = value.call( this, i, self.val() );
} else {
val = value;
}
// Treat null/undefined as ""; convert numbers to string
if ( val == null ) {
val = "";
} else if ( typeof val === "number" ) {
val += "";
} else if ( jQuery.isArray( val ) ) {
val = jQuery.map(val, function ( value ) {
return value == null ? "" : value + "";
});
}
hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
// If set returns undefined, fall back to normal setting
if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
this.value = val;
}
});
}
});
jQuery.extend({
valHooks: {
option: {
get: function( elem ) {
// attributes.value is undefined in Blackberry 4.7 but
// uses .value. See #6932
var val = elem.attributes.value;
return !val || val.specified ? elem.value : elem.text;
}
},
select: {
get: function( elem ) {
var value, i, max, option,
index = elem.selectedIndex,
values = [],
options = elem.options,
one = elem.type === "select-one";
// Nothing was selected
if ( index < 0 ) {
return null;
}
// Loop through all the selected options
i = one ? index : 0;
max = one ? index + 1 : options.length;
for ( ; i < max; i++ ) {
option = options[ i ];
// Don't return options that are disabled or in a disabled optgroup
if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
// Get the specific value for the option
value = jQuery( option ).val();
// We don't need an array for one selects
if ( one ) {
return value;
}
// Multi-Selects return an array
values.push( value );
}
}
// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
if ( one && !values.length && options.length ) {
return jQuery( options[ index ] ).val();
}
return values;
},
set: function( elem, value ) {
var values = jQuery.makeArray( value );
jQuery(elem).find("option").each(function() {
this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
});
if ( !values.length ) {
elem.selectedIndex = -1;
}
return values;
}
}
},
attrFn: {
val: true,
css: true,
html: true,
text: true,
data: true,
width: true,
height: true,
offset: true
},
attr: function( elem, name, value, pass ) {
var ret, hooks, notxml,
nType = elem.nodeType;
// don't get/set attributes on text, comment and attribute nodes
if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
return;
}
if ( pass && name in jQuery.attrFn ) {
return jQuery( elem )[ name ]( value );
}
// Fallback to prop when attributes are not supported
if ( typeof elem.getAttribute === "undefined" ) {
return jQuery.prop( elem, name, value );
}
notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
// All attributes are lowercase
// Grab necessary hook if one is defined
if ( notxml ) {
name = name.toLowerCase();
hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
}
if ( value !== undefined ) {
if ( value === null ) {
jQuery.removeAttr( elem, name );
return;
} else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
return ret;
} else {
elem.setAttribute( name, "" + value );
return value;
}
} else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
return ret;
} else {
ret = elem.getAttribute( name );
// Non-existent attributes return null, we normalize to undefined
return ret === null ?
undefined :
ret;
}
},
removeAttr: function( elem, value ) {
var propName, attrNames, name, l, isBool,
i = 0;
if ( value && elem.nodeType === 1 ) {
attrNames = value.toLowerCase().split( rspace );
l = attrNames.length;
for ( ; i < l; i++ ) {
name = attrNames[ i ];
if ( name ) {
propName = jQuery.propFix[ name ] || name;
isBool = rboolean.test( name );
// See #9699 for explanation of this approach (setting first, then removal)
// Do not do this for boolean attributes (see #10870)
if ( !isBool ) {
jQuery.attr( elem, name, "" );
}
elem.removeAttribute( getSetAttribute ? name : propName );
// Set corresponding property to false for boolean attributes
if ( isBool && propName in elem ) {
elem[ propName ] = false;
}
}
}
}
},
attrHooks: {
type: {
set: function( elem, value ) {
// We can't allow the type property to be changed (since it causes problems in IE)
if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
jQuery.error( "type property can't be changed" );
} else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
// Setting the type on a radio button after the value resets the value in IE6-9
// Reset value to it's default in case type is set after value
// This is for element creation
var val = elem.value;
elem.setAttribute( "type", value );
if ( val ) {
elem.value = val;
}
return value;
}
}
},
// Use the value property for back compat
// Use the nodeHook for button elements in IE6/7 (#1954)
value: {
get: function( elem, name ) {
if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
return nodeHook.get( elem, name );
}
return name in elem ?
elem.value :
null;
},
set: function( elem, value, name ) {
if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
return nodeHook.set( elem, value, name );
}
// Does not return so that setAttribute is also used
elem.value = value;
}
}
},
propFix: {
tabindex: "tabIndex",
readonly: "readOnly",
"for": "htmlFor",
"class": "className",
maxlength: "maxLength",
cellspacing: "cellSpacing",
cellpadding: "cellPadding",
rowspan: "rowSpan",
colspan: "colSpan",
usemap: "useMap",
frameborder: "frameBorder",
contenteditable: "contentEditable"
},
prop: function( elem, name, value ) {
var ret, hooks, notxml,
nType = elem.nodeType;
// don't get/set properties on text, comment and attribute nodes
if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
return;
}
notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
if ( notxml ) {
// Fix name and attach hooks
name = jQuery.propFix[ name ] || name;
hooks = jQuery.propHooks[ name ];
}
if ( value !== undefined ) {
if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
return ret;
} else {
return ( elem[ name ] = value );
}
} else {
if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
return ret;
} else {
return elem[ name ];
}
}
},
propHooks: {
tabIndex: {
get: function( elem ) {
// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
var attributeNode = elem.getAttributeNode("tabindex");
return attributeNode && attributeNode.specified ?
parseInt( attributeNode.value, 10 ) :
rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
0 :
undefined;
}
}
}
});
// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
// Hook for boolean attributes
boolHook = {
get: function( elem, name ) {
// Align boolean attributes with corresponding properties
// Fall back to attribute presence where some booleans are not supported
var attrNode,
property = jQuery.prop( elem, name );
return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
name.toLowerCase() :
undefined;
},
set: function( elem, value, name ) {
var propName;
if ( value === false ) {
// Remove boolean attributes when set to false
jQuery.removeAttr( elem, name );
} else {
// value is true since we know at this point it's type boolean and not false
// Set boolean attributes to the same name and set the DOM property
propName = jQuery.propFix[ name ] || name;
if ( propName in elem ) {
// Only set the IDL specifically if it already exists on the element
elem[ propName ] = true;
}
elem.setAttribute( name, name.toLowerCase() );
}
return name;
}
};
// IE6/7 do not support getting/setting some attributes with get/setAttribute
if ( !getSetAttribute ) {
fixSpecified = {
name: true,
id: true,
coords: true
};
// Use this for any attribute in IE6/7
// This fixes almost every IE6/7 issue
nodeHook = jQuery.valHooks.button = {
get: function( elem, name ) {
var ret;
ret = elem.getAttributeNode( name );
return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
ret.nodeValue :
undefined;
},
set: function( elem, value, name ) {
// Set the existing or create a new attribute node
var ret = elem.getAttributeNode( name );
if ( !ret ) {
ret = document.createAttribute( name );
elem.setAttributeNode( ret );
}
return ( ret.nodeValue = value + "" );
}
};
// Apply the nodeHook to tabindex
jQuery.attrHooks.tabindex.set = nodeHook.set;
// Set width and height to auto instead of 0 on empty string( Bug #8150 )
// This is for removals
jQuery.each([ "width", "height" ], function( i, name ) {
jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
set: function( elem, value ) {
if ( value === "" ) {
elem.setAttribute( name, "auto" );
return value;
}
}
});
});
// Set contenteditable to false on removals(#10429)
// Setting to empty string throws an error as an invalid value
jQuery.attrHooks.contenteditable = {
get: nodeHook.get,
set: function( elem, value, name ) {
if ( value === "" ) {
value = "false";
}
nodeHook.set( elem, value, name );
}
};
}
// Some attributes require a special call on IE
if ( !jQuery.support.hrefNormalized ) {
jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
get: function( elem ) {
var ret = elem.getAttribute( name, 2 );
return ret === null ? undefined : ret;
}
});
});
}
if ( !jQuery.support.style ) {
jQuery.attrHooks.style = {
get: function( elem ) {
// Return undefined in the case of empty string
// Normalize to lowercase since IE uppercases css property names
return elem.style.cssText.toLowerCase() || undefined;
},
set: function( elem, value ) {
return ( elem.style.cssText = "" + value );
}
};
}
// Safari mis-reports the default selected property of an option
// Accessing the parent's selectedIndex property fixes it
if ( !jQuery.support.optSelected ) {
jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
get: function( elem ) {
var parent = elem.parentNode;
if ( parent ) {
parent.selectedIndex;
// Make sure that it also works with optgroups, see #5701
if ( parent.parentNode ) {
parent.parentNode.selectedIndex;
}
}
return null;
}
});
}
// IE6/7 call enctype encoding
if ( !jQuery.support.enctype ) {
jQuery.propFix.enctype = "encoding";
}
// Radios and checkboxes getter/setter
if ( !jQuery.support.checkOn ) {
jQuery.each([ "radio", "checkbox" ], function() {
jQuery.valHooks[ this ] = {
get: function( elem ) {
// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
return elem.getAttribute("value") === null ? "on" : elem.value;
}
};
});
}
jQuery.each([ "radio", "checkbox" ], function() {
jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
set: function( elem, value ) {
if ( jQuery.isArray( value ) ) {
return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
}
}
});
});
var rformElems = /^(?:textarea|input|select)$/i,
rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
rhoverHack = /(?:^|\s)hover(\.\S+)?\b/,
rkeyEvent = /^key/,
rmouseEvent = /^(?:mouse|contextmenu)|click/,
rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
quickParse = function( selector ) {
var quick = rquickIs.exec( selector );
if ( quick ) {
// 0 1 2 3
// [ _, tag, id, class ]
quick[1] = ( quick[1] || "" ).toLowerCase();
quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
}
return quick;
},
quickIs = function( elem, m ) {
var attrs = elem.attributes || {};
return (
(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
(!m[2] || (attrs.id || {}).value === m[2]) &&
(!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
);
},
hoverHack = function( events ) {
return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
};
/*
* Helper functions for managing events -- not part of the public interface.
* Props to Dean Edwards' addEvent library for many of the ideas.
*/
jQuery.event = {
add: function( elem, types, handler, data, selector ) {
var elemData, eventHandle, events,
t, tns, type, namespaces, handleObj,
handleObjIn, quick, handlers, special;
// Don't attach events to noData or text/comment nodes (allow plain objects tho)
if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
return;
}
// Caller can pass in an object of custom data in lieu of the handler
if ( handler.handler ) {
handleObjIn = handler;
handler = handleObjIn.handler;
selector = handleObjIn.selector;
}
// Make sure that the handler has a unique ID, used to find/remove it later
if ( !handler.guid ) {
handler.guid = jQuery.guid++;
}
// Init the element's event structure and main handler, if this is the first
events = elemData.even
gitextract_lf6w0ydf/
├── .gitignore
├── BattleCity.html
├── LICENSE
├── README.md
├── SpecRunner.html
├── css/
│ └── BattleCity.css
├── lib/
│ ├── Stats.js
│ ├── jasmine-1.2.0/
│ │ ├── MIT.LICENSE
│ │ ├── jasmine-html.js
│ │ ├── jasmine.css
│ │ └── jasmine.js
│ └── jquery-1.7.2.js
├── sound/
│ ├── bullet_hit_1.ogg
│ ├── bullet_hit_2.ogg
│ ├── bullet_shot.ogg
│ ├── explosion_1.ogg
│ ├── explosion_2.ogg
│ ├── game_over.ogg
│ ├── pause.ogg
│ ├── powerup_appear.ogg
│ ├── powerup_pick.ogg
│ ├── stage_start.ogg
│ └── statistics_1.ogg
├── spec/
│ ├── AITankControllerContainerSpec.js
│ ├── AITankControllerFactorySpec.js
│ ├── AITankControllerSpec.js
│ ├── AnimationSpec.js
│ ├── BaseExplosionFactorySpec.js
│ ├── BaseExplosionSpec.js
│ ├── BaseSpec.js
│ ├── BaseWallBuilderSpec.js
│ ├── BrickWallSpec.js
│ ├── BuilderSpec.js
│ ├── BulletExplosionFactorySpec.js
│ ├── BulletFactorySpec.js
│ ├── BulletSpec.js
│ ├── CollisionDetectorSpec.js
│ ├── ConstructionMenuItemSpec.js
│ ├── CursorControllerSpec.js
│ ├── CursorSpec.js
│ ├── CurtainSpec.js
│ ├── DelaySpec.js
│ ├── EnemyFactorySpec.js
│ ├── EventManagerSpec.js
│ ├── ExplosionSpec.js
│ ├── FreezeTimerSpec.js
│ ├── MainMenuControllerSpec.js
│ ├── MainMenuSceneSpec.js
│ ├── MainMenuSpec.js
│ ├── MoveFnSpec.js
│ ├── OnePlayerMenuItemSpec.js
│ ├── PainterSpec.js
│ ├── PauseListenerSpec.js
│ ├── PauseSpec.js
│ ├── PlayerTankControllerFactorySpec.js
│ ├── PlayerTankFactorySpec.js
│ ├── PointSpec.js
│ ├── PointsFactorySpec.js
│ ├── PointsSpec.js
│ ├── PowerUpFactorySpec.js
│ ├── PowerUpHandlerSpec.js
│ ├── PowerUpSpec.js
│ ├── RandomSpec.js
│ ├── RectSpec.js
│ ├── SceneManagerSpec.js
│ ├── ScriptSpec.js
│ ├── ShovelHandlerSpec.js
│ ├── SpriteContainerSpec.js
│ ├── SpriteControllerSpec.js
│ ├── SpriteSerializerSpec.js
│ ├── SpriteSpec.js
│ ├── SteelWallSpec.js
│ ├── StructureManagerSpec.js
│ ├── TankColorSpec.js
│ ├── TankControllerSpec.js
│ ├── TankExplosionFactorySpec.js
│ ├── TankExplosionSpec.js
│ ├── TankSpec.js
│ ├── TankStateAppearingSpec.js
│ ├── TankStateInvincibleSpec.js
│ ├── TankStateNormalSpec.js
│ ├── UpdaterSpec.js
│ ├── UtilsSpec.js
│ └── WallSpec.js
└── src/
├── AITankController.js
├── AITankControllerContainer.js
├── AITankControllerFactory.js
├── Animation.js
├── Base.js
├── BaseExplosion.js
├── BaseExplosionFactory.js
├── BaseWallBuilder.js
├── BlinkTimer.js
├── BrickWall.js
├── BrickWallFactory.js
├── Builder.js
├── Bullet.js
├── BulletExplosion.js
├── BulletExplosionFactory.js
├── BulletFactory.js
├── CollisionDetector.js
├── Construction.js
├── ConstructionMenuItem.js
├── Cursor.js
├── CursorController.js
├── Curtain.js
├── Delay.js
├── EnemyFactory.js
├── EnemyFactoryView.js
├── EventManager.js
├── Explosion.js
├── FPSCounter.js
├── FreezeTimer.js
├── GameOverMessage.js
├── GameOverScene.js
├── GameScene.js
├── Gamefield.js
├── Globals.js
├── ImageManager.js
├── Keyboard.js
├── Level.js
├── LivesView.js
├── LoadingScene.js
├── MainMenu.js
├── MainMenuController.js
├── MainMenuCursor.js
├── MainMenuCursorView.js
├── MainMenuItem.js
├── MainMenuScene.js
├── MainMenuView.js
├── MoveFn.js
├── OnePlayerMenuItem.js
├── Painter.js
├── Pause.js
├── PauseListener.js
├── Player.js
├── PlayerTankControllerFactory.js
├── PlayerTankFactory.js
├── Point.js
├── Points.js
├── PointsFactory.js
├── PowerUp.js
├── PowerUpFactory.js
├── PowerUpHandler.js
├── Random.js
├── Rect.js
├── SceneManager.js
├── Script.js
├── ShovelHandler.js
├── SoundManager.js
├── Sprite.js
├── SpriteContainer.js
├── SpriteController.js
├── SpriteSerializer.js
├── SpriteSerializerController.js
├── StageMessage.js
├── StageStatisticsPoints.js
├── StageStatisticsScene.js
├── Stages.js
├── SteelWall.js
├── SteelWallFactory.js
├── StructureManager.js
├── Tank.js
├── TankColor.js
├── TankController.js
├── TankExplosion.js
├── TankExplosionFactory.js
├── TankStateAppearing.js
├── TankStateInvincible.js
├── TankStateNormal.js
├── Trees.js
├── Updater.js
├── Utils.js
├── Wall.js
└── Water.js
SYMBOL INDEX (147 symbols across 95 files)
FILE: lib/jasmine-1.2.0/jasmine-html.js
function focusedSpecName (line 125) | function focusedSpecName() {
function createReporterDom (line 147) | function createReporterDom(version) {
function showDetails (line 298) | function showDetails() {
function isUndefined (line 304) | function isUndefined(obj) {
function isDefined (line 308) | function isDefined(obj) {
function specPluralizedFor (line 312) | function specPluralizedFor(count) {
FILE: lib/jasmine-1.2.0/jasmine.js
function getGlobal (line 43) | function getGlobal() {
function tryIt (line 608) | function tryIt(f) {
FILE: lib/jquery-1.7.2.js
function jQuerySub (line 897) | function jQuerySub( selector, context ) {
function doScrollCheck (line 963) | function doScrollCheck() {
function createFlags (line 990) | function createFlags( flags ) {
function resolveFunc (line 1325) | function resolveFunc( i ) {
function progressFunc (line 1333) | function progressFunc( i ) {
function dataAttr (line 1985) | function dataAttr( elem, key, data ) {
function isEmptyDataObject (line 2016) | function isEmptyDataObject( obj ) {
function handleQueueMarkDefer (line 2034) | function handleQueueMarkDefer( elem, type, src ) {
function resolve (line 2193) | function resolve() {
function returnFalse (line 3546) | function returnFalse() {
function returnTrue (line 3549) | function returnTrue() {
function dirNodeCheck (line 5260) | function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
function dirCheck (line 5293) | function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
function isDisconnected (line 5566) | function isDisconnected( node ) {
function winnow (line 5683) | function winnow( elements, qualifier, keep ) {
function createSafeFragment (line 5720) | function createSafeFragment( document ) {
function root (line 6092) | function root( elem, cur ) {
function cloneCopyEvent (line 6099) | function cloneCopyEvent( src, dest ) {
function cloneFixAttributes (line 6127) | function cloneFixAttributes( src, dest ) {
function getAll (line 6272) | function getAll( elem ) {
function fixDefaultChecked (line 6285) | function fixDefaultChecked( elem ) {
function findInputs (line 6291) | function findInputs( elem ) {
function shimCloneNode (line 6302) | function shimCloneNode( elem ) {
function getWidthOrHeight (line 6793) | function getWidthOrHeight( elem, name, extra ) {
function addToPrefiltersOrTransports (line 7034) | function addToPrefiltersOrTransports( structure ) {
function inspectPrefiltersOrTransports (line 7070) | function inspectPrefiltersOrTransports( structure, options, originalOpti...
function ajaxExtend (line 7112) | function ajaxExtend( target, src ) {
function done (line 7454) | function done( status, nativeStatusText, responses, headers ) {
function buildParams (line 7769) | function buildParams( prefix, obj, traditional, add ) {
function ajaxHandleResponses (line 7819) | function ajaxHandleResponses( s, jqXHR, responses ) {
function ajaxConvert (line 7884) | function ajaxConvert( s, response ) {
function createStandardXHR (line 8149) | function createStandardXHR() {
function createActiveXHR (line 8155) | function createActiveXHR() {
function doAnimation (line 8494) | function doAnimation() {
function stopQueue (line 8650) | function stopQueue( elem, data, index ) {
function createFxNow (line 8692) | function createFxNow() {
function clearFxNow (line 8697) | function clearFxNow() {
function genFx (line 8702) | function genFx( type, num ) {
function t (line 8817) | function t( gotoEnd ) {
function defaultDisplay (line 9015) | function defaultDisplay( nodeName ) {
function getWindow (line 9299) | function getWindow( elem ) {
FILE: spec/BulletFactorySpec.js
function checkDirection (line 26) | function checkDirection(tankPosition, bulletPosition, direction) {
function checkType (line 61) | function checkType(type) {
FILE: spec/MainMenuSceneSpec.js
function checkKey (line 30) | function checkKey(key) {
FILE: spec/SpriteControllerSpec.js
function checkPressedKey (line 34) | function checkPressedKey(initialDirection, pressedKey, expectedSpeed, ex...
function checkReleasedKey (line 59) | function checkReleasedKey(key, expectedSpeed) {
FILE: spec/SpriteSpec.js
function checkDirection (line 78) | function checkDirection(direction, finalPosition) {
function checkDirection (line 173) | function checkDirection(spritePosition, direction, resolvedPosition) {
FILE: spec/TankSpec.js
function checkDirection (line 80) | function checkDirection(tankRect, wallRect, direction, resolvedTankPosit...
function checkMove (line 99) | function checkMove(limit, expectedPos) {
FILE: src/AITankController.js
function AITankController (line 1) | function AITankController(tank, random, spriteContainer) {
FILE: src/AITankControllerContainer.js
function AITankControllerContainer (line 1) | function AITankControllerContainer(eventManager) {
FILE: src/AITankControllerFactory.js
function AITankControllerFactory (line 1) | function AITankControllerFactory(eventManager, spriteContainer) {
FILE: src/Animation.js
function Animation (line 1) | function Animation(frames, frameDuration, loop) {
FILE: src/Base.js
function Base (line 1) | function Base(eventManager) {
FILE: src/BaseExplosion.js
function BaseExplosion (line 1) | function BaseExplosion(eventManager) {
FILE: src/BaseExplosionFactory.js
function BaseExplosionFactory (line 1) | function BaseExplosionFactory(eventManager) {
FILE: src/BaseWallBuilder.js
function BaseWallBuilder (line 1) | function BaseWallBuilder() {
FILE: src/BlinkTimer.js
function BlinkTimer (line 1) | function BlinkTimer(duration) {
FILE: src/BrickWall.js
function BrickWall (line 1) | function BrickWall(eventManager) {
FILE: src/BrickWallFactory.js
function BrickWallFactory (line 1) | function BrickWallFactory(eventManager) {
FILE: src/Builder.js
function Builder (line 1) | function Builder(eventManager) {
FILE: src/Bullet.js
function Bullet (line 1) | function Bullet(eventManager, tank) {
FILE: src/BulletExplosion.js
function BulletExplosion (line 1) | function BulletExplosion(eventManager) {
FILE: src/BulletExplosionFactory.js
function BulletExplosionFactory (line 1) | function BulletExplosionFactory(eventManager) {
FILE: src/BulletFactory.js
function BulletFactory (line 1) | function BulletFactory(eventManager) {
FILE: src/CollisionDetector.js
function CollisionDetector (line 1) | function CollisionDetector(eventManager, bounds, spriteContainer) {
FILE: src/Construction.js
function Construction (line 1) | function Construction(sceneManager) {
FILE: src/ConstructionMenuItem.js
function ConstructionMenuItem (line 1) | function ConstructionMenuItem(sceneManager) {
FILE: src/Cursor.js
function Cursor (line 1) | function Cursor(eventManager) {
FILE: src/CursorController.js
function CursorController (line 1) | function CursorController(eventManager, cursor) {
FILE: src/Curtain.js
function Curtain (line 1) | function Curtain() {
FILE: src/Delay.js
function Delay (line 1) | function Delay(script, duration) {
FILE: src/EnemyFactory.js
function EnemyFactory (line 1) | function EnemyFactory(eventManager) {
FILE: src/EnemyFactoryView.js
function EnemyFactoryView (line 1) | function EnemyFactoryView(enemyFactory) {
FILE: src/EventManager.js
function EventManager (line 1) | function EventManager() {
FILE: src/Explosion.js
function Explosion (line 1) | function Explosion(eventManager) {
FILE: src/FPSCounter.js
function FPSCounter (line 4) | function FPSCounter() {
FILE: src/FreezeTimer.js
function FreezeTimer (line 1) | function FreezeTimer(eventManager) {
FILE: src/GameOverMessage.js
function GameOverMessage (line 1) | function GameOverMessage() {
FILE: src/GameOverScene.js
function GameOverScene (line 1) | function GameOverScene(sceneManager) {
FILE: src/GameScene.js
function GameScene (line 1) | function GameScene(sceneManager, stage, player) {
FILE: src/Gamefield.js
function Gamefield (line 1) | function Gamefield(sceneManager) {
FILE: src/Keyboard.js
function Keyboard (line 1) | function Keyboard(eventManager) {
FILE: src/Level.js
function Level (line 1) | function Level(sceneManager, stageNumber, player) {
FILE: src/LivesView.js
function LivesView (line 1) | function LivesView(player) {
FILE: src/LoadingScene.js
function LoadingScene (line 1) | function LoadingScene(sceneManager) {
FILE: src/MainMenu.js
function MainMenu (line 1) | function MainMenu() {
FILE: src/MainMenuController.js
function MainMenuController (line 1) | function MainMenuController(eventManager, mainMenu) {
FILE: src/MainMenuCursor.js
function MainMenuCursor (line 1) | function MainMenuCursor() {
FILE: src/MainMenuCursorView.js
function MainMenuCursorView (line 1) | function MainMenuCursorView(cursor) {
FILE: src/MainMenuItem.js
function MainMenuItem (line 1) | function MainMenuItem(sceneManager) {
FILE: src/MainMenuScene.js
function MainMenuScene (line 1) | function MainMenuScene(sceneManager) {
FILE: src/MainMenuView.js
function MainMenuView (line 1) | function MainMenuView(mainMenu, cursorView) {
FILE: src/MoveFn.js
function MoveFn (line 1) | function MoveFn(object, property, endValue, duration, listener) {
FILE: src/OnePlayerMenuItem.js
function OnePlayerMenuItem (line 1) | function OnePlayerMenuItem(sceneManager) {
FILE: src/Painter.js
function Painter (line 1) | function Painter(spriteContainer) {
FILE: src/Pause.js
function Pause (line 1) | function Pause(eventManager) {
FILE: src/PauseListener.js
function PauseListener (line 1) | function PauseListener(eventManager) {
FILE: src/Player.js
function Player (line 1) | function Player() {
FILE: src/PlayerTankControllerFactory.js
function PlayerTankControllerFactory (line 1) | function PlayerTankControllerFactory(eventManager) {
FILE: src/PlayerTankFactory.js
function PlayerTankFactory (line 1) | function PlayerTankFactory(eventManager) {
FILE: src/Point.js
function Point (line 1) | function Point(x, y) {
FILE: src/Points.js
function Points (line 1) | function Points(eventManager) {
FILE: src/PointsFactory.js
function PointsFactory (line 1) | function PointsFactory(eventManager) {
FILE: src/PowerUp.js
function PowerUp (line 1) | function PowerUp(eventManager) {
FILE: src/PowerUpFactory.js
function PowerUpFactory (line 1) | function PowerUpFactory(eventManager) {
FILE: src/PowerUpHandler.js
function PowerUpHandler (line 1) | function PowerUpHandler(eventManager) {
FILE: src/Random.js
function Random (line 1) | function Random() {}
FILE: src/Rect.js
function Rect (line 1) | function Rect(x, y, w, h) {
FILE: src/SceneManager.js
function SceneManager (line 1) | function SceneManager(eventManager) {
FILE: src/Script.js
function Script (line 1) | function Script() {
FILE: src/ShovelHandler.js
function ShovelHandler (line 1) | function ShovelHandler(eventManager) {
FILE: src/Sprite.js
function Sprite (line 1) | function Sprite(eventManager) {
FILE: src/SpriteContainer.js
function SpriteContainer (line 1) | function SpriteContainer(eventManager) {
FILE: src/SpriteController.js
function SpriteController (line 1) | function SpriteController(eventManager, sprite) {
FILE: src/SpriteSerializer.js
function SpriteSerializer (line 1) | function SpriteSerializer(eventManager) {
FILE: src/SpriteSerializerController.js
function SpriteSerializerController (line 1) | function SpriteSerializerController(eventManager, structureManager) {
FILE: src/StageMessage.js
function StageMessage (line 1) | function StageMessage(stage) {
FILE: src/StageStatisticsPoints.js
function StageStatisticsPoints (line 1) | function StageStatisticsPoints(value, count, listener) {
FILE: src/StageStatisticsScene.js
function StageStatisticsScene (line 1) | function StageStatisticsScene(sceneManager, stage, player, gameOver) {
FILE: src/SteelWall.js
function SteelWall (line 1) | function SteelWall(eventManager) {
FILE: src/SteelWallFactory.js
function SteelWallFactory (line 1) | function SteelWallFactory(eventManager) {
FILE: src/StructureManager.js
function StructureManager (line 1) | function StructureManager(eventManager) {
FILE: src/Tank.js
function Tank (line 1) | function Tank(eventManager) {
FILE: src/TankColor.js
function TankColor (line 1) | function TankColor() {
FILE: src/TankController.js
function TankController (line 1) | function TankController(eventManager, tank) {
FILE: src/TankExplosion.js
function TankExplosion (line 1) | function TankExplosion(eventManager, tank) {
FILE: src/TankExplosionFactory.js
function TankExplosionFactory (line 1) | function TankExplosionFactory(eventManager) {
FILE: src/TankStateAppearing.js
function TankStateAppearing (line 1) | function TankStateAppearing(tank) {
FILE: src/TankStateInvincible.js
function TankStateInvincible (line 1) | function TankStateInvincible(tank) {
FILE: src/TankStateNormal.js
function TankStateNormal (line 1) | function TankStateNormal(tank) {
FILE: src/Trees.js
function Trees (line 1) | function Trees(eventManager) {
FILE: src/Updater.js
function Updater (line 1) | function Updater(spriteContainer) {
FILE: src/Utils.js
function arrayContains (line 17) | function arrayContains(arr, obj) {
function arrayRemove (line 26) | function arrayRemove(arr, obj) {
function arrayRandomElement (line 34) | function arrayRandomElement(arr) {
FILE: src/Wall.js
function Wall (line 1) | function Wall(eventManager) {
FILE: src/Water.js
function Water (line 1) | function Water(eventManager) {
Condensed preview — 175 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (746K chars).
[
{
"path": ".gitignore",
"chars": 25,
"preview": "/nbproject/\r\n/NOTES.txt\r\n"
},
{
"path": "BattleCity.html",
"chars": 8365,
"preview": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n "
},
{
"path": "LICENSE",
"chars": 1074,
"preview": "MIT License\n\nCopyright (c) 2021 Vyacheslav Rachek\n\nPermission is hereby granted, free of charge, to any person obtaining"
},
{
"path": "README.md",
"chars": 375,
"preview": "JavaScript/HTML5 remake of the Famicom \"Battle City\" game\n=====================================================\n\n[Play]("
},
{
"path": "SpecRunner.html",
"chars": 11226,
"preview": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n<head>\n "
},
{
"path": "css/BattleCity.css",
"chars": 415,
"preview": "@font-face {\r\n font-family: prstart;\r\n src: url('../fonts/prstart.ttf');\r\n}\r\nbody {\r\n font-family: prstart;\r\n font-s"
},
{
"path": "lib/Stats.js",
"chars": 3473,
"preview": "/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nvar Stats = function () {\n\n\tvar startTime = Date.now(), prevTime = start"
},
{
"path": "lib/jasmine-1.2.0/MIT.LICENSE",
"chars": 1061,
"preview": "Copyright (c) 2008-2011 Pivotal Labs\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of th"
},
{
"path": "lib/jasmine-1.2.0/jasmine-html.js",
"chars": 19065,
"preview": "jasmine.HtmlReporterHelpers = {};\n\njasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) {\n va"
},
{
"path": "lib/jasmine-1.2.0/jasmine.css",
"chars": 6444,
"preview": "body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }\n\n#HTMLReporter { font-size: 11px; font-"
},
{
"path": "lib/jasmine-1.2.0/jasmine.js",
"chars": 68641,
"preview": "var isCommonJS = typeof window == \"undefined\";\n\n/**\n * Top level namespace for Jasmine, a lightweight JavaScript BDD/spe"
},
{
"path": "lib/jquery-1.7.2.js",
"chars": 252881,
"preview": "/*!\n * jQuery JavaScript Library v1.7.2\n * http://jquery.com/\n *\n * Copyright 2011, John Resig\n * Dual licensed under th"
},
{
"path": "spec/AITankControllerContainerSpec.js",
"chars": 1965,
"preview": "describe(\"AITankControllerContainer\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new "
},
{
"path": "spec/AITankControllerFactorySpec.js",
"chars": 2191,
"preview": "describe(\"AITankControllerFactory\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new Ev"
},
{
"path": "spec/AITankControllerSpec.js",
"chars": 8292,
"preview": "describe(\"AITankController\", function () {\r\n it(\"should fire event on creation\", function () {\r\n var eventManager = "
},
{
"path": "spec/AnimationSpec.js",
"chars": 1411,
"preview": "describe(\"Animation\", function () {\r\n it(\"no loop\", function () {\r\n var animation = new Animation([1,2]);\r\n expec"
},
{
"path": "spec/BaseExplosionFactorySpec.js",
"chars": 1442,
"preview": "describe(\"BaseExplosionFactory\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new Event"
},
{
"path": "spec/BaseExplosionSpec.js",
"chars": 379,
"preview": "describe(\"BaseExplosion\", function () {\r\n it(\"#destroyHook\", function () {\r\n var eventManager = new EventManager();\r"
},
{
"path": "spec/BaseSpec.js",
"chars": 1705,
"preview": "describe(\"Base\", function () {\r\n it(\"#getClassName\", function () {\r\n var eventManager = new EventManager();\r\n var"
},
{
"path": "spec/BaseWallBuilderSpec.js",
"chars": 957,
"preview": "describe(\"BaseWallBuilder\", function () {\r\n it(\"#buildWall and #destroyWall\", function () {\r\n var eventManager = new"
},
{
"path": "spec/BrickWallSpec.js",
"chars": 230,
"preview": "describe(\"BrickWall\", function () {\r\n it(\"#getClassName\", function () {\r\n var eventManager = new EventManager();\r\n "
},
{
"path": "spec/BuilderSpec.js",
"chars": 8810,
"preview": "describe(\"Builder\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventManager();\r\n "
},
{
"path": "spec/BulletExplosionFactorySpec.js",
"chars": 2062,
"preview": "describe(\"BulletExplosionFactory\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new Eve"
},
{
"path": "spec/BulletFactorySpec.js",
"chars": 2619,
"preview": "describe(\"BulletFactory\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventManager"
},
{
"path": "spec/BulletSpec.js",
"chars": 5557,
"preview": "describe(\"Bullet\", function () {\r\n var eventManager, tank, bullet;\r\n \r\n beforeEach(function () {\r\n eventManager = "
},
{
"path": "spec/CollisionDetectorSpec.js",
"chars": 2076,
"preview": "describe(\"CollisionDetector\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventMan"
},
{
"path": "spec/ConstructionMenuItemSpec.js",
"chars": 328,
"preview": "describe(\"ConstructionMenuItem\", function () {\r\n it(\"#execute\", function () {\r\n var sceneManager = new SceneManager("
},
{
"path": "spec/CursorControllerSpec.js",
"chars": 1642,
"preview": "describe(\"CursorController\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventMana"
},
{
"path": "spec/CursorSpec.js",
"chars": 1834,
"preview": "describe(\"Cursor\", function () {\r\n it(\"should move with a delay\", function () {\r\n var eventManager = new EventManage"
},
{
"path": "spec/CurtainSpec.js",
"chars": 1965,
"preview": "describe(\"Curtain\", function () {\r\n var eventManager, curtain;\r\n \r\n beforeEach(function () {\r\n eventManager = new "
},
{
"path": "spec/DelaySpec.js",
"chars": 506,
"preview": "describe(\"Delay\", function () {\r\n it(\"#update\", function () {\r\n var script = jasmine.createSpyObj('script', ['action"
},
{
"path": "spec/EnemyFactorySpec.js",
"chars": 10742,
"preview": "describe(\"EnemyFactory\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventManager("
},
{
"path": "spec/EventManagerSpec.js",
"chars": 1659,
"preview": "describe(\"Event Manager\", function () {\r\n it(\"should notify subscribers about events\", function () {\r\n var EVENT_1 ="
},
{
"path": "spec/ExplosionSpec.js",
"chars": 903,
"preview": "describe(\"Explosion\", function () {\r\n describe(\"#updateHook\", function () {\r\n it(\"normal\", function () {\r\n var "
},
{
"path": "spec/FreezeTimerSpec.js",
"chars": 2487,
"preview": "describe(\"FreezeTimer\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventManager()"
},
{
"path": "spec/MainMenuControllerSpec.js",
"chars": 2053,
"preview": "describe(\"MainMenuController\", function () {\r\n it(\"subscribe\", function () {\r\n var eventManager = new EventManager()"
},
{
"path": "spec/MainMenuSceneSpec.js",
"chars": 4079,
"preview": "describe(\"MainMenuScene\", function () {\r\n it(\"subscribe\", function () {\r\n var eventManager = new EventManager();\r\n "
},
{
"path": "spec/MainMenuSpec.js",
"chars": 1348,
"preview": "describe(\"MainMenu\", function () {\r\n it(\"#nextItem\", function () {\r\n var sceneManager = new SceneManager();\r\n var"
},
{
"path": "spec/MoveFnSpec.js",
"chars": 3257,
"preview": "describe(\"MoveFn\", function () {\r\n describe(\"#update\", function () {\r\n describe(\"positive increment\", function () {\r"
},
{
"path": "spec/OnePlayerMenuItemSpec.js",
"chars": 306,
"preview": "describe(\"OnePlayerMenuItem\", function () {\r\n it(\"#execute\", function () {\r\n var sceneManager = new SceneManager();\r"
},
{
"path": "spec/PainterSpec.js",
"chars": 622,
"preview": "describe(\"Painter\", function () {\r\n it(\"should draw sprites\", function () {\r\n var eventManager = new EventManager();"
},
{
"path": "spec/PauseListenerSpec.js",
"chars": 1659,
"preview": "describe(\"PauseListener\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventManager"
},
{
"path": "spec/PauseSpec.js",
"chars": 1148,
"preview": "describe(\"Pause\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventManager();\r\n "
},
{
"path": "spec/PlayerTankControllerFactorySpec.js",
"chars": 1143,
"preview": "describe(\"PlayerTankControllerFactory\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = ne"
},
{
"path": "spec/PlayerTankFactorySpec.js",
"chars": 1407,
"preview": "describe(\"PlayerTankFactory\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventMan"
},
{
"path": "spec/PointSpec.js",
"chars": 442,
"preview": "describe(\"Point\", function () {\r\n it(\"default state\", function () {\r\n var point = new Point();\r\n expect(point.get"
},
{
"path": "spec/PointsFactorySpec.js",
"chars": 3350,
"preview": "describe(\"PointsFactory\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventManager"
},
{
"path": "spec/PointsSpec.js",
"chars": 1472,
"preview": "describe(\"Points\", function () {\r\n it(\"#update\", function () {\r\n var eventManager = new EventManager();\r\n var poi"
},
{
"path": "spec/PowerUpFactorySpec.js",
"chars": 1045,
"preview": "describe(\"PowerUpFactory\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventManage"
},
{
"path": "spec/PowerUpHandlerSpec.js",
"chars": 4957,
"preview": "describe(\"PowerUpHandler\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventManage"
},
{
"path": "spec/PowerUpSpec.js",
"chars": 1877,
"preview": "describe(\"PowerUp\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventManager();\r\n "
},
{
"path": "spec/RandomSpec.js",
"chars": 250,
"preview": "describe(\"Random\", function () {\r\n it(\"#getNumber\", function () {\r\n var random = new Random();\r\n var number = ran"
},
{
"path": "spec/RectSpec.js",
"chars": 2496,
"preview": "describe(\"Rect\", function () {\r\n it(\"default state\", function () {\r\n var rect = new Rect();\r\n expect(rect.getWidt"
},
{
"path": "spec/SceneManagerSpec.js",
"chars": 562,
"preview": "describe(\"SceneManager\", function () {\r\n it(\"#update\", function () {\r\n var eventManager = new EventManager();\r\n v"
},
{
"path": "spec/ScriptSpec.js",
"chars": 1919,
"preview": "describe(\"Script\", function () {\r\n var MockAction = function (script, numUpdates) {\r\n this._script = script;\r\n th"
},
{
"path": "spec/ShovelHandlerSpec.js",
"chars": 3988,
"preview": "describe(\"ShovelHandler\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventManager"
},
{
"path": "spec/SpriteContainerSpec.js",
"chars": 3581,
"preview": "describe(\"SpriteContainer\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventManag"
},
{
"path": "spec/SpriteControllerSpec.js",
"chars": 3236,
"preview": "describe(\"SpriteController\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventMana"
},
{
"path": "spec/SpriteSerializerSpec.js",
"chars": 1197,
"preview": "describe(\"SpriteSerializer\", function () {\r\n it(\"#serializeSprite\", function () {\r\n var eventManager = new EventMana"
},
{
"path": "spec/SpriteSpec.js",
"chars": 6222,
"preview": "describe(\"Sprite\", function () {\r\n var eventManager, sprite;\r\n \r\n beforeEach(function () {\r\n eventManager = new "
},
{
"path": "spec/SteelWallSpec.js",
"chars": 430,
"preview": "describe(\"SteelWall\", function () {\r\n it(\"initial state\", function () {\r\n var eventManager = new EventManager();\r\n "
},
{
"path": "spec/StructureManagerSpec.js",
"chars": 4138,
"preview": "describe(\"StructureManager\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new EventMana"
},
{
"path": "spec/TankColorSpec.js",
"chars": 1901,
"preview": "describe(\"TankColor\", function () {\r\n describe(\"#update\", function () {\r\n var color;\r\n \r\n beforeEach(function "
},
{
"path": "spec/TankControllerSpec.js",
"chars": 432,
"preview": "describe(\"TankController\", function () {\r\n describe(\"keyPressed\", function () {\r\n it(\"Keyboard.Key.SPACE\", function "
},
{
"path": "spec/TankExplosionFactorySpec.js",
"chars": 1499,
"preview": "describe(\"TankExplosionFactory\", function () {\r\n it(\"should subscribe\", function () {\r\n var eventManager = new Event"
},
{
"path": "spec/TankExplosionSpec.js",
"chars": 379,
"preview": "describe(\"TankExplosion\", function () {\r\n it(\"#destroyHook\", function () {\r\n var eventManager = new EventManager();\r"
},
{
"path": "spec/TankSpec.js",
"chars": 16848,
"preview": "describe(\"Tank\", function () {\r\n var eventManager, tank;\r\n \r\n beforeEach(function () {\r\n eventManager = new EventM"
},
{
"path": "spec/TankStateAppearingSpec.js",
"chars": 1320,
"preview": "describe(\"TankStateAppearing\", function () {\r\n var eventManager, tank, state;\r\n \r\n beforeEach(function () {\r\n even"
},
{
"path": "spec/TankStateInvincibleSpec.js",
"chars": 1276,
"preview": "describe(\"TankStateInvincible\", function () {\r\n var eventManager, tank, state;\r\n \r\n beforeEach(function () {\r\n eve"
},
{
"path": "spec/TankStateNormalSpec.js",
"chars": 3606,
"preview": "describe(\"TankStateNormal\", function () {\r\n var eventManager, tank, state;\r\n \r\n beforeEach(function () {\r\n eventMa"
},
{
"path": "spec/UpdaterSpec.js",
"chars": 590,
"preview": "describe(\"Updater\", function () {\r\n it(\"should update sprites\", function () {\r\n var eventManager = new EventManager("
},
{
"path": "spec/UtilsSpec.js",
"chars": 1065,
"preview": "describe(\"arrayContains\", function () {\r\n it(\"should tell if an array contains an object\", function () {\r\n var objec"
},
{
"path": "spec/WallSpec.js",
"chars": 5432,
"preview": "describe(\"Wall\", function () {\r\n it(\"initial state\", function () {\r\n var eventManager = new EventManager();\r\n var"
},
{
"path": "src/AITankController.js",
"chars": 4312,
"preview": "function AITankController(tank, random, spriteContainer) {\r\n this._tank = tank;\r\n this._random = random;\r\n this._spri"
},
{
"path": "src/AITankControllerContainer.js",
"chars": 1166,
"preview": "function AITankControllerContainer(eventManager) {\r\n this._eventManager = eventManager;\r\n eventManager.addSubscriber(t"
},
{
"path": "src/AITankControllerFactory.js",
"chars": 1172,
"preview": "function AITankControllerFactory(eventManager, spriteContainer) {\r\n this._eventManager = eventManager;\r\n this._eventMa"
},
{
"path": "src/Animation.js",
"chars": 1212,
"preview": "function Animation(frames, frameDuration, loop) {\r\n this._frames = frames !== undefined ? frames : [];\r\n this._frameDu"
},
{
"path": "src/Base.js",
"chars": 1209,
"preview": "function Base(eventManager) {\r\n Sprite.call(this, eventManager);\r\n \r\n this._eventManager.addSubscriber(this, [Collisi"
},
{
"path": "src/BaseExplosion.js",
"chars": 534,
"preview": "function BaseExplosion(eventManager) {\r\n Explosion.call(this, eventManager);\r\n this._animation = new Animation([1,2,3,"
},
{
"path": "src/BaseExplosionFactory.js",
"chars": 959,
"preview": "function BaseExplosionFactory(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber("
},
{
"path": "src/BaseWallBuilder.js",
"chars": 1001,
"preview": "function BaseWallBuilder() {\r\n this._positions = [];\r\n this._factory = null;\r\n this._spriteContainer = null\r\n}\r\n\r\nBas"
},
{
"path": "src/BlinkTimer.js",
"chars": 457,
"preview": "function BlinkTimer(duration) {\r\n this._duration = duration;\r\n this._timer = 0;\r\n this._visible = true;\r\n}\r\n\r\nBlinkTi"
},
{
"path": "src/BrickWall.js",
"chars": 257,
"preview": "function BrickWall(eventManager) {\r\n Wall.call(this, eventManager);\r\n}\r\n\r\nBrickWall.subclass(Wall);\r\n\r\nBrickWall.protot"
},
{
"path": "src/BrickWallFactory.js",
"chars": 186,
"preview": "function BrickWallFactory(eventManager) {\r\n this._eventManager = eventManager;\r\n}\r\n\r\nBrickWallFactory.prototype.create "
},
{
"path": "src/Builder.js",
"chars": 9191,
"preview": "function Builder(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber(this, [Cursor"
},
{
"path": "src/Bullet.js",
"chars": 3748,
"preview": "function Bullet(eventManager, tank) {\r\n Sprite.call(this, eventManager);\r\n eventManager.addSubscriber(this, [\r\n Col"
},
{
"path": "src/BulletExplosion.js",
"chars": 287,
"preview": "function BulletExplosion(eventManager) {\r\n Explosion.call(this, eventManager);\r\n this._animation = new Animation([1,2,"
},
{
"path": "src/BulletExplosionFactory.js",
"chars": 984,
"preview": "function BulletExplosionFactory(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscribe"
},
{
"path": "src/BulletFactory.js",
"chars": 1537,
"preview": "function BulletFactory(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber(this, ["
},
{
"path": "src/CollisionDetector.js",
"chars": 1430,
"preview": "function CollisionDetector(eventManager, bounds, spriteContainer) {\r\n this._eventManager = eventManager;\r\n this._event"
},
{
"path": "src/Construction.js",
"chars": 2761,
"preview": "function Construction(sceneManager) {\r\n Gamefield.call(this, sceneManager);\r\n \r\n this._eventManager.addSubscriber(thi"
},
{
"path": "src/ConstructionMenuItem.js",
"chars": 280,
"preview": "function ConstructionMenuItem(sceneManager) {\r\n MainMenuItem.call(this, sceneManager);\r\n this.setName(\"CONSTRUCTION\");"
},
{
"path": "src/Cursor.js",
"chars": 1680,
"preview": "function Cursor(eventManager) {\r\n Sprite.call(this, eventManager);\r\n \r\n eventManager.addSubscriber(this, [CollisionDe"
},
{
"path": "src/CursorController.js",
"chars": 922,
"preview": "function CursorController(eventManager, cursor) {\r\n SpriteController.call(this, eventManager, cursor);\r\n this._eventMa"
},
{
"path": "src/Curtain.js",
"chars": 1249,
"preview": "function Curtain() {\r\n this._height = Globals.CANVAS_HEIGHT / 2;\r\n this._speed = 15;\r\n this._position = 0;\r\n}\r\n\r\nCurt"
},
{
"path": "src/Delay.js",
"chars": 260,
"preview": "function Delay(script, duration) {\r\n this._script = script;\r\n this._duration = duration;\r\n this._timer = 0;\r\n}\r\n\r\nDel"
},
{
"path": "src/EnemyFactory.js",
"chars": 4122,
"preview": "function EnemyFactory(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber(this, [P"
},
{
"path": "src/EnemyFactoryView.js",
"chars": 386,
"preview": "function EnemyFactoryView(enemyFactory) {\r\n this._enemyFactory = enemyFactory;\r\n}\r\n\r\nEnemyFactoryView.prototype.draw = "
},
{
"path": "src/EventManager.js",
"chars": 861,
"preview": "function EventManager() {\r\n this._subscribers = {};\r\n}\r\n\r\nEventManager.prototype.addSubscriber = function (subscriber, "
},
{
"path": "src/Explosion.js",
"chars": 589,
"preview": "function Explosion(eventManager) {\r\n Sprite.call(this, eventManager);\r\n this._animation = new Animation();\r\n}\r\n\r\nExplo"
},
{
"path": "src/FPSCounter.js",
"chars": 477,
"preview": "/**\r\n * Wrapper around Stats.js library.\r\n */\r\nfunction FPSCounter() {\r\n this._stats = new Stats();\r\n this._stats.setM"
},
{
"path": "src/FreezeTimer.js",
"chars": 1086,
"preview": "function FreezeTimer(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber(this, [Po"
},
{
"path": "src/GameOverMessage.js",
"chars": 264,
"preview": "function GameOverMessage() {\r\n this.x = 210;\r\n this.y = Globals.CANVAS_HEIGHT + 16;\r\n}\r\n\r\nGameOverMessage.prototype.dr"
},
{
"path": "src/GameOverScene.js",
"chars": 686,
"preview": "function GameOverScene(sceneManager) {\r\n this._sceneManager = sceneManager;\r\n \r\n this._script = new Script();\r\n this"
},
{
"path": "src/GameScene.js",
"chars": 1317,
"preview": "function GameScene(sceneManager, stage, player) {\r\n var self = this;\r\n this._sceneManager = sceneManager;\r\n this._cur"
},
{
"path": "src/Gamefield.js",
"chars": 1000,
"preview": "function Gamefield(sceneManager) {\r\n Rect.call(this);\r\n \r\n this._sceneManager = sceneManager;\r\n this._eventManager ="
},
{
"path": "src/Globals.js",
"chars": 185,
"preview": "Globals = {};\r\n\r\nGlobals.UNIT_SIZE = 32;\r\nGlobals.TILE_SIZE = Globals.UNIT_SIZE / 2;\r\n\r\nGlobals.CANVAS_WIDTH = Globals.U"
},
{
"path": "src/ImageManager.js",
"chars": 5740,
"preview": "var ImageManager = (function() {\r\n var images = {\r\n tank_player1_down_c0_t1: null,\r\n tank_player1_down_c0_t2: nul"
},
{
"path": "src/Keyboard.js",
"chars": 1229,
"preview": "function Keyboard(eventManager) {\r\n this._eventManager = eventManager;\r\n this._events = [];\r\n this._listen();\r\n this"
},
{
"path": "src/Level.js",
"chars": 6710,
"preview": "function Level(sceneManager, stageNumber, player) {\r\n Gamefield.call(this, sceneManager);\r\n \r\n var self = this;\r\n \r\n"
},
{
"path": "src/LivesView.js",
"chars": 394,
"preview": "function LivesView(player) {\r\n this._player = player;\r\n}\r\n\r\nLivesView.prototype.draw = function (ctx) {\r\n ctx.fillStyl"
},
{
"path": "src/LoadingScene.js",
"chars": 586,
"preview": "function LoadingScene(sceneManager) {\r\n this._sceneManager = sceneManager;\r\n this._loadingProgress = 0;\r\n}\r\n\r\n\r\nLoadin"
},
{
"path": "src/MainMenu.js",
"chars": 852,
"preview": "function MainMenu() {\r\n this._items = [];\r\n this._item = 0;\r\n}\r\n\r\nMainMenu.prototype.setItems = function (items) {\r\n "
},
{
"path": "src/MainMenuController.js",
"chars": 811,
"preview": "function MainMenuController(eventManager, mainMenu) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSub"
},
{
"path": "src/MainMenuCursor.js",
"chars": 477,
"preview": "function MainMenuCursor() {\r\n this._trackAnimation = new Animation([1,2], 2, true);\r\n this._visible = false;\r\n}\r\n\r\nMai"
},
{
"path": "src/MainMenuCursorView.js",
"chars": 381,
"preview": "function MainMenuCursorView(cursor) {\r\n this._cursor = cursor;\r\n}\r\n\r\nMainMenuCursorView.prototype.draw = function (ctx,"
},
{
"path": "src/MainMenuItem.js",
"chars": 351,
"preview": "function MainMenuItem(sceneManager) {\r\n this._sceneManager = sceneManager;\r\n this._name = '';\r\n}\r\n\r\nMainMenuItem.proto"
},
{
"path": "src/MainMenuScene.js",
"chars": 2878,
"preview": "function MainMenuScene(sceneManager) {\r\n this._sceneManager = sceneManager;\r\n this._eventManager = this._sceneManager."
},
{
"path": "src/MainMenuView.js",
"chars": 459,
"preview": "function MainMenuView(mainMenu, cursorView) {\r\n this._menu = mainMenu;\r\n this._cursorView = cursorView;\r\n}\r\n\r\nMainMenu"
},
{
"path": "src/MoveFn.js",
"chars": 838,
"preview": "function MoveFn(object, property, endValue, duration, listener) {\r\n this._object = object;\r\n this._property = property"
},
{
"path": "src/OnePlayerMenuItem.js",
"chars": 259,
"preview": "function OnePlayerMenuItem(sceneManager) {\r\n MainMenuItem.call(this, sceneManager);\r\n this.setName(\"1 PLAYER\");\r\n}\r\n\r\n"
},
{
"path": "src/Painter.js",
"chars": 255,
"preview": "function Painter(spriteContainer) {\r\n this._spriteContainer = spriteContainer;\r\n}\r\n\r\nPainter.prototype.draw = function "
},
{
"path": "src/Pause.js",
"chars": 1252,
"preview": "function Pause(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber(this, [Keyboard"
},
{
"path": "src/PauseListener.js",
"chars": 713,
"preview": "function PauseListener(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber(this, ["
},
{
"path": "src/Player.js",
"chars": 1645,
"preview": "function Player() {\r\n this._lives = 2;\r\n this._score = 0;\r\n this.resetTanks();\r\n}\r\n\r\nPlayer.Event = {};\r\nPlayer.Event"
},
{
"path": "src/PlayerTankControllerFactory.js",
"chars": 521,
"preview": "function PlayerTankControllerFactory(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubs"
},
{
"path": "src/PlayerTankFactory.js",
"chars": 1314,
"preview": "function PlayerTankFactory(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber(thi"
},
{
"path": "src/Point.js",
"chars": 645,
"preview": "function Point(x, y) {\r\n this._x = x === undefined ? 0 : x;\r\n this._y = y === undefined ? 0 : y;\r\n}\r\n\r\nPoint.prototype"
},
{
"path": "src/Points.js",
"chars": 1374,
"preview": "function Points(eventManager) {\r\n Sprite.call(this, eventManager);\r\n this._value = 0;\r\n this._duration = 20;\r\n this."
},
{
"path": "src/PointsFactory.js",
"chars": 1608,
"preview": "function PointsFactory(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber(this, ["
},
{
"path": "src/PowerUp.js",
"chars": 2423,
"preview": "function PowerUp(eventManager) {\r\n Sprite.call(this, eventManager);\r\n this._eventManager.addSubscriber(this, [Collisio"
},
{
"path": "src/PowerUpFactory.js",
"chars": 888,
"preview": "function PowerUpFactory(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber(this, "
},
{
"path": "src/PowerUpHandler.js",
"chars": 2244,
"preview": "function PowerUpHandler(eventManager) {\r\n this._eventManager = eventManager;\r\n eventManager.addSubscriber(this, [Power"
},
{
"path": "src/Random.js",
"chars": 97,
"preview": "function Random() {}\r\n\r\nRandom.prototype.getNumber = function () {\r\n return Math.random();\r\n};\r\n"
},
{
"path": "src/Rect.js",
"chars": 1650,
"preview": "function Rect(x, y, w, h) {\r\n Point.call(this, x, y);\r\n this._w = w || 1;\r\n this._h = h || 1;\r\n}\r\n\r\nRect.subclass(Poi"
},
{
"path": "src/SceneManager.js",
"chars": 1593,
"preview": "function SceneManager(eventManager) {\r\n this._eventManager = eventManager;\r\n this._scene = null;\r\n}\r\n\r\nSceneManager.pr"
},
{
"path": "src/Script.js",
"chars": 638,
"preview": "function Script() {\r\n this._nodes = [];\r\n this._active = true;\r\n}\r\n\r\nScript.prototype.enqueue = function (node) {\r\n t"
},
{
"path": "src/ShovelHandler.js",
"chars": 1502,
"preview": "function ShovelHandler(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber(this, ["
},
{
"path": "src/SoundManager.js",
"chars": 524,
"preview": "var SoundManager = (function() {\r\n var sounds = {\r\n stage_start: null,\r\n game_over: null,\r\n bullet_shot: null,"
},
{
"path": "src/Sprite.js",
"chars": 4907,
"preview": "function Sprite(eventManager) {\r\n Rect.call(this);\r\n \r\n this._eventManager = eventManager;\r\n this._prevDirection = S"
},
{
"path": "src/SpriteContainer.js",
"chars": 1678,
"preview": "function SpriteContainer(eventManager) {\r\n this._eventManager = eventManager;\r\n eventManager.addSubscriber(this, [Spri"
},
{
"path": "src/SpriteController.js",
"chars": 1621,
"preview": "function SpriteController(eventManager, sprite) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscri"
},
{
"path": "src/SpriteSerializer.js",
"chars": 1024,
"preview": "function SpriteSerializer(eventManager) {\r\n this._eventManager = eventManager;\r\n}\r\n\r\nSpriteSerializer.SEPARATOR = ';';\r"
},
{
"path": "src/SpriteSerializerController.js",
"chars": 1224,
"preview": "function SpriteSerializerController(eventManager, structureManager) {\r\n this._eventManager = eventManager;\r\n this._eve"
},
{
"path": "src/StageMessage.js",
"chars": 434,
"preview": "function StageMessage(stage) {\r\n this._stage = stage;\r\n this._visible = false;\r\n}\r\n\r\nStageMessage.prototype.show = fun"
},
{
"path": "src/StageStatisticsPoints.js",
"chars": 1157,
"preview": "function StageStatisticsPoints(value, count, listener) {\r\n var self = this;\r\n \r\n this._value = value;\r\n this._count "
},
{
"path": "src/StageStatisticsScene.js",
"chars": 3446,
"preview": "function StageStatisticsScene(sceneManager, stage, player, gameOver) {\r\n var self = this;\r\n \r\n this._sceneManager = s"
},
{
"path": "src/Stages.js",
"chars": 19957,
"preview": "Globals.stages = [];\r\n\r\n// Stage 1\r\nGlobals.stages.push({\r\n map: \"Base(224,400);BrickWall(208,416);BrickWall(208,400);B"
},
{
"path": "src/SteelWall.js",
"chars": 301,
"preview": "function SteelWall(eventManager) {\r\n Wall.call(this, eventManager);\r\n this._invincibleForNormalBullets = true;\r\n}\r\n\r\nS"
},
{
"path": "src/SteelWallFactory.js",
"chars": 186,
"preview": "function SteelWallFactory(eventManager) {\r\n this._eventManager = eventManager;\r\n}\r\n\r\nSteelWallFactory.prototype.create "
},
{
"path": "src/StructureManager.js",
"chars": 1339,
"preview": "function StructureManager(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber(this"
},
{
"path": "src/Tank.js",
"chars": 10502,
"preview": "function Tank(eventManager) {\r\n Sprite.call(this, eventManager);\r\n \r\n eventManager.addSubscriber(this,\r\n [Bullet.Ev"
},
{
"path": "src/TankColor.js",
"chars": 523,
"preview": "function TankColor() {\r\n this._colors = [[0,0]];\r\n this._hit = 0;\r\n this._color = 0;\r\n}\r\n\r\nTankColor.prototype.setCol"
},
{
"path": "src/TankController.js",
"chars": 741,
"preview": "function TankController(eventManager, tank) {\r\n SpriteController.call(this, eventManager, tank);\r\n this._eventManager."
},
{
"path": "src/TankExplosion.js",
"chars": 639,
"preview": "function TankExplosion(eventManager, tank) {\r\n Explosion.call(this, eventManager);\r\n this._tank = tank;\r\n this._anima"
},
{
"path": "src/TankExplosionFactory.js",
"chars": 974,
"preview": "function TankExplosionFactory(eventManager) {\r\n this._eventManager = eventManager;\r\n this._eventManager.addSubscriber("
},
{
"path": "src/TankStateAppearing.js",
"chars": 1382,
"preview": "function TankStateAppearing(tank) {\r\n this._tank = tank;\r\n this._eventManager = this._tank.getEventManager();\r\n this."
},
{
"path": "src/TankStateInvincible.js",
"chars": 1640,
"preview": "function TankStateInvincible(tank) {\r\n TankStateNormal.call(this, tank);\r\n \r\n this._eventManager = this._tank.getEven"
},
{
"path": "src/TankStateNormal.js",
"chars": 2054,
"preview": "function TankStateNormal(tank) {\r\n this._tank = tank;\r\n this._trackAnimation = new Animation([1,2], this._tank.getTrac"
},
{
"path": "src/Trees.js",
"chars": 305,
"preview": "function Trees(eventManager) {\r\n Sprite.call(this, eventManager);\r\n this._zIndex = 1;\r\n}\r\n\r\nTrees.subclass(Sprite);\r\n\r"
},
{
"path": "src/Updater.js",
"chars": 253,
"preview": "function Updater(spriteContainer) {\r\n this._spriteContainer = spriteContainer;\r\n}\r\n\r\nUpdater.prototype.update = functio"
},
{
"path": "src/Utils.js",
"chars": 958,
"preview": "Function.prototype.subclass = function(base) {\r\n var c = Function.prototype.subclass.nonconstructor;\r\n c.prototype = b"
},
{
"path": "src/Wall.js",
"chars": 2953,
"preview": "function Wall(eventManager) {\r\n Sprite.call(this, eventManager);\r\n \r\n this._eventManager.addSubscriber(this, [Collisi"
},
{
"path": "src/Water.js",
"chars": 675,
"preview": "function Water(eventManager) {\r\n Sprite.call(this, eventManager);\r\n this._animation = new Animation([1,2], 30, true);\r"
}
]
// ... and 11 more files (download for full content)
About this extraction
This page contains the full source code of the newagebegins/BattleCity GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 175 files (662.9 KB), approximately 181.6k tokens, and a symbol index with 147 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.