├── README.md
├── src
├── ComicBookGallery
│ ├── Views
│ │ ├── _ViewStart.cshtml
│ │ ├── ComicBooks
│ │ │ ├── Index.cshtml
│ │ │ └── Detail.cshtml
│ │ ├── Shared
│ │ │ └── _Layout.cshtml
│ │ └── web.config
│ ├── Global.asax
│ ├── Images
│ │ ├── bone-50.jpg
│ │ ├── the-amazing-spider-man-657.jpg
│ │ └── the-amazing-spider-man-700.jpg
│ ├── Fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.ttf
│ │ └── glyphicons-halflings-regular.woff
│ ├── Models
│ │ ├── Artist.cs
│ │ └── ComicBook.cs
│ ├── Global.asax.cs
│ ├── packages.config
│ ├── App_Start
│ │ └── RouteConfig.cs
│ ├── Content
│ │ └── site.css
│ ├── Controllers
│ │ └── ComicBooksController.cs
│ ├── Web.Debug.config
│ ├── Web.Release.config
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── Web.config
│ ├── Data
│ │ └── ComicBookRepository.cs
│ ├── ComicBookGallery.csproj
│ └── Scripts
│ │ ├── bootstrap.min.js
│ │ └── modernizr-2.6.2.js
└── ComicBookGallery.sln
├── walkthroughs
├── README.md
├── add-a-tweet-button-to-the-detail-view
│ ├── README.md
│ ├── 01-adding-a-tweet-button.md
│ └── 02-using-app-configuration.md
└── add-series-list-and-detail-views
│ ├── README.md
│ ├── 06-removing-duplicated-view-code.md
│ ├── 04-adding-the-series-list-page.md
│ ├── 01-adding-a-series-model.md
│ ├── 03-adding-the-series-repository.md
│ ├── 05-adding-the-series-detail-page.md
│ └── 02-centralizing-our-data.md
└── .gitignore
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # ASP.NET MVC Basics
3 |
4 | ## Comic Book Gallery
5 |
--------------------------------------------------------------------------------
/src/ComicBookGallery/Views/_ViewStart.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | Layout = "~/Views/Shared/_Layout.cshtml";
3 | }
--------------------------------------------------------------------------------
/src/ComicBookGallery/Global.asax:
--------------------------------------------------------------------------------
1 | <%@ Application Codebehind="Global.asax.cs" Inherits="ComicBookGallery.MvcApplication" Language="C#" %>
2 |
--------------------------------------------------------------------------------
/src/ComicBookGallery/Images/bone-50.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/treehouse-projects/aspnet-comic-book-gallery/HEAD/src/ComicBookGallery/Images/bone-50.jpg
--------------------------------------------------------------------------------
/src/ComicBookGallery/Fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/treehouse-projects/aspnet-comic-book-gallery/HEAD/src/ComicBookGallery/Fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/src/ComicBookGallery/Fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/treehouse-projects/aspnet-comic-book-gallery/HEAD/src/ComicBookGallery/Fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/src/ComicBookGallery/Images/the-amazing-spider-man-657.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/treehouse-projects/aspnet-comic-book-gallery/HEAD/src/ComicBookGallery/Images/the-amazing-spider-man-657.jpg
--------------------------------------------------------------------------------
/src/ComicBookGallery/Images/the-amazing-spider-man-700.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/treehouse-projects/aspnet-comic-book-gallery/HEAD/src/ComicBookGallery/Images/the-amazing-spider-man-700.jpg
--------------------------------------------------------------------------------
/src/ComicBookGallery/Fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/treehouse-projects/aspnet-comic-book-gallery/HEAD/src/ComicBookGallery/Fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/src/ComicBookGallery/Models/Artist.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 |
6 | namespace ComicBookGallery.Models
7 | {
8 | public class Artist
9 | {
10 | public string Name { get; set; }
11 | public string Role { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/ComicBookGallery/Global.asax.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Web;
5 | using System.Web.Mvc;
6 | using System.Web.Routing;
7 |
8 | namespace ComicBookGallery
9 | {
10 | public class MvcApplication : System.Web.HttpApplication
11 | {
12 | protected void Application_Start()
13 | {
14 | AreaRegistration.RegisterAllAreas();
15 | RouteConfig.RegisterRoutes(RouteTable.Routes);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/walkthroughs/README.md:
--------------------------------------------------------------------------------
1 |
2 | # ASP.NET MVC Basics Walkthroughs
3 |
4 | Now that you've completed the ASP.NET MVC Basics course, here's an opportunity to practice your new skills!
5 |
6 | These walkthroughs are designed to re-enforce the material covered in the course. We'll also cover some additional new information about ASP.NET MVC, but reading these walkthroughs is not required, as well also cover that new information in future Treehouse courses.
7 |
8 | * [Add Series List and Detail Views](add-series-list-and-detail-views/)
9 | * [Add a Tweet Button to the Detail View](add-a-tweet-button-to-the-detail-view/)
10 |
--------------------------------------------------------------------------------
/walkthroughs/add-a-tweet-button-to-the-detail-view/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Add a Tweet Button to the Detail View
3 |
4 | ## Introduction
5 |
6 | In this step-by-step walkthrough, we'll update the Comic Book Gallery website's Comic Book Detail view with a "Tweet" button.
7 |
8 | To implement this feature, we'll use Twitter's website to generate the code for our "Tweet" button and learn how to use ASP.NET app configuration to parameterize key application values.
9 |
10 | * [Adding a Tweet Button](01-adding-a-tweet-button.md)
11 | * [Using App Configuration](02-using-app-configuration.md)
12 |
13 | [Return to Walkthroughs](../)
14 |
--------------------------------------------------------------------------------
/src/ComicBookGallery/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
Final issue! Witness the final hours of Doctor Octopus' life and his one, last, great act of revenge! Even if Spider-Man survives...will Peter Parker?
", 19 | Artists = new Artist[] 20 | { 21 | new Artist() { Name = "Dan Slott", Role = "Script" }, 22 | new Artist() { Name = "Humberto Ramos", Role = "Pencils" }, 23 | new Artist() { Name = "Victor Olazaba", Role = "Inks" }, 24 | new Artist() { Name = "Edgar Delgado", Role = "Colors" }, 25 | new Artist() { Name = "Chris Eliopoulos", Role = "Letters" }, 26 | } 27 | }, 28 | new ComicBook() 29 | { 30 | Id = 2, 31 | SeriesTitle = "The Amazing Spider-Man", 32 | IssueNumber = 657, 33 | DescriptionHtml = "FF: THREE TIE-IN. Spider-Man visits the FF for a very private wake--just for family.
", 34 | Artists = new Artist[] 35 | { 36 | new Artist() { Name = "Dan Slott", Role = "Script" }, 37 | new Artist() { Name = "Marcos Martin", Role = "Pencils" }, 38 | new Artist() { Name = "Marcos Martin", Role = "Inks" }, 39 | new Artist() { Name = "Muntsa Vicente", Role = "Colors" }, 40 | new Artist() { Name = "Joe Caramagna", Role = "Letters" } 41 | }, 42 | Favorite = false 43 | }, 44 | new ComicBook() 45 | { 46 | Id = 3, 47 | SeriesTitle = "Bone", 48 | IssueNumber = 50, 49 | DescriptionHtml = "The Dungeon & The Parapet, Part 1. Thorn is discovered by Lord Tarsil and the corrupted Stickeaters and thrown into a dungeon with Fone Bone. As she sleeps, a message comes to her about the mysterious \"Crown of Horns\".
", 50 | Artists = new Artist[] 51 | { 52 | new Artist() { Name = "Jeff Smith", Role = "Script" }, 53 | new Artist() { Name = "Jeff Smith", Role = "Pencils" }, 54 | new Artist() { Name = "Jeff Smith", Role = "Inks" }, 55 | new Artist() { Name = "Jeff Smith", Role = "Letters" } 56 | }, 57 | Favorite = false 58 | } 59 | }; 60 | 61 | public ComicBook[] GetComicBooks() 62 | { 63 | return _comicBooks; 64 | } 65 | 66 | public ComicBook GetComicBook(int id) 67 | { 68 | ComicBook comicBookToReturn = null; 69 | 70 | foreach (var comicBook in _comicBooks) 71 | { 72 | if (comicBook.Id == id) 73 | { 74 | comicBookToReturn = comicBook; 75 | 76 | break; 77 | } 78 | } 79 | 80 | return comicBookToReturn; 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /walkthroughs/add-a-tweet-button-to-the-detail-view/01-adding-a-tweet-button.md: -------------------------------------------------------------------------------- 1 | 2 | # Add a Tweet Button to the Detail View 3 | 4 | ## Adding a "Tweet" Button 5 | 6 | In this step, we'll visit Twitter's website to get the HTML and JavaScript to add a "Tweet" button to our Comic Book Detail page. 7 | 8 | To start, browse to [https://about.twitter.com/resources/buttons#tweet](https://about.twitter.com/resources/buttons#tweet). 9 | 10 | In the "Choose a button" section, select the "Share a link" option. Under the "Button options" section, use the following values. 11 | 12 | * For "Share URL" select "Use the page URL" option 13 | * For "Tweet text" select "Use the title of the page" option 14 | * For the "Via" value use your Twitter account name (for this walkthrough I'll be using my Twitter account name `SmashDev`) 15 | * Leave "Recommend" blank 16 | * For the "Hashtag" value use "comicbooks" 17 | * Check the "Large button" check box 18 | 19 | Then in the "Preview and code" section, select and copy the code in the field just below the preview "Tweet" button. At the time of this writing, the generated code looks like this. 20 | 21 | ``` 22 | Tweet 25 | 26 | ``` 27 | 28 | Now that we've got our "Tweet" button code, let's add it to our Comic Book Detail view! Open the "Views/ComicBooks/Detail.cshtml" view. 29 | 30 | Let's add the "Tweet" button in the "well" section of the view. Notice that I'm also adding a `` element, containing a non-breaking space HTML entity, just above the "Tweet" button in order to create some whitespace between the button and the content just above it. 31 | 32 | ``` 33 |
50 | 53 | 54 |
The Amazing Spider-Man (abbreviated as ASM) is an American comic book series published by Marvel Comics, featuring the adventures of the fictional superhero Spider-Man. Being the mainstream continuity of the franchise, it began publication in 1963 as a monthly periodical and was published continuously, with a brief interruption in 1995, until its relaunch with a new numbering order in 1999. In 2003 the series reverted to the numbering order of the first volume. The title has occasionally been published biweekly, and was published three times a month from 2008 to 2010. A film named after the comic was released July 3, 2012.
96 |
107 |
108 | The Amazing Spider-Man (abbreviated as ASM) is an American comic book series published by Marvel Comics, featuring the adventures of the fictional superhero Spider-Man. Being the mainstream continuity of the franchise, it began publication in 1963 as a monthly periodical and was published continuously, with a brief interruption in 1995, until its relaunch with a new numbering order in 1999. In 2003 the series reverted to the numbering order of the first volume. The title has occasionally been published biweekly, and was published three times a month from 2008 to 2010. A film named after the comic was released July 3, 2012.
" 107 | }, 108 | new Series() 109 | { 110 | Id = 2, 111 | Title = "Bone", 112 | DescriptionHtml = "Bone is an independently published comic book series, written and illustrated by Jeff Smith, originally serialized in 55 irregularly released issues from 1991 to 2004.
" 113 | } 114 | }; 115 | ``` 116 | 117 | With our series data now in place, we can update the comic books data to use the `Series` object instances. In the first comic book, go ahead and remove the code that is instantiating the `Series` object. Then we can set the `Series` property to the first element in the `series` array. 118 | 119 | We can index into the array by typing the `series` variable name followed by a set of brackets containing the numeral "0". Remember, array elements are numbered starting with zero, so the first element is index "0", the second is index "1", and so on. 120 | 121 | The second comic book `Series` property also needs to be set to the `series` array's first element. The third comic book `Series` property needs to be set to the second element, so use the numeral "1" in the brackets following the `series` variable. 122 | 123 | ``` 124 | var comicBooks = new ComicBook[] 125 | { 126 | new ComicBook() 127 | { 128 | Id = 1, 129 | Series = series[0], 130 | ... 131 | }, 132 | new ComicBook() 133 | { 134 | Id = 2, 135 | Series = series[0], 136 | ... 137 | }, 138 | new ComicBook() 139 | { 140 | Id = 3, 141 | Series = series[1], 142 | ... 143 | } 144 | }; 145 | ``` 146 | 147 | Nice! Now we have our series data separated from our comic books data and the `Series` object instances are not unnecessarily duplicated across our `ComicBook` objects. 148 | 149 | Let's turn our attention to how we're going to expose our data outside of this class. 150 | 151 | We currently have a private `_comicBooks` field. To start with, let's make this field visible to the rest of our website by changing the `private` access modifier to `public`. Now that our field is no longer private, let's change the name to `ComicBooks`. We want to ensure that we're only starting field names with an underscore and lowercase letter if they are private fields. 152 | 153 | ``` 154 | public static ComicBook[] ComicBooks; 155 | ``` 156 | 157 | We *could* leave this line of code as it is, but let's make one more improvement by converting the field to a property by adding a set of curly braces containing the `get` and `set` keywords. As you might have seen in a previous C# course, this is the syntax for implementing auto-properties. 158 | 159 | ``` 160 | public static ComicBook[] ComicBooks { get; set; } 161 | ``` 162 | 163 | If we add a private access modifier just before the set keyword, we can allow code outside of this class to get the property value, without being able to set the value. In general, we only want to provide the access that is necessary. 164 | 165 | ``` 166 | public static ComicBook[] ComicBooks { get; private set; } 167 | ``` 168 | 169 | While we're here, let's add a property for our series data. This property can also be `public` and `static`. Set its type to be an array of `Series` objects, use "Series" for the name, and add a public getter and a private setter. 170 | 171 | ``` 172 | public static Series[] Series { get; private set; } 173 | ``` 174 | 175 | Now that we have our data properties, we need to update the `InitData` method to set their values. At the bottom of the method, set the `ComicBooks` property to the `comicBooks` variable and the `Series` property to the `series` variable. 176 | 177 | ``` 178 | Series = series; 179 | ComicBooks = comicBooks; 180 | ``` 181 | 182 | We're getting close to being done with our `Data` class, but our implementation has a major shortcoming right now: we're initializing our data in the `InitData` method but we're currently not calling that method. 183 | 184 | Ideally, we only want to call the `InitData` method once. We can accomplish this by adding a static constructor to our class that calls the `InitData` method. Static constructors (see [https://msdn.microsoft.com/en-us/library/k9x6w0hc.aspx](https://msdn.microsoft.com/en-us/library/k9x6w0hc.aspx)) are called just before any instances of our class are created or any static members are accessed. They specifically exist to initialize class members, which fits our needs exactly. 185 | 186 | ``` 187 | static Data() 188 | { 189 | InitData(); 190 | } 191 | ``` 192 | 193 | Visual Studio is complaining about our `InitData` method call. We're getting this error because we're attempting to call an instance method from a static method. This is just an oversight on our part—we can easily make the `InitData` method static so that it can be called from our static constructor. Just add the `static` keyword right before the return type of the `InitData` method. 194 | 195 | ``` 196 | private static void InitData() 197 | { 198 | ... 199 | } 200 | ``` 201 | 202 | One last thing before we move on: all four of our `Data` class members are static. When a class just contains static members, we can make the class itself static by adding the `static` keyword just before the `class` keyword. 203 | 204 | Doing this adds additional clarity to our code and prevents our class from being instantiated—which wouldn't make any sense given that our class doesn't contain any instance members. It also prevents us from adding any instance members to our class, so it helps ensure that we keep our `Data` class design consistent. 205 | 206 | ``` 207 | public static class Data 208 | { 209 | ... 210 | } 211 | ``` 212 | 213 | Just like we did with the `ComicBookRepository` class, by making our data class static, we're ensuring that we only have a single copy of our data in memory at any given time. 214 | 215 | Now that we're *finally* done with our `Data` class, let's switch to the `ComicBookRepository` class and fix the broken references to the non-existent `_comicBooks` field. 216 | 217 | We just need to replace each broken field reference with a reference to the our new `Data.ComicBooks` property. Notice that since the `Data.ComicBooks` property is static, we can access it with just the class name—no object instance required. 218 | 219 | ``` 220 | public class ComicBookRepository 221 | { 222 | public ComicBook[] GetComicBooks() 223 | { 224 | return Data.ComicBooks; 225 | } 226 | 227 | public ComicBook GetComicBook(int id) 228 | { 229 | ComicBook comicBookToReturn = null; 230 | 231 | foreach (var comicBook in Data.ComicBooks) 232 | { 233 | ... 234 | } 235 | 236 | return comicBookToReturn; 237 | } 238 | } 239 | ``` 240 | 241 | Before we test our changes, let's set two breakpoints: one inside of the constructor for the `ComicBooksController` class and another inside of the static constructor for the `Data` class. By setting those breakpoints, we can see how often these constructors get called. 242 | 243 | Go ahead and start the website. 244 | 245 | The first breakpoint we hit is the constructor for the `ComicBooksController` class. This is MVC instantiating our controller in order to process the request for our "Home" page. Press `F5` to continue execution of our website. 246 | 247 | Next, we hit the breakpoint inside of the `Data` class static constructor. If we press `SHIFT+F11`, we can step out of the constructor and see what caused it to be called—the `ComicBooks` property getter. Press `SHIFT+F11` again to step out of the property getter. Now we're in the `ComicBookRepository.GetComicBooks` method. If we press `SHIFT+F11` one more time, we'll step out to the `ComicBooksController.Index` action method. 248 | 249 | All of this makes sense. MVC routed the request for our "Home" page to the controller's `Index` action method, which in turn called the repository's `GetComicBooks` method, which accessed the `Data.ComicBooks` static property, which caused the `Data.InitData` method to get called. 250 | 251 | Press `F5` to continue execution. You should now see the list page with everything intact. 252 | 253 | Click on the first comic book to browse to the Comic Book Detail page. And again, we hit the breakpoint in the `ComicBooksController` class constructor. This tells us that MVC instantiates a controller instance for each new request. 254 | 255 | Press `F5` to continue execution. You should now see the detail page. 256 | 257 | Notice that we didn't hit our breakpoint in the `Data` class static constructor. This confirms that the static constructor will only get called once. 258 | 259 | Go ahead and stop the website. 260 | 261 | If you're using GitHub, let's commit our changes. Enter a commit message of "Added Data class" and click the "Commit All" button. 262 | 263 | In the [next step](03-adding-the-series-repository.md), we'll add the series repository. 264 | 265 | [Return to Introduction](README.md) 266 | -------------------------------------------------------------------------------- /src/ComicBookGallery/Scripts/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | 16 | /** 17 | * bootstrap.js v3.0.0 by @fat and @mdo 18 | * Copyright 2013 Twitter Inc. 19 | * http://www.apache.org/licenses/LICENSE-2.0 20 | */ 21 | if(!jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(window.jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(window.jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(window.jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('').insertAfter(a(this)).on("click",b),f.trigger(d=a.Event("show.bs.dropdown")),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown"),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",f);if(h.length){var i=h.index(h.filter(":focus"));38==b.keyCode&&i>0&&i--,40==b.keyCode&&i