Repository: elbandit/PPPDDD Branch: master Commit: 4d9d864fa6d9 Files: 919 Total size: 4.2 MB Directory structure: gitextract_uu88b_d3/ ├── .gitattributes ├── .gitignore ├── 05 - Domain Model Implementation Patterns/ │ ├── PPPDDDChap05.DomainModel/ │ │ ├── PPPDDDChap05.DomainModel/ │ │ │ ├── Application/ │ │ │ │ └── BidOnAuctionService.cs │ │ │ ├── Model/ │ │ │ │ ├── Auction.cs │ │ │ │ ├── Bid.cs │ │ │ │ ├── ClassDiagram.cd │ │ │ │ ├── HistoricalBid.cs │ │ │ │ ├── IAuctionRepository.cs │ │ │ │ ├── Money.cs │ │ │ │ ├── Price.cs │ │ │ │ └── WinningBid.cs │ │ │ ├── PPPDDDChap05.DomainModel.csproj │ │ │ └── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── PPPDDDChap05.DomainModel.sln │ ├── PPPDDDChap05.TableModule/ │ │ ├── PPPDDDChap05.TableModule/ │ │ │ ├── Domain/ │ │ │ │ ├── Customers.cs │ │ │ │ ├── Orders.cs │ │ │ │ └── TableModuleBase.cs │ │ │ ├── PPPDDDChap05.TableModule.csproj │ │ │ └── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── PPPDDDChap05.TableModule.sln │ └── PPPDDDChap05.TransactionScript/ │ ├── PPPDDDChap05.TransactionScript/ │ │ ├── Application/ │ │ │ └── BidOnAuctionService.cs │ │ ├── Domain/ │ │ │ ├── Auction.cs │ │ │ ├── BidOnAuction.cs │ │ │ ├── BidOnAuctionCommand.cs │ │ │ ├── ClassDiagram1.cd │ │ │ ├── CreateAuction.cs │ │ │ └── ICommand.cs │ │ ├── PPPDDDChap05.TransactionScript.csproj │ │ └── Properties/ │ │ └── AssemblyInfo.cs │ └── PPPDDDChap05.TransactionScript.sln ├── 10 - Applying the Principles, Practices and Patterns of DDD/ │ └── PPPDDD.Chap10.ecommerce/ │ ├── PPPDDD.Chap10.ecommerce/ │ │ ├── ExplicitLogic/ │ │ │ └── Model/ │ │ │ ├── BasketItem.cs │ │ │ ├── BasketItemFactory.cs │ │ │ ├── BasketItems.cs │ │ │ ├── Country.cs │ │ │ ├── OverSeasSellingPolicyException.cs │ │ │ ├── OverseasSellingPolicy.cs │ │ │ ├── Product.cs │ │ │ ├── Quantity.cs │ │ │ └── basket.cs │ │ ├── ImplicitLogic/ │ │ │ └── Model/ │ │ │ ├── BasketItem.cs │ │ │ ├── BasketItemFactory.cs │ │ │ ├── BasketItems.cs │ │ │ ├── Product.cs │ │ │ ├── Quantity.cs │ │ │ └── basket.cs │ │ ├── PPPDDD.Chap10.ecommerce.csproj │ │ └── Properties/ │ │ └── AssemblyInfo.cs │ └── PPPDDD.Chap10.ecommerce.sln ├── 11 - Integrating Bounded Contexts/ │ └── README.md ├── 12 - Integrating Via Messaging/ │ ├── Billing.Messages/ │ │ ├── Billing.Messages.csproj │ │ ├── Commands/ │ │ │ └── RecordPaymentAttempt.cs │ │ ├── Events/ │ │ │ └── PaymentAccepted.cs │ │ └── Properties/ │ │ └── AssemblyInfo.cs │ ├── Billing.Payments.PaymentAccepted/ │ │ ├── App.config │ │ ├── Billing.Payments.PaymentAccepted.csproj │ │ ├── EndpointConfig.cs │ │ ├── OrderCreatedHandler.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── RecordPaymentAttemptHandler.cs │ │ └── packages.config │ ├── DDDesign.Web/ │ │ ├── App_Start/ │ │ │ ├── FilterConfig.cs │ │ │ ├── RouteConfig.cs │ │ │ └── WebApiConfig.cs │ │ ├── Controllers/ │ │ │ └── OrdersController.cs │ │ ├── DDDesign.Web.csproj │ │ ├── Global.asax │ │ ├── Global.asax.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── Views/ │ │ │ ├── Orders/ │ │ │ │ └── Index.cshtml │ │ │ └── Web.config │ │ ├── Web.Debug.config │ │ ├── Web.Release.config │ │ ├── Web.config │ │ └── packages.config │ ├── DDDesign.sln │ ├── Promotions.LuckyWinner.LuckyWinnerSelected/ │ │ ├── App.config │ │ ├── Application/ │ │ │ └── Program.cs │ │ ├── Promotions.LuckyWinner.LuckyWinnerSelected.csproj │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── packages.config │ ├── Promotions.LuckyWinner.LuckyWinnerSelected.Bridge/ │ │ ├── App.config │ │ ├── Application/ │ │ │ └── OrderCreatedHandler.cs │ │ ├── Infrastructure/ │ │ │ └── EndpointConfig.cs │ │ ├── Promotions.LuckyWinner.LuckyWinnerSelected.Bridge.csproj │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── packages.config │ ├── README.md │ ├── Sales.Messages/ │ │ ├── Commands/ │ │ │ └── PlaceOrder.cs │ │ ├── Events/ │ │ │ ├── OrderCreated.cs │ │ │ └── OrderCreated_V2.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── Sales.Messages.csproj │ ├── Sales.Orders.OrderCreated/ │ │ ├── App.config │ │ ├── Application/ │ │ │ └── PlaceOrderHandler.cs │ │ ├── Infrastructure/ │ │ │ └── EndpointConfig.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── Sales.Orders.OrderCreated.csproj │ │ └── packages.config │ ├── Shipping.BusinessCustomers.ShippingArranged/ │ │ ├── App.config │ │ ├── Application/ │ │ │ └── Handlers.cs │ │ ├── Infrastructure/ │ │ │ └── EndpointConfig.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── Shipping.BusinessCustomers.ShippingArranged.csproj │ │ └── packages.config │ └── Shipping.Messages/ │ ├── Events/ │ │ └── ShippingArranged.cs │ ├── Properties/ │ │ └── AssemblyInfo.cs │ └── Shipping.Messages.csproj ├── 13 - Integrating Via Http and Rest/ │ ├── PPPDDD.JSON.SocialMedia/ │ │ ├── AccountManagement/ │ │ │ ├── AccountManagement.csproj │ │ │ ├── App_Start/ │ │ │ │ └── WebApiConfig.cs │ │ │ ├── Controllers/ │ │ │ │ └── FollowerDirectoryController.cs │ │ │ ├── Global.asax │ │ │ ├── Global.asax.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── Web.Debug.config │ │ │ ├── Web.Release.config │ │ │ ├── Web.config │ │ │ └── packages.config │ │ ├── Discovery/ │ │ │ ├── App_Start/ │ │ │ │ └── WebApiConfig.cs │ │ │ ├── Controllers/ │ │ │ │ └── RecommenderController.cs │ │ │ ├── Discovery.csproj │ │ │ ├── Global.asax │ │ │ ├── Global.asax.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── Web.Debug.config │ │ │ ├── Web.Release.config │ │ │ ├── Web.config │ │ │ └── packages.config │ │ └── PPPDDD.JSON.SocialMedia.sln │ ├── PPPDDD.REST.SocialMedia/ │ │ ├── .gitignore │ │ ├── AccountManagement.Accounts.Api/ │ │ │ ├── AccountManagement.Accounts.Api.csproj │ │ │ ├── App_Start/ │ │ │ │ └── WebApiConfig.cs │ │ │ ├── Controllers/ │ │ │ │ ├── AccountsController.cs │ │ │ │ └── FollowersController.cs │ │ │ ├── Global.asax │ │ │ ├── Global.asax.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── Web.Debug.config │ │ │ ├── Web.Release.config │ │ │ ├── Web.config │ │ │ └── packages.config │ │ ├── AccountManagement.EntryPoint/ │ │ │ ├── .gitignore │ │ │ ├── AccountManagement.EntryPoint.Api.csproj │ │ │ ├── App_Start/ │ │ │ │ └── WebApiConfig.cs │ │ │ ├── Controllers/ │ │ │ │ └── EntryPointController.cs │ │ │ ├── Global.asax │ │ │ ├── Global.asax.cs │ │ │ ├── MIT-LICENSE.txt │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── README.md │ │ │ ├── Web.Debug.config │ │ │ ├── Web.Release.config │ │ │ ├── Web.config │ │ │ ├── browser.html │ │ │ ├── js/ │ │ │ │ ├── hal/ │ │ │ │ │ ├── browser.js │ │ │ │ │ ├── http/ │ │ │ │ │ │ └── client.js │ │ │ │ │ ├── resource.js │ │ │ │ │ └── views/ │ │ │ │ │ ├── browser.js │ │ │ │ │ ├── documentation.js │ │ │ │ │ ├── embedded_resource.js │ │ │ │ │ ├── embedded_resources.js │ │ │ │ │ ├── explorer.js │ │ │ │ │ ├── inspector.js │ │ │ │ │ ├── links.js │ │ │ │ │ ├── location_bar.js │ │ │ │ │ ├── navigation.js │ │ │ │ │ ├── non_safe_request_dialog.js │ │ │ │ │ ├── properties.js │ │ │ │ │ ├── query_uri_dialog.js │ │ │ │ │ ├── request_headers.js │ │ │ │ │ ├── resource.js │ │ │ │ │ ├── response.js │ │ │ │ │ ├── response_body.js │ │ │ │ │ └── response_headers.js │ │ │ │ └── hal.js │ │ │ ├── packages.config │ │ │ ├── styles.css │ │ │ └── vendor/ │ │ │ ├── css/ │ │ │ │ ├── bootstrap-responsive.css │ │ │ │ └── bootstrap.css │ │ │ └── js/ │ │ │ ├── backbone.js │ │ │ ├── bootstrap.js │ │ │ ├── jquery-1.10.2.js │ │ │ ├── underscore.js │ │ │ └── uritemplates.js │ │ ├── AccountManagement.RegularAccounts.BeganFollowing/ │ │ │ ├── AccountManagement.RegularAccounts.BeganFollowing.csproj │ │ │ ├── App_Start/ │ │ │ │ ├── EnableCorsAttribute.cs │ │ │ │ └── WebApiConfig.cs │ │ │ ├── Controllers/ │ │ │ │ └── BeganFollowingController.cs │ │ │ ├── Global.asax │ │ │ ├── Global.asax.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── Web.Debug.config │ │ │ ├── Web.Release.config │ │ │ ├── Web.config │ │ │ └── packages.config │ │ ├── Discovery.Reccommendations.Followers/ │ │ │ ├── BeganFollowingPollingFeedConsumer.cs │ │ │ ├── Discovery.Reccommendations.Followers.csproj │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ └── PPPDDD.REST.SocialMedia.sln │ ├── PPPDDD.SOAP.SocialMedia/ │ │ ├── AccountManagement/ │ │ │ ├── AccountManagement.csproj │ │ │ ├── FollowerDirectory.svc │ │ │ ├── FollowerDirectory.svc.cs │ │ │ ├── IFollowerDirectory.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── Web.Debug.config │ │ │ ├── Web.Release.config │ │ │ └── Web.config │ │ ├── Discovery/ │ │ │ ├── Discovery.csproj │ │ │ ├── IRecommender.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── Recommender.svc │ │ │ ├── Recommender.svc.cs │ │ │ ├── Service References/ │ │ │ │ └── AccountManagement/ │ │ │ │ ├── Discovery.AccountManagement.Follower.datasource │ │ │ │ ├── FollowerDirectory.disco │ │ │ │ ├── FollowerDirectory.wsdl │ │ │ │ ├── FollowerDirectory.xsd │ │ │ │ ├── FollowerDirectory1.xsd │ │ │ │ ├── FollowerDirectory2.xsd │ │ │ │ ├── FollowerDirectory3.xsd │ │ │ │ ├── Reference.cs │ │ │ │ ├── Reference.svcmap │ │ │ │ ├── configuration.svcinfo │ │ │ │ └── configuration91.svcinfo │ │ │ ├── Web.Debug.config │ │ │ ├── Web.Release.config │ │ │ └── Web.config │ │ └── PPPDDD.SOAP.SocialMedia.sln │ └── README.md ├── 14 - Introducing Domain Modelling Patterns and Best Practices/ │ └── README.md ├── 15 - Value Objects/ │ ├── Examples/ │ │ ├── BankAccount/ │ │ │ └── BankAccount.cs │ │ ├── Examples.csproj │ │ ├── Model/ │ │ │ ├── BankAccount.cs │ │ │ ├── Customer.cs │ │ │ ├── Meters.cs │ │ │ ├── MicroTypes.cs │ │ │ ├── Money.cs │ │ │ ├── Name.cs │ │ │ └── ValueObject.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── app.config │ │ └── packages.config │ ├── PPPDDD.Chap16.ValueObjects.sln │ ├── README.md │ └── Tests/ │ ├── Tests/ │ │ ├── Combining_money_tests.cs │ │ ├── DateTime_immutability_tests.cs │ │ ├── Denormalized_persistence_example.cs │ │ ├── Meters_equality_tests.cs │ │ ├── Micro_types_example_tests.cs │ │ ├── Name_validation_tests.cs │ │ ├── Normalized_persistence_example.cs │ │ ├── Persistence_format_examples.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── Tests.csproj │ │ ├── TimeSpan_factory_method_tests.cs │ │ ├── app.config │ │ └── packages.config │ └── Tests.sln ├── 16 - Entities/ │ ├── PPPDDDChap17.Entities.Examples/ │ │ ├── Customer.cs │ │ ├── Model/ │ │ │ ├── Book.cs │ │ │ ├── Dice.cs │ │ │ ├── FlightBooking.cs │ │ │ ├── GlobalCounter.cs │ │ │ ├── HolidayBooking.cs │ │ │ ├── Hotel.cs │ │ │ ├── OnlineTakeawayOrder.cs │ │ │ ├── SoccerMatch.cs │ │ │ └── Vehicle.cs │ │ ├── PPPDDDChap17.Entities.Examples.csproj │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── packages.config │ ├── PPPDDDChap17.Entities.Tests/ │ │ ├── BookTests.cs │ │ ├── DatastoreIdGenerationExample.cs │ │ ├── FlightBookingTests.cs │ │ ├── GlobalCounterTest.cs │ │ ├── HolidayBookingTest.cs │ │ ├── HotelTests.cs │ │ ├── PPPDDDChap17.Entities.Tests.csproj │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── app.config │ │ └── packages.config │ ├── PPPDDDChap17.Entities.sln │ └── README.md ├── 17 - Domain Services/ │ ├── PPPDDDChap18.DomainServices/ │ │ ├── Insurance/ │ │ │ ├── Application/ │ │ │ │ └── MultiMemberInsurancePremium.cs │ │ │ └── Model/ │ │ │ ├── IMemberRepository.cs │ │ │ ├── IMultiMemberPremiumCalculator.cs │ │ │ ├── IPolicyRepository.cs │ │ │ ├── Member.cs │ │ │ ├── Policy.cs │ │ │ └── Quote.cs │ │ ├── OnlineDating/ │ │ │ └── Model/ │ │ │ ├── BloodType.cs │ │ │ ├── CompatibilityRating.cs │ │ │ ├── LoveSeeker.cs │ │ │ └── RomanceOMeter.cs │ │ ├── OnlineGaming/ │ │ │ ├── WithDomainServices/ │ │ │ │ └── Model/ │ │ │ │ ├── Competitor.cs │ │ │ │ ├── IGame.cs │ │ │ │ ├── IGameRewardPolicy.cs │ │ │ │ ├── IGameScoringPolicy.cs │ │ │ │ ├── IScoreFinder.cs │ │ │ │ ├── OnlineDeathmatch.cs │ │ │ │ ├── Ranking.cs │ │ │ │ └── Score.cs │ │ │ └── WithoutDomainServices/ │ │ │ └── Model/ │ │ │ ├── Competitor.cs │ │ │ ├── OnlineDeathmatch.cs │ │ │ ├── Ranking.cs │ │ │ └── Score.cs │ │ ├── PPPDDDChap18.DomainServices.csproj │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── RestaurantBooking/ │ │ │ └── Model/ │ │ │ ├── BookingDetails.cs │ │ │ ├── Customer.cs │ │ │ ├── DomainEvents.cs │ │ │ ├── Events/ │ │ │ │ └── BookingConfirmedByCustomer.cs │ │ │ ├── Handlers/ │ │ │ │ └── NotifyRestaurantOnCustomerBookingConfirmation.cs │ │ │ ├── IHandleEvents.cs │ │ │ ├── Restaurant.cs │ │ │ ├── RestaurantBooking.cs │ │ │ ├── RestaurantBookingFactory.cs │ │ │ ├── RestaurantBookingRepository.cs │ │ │ └── RestaurantNotifier.cs │ │ └── Shipping/ │ │ ├── Application/ │ │ │ └── ShippingRouteFinder.cs │ │ └── Model/ │ │ └── IShippingRouteFinder.cs │ ├── PPPDDDChap18.DomainServices.sln │ └── README.md ├── 18 - Domain Events/ │ ├── .nuget/ │ │ ├── NuGet.Config │ │ └── NuGet.targets │ ├── DomainEvents.OnlineTakeawayStore.sln │ ├── OnlineTakeawayStore.NServiceBus/ │ │ ├── App.config │ │ ├── Application/ │ │ │ ├── ConfirmDeliveryOfOrder.cs │ │ │ └── Events/ │ │ │ └── RefundDueToLateDelivery.cs │ │ ├── Infrastructure/ │ │ │ └── EndpointConfig.cs │ │ ├── Model/ │ │ │ ├── Events/ │ │ │ │ └── DeliveryGuaranteeFailed.cs │ │ │ ├── FoodDeliveryOrderSteps.cs │ │ │ ├── IDeliveryGuaranteeOffer.cs │ │ │ ├── IOrderRepository.cs │ │ │ └── OrderForDelivery.cs │ │ ├── OnlineTakeawayStore.NServiceBus.csproj │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── packages.config │ ├── OnlineTakeawayStore.NativeEvents/ │ │ ├── Application/ │ │ │ ├── CofirmDeliveryOfOrder.cs │ │ │ └── Events/ │ │ │ └── RefundDueToLateDelivery.cs │ │ ├── Model/ │ │ │ ├── Events/ │ │ │ │ └── DeliveryGuaranteeFailed.cs │ │ │ ├── FoodDeliveryOrderSteps.cs │ │ │ ├── IDeliveryGuaranteeOffer.cs │ │ │ ├── IOrderRepository.cs │ │ │ └── OrderForDelivery.cs │ │ ├── OnlineTakeawayStore.NativeEvents.csproj │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── packages.config │ ├── OnlineTakeawayStore.ReturnEvents/ │ │ ├── Application/ │ │ │ └── ConfirmDeliveryOfOrder.cs │ │ ├── Infrastructure/ │ │ │ └── IEventDispatcher.cs │ │ ├── Model/ │ │ │ ├── Events/ │ │ │ │ └── DeliveryGuaranteeFailed.cs │ │ │ ├── FoodDeliveryOrderSteps.cs │ │ │ ├── IDeliveryGuaranteeOffer.cs │ │ │ ├── IOrderRepository.cs │ │ │ └── OrderForDelivery.cs │ │ ├── OnlineTakeawayStore.ReturnEvents.csproj │ │ └── Properties/ │ │ └── AssemblyInfo.cs │ ├── OnlineTakeawayStore.StaticDomainEvents/ │ │ ├── Application/ │ │ │ ├── ConfirmDeliveryOfOrder.cs │ │ │ └── Events/ │ │ │ └── RefundDueToLateDelivery.cs │ │ ├── Infrastructure/ │ │ │ └── DomainEvents.cs │ │ ├── Model/ │ │ │ ├── Events/ │ │ │ │ └── DeliveryGuaranteeFailed.cs │ │ │ ├── FoodDeliveryOrderSteps.cs │ │ │ ├── IDeliveryGuaranteeOffer.cs │ │ │ ├── IOrderRepository.cs │ │ │ └── OrderForDelivery.cs │ │ ├── OnlineTakeawayStore.StaticDomainEvents.csproj │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── packages.config │ └── OnlineTakeawayStore.Tests/ │ ├── OnlineTakeawayStore.Tests.csproj │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── ServiceLayerTestExamples/ │ │ └── Delivery_guarantee_failed.cs │ ├── UnitTestExamples/ │ │ ├── ReturnDomainEvents.cs │ │ └── StaticDomainEvents.cs │ └── packages.config ├── 19 - Aggregates/ │ ├── PPPDDDChap19.eBidder/ │ │ ├── PPPDDDChap19.eBidder.Common/ │ │ │ ├── PPPDDDChap19.eBidder.Common.csproj │ │ │ └── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── PPPDDDChap19.eBidder.Disputes/ │ │ │ ├── PPPDDDChap19.eBidder.Disputes.csproj │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── _ReadMe.txt │ │ ├── PPPDDDChap19.eBidder.Listings/ │ │ │ ├── Application/ │ │ │ │ ├── Auctions/ │ │ │ │ │ └── BusinessUseCases/ │ │ │ │ │ ├── AuctionCreation.cs │ │ │ │ │ ├── BidOnAuctionService.cs │ │ │ │ │ └── CreateAuctionService.cs │ │ │ │ ├── QandA/ │ │ │ │ │ └── BusinessUseCases/ │ │ │ │ │ ├── Answer.cs │ │ │ │ │ ├── AnswerAQuestionService.cs │ │ │ │ │ └── AskAQuestionService.cs │ │ │ │ └── Watching/ │ │ │ │ └── BusinessUseCases/ │ │ │ │ ├── UnWatchItem.cs │ │ │ │ ├── WatchItem.cs │ │ │ │ └── WatchItemService.cs │ │ │ ├── Infrastructure/ │ │ │ │ ├── DomainEvents.cs │ │ │ │ ├── Entity.cs │ │ │ │ ├── IClock.cs │ │ │ │ ├── SystemClock.cs │ │ │ │ └── ValueObject.cs │ │ │ ├── Model/ │ │ │ │ ├── ListingFormat/ │ │ │ │ │ ├── Auctions/ │ │ │ │ │ │ ├── Auction.cs │ │ │ │ │ │ ├── AuctionId.cs │ │ │ │ │ │ ├── AutomaticBidder.cs │ │ │ │ │ │ ├── BidHistory/ │ │ │ │ │ │ │ ├── Bid.cs │ │ │ │ │ │ │ └── IBidHistoryRepository.cs │ │ │ │ │ │ ├── BidPlaced.cs │ │ │ │ │ │ ├── IAuctionRepository.cs │ │ │ │ │ │ ├── Offer.cs │ │ │ │ │ │ ├── OutBid.cs │ │ │ │ │ │ ├── Price.cs │ │ │ │ │ │ └── WinningBid.cs │ │ │ │ │ └── FixedPriceListings/ │ │ │ │ │ ├── FixedPriceListing.cs │ │ │ │ │ ├── IFixedPriceListingRepository.cs │ │ │ │ │ └── Offers/ │ │ │ │ │ └── BestOffer.cs │ │ │ │ ├── Listings/ │ │ │ │ │ ├── FormatType.cs │ │ │ │ │ ├── IListingRepository.cs │ │ │ │ │ ├── Listing.cs │ │ │ │ │ ├── ListingFormat.cs │ │ │ │ │ ├── ListingRevision.cs │ │ │ │ │ └── ListingRevisionEvent.cs │ │ │ │ ├── Members/ │ │ │ │ │ ├── IMemberService.cs │ │ │ │ │ └── Member.cs │ │ │ │ ├── Money.cs │ │ │ │ ├── MoneyCannotBeANegativeValueException.cs │ │ │ │ ├── MoreThanTwoDecimalPlacesInMoneyValueException.cs │ │ │ │ ├── QandA/ │ │ │ │ │ ├── Answer.cs │ │ │ │ │ ├── IQuestionRepository.cs │ │ │ │ │ ├── Question.cs │ │ │ │ │ ├── QuestionAnswered.cs │ │ │ │ │ └── QuestionSubmitted.cs │ │ │ │ ├── Sellers/ │ │ │ │ │ ├── ISellerService.cs │ │ │ │ │ └── Seller.cs │ │ │ │ └── WatchLists/ │ │ │ │ ├── IWatchedItemRepository.cs │ │ │ │ └── WatchedItem.cs │ │ │ ├── PPPDDDChap19.eBidder.Listings.csproj │ │ │ └── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── PPPDDDChap19.eBidder.Membership/ │ │ │ ├── Model/ │ │ │ │ └── Members/ │ │ │ │ ├── IMemberRepository.cs │ │ │ │ └── Member.cs │ │ │ ├── PPPDDDChap19.eBidder.Membership.csproj │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── _ReadMe.txt │ │ ├── PPPDDDChap19.eBidder.SellerAccount/ │ │ │ ├── PPPDDDChap19.eBidder.SellerAccount.csproj │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── _ReadMe.txt │ │ └── PPPDDDChap19.eBidder.sln │ └── README.md ├── 20 - Factories/ │ └── README.md ├── 21 - Repositories/ │ ├── DDDPPP.Chap21.EFExample/ │ │ ├── .nuget/ │ │ │ ├── NuGet.Config │ │ │ └── NuGet.targets │ │ ├── DDDPPP.Chap21.EFExample.Application/ │ │ │ ├── App.config │ │ │ ├── Application/ │ │ │ │ ├── BusinessUseCases/ │ │ │ │ │ ├── BidOnAuction.cs │ │ │ │ │ ├── CreateAuction.cs │ │ │ │ │ └── NewAuctionRequest.cs │ │ │ │ └── Queries/ │ │ │ │ ├── AuctionStatus.cs │ │ │ │ ├── AuctionStatusQuery.cs │ │ │ │ ├── BidHistoryQuery.cs │ │ │ │ └── BidInformation.cs │ │ │ ├── Bootstrapper.cs │ │ │ ├── DDDPPP.Chap21.EFExample.Application.csproj │ │ │ ├── Infrastructure/ │ │ │ │ ├── AuctionDatabaseContext.cs │ │ │ │ ├── AuctionRepository.cs │ │ │ │ ├── BidHistoryRepository.cs │ │ │ │ ├── DataModel/ │ │ │ │ │ ├── AuctionDTO.cs │ │ │ │ │ └── BidDTO.cs │ │ │ │ ├── DomainEvents.cs │ │ │ │ ├── Entity.cs │ │ │ │ ├── IClock.cs │ │ │ │ ├── Mapping/ │ │ │ │ │ ├── AuctionMap.cs │ │ │ │ │ └── BidMap.cs │ │ │ │ ├── SystemClock.cs │ │ │ │ └── ValueObject.cs │ │ │ ├── Model/ │ │ │ │ ├── Auction/ │ │ │ │ │ ├── Auction.cs │ │ │ │ │ ├── AuctionSnapshot.cs │ │ │ │ │ ├── AutomaticBidder.cs │ │ │ │ │ ├── BidPlaced.cs │ │ │ │ │ ├── IAuctionRepository.cs │ │ │ │ │ ├── Money.cs │ │ │ │ │ ├── MoneyCannotBeANegativeValueException.cs │ │ │ │ │ ├── MoneySnapshot.cs │ │ │ │ │ ├── MoreThanTwoDecimalPlacesInMoneyValueException.cs │ │ │ │ │ ├── Offer.cs │ │ │ │ │ ├── OutBid.cs │ │ │ │ │ ├── Price.cs │ │ │ │ │ ├── WinningBid.cs │ │ │ │ │ └── WinningBidSnapshot.cs │ │ │ │ └── BidHistory/ │ │ │ │ ├── Bid.cs │ │ │ │ ├── BidHistory.cs │ │ │ │ └── IBidHistoryRepository.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ ├── DDDPPP.Chap21.EFExample.Presentation/ │ │ │ ├── App.config │ │ │ ├── DDDPPP.Chap21.EFExample.Presentation.csproj │ │ │ ├── Program.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ └── DDDPPP.Chap21.EFExample.sln │ ├── DDDPPP.Chap21.MicroORM/ │ │ ├── .nuget/ │ │ │ ├── NuGet.Config │ │ │ └── NuGet.targets │ │ ├── DDDPPP.Chap21.MicroORM.Application/ │ │ │ ├── Application/ │ │ │ │ ├── BusinessUseCases/ │ │ │ │ │ ├── BidOnAuction.cs │ │ │ │ │ ├── CreateAuction.cs │ │ │ │ │ └── NewAuctionRequest.cs │ │ │ │ └── Queries/ │ │ │ │ ├── AuctionStatus.cs │ │ │ │ ├── AuctionStatusQuery.cs │ │ │ │ ├── BidHistoryQuery.cs │ │ │ │ └── BidInformation.cs │ │ │ ├── Bootstrapper.cs │ │ │ ├── DDDPPP.Chap21.MicroORM.Application.csproj │ │ │ ├── Infrastructure/ │ │ │ │ ├── AuctionRepository.cs │ │ │ │ ├── BidHistoryRepository.cs │ │ │ │ ├── ConcurrencyException.cs │ │ │ │ ├── DataModel/ │ │ │ │ │ ├── AuctionDTO.cs │ │ │ │ │ └── BidDTO.cs │ │ │ │ ├── DomainEvents.cs │ │ │ │ ├── Entity.cs │ │ │ │ ├── IAggregateDataModel.cs │ │ │ │ ├── IClock.cs │ │ │ │ ├── IUnitOfWork.cs │ │ │ │ ├── IUnitOfWorkRepository.cs │ │ │ │ ├── SystemClock.cs │ │ │ │ ├── UnitOfWork.cs │ │ │ │ └── ValueObject.cs │ │ │ ├── Model/ │ │ │ │ ├── Auction/ │ │ │ │ │ ├── Auction.cs │ │ │ │ │ ├── AuctionSnapshot.cs │ │ │ │ │ ├── Bid.cs │ │ │ │ │ ├── BidPlaced.cs │ │ │ │ │ ├── IAuctionRepository.cs │ │ │ │ │ ├── Money.cs │ │ │ │ │ ├── MoneyCannotBeANegativeValueException.cs │ │ │ │ │ ├── MoneySnapshot.cs │ │ │ │ │ ├── MoreThanTwoDecimalPlacesInMoneyValueException.cs │ │ │ │ │ ├── OutBid.cs │ │ │ │ │ ├── Price.cs │ │ │ │ │ ├── WinningBid.cs │ │ │ │ │ └── WinningBidSnapshot.cs │ │ │ │ └── BidHistory/ │ │ │ │ ├── BidHistory.cs │ │ │ │ ├── HistoricalBid.cs │ │ │ │ └── IBidHistoryRepository.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ ├── DDDPPP.Chap21.MicroORM.Presentation/ │ │ │ ├── App.config │ │ │ ├── DDDPPP.Chap21.MicroORM.Presentation.csproj │ │ │ ├── Program.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ └── DDDPPP.Chap21.MicroORM.sln │ ├── DDDPPP.Chap21.NHibernateExample/ │ │ ├── .nuget/ │ │ │ ├── NuGet.Config │ │ │ └── NuGet.targets │ │ ├── DDDPPP.Chap21.NHibernateExample.Application/ │ │ │ ├── Application/ │ │ │ │ ├── BusinessUseCases/ │ │ │ │ │ ├── BidOnAuction.cs │ │ │ │ │ ├── CreateAuction.cs │ │ │ │ │ └── NewAuctionRequest.cs │ │ │ │ └── Queries/ │ │ │ │ ├── AuctionStatus.cs │ │ │ │ ├── AuctionStatusQuery.cs │ │ │ │ ├── BidHistoryQuery.cs │ │ │ │ └── BidInformation.cs │ │ │ ├── Bootstrapper.cs │ │ │ ├── DDDPPP.Chap21.NHibernateExample.Application.csproj │ │ │ ├── Infrastructure/ │ │ │ │ ├── Auction.hbm.xml │ │ │ │ ├── AuctionRepository.cs │ │ │ │ ├── Bid.hbm.xml │ │ │ │ ├── BidHistoryRepository.cs │ │ │ │ ├── DomainEvents.cs │ │ │ │ ├── Entity.cs │ │ │ │ ├── IClock.cs │ │ │ │ ├── SystemClock.cs │ │ │ │ └── ValueObject.cs │ │ │ ├── Model/ │ │ │ │ ├── Auction/ │ │ │ │ │ ├── Auction.cs │ │ │ │ │ ├── AutomaticBidder.cs │ │ │ │ │ ├── BidPlaced.cs │ │ │ │ │ ├── IAuctionRepository.cs │ │ │ │ │ ├── Money.cs │ │ │ │ │ ├── MoneyCannotBeANegativeValueException.cs │ │ │ │ │ ├── MoreThanTwoDecimalPlacesInMoneyValueException.cs │ │ │ │ │ ├── Offer.cs │ │ │ │ │ ├── OutBid.cs │ │ │ │ │ ├── Price.cs │ │ │ │ │ └── WinningBid.cs │ │ │ │ └── BidHistory/ │ │ │ │ ├── Bid.cs │ │ │ │ └── IBidHistoryRepository.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ ├── DDDPPP.Chap21.NHibernateExample.Presentation/ │ │ │ ├── App.config │ │ │ ├── DDDPPP.Chap21.NHibernateExample.Presentation.csproj │ │ │ ├── Program.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ └── DDDPPP.Chap21.NHibernateExample.sln │ ├── DDDPPP.Chap21.RavenDBExample/ │ │ ├── .nuget/ │ │ │ ├── NuGet.Config │ │ │ └── NuGet.targets │ │ ├── DDDPPP.Chap21.RavenDBExample.Application/ │ │ │ ├── Application/ │ │ │ │ ├── BusinessUseCases/ │ │ │ │ │ ├── BidOnAuction.cs │ │ │ │ │ ├── CreateAuction.cs │ │ │ │ │ └── NewAuctionRequest.cs │ │ │ │ └── Queries/ │ │ │ │ ├── AuctionStatus.cs │ │ │ │ ├── AuctionStatusQuery.cs │ │ │ │ ├── BidHistoryQuery.cs │ │ │ │ └── BidInformation.cs │ │ │ ├── Bootstrapper.cs │ │ │ ├── DDDPPP.Chap21.RavenDBExample.Application.csproj │ │ │ ├── Infrastructure/ │ │ │ │ ├── AuctionRepository.cs │ │ │ │ ├── BidHistoryRepository.cs │ │ │ │ ├── BidHistory_NumberOfBids.cs │ │ │ │ ├── DomainEvents.cs │ │ │ │ ├── Entity.cs │ │ │ │ ├── IClock.cs │ │ │ │ ├── SystemClock.cs │ │ │ │ └── ValueObject.cs │ │ │ ├── Model/ │ │ │ │ ├── Auction/ │ │ │ │ │ ├── Auction.cs │ │ │ │ │ ├── AutomaticBidder.cs │ │ │ │ │ ├── BidPlaced.cs │ │ │ │ │ ├── IAuctionRepository.cs │ │ │ │ │ ├── Money.cs │ │ │ │ │ ├── MoneyCannotBeANegativeValueException.cs │ │ │ │ │ ├── MoreThanTwoDecimalPlacesInMoneyValueException.cs │ │ │ │ │ ├── Offer.cs │ │ │ │ │ ├── OutBid.cs │ │ │ │ │ ├── Price.cs │ │ │ │ │ └── WinningBid.cs │ │ │ │ └── BidHistory/ │ │ │ │ ├── Bid.cs │ │ │ │ ├── BidHistory.cs │ │ │ │ └── IBidHistoryRepository.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ ├── DDDPPP.Chap21.RavenDBExample.Application.Tests/ │ │ │ ├── DDDPPP.Chap21.RavenDBExample.Application.Tests.csproj │ │ │ ├── Domain/ │ │ │ │ └── AutomaticBidderScenarios.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ ├── DDDPPP.Chap21.RavenDBExample.Presentation/ │ │ │ ├── App.config │ │ │ ├── DDDPPP.Chap21.RavenDBExample.Presentation.csproj │ │ │ ├── Program.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ └── DDDPPP.Chap21.RavenDBExample.sln │ └── Database_script_for_examples.sql ├── 22 - Event Sourcing/ │ ├── PPPDDD.Chap23.EventSourcing.EventStoreDemo/ │ │ ├── GetEventStore.cs │ │ ├── ImportTestData.cs │ │ ├── PPPDDD.Chap23.EventSourcing.EventStoreDemo.csproj │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── Tests.cs │ │ └── packages.config │ ├── PPPDDDChap22/ │ │ ├── .nuget/ │ │ │ ├── NuGet.Config │ │ │ └── NuGet.targets │ │ ├── PPPDDDChap23.EventSourcing.Application/ │ │ │ ├── Application/ │ │ │ │ └── BusinessUseCases/ │ │ │ │ ├── CreateAccount.cs │ │ │ │ ├── RecordPhonecall.cs │ │ │ │ └── TopUpCredit.cs │ │ │ ├── Bootstrapper.cs │ │ │ ├── Infrastructure/ │ │ │ │ ├── Entity.cs │ │ │ │ ├── EventSourcedAggregate.cs │ │ │ │ ├── EventStore.cs │ │ │ │ ├── EventStream.cs │ │ │ │ ├── EventWrapper.cs │ │ │ │ ├── IClock.cs │ │ │ │ ├── PayAsYouGoAccountRepository.cs │ │ │ │ ├── SystemClock.cs │ │ │ │ └── ValueObject.cs │ │ │ ├── Model/ │ │ │ │ └── PayAsYouGo/ │ │ │ │ ├── AccountCreated.cs │ │ │ │ ├── CreditAdded.cs │ │ │ │ ├── CreditSatisfiesFreeCallAllowanceOffer.cs │ │ │ │ ├── FreeCallAllowance.cs │ │ │ │ ├── IPayAsYouGoAccountRepository.cs │ │ │ │ ├── Minutes.cs │ │ │ │ ├── Money.cs │ │ │ │ ├── PayAsYouGoAccount.cs │ │ │ │ ├── PayAsYouGoAccountSnapshot.cs │ │ │ │ ├── PayAsYouGoInclusiveMinutesOffer.cs │ │ │ │ ├── PhoneCall.cs │ │ │ │ ├── PhoneCallCharged.cs │ │ │ │ ├── PhoneCallCosting.cs │ │ │ │ └── PhoneNumber.cs │ │ │ ├── PPPDDDChap23.EventSourcing.Application.csproj │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ ├── PPPDDDChap23.EventSourcing.ApplicationTests/ │ │ │ ├── PPPDDDChap23.EventSourcing.ApplicationTests.csproj │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ ├── PPPDDDChap23.EventSourcing.Presentation/ │ │ │ ├── App.config │ │ │ ├── PPPDDDChap23.EventSourcing.Presentation.csproj │ │ │ ├── Program.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ └── PPPDDDChap23.EventSourcing.sln │ ├── PPPDDDChap23.EventSourcing/ │ │ ├── .nuget/ │ │ │ ├── NuGet.Config │ │ │ └── NuGet.targets │ │ ├── PPPDDDChap23.EventSourcing.Application/ │ │ │ ├── Application/ │ │ │ │ └── BusinessUseCases/ │ │ │ │ ├── CreateAccount.cs │ │ │ │ ├── RecordPhonecall.cs │ │ │ │ └── TopUpCredit.cs │ │ │ ├── Bootstrapper.cs │ │ │ ├── Infrastructure/ │ │ │ │ ├── DomainEvent.cs │ │ │ │ ├── Entity.cs │ │ │ │ ├── EventSourcedAggregate.cs │ │ │ │ ├── EventStore.cs │ │ │ │ ├── EventStream.cs │ │ │ │ ├── EventWrapper.cs │ │ │ │ ├── IClock.cs │ │ │ │ ├── PasAsYouGoSnapshotJob.cs │ │ │ │ ├── PayAsYouGoAccountRepository.cs │ │ │ │ ├── SystemClock.cs │ │ │ │ └── ValueObject.cs │ │ │ ├── Model/ │ │ │ │ └── PayAsYouGo/ │ │ │ │ ├── AccountCreated.cs │ │ │ │ ├── CreditAdded.cs │ │ │ │ ├── CreditSatisfiesFreeCallAllowanceOffer.cs │ │ │ │ ├── FreeCallAllowance.cs │ │ │ │ ├── IPayAsYouGoAccountRepository.cs │ │ │ │ ├── Minutes.cs │ │ │ │ ├── Money.cs │ │ │ │ ├── PayAsYouGoAccount.cs │ │ │ │ ├── PayAsYouGoAccountSnapshot.cs │ │ │ │ ├── PayAsYouGoInclusiveMinutesOffer.cs │ │ │ │ ├── PhoneCall.cs │ │ │ │ ├── PhoneCallCharged.cs │ │ │ │ ├── PhoneCallCosting.cs │ │ │ │ └── PhoneNumber.cs │ │ │ ├── PPPDDDChap23.EventSourcing.Application.csproj │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ ├── PPPDDDChap23.EventSourcing.ApplicationTests/ │ │ │ ├── PPPDDDChap23.EventSourcing.ApplicationTests.csproj │ │ │ ├── PayAsYouGoAccount_Tests.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ ├── PPPDDDChap23.EventSourcing.Presentation/ │ │ │ ├── App.config │ │ │ ├── PPPDDDChap23.EventSourcing.Presentation.csproj │ │ │ ├── Program.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── packages.config │ │ └── PPPDDDChap23.EventSourcing.sln │ └── README.md ├── 23 - Architecting Application User Interfaces/ │ ├── PPPDDD.NonDist.UIComp/ │ │ ├── PPPDDD.NonDist.UIComp/ │ │ │ ├── App_Start/ │ │ │ │ └── RouteConfig.cs │ │ │ ├── Controllers/ │ │ │ │ ├── CatalogueBoundedContextController.cs │ │ │ │ ├── HomeController.cs │ │ │ │ ├── PricingBoundedContextController.cs │ │ │ │ └── ShippingBoundedContextController.cs │ │ │ ├── Global.asax │ │ │ ├── Global.asax.cs │ │ │ ├── PPPDDD.NonDist.UIComp.csproj │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── Scripts/ │ │ │ │ ├── jquery-1.10.2.intellisense.js │ │ │ │ ├── jquery-1.10.2.js │ │ │ │ ├── jquery.validate-vsdoc.js │ │ │ │ ├── jquery.validate.js │ │ │ │ └── jquery.validate.unobtrusive.js │ │ │ ├── Views/ │ │ │ │ ├── CatalogBoundedContext/ │ │ │ │ │ └── ItemInBasket.cshtml │ │ │ │ ├── Home/ │ │ │ │ │ └── Index.cshtml │ │ │ │ ├── PricingBoundedContext/ │ │ │ │ │ └── Price.cshtml │ │ │ │ ├── ShippingBoundedContext/ │ │ │ │ │ └── DeliveryOptions.cshtml │ │ │ │ └── web.config │ │ │ ├── Web.Debug.config │ │ │ ├── Web.Release.config │ │ │ ├── Web.config │ │ │ └── packages.config │ │ └── PPPDDD.NonDist.UIComp.sln │ ├── PPPSSS.Dist.UIComp/ │ │ ├── PPPSSS.Dist.UIComp/ │ │ │ ├── App_Start/ │ │ │ │ └── RouteConfig.cs │ │ │ ├── Controllers/ │ │ │ │ ├── HolidaysController.cs │ │ │ │ ├── HomeController.cs │ │ │ │ ├── PromotionsController.cs │ │ │ │ └── RecommendationsController.cs │ │ │ ├── Global.asax │ │ │ ├── Global.asax.cs │ │ │ ├── PPPSSS.Dist.UIComp.csproj │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── Scripts/ │ │ │ │ ├── jquery-1.10.2.intellisense.js │ │ │ │ ├── jquery-1.10.2.js │ │ │ │ ├── jquery.validate-vsdoc.js │ │ │ │ ├── jquery.validate.js │ │ │ │ ├── jquery.validate.unobtrusive.js │ │ │ │ └── pppddd-application.js │ │ │ ├── Views/ │ │ │ │ ├── Home/ │ │ │ │ │ └── Index.cshtml │ │ │ │ └── web.config │ │ │ ├── Web.Debug.config │ │ │ ├── Web.Release.config │ │ │ ├── Web.config │ │ │ └── packages.config │ │ └── PPPSSS.Dist.UIComp.sln │ └── README.md ├── 24 - CQRS An Architecture of A Bounded Context/ │ └── README.md ├── 25 - Commands Application Service Patterns for processing Business Use Cases/ │ ├── .nuget/ │ │ ├── NuGet.Config │ │ └── NuGet.targets │ ├── DDDPPP.Chap20.CommandHandler.Application/ │ │ ├── Application/ │ │ │ ├── Api.cs │ │ │ ├── Commands/ │ │ │ │ ├── AddProductToBasketCommand.cs │ │ │ │ ├── ApplyCouponToBasketCommand.cs │ │ │ │ ├── CreateABasketCommand.cs │ │ │ │ ├── RemoveOfferFromBasketCommand.cs │ │ │ │ ├── RemoveProductFromBasketCommand.cs │ │ │ │ └── UpdateBasketDeliveryCountry.cs │ │ │ ├── Contract/ │ │ │ │ └── _readme.txt │ │ │ ├── Handlers/ │ │ │ │ ├── AddProductToBasketCommandHandler.cs │ │ │ │ ├── ApplyCouponToBasketCommandHandler.cs │ │ │ │ ├── CreateABasketCommandHandler.cs │ │ │ │ ├── RemoveCouponFromBasketCommandHandler.cs │ │ │ │ └── RemoveProductFromBasketCommandHandler.cs │ │ │ └── ReadModel/ │ │ │ └── Product.cs │ │ ├── CommandHandlerRegistry.cs │ │ ├── DDDPPP.Chap20.CommandHandler.Application.csproj │ │ ├── DomainEventHandlerRegistery.cs │ │ ├── Infrastructure/ │ │ │ ├── BasketRepository.cs │ │ │ ├── Mapping/ │ │ │ │ ├── Basket.hbm.xml │ │ │ │ ├── BasketItem.hbm.xml │ │ │ │ ├── BasketVoucher.hbm.xml │ │ │ │ ├── Offer.hbm.xml │ │ │ │ └── Product.hbm.xml │ │ │ └── PromotionsRepository.cs │ │ ├── Model/ │ │ │ ├── Baskets/ │ │ │ │ ├── Basket.cs │ │ │ │ ├── BasketItem.cs │ │ │ │ ├── BasketItemFactory.cs │ │ │ │ ├── BasketPricingBreakdown.cs │ │ │ │ ├── BasketPricingService.cs │ │ │ │ ├── Events/ │ │ │ │ │ ├── BasketCreated.cs │ │ │ │ │ ├── BasketModified.cs │ │ │ │ │ ├── BasketPriceChanged.cs │ │ │ │ │ └── CouponNotApplicableForBasketItems.cs │ │ │ │ ├── IBasketPricingService.cs │ │ │ │ ├── IBasketRepository.cs │ │ │ │ ├── NonNegativeQuantity.cs │ │ │ │ └── ProductSnapshot.cs │ │ │ └── Promotions/ │ │ │ ├── Coupon.cs │ │ │ ├── CouponIssues.cs │ │ │ ├── ICouponPolicy.cs │ │ │ ├── IPromotionsRepository.cs │ │ │ ├── Promotion.cs │ │ │ └── PromotionNotApplicableException.cs │ │ └── Properties/ │ │ └── AssemblyInfo.cs │ ├── DDDPPP.Chap20.CommandHandler.Presentation/ │ │ ├── Content/ │ │ │ ├── Site.css │ │ │ └── themes/ │ │ │ └── base/ │ │ │ ├── jquery-ui.css │ │ │ ├── jquery.ui.accordion.css │ │ │ ├── jquery.ui.all.css │ │ │ ├── jquery.ui.autocomplete.css │ │ │ ├── jquery.ui.base.css │ │ │ ├── jquery.ui.button.css │ │ │ ├── jquery.ui.core.css │ │ │ ├── jquery.ui.datepicker.css │ │ │ ├── jquery.ui.dialog.css │ │ │ ├── jquery.ui.progressbar.css │ │ │ ├── jquery.ui.resizable.css │ │ │ ├── jquery.ui.selectable.css │ │ │ ├── jquery.ui.slider.css │ │ │ ├── jquery.ui.tabs.css │ │ │ └── jquery.ui.theme.css │ │ ├── Controllers/ │ │ │ ├── AccountController.cs │ │ │ └── HomeController.cs │ │ ├── DDDPPP.Chap20.CommandHandler.Presentation.csproj │ │ ├── Global.asax │ │ ├── Global.asax.cs │ │ ├── Models/ │ │ │ └── AccountModels.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── Scripts/ │ │ │ ├── MicrosoftAjax.debug.js │ │ │ ├── MicrosoftAjax.js │ │ │ ├── MicrosoftMvcAjax.debug.js │ │ │ ├── MicrosoftMvcAjax.js │ │ │ ├── MicrosoftMvcValidation.debug.js │ │ │ ├── MicrosoftMvcValidation.js │ │ │ ├── jquery-1.7.1.intellisense.js │ │ │ ├── jquery-1.7.1.js │ │ │ ├── jquery-ui-1.8.20.js │ │ │ ├── jquery.unobtrusive-ajax.js │ │ │ ├── jquery.validate-vsdoc.js │ │ │ ├── jquery.validate.js │ │ │ ├── jquery.validate.unobtrusive.js │ │ │ └── modernizr-2.5.3.js │ │ ├── Views/ │ │ │ ├── Account/ │ │ │ │ ├── ChangePassword.aspx │ │ │ │ ├── ChangePasswordSuccess.aspx │ │ │ │ ├── LogOn.aspx │ │ │ │ └── Register.aspx │ │ │ ├── Home/ │ │ │ │ ├── About.aspx │ │ │ │ └── Index.aspx │ │ │ ├── Shared/ │ │ │ │ ├── Error.aspx │ │ │ │ ├── LogOnUserControl.ascx │ │ │ │ └── Site.Master │ │ │ └── Web.config │ │ ├── Web.Debug.config │ │ ├── Web.Release.config │ │ ├── Web.config │ │ └── packages.config │ ├── DDDPPP.Chap20.CommandHandler.sln │ ├── PPPDDD.ApplicationServices.Gambling/ │ │ ├── App_Start/ │ │ │ └── RouteConfig.cs │ │ ├── ApplicationServices/ │ │ │ ├── 1_validation/ │ │ │ │ └── RecommendAFriendService.cs │ │ │ ├── 2_transaction/ │ │ │ │ └── RecommendAFriendService.cs │ │ │ ├── 3_error_handling/ │ │ │ │ └── RecommendAFriendService.cs │ │ │ ├── 4_logging_metrics/ │ │ │ │ └── RecommendAFriendService.cs │ │ │ ├── 5_authentication/ │ │ │ │ └── AdminRecommendAFriendService.cs │ │ │ ├── 6_communication/ │ │ │ │ └── RecommendAFriendService.cs │ │ │ ├── AsyncAwait/ │ │ │ │ └── RecommendAFriend.cs │ │ │ ├── CommandProcessor/ │ │ │ │ ├── BloatedRecommendAFriendService.cs │ │ │ │ └── RecommendAFriend.cs │ │ │ ├── CommandProcessorChained/ │ │ │ │ └── RecommendAFriend.cs │ │ │ ├── FrameworkHooks/ │ │ │ │ ├── ErrorFilter.cs │ │ │ │ └── TransactionFilter.cs │ │ │ ├── PublishSubscribe/ │ │ │ │ └── RecommendAFriend.cs │ │ │ ├── PublishSubscribeAsync/ │ │ │ │ └── ReferAFriend.cs │ │ │ └── RequestReply/ │ │ │ └── RecommendAFriend.cs │ │ ├── Controllers/ │ │ │ └── RecommendAFriendController.cs │ │ ├── Global.asax │ │ ├── Global.asax.cs │ │ ├── PPPDDD.ApplicationServices.RecommendAFriend.csproj │ │ ├── PPPDDD.ApplicationServices.RecommendAFriend.sln │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── Views/ │ │ │ └── web.config │ │ ├── Web.Debug.config │ │ ├── Web.Release.config │ │ ├── Web.config │ │ └── packages.config │ ├── PPPDDD.ApplicationServices.RecommendAFriend.sln │ └── PPPDDD.ApplicationServices.Tests/ │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── Refer_a_friend.cs │ ├── Tests.csproj │ └── packages.config ├── 26 - Queries Domain Reporting/ │ ├── PPPDDD.Reporting/ │ │ ├── App_Start/ │ │ │ └── RouteConfig.cs │ │ ├── Controllers/ │ │ │ ├── DealershipPerformanceReportController.cs │ │ │ ├── DealershipReportUsingMediatorController.cs │ │ │ ├── DenormalizedLoyaltyReportController.cs │ │ │ ├── HealthcareEventProjectionReportController.cs │ │ │ └── LoyaltyReportQueryingDatastoreController.cs │ │ ├── Global.asax │ │ ├── Global.asax.cs │ │ ├── PPPDDD.Reporting.csproj │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── Views/ │ │ │ └── web.config │ │ ├── Web.Debug.config │ │ ├── Web.Release.config │ │ ├── Web.config │ │ └── packages.config │ ├── PPPDDD.Reporting.sln │ ├── README.md │ └── SportsStoreDatabase/ │ ├── LoyaltyAccounts.sql │ ├── LoyaltySettings.sql │ ├── Orders.sql │ ├── TestData.sql │ ├── Users.sql │ └── sportsstoredatabase.sqlproj ├── README.md └── eBidder Case Study/ └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ ############################################################################### # Set default behavior to automatically normalize line endings. ############################################################################### * text=auto ############################################################################### # Set default behavior for command prompt diff. # # This is need for earlier builds of msysgit that does not have it on by # default for csharp files. # Note: This is only used by command line ############################################################################### #*.cs diff=csharp ############################################################################### # Set the merge driver for project and solution files # # Merging from the command prompt will add diff markers to the files if there # are conflicts (Merging from VS is not affected by the settings below, in VS # the diff markers are never inserted). Diff markers may cause the following # file extensions to fail to load in VS. An alternative would be to treat # these files as binary and thus will always conflict and require user # intervention with every merge. To do so, just uncomment the entries below ############################################################################### #*.sln merge=binary #*.csproj merge=binary #*.vbproj merge=binary #*.vcxproj merge=binary #*.vcproj merge=binary #*.dbproj merge=binary #*.fsproj merge=binary #*.lsproj merge=binary #*.wixproj merge=binary #*.modelproj merge=binary #*.sqlproj merge=binary #*.wwaproj merge=binary ############################################################################### # behavior for image files # # image files are treated as binary by default. ############################################################################### #*.jpg binary #*.png binary #*.gif binary ############################################################################### # diff behavior for common document formats # # Convert binary document formats to text before diffing them. This feature # is only available from the command line. Turn it on by uncommenting the # entries below. ############################################################################### #*.doc diff=astextplain #*.DOC diff=astextplain #*.docx diff=astextplain #*.DOCX diff=astextplain #*.dot diff=astextplain #*.DOT diff=astextplain #*.pdf diff=astextplain #*.PDF diff=astextplain #*.rtf diff=astextplain #*.RTF diff=astextplain ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. # User-specific files *.suo *.user *.sln.docstates # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ build/ bld/ [Bb]in/ [Oo]bj/ # Roslyn cache directories *.ide/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* #NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c *_i.c *_p.c *_i.h *.ilk *.meta *.obj *.pch *.pdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opensdf *.sdf *.cachefile # Visual Studio profiler *.psess *.vsp *.vspx # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding addin-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # NCrunch _NCrunch_* .*crunch*.local.xml # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # TODO: Comment the next line if you want to checkin your web deploy settings # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # NuGet Packages *.nupkg # The packages folder can be ignored because of Package Restore **/packages/* # except build/, which is used as an MSBuild target. !**/packages/build/ # If using the old MSBuild-Integrated Package Restore, uncomment this: #!**/packages/repositories.config # Windows Azure Build Output csx/ *.build.csdef # Windows Store app package directory AppPackages/ # Others sql/ *.Cache ClientBin/ [Ss]tyle[Cc]op.* ~$* *~ *.dbmdl *.dbproj.schemaview *.pfx *.publishsettings node_modules/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm # SQL Server files *.mdf *.ldf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings # Microsoft Fakes FakesAssemblies/ ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel/Application/BidOnAuctionService.cs ================================================ using System; using PPPDDDChap05.DomainModel.Model; namespace PPPPDDDChap05.DomainModel.Application { public class BidOnAuctionService { private IAuctionRepository _auctions; public BidOnAuctionService(IAuctionRepository auctions) { _auctions = auctions; } public void Bid(Guid auctionId, Guid memberId, decimal amount, DateTime dateOfBid) { var auction = _auctions.FindBy(auctionId); var bidAmount = new Money(amount); var offer = new Bid(memberId, bidAmount, dateOfBid); auction.PlaceBidFor(offer, dateOfBid); } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel/Model/Auction.cs ================================================ using System; using System.Collections.Generic; namespace PPPDDDChap05.DomainModel.Model { public class Auction { private Auction() { } public Auction(Guid id, Guid listingId, Money startingPrice, DateTime endsAt) { if (id == Guid.Empty) throw new ArgumentNullException("Auction Id cannot be null"); if (startingPrice == null) throw new ArgumentNullException("Starting Price cannot be null"); if (endsAt == DateTime.MinValue) throw new ArgumentNullException("EndsAt must have a value"); if (listingId == Guid.Empty) throw new ArgumentNullException("Lisitng Id cannot be null"); Id = id; ListingId = listingId; StartingPrice = startingPrice; EndsAt = endsAt; } private Guid Id { get; set; } private IList Bids { get; set; } private Guid ListingId { get; set; } private DateTime EndsAt { get; set; } private Money StartingPrice { get; set; } private WinningBid WinningBid { get; set; } private bool HasEnded { get; set; } private bool StillInProgress(DateTime currentTime) { return (EndsAt > currentTime); } public bool CanPlaceBid() { return HasEnded == false; } public void PlaceBidFor(Bid bid, DateTime currentTime) { if (StillInProgress(currentTime)) { if (IsFirstBid()) RegisterFirst(bid); else if (BidderIsIncreasingMaximumBid(bid)) WinningBid = WinningBid.RaiseMaximumBidTo(bid.MaximumBid); else if (WinningBid.CanMeetOrExceedBidIncrement(bid.MaximumBid)) { Place(WinningBid.DetermineWinningBidIncrement(bid)); } } } private bool BidderIsIncreasingMaximumBid(Bid bid) { return WinningBid.WasMadeBy(bid.Bidder) && bid.MaximumBid.IsGreaterThan(WinningBid.MaximumBid); } private bool IsFirstBid() { return WinningBid == null; } private void RegisterFirst(Bid bid) { if (IsFirstBid() && bid.MaximumBid.IsGreaterThanOrEqualTo(StartingPrice)) Place(new WinningBid(bid.Bidder, bid.MaximumBid, StartingPrice, bid.TimeOfOffer)); } private void Place(WinningBid newBid) { Bids.Add(new HistoricalBid(newBid.Bidder, newBid.MaximumBid, newBid.TimeOfBid)); WinningBid = newBid; } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel/Model/Bid.cs ================================================ using System; using System.Collections.Generic; namespace PPPDDDChap05.DomainModel.Model { public class Bid { public Bid(Guid bidderId, Money maximumBid, DateTime timeOfOffer) { if (bidderId == Guid.Empty) throw new ArgumentNullException("BidderId cannot be null"); if (maximumBid == null) throw new ArgumentNullException("MaximumBid cannot be null"); if (timeOfOffer == DateTime.MinValue) throw new ArgumentNullException("Time of Offer must have a value"); Bidder = bidderId; MaximumBid = maximumBid; TimeOfOffer = timeOfOffer; } public Guid Bidder { get; private set; } public Money MaximumBid { get; private set; } public DateTime TimeOfOffer { get; private set; } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel/Model/ClassDiagram.cd ================================================  AAACAABAEQgABAAAAAAABAAAACgAAAAABGCAAABAAAA= Model\Auction.cs AAIAAAAAAAAAAAAEAAAAgAAAAAQAAAAAAACoAAAAAAA= Model\Money.cs AAAAAAAAAQAAAAAAAAAAAAIAAAAAgAAAAAAAAAAAAAA= Model\Bid.cs AAAABAAAAAAAAAAAAAAAAACAAgAAAAAAAAAAAAAAAAA= Model\Price.cs BAAIAAAAAQAAAgAhAAAAIAIAAgAAAAUAAAAAAAAEBAA= Model\WinningBid.cs AAAAAAAAAQAAAAABAAAAAACAAAAAAAAAAAAAAAAAAAA= Model\HistoricalBid.cs ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel/Model/HistoricalBid.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDDChap05.DomainModel.Model { public class HistoricalBid { public HistoricalBid(Guid bidder, Money Bid, DateTime timeOfBid) { } public Guid Bidder {get; set;} public Money Amount {get; set;} public DateTime TimeOfBid { get; set; } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel/Model/IAuctionRepository.cs ================================================ using System; namespace PPPDDDChap05.DomainModel.Model { public interface IAuctionRepository { void Add(Auction item); Auction FindBy(Guid Id); } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel/Model/Money.cs ================================================ using System; using System.Collections.Generic; namespace PPPDDDChap05.DomainModel.Model { public class Money { protected decimal Value { get; set; } public Money() : this(0m) { } public Money(decimal value) { ThrowExceptionIfNotValid(value); Value = value; } private void ThrowExceptionIfNotValid(decimal value) { if (value % 0.01m != 0) throw new InvalidOperationException("There cannot be more than two decimal places."); if(value < 0) throw new InvalidOperationException("Money cannot be a negative value."); } public Money Add(Money money) { return new Money(Value + money.Value); } public bool IsGreaterThan(Money money) { return this.Value > money.Value; } public bool IsGreaterThanOrEqualTo(Money money) { return this.Value > money.Value || this.Equals(money); } public bool IsLessThanOrEqualTo(Money money) { return this.Value < money.Value || this.Equals(money); } public override string ToString() { return string.Format("{0}", Value); } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel/Model/Price.cs ================================================ using System; using System.Collections.Generic; namespace PPPDDDChap05.DomainModel.Model { public class Price { private Price() { } public Price(Money amount) { if (amount == null) throw new ArgumentNullException("Amount cannot be null"); Amount = amount; } public Money Amount { get; private set; } public Money BidIncrement() { if (Amount.IsGreaterThanOrEqualTo(new Money(0.01m)) && Amount.IsLessThanOrEqualTo(new Money(0.99m))) return Amount.Add(new Money(0.05m)); if (Amount.IsGreaterThanOrEqualTo(new Money(1.00m)) && Amount.IsLessThanOrEqualTo(new Money(4.99m))) return Amount.Add(new Money(0.20m)); if (Amount.IsGreaterThanOrEqualTo(new Money(5.00m)) && Amount.IsLessThanOrEqualTo(new Money(14.99m))) return Amount.Add(new Money(0.50m)); return Amount.Add(new Money(1.00m)); } public bool CanBeExceededBy(Money offer) { return offer.IsGreaterThanOrEqualTo(BidIncrement()); } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel/Model/WinningBid.cs ================================================ using System; using System.Collections.Generic; using System.Linq; namespace PPPDDDChap05.DomainModel.Model { public class WinningBid { private WinningBid() { } public WinningBid(Guid bidder, Money maximumBid, Money bid, DateTime timeOfBid) { if (bidder == Guid.Empty) throw new ArgumentNullException("Bidder cannot be null"); if (maximumBid == null) throw new ArgumentNullException("MaximumBid cannot be null"); if (timeOfBid == DateTime.MinValue) throw new ArgumentNullException("TimeOfBid must have a value"); Bidder = bidder; MaximumBid = maximumBid; TimeOfBid = timeOfBid; CurrentAuctionPrice = new Price(bid); } public Guid AuctionId { get; private set; } public Guid Bidder { get; private set; } public Money MaximumBid { get; private set; } public DateTime TimeOfBid { get; private set; } public Price CurrentAuctionPrice { get; private set; } public WinningBid RaiseMaximumBidTo(Money newAmount) { if (newAmount.IsGreaterThan(MaximumBid)) return new WinningBid(Bidder, newAmount, CurrentAuctionPrice.Amount, DateTime.Now); else throw new ApplicationException("Maximum bid increase must be larger than current maximum bid."); } public bool WasMadeBy(Guid bidder) { return Bidder.Equals(bidder); } public WinningBid DetermineWinningBidIncrement(Bid newbid) { if (this.CanMeetOrExceedBidIncrement(this.MaximumBid) && this.CanMeetOrExceedBidIncrement(newbid.MaximumBid)) { return DetermineWinnerFromProxyBidding(this, newbid); } else if (this.CanMeetOrExceedBidIncrement(newbid.MaximumBid)) { return CreateNewBid(newbid.Bidder, CurrentAuctionPrice.BidIncrement(), newbid.MaximumBid, newbid.TimeOfOffer); } else return this; } private WinningBid DetermineWinnerFromProxyBidding(WinningBid winningBid, Bid newbid) { WinningBid nextIncrement; if (winningBid.MaxBidCanBeExceededBy(newbid.MaximumBid)) { nextIncrement = CreateNewBid(this.Bidder, this.MaximumBid, this.MaximumBid, this.TimeOfBid); if (nextIncrement.CanMeetOrExceedBidIncrement(newbid.MaximumBid)) return CreateNewBid(newbid.Bidder, nextIncrement.CurrentAuctionPrice.BidIncrement(), newbid.MaximumBid, newbid.TimeOfOffer); else return CreateNewBid(newbid.Bidder, newbid.MaximumBid, newbid.MaximumBid, newbid.TimeOfOffer); } else { nextIncrement = CreateNewBid(newbid.Bidder, newbid.MaximumBid, newbid.MaximumBid, newbid.TimeOfOffer); if (nextIncrement.CanMeetOrExceedBidIncrement(winningBid.MaximumBid)) return CreateNewBid(winningBid.Bidder, nextIncrement.CurrentAuctionPrice.BidIncrement(), winningBid.MaximumBid, winningBid.TimeOfBid); else return CreateNewBid(winningBid.Bidder, winningBid.MaximumBid, winningBid.MaximumBid, winningBid.TimeOfBid); } } private WinningBid CreateNewBid(Guid bidder, Money bid, Money maxBid, DateTime timeOfBid) { return new WinningBid(bidder, bid, maxBid, timeOfBid); } private bool MaxBidCanBeExceededBy(Money bid) { return !this.MaximumBid.IsGreaterThanOrEqualTo(bid); } public bool CanMeetOrExceedBidIncrement(Money offer) { return CurrentAuctionPrice.CanBeExceededBy(offer); } public bool HasNotReachedMaximumBid() { return MaximumBid.IsGreaterThan(CurrentAuctionPrice.Amount); } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel.csproj ================================================  Debug AnyCPU {0E353285-2A32-46DB-88E3-6832FDA9FF68} Library Properties PPPDDDChap05.DomainModel PPPDDDChap05.DomainModel v4.5 512 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("PPPDDDChap05.DomainModel")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PPPDDDChap05.DomainModel")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("1caf44dd-f726-4107-aa0a-c13fc290c560")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.DomainModel/PPPDDDChap05.DomainModel.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPPDDDChap05.DomainModel", "PPPDDDChap05.DomainModel\PPPDDDChap05.DomainModel.csproj", "{0E353285-2A32-46DB-88E3-6832FDA9FF68}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {0E353285-2A32-46DB-88E3-6832FDA9FF68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0E353285-2A32-46DB-88E3-6832FDA9FF68}.Debug|Any CPU.Build.0 = Debug|Any CPU {0E353285-2A32-46DB-88E3-6832FDA9FF68}.Release|Any CPU.ActiveCfg = Release|Any CPU {0E353285-2A32-46DB-88E3-6832FDA9FF68}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TableModule/PPPDDDChap05.TableModule/Domain/Customers.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDDChap05.TableModule.Domain { public class Customers { } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TableModule/PPPDDDChap05.TableModule/Domain/Orders.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data; namespace PPPDDDChap05.TableModule.Domain { public class Orders { public Orders(DataSet dataSet) { } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TableModule/PPPDDDChap05.TableModule/Domain/TableModuleBase.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDDChap05.TableModule.Domain { public class TableModuleBase { } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TableModule/PPPDDDChap05.TableModule/PPPDDDChap05.TableModule.csproj ================================================  Debug AnyCPU {F9520565-61E6-438C-9452-97F1F0C298D3} Library Properties PPPDDDChap05.TableModule PPPDDDChap05.TableModule v4.5 512 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TableModule/PPPDDDChap05.TableModule/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("PPPDDDChap05.TableModule")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PPPDDDChap05.TableModule")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("42d09094-56a4-47a1-aac8-3c51dfac2a62")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TableModule/PPPDDDChap05.TableModule.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPPDDDChap05.TableModule", "PPPDDDChap05.TableModule\PPPDDDChap05.TableModule.csproj", "{F9520565-61E6-438C-9452-97F1F0C298D3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {F9520565-61E6-438C-9452-97F1F0C298D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F9520565-61E6-438C-9452-97F1F0C298D3}.Debug|Any CPU.Build.0 = Debug|Any CPU {F9520565-61E6-438C-9452-97F1F0C298D3}.Release|Any CPU.ActiveCfg = Release|Any CPU {F9520565-61E6-438C-9452-97F1F0C298D3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TransactionScript/PPPDDDChap05.TransactionScript/Application/BidOnAuctionService.cs ================================================ using System; using PPPDDDChap05.TransactionScript.Domain; namespace PPPPDDDChap05.TransactionScript.Application { public class BidOnAuctionService { private BidOnAuctionCommand _bidOnAuctionCommand; public BidOnAuctionService(BidOnAuctionCommand bidOnAuctionCommand) { _bidOnAuctionCommand = bidOnAuctionCommand; } public void Bid(Guid auctionId, Guid memberId, decimal amount, DateTime dateOfBid) { _bidOnAuctionCommand.Execute(auctionId, memberId, amount, dateOfBid); } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TransactionScript/PPPDDDChap05.TransactionScript/Domain/Auction.cs ================================================ using System; namespace PPPDDDChap05.TransactionScript.Domain { public class Auction { public Guid Id { get; set; } public Guid ListingId { get; set; } public DateTime EndsAt { get; set; } public decimal StartingPrice { get; set; } public decimal WinningBid { get; set; } public decimal WinninBidderMaximumBid { get; set; } public Guid WinningBidder { get; set; } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TransactionScript/PPPDDDChap05.TransactionScript/Domain/BidOnAuction.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDDChap05.TransactionScript.Domain { public class BidOnAuction: ICommand { public void Execute() { throw new NotImplementedException(); } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TransactionScript/PPPDDDChap05.TransactionScript/Domain/BidOnAuctionCommand.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Transactions; namespace PPPDDDChap05.TransactionScript.Domain { public class BidOnAuctionCommand: ICommand { private Guid auctionId {get; set;} private Guid bidderId {get; set;} private decimal amount {get; set;} private DateTime timeOfBid { get; set; } public BidOnAuctionCommand(Guid auctionId, Guid bidderId, decimal amount, DateTime timeOfBid) { this.auctionId = auctionId; this.bidderId = bidderId; this.amount = amount; this.timeOfBid = timeOfBid; } public void Execute() { using (TransactionScope scope = new TransactionScope()) { ThrowExceptionIfNotValid(auctionId, bidderId, amount, timeOfBid); ThrowExceptionIfAuctionHasEnded(auctionId); if (IsFirstBid(auctionId)) PlaceFirstBid(auctionId, bidderId, amount, timeOfBid); else if (IsIncreasingMaximimBid(auctionId, amount, bidderId)) IncreaseMaximumBidTo(amount); else if (CanMeetOrExceedBidIncrement(amount)) UpdatePrice(auctionId, bidderId, amount, timeOfBid); } } private void ThrowExceptionIfAuctionHasEnded(Guid auctionId) { // check at DB } private bool CanMeetOrExceedBidIncrement(decimal amount) { return true; } private void UpdatePrice(Guid auctionId, Guid bidderId, decimal amount, DateTime timeOfBi) { } private void IncreaseMaximumBidTo(decimal amount) { } private bool IsIncreasingMaximimBid(Guid auctionId, decimal amount, Guid bidderId) { return true; } private bool IsFirstBid(Guid auctionId) { return true; } private void PlaceFirstBid(Guid auctionId, Guid bidderId, decimal amount, DateTime timeOfBid) { } private void FirstBid(Auction auction, Guid bidderId, decimal amount, DateTime dateOfBid) { if (amount > auction.StartingPrice) { auction.WinningBidder = bidderId; auction.WinningBid = amount; // DB Update } else throw new ApplicationException("You have to bid greater than the starting price."); } private void ThrowExceptionIfNotValid(Guid auctionId, Guid bidderId, decimal amount, DateTime dateOfBid) { if (auctionId == Guid.Empty) throw new ArgumentNullException("AuctionId cannot be null"); if (bidderId == Guid.Empty) throw new ArgumentNullException("BidderId cannot be null"); if (dateOfBid == DateTime.MinValue) throw new ArgumentNullException("Time of bid must have a value"); if (amount % 0.01m != 0) throw new InvalidOperationException("There cannot be more than two decimal places."); if (amount < 0) throw new InvalidOperationException("Money cannot be a negative value."); } private decimal BidIncrement(decimal currentAuctionWinningBid) { if (currentAuctionWinningBid >= 0.01m && currentAuctionWinningBid <= 0.99m) return 0.05m; if (currentAuctionWinningBid >= 1.00m && currentAuctionWinningBid <= 4.99m) return 0.20m; if (currentAuctionWinningBid >= 5.00m && currentAuctionWinningBid >= 14.99m) return 0.50m; return 1.00m; } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TransactionScript/PPPDDDChap05.TransactionScript/Domain/ClassDiagram1.cd ================================================  AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA= Domain\CreateAuction.cs AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA= Domain\BidOnAuction.cs AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA= Domain\ICommand.cs ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TransactionScript/PPPDDDChap05.TransactionScript/Domain/CreateAuction.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDDChap05.TransactionScript.Domain { public class CreateAuction : ICommand { public void Execute() { throw new NotImplementedException(); } } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TransactionScript/PPPDDDChap05.TransactionScript/Domain/ICommand.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDDChap05.TransactionScript.Domain { public interface ICommand { public void Execute(); } } ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TransactionScript/PPPDDDChap05.TransactionScript/PPPDDDChap05.TransactionScript.csproj ================================================  Debug AnyCPU {32A69A1D-17FD-4F51-981B-81298242440F} Library Properties PPPDDDChap05.TransactionScript PPPDDDChap05.TransactionScript v4.5 512 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TransactionScript/PPPDDDChap05.TransactionScript/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("PPPDDDChap05.TransactionScript")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PPPDDDChap05.TransactionScript")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("973aaa8a-6c99-41e2-a811-0db1308fa968")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 05 - Domain Model Implementation Patterns/PPPDDDChap05.TransactionScript/PPPDDDChap05.TransactionScript.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPPDDDChap05.TransactionScript", "PPPDDDChap05.TransactionScript\PPPDDDChap05.TransactionScript.csproj", "{32A69A1D-17FD-4F51-981B-81298242440F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {32A69A1D-17FD-4F51-981B-81298242440F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {32A69A1D-17FD-4F51-981B-81298242440F}.Debug|Any CPU.Build.0 = Debug|Any CPU {32A69A1D-17FD-4F51-981B-81298242440F}.Release|Any CPU.ActiveCfg = Release|Any CPU {32A69A1D-17FD-4F51-981B-81298242440F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ExplicitLogic/Model/BasketItem.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ExplicitLogic.Model { public class BasketItem { public Quantity quantity() { throw new NotImplementedException(); } internal void increase_item_quantity_by(Quantity quantity) { throw new NotImplementedException(); } } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ExplicitLogic/Model/BasketItemFactory.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ExplicitLogic.Model { public class BasketItemFactory { internal static BasketItem create_item_for(Product product, basket basket) { throw new NotImplementedException(); } } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ExplicitLogic/Model/BasketItems.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ExplicitLogic.Model { public class BasketItems : List { } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ExplicitLogic/Model/Country.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace PPPDDD.Chap10.ecommerce.ExplicitLogic.Model { public class Country { } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ExplicitLogic/Model/OverSeasSellingPolicyException.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace PPPDDD.Chap10.ecommerce.ExplicitLogic.Model { class OverSeasSellingPolicyException : Exception { public OverSeasSellingPolicyException(string message) { } } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ExplicitLogic/Model/OverseasSellingPolicy.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ExplicitLogic.Model { public class OverSeasSellingPolicy { public static Quantity quantity_threshold = new Quantity(50); public bool is_satisfied_by(Quantity item_quantity, Country country) { if (item_quantity.contains_more_than(quantity_threshold)) return false; else return true; } internal bool is_satisfied_by(Quantity item_quantity) { throw new NotImplementedException(); } } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ExplicitLogic/Model/Product.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ExplicitLogic.Model { public class Product { } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ExplicitLogic/Model/Quantity.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ExplicitLogic.Model { public class Quantity { public Quantity(int p) { } public Quantity add(Quantity quantity) { throw new NotImplementedException(); } internal bool contains_more_than(Quantity quantity_threshold) { throw new NotImplementedException(); } } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ExplicitLogic/Model/basket.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ExplicitLogic.Model { // This example, including associated classes, accentuates making logic explicit. // It does not demonstrate coding and DDD best practices public class basket { private BasketItems _items; private OverSeasSellingPolicy _over_seas_selling_policy; public void add(Product product) { if (basket_contains_an_item_for(product)) { var item_quantity = get_item_for(product).quantity().add(new Quantity(1)); if (_over_seas_selling_policy.is_satisfied_by(item_quantity)) get_item_for(product).increase_item_quantity_by(new Quantity(1)); else throw new OverSeasSellingPolicyException( string.Format( "You can only purchase {0} of a single product.", OverSeasSellingPolicy.quantity_threshold) ); } else _items.Add(BasketItemFactory.create_item_for(product, this)); } private BasketItem get_item_for(Product product) { throw new NotImplementedException(); } private bool basket_contains_an_item_for(Product product) { throw new NotImplementedException(); } } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ImplicitLogic/Model/BasketItem.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ImplicitLogic.Model { public class BasketItem { public Quantity quantity() { throw new NotImplementedException(); } internal void increase_item_quantity_by(Quantity quantity) { throw new NotImplementedException(); } } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ImplicitLogic/Model/BasketItemFactory.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ImplicitLogic.Model { public class BasketItemFactory { internal static BasketItem create_item_for(Product product, basket basket) { throw new NotImplementedException(); } } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ImplicitLogic/Model/BasketItems.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ImplicitLogic.Model { public class BasketItems : List { } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ImplicitLogic/Model/Product.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ImplicitLogic.Model { public class Product { } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ImplicitLogic/Model/Quantity.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ImplicitLogic.Model { public class Quantity { public Quantity(int p) { } public Quantity add(Quantity quantity) { throw new NotImplementedException(); } internal bool contains_more_than(Quantity quantity_threshold) { throw new NotImplementedException(); } } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/ImplicitLogic/Model/basket.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace PPPDDD.Chap10.ecommerce.ImplicitLogic.Model { // This example, including associated classes, demonstrates the problems of not making concepts explicit. // It does not demonstrate coding and DDD best practices public class basket { private BasketItems _items; public void add(Product product) { if (basket_contains_an_item_for(product)) { var item_quantity = get_item_for(product).quantity() .add(new Quantity(1)); if (item_quantity.contains_more_than(new Quantity(50))) throw new ApplicationException( "You can only purchase 50 of a single product."); else get_item_for(product).increase_item_quantity_by( new Quantity(1)); } else _items.Add(BasketItemFactory.create_item_for(product, this)); } private BasketItem get_item_for(Product product) { throw new NotImplementedException(); } private bool basket_contains_an_item_for(Product product) { throw new NotImplementedException(); } } } ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce.csproj ================================================  Debug AnyCPU {4DFA816B-6069-4B9E-B7F2-F13B498EAD9F} Library Properties PPPDDD.Chap10.ecommerce PPPDDD.Chap10.ecommerce v4.5 512 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("PPPDDD.Chap10.ecommerce")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PPPDDD.Chap10.ecommerce")] [assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("4f3f7625-a00b-47a3-8154-ef201dd2d522")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 10 - Applying the Principles, Practices and Patterns of DDD/PPPDDD.Chap10.ecommerce/PPPDDD.Chap10.ecommerce.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Express 2013 for Web VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPPDDD.Chap10.ecommerce", "PPPDDD.Chap10.ecommerce\PPPDDD.Chap10.ecommerce.csproj", "{4DFA816B-6069-4B9E-B7F2-F13B498EAD9F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {4DFA816B-6069-4B9E-B7F2-F13B498EAD9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4DFA816B-6069-4B9E-B7F2-F13B498EAD9F}.Debug|Any CPU.Build.0 = Debug|Any CPU {4DFA816B-6069-4B9E-B7F2-F13B498EAD9F}.Release|Any CPU.ActiveCfg = Release|Any CPU {4DFA816B-6069-4B9E-B7F2-F13B498EAD9F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: 11 - Integrating Bounded Contexts/README.md ================================================ PPPDDD ====== There is no sample code for chapter 11. This chapter contains theory and case-studies of integrating bounded contexts and team in distributed domain driven design (DDDD) environments. ================================================ FILE: 12 - Integrating Via Messaging/Billing.Messages/Billing.Messages.csproj ================================================  Debug AnyCPU {B3707164-FF36-473E-877D-A652C8E41D14} Library Properties Billing.Messages Billing.Messages v4.5 512 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ================================================ FILE: 12 - Integrating Via Messaging/Billing.Messages/Commands/RecordPaymentAttempt.cs ================================================ using System; namespace Billing.Messages.Commands { public class RecordPaymentAttempt { public string OrderId { get; set; } public PaymentStatus Status { get; set; } } public enum PaymentStatus { Accepted, Rejected } } ================================================ FILE: 12 - Integrating Via Messaging/Billing.Messages/Events/PaymentAccepted.cs ================================================ using System; namespace Billing.Messages.Events { public class PaymentAccepted { public string OrderId { get; set; } } } ================================================ FILE: 12 - Integrating Via Messaging/Billing.Messages/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Billing.Messages")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Billing.Messages")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("e54fb802-aa29-4e02-8893-7c5e515a12ba")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 12 - Integrating Via Messaging/Billing.Payments.PaymentAccepted/App.config ================================================ 
================================================ FILE: 12 - Integrating Via Messaging/Billing.Payments.PaymentAccepted/Billing.Payments.PaymentAccepted.csproj ================================================  Debug AnyCPU {D8BE42BB-5FD0-4DB2-919B-9FCB8D455F63} Library Properties Billing.Payments.PaymentAccepted Billing.Payments.PaymentAccepted v4.5 512 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ..\packages\NServiceBus.Interfaces.4.3.4\lib\net40\NServiceBus.dll ..\packages\NServiceBus.4.3.4\lib\net40\NServiceBus.Core.dll ..\packages\NServiceBus.Host.4.3.3\lib\net40\NServiceBus.Host.exe {b3707164-ff36-473e-877d-a652c8e41d14} Billing.Messages {2dd347e9-1417-4ac5-9bdc-84dbe0707427} Sales.Messages Program $(ProjectDir)$(OutputPath)NServiceBus.Host.exe ================================================ FILE: 12 - Integrating Via Messaging/Billing.Payments.PaymentAccepted/EndpointConfig.cs ================================================ using NServiceBus; namespace Billing.Payments.PaymentAccepted { public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization, AsA_Publisher { public void Init() { Configure.With() .DefiningCommandsAs(t => t.Namespace != null && t.Namespace.Contains("Commands")) .DefiningEventsAs(t => t.Namespace != null && t.Namespace.Contains("Events")); } } } ================================================ FILE: 12 - Integrating Via Messaging/Billing.Payments.PaymentAccepted/OrderCreatedHandler.cs ================================================ using Billing.Messages.Commands; using NServiceBus; using Sales.Messages.Events; using System; namespace Billing.Payments.PaymentAccepted { public class OrderCreatedHandler : IHandleMessages { // dependency injected by NServiceBus public IBus Bus { get; set; } public void Handle(OrderCreated message) { Console.WriteLine("Received order created event: OrderId: {0}", message.OrderId); var cardDetails = Database.GetCardDetailsFor(message.UserId); var confirmation = PaymentProvider.ChargeCreditCard(cardDetails, message.Amount); var command = new RecordPaymentAttempt { OrderId = message.OrderId, Status = confirmation.Status }; Bus.SendLocal(command); } } public static class PaymentProvider { private static int Attempts = 0; public static PaymentConfirmation ChargeCreditCard(CardDetails details, double amount) { if (Attempts < 2) { Attempts++; throw new Exception("Service unavailable. Down for maintenance."); } return new PaymentConfirmation { Status = PaymentStatus.Accepted }; } } public class PaymentConfirmation { public PaymentStatus Status { get; set; } } public static class Database { public static CardDetails GetCardDetailsFor(string userId) { return new CardDetails(); } } public class CardDetails { // ... } } ================================================ FILE: 12 - Integrating Via Messaging/Billing.Payments.PaymentAccepted/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Billing.Payments.PaymentAccepted")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Billing.Payments.PaymentAccepted")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("7c14fade-565f-44ad-9e88-035ea990ed1d")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 12 - Integrating Via Messaging/Billing.Payments.PaymentAccepted/RecordPaymentAttemptHandler.cs ================================================ using System; using Billing.Messages.Commands; using NServiceBus; namespace Billing.Payments.PaymentAccepted { public class RecordPaymentAttemptHandler : IHandleMessages { // dependency injected by NServiceBus public IBus Bus { get; set; } public void Handle(RecordPaymentAttempt message) { Database.SavePaymentAttempt(message.OrderId, message.Status); if (message.Status == PaymentStatus.Accepted) { var evnt = new Billing.Messages.Events.PaymentAccepted { OrderId = message.OrderId }; Bus.Publish(evnt); Console.WriteLine( "Recevied payment accepted notification for Order: {0}. Published PaymentAccepted event", message.OrderId ); } else { // publish a payment rejected event } } public static class Database { public static void SavePaymentAttempt(string orderId, PaymentStatus status) { // .. save it to your favorite database } } } } ================================================ FILE: 12 - Integrating Via Messaging/Billing.Payments.PaymentAccepted/packages.config ================================================  ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/App_Start/FilterConfig.cs ================================================ using System.Web; using System.Web.Mvc; namespace DDDesign.Web { public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); } } } ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/App_Start/RouteConfig.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace DDDesign.Web { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } } ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/App_Start/WebApiConfig.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web.Http; namespace DDDesign.Web { public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } } } ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/Controllers/OrdersController.cs ================================================ using Sales.Messages.Commands; using System; using System.Linq; using System.Web; using System.Web.Mvc; namespace DDDesign.Web.Controllers { public class OrdersController : Controller { [HttpGet] public ActionResult Index() { return View(); } [HttpPost] public ActionResult Place(string userId, string productIds, string shippingTypeId) { var realProductIds = productIds.Split(','); var placeOrderCommand = new PlaceOrder { UserId = userId, ProductIds = realProductIds, ShippingTypeId = shippingTypeId, TimeStamp = DateTime.Now }; MvcApplication.Bus.Send("Sales.Orders.OrderCreated", placeOrderCommand); return Content("Your order has been placed. You will receive email confirmation shortly."); } } } ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/DDDesign.Web.csproj ================================================  Debug AnyCPU 2.0 {577647AD-2F18-4590-B28F-D46F9351E0E0} {E3E379DF-F4C6-4180-9B81-6769533ABE47};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} Library Properties DDDesign.Web DDDesign.Web v4.5 false true true full false bin\ DEBUG;TRACE prompt 4 pdbonly true bin\ TRACE prompt 4 ..\packages\NServiceBus.Interfaces.4.3.4\lib\net40\NServiceBus.dll ..\packages\NServiceBus.4.3.3\lib\net40\NServiceBus.Core.dll True ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll True ..\packages\Microsoft.AspNet.Mvc.FixedDisplayModes.1.0.0\lib\net40\Microsoft.Web.Mvc.FixedDisplayModes.dll ..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll ..\packages\Microsoft.AspNet.WebApi.Client.4.0.30506.0\lib\net40\System.Net.Http.Formatting.dll True ..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.Helpers.dll ..\packages\Microsoft.AspNet.WebApi.Core.4.0.30506.0\lib\net40\System.Web.Http.dll ..\packages\Microsoft.AspNet.WebApi.WebHost.4.0.30506.0\lib\net40\System.Web.Http.WebHost.dll True ..\packages\Microsoft.AspNet.Mvc.4.0.30506.0\lib\net40\System.Web.Mvc.dll True ..\packages\Microsoft.AspNet.Razor.2.0.30506.0\lib\net40\System.Web.Razor.dll True ..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.dll True ..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Deployment.dll True ..\packages\Microsoft.AspNet.WebPages.2.0.30506.0\lib\net40\System.Web.WebPages.Razor.dll Global.asax Web.config Web.config {2dd347e9-1417-4ac5-9bdc-84dbe0707427} Sales.Messages 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) True True 2066 / http://localhost:2066/ False False False ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/Global.asax ================================================ <%@ Application Codebehind="Global.asax.cs" Inherits="DDDesign.Web.MvcApplication" Language="C#" %> ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/Global.asax.cs ================================================ using System.Web.Http; using System.Web.Mvc; using System.Web.Routing; using NServiceBus; using NServiceBus.Installation.Environments; namespace DDDesign.Web { public class MvcApplication : System.Web.HttpApplication { private static IBus bus; public static IBus Bus { get { return bus; } } protected void Application_Start() { Configure.Serialization.Xml(); bus = Configure.With() .DefaultBuilder() .DefiningCommandsAs(t => t.Namespace != null && t.Namespace.Contains("Commands")) .UseTransport() .UnicastBus() .SendOnly(); // following code was provided by default and should remain un-modified AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); } } } ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("DDDesign.Web")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("DDDesign.Web")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("e000afce-ae81-469c-b2fb-21cb969ea18e")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/Views/Orders/Index.cshtml ================================================  Place an order

Place an order

UserId:

ProductIds:

ShippingTypeId:

================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/Views/Web.config ================================================ 
================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/Web.Debug.config ================================================  ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/Web.Release.config ================================================  ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/Web.config ================================================  ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.Web/packages.config ================================================  ================================================ FILE: 12 - Integrating Via Messaging/DDDesign.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Messages", "Sales.Messages\Sales.Messages.csproj", "{2DD347E9-1417-4AC5-9BDC-84DBE0707427}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DDDesign.Web", "DDDesign.Web\DDDesign.Web.csproj", "{577647AD-2F18-4590-B28F-D46F9351E0E0}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sales.Orders.OrderCreated", "Sales.Orders.OrderCreated\Sales.Orders.OrderCreated.csproj", "{18455B18-D42C-4B5A-98E0-2112F8066542}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Payments.PaymentAccepted", "Billing.Payments.PaymentAccepted\Billing.Payments.PaymentAccepted.csproj", "{D8BE42BB-5FD0-4DB2-919B-9FCB8D455F63}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.Messages", "Billing.Messages\Billing.Messages.csproj", "{B3707164-FF36-473E-877D-A652C8E41D14}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.BusinessCustomers.ShippingArranged", "Shipping.BusinessCustomers.ShippingArranged\Shipping.BusinessCustomers.ShippingArranged.csproj", "{2A146AA7-EF86-4304-839C-C43B97834F15}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shipping.Messages", "Shipping.Messages\Shipping.Messages.csproj", "{AB3A64C2-9FD1-4382-AAB8-10748573DE98}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Promotions.LuckyWinner.LuckyWinnerSelected", "Promotions.LuckyWinner.LuckyWinnerSelected\Promotions.LuckyWinner.LuckyWinnerSelected.csproj", "{150B3671-0358-4A92-B1B1-040E1E8A4E75}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Promotions.LuckyWinner.LuckyWinnerSelected.Bridge", "Promotions.LuckyWinner.LuckyWinnerSelected.Bridge\Promotions.LuckyWinner.LuckyWinnerSelected.Bridge.csproj", "{7E833DCC-577E-4601-83DD-E6B71F1B9D77}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Billing Context", "Billing Context", "{3127DD92-DAB4-481E-8A8B-37C22A6D6780}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Promotions Context", "Promotions Context", "{E9D889AA-241E-4DFA-B81D-43449F1DBE76}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sales Context", "Sales Context", "{AE53C794-2020-4930-A9A9-4F97EDAD9686}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shipping Context", "Shipping Context", "{079CBA19-BF9F-437B-83DE-47984F187549}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2DD347E9-1417-4AC5-9BDC-84DBE0707427}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2DD347E9-1417-4AC5-9BDC-84DBE0707427}.Debug|Any CPU.Build.0 = Debug|Any CPU {2DD347E9-1417-4AC5-9BDC-84DBE0707427}.Release|Any CPU.ActiveCfg = Release|Any CPU {2DD347E9-1417-4AC5-9BDC-84DBE0707427}.Release|Any CPU.Build.0 = Release|Any CPU {577647AD-2F18-4590-B28F-D46F9351E0E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {577647AD-2F18-4590-B28F-D46F9351E0E0}.Debug|Any CPU.Build.0 = Debug|Any CPU {577647AD-2F18-4590-B28F-D46F9351E0E0}.Release|Any CPU.ActiveCfg = Release|Any CPU {577647AD-2F18-4590-B28F-D46F9351E0E0}.Release|Any CPU.Build.0 = Release|Any CPU {18455B18-D42C-4B5A-98E0-2112F8066542}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {18455B18-D42C-4B5A-98E0-2112F8066542}.Debug|Any CPU.Build.0 = Debug|Any CPU {18455B18-D42C-4B5A-98E0-2112F8066542}.Release|Any CPU.ActiveCfg = Release|Any CPU {18455B18-D42C-4B5A-98E0-2112F8066542}.Release|Any CPU.Build.0 = Release|Any CPU {D8BE42BB-5FD0-4DB2-919B-9FCB8D455F63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D8BE42BB-5FD0-4DB2-919B-9FCB8D455F63}.Debug|Any CPU.Build.0 = Debug|Any CPU {D8BE42BB-5FD0-4DB2-919B-9FCB8D455F63}.Release|Any CPU.ActiveCfg = Release|Any CPU {D8BE42BB-5FD0-4DB2-919B-9FCB8D455F63}.Release|Any CPU.Build.0 = Release|Any CPU {B3707164-FF36-473E-877D-A652C8E41D14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B3707164-FF36-473E-877D-A652C8E41D14}.Debug|Any CPU.Build.0 = Debug|Any CPU {B3707164-FF36-473E-877D-A652C8E41D14}.Release|Any CPU.ActiveCfg = Release|Any CPU {B3707164-FF36-473E-877D-A652C8E41D14}.Release|Any CPU.Build.0 = Release|Any CPU {2A146AA7-EF86-4304-839C-C43B97834F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A146AA7-EF86-4304-839C-C43B97834F15}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A146AA7-EF86-4304-839C-C43B97834F15}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A146AA7-EF86-4304-839C-C43B97834F15}.Release|Any CPU.Build.0 = Release|Any CPU {AB3A64C2-9FD1-4382-AAB8-10748573DE98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AB3A64C2-9FD1-4382-AAB8-10748573DE98}.Debug|Any CPU.Build.0 = Debug|Any CPU {AB3A64C2-9FD1-4382-AAB8-10748573DE98}.Release|Any CPU.ActiveCfg = Release|Any CPU {AB3A64C2-9FD1-4382-AAB8-10748573DE98}.Release|Any CPU.Build.0 = Release|Any CPU {150B3671-0358-4A92-B1B1-040E1E8A4E75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {150B3671-0358-4A92-B1B1-040E1E8A4E75}.Debug|Any CPU.Build.0 = Debug|Any CPU {150B3671-0358-4A92-B1B1-040E1E8A4E75}.Release|Any CPU.ActiveCfg = Release|Any CPU {150B3671-0358-4A92-B1B1-040E1E8A4E75}.Release|Any CPU.Build.0 = Release|Any CPU {7E833DCC-577E-4601-83DD-E6B71F1B9D77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7E833DCC-577E-4601-83DD-E6B71F1B9D77}.Debug|Any CPU.Build.0 = Debug|Any CPU {7E833DCC-577E-4601-83DD-E6B71F1B9D77}.Release|Any CPU.ActiveCfg = Release|Any CPU {7E833DCC-577E-4601-83DD-E6B71F1B9D77}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {B3707164-FF36-473E-877D-A652C8E41D14} = {3127DD92-DAB4-481E-8A8B-37C22A6D6780} {D8BE42BB-5FD0-4DB2-919B-9FCB8D455F63} = {3127DD92-DAB4-481E-8A8B-37C22A6D6780} {150B3671-0358-4A92-B1B1-040E1E8A4E75} = {E9D889AA-241E-4DFA-B81D-43449F1DBE76} {7E833DCC-577E-4601-83DD-E6B71F1B9D77} = {E9D889AA-241E-4DFA-B81D-43449F1DBE76} {18455B18-D42C-4B5A-98E0-2112F8066542} = {AE53C794-2020-4930-A9A9-4F97EDAD9686} {2DD347E9-1417-4AC5-9BDC-84DBE0707427} = {AE53C794-2020-4930-A9A9-4F97EDAD9686} {2A146AA7-EF86-4304-839C-C43B97834F15} = {079CBA19-BF9F-437B-83DE-47984F187549} {AB3A64C2-9FD1-4382-AAB8-10748573DE98} = {079CBA19-BF9F-437B-83DE-47984F187549} EndGlobalSection EndGlobal ================================================ FILE: 12 - Integrating Via Messaging/Promotions.LuckyWinner.LuckyWinnerSelected/App.config ================================================  ================================================ FILE: 12 - Integrating Via Messaging/Promotions.LuckyWinner.LuckyWinnerSelected/Application/Program.cs ================================================ using MassTransit; using System; using System.Linq; using System.Collections.Generic; using System.Threading; using System.IO; using MassTransit.Context; using System.Text; namespace Promotions.LuckyWinner.LuckyWinnerSelected { public class Program { public static void Main(string[] args) { Bus.Initialize(config => { config.UseMsmq(); // look on this queue for order placed event messages config.ReceiveFrom("msmq://localhost/promotions.ordercreated"); // subscribe to order placed events config.Subscribe(sub => { // handle order placed events like this sub.Handler(msg => new OrderCreatedHandler().Handle(msg)); }); }); // keep the application running so it can listen for messages while(true) { Thread.Sleep(1000); } } } public class OrderCreated { public string OrderId { get; set; } public string UserId { get; set; } public List ProductIds { get; set; } public string ShippingTypeId { get; set; } public DateTime TimeStamp { get; set; } public double Amount { get; set; } } public class OrderCreatedHandler { public void Handle(OrderCreated message) { Console.WriteLine( "Mass Transit handling order placed event: Order: {0} for User: {1}", message.OrderId, message.UserId); } } } ================================================ FILE: 12 - Integrating Via Messaging/Promotions.LuckyWinner.LuckyWinnerSelected/Promotions.LuckyWinner.LuckyWinnerSelected.csproj ================================================  Debug AnyCPU {150B3671-0358-4A92-B1B1-040E1E8A4E75} Exe Properties Promotions.LuckyWinner.LuckyWinnerSelected Promotions.LuckyWinner.LuckyWinnerSelected v4.5 512 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ..\packages\Magnum.2.1.2\lib\NET40\Magnum.dll ..\packages\MassTransit.2.9.5\lib\net40\MassTransit.dll ..\packages\MassTransit.MSMQ.2.9.5\lib\net40\MassTransit.Transports.MSMQ.dll ..\packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll ================================================ FILE: 12 - Integrating Via Messaging/Promotions.LuckyWinner.LuckyWinnerSelected/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Promotions.LuckyWinner.LuckyWinnerSelected")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Promotions.LuckyWinner.LuckyWinnerSelected")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("dee36a48-7037-40ce-bc76-e357ca417751")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 12 - Integrating Via Messaging/Promotions.LuckyWinner.LuckyWinnerSelected/packages.config ================================================  ================================================ FILE: 12 - Integrating Via Messaging/Promotions.LuckyWinner.LuckyWinnerSelected.Bridge/App.config ================================================ 
================================================ FILE: 12 - Integrating Via Messaging/Promotions.LuckyWinner.LuckyWinnerSelected.Bridge/Application/OrderCreatedHandler.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using NServiceBus; using System.Messaging; using Sales.Messages.Events; using System.Xml.Linq; using System.Xml; namespace Promotions.LuckyWinner.LuckyWinnerSelected.Bridge { public class OrderCreatedHandler : IHandleMessages { public void Handle(OrderCreated_V2 message) { Console.WriteLine( "Bridge received order: {0}. " + "About to push it onto Mass Transit's queue", message.OrderId ); var massMsg = ConvertToMassTransitXmlMessageFormat(message); var msmqMsg = new Message { Body = XDocument.Parse(massMsg).Root, Extension = Encoding.UTF8.GetBytes("{\"Content-Type\":\"application/vnd.masstransit+xml\"}") }; var queue = new MessageQueue(".\\Private$\\promotions.ordercreated", QueueAccessMode.Send); queue.Send(msmqMsg); } // use a more robust strategy in production // this approach is used to highligh format mass transit needs private string ConvertToMassTransitXmlMessageFormat(OrderCreated_V2 message) { return "" + "" + "" + "msmq://localhost/promotions.ordercreated?tx=false&recoverable=true" + "" + "" + message.OrderId + "" + "" + message.UserId + "" + GenerateProductIdsXml(message.ProductIds) + "" + message.ShippingTypeId + "" + "" + message.Amount + "" + "" + XmlConvert.ToString(message.TimeStamp, XmlDateTimeSerializationMode.Utc) + "" + "" + "urn:message:Promotions.LuckyWinner.LuckyWinnerSelected:OrderCreated" + ""; } private string GenerateProductIdsXml(IEnumerable productIds) { return String.Join("", productIds.Select(p => "" + p + "")); } } } ================================================ FILE: 12 - Integrating Via Messaging/Promotions.LuckyWinner.LuckyWinnerSelected.Bridge/Infrastructure/EndpointConfig.cs ================================================ namespace Promotions.LuckyWinner.LuckyWinnerSelected.Bridge { using NServiceBus; public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization, AsA_Publisher { public void Init() { Configure.With() .DefiningCommandsAs(t => t.Namespace != null && t.Namespace.Contains("Commands")) .DefiningEventsAs(t => t.Namespace != null && t.Namespace.Contains("Events")); } } } ================================================ FILE: 12 - Integrating Via Messaging/Promotions.LuckyWinner.LuckyWinnerSelected.Bridge/Promotions.LuckyWinner.LuckyWinnerSelected.Bridge.csproj ================================================  Debug AnyCPU {7E833DCC-577E-4601-83DD-E6B71F1B9D77} Library Properties Promotions.LuckyWinner.LuckyWinnerSelected.Bridge Promotions.LuckyWinner.LuckyWinnerSelected.Bridge v4.5 512 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ..\packages\NServiceBus.Interfaces.4.3.4\lib\net40\NServiceBus.dll ..\packages\NServiceBus.4.3.4\lib\net40\NServiceBus.Core.dll ..\packages\NServiceBus.Host.4.3.3\lib\net40\NServiceBus.Host.exe {2dd347e9-1417-4ac5-9bdc-84dbe0707427} Sales.Messages Program $(ProjectDir)$(OutputPath)NServiceBus.Host.exe ================================================ FILE: 12 - Integrating Via Messaging/Promotions.LuckyWinner.LuckyWinnerSelected.Bridge/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Promotions.LuckyWinner.LuckyWinnerSelected.Bridge")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Promotions.LuckyWinner.LuckyWinnerSelected.Bridge")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("0c882311-bbaa-4ae0-9db2-b62c8ebbd5f6")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 12 - Integrating Via Messaging/Promotions.LuckyWinner.LuckyWinnerSelected.Bridge/packages.config ================================================  ================================================ FILE: 12 - Integrating Via Messaging/README.md ================================================ PPPDDD ====== See chapter 12 in the book for guidance on setting up and running this project, including NServiceBus and MSMQ installation instructions. ================================================ FILE: 12 - Integrating Via Messaging/Sales.Messages/Commands/PlaceOrder.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Sales.Messages.Commands { public class PlaceOrder { public string UserId { get; set; } public string[] ProductIds { get; set; } public string ShippingTypeId { get; set;} public DateTime TimeStamp { get; set; } } } ================================================ FILE: 12 - Integrating Via Messaging/Sales.Messages/Events/OrderCreated.cs ================================================ using System; using System.Collections.Generic; namespace Sales.Messages.Events { public class OrderCreated { public string OrderId { get; set; } public string UserId { get; set; } public string[] ProductIds { get; set; } public string ShippingTypeId { get; set; } public DateTime TimeStamp { get; set; } public double Amount { get; set; } } } ================================================ FILE: 12 - Integrating Via Messaging/Sales.Messages/Events/OrderCreated_V2.cs ================================================ using System; namespace Sales.Messages.Events { public class OrderCreated_V2 : OrderCreated { public string AddressId { get; set; } } } ================================================ FILE: 12 - Integrating Via Messaging/Sales.Messages/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Sales.Messages")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Sales.Messages")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("80347f4c-c890-4436-a066-0bdeaeb2cb86")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 12 - Integrating Via Messaging/Sales.Messages/Sales.Messages.csproj ================================================  Debug AnyCPU {2DD347E9-1417-4AC5-9BDC-84DBE0707427} Library Properties Sales.Messages Sales.Messages v4.5 512 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ================================================ FILE: 12 - Integrating Via Messaging/Sales.Orders.OrderCreated/App.config ================================================ 
================================================ FILE: 12 - Integrating Via Messaging/Sales.Orders.OrderCreated/Application/PlaceOrderHandler.cs ================================================ using System; using NServiceBus; using Sales.Messages.Commands; using System.Collections.Generic; namespace Sales.Orders.OrderCreated { public class PlaceOrderHandler : IHandleMessages { public IBus Bus { get; set; } public void Handle(PlaceOrder message) { var orderId = Database.SaveOrder(message.ProductIds, message.UserId, message.ShippingTypeId); Console.WriteLine( @"Created order #{3} : Products:{0} with shipping: {1} made by user: {2}", String.Join(",", message.ProductIds), message.ShippingTypeId, message.UserId, orderId ); // sending a V2 message now var orderCreatedEvent = new Sales.Messages.Events.OrderCreated_V2 { OrderId = orderId, UserId = message.UserId, ProductIds = message.ProductIds, ShippingTypeId = message.ShippingTypeId, TimeStamp = DateTime.Now, Amount = CalculateCostOf(message.ProductIds), /* * add a new field to the form and the PlaceOrder command * if you don't want to hard-code the value */ AddressId = "AddressID123" }; Bus.Publish(orderCreatedEvent); } private double CalculateCostOf(IEnumerable productIds) { // database lookup, etc return 1000.00; } } // This could be any database technology. It can differ between Business Components public static class Database { private static int Id = 0; public static string SaveOrder(IEnumerable productIds, string userId, string shippingTypeId) { var nextOrderId = Id++; return nextOrderId.ToString(); } } } ================================================ FILE: 12 - Integrating Via Messaging/Sales.Orders.OrderCreated/Infrastructure/EndpointConfig.cs ================================================ using NServiceBus; namespace Sales.Orders.OrderCreated { public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization, AsA_Publisher { public void Init() { Configure.With() .DefiningCommandsAs(t => t.Namespace != null && t.Namespace.Contains("Commands")) .DefiningEventsAs(t => t.Namespace != null && t.Namespace.Contains("Events")); } } } ================================================ FILE: 12 - Integrating Via Messaging/Sales.Orders.OrderCreated/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Sales.Orders.OrderCreated")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Sales.Orders.OrderCreated")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("f6917b3a-ce8f-4d92-9738-c44d79fc0072")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 12 - Integrating Via Messaging/Sales.Orders.OrderCreated/Sales.Orders.OrderCreated.csproj ================================================  Debug AnyCPU {18455B18-D42C-4B5A-98E0-2112F8066542} Library Properties Sales.Orders.OrderCreated Sales.Orders.OrderCreated v4.5 512 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ..\packages\NServiceBus.Interfaces.4.3.4\lib\net40\NServiceBus.dll ..\packages\NServiceBus.4.3.4\lib\net40\NServiceBus.Core.dll ..\packages\NServiceBus.Host.4.3.3\lib\net40\NServiceBus.Host.exe {2dd347e9-1417-4ac5-9bdc-84dbe0707427} Sales.Messages Program $(ProjectDir)$(OutputPath)NServiceBus.Host.exe ================================================ FILE: 12 - Integrating Via Messaging/Sales.Orders.OrderCreated/packages.config ================================================  ================================================ FILE: 12 - Integrating Via Messaging/Shipping.BusinessCustomers.ShippingArranged/App.config ================================================ 
================================================ FILE: 12 - Integrating Via Messaging/Shipping.BusinessCustomers.ShippingArranged/Application/Handlers.cs ================================================ using Billing.Messages.Events; using NServiceBus; using Sales.Messages.Events; using System; using System.Linq; using System.Collections.Generic; namespace Shipping.BusinessCustomers.ShippingArranged { // update inherited interface with V2 public class OrderCreatedHandler : IHandleMessages { // dependency injected by NServiceBus public IBus Bus { get; set; } // updated Handle accepting a V2 public void Handle(OrderCreated_V2 message) { Console.WriteLine( "Shipping BC storing: Order: {0} User: {1} Shipping Type: {2}", message.OrderId, message.UserId, message.ShippingTypeId, message.AddressId ); var order = new ShippingOrder { UserId = message.UserId, OrderId = message.OrderId, AddressId = message.AddressId, ShippingTypeId = message.ShippingTypeId }; ShippingDatabase.AddOrderDetails(order); } } public class PaymentAcceptedHandler : IHandleMessages { // dependency injected by NServiceBus public IBus Bus { get; set; } public void Handle(PaymentAccepted message) { var address = ShippingDatabase.GetCustomerAddress(message.OrderId); var confirmation = ShippingProvider.ArrangeShippingFor(address, message.OrderId); if (confirmation.Status == ShippingStatus.Success) { var evnt = new Shipping.Messages.Events.ShippingArranged { OrderId = message.OrderId }; Bus.Publish(evnt); Console.WriteLine( "Shipping BC arranged shipping for Order: {0}", message.OrderId, address ); } else { // .. notify failed shipping instead } } } public static class ShippingDatabase { private static List Orders = new List(); public static void AddOrderDetails(ShippingOrder order) { Orders.Add(order); } public static string GetCustomerAddress(string orderId) { var order = Orders .Single(o => o.OrderId == orderId); return string.Format( "{0}, Address ID: {1}", order.UserId, order.AddressId ); } } public class ShippingOrder { public string UserId { get; set; } public string OrderId { get; set; } public string ShippingTypeId { get; set; } public string AddressId { get; set; } } public static class ShippingProvider { public static ShippingConfirmation ArrangeShippingFor(string address, string referenceCode) { return new ShippingConfirmation { Status = ShippingStatus.Success }; } } public class ShippingConfirmation { public ShippingStatus Status { get; set; } } public enum ShippingStatus { Success, Failure } } ================================================ FILE: 12 - Integrating Via Messaging/Shipping.BusinessCustomers.ShippingArranged/Infrastructure/EndpointConfig.cs ================================================ using NServiceBus; namespace Shipping.BusinessCustomers.ShippingArranged { public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, AsA_Publisher, IWantCustomInitialization { public void Init() { Configure.With() .DefiningCommandsAs(t => t.Namespace != null && t.Namespace.Contains("Commands")) .DefiningEventsAs(t => t.Namespace != null && t.Namespace.Contains("Events")); } } } ================================================ FILE: 12 - Integrating Via Messaging/Shipping.BusinessCustomers.ShippingArranged/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Shipping.BusinessCustomers.ShippingArranged")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Shipping.BusinessCustomers.ShippingArranged")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("720d1f39-3d5e-4734-a0df-af71ad5ce28c")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 12 - Integrating Via Messaging/Shipping.BusinessCustomers.ShippingArranged/Shipping.BusinessCustomers.ShippingArranged.csproj ================================================  Debug AnyCPU {2A146AA7-EF86-4304-839C-C43B97834F15} Library Properties Shipping.BusinessCustomers.ShippingArranged Shipping.BusinessCustomers.ShippingArranged v4.5 512 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ..\packages\NServiceBus.Interfaces.4.3.4\lib\net40\NServiceBus.dll ..\packages\NServiceBus.4.3.4\lib\net40\NServiceBus.Core.dll ..\packages\NServiceBus.Host.4.3.3\lib\net40\NServiceBus.Host.exe {b3707164-ff36-473e-877d-a652c8e41d14} Billing.Messages {2dd347e9-1417-4ac5-9bdc-84dbe0707427} Sales.Messages {ab3a64c2-9fd1-4382-aab8-10748573de98} Shipping.Messages Designer Program $(ProjectDir)$(OutputPath)NServiceBus.Host.exe ================================================ FILE: 12 - Integrating Via Messaging/Shipping.BusinessCustomers.ShippingArranged/packages.config ================================================  ================================================ FILE: 12 - Integrating Via Messaging/Shipping.Messages/Events/ShippingArranged.cs ================================================ using System; namespace Shipping.Messages.Events { public class ShippingArranged { public string OrderId { get; set; } /* * Other fields, such as date/date range * could be added here depending on your * shipping provider(s) API */ } } ================================================ FILE: 12 - Integrating Via Messaging/Shipping.Messages/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Shipping.Messages")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Shipping.Messages")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("424a0f6d-c104-487a-a7fd-c21c51fab04a")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 12 - Integrating Via Messaging/Shipping.Messages/Shipping.Messages.csproj ================================================  Debug AnyCPU {AB3A64C2-9FD1-4382-AAB8-10748573DE98} Library Properties Shipping.Messages Shipping.Messages v4.5 512 true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/AccountManagement/AccountManagement.csproj ================================================  Debug AnyCPU 2.0 {A5683820-EAE9-4C2A-B91A-50F50A1D052F} {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} Library Properties AccountManagement AccountManagement v4.5 true true full false bin\ DEBUG;TRACE prompt 4 pdbonly true bin\ TRACE prompt 4 ..\packages\Newtonsoft.Json.5.0.6\lib\net45\Newtonsoft.Json.dll ..\packages\Microsoft.AspNet.WebApi.Client.5.0.0\lib\net45\System.Net.Http.Formatting.dll ..\packages\Microsoft.AspNet.WebApi.Core.5.0.0\lib\net45\System.Web.Http.dll ..\packages\Microsoft.AspNet.WebApi.WebHost.5.0.0\lib\net45\System.Web.Http.WebHost.dll Global.asax Web.config Web.config 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) True True 1091 / http://localhost:3200/ False False False ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/AccountManagement/App_Start/WebApiConfig.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web.Http; namespace AccountManagement { public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API configuration and services // Web API routes config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/AccountManagement/Controllers/FollowerDirectoryController.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; namespace AccountManagement.Controllers { public class FollowerDirectoryController : ApiController { public IHttpActionResult GetUsersFollowers(string accountId) { var followers = GenerateDummyFollowers().ToList(); return Json(followers); } private IEnumerable GenerateDummyFollowers() { for (int i = 0; i < 10; i++) { yield return new Follower { FollowerId = "follower_" + i, FollowerName = "happy follower " + i, SocialTags = new List { "programming", "DDD", "Psychology" }, }; } } } public class Follower { public string FollowerId { get; set; } public string FollowerName { get; set; } public List SocialTags { get; set; } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/AccountManagement/Global.asax ================================================ <%@ Application Codebehind="Global.asax.cs" Inherits="AccountManagement.WebApiApplication" Language="C#" %> ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/AccountManagement/Global.asax.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Routing; namespace AccountManagement { public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { GlobalConfiguration.Configure(WebApiConfig.Register); } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/AccountManagement/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("AccountManagement")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("AccountManagement")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("63f18f3d-8b2f-468d-bc97-fdc2a7fa1faa")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/AccountManagement/Web.Debug.config ================================================ ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/AccountManagement/Web.Release.config ================================================ ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/AccountManagement/Web.config ================================================  ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/AccountManagement/packages.config ================================================  ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/Discovery/App_Start/WebApiConfig.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web.Http; namespace Discovery { public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API configuration and services // Web API routes config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/Discovery/Controllers/RecommenderController.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using ServiceStack.Text; namespace Discovery.Controllers { public class RecommenderController : ApiController { public List GetRecommendedUsers(string accountId) { var accountManagementUrl = "http://localhost:3200/api/" + "followerdirectory/getusersfollowers?" + "accountId=" + accountId; var response = new WebClient().DownloadString(accountManagementUrl); var followers = JsonSerializer.DeserializeFromString>(response); // automatically converted to JSON by Web API return FindRecommendedUsersBasedOnSocialTags(followers); } private List FindRecommendedUsersBasedOnSocialTags(List followers) { /* * Real system would look at the users tags and find * popular accounts with similar tags by making more * RPC calls. */ var tags = followers.SelectMany(f => f.SocialTags).Distinct(); return tags.Select(t => t + "_user_1").ToList(); } } /* class not shared between Bounded Contexts to meet * requirement of no source code dependencies */ public class Follower { public string FollowerId { get; set; } public string FollowerName { get; set; } public List SocialTags { get; set; } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/Discovery/Discovery.csproj ================================================  Debug AnyCPU 2.0 {A8F7B7B2-F436-4F38-A5B6-A0C86FEC4F8F} {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} Library Properties Discovery Discovery v4.5 true true full false bin\ DEBUG;TRACE prompt 4 pdbonly true bin\ TRACE prompt 4 ..\packages\ServiceStack.Text.4.0.15\lib\net40\ServiceStack.Text.dll False ..\packages\Microsoft.AspNet.WebApi.Client.5.1.1\lib\net45\System.Net.Http.Formatting.dll ..\packages\Newtonsoft.Json.5.0.6\lib\net45\Newtonsoft.Json.dll ..\packages\Microsoft.AspNet.WebApi.Core.5.0.0\lib\net45\System.Web.Http.dll ..\packages\Microsoft.AspNet.WebApi.WebHost.5.0.0\lib\net45\System.Web.Http.WebHost.dll Global.asax Web.config Web.config 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) True True 1273 / http://localhost:1273/ False False False ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/Discovery/Global.asax ================================================ <%@ Application Codebehind="Global.asax.cs" Inherits="Discovery.WebApiApplication" Language="C#" %> ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/Discovery/Global.asax.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Routing; namespace Discovery { public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { GlobalConfiguration.Configure(WebApiConfig.Register); } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/Discovery/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Discovery")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Discovery")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("bbeb869f-f227-47bb-ba92-11196b518b3d")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/Discovery/Web.Debug.config ================================================ ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/Discovery/Web.Release.config ================================================ ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/Discovery/Web.config ================================================ ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/Discovery/packages.config ================================================  ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.JSON.SocialMedia/PPPDDD.JSON.SocialMedia.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Express 2013 for Web VisualStudioVersion = 12.0.30723.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AccountManagement", "AccountManagement\AccountManagement.csproj", "{A5683820-EAE9-4C2A-B91A-50F50A1D052F}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discovery", "Discovery\Discovery.csproj", "{A8F7B7B2-F436-4F38-A5B6-A0C86FEC4F8F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Account Management Context", "Account Management Context", "{71903407-D5A0-4EEE-934C-BF7EE76F1974}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Discovery Context", "Discovery Context", "{AB48B0DE-79AD-4177-98FA-4E04FDF7D9C1}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {A5683820-EAE9-4C2A-B91A-50F50A1D052F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A5683820-EAE9-4C2A-B91A-50F50A1D052F}.Debug|Any CPU.Build.0 = Debug|Any CPU {A5683820-EAE9-4C2A-B91A-50F50A1D052F}.Release|Any CPU.ActiveCfg = Release|Any CPU {A5683820-EAE9-4C2A-B91A-50F50A1D052F}.Release|Any CPU.Build.0 = Release|Any CPU {A8F7B7B2-F436-4F38-A5B6-A0C86FEC4F8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A8F7B7B2-F436-4F38-A5B6-A0C86FEC4F8F}.Debug|Any CPU.Build.0 = Debug|Any CPU {A8F7B7B2-F436-4F38-A5B6-A0C86FEC4F8F}.Release|Any CPU.ActiveCfg = Release|Any CPU {A8F7B7B2-F436-4F38-A5B6-A0C86FEC4F8F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {A5683820-EAE9-4C2A-B91A-50F50A1D052F} = {71903407-D5A0-4EEE-934C-BF7EE76F1974} {A8F7B7B2-F436-4F38-A5B6-A0C86FEC4F8F} = {AB48B0DE-79AD-4177-98FA-4E04FDF7D9C1} EndGlobalSection EndGlobal ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/.gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. # User-specific files *.suo *.user *.sln.docstates # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ x64/ build/ bld/ [Bb]in/ [Oo]bj/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* #NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c *_i.c *_p.c *_i.h *.ilk *.meta *.obj *.pch *.pdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opensdf *.sdf *.cachefile # Visual Studio profiler *.psess *.vsp *.vspx # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding addin-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # NCrunch *.ncrunch* _NCrunch_* .*crunch*.local.xml # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # NuGet Packages Directory packages/ ## TODO: If the tool you use requires repositories.config uncomment the next line #!packages/repositories.config # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) !packages/build/ # Windows Azure Build Output csx/ *.build.csdef # Windows Store app package directory AppPackages/ # Others sql/ *.Cache ClientBin/ [Ss]tyle[Cc]op.* ~$* *~ *.dbmdl *.dbproj.schemaview *.pfx *.publishsettings node_modules/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file to a newer # Visual Studio version. Backup files are not needed, because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm # SQL Server files *.mdf *.ldf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings # Microsoft Fakes FakesAssemblies/ ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.Accounts.Api/AccountManagement.Accounts.Api.csproj ================================================  Debug AnyCPU 2.0 {F9B8D9B8-C9C7-4F8B-A75B-39B28A8E7F55} {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} Library Properties AccountManagement.Accounts.Api AccountManagement.Accounts.Api v4.5 true true full false bin\ DEBUG;TRACE prompt 4 pdbonly true bin\ TRACE prompt 4 ..\packages\EventStore.Client.2.0.2\lib\net40\EventStore.ClientAPI.dll ..\packages\ServiceStack.Text.4.0.15\lib\net40\ServiceStack.Text.dll False ..\packages\Microsoft.AspNet.WebApi.Client.5.1.1\lib\net45\System.Net.Http.Formatting.dll False ..\packages\Microsoft.AspNet.Cors.5.1.1\lib\net45\System.Web.Cors.dll False ..\packages\Microsoft.AspNet.WebApi.Core.5.1.1\lib\net45\System.Web.Http.dll False ..\packages\Microsoft.AspNet.WebApi.Cors.5.1.1\lib\net45\System.Web.Http.Cors.dll ..\packages\WebApi.Hal.2.2.0.18\lib\net45\WebApi.Hal.dll ..\packages\Newtonsoft.Json.5.0.6\lib\net45\Newtonsoft.Json.dll ..\packages\Microsoft.AspNet.WebApi.WebHost.5.0.0\lib\net45\System.Web.Http.WebHost.dll Global.asax Web.config Web.config 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) True True 1088 / http://localhost:4101/ False False False ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.Accounts.Api/App_Start/WebApiConfig.cs ================================================ using System; using System.Web.Http; using System.Web.Http.Cors; namespace AccountManagement.Accounts.Api { public static class WebApiConfig { public static void Register(HttpConfiguration config) { var cors = new EnableCorsAttribute("*", "*", "*"); config.EnableCors(cors); config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "Accounts Collection", routeTemplate: "accountmanagement/accounts", defaults: new { controller = "Accounts", action = "Index" } ); config.Routes.MapHttpRoute( name: "Individual Account", routeTemplate: "accountmanagement/accounts/{accountId}", defaults: new { controller = "Accounts", action = "Account" } ); config.Routes.MapHttpRoute( name: "Account Followers", routeTemplate: "accountmanagement/accounts/{accountId}/followers", defaults: new { controller = "Followers", action = "Index" } ); } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.Accounts.Api/Controllers/AccountsController.cs ================================================ using System; using System.Collections.Generic; using System.Web.Http; using WebApi.Hal; namespace AccountManagement.Accounts.Api.Controllers { public class AccountsController : ApiController { private const string EntryPointBaseUrl = "http://localhost:4100/"; private const string AccountsBaseUrl = "http://localhost:4101/accountmanagement/"; [HttpGet] public AccountsRepresentation Index() { return new AccountsRepresentation { Href = AccountsBaseUrl + "accounts", Rel = "self", Links = new List { new Link { Href = AccountsBaseUrl + "accounts?page=1", Rel = "alternative", }, new Link { // automatically identified as a template Href = AccountsBaseUrl + "accounts/{accountId}", Rel = "account", Title = "account template" }, new Link { Href = AccountsBaseUrl + "accounts/123", Rel = "account", Title = "account 123" }, new Link { Href = AccountsBaseUrl + "accounts/456", Rel = "account", Title = "account 456" }, new Link { Href = AccountsBaseUrl + "acccounts?page=2", Rel = "next" }, new Link { Href = EntryPointBaseUrl + "accountmanagement", Rel = "parent" } }, }; } [HttpGet] public AccountRepresentation Account(string accountId) { // canned data.. for now return new AccountRepresentation { Href = AccountsBaseUrl + "accounts/" + accountId, Rel = "self", AccountId = accountId, Name = "Account_" + accountId, Links = new List { new Link { Href = AccountsBaseUrl + "accounts", Rel = "collection", }, new Link { Href = AccountsBaseUrl + "accounts/" + accountId + "/followers", Rel = "followers", }, new Link { Href = AccountsBaseUrl + "accounts/" + accountId + "/following", Rel = "following", }, new Link { Href = AccountsBaseUrl + "accounts/" + accountId + "/blurbs", Rel = "blurbs", } } }; } } public class AccountRepresentation : Representation { public string AccountId { get; set; } public string Name { get; set; } protected override void CreateHypermedia() { } } public class AccountsRepresentation : Representation { protected override void CreateHypermedia() { } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.Accounts.Api/Controllers/FollowersController.cs ================================================ using System; using System.Collections.Generic; using System.Web.Http; using WebApi.Hal; using EventStore.ClientAPI; using System.Net; using System.Text; using ServiceStack.Text; using System.Net.Http; namespace AccountManagement.Accounts.Controllers { public class FollowersController : ApiController { private const string AccountsBaseUrl = "http://localhost:4101/accountmanagement/"; [HttpGet] public FollowersRepresentation Index(string accountId) { return new FollowersRepresentation { Href = AccountsBaseUrl + "accounts/" + accountId + "/followers", Rel = "self", Links = new List { new Link { Href = AccountsBaseUrl + "accounts/" + accountId + "/followers?pages=2", Rel = "next", }, }, followers = GetFollowers(accountId) }; } private List GetFollowers(string accountId) { // replace with DB lookup etc return new List { new Follower { AccountId = "fl1", }, new Follower { AccountId = "fl2", }, new Follower { AccountId = "fl3", } }; } [HttpPost] // respond to POST requests only [ActionName("index")] // Web API will not allow duplicate names public IHttpActionResult IndexPOST(string accountId, Follower follower) { // accountId will be taken from querystring - it is a simple type // follower will be taken from request body - it is a complex type var evnt = new BeganFollowing { AccountId = accountId, FollowerId = follower.AccountId }; EventPersister.PersistEvent(evnt); return RedirectToRoute("Account Followers", new { accountId = accountId }); } } public class FollowersRepresentation : Representation { public List followers { get; set; } protected override void CreateHypermedia() { } } public class Follower { public string AccountId { get; set; } } // representing the domain event public class BeganFollowing { public string AccountId { get; set; } public string FollowerId { get; set; } } public static class EventPersister { private static IPEndPoint defaultEsEndpoint = new IPEndPoint(IPAddress.Loopback, 1113); private static IEventStoreConnection esConn = EventStoreConnection.Create(defaultEsEndpoint); static EventPersister() { esConn.Connect(); } public static void PersistEvent(object ev) { var commitHeaders = new Dictionary { {"CommitId", Guid.NewGuid()}, }; esConn.AppendToStream( "BeganFollowing", ExpectedVersion.Any, ToEventData(Guid.NewGuid(), ev, commitHeaders )); } private static EventData ToEventData(Guid eventId, object evnt, IDictionary headers) { var data = Encoding.UTF8.GetBytes( JsonSerializer.SerializeToString(evnt) ); var metadata = Encoding.UTF8.GetBytes( JsonSerializer.SerializeToString(headers) ); var typeName = evnt.GetType().Name; return new EventData(eventId, typeName, true, data, metadata); } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.Accounts.Api/Global.asax ================================================ <%@ Application Codebehind="Global.asax.cs" Inherits="AccountManagement.Accounts.Api.WebApiApplication" Language="C#" %> ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.Accounts.Api/Global.asax.cs ================================================ using System; using System.Web.Http; using WebApi.Hal; namespace AccountManagement.Accounts.Api { public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { GlobalConfiguration.Configure(WebApiConfig.Register); // default media type (HAL JSON) GlobalConfiguration.Configuration.Formatters.Insert( 0, new JsonHalMediaTypeFormatter() ); // alternative media type (HAL XML) // accept header must equal application/hal+xml GlobalConfiguration.Configuration.Formatters.Insert( 1, new XmlHalMediaTypeFormatter() ); } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.Accounts.Api/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("AccountManagement.Accounts.Api")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("AccountManagement.Accounts.Api")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("41bfc8b0-3ef3-4f17-9314-f6afdbce670e")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.Accounts.Api/Web.Debug.config ================================================ ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.Accounts.Api/Web.Release.config ================================================ ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.Accounts.Api/Web.config ================================================ ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.Accounts.Api/packages.config ================================================  ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/.gitignore ================================================ .DS_Store ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/AccountManagement.EntryPoint.Api.csproj ================================================  Debug AnyCPU 2.0 {66644357-5B60-4E85-9615-5378D400C18D} {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} Library Properties AccountManagement.EntryPoint.Api AccountManagement.EntryPoint.Api v4.5 true true full false bin\ DEBUG;TRACE prompt 4 pdbonly true bin\ TRACE prompt 4 ..\packages\WebApi.Hal.2.2.0.18\lib\net45\WebApi.Hal.dll ..\packages\Newtonsoft.Json.5.0.6\lib\net45\Newtonsoft.Json.dll ..\packages\Microsoft.AspNet.WebApi.Client.5.0.0\lib\net45\System.Net.Http.Formatting.dll ..\packages\Microsoft.AspNet.WebApi.Core.5.0.0\lib\net45\System.Web.Http.dll ..\packages\Microsoft.AspNet.WebApi.WebHost.5.0.0\lib\net45\System.Web.Http.WebHost.dll Global.asax Web.config Web.config 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) True True 1117 / http://localhost:4100/ False False False ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/App_Start/WebApiConfig.cs ================================================ using System; using System.Web.Http; namespace AccountManagement.EntryPoint.Api { public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "Entry Point", routeTemplate: "accountmanagement", defaults: new { controller = "EntryPoint", action = "Get" } ); } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/Controllers/EntryPointController.cs ================================================ using System; using System.Collections.Generic; using System.Web.Http; using WebApi.Hal; namespace AccountManagement.EntryPoint.Api.Controllers { public class EntryPointController : ApiController { private const string EntryPointBaseUrl = "http://localhost:4100/"; private const string AccountsBaseUrl = "http://localhost:4101/"; [HttpGet] public EntryPointRepresentation Get() { return new EntryPointRepresentation { Href = EntryPointBaseUrl + "accountmanagement", Rel = "self", Links = new List { new Link { Href = AccountsBaseUrl + "accountmanagement/accounts", Rel = "accounts" }, new Link { Href = "http://localhost:4102/accountmanagement/beganfollowing", Rel = "beganfollowing" } } }; } } public class EntryPointRepresentation : Representation { protected override void CreateHypermedia() { } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/Global.asax ================================================ <%@ Application Codebehind="Global.asax.cs" Inherits="AccountManagement.EntryPoint.Api.WebApiApplication" Language="C#" %> ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/Global.asax.cs ================================================ using System; using System.Web.Http; using WebApi.Hal; namespace AccountManagement.EntryPoint.Api { public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { GlobalConfiguration.Configure(WebApiConfig.Register); // default media type (HAL JSON) GlobalConfiguration.Configuration.Formatters.Insert( 0, new JsonHalMediaTypeFormatter() ); // alternative media type (HAL XML) // accept header must equal application/hal+xml GlobalConfiguration.Configuration.Formatters.Insert( 1, new XmlHalMediaTypeFormatter() ); } } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/MIT-LICENSE.txt ================================================ Copyright (c) 2012 Mike Kelly, http://stateless.co/ 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: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("AccountManagement.EntryPoint")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("AccountManagement.EntryPoint")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("294c0646-6ab6-44bd-8dce-8ade7cb52546")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/README.md ================================================ HAL-browser =========== An API browser for the hal+json media type Example Usage ============= Here is an example of a hal+json API using the browser: [http://haltalk.herokuapp.com/explorer/browser.html](http://haltalk.herokuapp.com/explorer/browser.html) About HAL ======== HAL is a format based on json that establishes conventions for representing links. For example: ```javascript { "_links": { "self": { "href": "/orders" }, "next": { "href": "/orders?page=2" } } } ``` More detail about HAL can be found at [http://stateless.co/hal_specification.html](http://stateless.co/hal_specification.html). Instructions ============ All you should need to do is copy the files into your webroot. It is OK to put it in a subdirectory; it does not need to be in the root. All the JS and CSS dependencies come included in the vendor directory. TODO =========== * Make Location and Content-Location headers clickable links * Provide feedback to user when there are issues with response (missing self link, wrong media type identifier) * Give 'self' and 'curies' links special treatment ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/Web.Debug.config ================================================ ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/Web.Release.config ================================================ ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/Web.config ================================================  ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/browser.html ================================================ The HAL Browser
================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/browser.js ================================================ HAL.Browser = Backbone.Router.extend({ initialize: function(opts) { opts = opts || {}; var vent = _.extend({}, Backbone.Events), $container = opts.container || $('#browser'); this.entryPoint = opts.entryPoint || '/'; // TODO: don't hang currentDoc off namespace vent.bind('response', function(e) { window.HAL.currentDocument = e.resource || {}; }); vent.bind('location-go', _.bind(this.loadUrl, this)); HAL.client = new HAL.Http.Client({ vent: vent }); var browser = new HAL.Views.Browser({ vent: vent, entryPoint: this.entryPoint }); browser.render() $container.html(browser.el); vent.trigger('app:loaded'); if (window.location.hash === '') { window.location.hash = this.entryPoint; } if(location.hash.slice(1,9) === 'NON-GET:') { new HAL.Views.NonSafeRequestDialog({ href: location.hash.slice(9), vent: vent }).render({}); } }, routes: { '*url': 'resourceRoute' }, loadUrl: function(url) { if (this.getHash() === url) { HAL.client.get(url); } else { window.location.hash = url; } }, getHash: function() { return window.location.hash.slice(1); }, resourceRoute: function() { url = location.hash.slice(1); console.log('target url changed to: ' + url); if (url.slice(0,8) !== 'NON-GET:') { HAL.client.get(url); } } }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/http/client.js ================================================ HAL.Http.Client = function(opts) { this.vent = opts.vent; $.ajaxSetup({ headers: { 'Accept': 'application/hal+json, application/json, */*; q=0.01' } }); }; HAL.Http.Client.prototype.get = function(url) { var self = this; this.vent.trigger('location-change', { url: url }); var jqxhr = $.ajax({ url: url, dataType: 'json', success: function(resource, textStatus, jqXHR) { self.vent.trigger('response', { resource: resource, jqxhr: jqXHR, headers: jqXHR.getAllResponseHeaders() }); } }).error(function() { self.vent.trigger('fail-response', { jqxhr: jqxhr }); }); }; HAL.Http.Client.prototype.request = function(opts) { var self = this; opts.dataType = 'json'; self.vent.trigger('location-change', { url: opts.url }); return jqxhr = $.ajax(opts); }; HAL.Http.Client.prototype.updateDefaultHeaders = function(headers) { this.defaultHeaders = headers; $.ajaxSetup({ headers: headers }); }; HAL.Http.Client.prototype.getDefaultHeaders = function() { return this.defaultHeaders; }; ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/resource.js ================================================ HAL.Models.Resource = Backbone.Model.extend({ initialize: function(representation) { representation = representation || {}; this.links = representation._links; if(representation._embedded !== undefined) { this.embeddedResources = this.buildEmbeddedResources(representation._embedded); } this.set(representation); this.unset('_embedded', { silent: true }); this.unset('_links', { silent: true }); }, buildEmbeddedResources: function(embeddedResources) { var result = {}; _.each(embeddedResources, function(obj, rel) { if($.isArray(obj)) { var arr = []; _.each(obj, function(resource, i) { var newResource = new HAL.Models.Resource(resource); newResource.identifier = rel + '[' + i + ']'; newResource.embed_rel = rel; arr.push(newResource); }); result[rel] = arr; } else { var newResource = new HAL.Models.Resource(obj); newResource.identifier = rel; newResource.embed_rel = rel; result[rel] = newResource; } }); return result; } }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/views/browser.js ================================================ HAL.Views.Browser = Backbone.View.extend({ initialize: function(opts) { var self = this; this.vent = opts.vent; this.entryPoint = opts.entryPoint; this.explorerView = new HAL.Views.Explorer({ vent: this.vent }); this.inspectorView = new HAL.Views.Inspector({ vent: this.vent }); }, className: 'hal-browser row-fluid', render: function() { this.$el.empty(); this.inspectorView.render(); this.explorerView.render(); this.$el.html(this.explorerView.el); this.$el.append(this.inspectorView.el); var entryPoint = this.entryPoint; $("#entryPointLink").click(function(event) { event.preventDefault(); window.location.hash = entryPoint; }); return this; } }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/views/documentation.js ================================================ HAL.Views.Documenation = Backbone.View.extend({ className: 'documentation', render: function(url) { this.$el.html(''); } }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/views/embedded_resource.js ================================================ HAL.Views.EmbeddedResource = Backbone.View.extend({ initialize: function(opts) { this.vent = opts.vent; this.resource = opts.resource; this.propertiesView = new HAL.Views.Properties({}); this.linksView = new HAL.Views.Links({ vent: this.vent }); _.bindAll(this, 'onToggleClick'); _.bindAll(this, 'onDoxClick'); }, events: { 'click a.accordion-toggle': 'onToggleClick', 'click span.dox': 'onDoxClick' }, className: 'embedded-resource accordion-group', onToggleClick: function(e) { e.preventDefault(); this.$accordionBody.collapse('toggle'); }, onDoxClick: function(e) { e.preventDefault(); this.vent.trigger('show-docs', { url: $(e.currentTarget).data('href') }); return false; }, render: function() { this.$el.empty(); this.propertiesView.render(this.resource.toJSON()); this.linksView.render(this.resource.links); this.$el.append(this.template({ resource: this.resource })); var $inner = $('
'); $inner.append(this.propertiesView.el); $inner.append(this.linksView.el); this.$accordionBody = $('
'); this.$accordionBody.append($inner) this.$el.append(this.$accordionBody); }, template: _.template($('#embedded-resource-template').html()) }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/views/embedded_resources.js ================================================ HAL.Views.EmbeddedResources = Backbone.View.extend({ initialize: function(opts) { this.vent = opts.vent; _.bindAll(this, 'render'); }, className: 'embedded-resources accordion', render: function(resources) { var self = this, resourceViews = [], buildView = function(resource) { return new HAL.Views.EmbeddedResource({ resource: resource, vent: self.vent }); }; _.each(resources, function(prop) { if ($.isArray(prop)) { _.each(prop, function(resource) { resourceViews.push(buildView(resource)); }); } else { resourceViews.push(buildView(prop)); } }); this.$el.html(this.template()); _.each(resourceViews, function(view) { view.render(); self.$el.append(view.el); }); return this; }, template: _.template($('#embedded-resources-template').html()) }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/views/explorer.js ================================================ HAL.Views.Explorer = Backbone.View.extend({ initialize: function(opts) { var self = this; this.vent = opts.vent; this.navigationView = new HAL.Views.Navigation({ vent: this.vent }); this.resourceView = new HAL.Views.Resource({ vent: this.vent }); }, className: 'explorer span6', render: function() { this.navigationView.render(); this.$el.html(this.template()); this.$el.append(this.navigationView.el); this.$el.append(this.resourceView.el); }, template: function() { return '

Explorer

'; } }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/views/inspector.js ================================================ HAL.Views.Inspector = Backbone.View.extend({ initialize: function(opts) { this.vent = opts.vent; _.bindAll(this, 'renderDocumentation'); _.bindAll(this, 'renderResponse'); this.vent.bind('show-docs', this.renderDocumentation); this.vent.bind('response', this.renderResponse); }, className: 'inspector span6', render: function() { this.$el.html(this.template()); }, renderResponse: function(response) { var responseView = new HAL.Views.Response({ vent: this.vent }); this.render(); responseView.render(response); this.$el.append(responseView.el); }, renderDocumentation: function(e) { var docView = new HAL.Views.Documenation({ vent: this.vent }); this.render(); docView.render(e.url); this.$el.append(docView.el); }, template: function() { return '

Inspector

'; } }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/views/links.js ================================================ HAL.Views.Links = Backbone.View.extend({ initialize: function(opts) { this.vent = opts.vent; }, events: { 'click .follow': 'followLink', 'click .non-get': 'showNonSafeRequestDialog', 'click .query': 'showUriQueryDialog', 'click .dox': 'showDocs' }, className: 'links', followLink: function(e) { e.preventDefault(); var $target = $(e.currentTarget); var uri = $target.attr('href'); window.location.hash = uri; }, showUriQueryDialog: function(e) { e.preventDefault(); var $target = $(e.currentTarget); var uri = $target.attr('href'); new HAL.Views.QueryUriDialog({ href: uri }).render({}); }, showNonSafeRequestDialog: function(e) { e.preventDefault(); var d = new HAL.Views.NonSafeRequestDialog({ href: $(e.currentTarget).attr('href'), vent: this.vent }).render({}); }, showDocs: function(e) { e.preventDefault(); var $target = $(e.target); var uri = $target.attr('href') || $target.parent().attr('href'); this.vent.trigger('show-docs', { url: uri }); }, template: _.template($('#links-template').html()), render: function(links) { this.$el.html(this.template({ links: links })); } }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/views/location_bar.js ================================================ HAL.Views.LocationBar = Backbone.View.extend({ initialize: function(opts) { this.vent = opts.vent; _.bindAll(this, 'render'); _.bindAll(this, 'onButtonClick'); this.vent.bind('location-change', this.render); this.vent.bind('location-change', _.bind(this.showSpinner, this)); this.vent.bind('response', _.bind(this.hideSpinner, this)); }, events: { 'submit form': 'onButtonClick' }, className: 'address', render: function(e) { e = e || { url: '' }; this.$el.html(this.template(e)); }, onButtonClick: function(e) { e.preventDefault(); this.vent.trigger('location-go', this.getLocation()); }, getLocation: function() { return this.$el.find('input').val(); }, showSpinner: function() { this.$el.find('.ajax-loader').addClass('visible'); }, hideSpinner: function() { this.$el.find('.ajax-loader').removeClass('visible'); }, template: _.template($('#location-bar-template').html()) }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/views/navigation.js ================================================ HAL.Views.Navigation = Backbone.View.extend({ initialize: function(opts) { this.vent = opts.vent; this.locationBar = new HAL.Views.LocationBar({ vent: this.vent }); this.requestHeadersView = new HAL.Views.RequestHeaders({ vent: this.vent }); }, className: 'navigation', render: function() { this.$el.empty(); this.locationBar.render(); this.requestHeadersView.render(); this.$el.append(this.locationBar.el); this.$el.append(this.requestHeadersView.el); } }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/views/non_safe_request_dialog.js ================================================ HAL.Views.NonSafeRequestDialog = Backbone.View.extend({ initialize: function(opts) { this.href = opts.href; this.vent = opts.vent; this.uriTemplate = uritemplate(this.href); _.bindAll(this, 'submitQuery'); }, events: { 'submit form': 'submitQuery' }, className: 'modal fade', submitQuery: function(e) { e.preventDefault(); var self = this, opts = { url: this.$('.url').val(), headers: HAL.parseHeaders(this.$('.headers').val()), method: this.$('.method').val(), data: this.$('.body').val() }; var request = HAL.client.request(opts); request.done(function(response) { self.vent.trigger('response', { resource: response, jqxhr: jqxhr }); }).fail(function(response) { self.vent.trigger('fail-response', { jqxhr: jqxhr }); }).always(function() { self.vent.trigger('response-headers', { jqxhr: jqxhr }); window.location.hash = 'NON-GET:' + opts.url; }); this.$el.modal('hide'); }, render: function(opts) { var headers = HAL.client.getDefaultHeaders(), headersString = ''; _.each(headers, function(value, name) { headersString += name + ': ' + value + '\n'; }); this.$el.html(this.template({ href: this.href, user_defined_headers: headersString })); this.$el.modal(); return this; }, template: _.template($('#non-safe-request-template').html()) }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/views/properties.js ================================================ HAL.Views.Properties = Backbone.View.extend({ initialize: function(opts) { this.vent = opts.vent; _.bindAll(this, 'render'); }, className: 'properties', render: function(props) { this.$el.html(this.template({ properties: props })); }, template: _.template($('#properties-template').html()) }); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/js/hal/views/query_uri_dialog.js ================================================ HAL.Views.QueryUriDialog = Backbone.View.extend({ initialize: function(opts) { this.href = opts.href; this.uriTemplate = uritemplate(this.href); _.bindAll(this, 'submitQuery'); _.bindAll(this, 'renderPreview'); }, className: 'modal fade', events: { 'submit form': 'submitQuery', 'keyup textarea': 'renderPreview', 'change textarea': 'renderPreview' }, submitQuery: function(e) { e.preventDefault(); var input; try { input = JSON.parse(this.$('textarea').val()); } catch(err) { input = {}; } this.$el.modal('hide'); window.location.hash = this.uriTemplate.expand(input); }, renderPreview: function(e) { var input, result; try { input = JSON.parse($(e.target).val()); result = this.uriTemplate.expand(input); } catch (err) { result = 'Invalid json input'; } this.$('.preview').html(result); }, extractExpressionNames: function (template) { var names = []; for (var i=0; i 1; }; var HAL = { Models: {}, Views: {}, Http: {}, currentDocument: {}, jsonIndent: 2, isUrl: function(str) { return str.match(urlRegex) || isCurie(str); }, truncateIfUrl: function(str) { var replaceRegex = /(http|https):\/\/([^\/]*)\//; return str.replace(replaceRegex, '.../'); }, buildUrl: function(rel) { if (!rel.match(urlRegex) && isCurie(rel) && HAL.currentDocument._links.curies) { var parts = rel.split(':'); var curies = HAL.currentDocument._links.curies; for (var i=0; i 1) { var name = parts.shift().trim(); var value = parts.join(':').trim(); headers[name] = value; } }); return headers; }, }; window.HAL = HAL; })(); ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/packages.config ================================================  ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/styles.css ================================================ #browser #location-bar { margin: 10px 0; } #browser #location-bar .address { border: 1px solid #999; padding: 4px; margin: 0; } #browser #headers-bar { border: 1px solid #888; padding: 5px } #request-headers { border: 0; outline: none; padding: 0; resize: vertical; width: 100%; height: 40px; margin-bottom: 0px; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } .inspector { height: 100%; } .documentation { height: 100%; } .documentation iframe { width: 100%; height: 100%; } .modal input, .modal textarea { width: 90%; } .modal textarea { height: 100px; } .links .btn { padding: 2px 5px 2px; font-size: 12px; line-height: 14px; } body table.table { font-size: 11px; } .location-bar-container { line-height: 30px; } .ajax-loader { vertical-align: middle; background-image: url("./vendor/img/ajax-loader.gif"); background-repeat: no-repeat; width: 16px; height: 16px; margin-left: 6px; opacity: 0; display: inline-block; transition: opacity 1s; } .ajax-loader.visible { opacity: 1; } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/vendor/css/bootstrap-responsive.css ================================================ /*! * Bootstrap Responsive v2.3.1 * * Copyright 2012 Twitter, Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world @twitter by @mdo and @fat. */ .clearfix { *zoom: 1; } .clearfix:before, .clearfix:after { display: table; line-height: 0; content: ""; } .clearfix:after { clear: both; } .hide-text { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } .input-block-level { display: block; width: 100%; min-height: 30px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } @-ms-viewport { width: device-width; } .hidden { display: none; visibility: hidden; } .visible-phone { display: none !important; } .visible-tablet { display: none !important; } .hidden-desktop { display: none !important; } .visible-desktop { display: inherit !important; } @media (min-width: 768px) and (max-width: 979px) { .hidden-desktop { display: inherit !important; } .visible-desktop { display: none !important ; } .visible-tablet { display: inherit !important; } .hidden-tablet { display: none !important; } } @media (max-width: 767px) { .hidden-desktop { display: inherit !important; } .visible-desktop { display: none !important; } .visible-phone { display: inherit !important; } .hidden-phone { display: none !important; } } .visible-print { display: none !important; } @media print { .visible-print { display: inherit !important; } .hidden-print { display: none !important; } } @media (min-width: 1200px) { .row { margin-left: -30px; *zoom: 1; } .row:before, .row:after { display: table; line-height: 0; content: ""; } .row:after { clear: both; } [class*="span"] { float: left; min-height: 1px; margin-left: 30px; } .container, .navbar-static-top .container, .navbar-fixed-top .container, .navbar-fixed-bottom .container { width: 1170px; } .span12 { width: 1170px; } .span11 { width: 1070px; } .span10 { width: 970px; } .span9 { width: 870px; } .span8 { width: 770px; } .span7 { width: 670px; } .span6 { width: 570px; } .span5 { width: 470px; } .span4 { width: 370px; } .span3 { width: 270px; } .span2 { width: 170px; } .span1 { width: 70px; } .offset12 { margin-left: 1230px; } .offset11 { margin-left: 1130px; } .offset10 { margin-left: 1030px; } .offset9 { margin-left: 930px; } .offset8 { margin-left: 830px; } .offset7 { margin-left: 730px; } .offset6 { margin-left: 630px; } .offset5 { margin-left: 530px; } .offset4 { margin-left: 430px; } .offset3 { margin-left: 330px; } .offset2 { margin-left: 230px; } .offset1 { margin-left: 130px; } .row-fluid { width: 100%; *zoom: 1; } .row-fluid:before, .row-fluid:after { display: table; line-height: 0; content: ""; } .row-fluid:after { clear: both; } .row-fluid [class*="span"] { display: block; float: left; width: 100%; min-height: 30px; margin-left: 2.564102564102564%; *margin-left: 2.5109110747408616%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .row-fluid [class*="span"]:first-child { margin-left: 0; } .row-fluid .controls-row [class*="span"] + [class*="span"] { margin-left: 2.564102564102564%; } .row-fluid .span12 { width: 100%; *width: 99.94680851063829%; } .row-fluid .span11 { width: 91.45299145299145%; *width: 91.39979996362975%; } .row-fluid .span10 { width: 82.90598290598291%; *width: 82.8527914166212%; } .row-fluid .span9 { width: 74.35897435897436%; *width: 74.30578286961266%; } .row-fluid .span8 { width: 65.81196581196582%; *width: 65.75877432260411%; } .row-fluid .span7 { width: 57.26495726495726%; *width: 57.21176577559556%; } .row-fluid .span6 { width: 48.717948717948715%; *width: 48.664757228587014%; } .row-fluid .span5 { width: 40.17094017094017%; *width: 40.11774868157847%; } .row-fluid .span4 { width: 31.623931623931625%; *width: 31.570740134569924%; } .row-fluid .span3 { width: 23.076923076923077%; *width: 23.023731587561375%; } .row-fluid .span2 { width: 14.52991452991453%; *width: 14.476723040552828%; } .row-fluid .span1 { width: 5.982905982905983%; *width: 5.929714493544281%; } .row-fluid .offset12 { margin-left: 105.12820512820512%; *margin-left: 105.02182214948171%; } .row-fluid .offset12:first-child { margin-left: 102.56410256410257%; *margin-left: 102.45771958537915%; } .row-fluid .offset11 { margin-left: 96.58119658119658%; *margin-left: 96.47481360247316%; } .row-fluid .offset11:first-child { margin-left: 94.01709401709402%; *margin-left: 93.91071103837061%; } .row-fluid .offset10 { margin-left: 88.03418803418803%; *margin-left: 87.92780505546462%; } .row-fluid .offset10:first-child { margin-left: 85.47008547008548%; *margin-left: 85.36370249136206%; } .row-fluid .offset9 { margin-left: 79.48717948717949%; *margin-left: 79.38079650845607%; } .row-fluid .offset9:first-child { margin-left: 76.92307692307693%; *margin-left: 76.81669394435352%; } .row-fluid .offset8 { margin-left: 70.94017094017094%; *margin-left: 70.83378796144753%; } .row-fluid .offset8:first-child { margin-left: 68.37606837606839%; *margin-left: 68.26968539734497%; } .row-fluid .offset7 { margin-left: 62.393162393162385%; *margin-left: 62.28677941443899%; } .row-fluid .offset7:first-child { margin-left: 59.82905982905982%; *margin-left: 59.72267685033642%; } .row-fluid .offset6 { margin-left: 53.84615384615384%; *margin-left: 53.739770867430444%; } .row-fluid .offset6:first-child { margin-left: 51.28205128205128%; *margin-left: 51.175668303327875%; } .row-fluid .offset5 { margin-left: 45.299145299145295%; *margin-left: 45.1927623204219%; } .row-fluid .offset5:first-child { margin-left: 42.73504273504273%; *margin-left: 42.62865975631933%; } .row-fluid .offset4 { margin-left: 36.75213675213675%; *margin-left: 36.645753773413354%; } .row-fluid .offset4:first-child { margin-left: 34.18803418803419%; *margin-left: 34.081651209310785%; } .row-fluid .offset3 { margin-left: 28.205128205128204%; *margin-left: 28.0987452264048%; } .row-fluid .offset3:first-child { margin-left: 25.641025641025642%; *margin-left: 25.53464266230224%; } .row-fluid .offset2 { margin-left: 19.65811965811966%; *margin-left: 19.551736679396257%; } .row-fluid .offset2:first-child { margin-left: 17.094017094017094%; *margin-left: 16.98763411529369%; } .row-fluid .offset1 { margin-left: 11.11111111111111%; *margin-left: 11.004728132387708%; } .row-fluid .offset1:first-child { margin-left: 8.547008547008547%; *margin-left: 8.440625568285142%; } input, textarea, .uneditable-input { margin-left: 0; } .controls-row [class*="span"] + [class*="span"] { margin-left: 30px; } input.span12, textarea.span12, .uneditable-input.span12 { width: 1156px; } input.span11, textarea.span11, .uneditable-input.span11 { width: 1056px; } input.span10, textarea.span10, .uneditable-input.span10 { width: 956px; } input.span9, textarea.span9, .uneditable-input.span9 { width: 856px; } input.span8, textarea.span8, .uneditable-input.span8 { width: 756px; } input.span7, textarea.span7, .uneditable-input.span7 { width: 656px; } input.span6, textarea.span6, .uneditable-input.span6 { width: 556px; } input.span5, textarea.span5, .uneditable-input.span5 { width: 456px; } input.span4, textarea.span4, .uneditable-input.span4 { width: 356px; } input.span3, textarea.span3, .uneditable-input.span3 { width: 256px; } input.span2, textarea.span2, .uneditable-input.span2 { width: 156px; } input.span1, textarea.span1, .uneditable-input.span1 { width: 56px; } .thumbnails { margin-left: -30px; } .thumbnails > li { margin-left: 30px; } .row-fluid .thumbnails { margin-left: 0; } } @media (min-width: 768px) and (max-width: 979px) { .row { margin-left: -20px; *zoom: 1; } .row:before, .row:after { display: table; line-height: 0; content: ""; } .row:after { clear: both; } [class*="span"] { float: left; min-height: 1px; margin-left: 20px; } .container, .navbar-static-top .container, .navbar-fixed-top .container, .navbar-fixed-bottom .container { width: 724px; } .span12 { width: 724px; } .span11 { width: 662px; } .span10 { width: 600px; } .span9 { width: 538px; } .span8 { width: 476px; } .span7 { width: 414px; } .span6 { width: 352px; } .span5 { width: 290px; } .span4 { width: 228px; } .span3 { width: 166px; } .span2 { width: 104px; } .span1 { width: 42px; } .offset12 { margin-left: 764px; } .offset11 { margin-left: 702px; } .offset10 { margin-left: 640px; } .offset9 { margin-left: 578px; } .offset8 { margin-left: 516px; } .offset7 { margin-left: 454px; } .offset6 { margin-left: 392px; } .offset5 { margin-left: 330px; } .offset4 { margin-left: 268px; } .offset3 { margin-left: 206px; } .offset2 { margin-left: 144px; } .offset1 { margin-left: 82px; } .row-fluid { width: 100%; *zoom: 1; } .row-fluid:before, .row-fluid:after { display: table; line-height: 0; content: ""; } .row-fluid:after { clear: both; } .row-fluid [class*="span"] { display: block; float: left; width: 100%; min-height: 30px; margin-left: 2.7624309392265194%; *margin-left: 2.709239449864817%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .row-fluid [class*="span"]:first-child { margin-left: 0; } .row-fluid .controls-row [class*="span"] + [class*="span"] { margin-left: 2.7624309392265194%; } .row-fluid .span12 { width: 100%; *width: 99.94680851063829%; } .row-fluid .span11 { width: 91.43646408839778%; *width: 91.38327259903608%; } .row-fluid .span10 { width: 82.87292817679558%; *width: 82.81973668743387%; } .row-fluid .span9 { width: 74.30939226519337%; *width: 74.25620077583166%; } .row-fluid .span8 { width: 65.74585635359117%; *width: 65.69266486422946%; } .row-fluid .span7 { width: 57.18232044198895%; *width: 57.12912895262725%; } .row-fluid .span6 { width: 48.61878453038674%; *width: 48.56559304102504%; } .row-fluid .span5 { width: 40.05524861878453%; *width: 40.00205712942283%; } .row-fluid .span4 { width: 31.491712707182323%; *width: 31.43852121782062%; } .row-fluid .span3 { width: 22.92817679558011%; *width: 22.87498530621841%; } .row-fluid .span2 { width: 14.3646408839779%; *width: 14.311449394616199%; } .row-fluid .span1 { width: 5.801104972375691%; *width: 5.747913483013988%; } .row-fluid .offset12 { margin-left: 105.52486187845304%; *margin-left: 105.41847889972962%; } .row-fluid .offset12:first-child { margin-left: 102.76243093922652%; *margin-left: 102.6560479605031%; } .row-fluid .offset11 { margin-left: 96.96132596685082%; *margin-left: 96.8549429881274%; } .row-fluid .offset11:first-child { margin-left: 94.1988950276243%; *margin-left: 94.09251204890089%; } .row-fluid .offset10 { margin-left: 88.39779005524862%; *margin-left: 88.2914070765252%; } .row-fluid .offset10:first-child { margin-left: 85.6353591160221%; *margin-left: 85.52897613729868%; } .row-fluid .offset9 { margin-left: 79.8342541436464%; *margin-left: 79.72787116492299%; } .row-fluid .offset9:first-child { margin-left: 77.07182320441989%; *margin-left: 76.96544022569647%; } .row-fluid .offset8 { margin-left: 71.2707182320442%; *margin-left: 71.16433525332079%; } .row-fluid .offset8:first-child { margin-left: 68.50828729281768%; *margin-left: 68.40190431409427%; } .row-fluid .offset7 { margin-left: 62.70718232044199%; *margin-left: 62.600799341718584%; } .row-fluid .offset7:first-child { margin-left: 59.94475138121547%; *margin-left: 59.838368402492065%; } .row-fluid .offset6 { margin-left: 54.14364640883978%; *margin-left: 54.037263430116376%; } .row-fluid .offset6:first-child { margin-left: 51.38121546961326%; *margin-left: 51.27483249088986%; } .row-fluid .offset5 { margin-left: 45.58011049723757%; *margin-left: 45.47372751851417%; } .row-fluid .offset5:first-child { margin-left: 42.81767955801105%; *margin-left: 42.71129657928765%; } .row-fluid .offset4 { margin-left: 37.01657458563536%; *margin-left: 36.91019160691196%; } .row-fluid .offset4:first-child { margin-left: 34.25414364640884%; *margin-left: 34.14776066768544%; } .row-fluid .offset3 { margin-left: 28.45303867403315%; *margin-left: 28.346655695309746%; } .row-fluid .offset3:first-child { margin-left: 25.69060773480663%; *margin-left: 25.584224756083227%; } .row-fluid .offset2 { margin-left: 19.88950276243094%; *margin-left: 19.783119783707537%; } .row-fluid .offset2:first-child { margin-left: 17.12707182320442%; *margin-left: 17.02068884448102%; } .row-fluid .offset1 { margin-left: 11.32596685082873%; *margin-left: 11.219583872105325%; } .row-fluid .offset1:first-child { margin-left: 8.56353591160221%; *margin-left: 8.457152932878806%; } input, textarea, .uneditable-input { margin-left: 0; } .controls-row [class*="span"] + [class*="span"] { margin-left: 20px; } input.span12, textarea.span12, .uneditable-input.span12 { width: 710px; } input.span11, textarea.span11, .uneditable-input.span11 { width: 648px; } input.span10, textarea.span10, .uneditable-input.span10 { width: 586px; } input.span9, textarea.span9, .uneditable-input.span9 { width: 524px; } input.span8, textarea.span8, .uneditable-input.span8 { width: 462px; } input.span7, textarea.span7, .uneditable-input.span7 { width: 400px; } input.span6, textarea.span6, .uneditable-input.span6 { width: 338px; } input.span5, textarea.span5, .uneditable-input.span5 { width: 276px; } input.span4, textarea.span4, .uneditable-input.span4 { width: 214px; } input.span3, textarea.span3, .uneditable-input.span3 { width: 152px; } input.span2, textarea.span2, .uneditable-input.span2 { width: 90px; } input.span1, textarea.span1, .uneditable-input.span1 { width: 28px; } } @media (max-width: 767px) { body { padding-right: 20px; padding-left: 20px; } .navbar-fixed-top, .navbar-fixed-bottom, .navbar-static-top { margin-right: -20px; margin-left: -20px; } .container-fluid { padding: 0; } .dl-horizontal dt { float: none; width: auto; clear: none; text-align: left; } .dl-horizontal dd { margin-left: 0; } .container { width: auto; } .row-fluid { width: 100%; } .row, .thumbnails { margin-left: 0; } .thumbnails > li { float: none; margin-left: 0; } [class*="span"], .uneditable-input[class*="span"], .row-fluid [class*="span"] { display: block; float: none; width: 100%; margin-left: 0; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .span12, .row-fluid .span12 { width: 100%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .row-fluid [class*="offset"]:first-child { margin-left: 0; } .input-large, .input-xlarge, .input-xxlarge, input[class*="span"], select[class*="span"], textarea[class*="span"], .uneditable-input { display: block; width: 100%; min-height: 30px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .input-prepend input, .input-append input, .input-prepend input[class*="span"], .input-append input[class*="span"] { display: inline-block; width: auto; } .controls-row [class*="span"] + [class*="span"] { margin-left: 0; } .modal { position: fixed; top: 20px; right: 20px; left: 20px; width: auto; margin: 0; } .modal.fade { top: -100px; } .modal.fade.in { top: 20px; } } @media (max-width: 480px) { .nav-collapse { -webkit-transform: translate3d(0, 0, 0); } .page-header h1 small { display: block; line-height: 20px; } input[type="checkbox"], input[type="radio"] { border: 1px solid #ccc; } .form-horizontal .control-label { float: none; width: auto; padding-top: 0; text-align: left; } .form-horizontal .controls { margin-left: 0; } .form-horizontal .control-list { padding-top: 0; } .form-horizontal .form-actions { padding-right: 10px; padding-left: 10px; } .media .pull-left, .media .pull-right { display: block; float: none; margin-bottom: 10px; } .media-object { margin-right: 0; margin-left: 0; } .modal { top: 10px; right: 10px; left: 10px; } .modal-header .close { padding: 10px; margin: -10px; } .carousel-caption { position: static; } } @media (max-width: 979px) { body { padding-top: 0; } .navbar-fixed-top, .navbar-fixed-bottom { position: static; } .navbar-fixed-top { margin-bottom: 20px; } .navbar-fixed-bottom { margin-top: 20px; } .navbar-fixed-top .navbar-inner, .navbar-fixed-bottom .navbar-inner { padding: 5px; } .navbar .container { width: auto; padding: 0; } .navbar .brand { padding-right: 10px; padding-left: 10px; margin: 0 0 0 -5px; } .nav-collapse { clear: both; } .nav-collapse .nav { float: none; margin: 0 0 10px; } .nav-collapse .nav > li { float: none; } .nav-collapse .nav > li > a { margin-bottom: 2px; } .nav-collapse .nav > .divider-vertical { display: none; } .nav-collapse .nav .nav-header { color: #777777; text-shadow: none; } .nav-collapse .nav > li > a, .nav-collapse .dropdown-menu a { padding: 9px 15px; font-weight: bold; color: #777777; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } .nav-collapse .btn { padding: 4px 10px 4px; font-weight: normal; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .nav-collapse .dropdown-menu li + li a { margin-bottom: 2px; } .nav-collapse .nav > li > a:hover, .nav-collapse .nav > li > a:focus, .nav-collapse .dropdown-menu a:hover, .nav-collapse .dropdown-menu a:focus { background-color: #f2f2f2; } .navbar-inverse .nav-collapse .nav > li > a, .navbar-inverse .nav-collapse .dropdown-menu a { color: #999999; } .navbar-inverse .nav-collapse .nav > li > a:hover, .navbar-inverse .nav-collapse .nav > li > a:focus, .navbar-inverse .nav-collapse .dropdown-menu a:hover, .navbar-inverse .nav-collapse .dropdown-menu a:focus { background-color: #111111; } .nav-collapse.in .btn-group { padding: 0; margin-top: 5px; } .nav-collapse .dropdown-menu { position: static; top: auto; left: auto; display: none; float: none; max-width: none; padding: 0; margin: 0 15px; background-color: transparent; border: none; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } .nav-collapse .open > .dropdown-menu { display: block; } .nav-collapse .dropdown-menu:before, .nav-collapse .dropdown-menu:after { display: none; } .nav-collapse .dropdown-menu .divider { display: none; } .nav-collapse .nav > li > .dropdown-menu:before, .nav-collapse .nav > li > .dropdown-menu:after { display: none; } .nav-collapse .navbar-form, .nav-collapse .navbar-search { float: none; padding: 10px 15px; margin: 10px 0; border-top: 1px solid #f2f2f2; border-bottom: 1px solid #f2f2f2; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); } .navbar-inverse .nav-collapse .navbar-form, .navbar-inverse .nav-collapse .navbar-search { border-top-color: #111111; border-bottom-color: #111111; } .navbar .nav-collapse .nav.pull-right { float: none; margin-left: 0; } .nav-collapse, .nav-collapse.collapse { height: 0; overflow: hidden; } .navbar .btn-navbar { display: block; } .navbar-static .navbar-inner { padding-right: 10px; padding-left: 10px; } } @media (min-width: 980px) { .nav-collapse.collapse { height: auto !important; overflow: visible !important; } } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/vendor/css/bootstrap.css ================================================ /*! * Bootstrap v2.3.1 * * Copyright 2012 Twitter, Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world @twitter by @mdo and @fat. */ .clearfix { *zoom: 1; } .clearfix:before, .clearfix:after { display: table; line-height: 0; content: ""; } .clearfix:after { clear: both; } .hide-text { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } .input-block-level { display: block; width: 100%; min-height: 30px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; } audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; } audio:not([controls]) { display: none; } html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } a:focus { outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } a:hover, a:active { outline: 0; } sub, sup { position: relative; font-size: 75%; line-height: 0; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } img { width: auto\9; height: auto; max-width: 100%; vertical-align: middle; border: 0; -ms-interpolation-mode: bicubic; } #map_canvas img, .google-maps img { max-width: none; } button, input, select, textarea { margin: 0; font-size: 100%; vertical-align: middle; } button, input { *overflow: visible; line-height: normal; } button::-moz-focus-inner, input::-moz-focus-inner { padding: 0; border: 0; } button, html input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; } label, select, button, input[type="button"], input[type="reset"], input[type="submit"], input[type="radio"], input[type="checkbox"] { cursor: pointer; } input[type="search"] { -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; -webkit-appearance: textfield; } input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; } textarea { overflow: auto; vertical-align: top; } @media print { * { color: #000 !important; text-shadow: none !important; background: transparent !important; box-shadow: none !important; } a, a:visited { text-decoration: underline; } a[href]:after { content: " (" attr(href) ")"; } abbr[title]:after { content: " (" attr(title) ")"; } .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } thead { display: table-header-group; } tr, img { page-break-inside: avoid; } img { max-width: 100% !important; } @page { margin: 0.5cm; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } } body { margin: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; color: #333333; background-color: #ffffff; } a { color: #0088cc; text-decoration: none; } a:hover, a:focus { color: #005580; text-decoration: underline; } .img-rounded { -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; } .img-polaroid { padding: 4px; background-color: #fff; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); } .img-circle { -webkit-border-radius: 500px; -moz-border-radius: 500px; border-radius: 500px; } .row { margin-left: -20px; *zoom: 1; } .row:before, .row:after { display: table; line-height: 0; content: ""; } .row:after { clear: both; } [class*="span"] { float: left; min-height: 1px; margin-left: 20px; } .container, .navbar-static-top .container, .navbar-fixed-top .container, .navbar-fixed-bottom .container { width: 940px; } .span12 { width: 940px; } .span11 { width: 860px; } .span10 { width: 780px; } .span9 { width: 700px; } .span8 { width: 620px; } .span7 { width: 540px; } .span6 { width: 460px; } .span5 { width: 380px; } .span4 { width: 300px; } .span3 { width: 220px; } .span2 { width: 140px; } .span1 { width: 60px; } .offset12 { margin-left: 980px; } .offset11 { margin-left: 900px; } .offset10 { margin-left: 820px; } .offset9 { margin-left: 740px; } .offset8 { margin-left: 660px; } .offset7 { margin-left: 580px; } .offset6 { margin-left: 500px; } .offset5 { margin-left: 420px; } .offset4 { margin-left: 340px; } .offset3 { margin-left: 260px; } .offset2 { margin-left: 180px; } .offset1 { margin-left: 100px; } .row-fluid { width: 100%; *zoom: 1; } .row-fluid:before, .row-fluid:after { display: table; line-height: 0; content: ""; } .row-fluid:after { clear: both; } .row-fluid [class*="span"] { display: block; float: left; width: 100%; min-height: 30px; margin-left: 2.127659574468085%; *margin-left: 2.074468085106383%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .row-fluid [class*="span"]:first-child { margin-left: 0; } .row-fluid .controls-row [class*="span"] + [class*="span"] { margin-left: 2.127659574468085%; } .row-fluid .span12 { width: 100%; *width: 99.94680851063829%; } .row-fluid .span11 { width: 91.48936170212765%; *width: 91.43617021276594%; } .row-fluid .span10 { width: 82.97872340425532%; *width: 82.92553191489361%; } .row-fluid .span9 { width: 74.46808510638297%; *width: 74.41489361702126%; } .row-fluid .span8 { width: 65.95744680851064%; *width: 65.90425531914893%; } .row-fluid .span7 { width: 57.44680851063829%; *width: 57.39361702127659%; } .row-fluid .span6 { width: 48.93617021276595%; *width: 48.88297872340425%; } .row-fluid .span5 { width: 40.42553191489362%; *width: 40.37234042553192%; } .row-fluid .span4 { width: 31.914893617021278%; *width: 31.861702127659576%; } .row-fluid .span3 { width: 23.404255319148934%; *width: 23.351063829787233%; } .row-fluid .span2 { width: 14.893617021276595%; *width: 14.840425531914894%; } .row-fluid .span1 { width: 6.382978723404255%; *width: 6.329787234042553%; } .row-fluid .offset12 { margin-left: 104.25531914893617%; *margin-left: 104.14893617021275%; } .row-fluid .offset12:first-child { margin-left: 102.12765957446808%; *margin-left: 102.02127659574467%; } .row-fluid .offset11 { margin-left: 95.74468085106382%; *margin-left: 95.6382978723404%; } .row-fluid .offset11:first-child { margin-left: 93.61702127659574%; *margin-left: 93.51063829787232%; } .row-fluid .offset10 { margin-left: 87.23404255319149%; *margin-left: 87.12765957446807%; } .row-fluid .offset10:first-child { margin-left: 85.1063829787234%; *margin-left: 84.99999999999999%; } .row-fluid .offset9 { margin-left: 78.72340425531914%; *margin-left: 78.61702127659572%; } .row-fluid .offset9:first-child { margin-left: 76.59574468085106%; *margin-left: 76.48936170212764%; } .row-fluid .offset8 { margin-left: 70.2127659574468%; *margin-left: 70.10638297872339%; } .row-fluid .offset8:first-child { margin-left: 68.08510638297872%; *margin-left: 67.9787234042553%; } .row-fluid .offset7 { margin-left: 61.70212765957446%; *margin-left: 61.59574468085106%; } .row-fluid .offset7:first-child { margin-left: 59.574468085106375%; *margin-left: 59.46808510638297%; } .row-fluid .offset6 { margin-left: 53.191489361702125%; *margin-left: 53.085106382978715%; } .row-fluid .offset6:first-child { margin-left: 51.063829787234035%; *margin-left: 50.95744680851063%; } .row-fluid .offset5 { margin-left: 44.68085106382979%; *margin-left: 44.57446808510638%; } .row-fluid .offset5:first-child { margin-left: 42.5531914893617%; *margin-left: 42.4468085106383%; } .row-fluid .offset4 { margin-left: 36.170212765957444%; *margin-left: 36.06382978723405%; } .row-fluid .offset4:first-child { margin-left: 34.04255319148936%; *margin-left: 33.93617021276596%; } .row-fluid .offset3 { margin-left: 27.659574468085104%; *margin-left: 27.5531914893617%; } .row-fluid .offset3:first-child { margin-left: 25.53191489361702%; *margin-left: 25.425531914893618%; } .row-fluid .offset2 { margin-left: 19.148936170212764%; *margin-left: 19.04255319148936%; } .row-fluid .offset2:first-child { margin-left: 17.02127659574468%; *margin-left: 16.914893617021278%; } .row-fluid .offset1 { margin-left: 10.638297872340425%; *margin-left: 10.53191489361702%; } .row-fluid .offset1:first-child { margin-left: 8.51063829787234%; *margin-left: 8.404255319148938%; } [class*="span"].hide, .row-fluid [class*="span"].hide { display: none; } [class*="span"].pull-right, .row-fluid [class*="span"].pull-right { float: right; } .container { margin-right: auto; margin-left: auto; *zoom: 1; } .container:before, .container:after { display: table; line-height: 0; content: ""; } .container:after { clear: both; } .container-fluid { padding-right: 20px; padding-left: 20px; *zoom: 1; } .container-fluid:before, .container-fluid:after { display: table; line-height: 0; content: ""; } .container-fluid:after { clear: both; } p { margin: 0 0 10px; } .lead { margin-bottom: 20px; font-size: 21px; font-weight: 200; line-height: 30px; } small { font-size: 85%; } strong { font-weight: bold; } em { font-style: italic; } cite { font-style: normal; } .muted { color: #999999; } a.muted:hover, a.muted:focus { color: #808080; } .text-warning { color: #c09853; } a.text-warning:hover, a.text-warning:focus { color: #a47e3c; } .text-error { color: #b94a48; } a.text-error:hover, a.text-error:focus { color: #953b39; } .text-info { color: #3a87ad; } a.text-info:hover, a.text-info:focus { color: #2d6987; } .text-success { color: #468847; } a.text-success:hover, a.text-success:focus { color: #356635; } .text-left { text-align: left; } .text-right { text-align: right; } .text-center { text-align: center; } h1, h2, h3, h4, h5, h6 { margin: 10px 0; font-family: inherit; font-weight: bold; line-height: 20px; color: inherit; text-rendering: optimizelegibility; } h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-weight: normal; line-height: 1; color: #999999; } h1, h2, h3 { line-height: 40px; } h1 { font-size: 38.5px; } h2 { font-size: 31.5px; } h3 { font-size: 24.5px; } h4 { font-size: 17.5px; } h5 { font-size: 14px; } h6 { font-size: 11.9px; } h1 small { font-size: 24.5px; } h2 small { font-size: 17.5px; } h3 small { font-size: 14px; } h4 small { font-size: 14px; } .page-header { padding-bottom: 9px; margin: 20px 0 30px; border-bottom: 1px solid #eeeeee; } ul, ol { padding: 0; margin: 0 0 10px 25px; } ul ul, ul ol, ol ol, ol ul { margin-bottom: 0; } li { line-height: 20px; } ul.unstyled, ol.unstyled { margin-left: 0; list-style: none; } ul.inline, ol.inline { margin-left: 0; list-style: none; } ul.inline > li, ol.inline > li { display: inline-block; *display: inline; padding-right: 5px; padding-left: 5px; *zoom: 1; } dl { margin-bottom: 20px; } dt, dd { line-height: 20px; } dt { font-weight: bold; } dd { margin-left: 10px; } .dl-horizontal { *zoom: 1; } .dl-horizontal:before, .dl-horizontal:after { display: table; line-height: 0; content: ""; } .dl-horizontal:after { clear: both; } .dl-horizontal dt { float: left; width: 160px; overflow: hidden; clear: left; text-align: right; text-overflow: ellipsis; white-space: nowrap; } .dl-horizontal dd { margin-left: 180px; } hr { margin: 20px 0; border: 0; border-top: 1px solid #eeeeee; border-bottom: 1px solid #ffffff; } abbr[title], abbr[data-original-title] { cursor: help; border-bottom: 1px dotted #999999; } abbr.initialism { font-size: 90%; text-transform: uppercase; } blockquote { padding: 0 0 0 15px; margin: 0 0 20px; border-left: 5px solid #eeeeee; } blockquote p { margin-bottom: 0; font-size: 17.5px; font-weight: 300; line-height: 1.25; } blockquote small { display: block; line-height: 20px; color: #999999; } blockquote small:before { content: '\2014 \00A0'; } blockquote.pull-right { float: right; padding-right: 15px; padding-left: 0; border-right: 5px solid #eeeeee; border-left: 0; } blockquote.pull-right p, blockquote.pull-right small { text-align: right; } blockquote.pull-right small:before { content: ''; } blockquote.pull-right small:after { content: '\00A0 \2014'; } q:before, q:after, blockquote:before, blockquote:after { content: ""; } address { display: block; margin-bottom: 20px; font-style: normal; line-height: 20px; } code, pre { padding: 0 3px 2px; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: #333333; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } code { padding: 2px 4px; color: #d14; white-space: nowrap; background-color: #f7f7f9; border: 1px solid #e1e1e8; } pre { display: block; padding: 9.5px; margin: 0 0 10px; font-size: 13px; line-height: 20px; word-break: break-all; word-wrap: break-word; white-space: pre; white-space: pre-wrap; background-color: #f5f5f5; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.15); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } pre.prettyprint { margin-bottom: 20px; } pre code { padding: 0; color: inherit; white-space: pre; white-space: pre-wrap; background-color: transparent; border: 0; } .pre-scrollable { max-height: 340px; overflow-y: scroll; } form { margin: 0 0 20px; } fieldset { padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; padding: 0; margin-bottom: 20px; font-size: 21px; line-height: 40px; color: #333333; border: 0; border-bottom: 1px solid #e5e5e5; } legend small { font-size: 15px; color: #999999; } label, input, button, select, textarea { font-size: 14px; font-weight: normal; line-height: 20px; } input, button, select, textarea { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } label { display: block; margin-bottom: 5px; } select, textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], .uneditable-input { display: inline-block; height: 20px; padding: 4px 6px; margin-bottom: 10px; font-size: 14px; line-height: 20px; color: #555555; vertical-align: middle; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } input, textarea, .uneditable-input { width: 206px; } textarea { height: auto; } textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], .uneditable-input { background-color: #ffffff; border: 1px solid #cccccc; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; -moz-transition: border linear 0.2s, box-shadow linear 0.2s; -o-transition: border linear 0.2s, box-shadow linear 0.2s; transition: border linear 0.2s, box-shadow linear 0.2s; } textarea:focus, input[type="text"]:focus, input[type="password"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="date"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, input[type="number"]:focus, input[type="email"]:focus, input[type="url"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="color"]:focus, .uneditable-input:focus { border-color: rgba(82, 168, 236, 0.8); outline: 0; outline: thin dotted \9; /* IE6-9 */ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6); } input[type="radio"], input[type="checkbox"] { margin: 4px 0 0; margin-top: 1px \9; *margin-top: 0; line-height: normal; } input[type="file"], input[type="image"], input[type="submit"], input[type="reset"], input[type="button"], input[type="radio"], input[type="checkbox"] { width: auto; } select, input[type="file"] { height: 30px; /* In IE7, the height of the select element cannot be changed by height, only font-size */ *margin-top: 4px; /* For IE7, add top margin to align select with labels */ line-height: 30px; } select { width: 220px; background-color: #ffffff; border: 1px solid #cccccc; } select[multiple], select[size] { height: auto; } select:focus, input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } .uneditable-input, .uneditable-textarea { color: #999999; cursor: not-allowed; background-color: #fcfcfc; border-color: #cccccc; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); } .uneditable-input { overflow: hidden; white-space: nowrap; } .uneditable-textarea { width: auto; height: auto; } input:-moz-placeholder, textarea:-moz-placeholder { color: #999999; } input:-ms-input-placeholder, textarea:-ms-input-placeholder { color: #999999; } input::-webkit-input-placeholder, textarea::-webkit-input-placeholder { color: #999999; } .radio, .checkbox { min-height: 20px; padding-left: 20px; } .radio input[type="radio"], .checkbox input[type="checkbox"] { float: left; margin-left: -20px; } .controls > .radio:first-child, .controls > .checkbox:first-child { padding-top: 5px; } .radio.inline, .checkbox.inline { display: inline-block; padding-top: 5px; margin-bottom: 0; vertical-align: middle; } .radio.inline + .radio.inline, .checkbox.inline + .checkbox.inline { margin-left: 10px; } .input-mini { width: 60px; } .input-small { width: 90px; } .input-medium { width: 150px; } .input-large { width: 210px; } .input-xlarge { width: 270px; } .input-xxlarge { width: 530px; } input[class*="span"], select[class*="span"], textarea[class*="span"], .uneditable-input[class*="span"], .row-fluid input[class*="span"], .row-fluid select[class*="span"], .row-fluid textarea[class*="span"], .row-fluid .uneditable-input[class*="span"] { float: none; margin-left: 0; } .input-append input[class*="span"], .input-append .uneditable-input[class*="span"], .input-prepend input[class*="span"], .input-prepend .uneditable-input[class*="span"], .row-fluid input[class*="span"], .row-fluid select[class*="span"], .row-fluid textarea[class*="span"], .row-fluid .uneditable-input[class*="span"], .row-fluid .input-prepend [class*="span"], .row-fluid .input-append [class*="span"] { display: inline-block; } input, textarea, .uneditable-input { margin-left: 0; } .controls-row [class*="span"] + [class*="span"] { margin-left: 20px; } input.span12, textarea.span12, .uneditable-input.span12 { width: 926px; } input.span11, textarea.span11, .uneditable-input.span11 { width: 846px; } input.span10, textarea.span10, .uneditable-input.span10 { width: 766px; } input.span9, textarea.span9, .uneditable-input.span9 { width: 686px; } input.span8, textarea.span8, .uneditable-input.span8 { width: 606px; } input.span7, textarea.span7, .uneditable-input.span7 { width: 526px; } input.span6, textarea.span6, .uneditable-input.span6 { width: 446px; } input.span5, textarea.span5, .uneditable-input.span5 { width: 366px; } input.span4, textarea.span4, .uneditable-input.span4 { width: 286px; } input.span3, textarea.span3, .uneditable-input.span3 { width: 206px; } input.span2, textarea.span2, .uneditable-input.span2 { width: 126px; } input.span1, textarea.span1, .uneditable-input.span1 { width: 46px; } .controls-row { *zoom: 1; } .controls-row:before, .controls-row:after { display: table; line-height: 0; content: ""; } .controls-row:after { clear: both; } .controls-row [class*="span"], .row-fluid .controls-row [class*="span"] { float: left; } .controls-row .checkbox[class*="span"], .controls-row .radio[class*="span"] { padding-top: 5px; } input[disabled], select[disabled], textarea[disabled], input[readonly], select[readonly], textarea[readonly] { cursor: not-allowed; background-color: #eeeeee; } input[type="radio"][disabled], input[type="checkbox"][disabled], input[type="radio"][readonly], input[type="checkbox"][readonly] { background-color: transparent; } .control-group.warning .control-label, .control-group.warning .help-block, .control-group.warning .help-inline { color: #c09853; } .control-group.warning .checkbox, .control-group.warning .radio, .control-group.warning input, .control-group.warning select, .control-group.warning textarea { color: #c09853; } .control-group.warning input, .control-group.warning select, .control-group.warning textarea { border-color: #c09853; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .control-group.warning input:focus, .control-group.warning select:focus, .control-group.warning textarea:focus { border-color: #a47e3c; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; } .control-group.warning .input-prepend .add-on, .control-group.warning .input-append .add-on { color: #c09853; background-color: #fcf8e3; border-color: #c09853; } .control-group.error .control-label, .control-group.error .help-block, .control-group.error .help-inline { color: #b94a48; } .control-group.error .checkbox, .control-group.error .radio, .control-group.error input, .control-group.error select, .control-group.error textarea { color: #b94a48; } .control-group.error input, .control-group.error select, .control-group.error textarea { border-color: #b94a48; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .control-group.error input:focus, .control-group.error select:focus, .control-group.error textarea:focus { border-color: #953b39; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; } .control-group.error .input-prepend .add-on, .control-group.error .input-append .add-on { color: #b94a48; background-color: #f2dede; border-color: #b94a48; } .control-group.success .control-label, .control-group.success .help-block, .control-group.success .help-inline { color: #468847; } .control-group.success .checkbox, .control-group.success .radio, .control-group.success input, .control-group.success select, .control-group.success textarea { color: #468847; } .control-group.success input, .control-group.success select, .control-group.success textarea { border-color: #468847; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .control-group.success input:focus, .control-group.success select:focus, .control-group.success textarea:focus { border-color: #356635; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; } .control-group.success .input-prepend .add-on, .control-group.success .input-append .add-on { color: #468847; background-color: #dff0d8; border-color: #468847; } .control-group.info .control-label, .control-group.info .help-block, .control-group.info .help-inline { color: #3a87ad; } .control-group.info .checkbox, .control-group.info .radio, .control-group.info input, .control-group.info select, .control-group.info textarea { color: #3a87ad; } .control-group.info input, .control-group.info select, .control-group.info textarea { border-color: #3a87ad; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); } .control-group.info input:focus, .control-group.info select:focus, .control-group.info textarea:focus { border-color: #2d6987; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3; } .control-group.info .input-prepend .add-on, .control-group.info .input-append .add-on { color: #3a87ad; background-color: #d9edf7; border-color: #3a87ad; } input:focus:invalid, textarea:focus:invalid, select:focus:invalid { color: #b94a48; border-color: #ee5f5b; } input:focus:invalid:focus, textarea:focus:invalid:focus, select:focus:invalid:focus { border-color: #e9322d; -webkit-box-shadow: 0 0 6px #f8b9b7; -moz-box-shadow: 0 0 6px #f8b9b7; box-shadow: 0 0 6px #f8b9b7; } .form-actions { padding: 19px 20px 20px; margin-top: 20px; margin-bottom: 20px; background-color: #f5f5f5; border-top: 1px solid #e5e5e5; *zoom: 1; } .form-actions:before, .form-actions:after { display: table; line-height: 0; content: ""; } .form-actions:after { clear: both; } .help-block, .help-inline { color: #595959; } .help-block { display: block; margin-bottom: 10px; } .help-inline { display: inline-block; *display: inline; padding-left: 5px; vertical-align: middle; *zoom: 1; } .input-append, .input-prepend { display: inline-block; margin-bottom: 10px; font-size: 0; white-space: nowrap; vertical-align: middle; } .input-append input, .input-prepend input, .input-append select, .input-prepend select, .input-append .uneditable-input, .input-prepend .uneditable-input, .input-append .dropdown-menu, .input-prepend .dropdown-menu, .input-append .popover, .input-prepend .popover { font-size: 14px; } .input-append input, .input-prepend input, .input-append select, .input-prepend select, .input-append .uneditable-input, .input-prepend .uneditable-input { position: relative; margin-bottom: 0; *margin-left: 0; vertical-align: top; -webkit-border-radius: 0 4px 4px 0; -moz-border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0; } .input-append input:focus, .input-prepend input:focus, .input-append select:focus, .input-prepend select:focus, .input-append .uneditable-input:focus, .input-prepend .uneditable-input:focus { z-index: 2; } .input-append .add-on, .input-prepend .add-on { display: inline-block; width: auto; height: 20px; min-width: 16px; padding: 4px 5px; font-size: 14px; font-weight: normal; line-height: 20px; text-align: center; text-shadow: 0 1px 0 #ffffff; background-color: #eeeeee; border: 1px solid #ccc; } .input-append .add-on, .input-prepend .add-on, .input-append .btn, .input-prepend .btn, .input-append .btn-group > .dropdown-toggle, .input-prepend .btn-group > .dropdown-toggle { vertical-align: top; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .input-append .active, .input-prepend .active { background-color: #a9dba9; border-color: #46a546; } .input-prepend .add-on, .input-prepend .btn { margin-right: -1px; } .input-prepend .add-on:first-child, .input-prepend .btn:first-child { -webkit-border-radius: 4px 0 0 4px; -moz-border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px; } .input-append input, .input-append select, .input-append .uneditable-input { -webkit-border-radius: 4px 0 0 4px; -moz-border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px; } .input-append input + .btn-group .btn:last-child, .input-append select + .btn-group .btn:last-child, .input-append .uneditable-input + .btn-group .btn:last-child { -webkit-border-radius: 0 4px 4px 0; -moz-border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0; } .input-append .add-on, .input-append .btn, .input-append .btn-group { margin-left: -1px; } .input-append .add-on:last-child, .input-append .btn:last-child, .input-append .btn-group:last-child > .dropdown-toggle { -webkit-border-radius: 0 4px 4px 0; -moz-border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0; } .input-prepend.input-append input, .input-prepend.input-append select, .input-prepend.input-append .uneditable-input { -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .input-prepend.input-append input + .btn-group .btn, .input-prepend.input-append select + .btn-group .btn, .input-prepend.input-append .uneditable-input + .btn-group .btn { -webkit-border-radius: 0 4px 4px 0; -moz-border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0; } .input-prepend.input-append .add-on:first-child, .input-prepend.input-append .btn:first-child { margin-right: -1px; -webkit-border-radius: 4px 0 0 4px; -moz-border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px; } .input-prepend.input-append .add-on:last-child, .input-prepend.input-append .btn:last-child { margin-left: -1px; -webkit-border-radius: 0 4px 4px 0; -moz-border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0; } .input-prepend.input-append .btn-group:first-child { margin-left: 0; } input.search-query { padding-right: 14px; padding-right: 4px \9; padding-left: 14px; padding-left: 4px \9; /* IE7-8 doesn't have border-radius, so don't indent the padding */ margin-bottom: 0; -webkit-border-radius: 15px; -moz-border-radius: 15px; border-radius: 15px; } /* Allow for input prepend/append in search forms */ .form-search .input-append .search-query, .form-search .input-prepend .search-query { -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .form-search .input-append .search-query { -webkit-border-radius: 14px 0 0 14px; -moz-border-radius: 14px 0 0 14px; border-radius: 14px 0 0 14px; } .form-search .input-append .btn { -webkit-border-radius: 0 14px 14px 0; -moz-border-radius: 0 14px 14px 0; border-radius: 0 14px 14px 0; } .form-search .input-prepend .search-query { -webkit-border-radius: 0 14px 14px 0; -moz-border-radius: 0 14px 14px 0; border-radius: 0 14px 14px 0; } .form-search .input-prepend .btn { -webkit-border-radius: 14px 0 0 14px; -moz-border-radius: 14px 0 0 14px; border-radius: 14px 0 0 14px; } .form-search input, .form-inline input, .form-horizontal input, .form-search textarea, .form-inline textarea, .form-horizontal textarea, .form-search select, .form-inline select, .form-horizontal select, .form-search .help-inline, .form-inline .help-inline, .form-horizontal .help-inline, .form-search .uneditable-input, .form-inline .uneditable-input, .form-horizontal .uneditable-input, .form-search .input-prepend, .form-inline .input-prepend, .form-horizontal .input-prepend, .form-search .input-append, .form-inline .input-append, .form-horizontal .input-append { display: inline-block; *display: inline; margin-bottom: 0; vertical-align: middle; *zoom: 1; } .form-search .hide, .form-inline .hide, .form-horizontal .hide { display: none; } .form-search label, .form-inline label, .form-search .btn-group, .form-inline .btn-group { display: inline-block; } .form-search .input-append, .form-inline .input-append, .form-search .input-prepend, .form-inline .input-prepend { margin-bottom: 0; } .form-search .radio, .form-search .checkbox, .form-inline .radio, .form-inline .checkbox { padding-left: 0; margin-bottom: 0; vertical-align: middle; } .form-search .radio input[type="radio"], .form-search .checkbox input[type="checkbox"], .form-inline .radio input[type="radio"], .form-inline .checkbox input[type="checkbox"] { float: left; margin-right: 3px; margin-left: 0; } .control-group { margin-bottom: 10px; } legend + .control-group { margin-top: 20px; -webkit-margin-top-collapse: separate; } .form-horizontal .control-group { margin-bottom: 20px; *zoom: 1; } .form-horizontal .control-group:before, .form-horizontal .control-group:after { display: table; line-height: 0; content: ""; } .form-horizontal .control-group:after { clear: both; } .form-horizontal .control-label { float: left; width: 160px; padding-top: 5px; text-align: right; } .form-horizontal .controls { *display: inline-block; *padding-left: 20px; margin-left: 180px; *margin-left: 0; } .form-horizontal .controls:first-child { *padding-left: 180px; } .form-horizontal .help-block { margin-bottom: 0; } .form-horizontal input + .help-block, .form-horizontal select + .help-block, .form-horizontal textarea + .help-block, .form-horizontal .uneditable-input + .help-block, .form-horizontal .input-prepend + .help-block, .form-horizontal .input-append + .help-block { margin-top: 10px; } .form-horizontal .form-actions { padding-left: 180px; } table { max-width: 100%; background-color: transparent; border-collapse: collapse; border-spacing: 0; } .table { width: 100%; margin-bottom: 20px; } .table th, .table td { padding: 8px; line-height: 20px; text-align: left; vertical-align: top; border-top: 1px solid #dddddd; } .table th { font-weight: bold; } .table thead th { vertical-align: bottom; } .table caption + thead tr:first-child th, .table caption + thead tr:first-child td, .table colgroup + thead tr:first-child th, .table colgroup + thead tr:first-child td, .table thead:first-child tr:first-child th, .table thead:first-child tr:first-child td { border-top: 0; } .table tbody + tbody { border-top: 2px solid #dddddd; } .table .table { background-color: #ffffff; } .table-condensed th, .table-condensed td { padding: 4px 5px; } .table-bordered { border: 1px solid #dddddd; border-collapse: separate; *border-collapse: collapse; border-left: 0; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .table-bordered th, .table-bordered td { border-left: 1px solid #dddddd; } .table-bordered caption + thead tr:first-child th, .table-bordered caption + tbody tr:first-child th, .table-bordered caption + tbody tr:first-child td, .table-bordered colgroup + thead tr:first-child th, .table-bordered colgroup + tbody tr:first-child th, .table-bordered colgroup + tbody tr:first-child td, .table-bordered thead:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child td { border-top: 0; } .table-bordered thead:first-child tr:first-child > th:first-child, .table-bordered tbody:first-child tr:first-child > td:first-child, .table-bordered tbody:first-child tr:first-child > th:first-child { -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topleft: 4px; } .table-bordered thead:first-child tr:first-child > th:last-child, .table-bordered tbody:first-child tr:first-child > td:last-child, .table-bordered tbody:first-child tr:first-child > th:last-child { -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-topright: 4px; } .table-bordered thead:last-child tr:last-child > th:first-child, .table-bordered tbody:last-child tr:last-child > td:first-child, .table-bordered tbody:last-child tr:last-child > th:first-child, .table-bordered tfoot:last-child tr:last-child > td:first-child, .table-bordered tfoot:last-child tr:last-child > th:first-child { -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomleft: 4px; } .table-bordered thead:last-child tr:last-child > th:last-child, .table-bordered tbody:last-child tr:last-child > td:last-child, .table-bordered tbody:last-child tr:last-child > th:last-child, .table-bordered tfoot:last-child tr:last-child > td:last-child, .table-bordered tfoot:last-child tr:last-child > th:last-child { -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; -moz-border-radius-bottomright: 4px; } .table-bordered tfoot + tbody:last-child tr:last-child td:first-child { -webkit-border-bottom-left-radius: 0; border-bottom-left-radius: 0; -moz-border-radius-bottomleft: 0; } .table-bordered tfoot + tbody:last-child tr:last-child td:last-child { -webkit-border-bottom-right-radius: 0; border-bottom-right-radius: 0; -moz-border-radius-bottomright: 0; } .table-bordered caption + thead tr:first-child th:first-child, .table-bordered caption + tbody tr:first-child td:first-child, .table-bordered colgroup + thead tr:first-child th:first-child, .table-bordered colgroup + tbody tr:first-child td:first-child { -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topleft: 4px; } .table-bordered caption + thead tr:first-child th:last-child, .table-bordered caption + tbody tr:first-child td:last-child, .table-bordered colgroup + thead tr:first-child th:last-child, .table-bordered colgroup + tbody tr:first-child td:last-child { -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-topright: 4px; } .table-striped tbody > tr:nth-child(odd) > td, .table-striped tbody > tr:nth-child(odd) > th { background-color: #f9f9f9; } .table-hover tbody tr:hover > td, .table-hover tbody tr:hover > th { background-color: #f5f5f5; } table td[class*="span"], table th[class*="span"], .row-fluid table td[class*="span"], .row-fluid table th[class*="span"] { display: table-cell; float: none; margin-left: 0; } .table td.span1, .table th.span1 { float: none; width: 44px; margin-left: 0; } .table td.span2, .table th.span2 { float: none; width: 124px; margin-left: 0; } .table td.span3, .table th.span3 { float: none; width: 204px; margin-left: 0; } .table td.span4, .table th.span4 { float: none; width: 284px; margin-left: 0; } .table td.span5, .table th.span5 { float: none; width: 364px; margin-left: 0; } .table td.span6, .table th.span6 { float: none; width: 444px; margin-left: 0; } .table td.span7, .table th.span7 { float: none; width: 524px; margin-left: 0; } .table td.span8, .table th.span8 { float: none; width: 604px; margin-left: 0; } .table td.span9, .table th.span9 { float: none; width: 684px; margin-left: 0; } .table td.span10, .table th.span10 { float: none; width: 764px; margin-left: 0; } .table td.span11, .table th.span11 { float: none; width: 844px; margin-left: 0; } .table td.span12, .table th.span12 { float: none; width: 924px; margin-left: 0; } .table tbody tr.success > td { background-color: #dff0d8; } .table tbody tr.error > td { background-color: #f2dede; } .table tbody tr.warning > td { background-color: #fcf8e3; } .table tbody tr.info > td { background-color: #d9edf7; } .table-hover tbody tr.success:hover > td { background-color: #d0e9c6; } .table-hover tbody tr.error:hover > td { background-color: #ebcccc; } .table-hover tbody tr.warning:hover > td { background-color: #faf2cc; } .table-hover tbody tr.info:hover > td { background-color: #c4e3f3; } [class^="icon-"], [class*=" icon-"] { display: inline-block; width: 14px; height: 14px; margin-top: 1px; *margin-right: .3em; line-height: 14px; vertical-align: text-top; background-image: url("../img/glyphicons-halflings.png"); background-position: 14px 14px; background-repeat: no-repeat; } /* White icons with optional class, or on hover/focus/active states of certain elements */ .icon-white, .nav-pills > .active > a > [class^="icon-"], .nav-pills > .active > a > [class*=" icon-"], .nav-list > .active > a > [class^="icon-"], .nav-list > .active > a > [class*=" icon-"], .navbar-inverse .nav > .active > a > [class^="icon-"], .navbar-inverse .nav > .active > a > [class*=" icon-"], .dropdown-menu > li > a:hover > [class^="icon-"], .dropdown-menu > li > a:focus > [class^="icon-"], .dropdown-menu > li > a:hover > [class*=" icon-"], .dropdown-menu > li > a:focus > [class*=" icon-"], .dropdown-menu > .active > a > [class^="icon-"], .dropdown-menu > .active > a > [class*=" icon-"], .dropdown-submenu:hover > a > [class^="icon-"], .dropdown-submenu:focus > a > [class^="icon-"], .dropdown-submenu:hover > a > [class*=" icon-"], .dropdown-submenu:focus > a > [class*=" icon-"] { background-image: url("../img/glyphicons-halflings-white.png"); } .icon-glass { background-position: 0 0; } .icon-music { background-position: -24px 0; } .icon-search { background-position: -48px 0; } .icon-envelope { background-position: -72px 0; } .icon-heart { background-position: -96px 0; } .icon-star { background-position: -120px 0; } .icon-star-empty { background-position: -144px 0; } .icon-user { background-position: -168px 0; } .icon-film { background-position: -192px 0; } .icon-th-large { background-position: -216px 0; } .icon-th { background-position: -240px 0; } .icon-th-list { background-position: -264px 0; } .icon-ok { background-position: -288px 0; } .icon-remove { background-position: -312px 0; } .icon-zoom-in { background-position: -336px 0; } .icon-zoom-out { background-position: -360px 0; } .icon-off { background-position: -384px 0; } .icon-signal { background-position: -408px 0; } .icon-cog { background-position: -432px 0; } .icon-trash { background-position: -456px 0; } .icon-home { background-position: 0 -24px; } .icon-file { background-position: -24px -24px; } .icon-time { background-position: -48px -24px; } .icon-road { background-position: -72px -24px; } .icon-download-alt { background-position: -96px -24px; } .icon-download { background-position: -120px -24px; } .icon-upload { background-position: -144px -24px; } .icon-inbox { background-position: -168px -24px; } .icon-play-circle { background-position: -192px -24px; } .icon-repeat { background-position: -216px -24px; } .icon-refresh { background-position: -240px -24px; } .icon-list-alt { background-position: -264px -24px; } .icon-lock { background-position: -287px -24px; } .icon-flag { background-position: -312px -24px; } .icon-headphones { background-position: -336px -24px; } .icon-volume-off { background-position: -360px -24px; } .icon-volume-down { background-position: -384px -24px; } .icon-volume-up { background-position: -408px -24px; } .icon-qrcode { background-position: -432px -24px; } .icon-barcode { background-position: -456px -24px; } .icon-tag { background-position: 0 -48px; } .icon-tags { background-position: -25px -48px; } .icon-book { background-position: -48px -48px; } .icon-bookmark { background-position: -72px -48px; } .icon-print { background-position: -96px -48px; } .icon-camera { background-position: -120px -48px; } .icon-font { background-position: -144px -48px; } .icon-bold { background-position: -167px -48px; } .icon-italic { background-position: -192px -48px; } .icon-text-height { background-position: -216px -48px; } .icon-text-width { background-position: -240px -48px; } .icon-align-left { background-position: -264px -48px; } .icon-align-center { background-position: -288px -48px; } .icon-align-right { background-position: -312px -48px; } .icon-align-justify { background-position: -336px -48px; } .icon-list { background-position: -360px -48px; } .icon-indent-left { background-position: -384px -48px; } .icon-indent-right { background-position: -408px -48px; } .icon-facetime-video { background-position: -432px -48px; } .icon-picture { background-position: -456px -48px; } .icon-pencil { background-position: 0 -72px; } .icon-map-marker { background-position: -24px -72px; } .icon-adjust { background-position: -48px -72px; } .icon-tint { background-position: -72px -72px; } .icon-edit { background-position: -96px -72px; } .icon-share { background-position: -120px -72px; } .icon-check { background-position: -144px -72px; } .icon-move { background-position: -168px -72px; } .icon-step-backward { background-position: -192px -72px; } .icon-fast-backward { background-position: -216px -72px; } .icon-backward { background-position: -240px -72px; } .icon-play { background-position: -264px -72px; } .icon-pause { background-position: -288px -72px; } .icon-stop { background-position: -312px -72px; } .icon-forward { background-position: -336px -72px; } .icon-fast-forward { background-position: -360px -72px; } .icon-step-forward { background-position: -384px -72px; } .icon-eject { background-position: -408px -72px; } .icon-chevron-left { background-position: -432px -72px; } .icon-chevron-right { background-position: -456px -72px; } .icon-plus-sign { background-position: 0 -96px; } .icon-minus-sign { background-position: -24px -96px; } .icon-remove-sign { background-position: -48px -96px; } .icon-ok-sign { background-position: -72px -96px; } .icon-question-sign { background-position: -96px -96px; } .icon-info-sign { background-position: -120px -96px; } .icon-screenshot { background-position: -144px -96px; } .icon-remove-circle { background-position: -168px -96px; } .icon-ok-circle { background-position: -192px -96px; } .icon-ban-circle { background-position: -216px -96px; } .icon-arrow-left { background-position: -240px -96px; } .icon-arrow-right { background-position: -264px -96px; } .icon-arrow-up { background-position: -289px -96px; } .icon-arrow-down { background-position: -312px -96px; } .icon-share-alt { background-position: -336px -96px; } .icon-resize-full { background-position: -360px -96px; } .icon-resize-small { background-position: -384px -96px; } .icon-plus { background-position: -408px -96px; } .icon-minus { background-position: -433px -96px; } .icon-asterisk { background-position: -456px -96px; } .icon-exclamation-sign { background-position: 0 -120px; } .icon-gift { background-position: -24px -120px; } .icon-leaf { background-position: -48px -120px; } .icon-fire { background-position: -72px -120px; } .icon-eye-open { background-position: -96px -120px; } .icon-eye-close { background-position: -120px -120px; } .icon-warning-sign { background-position: -144px -120px; } .icon-plane { background-position: -168px -120px; } .icon-calendar { background-position: -192px -120px; } .icon-random { width: 16px; background-position: -216px -120px; } .icon-comment { background-position: -240px -120px; } .icon-magnet { background-position: -264px -120px; } .icon-chevron-up { background-position: -288px -120px; } .icon-chevron-down { background-position: -313px -119px; } .icon-retweet { background-position: -336px -120px; } .icon-shopping-cart { background-position: -360px -120px; } .icon-folder-close { width: 16px; background-position: -384px -120px; } .icon-folder-open { width: 16px; background-position: -408px -120px; } .icon-resize-vertical { background-position: -432px -119px; } .icon-resize-horizontal { background-position: -456px -118px; } .icon-hdd { background-position: 0 -144px; } .icon-bullhorn { background-position: -24px -144px; } .icon-bell { background-position: -48px -144px; } .icon-certificate { background-position: -72px -144px; } .icon-thumbs-up { background-position: -96px -144px; } .icon-thumbs-down { background-position: -120px -144px; } .icon-hand-right { background-position: -144px -144px; } .icon-hand-left { background-position: -168px -144px; } .icon-hand-up { background-position: -192px -144px; } .icon-hand-down { background-position: -216px -144px; } .icon-circle-arrow-right { background-position: -240px -144px; } .icon-circle-arrow-left { background-position: -264px -144px; } .icon-circle-arrow-up { background-position: -288px -144px; } .icon-circle-arrow-down { background-position: -312px -144px; } .icon-globe { background-position: -336px -144px; } .icon-wrench { background-position: -360px -144px; } .icon-tasks { background-position: -384px -144px; } .icon-filter { background-position: -408px -144px; } .icon-briefcase { background-position: -432px -144px; } .icon-fullscreen { background-position: -456px -144px; } .dropup, .dropdown { position: relative; } .dropdown-toggle { *margin-bottom: -3px; } .dropdown-toggle:active, .open .dropdown-toggle { outline: 0; } .caret { display: inline-block; width: 0; height: 0; vertical-align: top; border-top: 4px solid #000000; border-right: 4px solid transparent; border-left: 4px solid transparent; content: ""; } .dropdown .caret { margin-top: 8px; margin-left: 2px; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; float: left; min-width: 160px; padding: 5px 0; margin: 2px 0 0; list-style: none; background-color: #ffffff; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.2); *border-right-width: 2px; *border-bottom-width: 2px; -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -webkit-background-clip: padding-box; -moz-background-clip: padding; background-clip: padding-box; } .dropdown-menu.pull-right { right: 0; left: auto; } .dropdown-menu .divider { *width: 100%; height: 1px; margin: 9px 1px; *margin: -5px 0 5px; overflow: hidden; background-color: #e5e5e5; border-bottom: 1px solid #ffffff; } .dropdown-menu > li > a { display: block; padding: 3px 20px; clear: both; font-weight: normal; line-height: 20px; color: #333333; white-space: nowrap; } .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus, .dropdown-submenu:hover > a, .dropdown-submenu:focus > a { color: #ffffff; text-decoration: none; background-color: #0081c2; background-image: -moz-linear-gradient(top, #0088cc, #0077b3); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); background-image: -o-linear-gradient(top, #0088cc, #0077b3); background-image: linear-gradient(to bottom, #0088cc, #0077b3); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); } .dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus { color: #ffffff; text-decoration: none; background-color: #0081c2; background-image: -moz-linear-gradient(top, #0088cc, #0077b3); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3)); background-image: -webkit-linear-gradient(top, #0088cc, #0077b3); background-image: -o-linear-gradient(top, #0088cc, #0077b3); background-image: linear-gradient(to bottom, #0088cc, #0077b3); background-repeat: repeat-x; outline: 0; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0); } .dropdown-menu > .disabled > a, .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { color: #999999; } .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { text-decoration: none; cursor: default; background-color: transparent; background-image: none; filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); } .open { *z-index: 1000; } .open > .dropdown-menu { display: block; } .pull-right > .dropdown-menu { right: 0; left: auto; } .dropup .caret, .navbar-fixed-bottom .dropdown .caret { border-top: 0; border-bottom: 4px solid #000000; content: ""; } .dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu { top: auto; bottom: 100%; margin-bottom: 1px; } .dropdown-submenu { position: relative; } .dropdown-submenu > .dropdown-menu { top: 0; left: 100%; margin-top: -6px; margin-left: -1px; -webkit-border-radius: 0 6px 6px 6px; -moz-border-radius: 0 6px 6px 6px; border-radius: 0 6px 6px 6px; } .dropdown-submenu:hover > .dropdown-menu { display: block; } .dropup .dropdown-submenu > .dropdown-menu { top: auto; bottom: 0; margin-top: 0; margin-bottom: -2px; -webkit-border-radius: 5px 5px 5px 0; -moz-border-radius: 5px 5px 5px 0; border-radius: 5px 5px 5px 0; } .dropdown-submenu > a:after { display: block; float: right; width: 0; height: 0; margin-top: 5px; margin-right: -10px; border-color: transparent; border-left-color: #cccccc; border-style: solid; border-width: 5px 0 5px 5px; content: " "; } .dropdown-submenu:hover > a:after { border-left-color: #ffffff; } .dropdown-submenu.pull-left { float: none; } .dropdown-submenu.pull-left > .dropdown-menu { left: -100%; margin-left: 10px; -webkit-border-radius: 6px 0 6px 6px; -moz-border-radius: 6px 0 6px 6px; border-radius: 6px 0 6px 6px; } .dropdown .dropdown-menu .nav-header { padding-right: 20px; padding-left: 20px; } .typeahead { z-index: 1051; margin-top: 2px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .well { min-height: 20px; padding: 19px; margin-bottom: 20px; background-color: #f5f5f5; border: 1px solid #e3e3e3; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); } .well blockquote { border-color: #ddd; border-color: rgba(0, 0, 0, 0.15); } .well-large { padding: 24px; -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; } .well-small { padding: 9px; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } .fade { opacity: 0; -webkit-transition: opacity 0.15s linear; -moz-transition: opacity 0.15s linear; -o-transition: opacity 0.15s linear; transition: opacity 0.15s linear; } .fade.in { opacity: 1; } .collapse { position: relative; height: 0; overflow: hidden; -webkit-transition: height 0.35s ease; -moz-transition: height 0.35s ease; -o-transition: height 0.35s ease; transition: height 0.35s ease; } .collapse.in { height: auto; } .close { float: right; font-size: 20px; font-weight: bold; line-height: 20px; color: #000000; text-shadow: 0 1px 0 #ffffff; opacity: 0.2; filter: alpha(opacity=20); } .close:hover, .close:focus { color: #000000; text-decoration: none; cursor: pointer; opacity: 0.4; filter: alpha(opacity=40); } button.close { padding: 0; cursor: pointer; background: transparent; border: 0; -webkit-appearance: none; } .btn { display: inline-block; *display: inline; padding: 4px 12px; margin-bottom: 0; *margin-left: .3em; font-size: 14px; line-height: 20px; color: #333333; text-align: center; text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); vertical-align: middle; cursor: pointer; background-color: #f5f5f5; *background-color: #e6e6e6; background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); background-repeat: repeat-x; border: 1px solid #cccccc; *border: 0; border-color: #e6e6e6 #e6e6e6 #bfbfbf; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); border-bottom-color: #b3b3b3; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); *zoom: 1; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); } .btn:hover, .btn:focus, .btn:active, .btn.active, .btn.disabled, .btn[disabled] { color: #333333; background-color: #e6e6e6; *background-color: #d9d9d9; } .btn:active, .btn.active { background-color: #cccccc \9; } .btn:first-child { *margin-left: 0; } .btn:hover, .btn:focus { color: #333333; text-decoration: none; background-position: 0 -15px; -webkit-transition: background-position 0.1s linear; -moz-transition: background-position 0.1s linear; -o-transition: background-position 0.1s linear; transition: background-position 0.1s linear; } .btn:focus { outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; outline-offset: -2px; } .btn.active, .btn:active { background-image: none; outline: 0; -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); } .btn.disabled, .btn[disabled] { cursor: default; background-image: none; opacity: 0.65; filter: alpha(opacity=65); -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } .btn-large { padding: 11px 19px; font-size: 17.5px; -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; } .btn-large [class^="icon-"], .btn-large [class*=" icon-"] { margin-top: 4px; } .btn-small { padding: 2px 10px; font-size: 11.9px; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } .btn-small [class^="icon-"], .btn-small [class*=" icon-"] { margin-top: 0; } .btn-mini [class^="icon-"], .btn-mini [class*=" icon-"] { margin-top: -1px; } .btn-mini { padding: 0 6px; font-size: 10.5px; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } .btn-block { display: block; width: 100%; padding-right: 0; padding-left: 0; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .btn-block + .btn-block { margin-top: 5px; } input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { width: 100%; } .btn-primary.active, .btn-warning.active, .btn-danger.active, .btn-success.active, .btn-info.active, .btn-inverse.active { color: rgba(255, 255, 255, 0.75); } .btn-primary { color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #006dcc; *background-color: #0044cc; background-image: -moz-linear-gradient(top, #0088cc, #0044cc); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); background-image: -o-linear-gradient(top, #0088cc, #0044cc); background-image: linear-gradient(to bottom, #0088cc, #0044cc); background-repeat: repeat-x; border-color: #0044cc #0044cc #002a80; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); } .btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .btn-primary.disabled, .btn-primary[disabled] { color: #ffffff; background-color: #0044cc; *background-color: #003bb3; } .btn-primary:active, .btn-primary.active { background-color: #003399 \9; } .btn-warning { color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #faa732; *background-color: #f89406; background-image: -moz-linear-gradient(top, #fbb450, #f89406); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); background-image: -webkit-linear-gradient(top, #fbb450, #f89406); background-image: -o-linear-gradient(top, #fbb450, #f89406); background-image: linear-gradient(to bottom, #fbb450, #f89406); background-repeat: repeat-x; border-color: #f89406 #f89406 #ad6704; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); } .btn-warning:hover, .btn-warning:focus, .btn-warning:active, .btn-warning.active, .btn-warning.disabled, .btn-warning[disabled] { color: #ffffff; background-color: #f89406; *background-color: #df8505; } .btn-warning:active, .btn-warning.active { background-color: #c67605 \9; } .btn-danger { color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #da4f49; *background-color: #bd362f; background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f)); background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f); background-image: -o-linear-gradient(top, #ee5f5b, #bd362f); background-image: linear-gradient(to bottom, #ee5f5b, #bd362f); background-repeat: repeat-x; border-color: #bd362f #bd362f #802420; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); } .btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active, .btn-danger.disabled, .btn-danger[disabled] { color: #ffffff; background-color: #bd362f; *background-color: #a9302a; } .btn-danger:active, .btn-danger.active { background-color: #942a25 \9; } .btn-success { color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #5bb75b; *background-color: #51a351; background-image: -moz-linear-gradient(top, #62c462, #51a351); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351)); background-image: -webkit-linear-gradient(top, #62c462, #51a351); background-image: -o-linear-gradient(top, #62c462, #51a351); background-image: linear-gradient(to bottom, #62c462, #51a351); background-repeat: repeat-x; border-color: #51a351 #51a351 #387038; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); } .btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active, .btn-success.disabled, .btn-success[disabled] { color: #ffffff; background-color: #51a351; *background-color: #499249; } .btn-success:active, .btn-success.active { background-color: #408140 \9; } .btn-info { color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #49afcd; *background-color: #2f96b4; background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4)); background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4); background-image: -o-linear-gradient(top, #5bc0de, #2f96b4); background-image: linear-gradient(to bottom, #5bc0de, #2f96b4); background-repeat: repeat-x; border-color: #2f96b4 #2f96b4 #1f6377; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); } .btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active, .btn-info.disabled, .btn-info[disabled] { color: #ffffff; background-color: #2f96b4; *background-color: #2a85a0; } .btn-info:active, .btn-info.active { background-color: #24748c \9; } .btn-inverse { color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #363636; *background-color: #222222; background-image: -moz-linear-gradient(top, #444444, #222222); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222)); background-image: -webkit-linear-gradient(top, #444444, #222222); background-image: -o-linear-gradient(top, #444444, #222222); background-image: linear-gradient(to bottom, #444444, #222222); background-repeat: repeat-x; border-color: #222222 #222222 #000000; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); } .btn-inverse:hover, .btn-inverse:focus, .btn-inverse:active, .btn-inverse.active, .btn-inverse.disabled, .btn-inverse[disabled] { color: #ffffff; background-color: #222222; *background-color: #151515; } .btn-inverse:active, .btn-inverse.active { background-color: #080808 \9; } button.btn, input[type="submit"].btn { *padding-top: 3px; *padding-bottom: 3px; } button.btn::-moz-focus-inner, input[type="submit"].btn::-moz-focus-inner { padding: 0; border: 0; } button.btn.btn-large, input[type="submit"].btn.btn-large { *padding-top: 7px; *padding-bottom: 7px; } button.btn.btn-small, input[type="submit"].btn.btn-small { *padding-top: 3px; *padding-bottom: 3px; } button.btn.btn-mini, input[type="submit"].btn.btn-mini { *padding-top: 1px; *padding-bottom: 1px; } .btn-link, .btn-link:active, .btn-link[disabled] { background-color: transparent; background-image: none; -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; } .btn-link { color: #0088cc; cursor: pointer; border-color: transparent; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .btn-link:hover, .btn-link:focus { color: #005580; text-decoration: underline; background-color: transparent; } .btn-link[disabled]:hover, .btn-link[disabled]:focus { color: #333333; text-decoration: none; } .btn-group { position: relative; display: inline-block; *display: inline; *margin-left: .3em; font-size: 0; white-space: nowrap; vertical-align: middle; *zoom: 1; } .btn-group:first-child { *margin-left: 0; } .btn-group + .btn-group { margin-left: 5px; } .btn-toolbar { margin-top: 10px; margin-bottom: 10px; font-size: 0; } .btn-toolbar > .btn + .btn, .btn-toolbar > .btn-group + .btn, .btn-toolbar > .btn + .btn-group { margin-left: 5px; } .btn-group > .btn { position: relative; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .btn-group > .btn + .btn { margin-left: -1px; } .btn-group > .btn, .btn-group > .dropdown-menu, .btn-group > .popover { font-size: 14px; } .btn-group > .btn-mini { font-size: 10.5px; } .btn-group > .btn-small { font-size: 11.9px; } .btn-group > .btn-large { font-size: 17.5px; } .btn-group > .btn:first-child { margin-left: 0; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -moz-border-radius-topleft: 4px; } .btn-group > .btn:last-child, .btn-group > .dropdown-toggle { -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; -moz-border-radius-topright: 4px; -moz-border-radius-bottomright: 4px; } .btn-group > .btn.large:first-child { margin-left: 0; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -moz-border-radius-topleft: 6px; } .btn-group > .btn.large:last-child, .btn-group > .large.dropdown-toggle { -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; -moz-border-radius-topright: 6px; -moz-border-radius-bottomright: 6px; } .btn-group > .btn:hover, .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active { z-index: 2; } .btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { outline: 0; } .btn-group > .btn + .dropdown-toggle { *padding-top: 5px; padding-right: 8px; *padding-bottom: 5px; padding-left: 8px; -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); } .btn-group > .btn-mini + .dropdown-toggle { *padding-top: 2px; padding-right: 5px; *padding-bottom: 2px; padding-left: 5px; } .btn-group > .btn-small + .dropdown-toggle { *padding-top: 5px; *padding-bottom: 4px; } .btn-group > .btn-large + .dropdown-toggle { *padding-top: 7px; padding-right: 12px; *padding-bottom: 7px; padding-left: 12px; } .btn-group.open .dropdown-toggle { background-image: none; -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); } .btn-group.open .btn.dropdown-toggle { background-color: #e6e6e6; } .btn-group.open .btn-primary.dropdown-toggle { background-color: #0044cc; } .btn-group.open .btn-warning.dropdown-toggle { background-color: #f89406; } .btn-group.open .btn-danger.dropdown-toggle { background-color: #bd362f; } .btn-group.open .btn-success.dropdown-toggle { background-color: #51a351; } .btn-group.open .btn-info.dropdown-toggle { background-color: #2f96b4; } .btn-group.open .btn-inverse.dropdown-toggle { background-color: #222222; } .btn .caret { margin-top: 8px; margin-left: 0; } .btn-large .caret { margin-top: 6px; } .btn-large .caret { border-top-width: 5px; border-right-width: 5px; border-left-width: 5px; } .btn-mini .caret, .btn-small .caret { margin-top: 8px; } .dropup .btn-large .caret { border-bottom-width: 5px; } .btn-primary .caret, .btn-warning .caret, .btn-danger .caret, .btn-info .caret, .btn-success .caret, .btn-inverse .caret { border-top-color: #ffffff; border-bottom-color: #ffffff; } .btn-group-vertical { display: inline-block; *display: inline; /* IE7 inline-block hack */ *zoom: 1; } .btn-group-vertical > .btn { display: block; float: none; max-width: 100%; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .btn-group-vertical > .btn + .btn { margin-top: -1px; margin-left: 0; } .btn-group-vertical > .btn:first-child { -webkit-border-radius: 4px 4px 0 0; -moz-border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0; } .btn-group-vertical > .btn:last-child { -webkit-border-radius: 0 0 4px 4px; -moz-border-radius: 0 0 4px 4px; border-radius: 0 0 4px 4px; } .btn-group-vertical > .btn-large:first-child { -webkit-border-radius: 6px 6px 0 0; -moz-border-radius: 6px 6px 0 0; border-radius: 6px 6px 0 0; } .btn-group-vertical > .btn-large:last-child { -webkit-border-radius: 0 0 6px 6px; -moz-border-radius: 0 0 6px 6px; border-radius: 0 0 6px 6px; } .alert { padding: 8px 35px 8px 14px; margin-bottom: 20px; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); background-color: #fcf8e3; border: 1px solid #fbeed5; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .alert, .alert h4 { color: #c09853; } .alert h4 { margin: 0; } .alert .close { position: relative; top: -2px; right: -21px; line-height: 20px; } .alert-success { color: #468847; background-color: #dff0d8; border-color: #d6e9c6; } .alert-success h4 { color: #468847; } .alert-danger, .alert-error { color: #b94a48; background-color: #f2dede; border-color: #eed3d7; } .alert-danger h4, .alert-error h4 { color: #b94a48; } .alert-info { color: #3a87ad; background-color: #d9edf7; border-color: #bce8f1; } .alert-info h4 { color: #3a87ad; } .alert-block { padding-top: 14px; padding-bottom: 14px; } .alert-block > p, .alert-block > ul { margin-bottom: 0; } .alert-block p + p { margin-top: 5px; } .nav { margin-bottom: 20px; margin-left: 0; list-style: none; } .nav > li > a { display: block; } .nav > li > a:hover, .nav > li > a:focus { text-decoration: none; background-color: #eeeeee; } .nav > li > a > img { max-width: none; } .nav > .pull-right { float: right; } .nav-header { display: block; padding: 3px 15px; font-size: 11px; font-weight: bold; line-height: 20px; color: #999999; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); text-transform: uppercase; } .nav li + .nav-header { margin-top: 9px; } .nav-list { padding-right: 15px; padding-left: 15px; margin-bottom: 0; } .nav-list > li > a, .nav-list .nav-header { margin-right: -15px; margin-left: -15px; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); } .nav-list > li > a { padding: 3px 15px; } .nav-list > .active > a, .nav-list > .active > a:hover, .nav-list > .active > a:focus { color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); background-color: #0088cc; } .nav-list [class^="icon-"], .nav-list [class*=" icon-"] { margin-right: 2px; } .nav-list .divider { *width: 100%; height: 1px; margin: 9px 1px; *margin: -5px 0 5px; overflow: hidden; background-color: #e5e5e5; border-bottom: 1px solid #ffffff; } .nav-tabs, .nav-pills { *zoom: 1; } .nav-tabs:before, .nav-pills:before, .nav-tabs:after, .nav-pills:after { display: table; line-height: 0; content: ""; } .nav-tabs:after, .nav-pills:after { clear: both; } .nav-tabs > li, .nav-pills > li { float: left; } .nav-tabs > li > a, .nav-pills > li > a { padding-right: 12px; padding-left: 12px; margin-right: 2px; line-height: 14px; } .nav-tabs { border-bottom: 1px solid #ddd; } .nav-tabs > li { margin-bottom: -1px; } .nav-tabs > li > a { padding-top: 8px; padding-bottom: 8px; line-height: 20px; border: 1px solid transparent; -webkit-border-radius: 4px 4px 0 0; -moz-border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0; } .nav-tabs > li > a:hover, .nav-tabs > li > a:focus { border-color: #eeeeee #eeeeee #dddddd; } .nav-tabs > .active > a, .nav-tabs > .active > a:hover, .nav-tabs > .active > a:focus { color: #555555; cursor: default; background-color: #ffffff; border: 1px solid #ddd; border-bottom-color: transparent; } .nav-pills > li > a { padding-top: 8px; padding-bottom: 8px; margin-top: 2px; margin-bottom: 2px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .nav-pills > .active > a, .nav-pills > .active > a:hover, .nav-pills > .active > a:focus { color: #ffffff; background-color: #0088cc; } .nav-stacked > li { float: none; } .nav-stacked > li > a { margin-right: 0; } .nav-tabs.nav-stacked { border-bottom: 0; } .nav-tabs.nav-stacked > li > a { border: 1px solid #ddd; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .nav-tabs.nav-stacked > li:first-child > a { -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -moz-border-radius-topleft: 4px; } .nav-tabs.nav-stacked > li:last-child > a { -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -moz-border-radius-bottomleft: 4px; } .nav-tabs.nav-stacked > li > a:hover, .nav-tabs.nav-stacked > li > a:focus { z-index: 2; border-color: #ddd; } .nav-pills.nav-stacked > li > a { margin-bottom: 3px; } .nav-pills.nav-stacked > li:last-child > a { margin-bottom: 1px; } .nav-tabs .dropdown-menu { -webkit-border-radius: 0 0 6px 6px; -moz-border-radius: 0 0 6px 6px; border-radius: 0 0 6px 6px; } .nav-pills .dropdown-menu { -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; } .nav .dropdown-toggle .caret { margin-top: 6px; border-top-color: #0088cc; border-bottom-color: #0088cc; } .nav .dropdown-toggle:hover .caret, .nav .dropdown-toggle:focus .caret { border-top-color: #005580; border-bottom-color: #005580; } /* move down carets for tabs */ .nav-tabs .dropdown-toggle .caret { margin-top: 8px; } .nav .active .dropdown-toggle .caret { border-top-color: #fff; border-bottom-color: #fff; } .nav-tabs .active .dropdown-toggle .caret { border-top-color: #555555; border-bottom-color: #555555; } .nav > .dropdown.active > a:hover, .nav > .dropdown.active > a:focus { cursor: pointer; } .nav-tabs .open .dropdown-toggle, .nav-pills .open .dropdown-toggle, .nav > li.dropdown.open.active > a:hover, .nav > li.dropdown.open.active > a:focus { color: #ffffff; background-color: #999999; border-color: #999999; } .nav li.dropdown.open .caret, .nav li.dropdown.open.active .caret, .nav li.dropdown.open a:hover .caret, .nav li.dropdown.open a:focus .caret { border-top-color: #ffffff; border-bottom-color: #ffffff; opacity: 1; filter: alpha(opacity=100); } .tabs-stacked .open > a:hover, .tabs-stacked .open > a:focus { border-color: #999999; } .tabbable { *zoom: 1; } .tabbable:before, .tabbable:after { display: table; line-height: 0; content: ""; } .tabbable:after { clear: both; } .tab-content { overflow: auto; } .tabs-below > .nav-tabs, .tabs-right > .nav-tabs, .tabs-left > .nav-tabs { border-bottom: 0; } .tab-content > .tab-pane, .pill-content > .pill-pane { display: none; } .tab-content > .active, .pill-content > .active { display: block; } .tabs-below > .nav-tabs { border-top: 1px solid #ddd; } .tabs-below > .nav-tabs > li { margin-top: -1px; margin-bottom: 0; } .tabs-below > .nav-tabs > li > a { -webkit-border-radius: 0 0 4px 4px; -moz-border-radius: 0 0 4px 4px; border-radius: 0 0 4px 4px; } .tabs-below > .nav-tabs > li > a:hover, .tabs-below > .nav-tabs > li > a:focus { border-top-color: #ddd; border-bottom-color: transparent; } .tabs-below > .nav-tabs > .active > a, .tabs-below > .nav-tabs > .active > a:hover, .tabs-below > .nav-tabs > .active > a:focus { border-color: transparent #ddd #ddd #ddd; } .tabs-left > .nav-tabs > li, .tabs-right > .nav-tabs > li { float: none; } .tabs-left > .nav-tabs > li > a, .tabs-right > .nav-tabs > li > a { min-width: 74px; margin-right: 0; margin-bottom: 3px; } .tabs-left > .nav-tabs { float: left; margin-right: 19px; border-right: 1px solid #ddd; } .tabs-left > .nav-tabs > li > a { margin-right: -1px; -webkit-border-radius: 4px 0 0 4px; -moz-border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px; } .tabs-left > .nav-tabs > li > a:hover, .tabs-left > .nav-tabs > li > a:focus { border-color: #eeeeee #dddddd #eeeeee #eeeeee; } .tabs-left > .nav-tabs .active > a, .tabs-left > .nav-tabs .active > a:hover, .tabs-left > .nav-tabs .active > a:focus { border-color: #ddd transparent #ddd #ddd; *border-right-color: #ffffff; } .tabs-right > .nav-tabs { float: right; margin-left: 19px; border-left: 1px solid #ddd; } .tabs-right > .nav-tabs > li > a { margin-left: -1px; -webkit-border-radius: 0 4px 4px 0; -moz-border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0; } .tabs-right > .nav-tabs > li > a:hover, .tabs-right > .nav-tabs > li > a:focus { border-color: #eeeeee #eeeeee #eeeeee #dddddd; } .tabs-right > .nav-tabs .active > a, .tabs-right > .nav-tabs .active > a:hover, .tabs-right > .nav-tabs .active > a:focus { border-color: #ddd #ddd #ddd transparent; *border-left-color: #ffffff; } .nav > .disabled > a { color: #999999; } .nav > .disabled > a:hover, .nav > .disabled > a:focus { text-decoration: none; cursor: default; background-color: transparent; } .navbar { *position: relative; *z-index: 2; margin-bottom: 20px; overflow: visible; } .navbar-inner { min-height: 40px; padding-right: 20px; padding-left: 20px; background-color: #fafafa; background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2)); background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2); background-image: -o-linear-gradient(top, #ffffff, #f2f2f2); background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); background-repeat: repeat-x; border: 1px solid #d4d4d4; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0); *zoom: 1; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065); } .navbar-inner:before, .navbar-inner:after { display: table; line-height: 0; content: ""; } .navbar-inner:after { clear: both; } .navbar .container { width: auto; } .nav-collapse.collapse { height: auto; overflow: visible; } .navbar .brand { display: block; float: left; padding: 10px 20px 10px; margin-left: -20px; font-size: 20px; font-weight: 200; color: #777777; text-shadow: 0 1px 0 #ffffff; } .navbar .brand:hover, .navbar .brand:focus { text-decoration: none; } .navbar-text { margin-bottom: 0; line-height: 40px; color: #777777; } .navbar-link { color: #777777; } .navbar-link:hover, .navbar-link:focus { color: #333333; } .navbar .divider-vertical { height: 40px; margin: 0 9px; border-right: 1px solid #ffffff; border-left: 1px solid #f2f2f2; } .navbar .btn, .navbar .btn-group { margin-top: 5px; } .navbar .btn-group .btn, .navbar .input-prepend .btn, .navbar .input-append .btn, .navbar .input-prepend .btn-group, .navbar .input-append .btn-group { margin-top: 0; } .navbar-form { margin-bottom: 0; *zoom: 1; } .navbar-form:before, .navbar-form:after { display: table; line-height: 0; content: ""; } .navbar-form:after { clear: both; } .navbar-form input, .navbar-form select, .navbar-form .radio, .navbar-form .checkbox { margin-top: 5px; } .navbar-form input, .navbar-form select, .navbar-form .btn { display: inline-block; margin-bottom: 0; } .navbar-form input[type="image"], .navbar-form input[type="checkbox"], .navbar-form input[type="radio"] { margin-top: 3px; } .navbar-form .input-append, .navbar-form .input-prepend { margin-top: 5px; white-space: nowrap; } .navbar-form .input-append input, .navbar-form .input-prepend input { margin-top: 0; } .navbar-search { position: relative; float: left; margin-top: 5px; margin-bottom: 0; } .navbar-search .search-query { padding: 4px 14px; margin-bottom: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; line-height: 1; -webkit-border-radius: 15px; -moz-border-radius: 15px; border-radius: 15px; } .navbar-static-top { position: static; margin-bottom: 0; } .navbar-static-top .navbar-inner { -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .navbar-fixed-top, .navbar-fixed-bottom { position: fixed; right: 0; left: 0; z-index: 1030; margin-bottom: 0; } .navbar-fixed-top .navbar-inner, .navbar-static-top .navbar-inner { border-width: 0 0 1px; } .navbar-fixed-bottom .navbar-inner { border-width: 1px 0 0; } .navbar-fixed-top .navbar-inner, .navbar-fixed-bottom .navbar-inner { padding-right: 0; padding-left: 0; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; } .navbar-static-top .container, .navbar-fixed-top .container, .navbar-fixed-bottom .container { width: 940px; } .navbar-fixed-top { top: 0; } .navbar-fixed-top .navbar-inner, .navbar-static-top .navbar-inner { -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1); } .navbar-fixed-bottom { bottom: 0; } .navbar-fixed-bottom .navbar-inner { -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); } .navbar .nav { position: relative; left: 0; display: block; float: left; margin: 0 10px 0 0; } .navbar .nav.pull-right { float: right; margin-right: 0; } .navbar .nav > li { float: left; } .navbar .nav > li > a { float: none; padding: 10px 15px 10px; color: #777777; text-decoration: none; text-shadow: 0 1px 0 #ffffff; } .navbar .nav .dropdown-toggle .caret { margin-top: 8px; } .navbar .nav > li > a:focus, .navbar .nav > li > a:hover { color: #333333; text-decoration: none; background-color: transparent; } .navbar .nav > .active > a, .navbar .nav > .active > a:hover, .navbar .nav > .active > a:focus { color: #555555; text-decoration: none; background-color: #e5e5e5; -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125); } .navbar .btn-navbar { display: none; float: right; padding: 7px 10px; margin-right: 5px; margin-left: 5px; color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #ededed; *background-color: #e5e5e5; background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5)); background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5); background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5); background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5); background-repeat: repeat-x; border-color: #e5e5e5 #e5e5e5 #bfbfbf; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075); } .navbar .btn-navbar:hover, .navbar .btn-navbar:focus, .navbar .btn-navbar:active, .navbar .btn-navbar.active, .navbar .btn-navbar.disabled, .navbar .btn-navbar[disabled] { color: #ffffff; background-color: #e5e5e5; *background-color: #d9d9d9; } .navbar .btn-navbar:active, .navbar .btn-navbar.active { background-color: #cccccc \9; } .navbar .btn-navbar .icon-bar { display: block; width: 18px; height: 2px; background-color: #f5f5f5; -webkit-border-radius: 1px; -moz-border-radius: 1px; border-radius: 1px; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); } .btn-navbar .icon-bar + .icon-bar { margin-top: 3px; } .navbar .nav > li > .dropdown-menu:before { position: absolute; top: -7px; left: 9px; display: inline-block; border-right: 7px solid transparent; border-bottom: 7px solid #ccc; border-left: 7px solid transparent; border-bottom-color: rgba(0, 0, 0, 0.2); content: ''; } .navbar .nav > li > .dropdown-menu:after { position: absolute; top: -6px; left: 10px; display: inline-block; border-right: 6px solid transparent; border-bottom: 6px solid #ffffff; border-left: 6px solid transparent; content: ''; } .navbar-fixed-bottom .nav > li > .dropdown-menu:before { top: auto; bottom: -7px; border-top: 7px solid #ccc; border-bottom: 0; border-top-color: rgba(0, 0, 0, 0.2); } .navbar-fixed-bottom .nav > li > .dropdown-menu:after { top: auto; bottom: -6px; border-top: 6px solid #ffffff; border-bottom: 0; } .navbar .nav li.dropdown > a:hover .caret, .navbar .nav li.dropdown > a:focus .caret { border-top-color: #333333; border-bottom-color: #333333; } .navbar .nav li.dropdown.open > .dropdown-toggle, .navbar .nav li.dropdown.active > .dropdown-toggle, .navbar .nav li.dropdown.open.active > .dropdown-toggle { color: #555555; background-color: #e5e5e5; } .navbar .nav li.dropdown > .dropdown-toggle .caret { border-top-color: #777777; border-bottom-color: #777777; } .navbar .nav li.dropdown.open > .dropdown-toggle .caret, .navbar .nav li.dropdown.active > .dropdown-toggle .caret, .navbar .nav li.dropdown.open.active > .dropdown-toggle .caret { border-top-color: #555555; border-bottom-color: #555555; } .navbar .pull-right > li > .dropdown-menu, .navbar .nav > li > .dropdown-menu.pull-right { right: 0; left: auto; } .navbar .pull-right > li > .dropdown-menu:before, .navbar .nav > li > .dropdown-menu.pull-right:before { right: 12px; left: auto; } .navbar .pull-right > li > .dropdown-menu:after, .navbar .nav > li > .dropdown-menu.pull-right:after { right: 13px; left: auto; } .navbar .pull-right > li > .dropdown-menu .dropdown-menu, .navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu { right: 100%; left: auto; margin-right: -1px; margin-left: 0; -webkit-border-radius: 6px 0 6px 6px; -moz-border-radius: 6px 0 6px 6px; border-radius: 6px 0 6px 6px; } .navbar-inverse .navbar-inner { background-color: #1b1b1b; background-image: -moz-linear-gradient(top, #222222, #111111); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); background-image: -webkit-linear-gradient(top, #222222, #111111); background-image: -o-linear-gradient(top, #222222, #111111); background-image: linear-gradient(to bottom, #222222, #111111); background-repeat: repeat-x; border-color: #252525; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); } .navbar-inverse .brand, .navbar-inverse .nav > li > a { color: #999999; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); } .navbar-inverse .brand:hover, .navbar-inverse .nav > li > a:hover, .navbar-inverse .brand:focus, .navbar-inverse .nav > li > a:focus { color: #ffffff; } .navbar-inverse .brand { color: #999999; } .navbar-inverse .navbar-text { color: #999999; } .navbar-inverse .nav > li > a:focus, .navbar-inverse .nav > li > a:hover { color: #ffffff; background-color: transparent; } .navbar-inverse .nav .active > a, .navbar-inverse .nav .active > a:hover, .navbar-inverse .nav .active > a:focus { color: #ffffff; background-color: #111111; } .navbar-inverse .navbar-link { color: #999999; } .navbar-inverse .navbar-link:hover, .navbar-inverse .navbar-link:focus { color: #ffffff; } .navbar-inverse .divider-vertical { border-right-color: #222222; border-left-color: #111111; } .navbar-inverse .nav li.dropdown.open > .dropdown-toggle, .navbar-inverse .nav li.dropdown.active > .dropdown-toggle, .navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle { color: #ffffff; background-color: #111111; } .navbar-inverse .nav li.dropdown > a:hover .caret, .navbar-inverse .nav li.dropdown > a:focus .caret { border-top-color: #ffffff; border-bottom-color: #ffffff; } .navbar-inverse .nav li.dropdown > .dropdown-toggle .caret { border-top-color: #999999; border-bottom-color: #999999; } .navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret, .navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret, .navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret { border-top-color: #ffffff; border-bottom-color: #ffffff; } .navbar-inverse .navbar-search .search-query { color: #ffffff; background-color: #515151; border-color: #111111; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15); -webkit-transition: none; -moz-transition: none; -o-transition: none; transition: none; } .navbar-inverse .navbar-search .search-query:-moz-placeholder { color: #cccccc; } .navbar-inverse .navbar-search .search-query:-ms-input-placeholder { color: #cccccc; } .navbar-inverse .navbar-search .search-query::-webkit-input-placeholder { color: #cccccc; } .navbar-inverse .navbar-search .search-query:focus, .navbar-inverse .navbar-search .search-query.focused { padding: 5px 15px; color: #333333; text-shadow: 0 1px 0 #ffffff; background-color: #ffffff; border: 0; outline: 0; -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); } .navbar-inverse .btn-navbar { color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #0e0e0e; *background-color: #040404; background-image: -moz-linear-gradient(top, #151515, #040404); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404)); background-image: -webkit-linear-gradient(top, #151515, #040404); background-image: -o-linear-gradient(top, #151515, #040404); background-image: linear-gradient(to bottom, #151515, #040404); background-repeat: repeat-x; border-color: #040404 #040404 #000000; border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0); filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); } .navbar-inverse .btn-navbar:hover, .navbar-inverse .btn-navbar:focus, .navbar-inverse .btn-navbar:active, .navbar-inverse .btn-navbar.active, .navbar-inverse .btn-navbar.disabled, .navbar-inverse .btn-navbar[disabled] { color: #ffffff; background-color: #040404; *background-color: #000000; } .navbar-inverse .btn-navbar:active, .navbar-inverse .btn-navbar.active { background-color: #000000 \9; } .breadcrumb { padding: 8px 15px; margin: 0 0 20px; list-style: none; background-color: #f5f5f5; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .breadcrumb > li { display: inline-block; *display: inline; text-shadow: 0 1px 0 #ffffff; *zoom: 1; } .breadcrumb > li > .divider { padding: 0 5px; color: #ccc; } .breadcrumb > .active { color: #999999; } .pagination { margin: 20px 0; } .pagination ul { display: inline-block; *display: inline; margin-bottom: 0; margin-left: 0; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; *zoom: 1; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); } .pagination ul > li { display: inline; } .pagination ul > li > a, .pagination ul > li > span { float: left; padding: 4px 12px; line-height: 20px; text-decoration: none; background-color: #ffffff; border: 1px solid #dddddd; border-left-width: 0; } .pagination ul > li > a:hover, .pagination ul > li > a:focus, .pagination ul > .active > a, .pagination ul > .active > span { background-color: #f5f5f5; } .pagination ul > .active > a, .pagination ul > .active > span { color: #999999; cursor: default; } .pagination ul > .disabled > span, .pagination ul > .disabled > a, .pagination ul > .disabled > a:hover, .pagination ul > .disabled > a:focus { color: #999999; cursor: default; background-color: transparent; } .pagination ul > li:first-child > a, .pagination ul > li:first-child > span { border-left-width: 1px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -moz-border-radius-topleft: 4px; } .pagination ul > li:last-child > a, .pagination ul > li:last-child > span { -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; -moz-border-radius-topright: 4px; -moz-border-radius-bottomright: 4px; } .pagination-centered { text-align: center; } .pagination-right { text-align: right; } .pagination-large ul > li > a, .pagination-large ul > li > span { padding: 11px 19px; font-size: 17.5px; } .pagination-large ul > li:first-child > a, .pagination-large ul > li:first-child > span { -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -moz-border-radius-topleft: 6px; } .pagination-large ul > li:last-child > a, .pagination-large ul > li:last-child > span { -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; -moz-border-radius-topright: 6px; -moz-border-radius-bottomright: 6px; } .pagination-mini ul > li:first-child > a, .pagination-small ul > li:first-child > a, .pagination-mini ul > li:first-child > span, .pagination-small ul > li:first-child > span { -webkit-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; -webkit-border-top-left-radius: 3px; border-top-left-radius: 3px; -moz-border-radius-bottomleft: 3px; -moz-border-radius-topleft: 3px; } .pagination-mini ul > li:last-child > a, .pagination-small ul > li:last-child > a, .pagination-mini ul > li:last-child > span, .pagination-small ul > li:last-child > span { -webkit-border-top-right-radius: 3px; border-top-right-radius: 3px; -webkit-border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; -moz-border-radius-topright: 3px; -moz-border-radius-bottomright: 3px; } .pagination-small ul > li > a, .pagination-small ul > li > span { padding: 2px 10px; font-size: 11.9px; } .pagination-mini ul > li > a, .pagination-mini ul > li > span { padding: 0 6px; font-size: 10.5px; } .pager { margin: 20px 0; text-align: center; list-style: none; *zoom: 1; } .pager:before, .pager:after { display: table; line-height: 0; content: ""; } .pager:after { clear: both; } .pager li { display: inline; } .pager li > a, .pager li > span { display: inline-block; padding: 5px 14px; background-color: #fff; border: 1px solid #ddd; -webkit-border-radius: 15px; -moz-border-radius: 15px; border-radius: 15px; } .pager li > a:hover, .pager li > a:focus { text-decoration: none; background-color: #f5f5f5; } .pager .next > a, .pager .next > span { float: right; } .pager .previous > a, .pager .previous > span { float: left; } .pager .disabled > a, .pager .disabled > a:hover, .pager .disabled > a:focus, .pager .disabled > span { color: #999999; cursor: default; background-color: #fff; } .modal-backdrop { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1040; background-color: #000000; } .modal-backdrop.fade { opacity: 0; } .modal-backdrop, .modal-backdrop.fade.in { opacity: 0.8; filter: alpha(opacity=80); } .modal { position: fixed; top: 10%; left: 50%; z-index: 1050; width: 560px; margin-left: -280px; background-color: #ffffff; border: 1px solid #999; border: 1px solid rgba(0, 0, 0, 0.3); *border: 1px solid #999; -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; outline: none; -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); -webkit-background-clip: padding-box; -moz-background-clip: padding-box; background-clip: padding-box; } .modal.fade { top: -25%; -webkit-transition: opacity 0.3s linear, top 0.3s ease-out; -moz-transition: opacity 0.3s linear, top 0.3s ease-out; -o-transition: opacity 0.3s linear, top 0.3s ease-out; transition: opacity 0.3s linear, top 0.3s ease-out; } .modal.fade.in { top: 10%; } .modal-header { padding: 9px 15px; border-bottom: 1px solid #eee; } .modal-header .close { margin-top: 2px; } .modal-header h3 { margin: 0; line-height: 30px; } .modal-body { position: relative; max-height: 400px; padding: 15px; overflow-y: auto; } .modal-form { margin-bottom: 0; } .modal-footer { padding: 14px 15px 15px; margin-bottom: 0; text-align: right; background-color: #f5f5f5; border-top: 1px solid #ddd; -webkit-border-radius: 0 0 6px 6px; -moz-border-radius: 0 0 6px 6px; border-radius: 0 0 6px 6px; *zoom: 1; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; } .modal-footer:before, .modal-footer:after { display: table; line-height: 0; content: ""; } .modal-footer:after { clear: both; } .modal-footer .btn + .btn { margin-bottom: 0; margin-left: 5px; } .modal-footer .btn-group .btn + .btn { margin-left: -1px; } .modal-footer .btn-block + .btn-block { margin-left: 0; } .tooltip { position: absolute; z-index: 1030; display: block; font-size: 11px; line-height: 1.4; opacity: 0; filter: alpha(opacity=0); visibility: visible; } .tooltip.in { opacity: 0.8; filter: alpha(opacity=80); } .tooltip.top { padding: 5px 0; margin-top: -3px; } .tooltip.right { padding: 0 5px; margin-left: 3px; } .tooltip.bottom { padding: 5px 0; margin-top: 3px; } .tooltip.left { padding: 0 5px; margin-left: -3px; } .tooltip-inner { max-width: 200px; padding: 8px; color: #ffffff; text-align: center; text-decoration: none; background-color: #000000; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .tooltip-arrow { position: absolute; width: 0; height: 0; border-color: transparent; border-style: solid; } .tooltip.top .tooltip-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-color: #000000; border-width: 5px 5px 0; } .tooltip.right .tooltip-arrow { top: 50%; left: 0; margin-top: -5px; border-right-color: #000000; border-width: 5px 5px 5px 0; } .tooltip.left .tooltip-arrow { top: 50%; right: 0; margin-top: -5px; border-left-color: #000000; border-width: 5px 0 5px 5px; } .tooltip.bottom .tooltip-arrow { top: 0; left: 50%; margin-left: -5px; border-bottom-color: #000000; border-width: 0 5px 5px; } .popover { position: absolute; top: 0; left: 0; z-index: 1010; display: none; max-width: 276px; padding: 1px; text-align: left; white-space: normal; background-color: #ffffff; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.2); -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -webkit-background-clip: padding-box; -moz-background-clip: padding; background-clip: padding-box; } .popover.top { margin-top: -10px; } .popover.right { margin-left: 10px; } .popover.bottom { margin-top: 10px; } .popover.left { margin-left: -10px; } .popover-title { padding: 8px 14px; margin: 0; font-size: 14px; font-weight: normal; line-height: 18px; background-color: #f7f7f7; border-bottom: 1px solid #ebebeb; -webkit-border-radius: 5px 5px 0 0; -moz-border-radius: 5px 5px 0 0; border-radius: 5px 5px 0 0; } .popover-title:empty { display: none; } .popover-content { padding: 9px 14px; } .popover .arrow, .popover .arrow:after { position: absolute; display: block; width: 0; height: 0; border-color: transparent; border-style: solid; } .popover .arrow { border-width: 11px; } .popover .arrow:after { border-width: 10px; content: ""; } .popover.top .arrow { bottom: -11px; left: 50%; margin-left: -11px; border-top-color: #999; border-top-color: rgba(0, 0, 0, 0.25); border-bottom-width: 0; } .popover.top .arrow:after { bottom: 1px; margin-left: -10px; border-top-color: #ffffff; border-bottom-width: 0; } .popover.right .arrow { top: 50%; left: -11px; margin-top: -11px; border-right-color: #999; border-right-color: rgba(0, 0, 0, 0.25); border-left-width: 0; } .popover.right .arrow:after { bottom: -10px; left: 1px; border-right-color: #ffffff; border-left-width: 0; } .popover.bottom .arrow { top: -11px; left: 50%; margin-left: -11px; border-bottom-color: #999; border-bottom-color: rgba(0, 0, 0, 0.25); border-top-width: 0; } .popover.bottom .arrow:after { top: 1px; margin-left: -10px; border-bottom-color: #ffffff; border-top-width: 0; } .popover.left .arrow { top: 50%; right: -11px; margin-top: -11px; border-left-color: #999; border-left-color: rgba(0, 0, 0, 0.25); border-right-width: 0; } .popover.left .arrow:after { right: 1px; bottom: -10px; border-left-color: #ffffff; border-right-width: 0; } .thumbnails { margin-left: -20px; list-style: none; *zoom: 1; } .thumbnails:before, .thumbnails:after { display: table; line-height: 0; content: ""; } .thumbnails:after { clear: both; } .row-fluid .thumbnails { margin-left: 0; } .thumbnails > li { float: left; margin-bottom: 20px; margin-left: 20px; } .thumbnail { display: block; padding: 4px; line-height: 20px; border: 1px solid #ddd; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055); -webkit-transition: all 0.2s ease-in-out; -moz-transition: all 0.2s ease-in-out; -o-transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out; } a.thumbnail:hover, a.thumbnail:focus { border-color: #0088cc; -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25); } .thumbnail > img { display: block; max-width: 100%; margin-right: auto; margin-left: auto; } .thumbnail .caption { padding: 9px; color: #555555; } .media, .media-body { overflow: hidden; *overflow: visible; zoom: 1; } .media, .media .media { margin-top: 15px; } .media:first-child { margin-top: 0; } .media-object { display: block; } .media-heading { margin: 0 0 5px; } .media > .pull-left { margin-right: 10px; } .media > .pull-right { margin-left: 10px; } .media-list { margin-left: 0; list-style: none; } .label, .badge { display: inline-block; padding: 2px 4px; font-size: 11.844px; font-weight: bold; line-height: 14px; color: #ffffff; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); white-space: nowrap; vertical-align: baseline; background-color: #999999; } .label { -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } .badge { padding-right: 9px; padding-left: 9px; -webkit-border-radius: 9px; -moz-border-radius: 9px; border-radius: 9px; } .label:empty, .badge:empty { display: none; } a.label:hover, a.label:focus, a.badge:hover, a.badge:focus { color: #ffffff; text-decoration: none; cursor: pointer; } .label-important, .badge-important { background-color: #b94a48; } .label-important[href], .badge-important[href] { background-color: #953b39; } .label-warning, .badge-warning { background-color: #f89406; } .label-warning[href], .badge-warning[href] { background-color: #c67605; } .label-success, .badge-success { background-color: #468847; } .label-success[href], .badge-success[href] { background-color: #356635; } .label-info, .badge-info { background-color: #3a87ad; } .label-info[href], .badge-info[href] { background-color: #2d6987; } .label-inverse, .badge-inverse { background-color: #333333; } .label-inverse[href], .badge-inverse[href] { background-color: #1a1a1a; } .btn .label, .btn .badge { position: relative; top: -1px; } .btn-mini .label, .btn-mini .badge { top: 0; } @-webkit-keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } } @-moz-keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } } @-ms-keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } } @-o-keyframes progress-bar-stripes { from { background-position: 0 0; } to { background-position: 40px 0; } } @keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } } .progress { height: 20px; margin-bottom: 20px; overflow: hidden; background-color: #f7f7f7; background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); background-repeat: repeat-x; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); } .progress .bar { float: left; width: 0; height: 100%; font-size: 12px; color: #ffffff; text-align: center; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); background-color: #0e90d2; background-image: -moz-linear-gradient(top, #149bdf, #0480be); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); background-image: -webkit-linear-gradient(top, #149bdf, #0480be); background-image: -o-linear-gradient(top, #149bdf, #0480be); background-image: linear-gradient(to bottom, #149bdf, #0480be); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-transition: width 0.6s ease; -moz-transition: width 0.6s ease; -o-transition: width 0.6s ease; transition: width 0.6s ease; } .progress .bar + .bar { -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15); } .progress-striped .bar { background-color: #149bdf; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -webkit-background-size: 40px 40px; -moz-background-size: 40px 40px; -o-background-size: 40px 40px; background-size: 40px 40px; } .progress.active .bar { -webkit-animation: progress-bar-stripes 2s linear infinite; -moz-animation: progress-bar-stripes 2s linear infinite; -ms-animation: progress-bar-stripes 2s linear infinite; -o-animation: progress-bar-stripes 2s linear infinite; animation: progress-bar-stripes 2s linear infinite; } .progress-danger .bar, .progress .bar-danger { background-color: #dd514c; background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35)); background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); background-image: linear-gradient(to bottom, #ee5f5b, #c43c35); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0); } .progress-danger.progress-striped .bar, .progress-striped .bar-danger { background-color: #ee5f5b; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-success .bar, .progress .bar-success { background-color: #5eb95e; background-image: -moz-linear-gradient(top, #62c462, #57a957); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957)); background-image: -webkit-linear-gradient(top, #62c462, #57a957); background-image: -o-linear-gradient(top, #62c462, #57a957); background-image: linear-gradient(to bottom, #62c462, #57a957); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0); } .progress-success.progress-striped .bar, .progress-striped .bar-success { background-color: #62c462; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-info .bar, .progress .bar-info { background-color: #4bb1cf; background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9)); background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); background-image: -o-linear-gradient(top, #5bc0de, #339bb9); background-image: linear-gradient(to bottom, #5bc0de, #339bb9); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0); } .progress-info.progress-striped .bar, .progress-striped .bar-info { background-color: #5bc0de; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .progress-warning .bar, .progress .bar-warning { background-color: #faa732; background-image: -moz-linear-gradient(top, #fbb450, #f89406); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); background-image: -webkit-linear-gradient(top, #fbb450, #f89406); background-image: -o-linear-gradient(top, #fbb450, #f89406); background-image: linear-gradient(to bottom, #fbb450, #f89406); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0); } .progress-warning.progress-striped .bar, .progress-striped .bar-warning { background-color: #fbb450; background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); } .accordion { margin-bottom: 20px; } .accordion-group { margin-bottom: 2px; border: 1px solid #e5e5e5; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .accordion-heading { border-bottom: 0; } .accordion-heading .accordion-toggle { display: block; padding: 8px 15px; } .accordion-toggle { cursor: pointer; } .accordion-inner { padding: 9px 15px; border-top: 1px solid #e5e5e5; } .carousel { position: relative; margin-bottom: 20px; line-height: 1; } .carousel-inner { position: relative; width: 100%; overflow: hidden; } .carousel-inner > .item { position: relative; display: none; -webkit-transition: 0.6s ease-in-out left; -moz-transition: 0.6s ease-in-out left; -o-transition: 0.6s ease-in-out left; transition: 0.6s ease-in-out left; } .carousel-inner > .item > img, .carousel-inner > .item > a > img { display: block; line-height: 1; } .carousel-inner > .active, .carousel-inner > .next, .carousel-inner > .prev { display: block; } .carousel-inner > .active { left: 0; } .carousel-inner > .next, .carousel-inner > .prev { position: absolute; top: 0; width: 100%; } .carousel-inner > .next { left: 100%; } .carousel-inner > .prev { left: -100%; } .carousel-inner > .next.left, .carousel-inner > .prev.right { left: 0; } .carousel-inner > .active.left { left: -100%; } .carousel-inner > .active.right { left: 100%; } .carousel-control { position: absolute; top: 40%; left: 15px; width: 40px; height: 40px; margin-top: -20px; font-size: 60px; font-weight: 100; line-height: 30px; color: #ffffff; text-align: center; background: #222222; border: 3px solid #ffffff; -webkit-border-radius: 23px; -moz-border-radius: 23px; border-radius: 23px; opacity: 0.5; filter: alpha(opacity=50); } .carousel-control.right { right: 15px; left: auto; } .carousel-control:hover, .carousel-control:focus { color: #ffffff; text-decoration: none; opacity: 0.9; filter: alpha(opacity=90); } .carousel-indicators { position: absolute; top: 15px; right: 15px; z-index: 5; margin: 0; list-style: none; } .carousel-indicators li { display: block; float: left; width: 10px; height: 10px; margin-left: 5px; text-indent: -999px; background-color: #ccc; background-color: rgba(255, 255, 255, 0.25); border-radius: 5px; } .carousel-indicators .active { background-color: #fff; } .carousel-caption { position: absolute; right: 0; bottom: 0; left: 0; padding: 15px; background: #333333; background: rgba(0, 0, 0, 0.75); } .carousel-caption h4, .carousel-caption p { line-height: 20px; color: #ffffff; } .carousel-caption h4 { margin: 0 0 5px; } .carousel-caption p { margin-bottom: 0; } .hero-unit { padding: 60px; margin-bottom: 30px; font-size: 18px; font-weight: 200; line-height: 30px; color: inherit; background-color: #eeeeee; -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; } .hero-unit h1 { margin-bottom: 0; font-size: 60px; line-height: 1; letter-spacing: -1px; color: inherit; } .hero-unit li { line-height: 30px; } .pull-right { float: right; } .pull-left { float: left; } .hide { display: none; } .show { display: block; } .invisible { visibility: hidden; } .affix { position: fixed; } ================================================ FILE: 13 - Integrating Via Http and Rest/PPPDDD.REST.SocialMedia/AccountManagement.EntryPoint/vendor/js/backbone.js ================================================ // Backbone.js // =========== // > (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc. // > Backbone may be freely distributed under the MIT license. // > For all details and documentation: http://backbonejs.org // Initial Setup // ------------- (function(){ // Save a reference to the global object (`window` in the browser, `exports` // on the server). var root = this; // Save the previous value of the `Backbone` variable, so that it can be // restored later on, if `noConflict` is used. var previousBackbone = root.Backbone; // Create a local reference to array methods. var array = []; var push = array.push; var slice = array.slice; var splice = array.splice; // The top-level namespace. All public Backbone classes and modules will // be attached to this. Exported for both CommonJS and the browser. var Backbone; if (typeof exports !== 'undefined') { Backbone = exports; } else { Backbone = root.Backbone = {}; } // Current version of the library. Keep in sync with `package.json`. Backbone.VERSION = '0.9.10'; // Require Underscore, if we're on the server, and it's not already present. var _ = root._; if (!_ && (typeof require !== 'undefined')) _ = require('underscore'); // For Backbone's purposes, jQuery, Zepto, or Ender owns the `$` variable. Backbone.$ = root.jQuery || root.Zepto || root.ender; // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable // to its previous owner. Returns a reference to this Backbone object. Backbone.noConflict = function() { root.Backbone = previousBackbone; return this; }; // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option // will fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and // set a `X-Http-Method-Override` header. Backbone.emulateHTTP = false; // Turn on `emulateJSON` to support legacy servers that can't deal with direct // `application/json` requests ... will encode the body as // `application/x-www-form-urlencoded` instead and will send the model in a // form param named `model`. Backbone.emulateJSON = false; // Backbone.Events // --------------- // Regular expression used to split event strings. var eventSplitter = /\s+/; // Implement fancy features of the Events API such as multiple event // names `"change blur"` and jQuery-style event maps `{change: action}` // in terms of the existing API. var eventsApi = function(obj, action, name, rest) { if (!name) return true; if (typeof name === 'object') { for (var key in name) { obj[action].apply(obj, [key, name[key]].concat(rest)); } } else if (eventSplitter.test(name)) { var names = name.split(eventSplitter); for (var i = 0, l = names.length; i < l; i++) { obj[action].apply(obj, [names[i]].concat(rest)); } } else { return true; } }; // Optimized internal dispatch function for triggering events. Tries to // keep the usual cases speedy (most Backbone events have 3 arguments). var triggerEvents = function(events, args) { var ev, i = -1, l = events.length; switch (args.length) { case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return; case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0]); return; case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1]); return; case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1], args[2]); return; default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); } }; // A module that can be mixed in to *any object* in order to provide it with // custom events. You may bind with `on` or remove with `off` callback // functions to an event; `trigger`-ing an event fires all callbacks in // succession. var Events = Backbone.Events = { // Bind one or more space separated events, or an events map, // to a `callback` function. Passing `"all"` will bind the callback to // all events fired. on: function(name, callback, context) { if (!(eventsApi(this, 'on', name, [callback, context]) && callback)) return this; this._events || (this._events = {}); var list = this._events[name] || (this._events[name] = []); list.push({callback: callback, context: context, ctx: context || this}); return this; }, // Bind events to only be triggered a single time. After the first time // the callback is invoked, it will be removed. once: function(name, callback, context) { if (!(eventsApi(this, 'once', name, [callback, context]) && callback)) return this; var self = this; var once = _.once(function() { self.off(name, once); callback.apply(this, arguments); }); once._callback = callback; this.on(name, once, context); return this; }, // Remove one or many callbacks. If `context` is null, removes all // callbacks with that function. If `callback` is null, removes all // callbacks for the event. If `name` is null, removes all bound // callbacks for all events. off: function(name, callback, context) { var list, ev, events, names, i, l, j, k; if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this; if (!name && !callback && !context) { this._events = {}; return this; } names = name ? [name] : _.keys(this._events); for (i = 0, l = names.length; i < l; i++) { name = names[i]; if (list = this._events[name]) { events = []; if (callback || context) { for (j = 0, k = list.length; j < k; j++) { ev = list[j]; if ((callback && callback !== ev.callback && callback !== ev.callback._callback) || (context && context !== ev.context)) { events.push(ev); } } } this._events[name] = events; } } return this; }, // Trigger one or many events, firing all bound callbacks. Callbacks are // passed the same arguments as `trigger` is, apart from the event name // (unless you're listening on `"all"`, which will cause your callback to // receive the true name of the event as the first argument). trigger: function(name) { if (!this._events) return this; var args = slice.call(arguments, 1); if (!eventsApi(this, 'trigger', name, args)) return this; var events = this._events[name]; var allEvents = this._events.all; if (events) triggerEvents(events, args); if (allEvents) triggerEvents(allEvents, arguments); return this; }, // An inversion-of-control version of `on`. Tell *this* object to listen to // an event in another object ... keeping track of what it's listening to. listenTo: function(obj, name, callback) { var listeners = this._listeners || (this._listeners = {}); var id = obj._listenerId || (obj._listenerId = _.uniqueId('l')); listeners[id] = obj; obj.on(name, typeof name === 'object' ? this : callback, this); return this; }, // Tell this object to stop listening to either specific events ... or // to every object it's currently listening to. stopListening: function(obj, name, callback) { var listeners = this._listeners; if (!listeners) return; if (obj) { obj.off(name, typeof name === 'object' ? this : callback, this); if (!name && !callback) delete listeners[obj._listenerId]; } else { if (typeof name === 'object') callback = this; for (var id in listeners) { listeners[id].off(name, callback, this); } this._listeners = {}; } return this; } }; // Aliases for backwards compatibility. Events.bind = Events.on; Events.unbind = Events.off; // Allow the `Backbone` object to serve as a global event bus, for folks who // want global "pubsub" in a convenient place. _.extend(Backbone, Events); // Backbone.Model // -------------- // Create a new model, with defined attributes. A client id (`cid`) // is automatically generated and assigned for you. var Model = Backbone.Model = function(attributes, options) { var defaults; var attrs = attributes || {}; this.cid = _.uniqueId('c'); this.attributes = {}; if (options && options.collection) this.collection = options.collection; if (options && options.parse) attrs = this.parse(attrs, options) || {}; if (defaults = _.result(this, 'defaults')) { attrs = _.defaults({}, attrs, defaults); } this.set(attrs, options); this.changed = {}; this.initialize.apply(this, arguments); }; // Attach all inheritable methods to the Model prototype. _.extend(Model.prototype, Events, { // A hash of attributes whose current and previous value differ. changed: null, // The default name for the JSON `id` attribute is `"id"`. MongoDB and // CouchDB users may want to set this to `"_id"`. idAttribute: 'id', // Initialize is an empty function by default. Override it with your own // initialization logic. initialize: function(){}, // Return a copy of the model's `attributes` object. toJSON: function(options) { return _.clone(this.attributes); }, // Proxy `Backbone.sync` by default. sync: function() { return Backbone.sync.apply(this, arguments); }, // Get the value of an attribute. get: function(attr) { return this.attributes[attr]; }, // Get the HTML-escaped value of an attribute. escape: function(attr) { return _.escape(this.get(attr)); }, // Returns `true` if the attribute contains a value that is not null // or undefined. has: function(attr) { return this.get(attr) != null; }, // ---------------------------------------------------------------------- // Set a hash of model attributes on the object, firing `"change"` unless // you choose to silence it. set: function(key, val, options) { var attr, attrs, unset, changes, silent, changing, prev, current; if (key == null) return this; // Handle both `"key", value` and `{key: value}` -style arguments. if (typeof key === 'object') { attrs = key; options = val; } else { (attrs = {})[key] = val; } options || (options = {}); // Run validation. if (!this._validate(attrs, options)) return false; // Extract attributes and options. unset = options.unset; silent = options.silent; changes = []; changing = this._changing; this._changing = true; if (!changing) { this._previousAttributes = _.clone(this.attributes); this.changed = {}; } current = this.attributes, prev = this._previousAttributes; // Check for changes of `id`. if (this.idAttribute in attrs) this.id = attrs[this.idAttribute]; // For each `set` attribute, update or delete the current value. for (attr in attrs) { val = attrs[attr]; if (!_.isEqual(current[attr], val)) changes.push(attr); if (!_.isEqual(prev[attr], val)) { this.changed[attr] = val; } else { delete this.changed[attr]; } unset ? delete current[attr] : current[attr] = val; } // Trigger all relevant attribute changes. if (!silent) { if (changes.length) this._pending = true; for (var i = 0, l = changes.length; i < l; i++) { this.trigger('change:' + changes[i], this, current[changes[i]], options); } } if (changing) return this; if (!silent) { while (this._pending) { this._pending = false; this.trigger('change', this, options); } } this._pending = false; this._changing = false; return this; }, // Remove an attribute from the model, firing `"change"` unless you choose // to silence it. `unset` is a noop if the attribute doesn't exist. unset: function(attr, options) { return this.set(attr, void 0, _.extend({}, options, {unset: true})); }, // Clear all attributes on the model, firing `"change"` unless you choose // to silence it. clear: function(options) { var attrs = {}; for (var key in this.attributes) attrs[key] = void 0; return this.set(attrs, _.extend({}, options, {unset: true})); }, // Determine if the model has changed since the last `"change"` event. // If you specify an attribute name, determine if that attribute has changed. hasChanged: function(attr) { if (attr == null) return !_.isEmpty(this.changed); return _.has(this.changed, attr); }, // Return an object containing all the attributes that have changed, or // false if there are no changed attributes. Useful for determining what // parts of a view need to be updated and/or what attributes need to be // persisted to the server. Unset attributes will be set to undefined. // You can also pass an attributes object to diff against the model, // determining if there *would be* a change. changedAttributes: function(diff) { if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; var val, changed = false; var old = this._changing ? this._previousAttributes : this.attributes; for (var attr in diff) { if (_.isEqual(old[attr], (val = diff[attr]))) continue; (changed || (changed = {}))[attr] = val; } return changed; }, // Get the previous value of an attribute, recorded at the time the last // `"change"` event was fired. previous: function(attr) { if (attr == null || !this._previousAttributes) return null; return this._previousAttributes[attr]; }, // Get all of the attributes of the model at the time of the previous // `"change"` event. previousAttributes: function() { return _.clone(this._previousAttributes); }, // --------------------------------------------------------------------- // Fetch the model from the server. If the server's representation of the // model differs from its current attributes, they will be overriden, // triggering a `"change"` event. fetch: function(options) { options = options ? _.clone(options) : {}; if (options.parse === void 0) options.parse = true; var success = options.success; options.success = function(model, resp, options) { if (!model.set(model.parse(resp, options), options)) return false; if (success) success(model, resp, options); }; return this.sync('read', this, options); }, // Set a hash of model attributes, and sync the model to the server. // If the server returns an attributes hash that differs, the model's // state will be `set` again. save: function(key, val, options) { var attrs, success, method, xhr, attributes = this.attributes; // Handle both `"key", value` and `{key: value}` -style arguments. if (key == null || typeof key === 'object') { attrs = key; options = val; } else { (attrs = {})[key] = val; } // If we're not waiting and attributes exist, save acts as `set(attr).save(null, opts)`. if (attrs && (!options || !options.wait) && !this.set(attrs, options)) return false; options = _.extend({validate: true}, options); // Do not persist invalid models. if (!this._validate(attrs, options)) return false; // Set temporary attributes if `{wait: true}`. if (attrs && options.wait) { this.attributes = _.extend({}, attributes, attrs); } // After a successful server-side save, the client is (optionally) // updated with the server-side state. if (options.parse === void 0) options.parse = true; success = options.success; options.success = function(model, resp, options) { // Ensure attributes are restored during synchronous saves. model.attributes = attributes; var serverAttrs = model.parse(resp, options); if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs); if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) { return false; } if (success) success(model, resp, options); }; // Finish configuring and sending the Ajax request. method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update'); if (method === 'patch') options.attrs = attrs; xhr = this.sync(method, this, options); // Restore attributes. if (attrs && options.wait) this.attributes = attributes; return xhr; }, // Destroy this model on the server if it was already persisted. // Optimistically removes the model from its collection, if it has one. // If `wait: true` is passed, waits for the server to respond before removal. destroy: function(options) { options = options ? _.clone(options) : {}; var model = this; var success = options.success; var destroy = function() { model.trigger('destroy', model, model.collection, options); }; options.success = function(model, resp, options) { if (options.wait || model.isNew()) destroy(); if (success) success(model, resp, options); }; if (this.isNew()) { options.success(this, null, options); return false; } var xhr = this.sync('delete', this, options); if (!options.wait) destroy(); return xhr; }, // Default URL for the model's representation on the server -- if you're // using Backbone's restful methods, override this to change the endpoint // that will be called. url: function() { var base = _.result(this, 'urlRoot') || _.result(this.collection, 'url') || urlError(); if (this.isNew()) return base; return base + (base.charAt(base.length - 1) === '/' ? '' : '/') + encodeURIComponent(this.id); }, // **parse** converts a response into the hash of attributes to be `set` on // the model. The default implementation is just to pass the response along. parse: function(resp, options) { return resp; }, // Create a new model with identical attributes to this one. clone: function() { return new this.constructor(this.attributes); }, // A model is new if it has never been saved to the server, and lacks an id. isNew: function() { return this.id == null; }, // Check if the model is currently in a valid state. isValid: function(options) { return !this.validate || !this.validate(this.attributes, options); }, // Run validation against the next complete set of model attributes, // returning `true` if all is well. Otherwise, fire a general // `"error"` event and call the error callback, if specified. _validate: function(attrs, options) { if (!options.validate || !this.validate) return true; attrs = _.extend({}, this.attributes, attrs); var error = this.validationError = this.validate(attrs, options) || null; if (!error) return true; this.trigger('invalid', this, error, options || {}); return false; } }); // Backbone.Collection // ------------------- // Provides a standard collection class for our sets of models, ordered // or unordered. If a `comparator` is specified, the Collection will maintain // its models in sort order, as they're added and removed. var Collection = Backbone.Collection = function(models, options) { options || (options = {}); if (options.model) this.model = options.model; if (options.comparator !== void 0) this.comparator = options.comparator; this.models = []; this._reset(); this.initialize.apply(this, arguments); if (models) this.reset(models, _.extend({silent: true}, options)); }; // Define the Collection's inheritable methods. _.extend(Collection.prototype, Events, { // The default model for a collection is just a **Backbone.Model**. // This should be overridden in most cases. model: Model, // Initialize is an empty function by default. Override it with your own // initialization logic. initialize: function(){}, // The JSON representation of a Collection is an array of the // models' attributes. toJSON: function(options) { return this.map(function(model){ return model.toJSON(options); }); }, // Proxy `Backbone.sync` by default. sync: function() { return Backbone.sync.apply(this, arguments); }, // Add a model, or list of models to the set. add: function(models, options) { models = _.isArray(models) ? models.slice() : [models]; options || (options = {}); var i, l, model, attrs, existing, doSort, add, at, sort, sortAttr; add = []; at = options.at; sort = this.comparator && (at == null) && options.sort != false; sortAttr = _.isString(this.comparator) ? this.comparator : null; // Turn bare objects into model references, and prevent invalid models // from being added. for (i = 0, l = models.length; i < l; i++) { if (!(model = this._prepareModel(attrs = models[i], options))) { this.trigger('invalid', this, attrs, options); continue; } // If a duplicate is found, prevent it from being added and // optionally merge it into the existing model. if (existing = this.get(model)) { if (options.merge) { existing.set(attrs === model ? model.attributes : attrs, options); if (sort && !doSort && existing.hasChanged(sortAttr)) doSort = true; } continue; } // This is a new model, push it to the `add` list. add.push(model); // Listen to added models' events, and index models for lookup by // `id` and by `cid`. model.on('all', this._onModelEvent, this); this._byId[model.cid] = model; if (model.id != null) this._byId[model.id] = model; } // See if sorting is needed, update `length` and splice in new models. if (add.length) { if (sort) doSort = true; this.length += add.length; if (at != null) { splice.apply(this.models, [at, 0].concat(add)); } else { push.apply(this.models, add); } } // Silently sort the collection if appropriate. if (doSort) this.sort({silent: true}); if (options.silent) return this; // Trigger `add` events. for (i = 0, l = add.length; i < l; i++) { (model = add[i]).trigger('add', model, this, options); } // Trigger `sort` if the collection was sorted. if (doSort) this.trigger('sort', this, options); return this; }, // Remove a model, or a list of models from the set. remove: function(models, options) { models = _.isArray(models) ? models.slice() : [models]; options || (options = {}); var i, l, index, model; for (i = 0, l = models.length; i < l; i++) { model = this.get(models[i]); if (!model) continue; delete this._byId[model.id]; delete this._byId[model.cid]; index = this.indexOf(model); this.models.splice(index, 1); this.length--; if (!options.silent) { options.index = index; model.trigger('remove', model, this, options); } this._removeReference(model); } return this; }, // Add a model to the end of the collection. push: function(model, options) { model = this._prepareModel(model, options); this.add(model, _.extend({at: this.length}, options)); return model; }, // Remove a model from the end of the collection. pop: function(options) { var model = this.at(this.length - 1); this.remove(model, options); return model; }, // Add a model to the beginning of the collection. unshift: function(model, options) { model = this._prepareModel(model, options); this.add(model, _.extend({at: 0}, options)); return model; }, // Remove a model from the beginning of the collection. shift: function(options) { var model = this.at(0); this.remove(model, options); return model; }, // Slice out a sub-array of models from the collection. slice: function(begin, end) { return this.models.slice(begin, end); }, // Get a model from the set by id. get: function(obj) { if (obj == null) return void 0; this._idAttr || (this._idAttr = this.model.prototype.idAttribute); return this._byId[obj.id || obj.cid || obj[this._idAttr] || obj]; }, // Get the model at the given index. at: function(index) { return this.models[index]; }, // Return models with matching attributes. Useful for simple cases of `filter`. where: function(attrs) { if (_.isEmpty(attrs)) return []; return this.filter(function(model) { for (var key in attrs) { if (attrs[key] !== model.get(key)) return false; } return true; }); }, // Force the collection to re-sort itself. You don't need to call this under // normal circumstances, as the set will maintain sort order as each item // is added. sort: function(options) { if (!this.comparator) { throw new Error('Cannot sort a set without a comparator'); } options || (options = {}); // Run sort based on type of `comparator`. if (_.isString(this.comparator) || this.comparator.length === 1) { this.models = this.sortBy(this.comparator, this); } else { this.models.sort(_.bind(this.comparator, this)); } if (!options.silent) this.trigger('sort', this, options); return this; }, // Pluck an attribute from each model in the collection. pluck: function(attr) { return _.invoke(this.models, 'get', attr); }, // Smartly update a collection with a change set of models, adding, // removing, and merging as necessary. update: function(models, options) { options = _.extend({add: true, merge: true, remove: true}, options); if (options.parse) models = this.parse(models, options); var model, i, l, existing; var add = [], remove = [], modelMap = {}; // Allow a single model (or no argument) to be passed. if (!_.isArray(models)) models = models ? [models] : []; // Proxy to `add` for this case, no need to iterate... if (options.add && !options.remove) return this.add(models, options); // Determine which models to add and merge, and which to remove. for (i = 0, l = models.length; i < l; i++) { model = models[i]; existing = this.get(model); if (options.remove && existing) modelMap[existing.cid] = true; if ((options.add && !existing) || (options.merge && existing)) { add.push(model); } } if (options.remove) { for (i = 0, l = this.models.length; i < l; i++) { model = this.models[i]; if (!modelMap[model.cid]) remove.push(model); } } // Remove models (if applicable) before we add and merge the rest. if (remove.length) this.remove(remove, options); if (add.length) this.add(add, options); return this; }, // When you have more items than you want to add or remove individually, // you can reset the entire set with a new list of models, without firing // any `add` or `remove` events. Fires `reset` when finished. reset: function(models, options) { options || (options = {}); if (options.parse) models = this.parse(models, options); for (var i = 0, l = this.models.length; i < l; i++) { this._removeReference(this.models[i]); } options.previousModels = this.models.slice(); this._reset(); if (models) this.add(models, _.extend({silent: true}, options)); if (!options.silent) this.trigger('reset', this, options); return this; }, // Fetch the default set of models for this collection, resetting the // collection when they arrive. If `update: true` is passed, the response // data will be passed through the `update` method instead of `reset`. fetch: function(options) { options = options ? _.clone(options) : {}; if (options.parse === void 0) options.parse = true; var success = options.success; options.success = function(collection, resp, options) { var method = options.update ? 'update' : 'reset'; collection[method](resp, options); if (success) success(collection, resp, options); }; return this.sync('read', this, options); }, // Create a new instance of a model in this collection. Add the model to the // collection immediately, unless `wait: true` is passed, in which case we // wait for the server to agree. create: function(model, options) { options = options ? _.clone(options) : {}; if (!(model = this._prepareModel(model, options))) return false; if (!options.wait) this.add(model, options); var collection = this; var success = options.success; options.success = function(model, resp, options) { if (options.wait) collection.add(model, options); if (success) success(model, resp, options); }; model.save(null, options); return model; }, // **parse** converts a response into a list of models to be added to the // collection. The default implementation is just to pass it through. parse: function(resp, options) { return resp; }, // Create a new collection with an identical list of models as this one. clone: function() { return new this.constructor(this.models); }, // Reset all internal state. Called when the collection is reset. _reset: function() { this.length = 0; this.models.length = 0; this._byId = {}; }, // Prepare a model or hash of attributes to be added to this collection. _prepareModel: function(attrs, options) { if (attrs instanceof Model) { if (!attrs.collection) attrs.collection = this; return attrs; } options || (options = {}); options.collection = this; var model = new this.model(attrs, options); if (!model._validate(attrs, options)) return false; return model; }, // Internal method to remove a model's ties to a collection. _removeReference: function(model) { if (this === model.collection) delete model.collection; model.off('all', this._onModelEvent, this); }, // Internal method called every time a model in the set fires an event. // Sets need to update their indexes when models change ids. All other // events simply proxy through. "add" and "remove" events that originate // in other collections are ignored. _onModelEvent: function(event, model, collection, options) { if ((event === 'add' || event === 'remove') && collection !== this) return; if (event === 'destroy') this.remove(model, options); if (model && event === 'change:' + model.idAttribute) { delete this._byId[model.previous(model.idAttribute)]; if (model.id != null) this._byId[model.id] = model; } this.trigger.apply(this, arguments); }, sortedIndex: function (model, value, context) { value || (value = this.comparator); var iterator = _.isFunction(value) ? value : function(model) { return model.get(value); }; return _.sortedIndex(this.models, model, iterator, context); } }); // Underscore methods that we want to implement on the Collection. var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl', 'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select', 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke', 'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest', 'tail', 'drop', 'last', 'without', 'indexOf', 'shuffle', 'lastIndexOf', 'isEmpty', 'chain']; // Mix in each Underscore method as a proxy to `Collection#models`. _.each(methods, function(method) { Collection.prototype[method] = function() { var args = slice.call(arguments); args.unshift(this.models); return _[method].apply(_, args); }; }); // Underscore methods that take a property name as an argument. var attributeMethods = ['groupBy', 'countBy', 'sortBy']; // Use attributes instead of properties. _.each(attributeMethods, function(method) { Collection.prototype[method] = function(value, context) { var iterator = _.isFunction(value) ? value : function(model) { return model.get(value); }; return _[method](this.models, iterator, context); }; }); // Backbone.Router // --------------- // Routers map faux-URLs to actions, and fire events when routes are // matched. Creating a new one sets its `routes` hash, if not set statically. var Router = Backbone.Router = function(options) { options || (options = {}); if (options.routes) this.routes = options.routes; this._bindRoutes(); this.initialize.apply(this, arguments); }; // Cached regular expressions for matching named param parts and splatted // parts of route strings. var optionalParam = /\((.*?)\)/g; var namedParam = /(\(\?)?:\w+/g; var splatParam = /\*\w+/g; var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; // Set up all inheritable **Backbone.Router** properties and methods. _.extend(Router.prototype, Events, { // Initialize is an empty function by default. Override it with your own // initialization logic. initialize: function(){}, // Manually bind a single named route to a callback function. route: function(route, name, callback) { if (!_.isRegExp(route)) route = this._routeToRegExp(route); if (!callback) callback = this[name]; Backbone.history.route(route, _.bind(function(fragment) { var args = this._extractParameters(route, fragment); callback && callback.apply(this, args); this.trigger.apply(this, ['route:' + name].concat(args)); this.trigger('route', name, args); Backbone.history.trigger('route', this, name, args); }, this)); return this; }, // Simple proxy to `Backbone.history` to save a fragment into the history. navigate: function(fragment, options) { Backbone.history.navigate(fragment, options); return this; }, // Bind all defined routes to `Backbone.history`. We have to reverse the // order of the routes here to support behavior where the most general // routes can be defined at the bottom of the route map. _bindRoutes: function() { if (!this.routes) return; var route, routes = _.keys(this.routes); while ((route = routes.pop()) != null) { this.route(route, this.routes[route]); } }, // Convert a route string into a regular expression, suitable for matching // against the current location hash. _routeToRegExp: function(route) { route = route.replace(escapeRegExp, '\\$&') .replace(optionalParam, '(?:$1)?') .replace(namedParam, function(match, optional){ return optional ? match : '([^\/]+)'; }) .replace(splatParam, '(.*?)'); return new RegExp('^' + route + '$'); }, // Given a route, and a URL fragment that it matches, return the array of // extracted parameters. _extractParameters: function(route, fragment) { return route.exec(fragment).slice(1); } }); // Backbone.History // ---------------- // Handles cross-browser history management, based on URL fragments. If the // browser does not support `onhashchange`, falls back to polling. var History = Backbone.History = function() { this.handlers = []; _.bindAll(this, 'checkUrl'); // Ensure that `History` can be used outside of the browser. if (typeof window !== 'undefined') { this.location = window.location; this.history = window.history; } }; // Cached regex for stripping a leading hash/slash and trailing space. var routeStripper = /^[#\/]|\s+$/g; // Cached regex for stripping leading and trailing slashes. var rootStripper = /^\/+|\/+$/g; // Cached regex for detecting MSIE. var isExplorer = /msie [\w.]+/; // Cached regex for removing a trailing slash. var trailingSlash = /\/$/; // Has the history handling already been started? History.started = false; // Set up all inheritable **Backbone.History** properties and methods. _.extend(History.prototype, Events, { // The default interval to poll for hash changes, if necessary, is // twenty times a second. interval: 50, // Gets the true hash value. Cannot use location.hash directly due to bug // in Firefox where location.hash will always be decoded. getHash: function(window) { var match = (window || this).location.href.match(/#(.*)$/); return match ? match[1] : ''; }, // Get the cross-browser normalized URL fragment, either from the URL, // the hash, or the override. getFragment: function(fragment, forcePushState) { if (fragment == null) { if (this._hasPushState || !this._wantsHashChange || forcePushState) { fragment = this.location.pathname; var root = this.root.replace(trailingSlash, ''); if (!fragment.indexOf(root)) fragment = fragment.substr(root.length); } else { fragment = this.getHash(); } } return fragment.replace(routeStripper, ''); }, // Start the hash change handling, returning `true` if the current URL matches // an existing route, and `false` otherwise. start: function(options) { if (History.started) throw new Error("Backbone.history has already been started"); History.started = true; // Figure out the initial configuration. Do we need an iframe? // Is pushState desired ... is it available? this.options = _.extend({}, {root: '/'}, this.options, options); this.root = this.options.root; this._wantsHashChange = this.options.hashChange !== false; this._wantsPushState = !!this.options.pushState; this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); var fragment = this.getFragment(); var docMode = document.documentMode; var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7)); // Normalize root to always include a leading and trailing slash. this.root = ('/' + this.root + '/').replace(rootStripper, '/'); if (oldIE && this._wantsHashChange) { this.iframe = Backbone.$('' : ''); inst._keyEvent = false; return html; }, /* Generate the month and year header. */ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, secondary, monthNames, monthNamesShort) { var changeMonth = this._get(inst, 'changeMonth'); var changeYear = this._get(inst, 'changeYear'); var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); var html = '
'; var monthHtml = ''; // month selection if (secondary || !changeMonth) monthHtml += '' + monthNames[drawMonth] + ''; else { var inMinYear = (minDate && minDate.getFullYear() == drawYear); var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); monthHtml += ''; } if (!showMonthAfterYear) html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : ''); // year selection if ( !inst.yearshtml ) { inst.yearshtml = ''; if (secondary || !changeYear) html += '' + drawYear + ''; else { // determine range of years to display var years = this._get(inst, 'yearRange').split(':'); var thisYear = new Date().getFullYear(); var determineYear = function(value) { var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : parseInt(value, 10))); return (isNaN(year) ? thisYear : year); }; var year = determineYear(years[0]); var endYear = Math.max(year, determineYear(years[1] || '')); year = (minDate ? Math.max(year, minDate.getFullYear()) : year); endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); inst.yearshtml += ''; html += inst.yearshtml; inst.yearshtml = null; } } html += this._get(inst, 'yearSuffix'); if (showMonthAfterYear) html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml; html += '
'; // Close datepicker_header return html; }, /* Adjust one of the date sub-fields. */ _adjustInstDate: function(inst, offset, period) { var year = inst.drawYear + (period == 'Y' ? offset : 0); var month = inst.drawMonth + (period == 'M' ? offset : 0); var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period == 'D' ? offset : 0); var date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); inst.selectedDay = date.getDate(); inst.drawMonth = inst.selectedMonth = date.getMonth(); inst.drawYear = inst.selectedYear = date.getFullYear(); if (period == 'M' || period == 'Y') this._notifyChange(inst); }, /* Ensure a date is within any min/max bounds. */ _restrictMinMax: function(inst, date) { var minDate = this._getMinMaxDate(inst, 'min'); var maxDate = this._getMinMaxDate(inst, 'max'); var newDate = (minDate && date < minDate ? minDate : date); newDate = (maxDate && newDate > maxDate ? maxDate : newDate); return newDate; }, /* Notify change of month/year. */ _notifyChange: function(inst) { var onChange = this._get(inst, 'onChangeMonthYear'); if (onChange) onChange.apply((inst.input ? inst.input[0] : null), [inst.selectedYear, inst.selectedMonth + 1, inst]); }, /* Determine the number of months to show. */ _getNumberOfMonths: function(inst) { var numMonths = this._get(inst, 'numberOfMonths'); return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); }, /* Determine the current maximum date - ensure no time components are set. */ _getMinMaxDate: function(inst, minMax) { return this._determineDate(inst, this._get(inst, minMax + 'Date'), null); }, /* Find the number of days in a given month. */ _getDaysInMonth: function(year, month) { return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); }, /* Find the day of the week of the first of a month. */ _getFirstDayOfMonth: function(year, month) { return new Date(year, month, 1).getDay(); }, /* Determines if we should allow a "next/prev" month display change. */ _canAdjustMonth: function(inst, offset, curYear, curMonth) { var numMonths = this._getNumberOfMonths(inst); var date = this._daylightSavingAdjust(new Date(curYear, curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); if (offset < 0) date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); return this._isInRange(inst, date); }, /* Is the given date in the accepted range? */ _isInRange: function(inst, date) { var minDate = this._getMinMaxDate(inst, 'min'); var maxDate = this._getMinMaxDate(inst, 'max'); return ((!minDate || date.getTime() >= minDate.getTime()) && (!maxDate || date.getTime() <= maxDate.getTime())); }, /* Provide the configuration settings for formatting/parsing. */ _getFormatConfig: function(inst) { var shortYearCutoff = this._get(inst, 'shortYearCutoff'); shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); return {shortYearCutoff: shortYearCutoff, dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; }, /* Format the given date for display. */ _formatDate: function(inst, day, month, year) { if (!day) { inst.currentDay = inst.selectedDay; inst.currentMonth = inst.selectedMonth; inst.currentYear = inst.selectedYear; } var date = (day ? (typeof day == 'object' ? day : this._daylightSavingAdjust(new Date(year, month, day))) : this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); } }); /* * Bind hover events for datepicker elements. * Done via delegate so the binding only occurs once in the lifetime of the parent div. * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. */ function bindHover(dpDiv) { var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; return dpDiv.bind('mouseout', function(event) { var elem = $( event.target ).closest( selector ); if ( !elem.length ) { return; } elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" ); }) .bind('mouseover', function(event) { var elem = $( event.target ).closest( selector ); if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) || !elem.length ) { return; } elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); elem.addClass('ui-state-hover'); if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover'); if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover'); }); } /* jQuery extend now ignores nulls! */ function extendRemove(target, props) { $.extend(target, props); for (var name in props) if (props[name] == null || props[name] == undefined) target[name] = props[name]; return target; }; /* Determine whether an object is an array. */ function isArray(a) { return (a && (($.browser.safari && typeof a == 'object' && a.length) || (a.constructor && a.constructor.toString().match(/\Array\(\)/)))); }; /* Invoke the datepicker functionality. @param options string - a command, optionally followed by additional parameters or Object - settings for attaching new datepicker functionality @return jQuery object */ $.fn.datepicker = function(options){ /* Verify an empty collection wasn't passed - Fixes #6976 */ if ( !this.length ) { return this; } /* Initialise the date picker. */ if (!$.datepicker.initialized) { $(document).mousedown($.datepicker._checkExternalClick). find('body').append($.datepicker.dpDiv); $.datepicker.initialized = true; } var otherArgs = Array.prototype.slice.call(arguments, 1); if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget')) return $.datepicker['_' + options + 'Datepicker']. apply($.datepicker, [this[0]].concat(otherArgs)); if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') return $.datepicker['_' + options + 'Datepicker']. apply($.datepicker, [this[0]].concat(otherArgs)); return this.each(function() { typeof options == 'string' ? $.datepicker['_' + options + 'Datepicker']. apply($.datepicker, [this].concat(otherArgs)) : $.datepicker._attachDatepicker(this, options); }); }; $.datepicker = new Datepicker(); // singleton instance $.datepicker.initialized = false; $.datepicker.uuid = new Date().getTime(); $.datepicker.version = "1.8.20"; // Workaround for #4055 // Add another global to avoid noConflict issues with inline event handlers window['DP_jQuery_' + dpuuid] = $; })(jQuery); (function( $, undefined ) { var uiDialogClasses = 'ui-dialog ' + 'ui-widget ' + 'ui-widget-content ' + 'ui-corner-all ', sizeRelatedOptions = { buttons: true, height: true, maxHeight: true, maxWidth: true, minHeight: true, minWidth: true, width: true }, resizableRelatedOptions = { maxHeight: true, maxWidth: true, minHeight: true, minWidth: true }, // support for jQuery 1.3.2 - handle common attrFn methods for dialog attrFn = $.attrFn || { val: true, css: true, html: true, text: true, data: true, width: true, height: true, offset: true, click: true }; $.widget("ui.dialog", { options: { autoOpen: true, buttons: {}, closeOnEscape: true, closeText: 'close', dialogClass: '', draggable: true, hide: null, height: 'auto', maxHeight: false, maxWidth: false, minHeight: 150, minWidth: 150, modal: false, position: { my: 'center', at: 'center', collision: 'fit', // ensure that the titlebar is never outside the document using: function(pos) { var topOffset = $(this).css(pos).offset().top; if (topOffset < 0) { $(this).css('top', pos.top - topOffset); } } }, resizable: true, show: null, stack: true, title: '', width: 300, zIndex: 1000 }, _create: function() { this.originalTitle = this.element.attr('title'); // #5742 - .attr() might return a DOMElement if ( typeof this.originalTitle !== "string" ) { this.originalTitle = ""; } this.options.title = this.options.title || this.originalTitle; var self = this, options = self.options, title = options.title || ' ', titleId = $.ui.dialog.getTitleId(self.element), uiDialog = (self.uiDialog = $('
')) .appendTo(document.body) .hide() .addClass(uiDialogClasses + options.dialogClass) .css({ zIndex: options.zIndex }) // setting tabIndex makes the div focusable // setting outline to 0 prevents a border on focus in Mozilla .attr('tabIndex', -1).css('outline', 0).keydown(function(event) { if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && event.keyCode === $.ui.keyCode.ESCAPE) { self.close(event); event.preventDefault(); } }) .attr({ role: 'dialog', 'aria-labelledby': titleId }) .mousedown(function(event) { self.moveToTop(false, event); }), uiDialogContent = self.element .show() .removeAttr('title') .addClass( 'ui-dialog-content ' + 'ui-widget-content') .appendTo(uiDialog), uiDialogTitlebar = (self.uiDialogTitlebar = $('
')) .addClass( 'ui-dialog-titlebar ' + 'ui-widget-header ' + 'ui-corner-all ' + 'ui-helper-clearfix' ) .prependTo(uiDialog), uiDialogTitlebarClose = $('') .addClass( 'ui-dialog-titlebar-close ' + 'ui-corner-all' ) .attr('role', 'button') .hover( function() { uiDialogTitlebarClose.addClass('ui-state-hover'); }, function() { uiDialogTitlebarClose.removeClass('ui-state-hover'); } ) .focus(function() { uiDialogTitlebarClose.addClass('ui-state-focus'); }) .blur(function() { uiDialogTitlebarClose.removeClass('ui-state-focus'); }) .click(function(event) { self.close(event); return false; }) .appendTo(uiDialogTitlebar), uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('')) .addClass( 'ui-icon ' + 'ui-icon-closethick' ) .text(options.closeText) .appendTo(uiDialogTitlebarClose), uiDialogTitle = $('') .addClass('ui-dialog-title') .attr('id', titleId) .html(title) .prependTo(uiDialogTitlebar); //handling of deprecated beforeclose (vs beforeClose) option //Ticket #4669 http://dev.jqueryui.com/ticket/4669 //TODO: remove in 1.9pre if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) { options.beforeClose = options.beforeclose; } uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection(); if (options.draggable && $.fn.draggable) { self._makeDraggable(); } if (options.resizable && $.fn.resizable) { self._makeResizable(); } self._createButtons(options.buttons); self._isOpen = false; if ($.fn.bgiframe) { uiDialog.bgiframe(); } }, _init: function() { if ( this.options.autoOpen ) { this.open(); } }, destroy: function() { var self = this; if (self.overlay) { self.overlay.destroy(); } self.uiDialog.hide(); self.element .unbind('.dialog') .removeData('dialog') .removeClass('ui-dialog-content ui-widget-content') .hide().appendTo('body'); self.uiDialog.remove(); if (self.originalTitle) { self.element.attr('title', self.originalTitle); } return self; }, widget: function() { return this.uiDialog; }, close: function(event) { var self = this, maxZ, thisZ; if (false === self._trigger('beforeClose', event)) { return; } if (self.overlay) { self.overlay.destroy(); } self.uiDialog.unbind('keypress.ui-dialog'); self._isOpen = false; if (self.options.hide) { self.uiDialog.hide(self.options.hide, function() { self._trigger('close', event); }); } else { self.uiDialog.hide(); self._trigger('close', event); } $.ui.dialog.overlay.resize(); // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) if (self.options.modal) { maxZ = 0; $('.ui-dialog').each(function() { if (this !== self.uiDialog[0]) { thisZ = $(this).css('z-index'); if(!isNaN(thisZ)) { maxZ = Math.max(maxZ, thisZ); } } }); $.ui.dialog.maxZ = maxZ; } return self; }, isOpen: function() { return this._isOpen; }, // the force parameter allows us to move modal dialogs to their correct // position on open moveToTop: function(force, event) { var self = this, options = self.options, saveScroll; if ((options.modal && !force) || (!options.stack && !options.modal)) { return self._trigger('focus', event); } if (options.zIndex > $.ui.dialog.maxZ) { $.ui.dialog.maxZ = options.zIndex; } if (self.overlay) { $.ui.dialog.maxZ += 1; self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ); } //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed. // http://ui.jquery.com/bugs/ticket/3193 saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() }; $.ui.dialog.maxZ += 1; self.uiDialog.css('z-index', $.ui.dialog.maxZ); self.element.attr(saveScroll); self._trigger('focus', event); return self; }, open: function() { if (this._isOpen) { return; } var self = this, options = self.options, uiDialog = self.uiDialog; self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null; self._size(); self._position(options.position); uiDialog.show(options.show); self.moveToTop(true); // prevent tabbing out of modal dialogs if ( options.modal ) { uiDialog.bind( "keydown.ui-dialog", function( event ) { if ( event.keyCode !== $.ui.keyCode.TAB ) { return; } var tabbables = $(':tabbable', this), first = tabbables.filter(':first'), last = tabbables.filter(':last'); if (event.target === last[0] && !event.shiftKey) { first.focus(1); return false; } else if (event.target === first[0] && event.shiftKey) { last.focus(1); return false; } }); } // set focus to the first tabbable element in the content area or the first button // if there are no tabbable elements, set focus on the dialog itself $(self.element.find(':tabbable').get().concat( uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat( uiDialog.get()))).eq(0).focus(); self._isOpen = true; self._trigger('open'); return self; }, _createButtons: function(buttons) { var self = this, hasButtons = false, uiDialogButtonPane = $('
') .addClass( 'ui-dialog-buttonpane ' + 'ui-widget-content ' + 'ui-helper-clearfix' ), uiButtonSet = $( "
" ) .addClass( "ui-dialog-buttonset" ) .appendTo( uiDialogButtonPane ); // if we already have a button pane, remove it self.uiDialog.find('.ui-dialog-buttonpane').remove(); if (typeof buttons === 'object' && buttons !== null) { $.each(buttons, function() { return !(hasButtons = true); }); } if (hasButtons) { $.each(buttons, function(name, props) { props = $.isFunction( props ) ? { click: props, text: name } : props; var button = $('') .click(function() { props.click.apply(self.element[0], arguments); }) .appendTo(uiButtonSet); // can't use .attr( props, true ) with jQuery 1.3.2. $.each( props, function( key, value ) { if ( key === "click" ) { return; } if ( key in attrFn ) { button[ key ]( value ); } else { button.attr( key, value ); } }); if ($.fn.button) { button.button(); } }); uiDialogButtonPane.appendTo(self.uiDialog); } }, _makeDraggable: function() { var self = this, options = self.options, doc = $(document), heightBeforeDrag; function filteredUi(ui) { return { position: ui.position, offset: ui.offset }; } self.uiDialog.draggable({ cancel: '.ui-dialog-content, .ui-dialog-titlebar-close', handle: '.ui-dialog-titlebar', containment: 'document', start: function(event, ui) { heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height(); $(this).height($(this).height()).addClass("ui-dialog-dragging"); self._trigger('dragStart', event, filteredUi(ui)); }, drag: function(event, ui) { self._trigger('drag', event, filteredUi(ui)); }, stop: function(event, ui) { options.position = [ui.position.left - doc.scrollLeft(), ui.position.top - doc.scrollTop()]; $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag); self._trigger('dragStop', event, filteredUi(ui)); $.ui.dialog.overlay.resize(); } }); }, _makeResizable: function(handles) { handles = (handles === undefined ? this.options.resizable : handles); var self = this, options = self.options, // .ui-resizable has position: relative defined in the stylesheet // but dialogs have to use absolute or fixed positioning position = self.uiDialog.css('position'), resizeHandles = (typeof handles === 'string' ? handles : 'n,e,s,w,se,sw,ne,nw' ); function filteredUi(ui) { return { originalPosition: ui.originalPosition, originalSize: ui.originalSize, position: ui.position, size: ui.size }; } self.uiDialog.resizable({ cancel: '.ui-dialog-content', containment: 'document', alsoResize: self.element, maxWidth: options.maxWidth, maxHeight: options.maxHeight, minWidth: options.minWidth, minHeight: self._minHeight(), handles: resizeHandles, start: function(event, ui) { $(this).addClass("ui-dialog-resizing"); self._trigger('resizeStart', event, filteredUi(ui)); }, resize: function(event, ui) { self._trigger('resize', event, filteredUi(ui)); }, stop: function(event, ui) { $(this).removeClass("ui-dialog-resizing"); options.height = $(this).height(); options.width = $(this).width(); self._trigger('resizeStop', event, filteredUi(ui)); $.ui.dialog.overlay.resize(); } }) .css('position', position) .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se'); }, _minHeight: function() { var options = this.options; if (options.height === 'auto') { return options.minHeight; } else { return Math.min(options.minHeight, options.height); } }, _position: function(position) { var myAt = [], offset = [0, 0], isVisible; if (position) { // deep extending converts arrays to objects in jQuery <= 1.3.2 :-( // if (typeof position == 'string' || $.isArray(position)) { // myAt = $.isArray(position) ? position : position.split(' '); if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) { myAt = position.split ? position.split(' ') : [position[0], position[1]]; if (myAt.length === 1) { myAt[1] = myAt[0]; } $.each(['left', 'top'], function(i, offsetPosition) { if (+myAt[i] === myAt[i]) { offset[i] = myAt[i]; myAt[i] = offsetPosition; } }); position = { my: myAt.join(" "), at: myAt.join(" "), offset: offset.join(" ") }; } position = $.extend({}, $.ui.dialog.prototype.options.position, position); } else { position = $.ui.dialog.prototype.options.position; } // need to show the dialog to get the actual offset in the position plugin isVisible = this.uiDialog.is(':visible'); if (!isVisible) { this.uiDialog.show(); } this.uiDialog // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 .css({ top: 0, left: 0 }) .position($.extend({ of: window }, position)); if (!isVisible) { this.uiDialog.hide(); } }, _setOptions: function( options ) { var self = this, resizableOptions = {}, resize = false; $.each( options, function( key, value ) { self._setOption( key, value ); if ( key in sizeRelatedOptions ) { resize = true; } if ( key in resizableRelatedOptions ) { resizableOptions[ key ] = value; } }); if ( resize ) { this._size(); } if ( this.uiDialog.is( ":data(resizable)" ) ) { this.uiDialog.resizable( "option", resizableOptions ); } }, _setOption: function(key, value){ var self = this, uiDialog = self.uiDialog; switch (key) { //handling of deprecated beforeclose (vs beforeClose) option //Ticket #4669 http://dev.jqueryui.com/ticket/4669 //TODO: remove in 1.9pre case "beforeclose": key = "beforeClose"; break; case "buttons": self._createButtons(value); break; case "closeText": // ensure that we always pass a string self.uiDialogTitlebarCloseText.text("" + value); break; case "dialogClass": uiDialog .removeClass(self.options.dialogClass) .addClass(uiDialogClasses + value); break; case "disabled": if (value) { uiDialog.addClass('ui-dialog-disabled'); } else { uiDialog.removeClass('ui-dialog-disabled'); } break; case "draggable": var isDraggable = uiDialog.is( ":data(draggable)" ); if ( isDraggable && !value ) { uiDialog.draggable( "destroy" ); } if ( !isDraggable && value ) { self._makeDraggable(); } break; case "position": self._position(value); break; case "resizable": // currently resizable, becoming non-resizable var isResizable = uiDialog.is( ":data(resizable)" ); if (isResizable && !value) { uiDialog.resizable('destroy'); } // currently resizable, changing handles if (isResizable && typeof value === 'string') { uiDialog.resizable('option', 'handles', value); } // currently non-resizable, becoming resizable if (!isResizable && value !== false) { self._makeResizable(value); } break; case "title": // convert whatever was passed in o a string, for html() to not throw up $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || ' ')); break; } $.Widget.prototype._setOption.apply(self, arguments); }, _size: function() { /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content * divs will both have width and height set, so we need to reset them */ var options = this.options, nonContentHeight, minContentHeight, isVisible = this.uiDialog.is( ":visible" ); // reset content sizing this.element.show().css({ width: 'auto', minHeight: 0, height: 0 }); if (options.minWidth > options.width) { options.width = options.minWidth; } // reset wrapper sizing // determine the height of all the non-content elements nonContentHeight = this.uiDialog.css({ height: 'auto', width: options.width }) .height(); minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); if ( options.height === "auto" ) { // only needed for IE6 support if ( $.support.minHeight ) { this.element.css({ minHeight: minContentHeight, height: "auto" }); } else { this.uiDialog.show(); var autoHeight = this.element.css( "height", "auto" ).height(); if ( !isVisible ) { this.uiDialog.hide(); } this.element.height( Math.max( autoHeight, minContentHeight ) ); } } else { this.element.height( Math.max( options.height - nonContentHeight, 0 ) ); } if (this.uiDialog.is(':data(resizable)')) { this.uiDialog.resizable('option', 'minHeight', this._minHeight()); } } }); $.extend($.ui.dialog, { version: "1.8.20", uuid: 0, maxZ: 0, getTitleId: function($el) { var id = $el.attr('id'); if (!id) { this.uuid += 1; id = this.uuid; } return 'ui-dialog-title-' + id; }, overlay: function(dialog) { this.$el = $.ui.dialog.overlay.create(dialog); } }); $.extend($.ui.dialog.overlay, { instances: [], // reuse old instances due to IE memory leak with alpha transparency (see #5185) oldInstances: [], maxZ: 0, events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','), function(event) { return event + '.dialog-overlay'; }).join(' '), create: function(dialog) { if (this.instances.length === 0) { // prevent use of anchors and inputs // we use a setTimeout in case the overlay is created from an // event that we're going to be cancelling (see #2804) setTimeout(function() { // handle $(el).dialog().dialog('close') (see #4065) if ($.ui.dialog.overlay.instances.length) { $(document).bind($.ui.dialog.overlay.events, function(event) { // stop events if the z-index of the target is < the z-index of the overlay // we cannot return true when we don't want to cancel the event (#3523) if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) { return false; } }); } }, 1); // allow closing by pressing the escape key $(document).bind('keydown.dialog-overlay', function(event) { if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && event.keyCode === $.ui.keyCode.ESCAPE) { dialog.close(event); event.preventDefault(); } }); // handle window resize $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize); } var $el = (this.oldInstances.pop() || $('
').addClass('ui-widget-overlay')) .appendTo(document.body) .css({ width: this.width(), height: this.height() }); if ($.fn.bgiframe) { $el.bgiframe(); } this.instances.push($el); return $el; }, destroy: function($el) { var indexOf = $.inArray($el, this.instances); if (indexOf != -1){ this.oldInstances.push(this.instances.splice(indexOf, 1)[0]); } if (this.instances.length === 0) { $([document, window]).unbind('.dialog-overlay'); } $el.remove(); // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) var maxZ = 0; $.each(this.instances, function() { maxZ = Math.max(maxZ, this.css('z-index')); }); this.maxZ = maxZ; }, height: function() { var scrollHeight, offsetHeight; // handle IE 6 if ($.browser.msie && $.browser.version < 7) { scrollHeight = Math.max( document.documentElement.scrollHeight, document.body.scrollHeight ); offsetHeight = Math.max( document.documentElement.offsetHeight, document.body.offsetHeight ); if (scrollHeight < offsetHeight) { return $(window).height() + 'px'; } else { return scrollHeight + 'px'; } // handle "good" browsers } else { return $(document).height() + 'px'; } }, width: function() { var scrollWidth, offsetWidth; // handle IE if ( $.browser.msie ) { scrollWidth = Math.max( document.documentElement.scrollWidth, document.body.scrollWidth ); offsetWidth = Math.max( document.documentElement.offsetWidth, document.body.offsetWidth ); if (scrollWidth < offsetWidth) { return $(window).width() + 'px'; } else { return scrollWidth + 'px'; } // handle "good" browsers } else { return $(document).width() + 'px'; } }, resize: function() { /* If the dialog is draggable and the user drags it past the * right edge of the window, the document becomes wider so we * need to stretch the overlay. If the user then drags the * dialog back to the left, the document will become narrower, * so we need to shrink the overlay to the appropriate size. * This is handled by shrinking the overlay before setting it * to the full document size. */ var $overlays = $([]); $.each($.ui.dialog.overlay.instances, function() { $overlays = $overlays.add(this); }); $overlays.css({ width: 0, height: 0 }).css({ width: $.ui.dialog.overlay.width(), height: $.ui.dialog.overlay.height() }); } }); $.extend($.ui.dialog.overlay.prototype, { destroy: function() { $.ui.dialog.overlay.destroy(this.$el); } }); }(jQuery)); (function( $, undefined ) { $.ui = $.ui || {}; var horizontalPositions = /left|center|right/, verticalPositions = /top|center|bottom/, center = "center", support = {}, _position = $.fn.position, _offset = $.fn.offset; $.fn.position = function( options ) { if ( !options || !options.of ) { return _position.apply( this, arguments ); } // make a copy, we don't want to modify arguments options = $.extend( {}, options ); var target = $( options.of ), targetElem = target[0], collision = ( options.collision || "flip" ).split( " " ), offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ], targetWidth, targetHeight, basePosition; if ( targetElem.nodeType === 9 ) { targetWidth = target.width(); targetHeight = target.height(); basePosition = { top: 0, left: 0 }; // TODO: use $.isWindow() in 1.9 } else if ( targetElem.setTimeout ) { targetWidth = target.width(); targetHeight = target.height(); basePosition = { top: target.scrollTop(), left: target.scrollLeft() }; } else if ( targetElem.preventDefault ) { // force left top to allow flipping options.at = "left top"; targetWidth = targetHeight = 0; basePosition = { top: options.of.pageY, left: options.of.pageX }; } else { targetWidth = target.outerWidth(); targetHeight = target.outerHeight(); basePosition = target.offset(); } // force my and at to have valid horizontal and veritcal positions // if a value is missing or invalid, it will be converted to center $.each( [ "my", "at" ], function() { var pos = ( options[this] || "" ).split( " " ); if ( pos.length === 1) { pos = horizontalPositions.test( pos[0] ) ? pos.concat( [center] ) : verticalPositions.test( pos[0] ) ? [ center ].concat( pos ) : [ center, center ]; } pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center; pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center; options[ this ] = pos; }); // normalize collision option if ( collision.length === 1 ) { collision[ 1 ] = collision[ 0 ]; } // normalize offset option offset[ 0 ] = parseInt( offset[0], 10 ) || 0; if ( offset.length === 1 ) { offset[ 1 ] = offset[ 0 ]; } offset[ 1 ] = parseInt( offset[1], 10 ) || 0; if ( options.at[0] === "right" ) { basePosition.left += targetWidth; } else if ( options.at[0] === center ) { basePosition.left += targetWidth / 2; } if ( options.at[1] === "bottom" ) { basePosition.top += targetHeight; } else if ( options.at[1] === center ) { basePosition.top += targetHeight / 2; } basePosition.left += offset[ 0 ]; basePosition.top += offset[ 1 ]; return this.each(function() { var elem = $( this ), elemWidth = elem.outerWidth(), elemHeight = elem.outerHeight(), marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, collisionWidth = elemWidth + marginLeft + ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ), collisionHeight = elemHeight + marginTop + ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ), position = $.extend( {}, basePosition ), collisionPosition; if ( options.my[0] === "right" ) { position.left -= elemWidth; } else if ( options.my[0] === center ) { position.left -= elemWidth / 2; } if ( options.my[1] === "bottom" ) { position.top -= elemHeight; } else if ( options.my[1] === center ) { position.top -= elemHeight / 2; } // prevent fractions if jQuery version doesn't support them (see #5280) if ( !support.fractions ) { position.left = Math.round( position.left ); position.top = Math.round( position.top ); } collisionPosition = { left: position.left - marginLeft, top: position.top - marginTop }; $.each( [ "left", "top" ], function( i, dir ) { if ( $.ui.position[ collision[i] ] ) { $.ui.position[ collision[i] ][ dir ]( position, { targetWidth: targetWidth, targetHeight: targetHeight, elemWidth: elemWidth, elemHeight: elemHeight, collisionPosition: collisionPosition, collisionWidth: collisionWidth, collisionHeight: collisionHeight, offset: offset, my: options.my, at: options.at }); } }); if ( $.fn.bgiframe ) { elem.bgiframe(); } elem.offset( $.extend( position, { using: options.using } ) ); }); }; $.ui.position = { fit: { left: function( position, data ) { var win = $( window ), over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left ); }, top: function( position, data ) { var win = $( window ), over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top ); } }, flip: { left: function( position, data ) { if ( data.at[0] === center ) { return; } var win = $( window ), over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), myOffset = data.my[ 0 ] === "left" ? -data.elemWidth : data.my[ 0 ] === "right" ? data.elemWidth : 0, atOffset = data.at[ 0 ] === "left" ? data.targetWidth : -data.targetWidth, offset = -2 * data.offset[ 0 ]; position.left += data.collisionPosition.left < 0 ? myOffset + atOffset + offset : over > 0 ? myOffset + atOffset + offset : 0; }, top: function( position, data ) { if ( data.at[1] === center ) { return; } var win = $( window ), over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), myOffset = data.my[ 1 ] === "top" ? -data.elemHeight : data.my[ 1 ] === "bottom" ? data.elemHeight : 0, atOffset = data.at[ 1 ] === "top" ? data.targetHeight : -data.targetHeight, offset = -2 * data.offset[ 1 ]; position.top += data.collisionPosition.top < 0 ? myOffset + atOffset + offset : over > 0 ? myOffset + atOffset + offset : 0; } } }; // offset setter from jQuery 1.4 if ( !$.offset.setOffset ) { $.offset.setOffset = function( elem, options ) { // set position first, in-case top/left are set even on static elem if ( /static/.test( $.curCSS( elem, "position" ) ) ) { elem.style.position = "relative"; } var curElem = $( elem ), curOffset = curElem.offset(), curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0, curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0, props = { top: (options.top - curOffset.top) + curTop, left: (options.left - curOffset.left) + curLeft }; if ( 'using' in options ) { options.using.call( elem, props ); } else { curElem.css( props ); } }; $.fn.offset = function( options ) { var elem = this[ 0 ]; if ( !elem || !elem.ownerDocument ) { return null; } if ( options ) { return this.each(function() { $.offset.setOffset( this, options ); }); } return _offset.call( this ); }; } // fraction support test (older versions of jQuery don't support fractions) (function () { var body = document.getElementsByTagName( "body" )[ 0 ], div = document.createElement( "div" ), testElement, testElementParent, testElementStyle, offset, offsetTotal; //Create a "fake body" for testing based on method used in jQuery.support testElement = document.createElement( body ? "div" : "body" ); testElementStyle = { visibility: "hidden", width: 0, height: 0, border: 0, margin: 0, background: "none" }; if ( body ) { $.extend( testElementStyle, { position: "absolute", left: "-1000px", top: "-1000px" }); } for ( var i in testElementStyle ) { testElement.style[ i ] = testElementStyle[ i ]; } testElement.appendChild( div ); testElementParent = body || document.documentElement; testElementParent.insertBefore( testElement, testElementParent.firstChild ); div.style.cssText = "position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;"; offset = $( div ).offset( function( _, offset ) { return offset; }).offset(); testElement.innerHTML = ""; testElementParent.removeChild( testElement ); offsetTotal = offset.top + offset.left + ( body ? 2000 : 0 ); support.fractions = offsetTotal > 21 && offsetTotal < 22; })(); }( jQuery )); (function( $, undefined ) { $.widget( "ui.progressbar", { options: { value: 0, max: 100 }, min: 0, _create: function() { this.element .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) .attr({ role: "progressbar", "aria-valuemin": this.min, "aria-valuemax": this.options.max, "aria-valuenow": this._value() }); this.valueDiv = $( "
" ) .appendTo( this.element ); this.oldValue = this._value(); this._refreshValue(); }, destroy: function() { this.element .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) .removeAttr( "role" ) .removeAttr( "aria-valuemin" ) .removeAttr( "aria-valuemax" ) .removeAttr( "aria-valuenow" ); this.valueDiv.remove(); $.Widget.prototype.destroy.apply( this, arguments ); }, value: function( newValue ) { if ( newValue === undefined ) { return this._value(); } this._setOption( "value", newValue ); return this; }, _setOption: function( key, value ) { if ( key === "value" ) { this.options.value = value; this._refreshValue(); if ( this._value() === this.options.max ) { this._trigger( "complete" ); } } $.Widget.prototype._setOption.apply( this, arguments ); }, _value: function() { var val = this.options.value; // normalize invalid value if ( typeof val !== "number" ) { val = 0; } return Math.min( this.options.max, Math.max( this.min, val ) ); }, _percentage: function() { return 100 * this._value() / this.options.max; }, _refreshValue: function() { var value = this.value(); var percentage = this._percentage(); if ( this.oldValue !== value ) { this.oldValue = value; this._trigger( "change" ); } this.valueDiv .toggle( value > this.min ) .toggleClass( "ui-corner-right", value === this.options.max ) .width( percentage.toFixed(0) + "%" ); this.element.attr( "aria-valuenow", value ); } }); $.extend( $.ui.progressbar, { version: "1.8.20" }); })( jQuery ); (function( $, undefined ) { // number of pages in a slider // (how many times can you page up/down to go through the whole range) var numPages = 5; $.widget( "ui.slider", $.ui.mouse, { widgetEventPrefix: "slide", options: { animate: false, distance: 0, max: 100, min: 0, orientation: "horizontal", range: false, step: 1, value: 0, values: null }, _create: function() { var self = this, o = this.options, existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), handle = "", handleCount = ( o.values && o.values.length ) || 1, handles = []; this._keySliding = false; this._mouseSliding = false; this._animateOff = true; this._handleIndex = null; this._detectOrientation(); this._mouseInit(); this.element .addClass( "ui-slider" + " ui-slider-" + this.orientation + " ui-widget" + " ui-widget-content" + " ui-corner-all" + ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) ); this.range = $([]); if ( o.range ) { if ( o.range === true ) { if ( !o.values ) { o.values = [ this._valueMin(), this._valueMin() ]; } if ( o.values.length && o.values.length !== 2 ) { o.values = [ o.values[0], o.values[0] ]; } } this.range = $( "
" ) .appendTo( this.element ) .addClass( "ui-slider-range" + // note: this isn't the most fittingly semantic framework class for this element, // but worked best visually with a variety of themes " ui-widget-header" + ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); } for ( var i = existingHandles.length; i < handleCount; i += 1 ) { handles.push( handle ); } this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) ); this.handle = this.handles.eq( 0 ); this.handles.add( this.range ).filter( "a" ) .click(function( event ) { event.preventDefault(); }) .hover(function() { if ( !o.disabled ) { $( this ).addClass( "ui-state-hover" ); } }, function() { $( this ).removeClass( "ui-state-hover" ); }) .focus(function() { if ( !o.disabled ) { $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" ); $( this ).addClass( "ui-state-focus" ); } else { $( this ).blur(); } }) .blur(function() { $( this ).removeClass( "ui-state-focus" ); }); this.handles.each(function( i ) { $( this ).data( "index.ui-slider-handle", i ); }); this.handles .keydown(function( event ) { var index = $( this ).data( "index.ui-slider-handle" ), allowed, curVal, newVal, step; if ( self.options.disabled ) { return; } switch ( event.keyCode ) { case $.ui.keyCode.HOME: case $.ui.keyCode.END: case $.ui.keyCode.PAGE_UP: case $.ui.keyCode.PAGE_DOWN: case $.ui.keyCode.UP: case $.ui.keyCode.RIGHT: case $.ui.keyCode.DOWN: case $.ui.keyCode.LEFT: event.preventDefault(); if ( !self._keySliding ) { self._keySliding = true; $( this ).addClass( "ui-state-active" ); allowed = self._start( event, index ); if ( allowed === false ) { return; } } break; } step = self.options.step; if ( self.options.values && self.options.values.length ) { curVal = newVal = self.values( index ); } else { curVal = newVal = self.value(); } switch ( event.keyCode ) { case $.ui.keyCode.HOME: newVal = self._valueMin(); break; case $.ui.keyCode.END: newVal = self._valueMax(); break; case $.ui.keyCode.PAGE_UP: newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) ); break; case $.ui.keyCode.PAGE_DOWN: newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) ); break; case $.ui.keyCode.UP: case $.ui.keyCode.RIGHT: if ( curVal === self._valueMax() ) { return; } newVal = self._trimAlignValue( curVal + step ); break; case $.ui.keyCode.DOWN: case $.ui.keyCode.LEFT: if ( curVal === self._valueMin() ) { return; } newVal = self._trimAlignValue( curVal - step ); break; } self._slide( event, index, newVal ); }) .keyup(function( event ) { var index = $( this ).data( "index.ui-slider-handle" ); if ( self._keySliding ) { self._keySliding = false; self._stop( event, index ); self._change( event, index ); $( this ).removeClass( "ui-state-active" ); } }); this._refreshValue(); this._animateOff = false; }, destroy: function() { this.handles.remove(); this.range.remove(); this.element .removeClass( "ui-slider" + " ui-slider-horizontal" + " ui-slider-vertical" + " ui-slider-disabled" + " ui-widget" + " ui-widget-content" + " ui-corner-all" ) .removeData( "slider" ) .unbind( ".slider" ); this._mouseDestroy(); return this; }, _mouseCapture: function( event ) { var o = this.options, position, normValue, distance, closestHandle, self, index, allowed, offset, mouseOverHandle; if ( o.disabled ) { return false; } this.elementSize = { width: this.element.outerWidth(), height: this.element.outerHeight() }; this.elementOffset = this.element.offset(); position = { x: event.pageX, y: event.pageY }; normValue = this._normValueFromMouse( position ); distance = this._valueMax() - this._valueMin() + 1; self = this; this.handles.each(function( i ) { var thisDistance = Math.abs( normValue - self.values(i) ); if ( distance > thisDistance ) { distance = thisDistance; closestHandle = $( this ); index = i; } }); // workaround for bug #3736 (if both handles of a range are at 0, // the first is always used as the one with least distance, // and moving it is obviously prevented by preventing negative ranges) if( o.range === true && this.values(1) === o.min ) { index += 1; closestHandle = $( this.handles[index] ); } allowed = this._start( event, index ); if ( allowed === false ) { return false; } this._mouseSliding = true; self._handleIndex = index; closestHandle .addClass( "ui-state-active" ) .focus(); offset = closestHandle.offset(); mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" ); this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { left: event.pageX - offset.left - ( closestHandle.width() / 2 ), top: event.pageY - offset.top - ( closestHandle.height() / 2 ) - ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) }; if ( !this.handles.hasClass( "ui-state-hover" ) ) { this._slide( event, index, normValue ); } this._animateOff = true; return true; }, _mouseStart: function( event ) { return true; }, _mouseDrag: function( event ) { var position = { x: event.pageX, y: event.pageY }, normValue = this._normValueFromMouse( position ); this._slide( event, this._handleIndex, normValue ); return false; }, _mouseStop: function( event ) { this.handles.removeClass( "ui-state-active" ); this._mouseSliding = false; this._stop( event, this._handleIndex ); this._change( event, this._handleIndex ); this._handleIndex = null; this._clickOffset = null; this._animateOff = false; return false; }, _detectOrientation: function() { this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; }, _normValueFromMouse: function( position ) { var pixelTotal, pixelMouse, percentMouse, valueTotal, valueMouse; if ( this.orientation === "horizontal" ) { pixelTotal = this.elementSize.width; pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); } else { pixelTotal = this.elementSize.height; pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); } percentMouse = ( pixelMouse / pixelTotal ); if ( percentMouse > 1 ) { percentMouse = 1; } if ( percentMouse < 0 ) { percentMouse = 0; } if ( this.orientation === "vertical" ) { percentMouse = 1 - percentMouse; } valueTotal = this._valueMax() - this._valueMin(); valueMouse = this._valueMin() + percentMouse * valueTotal; return this._trimAlignValue( valueMouse ); }, _start: function( event, index ) { var uiHash = { handle: this.handles[ index ], value: this.value() }; if ( this.options.values && this.options.values.length ) { uiHash.value = this.values( index ); uiHash.values = this.values(); } return this._trigger( "start", event, uiHash ); }, _slide: function( event, index, newVal ) { var otherVal, newValues, allowed; if ( this.options.values && this.options.values.length ) { otherVal = this.values( index ? 0 : 1 ); if ( ( this.options.values.length === 2 && this.options.range === true ) && ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) ) { newVal = otherVal; } if ( newVal !== this.values( index ) ) { newValues = this.values(); newValues[ index ] = newVal; // A slide can be canceled by returning false from the slide callback allowed = this._trigger( "slide", event, { handle: this.handles[ index ], value: newVal, values: newValues } ); otherVal = this.values( index ? 0 : 1 ); if ( allowed !== false ) { this.values( index, newVal, true ); } } } else { if ( newVal !== this.value() ) { // A slide can be canceled by returning false from the slide callback allowed = this._trigger( "slide", event, { handle: this.handles[ index ], value: newVal } ); if ( allowed !== false ) { this.value( newVal ); } } } }, _stop: function( event, index ) { var uiHash = { handle: this.handles[ index ], value: this.value() }; if ( this.options.values && this.options.values.length ) { uiHash.value = this.values( index ); uiHash.values = this.values(); } this._trigger( "stop", event, uiHash ); }, _change: function( event, index ) { if ( !this._keySliding && !this._mouseSliding ) { var uiHash = { handle: this.handles[ index ], value: this.value() }; if ( this.options.values && this.options.values.length ) { uiHash.value = this.values( index ); uiHash.values = this.values(); } this._trigger( "change", event, uiHash ); } }, value: function( newValue ) { if ( arguments.length ) { this.options.value = this._trimAlignValue( newValue ); this._refreshValue(); this._change( null, 0 ); return; } return this._value(); }, values: function( index, newValue ) { var vals, newValues, i; if ( arguments.length > 1 ) { this.options.values[ index ] = this._trimAlignValue( newValue ); this._refreshValue(); this._change( null, index ); return; } if ( arguments.length ) { if ( $.isArray( arguments[ 0 ] ) ) { vals = this.options.values; newValues = arguments[ 0 ]; for ( i = 0; i < vals.length; i += 1 ) { vals[ i ] = this._trimAlignValue( newValues[ i ] ); this._change( null, i ); } this._refreshValue(); } else { if ( this.options.values && this.options.values.length ) { return this._values( index ); } else { return this.value(); } } } else { return this._values(); } }, _setOption: function( key, value ) { var i, valsLength = 0; if ( $.isArray( this.options.values ) ) { valsLength = this.options.values.length; } $.Widget.prototype._setOption.apply( this, arguments ); switch ( key ) { case "disabled": if ( value ) { this.handles.filter( ".ui-state-focus" ).blur(); this.handles.removeClass( "ui-state-hover" ); this.handles.propAttr( "disabled", true ); this.element.addClass( "ui-disabled" ); } else { this.handles.propAttr( "disabled", false ); this.element.removeClass( "ui-disabled" ); } break; case "orientation": this._detectOrientation(); this.element .removeClass( "ui-slider-horizontal ui-slider-vertical" ) .addClass( "ui-slider-" + this.orientation ); this._refreshValue(); break; case "value": this._animateOff = true; this._refreshValue(); this._change( null, 0 ); this._animateOff = false; break; case "values": this._animateOff = true; this._refreshValue(); for ( i = 0; i < valsLength; i += 1 ) { this._change( null, i ); } this._animateOff = false; break; } }, //internal value getter // _value() returns value trimmed by min and max, aligned by step _value: function() { var val = this.options.value; val = this._trimAlignValue( val ); return val; }, //internal values getter // _values() returns array of values trimmed by min and max, aligned by step // _values( index ) returns single value trimmed by min and max, aligned by step _values: function( index ) { var val, vals, i; if ( arguments.length ) { val = this.options.values[ index ]; val = this._trimAlignValue( val ); return val; } else { // .slice() creates a copy of the array // this copy gets trimmed by min and max and then returned vals = this.options.values.slice(); for ( i = 0; i < vals.length; i+= 1) { vals[ i ] = this._trimAlignValue( vals[ i ] ); } return vals; } }, // returns the step-aligned value that val is closest to, between (inclusive) min and max _trimAlignValue: function( val ) { if ( val <= this._valueMin() ) { return this._valueMin(); } if ( val >= this._valueMax() ) { return this._valueMax(); } var step = ( this.options.step > 0 ) ? this.options.step : 1, valModStep = (val - this._valueMin()) % step, alignValue = val - valModStep; if ( Math.abs(valModStep) * 2 >= step ) { alignValue += ( valModStep > 0 ) ? step : ( -step ); } // Since JavaScript has problems with large floats, round // the final value to 5 digits after the decimal point (see #4124) return parseFloat( alignValue.toFixed(5) ); }, _valueMin: function() { return this.options.min; }, _valueMax: function() { return this.options.max; }, _refreshValue: function() { var oRange = this.options.range, o = this.options, self = this, animate = ( !this._animateOff ) ? o.animate : false, valPercent, _set = {}, lastValPercent, value, valueMin, valueMax; if ( this.options.values && this.options.values.length ) { this.handles.each(function( i, j ) { valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100; _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); if ( self.options.range === true ) { if ( self.orientation === "horizontal" ) { if ( i === 0 ) { self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); } if ( i === 1 ) { self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); } } else { if ( i === 0 ) { self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); } if ( i === 1 ) { self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); } } } lastValPercent = valPercent; }); } else { value = this.value(); valueMin = this._valueMin(); valueMax = this._valueMax(); valPercent = ( valueMax !== valueMin ) ? ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 0; _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); if ( oRange === "min" && this.orientation === "horizontal" ) { this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); } if ( oRange === "max" && this.orientation === "horizontal" ) { this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); } if ( oRange === "min" && this.orientation === "vertical" ) { this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); } if ( oRange === "max" && this.orientation === "vertical" ) { this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); } } } }); $.extend( $.ui.slider, { version: "1.8.20" }); }(jQuery)); (function( $, undefined ) { var tabId = 0, listId = 0; function getNextTabId() { return ++tabId; } function getNextListId() { return ++listId; } $.widget( "ui.tabs", { options: { add: null, ajaxOptions: null, cache: false, cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } collapsible: false, disable: null, disabled: [], enable: null, event: "click", fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } idPrefix: "ui-tabs-", load: null, panelTemplate: "
", remove: null, select: null, show: null, spinner: "Loading…", tabTemplate: "
  • #{label}
  • " }, _create: function() { this._tabify( true ); }, _setOption: function( key, value ) { if ( key == "selected" ) { if (this.options.collapsible && value == this.options.selected ) { return; } this.select( value ); } else { this.options[ key ] = value; this._tabify(); } }, _tabId: function( a ) { return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) || this.options.idPrefix + getNextTabId(); }, _sanitizeSelector: function( hash ) { // we need this because an id may contain a ":" return hash.replace( /:/g, "\\:" ); }, _cookie: function() { var cookie = this.cookie || ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() ); return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) ); }, _ui: function( tab, panel ) { return { tab: tab, panel: panel, index: this.anchors.index( tab ) }; }, _cleanup: function() { // restore all former loading tabs labels this.lis.filter( ".ui-state-processing" ) .removeClass( "ui-state-processing" ) .find( "span:data(label.tabs)" ) .each(function() { var el = $( this ); el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" ); }); }, _tabify: function( init ) { var self = this, o = this.options, fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash this.list = this.element.find( "ol,ul" ).eq( 0 ); this.lis = $( " > li:has(a[href])", this.list ); this.anchors = this.lis.map(function() { return $( "a", this )[ 0 ]; }); this.panels = $( [] ); this.anchors.each(function( i, a ) { var href = $( a ).attr( "href" ); // For dynamically created HTML that contains a hash as href IE < 8 expands // such href to the full page url with hash and then misinterprets tab as ajax. // Same consideration applies for an added tab with a fragment identifier // since a[href=#fragment-identifier] does unexpectedly not match. // Thus normalize href attribute... var hrefBase = href.split( "#" )[ 0 ], baseEl; if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] || ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) { href = a.hash; a.href = href; } // inline tab if ( fragmentId.test( href ) ) { self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) ); // remote tab // prevent loading the page itself if href is just "#" } else if ( href && href !== "#" ) { // required for restore on destroy $.data( a, "href.tabs", href ); // TODO until #3808 is fixed strip fragment identifier from url // (IE fails to load from such url) $.data( a, "load.tabs", href.replace( /#.*$/, "" ) ); var id = self._tabId( a ); a.href = "#" + id; var $panel = self.element.find( "#" + id ); if ( !$panel.length ) { $panel = $( o.panelTemplate ) .attr( "id", id ) .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) .insertAfter( self.panels[ i - 1 ] || self.list ); $panel.data( "destroy.tabs", true ); } self.panels = self.panels.add( $panel ); // invalid tab href } else { o.disabled.push( i ); } }); // initialization from scratch if ( init ) { // attach necessary classes for styling this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ); this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); this.lis.addClass( "ui-state-default ui-corner-top" ); this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ); // Selected tab // use "selected" option or try to retrieve: // 1. from fragment identifier in url // 2. from cookie // 3. from selected class attribute on
  • if ( o.selected === undefined ) { if ( location.hash ) { this.anchors.each(function( i, a ) { if ( a.hash == location.hash ) { o.selected = i; return false; } }); } if ( typeof o.selected !== "number" && o.cookie ) { o.selected = parseInt( self._cookie(), 10 ); } if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) { o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); } o.selected = o.selected || ( this.lis.length ? 0 : -1 ); } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release o.selected = -1; } // sanity check - default to first tab... o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 ) ? o.selected : 0; // Take disabling tabs via class attribute from HTML // into account and update option properly. // A selected tab cannot become disabled. o.disabled = $.unique( o.disabled.concat( $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) { return self.lis.index( n ); }) ) ).sort(); if ( $.inArray( o.selected, o.disabled ) != -1 ) { o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 ); } // highlight selected tab this.panels.addClass( "ui-tabs-hide" ); this.lis.removeClass( "ui-tabs-selected ui-state-active" ); // check for length avoids error when initializing empty list if ( o.selected >= 0 && this.anchors.length ) { self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" ); this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" ); // seems to be expected behavior that the show callback is fired self.element.queue( "tabs", function() { self._trigger( "show", null, self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) ); }); this.load( o.selected ); } // clean up to avoid memory leaks in certain versions of IE 6 // TODO: namespace this event $( window ).bind( "unload", function() { self.lis.add( self.anchors ).unbind( ".tabs" ); self.lis = self.anchors = self.panels = null; }); // update selected after add/remove } else { o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); } // update collapsible // TODO: use .toggleClass() this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" ); // set or update cookie after init and add/remove respectively if ( o.cookie ) { this._cookie( o.selected, o.cookie ); } // disable tabs for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) { $( li )[ $.inArray( i, o.disabled ) != -1 && // TODO: use .toggleClass() !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" ); } // reset cache if switching from cached to not cached if ( o.cache === false ) { this.anchors.removeData( "cache.tabs" ); } // remove all handlers before, tabify may run on existing tabs after add or option change this.lis.add( this.anchors ).unbind( ".tabs" ); if ( o.event !== "mouseover" ) { var addState = function( state, el ) { if ( el.is( ":not(.ui-state-disabled)" ) ) { el.addClass( "ui-state-" + state ); } }; var removeState = function( state, el ) { el.removeClass( "ui-state-" + state ); }; this.lis.bind( "mouseover.tabs" , function() { addState( "hover", $( this ) ); }); this.lis.bind( "mouseout.tabs", function() { removeState( "hover", $( this ) ); }); this.anchors.bind( "focus.tabs", function() { addState( "focus", $( this ).closest( "li" ) ); }); this.anchors.bind( "blur.tabs", function() { removeState( "focus", $( this ).closest( "li" ) ); }); } // set up animations var hideFx, showFx; if ( o.fx ) { if ( $.isArray( o.fx ) ) { hideFx = o.fx[ 0 ]; showFx = o.fx[ 1 ]; } else { hideFx = showFx = o.fx; } } // Reset certain styles left over from animation // and prevent IE's ClearType bug... function resetStyle( $el, fx ) { $el.css( "display", "" ); if ( !$.support.opacity && fx.opacity ) { $el[ 0 ].style.removeAttribute( "filter" ); } } // Show a tab... var showTab = showFx ? function( clicked, $show ) { $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way .animate( showFx, showFx.duration || "normal", function() { resetStyle( $show, showFx ); self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); }); } : function( clicked, $show ) { $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); $show.removeClass( "ui-tabs-hide" ); self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); }; // Hide a tab, $show is optional... var hideTab = hideFx ? function( clicked, $hide ) { $hide.animate( hideFx, hideFx.duration || "normal", function() { self.lis.removeClass( "ui-tabs-selected ui-state-active" ); $hide.addClass( "ui-tabs-hide" ); resetStyle( $hide, hideFx ); self.element.dequeue( "tabs" ); }); } : function( clicked, $hide, $show ) { self.lis.removeClass( "ui-tabs-selected ui-state-active" ); $hide.addClass( "ui-tabs-hide" ); self.element.dequeue( "tabs" ); }; // attach tab event handler, unbind to avoid duplicates from former tabifying... this.anchors.bind( o.event + ".tabs", function() { var el = this, $li = $(el).closest( "li" ), $hide = self.panels.filter( ":not(.ui-tabs-hide)" ), $show = self.element.find( self._sanitizeSelector( el.hash ) ); // If tab is already selected and not collapsible or tab disabled or // or is already loading or click callback returns false stop here. // Check if click handler returns false last so that it is not executed // for a disabled or loading tab! if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) || $li.hasClass( "ui-state-disabled" ) || $li.hasClass( "ui-state-processing" ) || self.panels.filter( ":animated" ).length || self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) { this.blur(); return false; } o.selected = self.anchors.index( this ); self.abort(); // if tab may be closed if ( o.collapsible ) { if ( $li.hasClass( "ui-tabs-selected" ) ) { o.selected = -1; if ( o.cookie ) { self._cookie( o.selected, o.cookie ); } self.element.queue( "tabs", function() { hideTab( el, $hide ); }).dequeue( "tabs" ); this.blur(); return false; } else if ( !$hide.length ) { if ( o.cookie ) { self._cookie( o.selected, o.cookie ); } self.element.queue( "tabs", function() { showTab( el, $show ); }); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171 self.load( self.anchors.index( this ) ); this.blur(); return false; } } if ( o.cookie ) { self._cookie( o.selected, o.cookie ); } // show new tab if ( $show.length ) { if ( $hide.length ) { self.element.queue( "tabs", function() { hideTab( el, $hide ); }); } self.element.queue( "tabs", function() { showTab( el, $show ); }); self.load( self.anchors.index( this ) ); } else { throw "jQuery UI Tabs: Mismatching fragment identifier."; } // Prevent IE from keeping other link focussed when using the back button // and remove dotted border from clicked link. This is controlled via CSS // in modern browsers; blur() removes focus from address bar in Firefox // which can become a usability and annoying problem with tabs('rotate'). if ( $.browser.msie ) { this.blur(); } }); // disable click in any case this.anchors.bind( "click.tabs", function(){ return false; }); }, _getIndex: function( index ) { // meta-function to give users option to provide a href string instead of a numerical index. // also sanitizes numerical indexes to valid values. if ( typeof index == "string" ) { index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); } return index; }, destroy: function() { var o = this.options; this.abort(); this.element .unbind( ".tabs" ) .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ) .removeData( "tabs" ); this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); this.anchors.each(function() { var href = $.data( this, "href.tabs" ); if ( href ) { this.href = href; } var $this = $( this ).unbind( ".tabs" ); $.each( [ "href", "load", "cache" ], function( i, prefix ) { $this.removeData( prefix + ".tabs" ); }); }); this.lis.unbind( ".tabs" ).add( this.panels ).each(function() { if ( $.data( this, "destroy.tabs" ) ) { $( this ).remove(); } else { $( this ).removeClass([ "ui-state-default", "ui-corner-top", "ui-tabs-selected", "ui-state-active", "ui-state-hover", "ui-state-focus", "ui-state-disabled", "ui-tabs-panel", "ui-widget-content", "ui-corner-bottom", "ui-tabs-hide" ].join( " " ) ); } }); if ( o.cookie ) { this._cookie( null, o.cookie ); } return this; }, add: function( url, label, index ) { if ( index === undefined ) { index = this.anchors.length; } var self = this, o = this.options, $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ), id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] ); $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true ); // try to find an existing element before creating a new one var $panel = self.element.find( "#" + id ); if ( !$panel.length ) { $panel = $( o.panelTemplate ) .attr( "id", id ) .data( "destroy.tabs", true ); } $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" ); if ( index >= this.lis.length ) { $li.appendTo( this.list ); $panel.appendTo( this.list[ 0 ].parentNode ); } else { $li.insertBefore( this.lis[ index ] ); $panel.insertBefore( this.panels[ index ] ); } o.disabled = $.map( o.disabled, function( n, i ) { return n >= index ? ++n : n; }); this._tabify(); if ( this.anchors.length == 1 ) { o.selected = 0; $li.addClass( "ui-tabs-selected ui-state-active" ); $panel.removeClass( "ui-tabs-hide" ); this.element.queue( "tabs", function() { self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) ); }); this.load( 0 ); } this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); return this; }, remove: function( index ) { index = this._getIndex( index ); var o = this.options, $li = this.lis.eq( index ).remove(), $panel = this.panels.eq( index ).remove(); // If selected tab was removed focus tab to the right or // in case the last tab was removed the tab to the left. if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) { this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); } o.disabled = $.map( $.grep( o.disabled, function(n, i) { return n != index; }), function( n, i ) { return n >= index ? --n : n; }); this._tabify(); this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) ); return this; }, enable: function( index ) { index = this._getIndex( index ); var o = this.options; if ( $.inArray( index, o.disabled ) == -1 ) { return; } this.lis.eq( index ).removeClass( "ui-state-disabled" ); o.disabled = $.grep( o.disabled, function( n, i ) { return n != index; }); this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); return this; }, disable: function( index ) { index = this._getIndex( index ); var self = this, o = this.options; // cannot disable already selected tab if ( index != o.selected ) { this.lis.eq( index ).addClass( "ui-state-disabled" ); o.disabled.push( index ); o.disabled.sort(); this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); } return this; }, select: function( index ) { index = this._getIndex( index ); if ( index == -1 ) { if ( this.options.collapsible && this.options.selected != -1 ) { index = this.options.selected; } else { return this; } } this.anchors.eq( index ).trigger( this.options.event + ".tabs" ); return this; }, load: function( index ) { index = this._getIndex( index ); var self = this, o = this.options, a = this.anchors.eq( index )[ 0 ], url = $.data( a, "load.tabs" ); this.abort(); // not remote or from cache if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) { this.element.dequeue( "tabs" ); return; } // load remote from here on this.lis.eq( index ).addClass( "ui-state-processing" ); if ( o.spinner ) { var span = $( "span", a ); span.data( "label.tabs", span.html() ).html( o.spinner ); } this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, { url: url, success: function( r, s ) { self.element.find( self._sanitizeSelector( a.hash ) ).html( r ); // take care of tab labels self._cleanup(); if ( o.cache ) { $.data( a, "cache.tabs", true ); } self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); try { o.ajaxOptions.success( r, s ); } catch ( e ) {} }, error: function( xhr, s, e ) { // take care of tab labels self._cleanup(); self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); try { // Passing index avoid a race condition when this method is // called after the user has selected another tab. // Pass the anchor that initiated this request allows // loadError to manipulate the tab content panel via $(a.hash) o.ajaxOptions.error( xhr, s, index, a ); } catch ( e ) {} } } ) ); // last, so that load event is fired before show... self.element.dequeue( "tabs" ); return this; }, abort: function() { // stop possibly running animations this.element.queue( [] ); this.panels.stop( false, true ); // "tabs" queue must not contain more than two elements, // which are the callbacks for the latest clicked tab... this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) ); // terminate pending requests from other tabs if ( this.xhr ) { this.xhr.abort(); delete this.xhr; } // take care of tab labels this._cleanup(); return this; }, url: function( index, url ) { this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url ); return this; }, length: function() { return this.anchors.length; } }); $.extend( $.ui.tabs, { version: "1.8.20" }); /* * Tabs Extensions */ /* * Rotate */ $.extend( $.ui.tabs.prototype, { rotation: null, rotate: function( ms, continuing ) { var self = this, o = this.options; var rotate = self._rotate || ( self._rotate = function( e ) { clearTimeout( self.rotation ); self.rotation = setTimeout(function() { var t = o.selected; self.select( ++t < self.anchors.length ? t : 0 ); }, ms ); if ( e ) { e.stopPropagation(); } }); var stop = self._unrotate || ( self._unrotate = !continuing ? function(e) { if (e.clientX) { // in case of a true click self.rotate(null); } } : function( e ) { rotate(); }); // start rotation if ( ms ) { this.element.bind( "tabsshow", rotate ); this.anchors.bind( o.event + ".tabs", stop ); rotate(); // stop rotation } else { clearTimeout( self.rotation ); this.element.unbind( "tabsshow", rotate ); this.anchors.unbind( o.event + ".tabs", stop ); delete this._rotate; delete this._unrotate; } return this; } }); })( jQuery ); ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Scripts/jquery.unobtrusive-ajax.js ================================================ /// /*! ** Unobtrusive Ajax support library for jQuery ** Copyright (C) Microsoft Corporation. All rights reserved. */ /*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ /*global window: false, jQuery: false */ (function ($) { var data_click = "unobtrusiveAjaxClick", data_validation = "unobtrusiveValidation"; function getFunction(code, argNames) { var fn = window, parts = (code || "").split("."); while (fn && parts.length) { fn = fn[parts.shift()]; } if (typeof (fn) === "function") { return fn; } argNames.push(code); return Function.constructor.apply(null, argNames); } function isMethodProxySafe(method) { return method === "GET" || method === "POST"; } function asyncOnBeforeSend(xhr, method) { if (!isMethodProxySafe(method)) { xhr.setRequestHeader("X-HTTP-Method-Override", method); } } function asyncOnSuccess(element, data, contentType) { var mode; if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us return; } mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase(); $(element.getAttribute("data-ajax-update")).each(function (i, update) { var top; switch (mode) { case "BEFORE": top = update.firstChild; $("
    ").html(data).contents().each(function () { update.insertBefore(this, top); }); break; case "AFTER": $("
    ").html(data).contents().each(function () { update.appendChild(this); }); break; default: $(update).html(data); break; } }); } function asyncRequest(element, options) { var confirm, loading, method, duration; confirm = element.getAttribute("data-ajax-confirm"); if (confirm && !window.confirm(confirm)) { return; } loading = $(element.getAttribute("data-ajax-loading")); duration = element.getAttribute("data-ajax-loading-duration") || 0; $.extend(options, { type: element.getAttribute("data-ajax-method") || undefined, url: element.getAttribute("data-ajax-url") || undefined, beforeSend: function (xhr) { var result; asyncOnBeforeSend(xhr, method); result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments); if (result !== false) { loading.show(duration); } return result; }, complete: function () { loading.hide(duration); getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments); }, success: function (data, status, xhr) { asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html"); getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments); }, error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]) }); options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" }); method = options.type.toUpperCase(); if (!isMethodProxySafe(method)) { options.type = "POST"; options.data.push({ name: "X-HTTP-Method-Override", value: method }); } $.ajax(options); } function validate(form) { var validationInfo = $(form).data(data_validation); return !validationInfo || !validationInfo.validate || validationInfo.validate(); } $("a[data-ajax=true]").live("click", function (evt) { evt.preventDefault(); asyncRequest(this, { url: this.href, type: "GET", data: [] }); }); $("form[data-ajax=true] input[type=image]").live("click", function (evt) { var name = evt.target.name, $target = $(evt.target), form = $target.parents("form")[0], offset = $target.offset(); $(form).data(data_click, [ { name: name + ".x", value: Math.round(evt.pageX - offset.left) }, { name: name + ".y", value: Math.round(evt.pageY - offset.top) } ]); setTimeout(function () { $(form).removeData(data_click); }, 0); }); $("form[data-ajax=true] :submit").live("click", function (evt) { var name = evt.target.name, form = $(evt.target).parents("form")[0]; $(form).data(data_click, name ? [{ name: name, value: evt.target.value }] : []); setTimeout(function () { $(form).removeData(data_click); }, 0); }); $("form[data-ajax=true]").live("submit", function (evt) { var clickInfo = $(this).data(data_click) || []; evt.preventDefault(); if (!validate(this)) { return; } asyncRequest(this, { url: this.action, type: this.method || "GET", data: clickInfo.concat($(this).serializeArray()) }); }); }(jQuery)); ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Scripts/jquery.validate-vsdoc.js ================================================ /* * This file has been commented to support Visual Studio Intellisense. * You should not use this file at runtime inside the browser--it is only * intended to be used only for design-time IntelliSense. Please use the * standard jQuery library for all production use. * * Comment version: 1.8 */ /* * Note: While Microsoft is not the author of this file, Microsoft is * offering you a license subject to the terms of the Microsoft Software * License Terms for Microsoft ASP.NET Model View Controller 3. * Microsoft reserves all other rights. The notices below are provided * for informational purposes only and are not the license terms under * which Microsoft distributed this file. * * jQuery validation plugin 1.8.0 * * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ * http://docs.jquery.com/Plugins/Validation * * Copyright (c) 2006 - 2011 Jörn Zaefferer * */ (function($) { $.extend($.fn, { // http://docs.jquery.com/Plugins/Validation/validate validate: function( options ) { /// /// Validates the selected form. This method sets up event handlers for submit, focus, /// keyup, blur and click to trigger validation of the entire form or individual /// elements. Each one can be disabled, see the onxxx options (onsubmit, onfocusout, /// onkeyup, onclick). focusInvalid focuses elements when submitting a invalid form. /// /// /// A set of key/value pairs that configure the validate. All options are optional. /// // if nothing is selected, return nothing; can't chain anyway if (!this.length) { options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" ); return; } // check if a validator for this form was already created var validator = $.data(this[0], 'validator'); if ( validator ) { return validator; } validator = new $.validator( options, this[0] ); $.data(this[0], 'validator', validator); if ( validator.settings.onsubmit ) { // allow suppresing validation by adding a cancel class to the submit button this.find("input, button").filter(".cancel").click(function() { validator.cancelSubmit = true; }); // when a submitHandler is used, capture the submitting button if (validator.settings.submitHandler) { this.find("input, button").filter(":submit").click(function() { validator.submitButton = this; }); } // validate the form on submit this.submit( function( event ) { if ( validator.settings.debug ) // prevent form submit to be able to see console output event.preventDefault(); function handle() { if ( validator.settings.submitHandler ) { if (validator.submitButton) { // insert a hidden input as a replacement for the missing submit button var hidden = $("").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm); } validator.settings.submitHandler.call( validator, validator.currentForm ); if (validator.submitButton) { // and clean up afterwards; thanks to no-block-scope, hidden can be referenced hidden.remove(); } return false; } return true; } // prevent submit for invalid forms or custom submit handlers if ( validator.cancelSubmit ) { validator.cancelSubmit = false; return handle(); } if ( validator.form() ) { if ( validator.pendingRequest ) { validator.formSubmitted = true; return false; } return handle(); } else { validator.focusInvalid(); return false; } }); } return validator; }, // http://docs.jquery.com/Plugins/Validation/valid valid: function() { /// /// Checks if the selected form is valid or if all selected elements are valid. /// validate() needs to be called on the form before checking it using this method. /// /// if ( $(this[0]).is('form')) { return this.validate().form(); } else { var valid = true; var validator = $(this[0].form).validate(); this.each(function() { valid &= validator.element(this); }); return valid; } }, // attributes: space seperated list of attributes to retrieve and remove removeAttrs: function(attributes) { /// /// Remove the specified attributes from the first matched element and return them. /// /// /// A space-seperated list of attribute names to remove. /// var result = {}, $element = this; $.each(attributes.split(/\s/), function(index, value) { result[value] = $element.attr(value); $element.removeAttr(value); }); return result; }, // http://docs.jquery.com/Plugins/Validation/rules rules: function(command, argument) { /// /// Return the validations rules for the first selected element. /// /// /// Can be either "add" or "remove". /// /// /// A list of rules to add or remove. /// var element = this[0]; if (command) { var settings = $.data(element.form, 'validator').settings; var staticRules = settings.rules; var existingRules = $.validator.staticRules(element); switch(command) { case "add": $.extend(existingRules, $.validator.normalizeRule(argument)); staticRules[element.name] = existingRules; if (argument.messages) settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages ); break; case "remove": if (!argument) { delete staticRules[element.name]; return existingRules; } var filtered = {}; $.each(argument.split(/\s/), function(index, method) { filtered[method] = existingRules[method]; delete existingRules[method]; }); return filtered; } } var data = $.validator.normalizeRules( $.extend( {}, $.validator.metadataRules(element), $.validator.classRules(element), $.validator.attributeRules(element), $.validator.staticRules(element) ), element); // make sure required is at front if (data.required) { var param = data.required; delete data.required; data = $.extend({required: param}, data); } return data; } }); // Custom selectors $.extend($.expr[":"], { // http://docs.jquery.com/Plugins/Validation/blank blank: function(a) {return !$.trim("" + a.value);}, // http://docs.jquery.com/Plugins/Validation/filled filled: function(a) {return !!$.trim("" + a.value);}, // http://docs.jquery.com/Plugins/Validation/unchecked unchecked: function(a) {return !a.checked;} }); // constructor for validator $.validator = function( options, form ) { this.settings = $.extend( true, {}, $.validator.defaults, options ); this.currentForm = form; this.init(); }; $.validator.format = function(source, params) { /// /// Replaces {n} placeholders with arguments. /// One or more arguments can be passed, in addition to the string template itself, to insert /// into the string. /// /// /// The string to format. /// /// /// The first argument to insert, or an array of Strings to insert /// /// if ( arguments.length == 1 ) return function() { var args = $.makeArray(arguments); args.unshift(source); return $.validator.format.apply( this, args ); }; if ( arguments.length > 2 && params.constructor != Array ) { params = $.makeArray(arguments).slice(1); } if ( params.constructor != Array ) { params = [ params ]; } $.each(params, function(i, n) { source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n); }); return source; }; $.extend($.validator, { defaults: { messages: {}, groups: {}, rules: {}, errorClass: "error", validClass: "valid", errorElement: "label", focusInvalid: true, errorContainer: $( [] ), errorLabelContainer: $( [] ), onsubmit: true, ignore: [], ignoreTitle: false, onfocusin: function(element) { this.lastActive = element; // hide error label and remove error class on focus if enabled if ( this.settings.focusCleanup && !this.blockFocusCleanup ) { this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); this.addWrapper(this.errorsFor(element)).hide(); } }, onfocusout: function(element) { if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) { this.element(element); } }, onkeyup: function(element) { if ( element.name in this.submitted || element == this.lastElement ) { this.element(element); } }, onclick: function(element) { // click on selects, radiobuttons and checkboxes if ( element.name in this.submitted ) this.element(element); // or option elements, check parent select in that case else if (element.parentNode.name in this.submitted) this.element(element.parentNode); }, highlight: function( element, errorClass, validClass ) { $(element).addClass(errorClass).removeClass(validClass); }, unhighlight: function( element, errorClass, validClass ) { $(element).removeClass(errorClass).addClass(validClass); } }, // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults setDefaults: function(settings) { /// /// Modify default settings for validation. /// Accepts everything that Plugins/Validation/validate accepts. /// /// /// Options to set as default. /// $.extend( $.validator.defaults, settings ); }, messages: { required: "This field is required.", remote: "Please fix this field.", email: "Please enter a valid email address.", url: "Please enter a valid URL.", date: "Please enter a valid date.", dateISO: "Please enter a valid date (ISO).", number: "Please enter a valid number.", digits: "Please enter only digits.", creditcard: "Please enter a valid credit card number.", equalTo: "Please enter the same value again.", accept: "Please enter a value with a valid extension.", maxlength: $.validator.format("Please enter no more than {0} characters."), minlength: $.validator.format("Please enter at least {0} characters."), rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), range: $.validator.format("Please enter a value between {0} and {1}."), max: $.validator.format("Please enter a value less than or equal to {0}."), min: $.validator.format("Please enter a value greater than or equal to {0}.") }, autoCreateRanges: false, prototype: { init: function() { this.labelContainer = $(this.settings.errorLabelContainer); this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer ); this.submitted = {}; this.valueCache = {}; this.pendingRequest = 0; this.pending = {}; this.invalid = {}; this.reset(); var groups = (this.groups = {}); $.each(this.settings.groups, function(key, value) { $.each(value.split(/\s/), function(index, name) { groups[name] = key; }); }); var rules = this.settings.rules; $.each(rules, function(key, value) { rules[key] = $.validator.normalizeRule(value); }); function delegate(event) { var validator = $.data(this[0].form, "validator"), eventType = "on" + event.type.replace(/^validate/, ""); validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] ); } $(this.currentForm) .validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate) .validateDelegate(":radio, :checkbox, select, option", "click", delegate); if (this.settings.invalidHandler) $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); }, // http://docs.jquery.com/Plugins/Validation/Validator/form form: function() { /// /// Validates the form, returns true if it is valid, false otherwise. /// This behaves as a normal submit event, but returns the result. /// /// this.checkForm(); $.extend(this.submitted, this.errorMap); this.invalid = $.extend({}, this.errorMap); if (!this.valid()) $(this.currentForm).triggerHandler("invalid-form", [this]); this.showErrors(); return this.valid(); }, checkForm: function() { this.prepareForm(); for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) { this.check( elements[i] ); } return this.valid(); }, // http://docs.jquery.com/Plugins/Validation/Validator/element element: function( element ) { /// /// Validates a single element, returns true if it is valid, false otherwise. /// This behaves as validation on blur or keyup, but returns the result. /// /// /// An element to validate, must be inside the validated form. /// /// element = this.clean( element ); this.lastElement = element; this.prepareElement( element ); this.currentElements = $(element); var result = this.check( element ); if ( result ) { delete this.invalid[element.name]; } else { this.invalid[element.name] = true; } if ( !this.numberOfInvalids() ) { // Hide error containers on last error this.toHide = this.toHide.add( this.containers ); } this.showErrors(); return result; }, // http://docs.jquery.com/Plugins/Validation/Validator/showErrors showErrors: function(errors) { /// /// Show the specified messages. /// Keys have to refer to the names of elements, values are displayed for those elements, using the configured error placement. /// /// /// One or more key/value pairs of input names and messages. /// if(errors) { // add items to error list and map $.extend( this.errorMap, errors ); this.errorList = []; for ( var name in errors ) { this.errorList.push({ message: errors[name], element: this.findByName(name)[0] }); } // remove items from success list this.successList = $.grep( this.successList, function(element) { return !(element.name in errors); }); } this.settings.showErrors ? this.settings.showErrors.call( this, this.errorMap, this.errorList ) : this.defaultShowErrors(); }, // http://docs.jquery.com/Plugins/Validation/Validator/resetForm resetForm: function() { /// /// Resets the controlled form. /// Resets input fields to their original value (requires form plugin), removes classes /// indicating invalid elements and hides error messages. /// if ( $.fn.resetForm ) $( this.currentForm ).resetForm(); this.submitted = {}; this.prepareForm(); this.hideErrors(); this.elements().removeClass( this.settings.errorClass ); }, numberOfInvalids: function() { /// /// Returns the number of invalid fields. /// This depends on the internal validator state. It covers all fields only after /// validating the complete form (on submit or via $("form").valid()). After validating /// a single element, only that element is counted. Most useful in combination with the /// invalidHandler-option. /// /// return this.objectLength(this.invalid); }, objectLength: function( obj ) { var count = 0; for ( var i in obj ) count++; return count; }, hideErrors: function() { this.addWrapper( this.toHide ).hide(); }, valid: function() { return this.size() == 0; }, size: function() { return this.errorList.length; }, focusInvalid: function() { if( this.settings.focusInvalid ) { try { $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []) .filter(":visible") .focus() // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find .trigger("focusin"); } catch(e) { // ignore IE throwing errors when focusing hidden elements } } }, findLastActive: function() { var lastActive = this.lastActive; return lastActive && $.grep(this.errorList, function(n) { return n.element.name == lastActive.name; }).length == 1 && lastActive; }, elements: function() { var validator = this, rulesCache = {}; // select all valid inputs inside the form (no submit or reset buttons) // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved return $([]).add(this.currentForm.elements) .filter(":input") .not(":submit, :reset, :image, [disabled]") .not( this.settings.ignore ) .filter(function() { !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this); // select only the first element for each name, and only those with rules specified if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) return false; rulesCache[this.name] = true; return true; }); }, clean: function( selector ) { return $( selector )[0]; }, errors: function() { return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext ); }, reset: function() { this.successList = []; this.errorList = []; this.errorMap = {}; this.toShow = $([]); this.toHide = $([]); this.currentElements = $([]); }, prepareForm: function() { this.reset(); this.toHide = this.errors().add( this.containers ); }, prepareElement: function( element ) { this.reset(); this.toHide = this.errorsFor(element); }, check: function( element ) { element = this.clean( element ); // if radio/checkbox, validate first element in group instead if (this.checkable(element)) { element = this.findByName(element.name).not(this.settings.ignore)[0]; } var rules = $(element).rules(); var dependencyMismatch = false; for (var method in rules) { var rule = { method: method, parameters: rules[method] }; try { var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters ); // if a method indicates that the field is optional and therefore valid, // don't mark it as valid when there are no other rules if ( result == "dependency-mismatch" ) { dependencyMismatch = true; continue; } dependencyMismatch = false; if ( result == "pending" ) { this.toHide = this.toHide.not( this.errorsFor(element) ); return; } if( !result ) { this.formatAndAdd( element, rule ); return false; } } catch(e) { this.settings.debug && window.console && console.log("exception occured when checking element " + element.id + ", check the '" + rule.method + "' method", e); throw e; } } if (dependencyMismatch) return; if ( this.objectLength(rules) ) this.successList.push(element); return true; }, // return the custom message for the given element and validation method // specified in the element's "messages" metadata customMetaMessage: function(element, method) { if (!$.metadata) return; var meta = this.settings.meta ? $(element).metadata()[this.settings.meta] : $(element).metadata(); return meta && meta.messages && meta.messages[method]; }, // return the custom message for the given element name and validation method customMessage: function( name, method ) { var m = this.settings.messages[name]; return m && (m.constructor == String ? m : m[method]); }, // return the first defined argument, allowing empty strings findDefined: function() { for(var i = 0; i < arguments.length; i++) { if (arguments[i] !== undefined) return arguments[i]; } return undefined; }, defaultMessage: function( element, method) { return this.findDefined( this.customMessage( element.name, method ), this.customMetaMessage( element, method ), // title is never undefined, so handle empty string as undefined !this.settings.ignoreTitle && element.title || undefined, $.validator.messages[method], "Warning: No message defined for " + element.name + "" ); }, formatAndAdd: function( element, rule ) { var message = this.defaultMessage( element, rule.method ), theregex = /\$?\{(\d+)\}/g; if ( typeof message == "function" ) { message = message.call(this, rule.parameters, element); } else if (theregex.test(message)) { message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters); } this.errorList.push({ message: message, element: element }); this.errorMap[element.name] = message; this.submitted[element.name] = message; }, addWrapper: function(toToggle) { if ( this.settings.wrapper ) toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); return toToggle; }, defaultShowErrors: function() { for ( var i = 0; this.errorList[i]; i++ ) { var error = this.errorList[i]; this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass ); this.showLabel( error.element, error.message ); } if( this.errorList.length ) { this.toShow = this.toShow.add( this.containers ); } if (this.settings.success) { for ( var i = 0; this.successList[i]; i++ ) { this.showLabel( this.successList[i] ); } } if (this.settings.unhighlight) { for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) { this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass ); } } this.toHide = this.toHide.not( this.toShow ); this.hideErrors(); this.addWrapper( this.toShow ).show(); }, validElements: function() { return this.currentElements.not(this.invalidElements()); }, invalidElements: function() { return $(this.errorList).map(function() { return this.element; }); }, showLabel: function(element, message) { var label = this.errorsFor( element ); if ( label.length ) { // refresh error/success class label.removeClass().addClass( this.settings.errorClass ); // check if we have a generated label, replace the message then label.attr("generated") && label.html(message); } else { // create label label = $("<" + this.settings.errorElement + "/>") .attr({"for": this.idOrName(element), generated: true}) .addClass(this.settings.errorClass) .html(message || ""); if ( this.settings.wrapper ) { // make sure the element is visible, even in IE // actually showing the wrapped element is handled elsewhere label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); } if ( !this.labelContainer.append(label).length ) this.settings.errorPlacement ? this.settings.errorPlacement(label, $(element) ) : label.insertAfter(element); } if ( !message && this.settings.success ) { label.text(""); typeof this.settings.success == "string" ? label.addClass( this.settings.success ) : this.settings.success( label ); } this.toShow = this.toShow.add(label); }, errorsFor: function(element) { var name = this.idOrName(element); return this.errors().filter(function() { return $(this).attr('for') == name; }); }, idOrName: function(element) { return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); }, checkable: function( element ) { return /radio|checkbox/i.test(element.type); }, findByName: function( name ) { // select by name and filter by form for performance over form.find("[name=...]") var form = this.currentForm; return $(document.getElementsByName(name)).map(function(index, element) { return element.form == form && element.name == name && element || null; }); }, getLength: function(value, element) { switch( element.nodeName.toLowerCase() ) { case 'select': return $("option:selected", element).length; case 'input': if( this.checkable( element) ) return this.findByName(element.name).filter(':checked').length; } return value.length; }, depend: function(param, element) { return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true; }, dependTypes: { "boolean": function(param, element) { return param; }, "string": function(param, element) { return !!$(param, element.form).length; }, "function": function(param, element) { return param(element); } }, optional: function(element) { return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch"; }, startRequest: function(element) { if (!this.pending[element.name]) { this.pendingRequest++; this.pending[element.name] = true; } }, stopRequest: function(element, valid) { this.pendingRequest--; // sometimes synchronization fails, make sure pendingRequest is never < 0 if (this.pendingRequest < 0) this.pendingRequest = 0; delete this.pending[element.name]; if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) { $(this.currentForm).submit(); this.formSubmitted = false; } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) { $(this.currentForm).triggerHandler("invalid-form", [this]); this.formSubmitted = false; } }, previousValue: function(element) { return $.data(element, "previousValue") || $.data(element, "previousValue", { old: null, valid: true, message: this.defaultMessage( element, "remote" ) }); } }, classRuleSettings: { required: {required: true}, email: {email: true}, url: {url: true}, date: {date: true}, dateISO: {dateISO: true}, dateDE: {dateDE: true}, number: {number: true}, numberDE: {numberDE: true}, digits: {digits: true}, creditcard: {creditcard: true} }, addClassRules: function(className, rules) { /// /// Add a compound class method - useful to refactor common combinations of rules into a single /// class. /// /// /// The name of the class rule to add /// /// /// The compound rules /// className.constructor == String ? this.classRuleSettings[className] = rules : $.extend(this.classRuleSettings, className); }, classRules: function(element) { var rules = {}; var classes = $(element).attr('class'); classes && $.each(classes.split(' '), function() { if (this in $.validator.classRuleSettings) { $.extend(rules, $.validator.classRuleSettings[this]); } }); return rules; }, attributeRules: function(element) { var rules = {}; var $element = $(element); for (var method in $.validator.methods) { var value = $element.attr(method); if (value) { rules[method] = value; } } // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) { delete rules.maxlength; } return rules; }, metadataRules: function(element) { if (!$.metadata) return {}; var meta = $.data(element.form, 'validator').settings.meta; return meta ? $(element).metadata()[meta] : $(element).metadata(); }, staticRules: function(element) { var rules = {}; var validator = $.data(element.form, 'validator'); if (validator.settings.rules) { rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; } return rules; }, normalizeRules: function(rules, element) { // handle dependency check $.each(rules, function(prop, val) { // ignore rule when param is explicitly false, eg. required:false if (val === false) { delete rules[prop]; return; } if (val.param || val.depends) { var keepRule = true; switch (typeof val.depends) { case "string": keepRule = !!$(val.depends, element.form).length; break; case "function": keepRule = val.depends.call(element, element); break; } if (keepRule) { rules[prop] = val.param !== undefined ? val.param : true; } else { delete rules[prop]; } } }); // evaluate parameters $.each(rules, function(rule, parameter) { rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; }); // clean number parameters $.each(['minlength', 'maxlength', 'min', 'max'], function() { if (rules[this]) { rules[this] = Number(rules[this]); } }); $.each(['rangelength', 'range'], function() { if (rules[this]) { rules[this] = [Number(rules[this][0]), Number(rules[this][1])]; } }); if ($.validator.autoCreateRanges) { // auto-create ranges if (rules.min && rules.max) { rules.range = [rules.min, rules.max]; delete rules.min; delete rules.max; } if (rules.minlength && rules.maxlength) { rules.rangelength = [rules.minlength, rules.maxlength]; delete rules.minlength; delete rules.maxlength; } } // To support custom messages in metadata ignore rule methods titled "messages" if (rules.messages) { delete rules.messages; } return rules; }, // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} normalizeRule: function(data) { if( typeof data == "string" ) { var transformed = {}; $.each(data.split(/\s/), function() { transformed[this] = true; }); data = transformed; } return data; }, // http://docs.jquery.com/Plugins/Validation/Validator/addMethod addMethod: function(name, method, message) { /// /// Add a custom validation method. It must consist of a name (must be a legal javascript /// identifier), a javascript based function and a default string message. /// /// /// The name of the method, used to identify and referencing it, must be a valid javascript /// identifier /// /// /// The actual method implementation, returning true if an element is valid /// /// /// (Optional) The default message to display for this method. Can be a function created by /// jQuery.validator.format(value). When undefined, an already existing message is used /// (handy for localization), otherwise the field-specific messages have to be defined. /// $.validator.methods[name] = method; $.validator.messages[name] = message != undefined ? message : $.validator.messages[name]; if (method.length < 3) { $.validator.addClassRules(name, $.validator.normalizeRule(name)); } }, methods: { // http://docs.jquery.com/Plugins/Validation/Methods/required required: function(value, element, param) { // check if dependency is met if ( !this.depend(param, element) ) return "dependency-mismatch"; switch( element.nodeName.toLowerCase() ) { case 'select': // could be an array for select-multiple or a string, both are fine this way var val = $(element).val(); return val && val.length > 0; case 'input': if ( this.checkable(element) ) return this.getLength(value, element) > 0; default: return $.trim(value).length > 0; } }, // http://docs.jquery.com/Plugins/Validation/Methods/remote remote: function(value, element, param) { if ( this.optional(element) ) return "dependency-mismatch"; var previous = this.previousValue(element); if (!this.settings.messages[element.name] ) this.settings.messages[element.name] = {}; previous.originalMessage = this.settings.messages[element.name].remote; this.settings.messages[element.name].remote = previous.message; param = typeof param == "string" && {url:param} || param; if ( this.pending[element.name] ) { return "pending"; } if ( previous.old === value ) { return previous.valid; } previous.old = value; var validator = this; this.startRequest(element); var data = {}; data[element.name] = value; $.ajax($.extend(true, { url: param, mode: "abort", port: "validate" + element.name, dataType: "json", data: data, success: function(response) { validator.settings.messages[element.name].remote = previous.originalMessage; var valid = response === true; if ( valid ) { var submitted = validator.formSubmitted; validator.prepareElement(element); validator.formSubmitted = submitted; validator.successList.push(element); validator.showErrors(); } else { var errors = {}; var message = response || validator.defaultMessage(element, "remote"); errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message; validator.showErrors(errors); } previous.valid = valid; validator.stopRequest(element, valid); } }, param)); return "pending"; }, // http://docs.jquery.com/Plugins/Validation/Methods/minlength minlength: function(value, element, param) { return this.optional(element) || this.getLength($.trim(value), element) >= param; }, // http://docs.jquery.com/Plugins/Validation/Methods/maxlength maxlength: function(value, element, param) { return this.optional(element) || this.getLength($.trim(value), element) <= param; }, // http://docs.jquery.com/Plugins/Validation/Methods/rangelength rangelength: function(value, element, param) { var length = this.getLength($.trim(value), element); return this.optional(element) || ( length >= param[0] && length <= param[1] ); }, // http://docs.jquery.com/Plugins/Validation/Methods/min min: function( value, element, param ) { return this.optional(element) || value >= param; }, // http://docs.jquery.com/Plugins/Validation/Methods/max max: function( value, element, param ) { return this.optional(element) || value <= param; }, // http://docs.jquery.com/Plugins/Validation/Methods/range range: function( value, element, param ) { return this.optional(element) || ( value >= param[0] && value <= param[1] ); }, // http://docs.jquery.com/Plugins/Validation/Methods/email email: function(value, element) { // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/ return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/url url: function(value, element) { // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/date date: function(value, element) { return this.optional(element) || !/Invalid|NaN/.test(new Date(value)); }, // http://docs.jquery.com/Plugins/Validation/Methods/dateISO dateISO: function(value, element) { return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/number number: function(value, element) { return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/digits digits: function(value, element) { return this.optional(element) || /^\d+$/.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/creditcard // based on http://en.wikipedia.org/wiki/Luhn creditcard: function(value, element) { if ( this.optional(element) ) return "dependency-mismatch"; // accept only digits and dashes if (/[^0-9-]+/.test(value)) return false; var nCheck = 0, nDigit = 0, bEven = false; value = value.replace(/\D/g, ""); for (var n = value.length - 1; n >= 0; n--) { var cDigit = value.charAt(n); var nDigit = parseInt(cDigit, 10); if (bEven) { if ((nDigit *= 2) > 9) nDigit -= 9; } nCheck += nDigit; bEven = !bEven; } return (nCheck % 10) == 0; }, // http://docs.jquery.com/Plugins/Validation/Methods/accept accept: function(value, element, param) { param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif"; return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); }, // http://docs.jquery.com/Plugins/Validation/Methods/equalTo equalTo: function(value, element, param) { // bind to the blur event of the target in order to revalidate whenever the target field is updated // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() { $(element).valid(); }); return value == target.val(); } } }); // deprecated, use $.validator.format instead $.format = $.validator.format; })(jQuery); // ajax mode: abort // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() ;(function($) { var pendingRequests = {}; // Use a prefilter if available (1.5+) if ( $.ajaxPrefilter ) { $.ajaxPrefilter(function(settings, _, xhr) { var port = settings.port; if (settings.mode == "abort") { if ( pendingRequests[port] ) { pendingRequests[port].abort(); } pendingRequests[port] = xhr; } }); } else { // Proxy ajax var ajax = $.ajax; $.ajax = function(settings) { var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode, port = ( "port" in settings ? settings : $.ajaxSettings ).port; if (mode == "abort") { if ( pendingRequests[port] ) { pendingRequests[port].abort(); } return (pendingRequests[port] = ajax.apply(this, arguments)); } return ajax.apply(this, arguments); }; } })(jQuery); // provides cross-browser focusin and focusout events // IE has native support, in other browsers, use event caputuring (neither bubbles) // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target ;(function($) { // only implement if not provided by jQuery core (since 1.4) // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) { $.each({ focus: 'focusin', blur: 'focusout' }, function( original, fix ){ $.event.special[fix] = { setup:function() { this.addEventListener( original, handler, true ); }, teardown:function() { this.removeEventListener( original, handler, true ); }, handler: function(e) { arguments[0] = $.event.fix(e); arguments[0].type = fix; return $.event.handle.apply(this, arguments); } }; function handler(e) { e = $.event.fix(e); e.type = fix; return $.event.handle.call(this, e); } }); }; $.extend($.fn, { validateDelegate: function(delegate, type, handler) { return this.bind(type, function(event) { var target = $(event.target); if (target.is(delegate)) { return handler.apply(target, arguments); } }); } }); })(jQuery); ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Scripts/jquery.validate.js ================================================ /** * jQuery Validation Plugin 1.9.0 * * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ * http://docs.jquery.com/Plugins/Validation * * Copyright (c) 2006 - 2011 Jörn Zaefferer * * Licensed under MIT: http://www.opensource.org/licenses/mit-license.php */ (function($) { $.extend($.fn, { // http://docs.jquery.com/Plugins/Validation/validate validate: function( options ) { // if nothing is selected, return nothing; can't chain anyway if (!this.length) { options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" ); return; } // check if a validator for this form was already created var validator = $.data(this[0], 'validator'); if ( validator ) { return validator; } // Add novalidate tag if HTML5. this.attr('novalidate', 'novalidate'); validator = new $.validator( options, this[0] ); $.data(this[0], 'validator', validator); if ( validator.settings.onsubmit ) { var inputsAndButtons = this.find("input, button"); // allow suppresing validation by adding a cancel class to the submit button inputsAndButtons.filter(".cancel").click(function () { validator.cancelSubmit = true; }); // when a submitHandler is used, capture the submitting button if (validator.settings.submitHandler) { inputsAndButtons.filter(":submit").click(function () { validator.submitButton = this; }); } // validate the form on submit this.submit( function( event ) { if ( validator.settings.debug ) // prevent form submit to be able to see console output event.preventDefault(); function handle() { if ( validator.settings.submitHandler ) { if (validator.submitButton) { // insert a hidden input as a replacement for the missing submit button var hidden = $("").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm); } validator.settings.submitHandler.call( validator, validator.currentForm ); if (validator.submitButton) { // and clean up afterwards; thanks to no-block-scope, hidden can be referenced hidden.remove(); } return false; } return true; } // prevent submit for invalid forms or custom submit handlers if ( validator.cancelSubmit ) { validator.cancelSubmit = false; return handle(); } if ( validator.form() ) { if ( validator.pendingRequest ) { validator.formSubmitted = true; return false; } return handle(); } else { validator.focusInvalid(); return false; } }); } return validator; }, // http://docs.jquery.com/Plugins/Validation/valid valid: function() { if ( $(this[0]).is('form')) { return this.validate().form(); } else { var valid = true; var validator = $(this[0].form).validate(); this.each(function() { valid &= validator.element(this); }); return valid; } }, // attributes: space seperated list of attributes to retrieve and remove removeAttrs: function(attributes) { var result = {}, $element = this; $.each(attributes.split(/\s/), function(index, value) { result[value] = $element.attr(value); $element.removeAttr(value); }); return result; }, // http://docs.jquery.com/Plugins/Validation/rules rules: function(command, argument) { var element = this[0]; if (command) { var settings = $.data(element.form, 'validator').settings; var staticRules = settings.rules; var existingRules = $.validator.staticRules(element); switch(command) { case "add": $.extend(existingRules, $.validator.normalizeRule(argument)); staticRules[element.name] = existingRules; if (argument.messages) settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages ); break; case "remove": if (!argument) { delete staticRules[element.name]; return existingRules; } var filtered = {}; $.each(argument.split(/\s/), function(index, method) { filtered[method] = existingRules[method]; delete existingRules[method]; }); return filtered; } } var data = $.validator.normalizeRules( $.extend( {}, $.validator.metadataRules(element), $.validator.classRules(element), $.validator.attributeRules(element), $.validator.staticRules(element) ), element); // make sure required is at front if (data.required) { var param = data.required; delete data.required; data = $.extend({required: param}, data); } return data; } }); // Custom selectors $.extend($.expr[":"], { // http://docs.jquery.com/Plugins/Validation/blank blank: function(a) {return !$.trim("" + a.value);}, // http://docs.jquery.com/Plugins/Validation/filled filled: function(a) {return !!$.trim("" + a.value);}, // http://docs.jquery.com/Plugins/Validation/unchecked unchecked: function(a) {return !a.checked;} }); // constructor for validator $.validator = function( options, form ) { this.settings = $.extend( true, {}, $.validator.defaults, options ); this.currentForm = form; this.init(); }; $.validator.format = function(source, params) { if ( arguments.length == 1 ) return function() { var args = $.makeArray(arguments); args.unshift(source); return $.validator.format.apply( this, args ); }; if ( arguments.length > 2 && params.constructor != Array ) { params = $.makeArray(arguments).slice(1); } if ( params.constructor != Array ) { params = [ params ]; } $.each(params, function(i, n) { source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n); }); return source; }; $.extend($.validator, { defaults: { messages: {}, groups: {}, rules: {}, errorClass: "error", validClass: "valid", errorElement: "label", focusInvalid: true, errorContainer: $( [] ), errorLabelContainer: $( [] ), onsubmit: true, ignore: ":hidden", ignoreTitle: false, onfocusin: function(element, event) { this.lastActive = element; // hide error label and remove error class on focus if enabled if ( this.settings.focusCleanup && !this.blockFocusCleanup ) { this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); this.addWrapper(this.errorsFor(element)).hide(); } }, onfocusout: function(element, event) { if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) { this.element(element); } }, onkeyup: function(element, event) { if ( element.name in this.submitted || element == this.lastElement ) { this.element(element); } }, onclick: function(element, event) { // click on selects, radiobuttons and checkboxes if ( element.name in this.submitted ) this.element(element); // or option elements, check parent select in that case else if (element.parentNode.name in this.submitted) this.element(element.parentNode); }, highlight: function(element, errorClass, validClass) { if (element.type === 'radio') { this.findByName(element.name).addClass(errorClass).removeClass(validClass); } else { $(element).addClass(errorClass).removeClass(validClass); } }, unhighlight: function(element, errorClass, validClass) { if (element.type === 'radio') { this.findByName(element.name).removeClass(errorClass).addClass(validClass); } else { $(element).removeClass(errorClass).addClass(validClass); } } }, // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults setDefaults: function(settings) { $.extend( $.validator.defaults, settings ); }, messages: { required: "This field is required.", remote: "Please fix this field.", email: "Please enter a valid email address.", url: "Please enter a valid URL.", date: "Please enter a valid date.", dateISO: "Please enter a valid date (ISO).", number: "Please enter a valid number.", digits: "Please enter only digits.", creditcard: "Please enter a valid credit card number.", equalTo: "Please enter the same value again.", accept: "Please enter a value with a valid extension.", maxlength: $.validator.format("Please enter no more than {0} characters."), minlength: $.validator.format("Please enter at least {0} characters."), rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), range: $.validator.format("Please enter a value between {0} and {1}."), max: $.validator.format("Please enter a value less than or equal to {0}."), min: $.validator.format("Please enter a value greater than or equal to {0}.") }, autoCreateRanges: false, prototype: { init: function() { this.labelContainer = $(this.settings.errorLabelContainer); this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer ); this.submitted = {}; this.valueCache = {}; this.pendingRequest = 0; this.pending = {}; this.invalid = {}; this.reset(); var groups = (this.groups = {}); $.each(this.settings.groups, function(key, value) { $.each(value.split(/\s/), function(index, name) { groups[name] = key; }); }); var rules = this.settings.rules; $.each(rules, function(key, value) { rules[key] = $.validator.normalizeRule(value); }); function delegate(event) { var validator = $.data(this[0].form, "validator"), eventType = "on" + event.type.replace(/^validate/, ""); validator.settings[eventType] && validator.settings[eventType].call(validator, this[0], event); } $(this.currentForm) .validateDelegate("[type='text'], [type='password'], [type='file'], select, textarea, " + "[type='number'], [type='search'] ,[type='tel'], [type='url'], " + "[type='email'], [type='datetime'], [type='date'], [type='month'], " + "[type='week'], [type='time'], [type='datetime-local'], " + "[type='range'], [type='color'] ", "focusin focusout keyup", delegate) .validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", delegate); if (this.settings.invalidHandler) $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); }, // http://docs.jquery.com/Plugins/Validation/Validator/form form: function() { this.checkForm(); $.extend(this.submitted, this.errorMap); this.invalid = $.extend({}, this.errorMap); if (!this.valid()) $(this.currentForm).triggerHandler("invalid-form", [this]); this.showErrors(); return this.valid(); }, checkForm: function() { this.prepareForm(); for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) { this.check( elements[i] ); } return this.valid(); }, // http://docs.jquery.com/Plugins/Validation/Validator/element element: function( element ) { element = this.validationTargetFor( this.clean( element ) ); this.lastElement = element; this.prepareElement( element ); this.currentElements = $(element); var result = this.check( element ); if ( result ) { delete this.invalid[element.name]; } else { this.invalid[element.name] = true; } if ( !this.numberOfInvalids() ) { // Hide error containers on last error this.toHide = this.toHide.add( this.containers ); } this.showErrors(); return result; }, // http://docs.jquery.com/Plugins/Validation/Validator/showErrors showErrors: function(errors) { if(errors) { // add items to error list and map $.extend( this.errorMap, errors ); this.errorList = []; for ( var name in errors ) { this.errorList.push({ message: errors[name], element: this.findByName(name)[0] }); } // remove items from success list this.successList = $.grep( this.successList, function(element) { return !(element.name in errors); }); } this.settings.showErrors ? this.settings.showErrors.call( this, this.errorMap, this.errorList ) : this.defaultShowErrors(); }, // http://docs.jquery.com/Plugins/Validation/Validator/resetForm resetForm: function() { if ( $.fn.resetForm ) $( this.currentForm ).resetForm(); this.submitted = {}; this.lastElement = null; this.prepareForm(); this.hideErrors(); this.elements().removeClass( this.settings.errorClass ); }, numberOfInvalids: function() { return this.objectLength(this.invalid); }, objectLength: function( obj ) { var count = 0; for ( var i in obj ) count++; return count; }, hideErrors: function() { this.addWrapper( this.toHide ).hide(); }, valid: function() { return this.size() == 0; }, size: function() { return this.errorList.length; }, focusInvalid: function() { if( this.settings.focusInvalid ) { try { $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []) .filter(":visible") .focus() // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find .trigger("focusin"); } catch(e) { // ignore IE throwing errors when focusing hidden elements } } }, findLastActive: function() { var lastActive = this.lastActive; return lastActive && $.grep(this.errorList, function(n) { return n.element.name == lastActive.name; }).length == 1 && lastActive; }, elements: function() { var validator = this, rulesCache = {}; // select all valid inputs inside the form (no submit or reset buttons) return $(this.currentForm) .find("input, select, textarea") .not(":submit, :reset, :image, [disabled]") .not( this.settings.ignore ) .filter(function() { !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this); // select only the first element for each name, and only those with rules specified if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) return false; rulesCache[this.name] = true; return true; }); }, clean: function( selector ) { return $( selector )[0]; }, errors: function() { return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext ); }, reset: function() { this.successList = []; this.errorList = []; this.errorMap = {}; this.toShow = $([]); this.toHide = $([]); this.currentElements = $([]); }, prepareForm: function() { this.reset(); this.toHide = this.errors().add( this.containers ); }, prepareElement: function( element ) { this.reset(); this.toHide = this.errorsFor(element); }, check: function( element ) { element = this.validationTargetFor( this.clean( element ) ); var rules = $(element).rules(); var dependencyMismatch = false; for (var method in rules ) { var rule = { method: method, parameters: rules[method] }; try { var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters ); // if a method indicates that the field is optional and therefore valid, // don't mark it as valid when there are no other rules if ( result == "dependency-mismatch" ) { dependencyMismatch = true; continue; } dependencyMismatch = false; if ( result == "pending" ) { this.toHide = this.toHide.not( this.errorsFor(element) ); return; } if( !result ) { this.formatAndAdd( element, rule ); return false; } } catch(e) { this.settings.debug && window.console && console.log("exception occured when checking element " + element.id + ", check the '" + rule.method + "' method", e); throw e; } } if (dependencyMismatch) return; if ( this.objectLength(rules) ) this.successList.push(element); return true; }, // return the custom message for the given element and validation method // specified in the element's "messages" metadata customMetaMessage: function(element, method) { if (!$.metadata) return; var meta = this.settings.meta ? $(element).metadata()[this.settings.meta] : $(element).metadata(); return meta && meta.messages && meta.messages[method]; }, // return the custom message for the given element name and validation method customMessage: function( name, method ) { var m = this.settings.messages[name]; return m && (m.constructor == String ? m : m[method]); }, // return the first defined argument, allowing empty strings findDefined: function() { for(var i = 0; i < arguments.length; i++) { if (arguments[i] !== undefined) return arguments[i]; } return undefined; }, defaultMessage: function( element, method) { return this.findDefined( this.customMessage( element.name, method ), this.customMetaMessage( element, method ), // title is never undefined, so handle empty string as undefined !this.settings.ignoreTitle && element.title || undefined, $.validator.messages[method], "Warning: No message defined for " + element.name + "" ); }, formatAndAdd: function( element, rule ) { var message = this.defaultMessage( element, rule.method ), theregex = /\$?\{(\d+)\}/g; if ( typeof message == "function" ) { message = message.call(this, rule.parameters, element); } else if (theregex.test(message)) { message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters); } this.errorList.push({ message: message, element: element }); this.errorMap[element.name] = message; this.submitted[element.name] = message; }, addWrapper: function(toToggle) { if ( this.settings.wrapper ) toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); return toToggle; }, defaultShowErrors: function() { for ( var i = 0; this.errorList[i]; i++ ) { var error = this.errorList[i]; this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass ); this.showLabel( error.element, error.message ); } if( this.errorList.length ) { this.toShow = this.toShow.add( this.containers ); } if (this.settings.success) { for ( var i = 0; this.successList[i]; i++ ) { this.showLabel( this.successList[i] ); } } if (this.settings.unhighlight) { for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) { this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass ); } } this.toHide = this.toHide.not( this.toShow ); this.hideErrors(); this.addWrapper( this.toShow ).show(); }, validElements: function() { return this.currentElements.not(this.invalidElements()); }, invalidElements: function() { return $(this.errorList).map(function() { return this.element; }); }, showLabel: function(element, message) { var label = this.errorsFor( element ); if ( label.length ) { // refresh error/success class label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass ); // check if we have a generated label, replace the message then label.attr("generated") && label.html(message); } else { // create label label = $("<" + this.settings.errorElement + "/>") .attr({"for": this.idOrName(element), generated: true}) .addClass(this.settings.errorClass) .html(message || ""); if ( this.settings.wrapper ) { // make sure the element is visible, even in IE // actually showing the wrapped element is handled elsewhere label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); } if ( !this.labelContainer.append(label).length ) this.settings.errorPlacement ? this.settings.errorPlacement(label, $(element) ) : label.insertAfter(element); } if ( !message && this.settings.success ) { label.text(""); typeof this.settings.success == "string" ? label.addClass( this.settings.success ) : this.settings.success( label ); } this.toShow = this.toShow.add(label); }, errorsFor: function(element) { var name = this.idOrName(element); return this.errors().filter(function() { return $(this).attr('for') == name; }); }, idOrName: function(element) { return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); }, validationTargetFor: function(element) { // if radio/checkbox, validate first element in group instead if (this.checkable(element)) { element = this.findByName( element.name ).not(this.settings.ignore)[0]; } return element; }, checkable: function( element ) { return /radio|checkbox/i.test(element.type); }, findByName: function( name ) { // select by name and filter by form for performance over form.find("[name=...]") var form = this.currentForm; return $(document.getElementsByName(name)).map(function(index, element) { return element.form == form && element.name == name && element || null; }); }, getLength: function(value, element) { switch( element.nodeName.toLowerCase() ) { case 'select': return $("option:selected", element).length; case 'input': if( this.checkable( element) ) return this.findByName(element.name).filter(':checked').length; } return value.length; }, depend: function(param, element) { return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true; }, dependTypes: { "boolean": function(param, element) { return param; }, "string": function(param, element) { return !!$(param, element.form).length; }, "function": function(param, element) { return param(element); } }, optional: function(element) { return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch"; }, startRequest: function(element) { if (!this.pending[element.name]) { this.pendingRequest++; this.pending[element.name] = true; } }, stopRequest: function(element, valid) { this.pendingRequest--; // sometimes synchronization fails, make sure pendingRequest is never < 0 if (this.pendingRequest < 0) this.pendingRequest = 0; delete this.pending[element.name]; if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) { $(this.currentForm).submit(); this.formSubmitted = false; } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) { $(this.currentForm).triggerHandler("invalid-form", [this]); this.formSubmitted = false; } }, previousValue: function(element) { return $.data(element, "previousValue") || $.data(element, "previousValue", { old: null, valid: true, message: this.defaultMessage( element, "remote" ) }); } }, classRuleSettings: { required: {required: true}, email: {email: true}, url: {url: true}, date: {date: true}, dateISO: {dateISO: true}, dateDE: {dateDE: true}, number: {number: true}, numberDE: {numberDE: true}, digits: {digits: true}, creditcard: {creditcard: true} }, addClassRules: function(className, rules) { className.constructor == String ? this.classRuleSettings[className] = rules : $.extend(this.classRuleSettings, className); }, classRules: function(element) { var rules = {}; var classes = $(element).attr('class'); classes && $.each(classes.split(' '), function() { if (this in $.validator.classRuleSettings) { $.extend(rules, $.validator.classRuleSettings[this]); } }); return rules; }, attributeRules: function(element) { var rules = {}; var $element = $(element); for (var method in $.validator.methods) { var value; // If .prop exists (jQuery >= 1.6), use it to get true/false for required if (method === 'required' && typeof $.fn.prop === 'function') { value = $element.prop(method); } else { value = $element.attr(method); } if (value) { rules[method] = value; } else if ($element[0].getAttribute("type") === method) { rules[method] = true; } } // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) { delete rules.maxlength; } return rules; }, metadataRules: function(element) { if (!$.metadata) return {}; var meta = $.data(element.form, 'validator').settings.meta; return meta ? $(element).metadata()[meta] : $(element).metadata(); }, staticRules: function(element) { var rules = {}; var validator = $.data(element.form, 'validator'); if (validator.settings.rules) { rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; } return rules; }, normalizeRules: function(rules, element) { // handle dependency check $.each(rules, function(prop, val) { // ignore rule when param is explicitly false, eg. required:false if (val === false) { delete rules[prop]; return; } if (val.param || val.depends) { var keepRule = true; switch (typeof val.depends) { case "string": keepRule = !!$(val.depends, element.form).length; break; case "function": keepRule = val.depends.call(element, element); break; } if (keepRule) { rules[prop] = val.param !== undefined ? val.param : true; } else { delete rules[prop]; } } }); // evaluate parameters $.each(rules, function(rule, parameter) { rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; }); // clean number parameters $.each(['minlength', 'maxlength', 'min', 'max'], function() { if (rules[this]) { rules[this] = Number(rules[this]); } }); $.each(['rangelength', 'range'], function() { if (rules[this]) { rules[this] = [Number(rules[this][0]), Number(rules[this][1])]; } }); if ($.validator.autoCreateRanges) { // auto-create ranges if (rules.min && rules.max) { rules.range = [rules.min, rules.max]; delete rules.min; delete rules.max; } if (rules.minlength && rules.maxlength) { rules.rangelength = [rules.minlength, rules.maxlength]; delete rules.minlength; delete rules.maxlength; } } // To support custom messages in metadata ignore rule methods titled "messages" if (rules.messages) { delete rules.messages; } return rules; }, // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} normalizeRule: function(data) { if( typeof data == "string" ) { var transformed = {}; $.each(data.split(/\s/), function() { transformed[this] = true; }); data = transformed; } return data; }, // http://docs.jquery.com/Plugins/Validation/Validator/addMethod addMethod: function(name, method, message) { $.validator.methods[name] = method; $.validator.messages[name] = message != undefined ? message : $.validator.messages[name]; if (method.length < 3) { $.validator.addClassRules(name, $.validator.normalizeRule(name)); } }, methods: { // http://docs.jquery.com/Plugins/Validation/Methods/required required: function(value, element, param) { // check if dependency is met if ( !this.depend(param, element) ) return "dependency-mismatch"; switch( element.nodeName.toLowerCase() ) { case 'select': // could be an array for select-multiple or a string, both are fine this way var val = $(element).val(); return val && val.length > 0; case 'input': if ( this.checkable(element) ) return this.getLength(value, element) > 0; default: return $.trim(value).length > 0; } }, // http://docs.jquery.com/Plugins/Validation/Methods/remote remote: function(value, element, param) { if ( this.optional(element) ) return "dependency-mismatch"; var previous = this.previousValue(element); if (!this.settings.messages[element.name] ) this.settings.messages[element.name] = {}; previous.originalMessage = this.settings.messages[element.name].remote; this.settings.messages[element.name].remote = previous.message; param = typeof param == "string" && {url:param} || param; if ( this.pending[element.name] ) { return "pending"; } if ( previous.old === value ) { return previous.valid; } previous.old = value; var validator = this; this.startRequest(element); var data = {}; data[element.name] = value; $.ajax($.extend(true, { url: param, mode: "abort", port: "validate" + element.name, dataType: "json", data: data, success: function(response) { validator.settings.messages[element.name].remote = previous.originalMessage; var valid = response === true; if ( valid ) { var submitted = validator.formSubmitted; validator.prepareElement(element); validator.formSubmitted = submitted; validator.successList.push(element); validator.showErrors(); } else { var errors = {}; var message = response || validator.defaultMessage( element, "remote" ); errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message; validator.showErrors(errors); } previous.valid = valid; validator.stopRequest(element, valid); } }, param)); return "pending"; }, // http://docs.jquery.com/Plugins/Validation/Methods/minlength minlength: function(value, element, param) { return this.optional(element) || this.getLength($.trim(value), element) >= param; }, // http://docs.jquery.com/Plugins/Validation/Methods/maxlength maxlength: function(value, element, param) { return this.optional(element) || this.getLength($.trim(value), element) <= param; }, // http://docs.jquery.com/Plugins/Validation/Methods/rangelength rangelength: function(value, element, param) { var length = this.getLength($.trim(value), element); return this.optional(element) || ( length >= param[0] && length <= param[1] ); }, // http://docs.jquery.com/Plugins/Validation/Methods/min min: function( value, element, param ) { return this.optional(element) || value >= param; }, // http://docs.jquery.com/Plugins/Validation/Methods/max max: function( value, element, param ) { return this.optional(element) || value <= param; }, // http://docs.jquery.com/Plugins/Validation/Methods/range range: function( value, element, param ) { return this.optional(element) || ( value >= param[0] && value <= param[1] ); }, // http://docs.jquery.com/Plugins/Validation/Methods/email email: function(value, element) { // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/ return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/url url: function(value, element) { // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/date date: function(value, element) { return this.optional(element) || !/Invalid|NaN/.test(new Date(value)); }, // http://docs.jquery.com/Plugins/Validation/Methods/dateISO dateISO: function(value, element) { return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/number number: function(value, element) { return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/digits digits: function(value, element) { return this.optional(element) || /^\d+$/.test(value); }, // http://docs.jquery.com/Plugins/Validation/Methods/creditcard // based on http://en.wikipedia.org/wiki/Luhn creditcard: function(value, element) { if ( this.optional(element) ) return "dependency-mismatch"; // accept only spaces, digits and dashes if (/[^0-9 -]+/.test(value)) return false; var nCheck = 0, nDigit = 0, bEven = false; value = value.replace(/\D/g, ""); for (var n = value.length - 1; n >= 0; n--) { var cDigit = value.charAt(n); var nDigit = parseInt(cDigit, 10); if (bEven) { if ((nDigit *= 2) > 9) nDigit -= 9; } nCheck += nDigit; bEven = !bEven; } return (nCheck % 10) == 0; }, // http://docs.jquery.com/Plugins/Validation/Methods/accept accept: function(value, element, param) { param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif"; return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); }, // http://docs.jquery.com/Plugins/Validation/Methods/equalTo equalTo: function(value, element, param) { // bind to the blur event of the target in order to revalidate whenever the target field is updated // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() { $(element).valid(); }); return value == target.val(); } } }); // deprecated, use $.validator.format instead $.format = $.validator.format; })(jQuery); // ajax mode: abort // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() ;(function($) { var pendingRequests = {}; // Use a prefilter if available (1.5+) if ( $.ajaxPrefilter ) { $.ajaxPrefilter(function(settings, _, xhr) { var port = settings.port; if (settings.mode == "abort") { if ( pendingRequests[port] ) { pendingRequests[port].abort(); } pendingRequests[port] = xhr; } }); } else { // Proxy ajax var ajax = $.ajax; $.ajax = function(settings) { var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode, port = ( "port" in settings ? settings : $.ajaxSettings ).port; if (mode == "abort") { if ( pendingRequests[port] ) { pendingRequests[port].abort(); } return (pendingRequests[port] = ajax.apply(this, arguments)); } return ajax.apply(this, arguments); }; } })(jQuery); // provides cross-browser focusin and focusout events // IE has native support, in other browsers, use event caputuring (neither bubbles) // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target ;(function($) { // only implement if not provided by jQuery core (since 1.4) // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) { $.each({ focus: 'focusin', blur: 'focusout' }, function( original, fix ){ $.event.special[fix] = { setup:function() { this.addEventListener( original, handler, true ); }, teardown:function() { this.removeEventListener( original, handler, true ); }, handler: function(e) { arguments[0] = $.event.fix(e); arguments[0].type = fix; return $.event.handle.apply(this, arguments); } }; function handler(e) { e = $.event.fix(e); e.type = fix; return $.event.handle.call(this, e); } }); }; $.extend($.fn, { validateDelegate: function(delegate, type, handler) { return this.bind(type, function(event) { var target = $(event.target); if (target.is(delegate)) { return handler.apply(target, arguments); } }); } }); })(jQuery); ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Scripts/jquery.validate.unobtrusive.js ================================================ /// /// /*! ** Unobtrusive validation support library for jQuery and jQuery Validate ** Copyright (C) Microsoft Corporation. All rights reserved. */ /*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ /*global document: false, jQuery: false */ (function ($) { var $jQval = $.validator, adapters, data_validation = "unobtrusiveValidation"; function setValidationValues(options, ruleName, value) { options.rules[ruleName] = value; if (options.message) { options.messages[ruleName] = options.message; } } function splitAndTrim(value) { return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g); } function getModelPrefix(fieldName) { return fieldName.substr(0, fieldName.lastIndexOf(".") + 1); } function appendModelPrefix(value, prefix) { if (value.indexOf("*.") === 0) { value = value.replace("*.", prefix); } return value; } function onError(error, inputElement) { // 'this' is the form element var container = $(this).find("[data-valmsg-for='" + inputElement[0].name + "']"), replace = $.parseJSON(container.attr("data-valmsg-replace")) !== false; container.removeClass("field-validation-valid").addClass("field-validation-error"); error.data("unobtrusiveContainer", container); if (replace) { container.empty(); error.removeClass("input-validation-error").appendTo(container); } else { error.hide(); } } function onErrors(form, validator) { // 'this' is the form element var container = $(this).find("[data-valmsg-summary=true]"), list = container.find("ul"); if (list && list.length && validator.errorList.length) { list.empty(); container.addClass("validation-summary-errors").removeClass("validation-summary-valid"); $.each(validator.errorList, function () { $("
  • ").html(this.message).appendTo(list); }); } } function onSuccess(error) { // 'this' is the form element var container = error.data("unobtrusiveContainer"), replace = $.parseJSON(container.attr("data-valmsg-replace")); if (container) { container.addClass("field-validation-valid").removeClass("field-validation-error"); error.removeData("unobtrusiveContainer"); if (replace) { container.empty(); } } } function validationInfo(form) { var $form = $(form), result = $form.data(data_validation); if (!result) { result = { options: { // options structure passed to jQuery Validate's validate() method errorClass: "input-validation-error", errorElement: "span", errorPlacement: $.proxy(onError, form), invalidHandler: $.proxy(onErrors, form), messages: {}, rules: {}, success: $.proxy(onSuccess, form) }, attachValidation: function () { $form.validate(this.options); }, validate: function () { // a validation function that is called by unobtrusive Ajax $form.validate(); return $form.valid(); } }; $form.data(data_validation, result); } return result; } $jQval.unobtrusive = { adapters: [], parseElement: function (element, skipAttach) { /// /// Parses a single HTML element for unobtrusive validation attributes. /// /// The HTML element to be parsed. /// [Optional] true to skip attaching the /// validation to the form. If parsing just this single element, you should specify true. /// If parsing several elements, you should specify false, and manually attach the validation /// to the form when you are finished. The default is false. var $element = $(element), form = $element.parents("form")[0], valInfo, rules, messages; if (!form) { // Cannot do client-side validation without a form return; } valInfo = validationInfo(form); valInfo.options.rules[element.name] = rules = {}; valInfo.options.messages[element.name] = messages = {}; $.each(this.adapters, function () { var prefix = "data-val-" + this.name, message = $element.attr(prefix), paramValues = {}; if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy) prefix += "-"; $.each(this.params, function () { paramValues[this] = $element.attr(prefix + this); }); this.adapt({ element: element, form: form, message: message, params: paramValues, rules: rules, messages: messages }); } }); jQuery.extend(rules, { "__dummy__": true }); if (!skipAttach) { valInfo.attachValidation(); } }, parse: function (selector) { /// /// Parses all the HTML elements in the specified selector. It looks for input elements decorated /// with the [data-val=true] attribute value and enables validation according to the data-val-* /// attribute values. /// /// Any valid jQuery selector. $(selector).find(":input[data-val=true]").each(function () { $jQval.unobtrusive.parseElement(this, true); }); $("form").each(function () { var info = validationInfo(this); if (info) { info.attachValidation(); } }); } }; adapters = $jQval.unobtrusive.adapters; adapters.add = function (adapterName, params, fn) { /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation. /// The name of the adapter to be added. This matches the name used /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). /// [Optional] An array of parameter names (strings) that will /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and /// mmmm is the parameter name). /// The function to call, which adapts the values from the HTML /// attributes into jQuery Validate rules and/or messages. /// if (!fn) { // Called with no params, just a function fn = params; params = []; } this.push({ name: adapterName, params: params, adapt: fn }); return this; }; adapters.addBool = function (adapterName, ruleName) { /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where /// the jQuery Validate validation rule has no parameter values. /// The name of the adapter to be added. This matches the name used /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). /// [Optional] The name of the jQuery Validate rule. If not provided, the value /// of adapterName will be used instead. /// return this.add(adapterName, function (options) { setValidationValues(options, ruleName || adapterName, true); }); }; adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) { /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and /// one for min-and-max). The HTML parameters are expected to be named -min and -max. /// The name of the adapter to be added. This matches the name used /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). /// The name of the jQuery Validate rule to be used when you only /// have a minimum value. /// The name of the jQuery Validate rule to be used when you only /// have a maximum value. /// The name of the jQuery Validate rule to be used when you /// have both a minimum and maximum value. /// [Optional] The name of the HTML attribute that /// contains the minimum value. The default is "min". /// [Optional] The name of the HTML attribute that /// contains the maximum value. The default is "max". /// return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) { var min = options.params.min, max = options.params.max; if (min && max) { setValidationValues(options, minMaxRuleName, [min, max]); } else if (min) { setValidationValues(options, minRuleName, min); } else if (max) { setValidationValues(options, maxRuleName, max); } }); }; adapters.addSingleVal = function (adapterName, attribute, ruleName) { /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where /// the jQuery Validate validation rule has a single value. /// The name of the adapter to be added. This matches the name used /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name). /// [Optional] The name of the HTML attribute that contains the value. /// The default is "val". /// [Optional] The name of the jQuery Validate rule. If not provided, the value /// of adapterName will be used instead. /// return this.add(adapterName, [attribute || "val"], function (options) { setValidationValues(options, ruleName || adapterName, options.params[attribute]); }); }; $jQval.addMethod("__dummy__", function (value, element, params) { return true; }); $jQval.addMethod("regex", function (value, element, params) { var match; if (this.optional(element)) { return true; } match = new RegExp(params).exec(value); return (match && (match.index === 0) && (match[0].length === value.length)); }); adapters.addSingleVal("accept", "exts").addSingleVal("regex", "pattern"); adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"); adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range"); adapters.add("equalto", ["other"], function (options) { var prefix = getModelPrefix(options.element.name), other = options.params.other, fullOtherName = appendModelPrefix(other, prefix), element = $(options.form).find(":input[name=" + fullOtherName + "]")[0]; setValidationValues(options, "equalTo", element); }); adapters.add("required", function (options) { // jQuery Validate equates "required" with "mandatory" for checkbox elements if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") { setValidationValues(options, "required", true); } }); adapters.add("remote", ["url", "type", "additionalfields"], function (options) { var value = { url: options.params.url, type: options.params.type || "GET", data: {} }, prefix = getModelPrefix(options.element.name); $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) { var paramName = appendModelPrefix(fieldName, prefix); value.data[paramName] = function () { return $(options.form).find(":input[name='" + paramName + "']").val(); }; }); setValidationValues(options, "remote", value); }); $(function () { $jQval.unobtrusive.parse(document); }); }(jQuery)); ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Scripts/modernizr-2.5.3.js ================================================ /*! * Modernizr v2.5.3 * www.modernizr.com * * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton * Available under the BSD and MIT licenses: www.modernizr.com/license/ */ /* * Modernizr tests which native CSS3 and HTML5 features are available in * the current UA and makes the results available to you in two ways: * as properties on a global Modernizr object, and as classes on the * element. This information allows you to progressively enhance * your pages with a granular level of control over the experience. * * Modernizr has an optional (not included) conditional resource loader * called Modernizr.load(), based on Yepnope.js (yepnopejs.com). * To get a build that includes Modernizr.load(), as well as choosing * which tests to include, go to www.modernizr.com/download/ * * Authors Faruk Ates, Paul Irish, Alex Sexton * Contributors Ryan Seddon, Ben Alman */ window.Modernizr = (function( window, document, undefined ) { var version = '2.5.3', Modernizr = {}, // option for enabling the HTML classes to be added enableClasses = true, docElement = document.documentElement, /** * Create our "modernizr" element that we do most feature tests on. */ mod = 'modernizr', modElem = document.createElement(mod), mStyle = modElem.style, /** * Create the input element for various Web Forms feature tests. */ inputElem = document.createElement('input'), smile = ':)', toString = {}.toString, // List of property values to set for css tests. See ticket #21 prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), // Following spec is to expose vendor-specific style properties as: // elem.style.WebkitBorderRadius // and the following would be incorrect: // elem.style.webkitBorderRadius // Webkit ghosts their properties in lowercase but Opera & Moz do not. // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+ // erik.eae.net/archives/2008/03/10/21.48.10/ // More here: github.com/Modernizr/Modernizr/issues/issue/21 omPrefixes = 'Webkit Moz O ms', cssomPrefixes = omPrefixes.split(' '), domPrefixes = omPrefixes.toLowerCase().split(' '), ns = {'svg': 'http://www.w3.org/2000/svg'}, tests = {}, inputs = {}, attrs = {}, classes = [], slice = classes.slice, featureName, // used in testing loop // Inject element with style element and some CSS rules injectElementWithStyles = function( rule, callback, nodes, testnames ) { var style, ret, node, div = document.createElement('div'), // After page load injecting a fake body doesn't work so check if body exists body = document.body, // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it. fakeBody = body ? body : document.createElement('body'); if ( parseInt(nodes, 10) ) { // In order not to give false positives we create a node for each test // This also allows the method to scale for unspecified uses while ( nodes-- ) { node = document.createElement('div'); node.id = testnames ? testnames[nodes] : mod + (nodes + 1); div.appendChild(node); } } // '].join(''); div.id = mod; // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody. // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 fakeBody.innerHTML += style; fakeBody.appendChild(div); if(!body){ //avoid crashing IE8, if background image is used fakeBody.style.background = ""; docElement.appendChild(fakeBody); } ret = callback(div, rule); // If this is done after page load we don't want to remove the body so check if body exists !body ? fakeBody.parentNode.removeChild(fakeBody) : div.parentNode.removeChild(div); return !!ret; }, // adapted from matchMedia polyfill // by Scott Jehl and Paul Irish // gist.github.com/786768 testMediaQuery = function( mq ) { var matchMedia = window.matchMedia || window.msMatchMedia; if ( matchMedia ) { return matchMedia(mq).matches; } var bool; injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) { bool = (window.getComputedStyle ? getComputedStyle(node, null) : node.currentStyle)['position'] == 'absolute'; }); return bool; }, /** * isEventSupported determines if a given element supports the given event * function from yura.thinkweb2.com/isEventSupported/ */ isEventSupported = (function() { var TAGNAMES = { 'select': 'input', 'change': 'input', 'submit': 'form', 'reset': 'form', 'error': 'img', 'load': 'img', 'abort': 'img' }; function isEventSupported( eventName, element ) { element = element || document.createElement(TAGNAMES[eventName] || 'div'); eventName = 'on' + eventName; // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those var isSupported = eventName in element; if ( !isSupported ) { // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element if ( !element.setAttribute ) { element = document.createElement('div'); } if ( element.setAttribute && element.removeAttribute ) { element.setAttribute(eventName, ''); isSupported = is(element[eventName], 'function'); // If property was created, "remove it" (by setting value to `undefined`) if ( !is(element[eventName], 'undefined') ) { element[eventName] = undefined; } element.removeAttribute(eventName); } } element = null; return isSupported; } return isEventSupported; })(); // hasOwnProperty shim by kangax needed for Safari 2.0 support var _hasOwnProperty = ({}).hasOwnProperty, hasOwnProperty; if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { hasOwnProperty = function (object, property) { return _hasOwnProperty.call(object, property); }; } else { hasOwnProperty = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ return ((property in object) && is(object.constructor.prototype[property], 'undefined')); }; } // Taken from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js // ES-5 15.3.4.5 // http://es5.github.com/#x15.3.4.5 if (!Function.prototype.bind) { Function.prototype.bind = function bind(that) { var target = this; if (typeof target != "function") { throw new TypeError(); } var args = slice.call(arguments, 1), bound = function () { if (this instanceof bound) { var F = function(){}; F.prototype = target.prototype; var self = new F; var result = target.apply( self, args.concat(slice.call(arguments)) ); if (Object(result) === result) { return result; } return self; } else { return target.apply( that, args.concat(slice.call(arguments)) ); } }; return bound; }; } /** * setCss applies given styles to the Modernizr DOM node. */ function setCss( str ) { mStyle.cssText = str; } /** * setCssAll extrapolates all vendor-specific css strings. */ function setCssAll( str1, str2 ) { return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); } /** * is returns a boolean for if typeof obj is exactly type. */ function is( obj, type ) { return typeof obj === type; } /** * contains returns a boolean for if substr is found within str. */ function contains( str, substr ) { return !!~('' + str).indexOf(substr); } /** * testProps is a generic CSS / DOM property test; if a browser supports * a certain property, it won't return undefined for it. * A supported CSS property returns empty string when its not yet set. */ function testProps( props, prefixed ) { for ( var i in props ) { if ( mStyle[ props[i] ] !== undefined ) { return prefixed == 'pfx' ? props[i] : true; } } return false; } /** * testDOMProps is a generic DOM property test; if a browser supports * a certain property, it won't return undefined for it. */ function testDOMProps( props, obj, elem ) { for ( var i in props ) { var item = obj[props[i]]; if ( item !== undefined) { // return the property name as a string if (elem === false) return props[i]; // let's bind a function if (is(item, 'function')){ // default to autobind unless override return item.bind(elem || obj); } // return the unbound function or obj or value return item; } } return false; } /** * testPropsAll tests a list of DOM properties we want to check against. * We specify literally ALL possible (known and/or likely) properties on * the element including the non-vendor prefixed one, for forward- * compatibility. */ function testPropsAll( prop, prefixed, elem ) { var ucProp = prop.charAt(0).toUpperCase() + prop.substr(1), props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); // did they call .prefixed('boxSizing') or are we just testing a prop? if(is(prefixed, "string") || is(prefixed, "undefined")) { return testProps(props, prefixed); // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) } else { props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); return testDOMProps(props, prefixed, elem); } } /** * testBundle tests a list of CSS features that require element and style injection. * By bundling them together we can reduce the need to touch the DOM multiple times. */ /*>>testBundle*/ var testBundle = (function( styles, tests ) { var style = styles.join(''), len = tests.length; injectElementWithStyles(style, function( node, rule ) { var style = document.styleSheets[document.styleSheets.length - 1], // IE8 will bork if you create a custom build that excludes both fontface and generatedcontent tests. // So we check for cssRules and that there is a rule available // More here: github.com/Modernizr/Modernizr/issues/288 & github.com/Modernizr/Modernizr/issues/293 cssText = style ? (style.cssRules && style.cssRules[0] ? style.cssRules[0].cssText : style.cssText || '') : '', children = node.childNodes, hash = {}; while ( len-- ) { hash[children[len].id] = children[len]; } /*>>touch*/ Modernizr['touch'] = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch || (hash['touch'] && hash['touch'].offsetTop) === 9; /*>>touch*/ /*>>csstransforms3d*/ Modernizr['csstransforms3d'] = (hash['csstransforms3d'] && hash['csstransforms3d'].offsetLeft) === 9 && hash['csstransforms3d'].offsetHeight === 3; /*>>csstransforms3d*/ /*>>generatedcontent*/Modernizr['generatedcontent'] = (hash['generatedcontent'] && hash['generatedcontent'].offsetHeight) >= 1; /*>>generatedcontent*/ /*>>fontface*/ Modernizr['fontface'] = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0; /*>>fontface*/ }, len, tests); })([ // Pass in styles to be injected into document /*>>fontface*/ '@font-face {font-family:"font";src:url("https://")}' /*>>fontface*/ /*>>touch*/ ,['@media (',prefixes.join('touch-enabled),('),mod,')', '{#touch{top:9px;position:absolute}}'].join('') /*>>touch*/ /*>>csstransforms3d*/ ,['@media (',prefixes.join('transform-3d),('),mod,')', '{#csstransforms3d{left:9px;position:absolute;height:3px;}}'].join('')/*>>csstransforms3d*/ /*>>generatedcontent*/,['#generatedcontent:after{content:"',smile,'";visibility:hidden}'].join('') /*>>generatedcontent*/ ], [ /*>>fontface*/ 'fontface' /*>>fontface*/ /*>>touch*/ ,'touch' /*>>touch*/ /*>>csstransforms3d*/ ,'csstransforms3d' /*>>csstransforms3d*/ /*>>generatedcontent*/,'generatedcontent' /*>>generatedcontent*/ ]);/*>>testBundle*/ /** * Tests * ----- */ // The *new* flexbox // dev.w3.org/csswg/css3-flexbox tests['flexbox'] = function() { return testPropsAll('flexOrder'); }; // The *old* flexbox // www.w3.org/TR/2009/WD-css3-flexbox-20090723/ tests['flexbox-legacy'] = function() { return testPropsAll('boxDirection'); }; // On the S60 and BB Storm, getContext exists, but always returns undefined // so we actually have to call getContext() to verify // github.com/Modernizr/Modernizr/issues/issue/97/ tests['canvas'] = function() { var elem = document.createElement('canvas'); return !!(elem.getContext && elem.getContext('2d')); }; tests['canvastext'] = function() { return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function')); }; // this test initiates a new webgl context. // webk.it/70117 is tracking a legit feature detect proposal tests['webgl'] = function() { try { var canvas = document.createElement('canvas'), ret; ret = !!(window.WebGLRenderingContext && (canvas.getContext('experimental-webgl') || canvas.getContext('webgl'))); canvas = undefined; } catch (e){ ret = false; } return ret; }; /* * The Modernizr.touch test only indicates if the browser supports * touch events, which does not necessarily reflect a touchscreen * device, as evidenced by tablets running Windows 7 or, alas, * the Palm Pre / WebOS (touch) phones. * * Additionally, Chrome (desktop) used to lie about its support on this, * but that has since been rectified: crbug.com/36415 * * We also test for Firefox 4 Multitouch Support. * * For more info, see: modernizr.github.com/Modernizr/touch.html */ tests['touch'] = function() { return Modernizr['touch']; }; /** * geolocation tests for the new Geolocation API specification. * This test is a standards compliant-only test; for more complete * testing, including a Google Gears fallback, please see: * code.google.com/p/geo-location-javascript/ * or view a fallback solution using google's geo API: * gist.github.com/366184 */ tests['geolocation'] = function() { return !!navigator.geolocation; }; // Per 1.6: // This used to be Modernizr.crosswindowmessaging but the longer // name has been deprecated in favor of a shorter and property-matching one. // The old API is still available in 1.6, but as of 2.0 will throw a warning, // and in the first release thereafter disappear entirely. tests['postmessage'] = function() { return !!window.postMessage; }; // Chrome incognito mode used to throw an exception when using openDatabase // It doesn't anymore. tests['websqldatabase'] = function() { return !!window.openDatabase; }; // Vendors had inconsistent prefixing with the experimental Indexed DB: // - Webkit's implementation is accessible through webkitIndexedDB // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB // For speed, we don't test the legacy (and beta-only) indexedDB tests['indexedDB'] = function() { return !!testPropsAll("indexedDB",window); }; // documentMode logic from YUI to filter out IE8 Compat Mode // which false positives. tests['hashchange'] = function() { return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7); }; // Per 1.6: // This used to be Modernizr.historymanagement but the longer // name has been deprecated in favor of a shorter and property-matching one. // The old API is still available in 1.6, but as of 2.0 will throw a warning, // and in the first release thereafter disappear entirely. tests['history'] = function() { return !!(window.history && history.pushState); }; tests['draganddrop'] = function() { var div = document.createElement('div'); return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); }; // FIXME: Once FF10 is sunsetted, we can drop prefixed MozWebSocket // bugzil.la/695635 tests['websockets'] = function() { for ( var i = -1, len = cssomPrefixes.length; ++i < len; ){ if ( window[cssomPrefixes[i] + 'WebSocket'] ){ return true; } } return 'WebSocket' in window; }; // css-tricks.com/rgba-browser-support/ tests['rgba'] = function() { // Set an rgba() color and check the returned value setCss('background-color:rgba(150,255,150,.5)'); return contains(mStyle.backgroundColor, 'rgba'); }; tests['hsla'] = function() { // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally, // except IE9 who retains it as hsla setCss('background-color:hsla(120,40%,100%,.5)'); return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla'); }; tests['multiplebgs'] = function() { // Setting multiple images AND a color on the background shorthand property // and then querying the style.background property value for the number of // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! setCss('background:url(https://),url(https://),red url(https://)'); // If the UA supports multiple backgrounds, there should be three occurrences // of the string "url(" in the return value for elemStyle.background return /(url\s*\(.*?){3}/.test(mStyle.background); }; // In testing support for a given CSS property, it's legit to test: // `elem.style[styleName] !== undefined` // If the property is supported it will return an empty string, // if unsupported it will return undefined. // We'll take advantage of this quick test and skip setting a style // on our modernizr element, but instead just testing undefined vs // empty string. tests['backgroundsize'] = function() { return testPropsAll('backgroundSize'); }; tests['borderimage'] = function() { return testPropsAll('borderImage'); }; // Super comprehensive table about all the unique implementations of // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance tests['borderradius'] = function() { return testPropsAll('borderRadius'); }; // WebOS unfortunately false positives on this test. tests['boxshadow'] = function() { return testPropsAll('boxShadow'); }; // FF3.0 will false positive on this test tests['textshadow'] = function() { return document.createElement('div').style.textShadow === ''; }; tests['opacity'] = function() { // Browsers that actually have CSS Opacity implemented have done so // according to spec, which means their return values are within the // range of [0.0,1.0] - including the leading zero. setCssAll('opacity:.55'); // The non-literal . in this regex is intentional: // German Chrome returns this value as 0,55 // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 return /^0.55$/.test(mStyle.opacity); }; // Note, Android < 4 will pass this test, but can only animate // a single property at a time // daneden.me/2011/12/putting-up-with-androids-bullshit/ tests['cssanimations'] = function() { return testPropsAll('animationName'); }; tests['csscolumns'] = function() { return testPropsAll('columnCount'); }; tests['cssgradients'] = function() { /** * For CSS Gradients syntax, please see: * webkit.org/blog/175/introducing-css-gradients/ * developer.mozilla.org/en/CSS/-moz-linear-gradient * developer.mozilla.org/en/CSS/-moz-radial-gradient * dev.w3.org/csswg/css3-images/#gradients- */ var str1 = 'background-image:', str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', str3 = 'linear-gradient(left top,#9f9, white);'; setCss( // legacy webkit syntax (FIXME: remove when syntax not in use anymore) (str1 + '-webkit- '.split(' ').join(str2 + str1) // standard syntax // trailing 'background-image:' + prefixes.join(str3 + str1)).slice(0, -str1.length) ); return contains(mStyle.backgroundImage, 'gradient'); }; tests['cssreflections'] = function() { return testPropsAll('boxReflect'); }; tests['csstransforms'] = function() { return !!testPropsAll('transform'); }; tests['csstransforms3d'] = function() { var ret = !!testPropsAll('perspective'); // Webkit's 3D transforms are passed off to the browser's own graphics renderer. // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in // some conditions. As a result, Webkit typically recognizes the syntax but // will sometimes throw a false positive, thus we must do a more thorough check: if ( ret && 'webkitPerspective' in docElement.style ) { // Webkit allows this media query to succeed only if the feature is enabled. // `@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-ms-transform-3d),(-webkit-transform-3d),(modernizr){ ... }` ret = Modernizr['csstransforms3d']; } return ret; }; tests['csstransitions'] = function() { return testPropsAll('transition'); }; /*>>fontface*/ // @font-face detection routine by Diego Perini // javascript.nwbox.com/CSSSupport/ // false positives in WebOS: github.com/Modernizr/Modernizr/issues/342 tests['fontface'] = function() { return Modernizr['fontface']; }; /*>>fontface*/ // CSS generated content detection tests['generatedcontent'] = function() { return Modernizr['generatedcontent']; }; // These tests evaluate support of the video/audio elements, as well as // testing what types of content they support. // // We're using the Boolean constructor here, so that we can extend the value // e.g. Modernizr.video // true // Modernizr.video.ogg // 'probably' // // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845 // thx to NielsLeenheer and zcorpan // Note: in some older browsers, "no" was a return value instead of empty string. // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2 // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5 tests['video'] = function() { var elem = document.createElement('video'), bool = false; // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224 try { if ( bool = !!elem.canPlayType ) { bool = new Boolean(bool); bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,''); bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,''); bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,''); } } catch(e) { } return bool; }; tests['audio'] = function() { var elem = document.createElement('audio'), bool = false; try { if ( bool = !!elem.canPlayType ) { bool = new Boolean(bool); bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''); bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,''); // Mimetypes accepted: // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements // bit.ly/iphoneoscodecs bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,''); bool.m4a = ( elem.canPlayType('audio/x-m4a;') || elem.canPlayType('audio/aac;')) .replace(/^no$/,''); } } catch(e) { } return bool; }; // In FF4, if disabled, window.localStorage should === null. // Normally, we could not test that directly and need to do a // `('localStorage' in window) && ` test first because otherwise Firefox will // throw bugzil.la/365772 if cookies are disabled // Also in iOS5 Private Browsing mode, attepting to use localStorage.setItem // will throw the exception: // QUOTA_EXCEEDED_ERRROR DOM Exception 22. // Peculiarly, getItem and removeItem calls do not throw. // Because we are forced to try/catch this, we'll go aggressive. // Just FWIW: IE8 Compat mode supports these features completely: // www.quirksmode.org/dom/html5.html // But IE8 doesn't support either with local files tests['localstorage'] = function() { try { localStorage.setItem(mod, mod); localStorage.removeItem(mod); return true; } catch(e) { return false; } }; tests['sessionstorage'] = function() { try { sessionStorage.setItem(mod, mod); sessionStorage.removeItem(mod); return true; } catch(e) { return false; } }; tests['webworkers'] = function() { return !!window.Worker; }; tests['applicationcache'] = function() { return !!window.applicationCache; }; // Thanks to Erik Dahlstrom tests['svg'] = function() { return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; }; // specifically for SVG inline in HTML, not within XHTML // test page: paulirish.com/demo/inline-svg tests['inlinesvg'] = function() { var div = document.createElement('div'); div.innerHTML = ''; return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; }; // SVG SMIL animation tests['smil'] = function() { return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate'))); }; // This test is only for clip paths in SVG proper, not clip paths on HTML content // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg // However read the comments to dig into applying SVG clippaths to HTML content here: // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491 tests['svgclippaths'] = function() { return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath'))); }; // input features and input types go directly onto the ret object, bypassing the tests loop. // Hold this guy to execute in a moment. function webforms() { // Run through HTML5's new input attributes to see if the UA understands any. // We're using f which is the element created early on // Mike Taylr has created a comprehensive resource for testing these attributes // when applied to all input types: // miketaylr.com/code/input-type-attr.html // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary // Only input placeholder is tested while textarea's placeholder is not. // Currently Safari 4 and Opera 11 have support only for the input placeholder // Both tests are available in feature-detects/forms-placeholder.js Modernizr['input'] = (function( props ) { for ( var i = 0, len = props.length; i < len; i++ ) { attrs[ props[i] ] = !!(props[i] in inputElem); } if (attrs.list){ // safari false positive's on datalist: webk.it/74252 // see also github.com/Modernizr/Modernizr/issues/146 attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); } return attrs; })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); // Run through HTML5's new input types to see if the UA understands any. // This is put behind the tests runloop because it doesn't return a // true/false like all the other tests; instead, it returns an object // containing each input type with its corresponding true/false value // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/ Modernizr['inputtypes'] = (function(props) { for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) { inputElem.setAttribute('type', inputElemType = props[i]); bool = inputElem.type !== 'text'; // We first check to see if the type we give it sticks.. // If the type does, we feed it a textual value, which shouldn't be valid. // If the value doesn't stick, we know there's input sanitization which infers a custom UI if ( bool ) { inputElem.value = smile; inputElem.style.cssText = 'position:absolute;visibility:hidden;'; if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { docElement.appendChild(inputElem); defaultView = document.defaultView; // Safari 2-4 allows the smiley as a value, despite making a slider bool = defaultView.getComputedStyle && defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && // Mobile android web browser has false positive, so must // check the height to see if the widget is actually there. (inputElem.offsetHeight !== 0); docElement.removeChild(inputElem); } else if ( /^(search|tel)$/.test(inputElemType) ){ // Spec doesnt define any special parsing or detectable UI // behaviors so we pass these through as true // Interestingly, opera fails the earlier test, so it doesn't // even make it here. } else if ( /^(url|email)$/.test(inputElemType) ) { // Real url and email support comes with prebaked validation. bool = inputElem.checkValidity && inputElem.checkValidity() === false; } else if ( /^color$/.test(inputElemType) ) { // chuck into DOM and force reflow for Opera bug in 11.00 // github.com/Modernizr/Modernizr/issues#issue/159 docElement.appendChild(inputElem); docElement.offsetWidth; bool = inputElem.value != smile; docElement.removeChild(inputElem); } else { // If the upgraded input compontent rejects the :) text, we got a winner bool = inputElem.value != smile; } } inputs[ props[i] ] = !!bool; } return inputs; })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); } // End of test definitions // ----------------------- // Run through all tests and detect their support in the current UA. // todo: hypothetically we could be doing an array of tests and use a basic loop here. for ( var feature in tests ) { if ( hasOwnProperty(tests, feature) ) { // run the test, throw the return value into the Modernizr, // then based on that boolean, define an appropriate className // and push it into an array of classes we'll join later. featureName = feature.toLowerCase(); Modernizr[featureName] = tests[feature](); classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); } } // input tests need to run. Modernizr.input || webforms(); /** * addTest allows the user to define their own feature tests * the result will be added onto the Modernizr object, * as well as an appropriate className set on the html element * * @param feature - String naming the feature * @param test - Function returning true if feature is supported, false if not */ Modernizr.addTest = function ( feature, test ) { if ( typeof feature == 'object' ) { for ( var key in feature ) { if ( hasOwnProperty( feature, key ) ) { Modernizr.addTest( key, feature[ key ] ); } } } else { feature = feature.toLowerCase(); if ( Modernizr[feature] !== undefined ) { // we're going to quit if you're trying to overwrite an existing test // if we were to allow it, we'd do this: // var re = new RegExp("\\b(no-)?" + feature + "\\b"); // docElement.className = docElement.className.replace( re, '' ); // but, no rly, stuff 'em. return Modernizr; } test = typeof test == 'function' ? test() : test; docElement.className += ' ' + (test ? '' : 'no-') + feature; Modernizr[feature] = test; } return Modernizr; // allow chaining. }; // Reset modElem.cssText to nothing to reduce memory footprint. setCss(''); modElem = inputElem = null; //>>BEGIN IEPP // Enable HTML 5 elements for styling in IE & add HTML5 css /*! HTML5 Shiv v3.4 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */ ;(function(window, document) { /** Preset options */ var options = window.html5 || {}; /** Used to skip problem elements */ var reSkip = /^<|^(?:button|form|map|select|textarea)$/i; /** Detect whether the browser supports default html5 styles */ var supportsHtml5Styles; /** Detect whether the browser supports unknown elements */ var supportsUnknownElements; (function() { var a = document.createElement('a'); a.innerHTML = ''; //if the hidden property is implemented we can assume, that the browser supports HTML5 Styles supportsHtml5Styles = ('hidden' in a); supportsUnknownElements = a.childNodes.length == 1 || (function() { // assign a false positive if unable to shiv try { (document.createElement)('a'); } catch(e) { return true; } var frag = document.createDocumentFragment(); return ( typeof frag.cloneNode == 'undefined' || typeof frag.createDocumentFragment == 'undefined' || typeof frag.createElement == 'undefined' ); }()); }()); /*--------------------------------------------------------------------------*/ /** * Creates a style sheet with the given CSS text and adds it to the document. * @private * @param {Document} ownerDocument The document. * @param {String} cssText The CSS text. * @returns {StyleSheet} The style element. */ function addStyleSheet(ownerDocument, cssText) { var p = ownerDocument.createElement('p'), parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; p.innerHTML = 'x'; return parent.insertBefore(p.lastChild, parent.firstChild); } /** * Returns the value of `html5.elements` as an array. * @private * @returns {Array} An array of shived element node names. */ function getElements() { var elements = html5.elements; return typeof elements == 'string' ? elements.split(' ') : elements; } /** * Shivs the `createElement` and `createDocumentFragment` methods of the document. * @private * @param {Document|DocumentFragment} ownerDocument The document. */ function shivMethods(ownerDocument) { var cache = {}, docCreateElement = ownerDocument.createElement, docCreateFragment = ownerDocument.createDocumentFragment, frag = docCreateFragment(); ownerDocument.createElement = function(nodeName) { // Avoid adding some elements to fragments in IE < 9 because // * Attributes like `name` or `type` cannot be set/changed once an element // is inserted into a document/fragment // * Link elements with `src` attributes that are inaccessible, as with // a 403 response, will cause the tab/window to crash // * Script elements appended to fragments will execute when their `src` // or `text` property is set var node = (cache[nodeName] || (cache[nodeName] = docCreateElement(nodeName))).cloneNode(); return html5.shivMethods && node.canHaveChildren && !reSkip.test(nodeName) ? frag.appendChild(node) : node; }; ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' + 'var n=f.cloneNode(),c=n.createElement;' + 'h.shivMethods&&(' + // unroll the `createElement` calls getElements().join().replace(/\w+/g, function(nodeName) { cache[nodeName] = docCreateElement(nodeName); frag.createElement(nodeName); return 'c("' + nodeName + '")'; }) + ');return n}' )(html5, frag); } /*--------------------------------------------------------------------------*/ /** * Shivs the given document. * @memberOf html5 * @param {Document} ownerDocument The document to shiv. * @returns {Document} The shived document. */ function shivDocument(ownerDocument) { var shived; if (ownerDocument.documentShived) { return ownerDocument; } if (html5.shivCSS && !supportsHtml5Styles) { shived = !!addStyleSheet(ownerDocument, // corrects block display not defined in IE6/7/8/9 'article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}' + // corrects audio display not defined in IE6/7/8/9 'audio{display:none}' + // corrects canvas and video display not defined in IE6/7/8/9 'canvas,video{display:inline-block;*display:inline;*zoom:1}' + // corrects 'hidden' attribute and audio[controls] display not present in IE7/8/9 '[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}' + // adds styling not present in IE6/7/8/9 'mark{background:#FF0;color:#000}' ); } if (!supportsUnknownElements) { shived = !shivMethods(ownerDocument); } if (shived) { ownerDocument.documentShived = shived; } return ownerDocument; } /*--------------------------------------------------------------------------*/ /** * The `html5` object is exposed so that more elements can be shived and * existing shiving can be detected on iframes. * @type Object * @example * * // options can be changed before the script is included * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false }; */ var html5 = { /** * An array or space separated string of node names of the elements to shiv. * @memberOf html5 * @type Array|String */ 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video', /** * A flag to indicate that the HTML5 style sheet should be inserted. * @memberOf html5 * @type Boolean */ 'shivCSS': !(options.shivCSS === false), /** * A flag to indicate that the document's `createElement` and `createDocumentFragment` * methods should be overwritten. * @memberOf html5 * @type Boolean */ 'shivMethods': !(options.shivMethods === false), /** * A string to describe the type of `html5` object ("default" or "default print"). * @memberOf html5 * @type String */ 'type': 'default', // shivs the document according to the specified `html5` object options 'shivDocument': shivDocument }; /*--------------------------------------------------------------------------*/ // expose html5 window.html5 = html5; // shiv the document shivDocument(document); }(this, document)); //>>END IEPP // Assign private properties to the return object with prefix Modernizr._version = version; // expose these for the plugin API. Look in the source for how to join() them against your input Modernizr._prefixes = prefixes; Modernizr._domPrefixes = domPrefixes; Modernizr._cssomPrefixes = cssomPrefixes; // Modernizr.mq tests a given media query, live against the current state of the window // A few important notes: // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false // * A max-width or orientation query will be evaluated against the current state, which may change later. // * You must specify values. Eg. If you are testing support for the min-width media query use: // Modernizr.mq('(min-width:0)') // usage: // Modernizr.mq('only screen and (max-width:768)') Modernizr.mq = testMediaQuery; // Modernizr.hasEvent() detects support for a given event, with an optional element to test on // Modernizr.hasEvent('gesturestart', elem) Modernizr.hasEvent = isEventSupported; // Modernizr.testProp() investigates whether a given style property is recognized // Note that the property names must be provided in the camelCase variant. // Modernizr.testProp('pointerEvents') Modernizr.testProp = function(prop){ return testProps([prop]); }; // Modernizr.testAllProps() investigates whether a given style property, // or any of its vendor-prefixed variants, is recognized // Note that the property names must be provided in the camelCase variant. // Modernizr.testAllProps('boxSizing') Modernizr.testAllProps = testPropsAll; // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... }) Modernizr.testStyles = injectElementWithStyles; // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style. // Return values will also be the camelCase variant, if you need to translate that to hypenated style use: // // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); // If you're trying to ascertain which transition end event to bind to, you might do something like... // // var transEndEventNames = { // 'WebkitTransition' : 'webkitTransitionEnd', // 'MozTransition' : 'transitionend', // 'OTransition' : 'oTransitionEnd', // 'msTransition' : 'MsTransitionEnd', // 'transition' : 'transitionend' // }, // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; Modernizr.prefixed = function(prop, obj, elem){ if(!obj) { return testPropsAll(prop, 'pfx'); } else { // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' return testPropsAll(prop, obj, elem); } }; // Remove "no-js" class from element, if it exists: docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + // Add the new classes to the element. (enableClasses ? ' js ' + classes.join(' ') : ''); return Modernizr; })(this, this.document); ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Views/Account/ChangePassword.aspx ================================================ <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> Change Password

    Change Password

    Use the form below to change your password.

    New passwords are required to be a minimum of <%: Membership.MinRequiredPasswordLength %> characters in length.

    <% using (Html.BeginForm()) { %> <%: Html.ValidationSummary(true, "Password change was unsuccessful. Please correct the errors and try again.") %>
    Account Information
    <%: Html.LabelFor(m => m.OldPassword) %>
    <%: Html.PasswordFor(m => m.OldPassword) %> <%: Html.ValidationMessageFor(m => m.OldPassword) %>
    <%: Html.LabelFor(m => m.NewPassword) %>
    <%: Html.PasswordFor(m => m.NewPassword) %> <%: Html.ValidationMessageFor(m => m.NewPassword) %>
    <%: Html.LabelFor(m => m.ConfirmPassword) %>
    <%: Html.PasswordFor(m => m.ConfirmPassword) %> <%: Html.ValidationMessageFor(m => m.ConfirmPassword) %>

    <% } %>
    ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Views/Account/ChangePasswordSuccess.aspx ================================================ <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> Change Password

    Change Password

    Your password has been changed successfully.

    ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Views/Account/LogOn.aspx ================================================ <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> Log On

    Log On

    Please enter your user name and password. <%: Html.ActionLink("Register", "Register") %> if you don't have an account.

    <% using (Html.BeginForm()) { %> <%: Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.") %>
    Account Information
    <%: Html.LabelFor(m => m.UserName) %>
    <%: Html.TextBoxFor(m => m.UserName) %> <%: Html.ValidationMessageFor(m => m.UserName) %>
    <%: Html.LabelFor(m => m.Password) %>
    <%: Html.PasswordFor(m => m.Password) %> <%: Html.ValidationMessageFor(m => m.Password) %>
    <%: Html.CheckBoxFor(m => m.RememberMe) %> <%: Html.LabelFor(m => m.RememberMe) %>

    <% } %>
    ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Views/Account/Register.aspx ================================================ <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> Register

    Create a New Account

    Use the form below to create a new account.

    Passwords are required to be a minimum of <%: Membership.MinRequiredPasswordLength %> characters in length.

    <% using (Html.BeginForm()) { %> <%: Html.ValidationSummary(true, "Account creation was unsuccessful. Please correct the errors and try again.") %>
    Account Information
    <%: Html.LabelFor(m => m.UserName) %>
    <%: Html.TextBoxFor(m => m.UserName) %> <%: Html.ValidationMessageFor(m => m.UserName) %>
    <%: Html.LabelFor(m => m.Email) %>
    <%: Html.TextBoxFor(m => m.Email) %> <%: Html.ValidationMessageFor(m => m.Email) %>
    <%: Html.LabelFor(m => m.Password) %>
    <%: Html.PasswordFor(m => m.Password) %> <%: Html.ValidationMessageFor(m => m.Password) %>
    <%: Html.LabelFor(m => m.ConfirmPassword) %>
    <%: Html.PasswordFor(m => m.ConfirmPassword) %> <%: Html.ValidationMessageFor(m => m.ConfirmPassword) %>

    <% } %>
    ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Views/Home/About.aspx ================================================ <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> About Us

    About

    Put content here.

    ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Views/Home/Index.aspx ================================================ <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> Home Page

    <%: ViewBag.Message %>

    To learn more about ASP.NET MVC visit http://asp.net/mvc.

    ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Views/Shared/Error.aspx ================================================ <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> Error

    Sorry, an error occurred while processing your request.

    ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Views/Shared/LogOnUserControl.ascx ================================================ <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %> <% if (Request.IsAuthenticated) { %> Welcome <%: Page.User.Identity.Name %>! [ <%: Html.ActionLink("Log Off", "LogOff", "Account") %> ] <% } else { %> [ <%: Html.ActionLink("Log On", "LogOn", "Account") %> ] <% } %> ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Views/Shared/Site.Master ================================================ <%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> <asp:ContentPlaceHolder ID="TitleContent" runat="server" />
    ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Views/Web.config ================================================ 
    ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Web.Debug.config ================================================  ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Web.Release.config ================================================  ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/Web.config ================================================ 
    ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.Presentation/packages.config ================================================  ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/DDDPPP.Chap20.CommandHandler.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DDDPPP.Chap20.CommandHandler.Application", "DDDPPP.Chap20.CommandHandler.Application\DDDPPP.Chap20.CommandHandler.Application.csproj", "{52858090-3479-4015-984F-5AA049857F3F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{C0A1BA29-2AC9-4C3D-B3BF-CE1E466478C9}" ProjectSection(SolutionItems) = preProject .nuget\NuGet.Config = .nuget\NuGet.Config .nuget\NuGet.exe = .nuget\NuGet.exe .nuget\NuGet.targets = .nuget\NuGet.targets EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {52858090-3479-4015-984F-5AA049857F3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {52858090-3479-4015-984F-5AA049857F3F}.Debug|Any CPU.Build.0 = Debug|Any CPU {52858090-3479-4015-984F-5AA049857F3F}.Release|Any CPU.ActiveCfg = Release|Any CPU {52858090-3479-4015-984F-5AA049857F3F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/App_Start/RouteConfig.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace PPPDDD.ApplicationServices.Gambling { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/1_validation/RecommendAFriendService.cs ================================================ using System; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.ApplicationValidation { public class RecommendAFriendService { public void RecommendAFriend(int referrerId, NewAccount friendsAccountDetails) { Validate(friendsAccountDetails); // ... } // technical validation carried out at the application level private void Validate(NewAccount account) { if (!account.Email.Contains("@")) throw new ValidationFailure("Not a valid email address"); if (account.Email.Length >= 50) throw new ValidationFailure("Email address must be less than 50 characters"); if (account.Nickname.Length >= 25) throw new ValidationFailure("Nickname must be less than 25 characters"); if (String.IsNullOrWhiteSpace(account.Email)) throw new ValidationFailure("You must supply an email"); if (String.IsNullOrWhiteSpace(account.Nickname)) throw new ValidationFailure("You must supply a Nickname"); } } public class NewAccount { public string Email { get; set; } public string Nickname { get; set; } public int Age { get; set; } } public class ValidationFailure : Exception { public ValidationFailure(string message) : base(message) { } } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/2_transaction/RecommendAFriendService.cs ================================================ using Raven.Client; using System; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.Transaction { public class RecommendAFriendService { public void RecommendAFriend(int referrerId, NewAccount friendsAccountDetails) { Validate(friendsAccountDetails); // most technologies have similar transaction APIs using (var transaction = new System.Transactions.TransactionScope()) { try { // ... interact with domain multiple times transaction.Complete(); } catch { // transaction will roll back if Complete() not called } } } // technical validation carried out at the application level private void Validate(NewAccount account) { if (!account.Email.Contains("@")) throw new ValidationFailure("Not a valid email address"); if (account.Email.Length >= 50) throw new ValidationFailure("Email address must be less than 50 characters"); if (account.Nickname.Length >= 25) throw new ValidationFailure("Nickname must be less than 25 characters"); if (String.IsNullOrWhiteSpace(account.Email)) throw new ValidationFailure("You must supply an email"); if (String.IsNullOrWhiteSpace(account.Nickname)) throw new ValidationFailure("You must supply a Nickname"); } } public class NewAccount { public string Email { get; set; } public string Nickname { get; set; } public int Age { get; set; } } public class ValidationFailure : Exception { public ValidationFailure(string message) : base(message) { } } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/3_error_handling/RecommendAFriendService.cs ================================================ using Raven.Client; using System; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.ErrorHandling { public class RecommendAFriendService { public void RecommendAFriend(int referrerId, NewAccount friendsAccountDetails) { Validate(friendsAccountDetails); // most technologies have similar transaction APIs using (var transaction = new System.Transactions.TransactionScope()) { try { // ... interact with domain multiple times transaction.Complete(); } catch(ReferralRejectedDueToLongTermOutstandingBalance) { throw new ApplicationError( "Sorry, this referral cannot be completed. The referrer " + "currently has an outstanding balance. Please contact " + "Customer Services" ); // transaction will roll back if Complete() not called } } } // technical validation carried out at the application level private void Validate(NewAccount account) { if (!account.Email.Contains("@")) throw new ValidationFailure("Not a valid email address"); if (account.Email.Length >= 50) throw new ValidationFailure("Email address must be less than 50 characters"); if (account.Nickname.Length >= 25) throw new ValidationFailure("Nickname must be less than 25 characters"); if (String.IsNullOrWhiteSpace(account.Email)) throw new ValidationFailure("You must supply an email"); if (String.IsNullOrWhiteSpace(account.Nickname)) throw new ValidationFailure("You must supply a Nickname"); } } public class NewAccount { public string Email { get; set; } public string Nickname { get; set; } public int Age { get; set; } } public class ValidationFailure : Exception { public ValidationFailure(string message) : base(message) { } } public class ApplicationError : Exception { public ApplicationError(string message) : base(message) { } } public class ReferralRejectedDueToLongTermOutstandingBalance : Exception { } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/4_logging_metrics/RecommendAFriendService.cs ================================================ using System; using StatsdClient; using Domain; using log4net; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.LoggingAndMetrics { public class RecommendAFriendService { private ILog logger = LogManager.GetLogger(typeof(RecommendAFriendService)); private ICustomerDirectory customerDirectory; private IReferAFriendPolicy referAFriendPolicy; public RecommendAFriendService(ICustomerDirectory customerDirectory, IReferAFriendPolicy referAFriendPolicy) { this.customerDirectory = customerDirectory; this.referAFriendPolicy = referAFriendPolicy; } public void RecommendAFriend(int referrerId, NewAccount friendsAccountDetails) { Validate(friendsAccountDetails); // most technologies have similar transaction APIs using (var transaction = new System.Transactions.TransactionScope()) { try { // customerDirectory is a domain repository var referrer = customerDirectory.Find(referrerId); var friend = customerDirectory.Add(friendsAccountDetails); // referAFriend policy is a domain policy referAFriendPolicy.Apply(referrer, friend); transaction.Complete(); // log here to keep to avoid cluttering domain logger.Debug("Successful friend recommendation"); StatsdClient.Metrics.Counter("friendReferrals"); } catch (ReferralRejectedDueToLongTermOutstandingBalance ex) { logger.Error(ex); StatsdClient.Metrics.Counter("ReferralRejected"); throw new ApplicationError( "Sorry, this referral cannot be completed. The referrer " + "currently has an outstanding balance. Please contact " + "customer support" ); // transaction will roll back if Complete() not called } } } // technical validation carried out at the application level private void Validate(NewAccount account) { if (!account.Email.Contains("@")) throw new ValidationFailure("Not a valid email address"); if (account.Email.Length >= 50) throw new ValidationFailure("Email address must be less than 50 characters"); if (account.Nickname.Length >= 25) throw new ValidationFailure("Nickname must be less than 25 characters"); if (String.IsNullOrWhiteSpace(account.Email)) throw new ValidationFailure("You must supply an email"); if (String.IsNullOrWhiteSpace(account.Nickname)) throw new ValidationFailure("You must supply a Nickname"); } } public class ValidationFailure : Exception { public ValidationFailure(string message) : base(message) { } } public class ApplicationError : Exception { public ApplicationError(string message) : base(message) { } } public class ReferralRejectedDueToLongTermOutstandingBalance : Exception { } } // just to exemplify that these classes belong to the domain namespace Domain { public class NewAccount { public string Email { get; set; } public string Nickname { get; set; } public int Age { get; set; } } public class Customer { public int Id { get; set; } } public interface ICustomerDirectory { Customer Find(int customerId); Customer Add(NewAccount account); } public interface IReferAFriendPolicy { void Apply(Customer referrer, Customer friend); } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/5_authentication/AdminRecommendAFriendService.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices._5_authentication { public class AdminRecommendAFriendService { private IAuthenticationService authentication; private IAuthorizationService authorization; public AdminRecommendAFriendService(IAuthenticationService authentication, IAuthorizationService authorization) { this.authentication = authentication; this.authorization = authorization; } public void ReferAFriend(int referrerId, int friendId) { if (!authentication.IsLoggedInUser()) throw new AuthenticationError(); if (!authorization.IsCurrentUserAdmin()) throw new AuthorizationError(); // look up customers // apply referral policy } } public interface IAuthenticationService { bool IsLoggedInUser(); } public interface IAuthorizationService { bool IsCurrentUserAdmin(); } public class AuthenticationError : Exception { } public class AuthorizationError : Exception { } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/6_communication/RecommendAFriendService.cs ================================================ using System; using Domain; using NServiceBus; using PPPDDD.ApplicationServices.Gambling.Messages; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.communication { public class RecommendAFriendService { private ICustomerDirectory customerDirectory; private IReferAFriendPolicy referAFriendPolicy; private IBus bus; public RecommendAFriendService(ICustomerDirectory customerDirectory, IReferAFriendPolicy referAFriendPolicy, IBus bus) { this.customerDirectory = customerDirectory; this.referAFriendPolicy = referAFriendPolicy; this.bus = bus; } public void RecommendAFriend(int referrerId, NewAccount friendsAccountDetails) { Validate(friendsAccountDetails); using (var transaction = new System.Transactions.TransactionScope()) { try { var referrer = customerDirectory.Find(referrerId); var friend = customerDirectory.Add(friendsAccountDetails); referAFriendPolicy.Apply(referrer, friend); transaction.Complete(); var msg = new CustomerRegisteredViaReferralPolicy { ReferrerId = referrerId, FriendId = friend.Id }; bus.Publish(msg); } catch (ReferralRejectedDueToLongTermOutstandingBalance) { var msg = new ReferralSignupRejected { ReferrerId = referrerId, FriendEmail = friendsAccountDetails.Email, Reason = "Referrer has long term outstanding balance" }; bus.Publish(msg); } } } private void Validate(NewAccount account) { // ... } } public class ReferralRejectedDueToLongTermOutstandingBalance : Exception { } } // keep messagees (external communication contract) in separate project (see chapter 12) namespace PPPDDD.ApplicationServices.Gambling.Messages { public class CustomerRegisteredViaReferralPolicy { public int ReferrerId { get; set; } public int FriendId { get; set; } } public class ReferralSignupRejected { public int ReferrerId { get; set; } public string FriendEmail { get; set; } public string Reason { get; set; } } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/AsyncAwait/RecommendAFriend.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Web; using AsyncAwaitDomain; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.AsyncAwait { public class RecommendAFriendService { private ICustomerDirectory directory; private IReferAFriendPolicy policy; public RecommendAFriendService(ICustomerDirectory customerDirectory, IReferAFriendPolicy policy) { this.directory = customerDirectory; this.policy = policy; } public async void ReferAFriend(int referrerId, NewAccount friend) { // ... var referrer = await directory.Find(referrerId); var newAcct = await directory.Create(friend); policy.Apply(referrer, newAcct); // ... } } } namespace AsyncAwaitDomain { public interface ICustomerDirectory { Task Find(int customerId); Task Create(NewAccount details); } public class NewAccount { public string Email { get; set; } public string Nickname { get; set; } public int Age { get; set; } } public class Customer { public int Id { get; set; } } public interface IReferAFriendPolicy { void Apply(Customer referrer, Customer friend); } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/CommandProcessor/BloatedRecommendAFriendService.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.CommandProcessor { public class BloatedRefcommendAFriendService { public void RecommendAFriend(int referrerId, NewAccount friend) { // ... } public void RecommendAFriendInDifferentCountry(int referrerId, NewAccount friend) { // ... } public void ReverseFriendReferral(int referrerId, int friendId) { // ... } public void ReferAFriendWithoutLoyaltyBonus(int referrerId, NewAccount friend) { // ... } // .... more methods like this } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/CommandProcessor/RecommendAFriend.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.CommandProcessor { // command expressing intent public class RecommendAFriend { public int ReferrerId { get; set; } public NewAccount Friend { get; set; } } public interface IRecommendAFriendProcessor { void Process(RecommendAFriend command); } public class NewAccount { public string Email { get; set; } public string Nickname { get; set; } public int Age { get; set; } } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/CommandProcessorChained/RecommendAFriend.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.CommandProcessorChained { public interface ICommandProcessor { void Process(T command); } public class RecommendAFriend { public int ReferrerId { get; set; } } public class RecommendAFriendProcessor : ICommandProcessor { public void Process(RecommendAFriend command) { Console.WriteLine("Processing ReferAFriend command"); } } public class LoggingProcessor : ICommandProcessor { private ICommandProcessor nextLinkInChain; public LoggingProcessor(ICommandProcessor processor) { this.nextLinkInChain = processor; } public void Process(T command) { // log something before nextLinkInChain.Process(command); // log something after } } public class TransactionProcessor : ICommandProcessor { private ICommandProcessor nextLinkInChain; public TransactionProcessor(ICommandProcessor processor) { this.nextLinkInChain = processor; } public void Process(T command) { // start transaction try { nextLinkInChain.Process(command); // commit transaction } catch { // rollback transaction } } } public static class Bootstrap { public static ICommandProcessor ReferAFriendProcessor { get; set; } public static void ConfigureApplication() { // create inner processor var referAFriendProcessor = new RecommendAFriendProcessor(); // wrap inner processor with logging var loggingProcessor = new LoggingProcessor(referAFriendProcessor); // wrap logging processor (that wraps inner) with a transaction var transactionProcessor = new TransactionProcessor(loggingProcessor); ReferAFriendProcessor = transactionProcessor; // alternatively you can use dependency injection } } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/FrameworkHooks/ErrorFilter.cs ================================================ using System; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.FrameworkHooks { public class ErrorFilter : HandleErrorAttribute { public override void OnException(ExceptionContext filterContext) { if (filterContext.Exception.GetType() == typeof(ApplicationError)) { // return specific message to user var msg = filterContext.Exception.Message; ErrorResponse(msg, filterContext); } else { // return generic message for security reasons var msg = "Sorry. Something really unexpected has occurred"; ErrorResponse(msg, filterContext); } } public void ErrorResponse(string msg, ExceptionContext ec) { var routeData = new RouteValueDictionary(new { message = msg }); var response = new RedirectToRouteResult("ErrorPage", routeData); ec.Result = response; ec.ExceptionHandled = true; } } public class ApplicationError : Exception { } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/FrameworkHooks/TransactionFilter.cs ================================================ using System; using System.Transactions; using System.Web; using System.Web.Mvc; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.FrameworkHooks { public class TransactionFilter : ActionFilterAttribute, IActionFilter { // executes before controller public override void OnResultExecuting(ResultExecutingContext filterContext) { // start a transaction var t = new TransactionScope(); HttpContext.Current.Items["transaction"] = t; base.OnResultExecuting(filterContext); } // executes after controller public override void OnActionExecuted(ActionExecutedContext filterContext) { // close the transaction created at start of this request var t = (TransactionScope)HttpContext.Current.Items["transaction"]; t.Complete(); base.OnActionExecuted(filterContext); } } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/PublishSubscribe/RecommendAFriend.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using Domain; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.PublishSubscribe { public class RecommendAFriendService { private IReferralPolicy policy; public RecommendAFriendService(Domain.IReferralPolicy policy) { // subscribe to events on domain model policy.ReferralAccepted += HandleReferralAccepted; policy.ReferralRejected += HandleReferralRejected; this.policy = policy; } private void HandleReferralAccepted(object sender, Domain.Referral e) { // send confirmation emails etc } private void HandleReferralRejected(object sender, Domain.Referral e) { // send rejection emails etc } public void ReferAFriend(int referrerId, NewAccount friend) { // validation, open transaction etc var command = new RecommendAFriend { ReferrerId = referrerId, Friend = friend }; policy.Apply(command); // close transaction - success and failure handled in handlers } } } // named appropriately after your domain and living in another project namespace Domain { public interface IReferralPolicy { event EventHandler ReferralAccepted; event EventHandler ReferralRejected; void Apply(RecommendAFriend command); } public class Referral { public int ReferrerId { get; set; } public int FriendId { get; set; } } public class RecommendAFriend { public int ReferrerId { get; set; } public NewAccount Friend { get; set; } } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/PublishSubscribeAsync/ReferAFriend.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using Domain; using System.Threading.Tasks; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.PublishSubscribeAsync { public class RecommendAFriendService { private IReferralPolicy policy; public RecommendAFriendService(Domain.IReferralPolicy policy) { // subscribe to events on domain model policy.ReferralAccepted += HandleReferralAccepted; policy.ReferralRejected += HandleReferralRejected; this.policy = policy; } private void HandleReferralAccepted(object sender, Domain.Referral e) { // send confirmation emails etc } private void HandleReferralRejected(object sender, Domain.Referral e) { // send rejection emails etc } public void RecommendAFriend(int referrerId, NewAccount friend) { // validation, open transaction etc var command = new RecommendAFriend { ReferrerId = referrerId, Friend = friend }; Task.Factory.StartNew(() => policy.Apply(command)); // close transaction - success and failure handled in handlers } } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/ApplicationServices/RequestReply/RecommendAFriend.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using Domain; using NewAccount = Domain.NewAccount; using PPPDDD.ApplicationServices.Gambling.ApplicationServices.ErrorHandling; namespace PPPDDD.ApplicationServices.Gambling.ApplicationServices.RequestReply { public class RecommendAFriendService { private IReferralPolicy policy; public RecommendAFriendService(Domain.IReferralPolicy policy) { this.policy = policy; } public RecommendAFriendResponse RecommendAFriend(RecommendAFriendRequest request) { try { var command = new RecommendAFriend { ReferrerId = request.ReferrerId, Friend = request.Friend }; policy.Apply(command); return new RecommendAFriendResponse { Status = RecommendAFriendStatus.Success }; } catch (ReferralRejectedDueToLongTermOutstandingBalance) { return new RecommendAFriendResponse { Status = RecommendAFriendStatus.ReferralRejected }; } } } public class RecommendAFriendRequest { public int ReferrerId { get; set; } public NewAccount Friend { get; set; } } public class RecommendAFriendResponse { public RecommendAFriendStatus Status { get; set; } } public enum RecommendAFriendStatus { Success, ReferralRejected } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/Controllers/RecommendAFriendController.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using ControllerDomain; using System.Threading.Tasks; namespace PPPDDD.ApplicationServices.Gambling.Controllers { public class RecommendAFriendController : Controller { private ICustomerDirectory directory; private IReferAFriendPolicy policy; public RecommendAFriendController( ICustomerDirectory customerDirectory, IReferAFriendPolicy policy) { this.directory = customerDirectory; this.policy = policy; } // all infrastructure concerns handled by framework public ActionResult Index(int referrerId, NewAccount friend) { var referrer = directory.Find(referrerId); var newAcct = directory.Create(friend); policy.Apply(referrer, newAcct); return View(); } } } namespace ControllerDomain { public interface ICustomerDirectory { Customer Find(int customerId); Customer Create(NewAccount details); } public class NewAccount { public string Email { get; set; } public string Nickname { get; set; } public int Age { get; set; } } public class Customer { public int Id { get; set; } } public interface IReferAFriendPolicy { void Apply(Customer referrer, Customer friend); } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/Global.asax ================================================ <%@ Application Codebehind="Global.asax.cs" Inherits="PPPDDD.ApplicationServices.Gambling.MvcApplication" Language="C#" %> ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/Global.asax.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace PPPDDD.ApplicationServices.Gambling { public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); } } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/PPPDDD.ApplicationServices.RecommendAFriend.csproj ================================================  Debug AnyCPU 2.0 {DF2F8764-86BC-4833-98A0-5A7E34A6EB7E} {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} Library Properties PPPDDD.ApplicationServices.Gambling PPPDDD.ApplicationServices.Gambling v4.5 true ..\ true true full false bin\ DEBUG;TRACE prompt 4 pdbonly true bin\ TRACE prompt 4 ..\packages\log4net.2.0.3\lib\net40-full\log4net.dll ..\packages\NServiceBus.Interfaces.4.6.1\lib\net40\NServiceBus.dll ..\packages\NServiceBus.4.6.1\lib\net40\NServiceBus.Core.dll ..\packages\RavenDB.Client.2.5.2874\lib\net45\Raven.Abstractions.dll ..\packages\RavenDB.Client.2.5.2874\lib\net45\Raven.Client.Lightweight.dll ..\packages\StatsdClient.1.0.0.16\lib\net35\StatsdClient.dll ..\packages\StatsdClient.1.0.0.16\lib\net35\StatsdClient.Configuration.dll ..\packages\Microsoft.AspNet.Razor.3.0.0\lib\net45\System.Web.Razor.dll ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Webpages.dll ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Webpages.Deployment.dll ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Webpages.Razor.dll ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Helpers.dll ..\packages\Microsoft.AspNet.Mvc.5.0.0\lib\net45\System.Web.Mvc.dll Global.asax Web.config Web.config 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) True True 1154 / http://localhost:1154/ False False False This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/PPPDDD.ApplicationServices.RecommendAFriend.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Express 2013 for Web VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPPDDD.ApplicationServices.RecommendAFriend", "PPPDDD.ApplicationServices.RecommendAFriend.csproj", "{DF2F8764-86BC-4833-98A0-5A7E34A6EB7E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {DF2F8764-86BC-4833-98A0-5A7E34A6EB7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DF2F8764-86BC-4833-98A0-5A7E34A6EB7E}.Debug|Any CPU.Build.0 = Debug|Any CPU {DF2F8764-86BC-4833-98A0-5A7E34A6EB7E}.Release|Any CPU.ActiveCfg = Release|Any CPU {DF2F8764-86BC-4833-98A0-5A7E34A6EB7E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("PPPDDD.ApplicationServices.Gambling")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PPPDDD.ApplicationServices.Gambling")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("38a58e47-9ce5-499a-a7ad-15f23a5d0083")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/Views/web.config ================================================ 
    ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/Web.Debug.config ================================================ ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/Web.Release.config ================================================ ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/Web.config ================================================  ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Gambling/packages.config ================================================  ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.RecommendAFriend.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Express 2013 for Web VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "PPPDDD.ApplicationServices.Tests\Tests.csproj", "{E9ED1E1B-7722-4AF7-86B3-6FDE6A3B6A15}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPPDDD.ApplicationServices.RecommendAFriend", "PPPDDD.ApplicationServices.Gambling\PPPDDD.ApplicationServices.RecommendAFriend.csproj", "{DF2F8764-86BC-4833-98A0-5A7E34A6EB7E}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{4DE68C7C-1370-4861-97C9-79840B6B1A0F}" ProjectSection(SolutionItems) = preProject .nuget\NuGet.Config = .nuget\NuGet.Config .nuget\NuGet.exe = .nuget\NuGet.exe .nuget\NuGet.targets = .nuget\NuGet.targets EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E9ED1E1B-7722-4AF7-86B3-6FDE6A3B6A15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E9ED1E1B-7722-4AF7-86B3-6FDE6A3B6A15}.Debug|Any CPU.Build.0 = Debug|Any CPU {E9ED1E1B-7722-4AF7-86B3-6FDE6A3B6A15}.Release|Any CPU.ActiveCfg = Release|Any CPU {E9ED1E1B-7722-4AF7-86B3-6FDE6A3B6A15}.Release|Any CPU.Build.0 = Release|Any CPU {DF2F8764-86BC-4833-98A0-5A7E34A6EB7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DF2F8764-86BC-4833-98A0-5A7E34A6EB7E}.Debug|Any CPU.Build.0 = Debug|Any CPU {DF2F8764-86BC-4833-98A0-5A7E34A6EB7E}.Release|Any CPU.ActiveCfg = Release|Any CPU {DF2F8764-86BC-4833-98A0-5A7E34A6EB7E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Tests/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Tests")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Tests")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("80819b98-929a-4d49-99ef-ed0e759fca74")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Tests/Refer_a_friend.cs ================================================ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using TestApplication; using TestDomain; using Rhino.Mocks; namespace Tests { [TestClass] public class Recommend_a_friend // class named after domain concept / use-case { private ReferAFriendService service; private IEmailer emailer; private ICustomerDirectory directory; // test data private int referrerId = 454456; private NewAccount friendsDetails = new NewAccount { Age = 24, Email = "pppddd@wrox.com", Nickname = "Deedeedee" }; // this will run first (once only) then each test will run [ClassInitialize] public void When_a_user_signs_up_with_a_referral_from_a_friend() { // test as much of the implementation as possible directory = new CustomerDirectory(new InMemoryDatabase()); var policy = new ReferralPolicy(); // cannot test emailing implementation - easier to stub emailer = MockRepository.GenerateStub(); service = new ReferAFriendService(directory, policy, emailer); service.ReferAFriend(referrerId, friendsDetails); } [TestMethod] public void The_referrer_has_50_dollars_credited_to_their_account() { // ... } [TestMethod] public void The_friend_has_an_account_created_with_an_initial_50_dollars() { // ... } [TestMethod] public void The_referrers_loyalty_is_upgraded_to_gold_status() { var referrer = directory.Find(referrerId); Assert.AreEqual(LoyaltyStatus.Gold, referrer.LoyaltyStatus); } [TestMethod] public void The_refferer_gets_an_email_notifying_of_the_referral() { var referrer = directory.Find(referrerId); emailer.AssertWasCalled(em => { em.SendReferralAcknowledgement(referrer); }); } [TestMethod] public void The_friend_gets_an_email_notifying_of_account_creation() { // ... } } } // mimick an application namespace TestApplication { public class ReferAFriendService { private ICustomerDirectory directory; private IReferralPolicy policy; private IEmailer emailer; public ReferAFriendService(ICustomerDirectory directory, IReferralPolicy policy, IEmailer emailer) { this.directory = directory; this.policy = policy; this.emailer = emailer; } public void ReferAFriend(int referrerId, NewAccount friend) { // ***** Activity 1 - implement this if you want to make the tests pass } } public interface IEmailer { void SendReferralAcknowledgement(Customer customer); void SendPostReferralSignUpWelcome(Customer customer); } public class CustomerDirectory : ICustomerDirectory { public CustomerDirectory(InMemoryDatabase databaseContext) { // replace database context with a technology of your choice } public Customer Find(int customerId) { // ***** Activity 2 - implement this if you want to make the tests pass // You will need to choose an appropriate in-memory database return null; } } public class InMemoryDatabase { /* * Options for in-memory databases include: * - SQLite for use with SQL Server * - RavenDB embedded for RavenDB */ } } // mimick a domain namespace TestDomain { public interface ICustomerDirectory { Customer Find(int customerId); } public interface IReferralPolicy { void Apply(Customer referrer, Customer friend); } public class ReferralPolicy : IReferralPolicy { public void Apply(Customer referrer, Customer friend) { // ***** Activity 3 - implement this if you want to make the tests pass } } public class Customer { public int ID { get; set; } public string Email { get; set; } public string Nickname { get; set; } public int Age { get; set; } public LoyaltyStatus LoyaltyStatus { get; set; } } public class NewAccount { public string Email { get; set; } public string Nickname { get; set; } public int Age { get; set; } } public enum LoyaltyStatus { Bronze, Silver, Gold } } ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Tests/Tests.csproj ================================================  Debug AnyCPU {E9ED1E1B-7722-4AF7-86B3-6FDE6A3B6A15} Library Properties Tests Tests v4.5 512 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages False UnitTest ..\ true true full false bin\Debug\ DEBUG;TRACE prompt 4 pdbonly true bin\Release\ TRACE prompt 4 ..\packages\RhinoMocks.3.6.1\lib\net\Rhino.Mocks.dll False False False False This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. ================================================ FILE: 25 - Commands Application Service Patterns for processing Business Use Cases/PPPDDD.ApplicationServices.Tests/packages.config ================================================  ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/App_Start/RouteConfig.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace PPPDDD.Reporting { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } } ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/Controllers/DealershipPerformanceReportController.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using DealershipPerformanceReportDomain; namespace PPPDDD.Reporting.Controllers { public class DealershipPerformanceReportController : Controller { private DealershipPerformanceReportBuilder builder; public DealershipPerformanceReportController(IDealershipRepository repository, IDealershipRevenueCalculator calculator, IDealershipPerformanceTargetsProvider provider) { this.builder = new DealershipPerformanceReportBuilder( repository, calculator, provider ); } public ActionResult Index(IEnumerable dealershipIds, DateTime start, DateTime end) { var viewModel = builder.BuildReport(dealershipIds, start, end); return View(viewModel); } } // Application Service public class DealershipPerformanceReportBuilder { private IDealershipRepository repository; private IDealershipRevenueCalculator calculator; private IDealershipPerformanceTargetsProvider provider; public DealershipPerformanceReportBuilder(IDealershipRepository repository, IDealershipRevenueCalculator calculator, IDealershipPerformanceTargetsProvider provider) { this.repository = repository; this.calculator = calculator; this.provider = provider; } public DealershipPerformanceReport BuildReport(IEnumerable dealershipIds, DateTime start, DateTime end) { var statuses = BuildStatuses(dealershipIds, start, end); return new DealershipPerformanceReport { ReportStartDate = start, ReportEndDate = end, Dealerships = statuses }; } private List BuildStatuses(IEnumerable dealershipIds, DateTime start, DateTime end) { var statuses = new List(); foreach (var id in dealershipIds) { // select N+1 - potentially bad for performance and efficiency // re-using existing domain code - quick to implement var dealership = repository.Get(id); var targets = provider.Get(dealership, start, end); var actuals = calculator.CalculateFor(dealership, start, end); // map from domain to view model so UI is not coupled to domain objects // could move this logic into a separate mapper statuses.Add(new DealershipPerformanceStatus { DealershipName = dealership.Name, TotalRevenue = actuals.TotalRevenue, TargetRevenue = targets.TargetRevenue, NetProfit = actuals.NetProfit, TargetProfit = targets.TargetProfit }); } return statuses; } } // view model public class DealershipPerformanceReport { public DateTime ReportStartDate { get; set; } public DateTime ReportEndDate { get; set; } public List Dealerships { get; set; } } public class DealershipPerformanceStatus { public string DealershipName { get; set; } public int TotalRevenue { get; set; } public int TargetRevenue { get; set; } public int NetProfit { get; set; } public int TargetProfit { get; set; } } } // this would be a separate project namespace DealershipPerformanceReportDomain { public interface IDealershipRepository { Dealership Get(int dealershipId); } public interface IDealershipRevenueCalculator { DealershipPerformanceActuals CalculateFor(Dealership dealership, DateTime start, DateTime end); } public interface IDealershipPerformanceTargetsProvider { DealershipPerformanceTargets Get(Dealership dealership, DateTime start, DateTime end); } public class DealershipPerformanceTargets { public int TargetRevenue { get; set; } public int TargetProfit { get; set; } } public class DealershipPerformanceActuals { public int TotalRevenue { get; set; } public int NetProfit { get; set; } } public class Dealership { public int Id { get; set; } public string Name { get; set; } } } ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/Controllers/DealershipReportUsingMediatorController.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using DealershipPerformanceReportDomainForMediator; namespace PPPDDD.Reporting.Controllers { public class DealershipReportUsingMediatorController : Controller { private IDealershipRepository repository; public DealershipReportUsingMediatorController(IDealershipRepository repository) { this.repository = repository; } public ActionResult Index(IEnumerable dealershipIds, DateTime start, DateTime end) { var dealerships = repository.Get(dealershipIds); var builder = new DealershipPerformanceReportBuilderUsingMediator(); var viewModel = builder.BuildReport(dealerships, start, end); return View(viewModel); } } public class DealershipPerformanceReportBuilderUsingMediator { private IDealershipRevenueCalculator calculator; private IDealershipPerformanceTargetsProvider provider; public DealershipPerformanceReport BuildReport(IEnumerable dealerships, DateTime start, DateTime end) { var statuses = BuildStatuses(dealerships, start, end); return new DealershipPerformanceReport { Dealerships = statuses, ReportStartDate = start, ReportEndDate = end }; } private List BuildStatuses(IEnumerable dealerships, DateTime start, DateTime end) { var statuses = new List(); foreach (var dealership in dealerships) { var status = new DealershipPerformanceStatus(); var mediator = new DealershipAssessmentMediator(status); // Mediator wraps status var targets = provider.Get(dealership, start, end); var actuals = calculator.CalculateFor(dealership, start, end); // pass in the mediator, so private data can be set on the media targets.Populate(mediator); actuals.Populate(mediator); statuses.Add(status); // values will have been set by the mediator when passed into domain objects } return statuses; } } // "mediator" suffix on class name used for demo clarity public class DealershipAssessmentMediator : IDealershipAssessment { private DealershipPerformanceStatus status; public DealershipAssessmentMediator(DealershipPerformanceStatus status) { this.status = status; } public int TotalRevenue { get { return status.TotalRevenue; } set { status.TotalRevenue = value; } } public int TargetRevenue { get { return status.TargetRevenue; } set { status.TargetRevenue = value; } } public int NetProfit { get { return status.NetProfit; } set { status.NetProfit = value; } } public int TargetProfit { get { return status.TargetProfit; } set { status.TargetProfit = value; } } } } // this would be a separate pure domain project namespace DealershipPerformanceReportDomainForMediator { // mediator interface - stable domain structure that can be exposed public interface IDealershipAssessment { int TotalRevenue { get; set; } int TargetRevenue { get; set; } int NetProfit { get; set; } int TargetProfit { get; set; } } public interface IDealershipRepository { Dealership Get(int dealershipId); IEnumerable Get(IEnumerable dealershipIds); } public interface IDealershipRevenueCalculator { DealershipPerformanceActuals CalculateFor(Dealership dealership, DateTime start, DateTime end); } public interface IDealershipPerformanceTargetsProvider { DealershipPerformanceTargets Get(Dealership dealership, DateTime start, DateTime end); } public class DealershipPerformanceTargets { // private fields hide potentially volatile domain structure private int targetRevenue; private int targetProfit; public void Populate(IDealershipAssessment mediator) { mediator.TargetRevenue = targetRevenue; mediator.TargetProfit = targetProfit; } } public class DealershipPerformanceActuals { // private fields hide potentially volatile domain structure private int totalRevenue; private int netProfit; public void Populate(IDealershipAssessment mediator) { mediator.TotalRevenue = totalRevenue; mediator.NetProfit = netProfit; } } public class DealershipPerformance { // private fields hide potentially volatile domain structure private int totalRevenue; private int netProfit; public void Populate(IDealershipAssessment mediator) { mediator.TotalRevenue = totalRevenue; mediator.NetProfit = netProfit; } } public class Dealership { public int Id { get; set; } public string Name { get; set; } } } ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/Controllers/DenormalizedLoyaltyReportController.cs ================================================ using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Web; using System.Web.Mvc; using Dapper; namespace PPPDDD.Reporting.Controllers { public class DenormalizedLoyaltyReportController : Controller { // // GET: /DenormalizedLoyaltyReport/ public ActionResult Index() { return View(); } public class DenormalizedLoyaltyReportBuilder { private string connString = ""; public LoyaltyReport Build(DateTime start, DateTime end) { IEnumerable summaries; using(var con = new SqlConnection(connString)) { con.Open(); var query = "select [Month], PointsPerDollar, NetProfit, Signups, Purchases " + "from denormalizedLoyaltyReportViewCache " + "where [Month] >= @start " + "and [Month] < @end"; summaries = con.Query(query, new { start = start, end = end }); } return new LoyaltyReport { Summarries = summaries }; } } } } ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/Controllers/HealthcareEventProjectionReportController.cs ================================================ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Web; using System.Web.Helpers; using System.Web.Mvc; namespace PPPDDD.Reporting.Controllers { public class HealthcareEventProjectionReportController : Controller { // Run the application and browser to this url "/HealthcareProjectionReport/TestData" to insert test data for this demo public ActionResult TestData() { InsertTestData.Insert(); return Content("Test Data inserted. Navigate to: http://localhost:2113/web/streams.htm"); } // Example: http://localhost:{yourPort}/HealthcareEventProjectionReport?start=2014/01&end=2014/03&diagnosisIds=dg1 public ActionResult Index(DateTime start, DateTime end, string diagnosisIds) { var reportViewModel = new HealthcareReportBuilder().Build(start, end, diagnosisIds.Split(',')); // Optional: Create a view and display the report return Json(reportViewModel, JsonRequestBehavior.AllowGet); } } // Report building Application Service public class HealthcareReportBuilder { public HealthcareReport Build(DateTime start, DateTime end, IEnumerable diagnosisIds) { var monthsInReport = GetMonthsInRange(start, end).ToList(); // report columns var monthlyOverallTotals = FetchMonthlyTotalsFromES(monthsInReport); // used to calculate percentages var queries = BuildQueriesFor(monthsInReport, diagnosisIds).ToList(); // queries for ES var summaries = BuildMonthlySummariesFor(queries, monthlyOverallTotals).ToList(); // use queries return new HealthcareReport { Start = start, End = end, Summaries = summaries }; } private IEnumerable BuildMonthlySummariesFor(IEnumerable queries, Dictionary monthlyTotals) { foreach (var q in queries) // may want to run these in parallel for perf { var diagnosisTotal = FetchTotalFromESFor(q); var monthTotal = monthlyTotals[q.Month]; var percent = monthTotal == 0 ? 0 : ((decimal)diagnosisTotal / monthTotal) * 100; yield return new DiagnosisSummary { Amount = diagnosisTotal, DiagnosisName = GetDiagnosisName(q.DiagnosisId), Month = q.Month, Percentage = percent, MonthString = q.Month.ToString("yyyy/MM") }; } } private int FetchTotalFromESFor(DiagnosisQuery query) { // don't hard-code this URL. Access via entry point resource var projectionStateUrl = "http://localhost:2113/projection/DiagnosesByMonthCounts/state"; var streamname = "diagnosis-" + query.DiagnosisId + "_" + query.Month.ToString("yyyyMM"); // may want to use caching here var response = new WebClient().DownloadString(projectionStateUrl + "?partition=" + streamname); var count = Json.Decode(response); return count == null ? 0 : count.Count; } private Dictionary FetchMonthlyTotalsFromES(IEnumerable months) { // don't hard-code this URL. Access via entry point resource var projectionStateUrl = "http://localhost:2113/projection/MonthsCounts/state"; var totals = new Dictionary(); foreach(var m in months) { var streamName = "month-" + m.ToString("yyyyMM"); var url = projectionStateUrl + "?partition=" + streamName; var response = new WebClient().DownloadString(url); var count = Json.Decode(response); totals.Add(m, count == null ? 0 : count.Count); } return totals; } private IEnumerable BuildQueriesFor(IEnumerable months, IEnumerable diagnosisIds) { foreach (var month in months) { foreach (var id in diagnosisIds) { yield return new DiagnosisQuery { DiagnosisId = id, Month = month, }; } } } // this would problably live inside a helper, and not in an application service private IEnumerable GetMonthsInRange(DateTime start, DateTime end) { var startOfFirst = new DateTime(start.Year, start.Month, 1); var lastOfEnd = new DateTime(end.Year, end.Month + 1, 1); var current = startOfFirst; do { yield return current; current = current.AddMonths(1); } while (current < lastOfEnd); } private string GetDiagnosisName(string diagnosisId) { // many ways to implements this: // could come from an event stream // could live as a fixed list in cache if diagnosis never change // could be a lookup from a datastore switch(diagnosisId) { case "dg1": { return "Eczema"; break; }; case "dg2": { return "Vertigo"; break ;}; case "dg3": { return "Hypochrondriac"; break; }; default: { return "Unknown"; } } } } // represents state projection public class DiagnosisCount { public int Count { get; set; } } public class DiagnosisQuery { public DateTime Month { get; set; } public string DiagnosisId { get; set; } } // report view models public class HealthcareReport { public DateTime Start { get; set; } public DateTime End { get; set; } public IEnumerable Summaries { get; set; } } public class DiagnosisSummary { public string DiagnosisName { get; set; } public DateTime Month { get; set; } public string MonthString { get; set; } public int Amount { get; set; } public decimal Percentage { get; set; } } /* * Inserts test diagnosis events into Event Store. * Requires event store to be running on port 2113. */ public static class InsertTestData { private static string diagnosesStreamUrl = "http://localhost:2113/streams/diagnoses"; public static void Insert() { var request = (HttpWebRequest)WebRequest.Create(diagnosesStreamUrl); request.ContentType = "application/json"; request.Method = "POST"; var json = Json.Encode(DiagnosisEvents); using (var sr = new StreamWriter(request.GetRequestStream())) { sr.Write(json); sr.Flush(); sr.Close(); } request.GetResponse(); } // model of an event - used to push data into ES not used for the report private class Diagnosis { public Guid EventId { get; set; } public string EventType { get; set; } public DiagnosisData data { get; set; } } private class DiagnosisData { public string DiagnosisId { get; set; } public string DiagnosisName { get; set; } public string DoctorId { get; set; } public string DoctorName { get; set; } public string Date { get; set; } } private static IEnumerable DiagnosisEvents = new List { new Diagnosis { EventId = Guid.NewGuid(), EventType = "diagnosis", data = new DiagnosisData { DiagnosisId = "dg1", DiagnosisName = "Eczema", DoctorId = "doc1", DoctorName = "D.C. Green", Date = "2014/02" } }, new Diagnosis { EventId = Guid.NewGuid(), EventType = "diagnosis", data = new DiagnosisData { DiagnosisId = "dg2", DiagnosisName = "Vertigo", DoctorId = "doc1", DoctorName = "D.C. Green", Date = "2014/02" } }, new Diagnosis { EventId = Guid.NewGuid(), EventType = "diagnosis", data = new DiagnosisData { DiagnosisId = "dg1", DiagnosisName = "Eczema", DoctorId = "doc2", DoctorName = "J.P. Finch", Date = "2014/03" } }, new Diagnosis { EventId = Guid.NewGuid(), EventType = "diagnosis", data = new DiagnosisData { DiagnosisId = "dg1", DiagnosisName = "Eczema", DoctorId = "doc2", DoctorName = "J.P. Finch", Date = "2014/03" } }, new Diagnosis { EventId = Guid.NewGuid(), EventType = "diagnosis", data = new DiagnosisData { DiagnosisId = "dg3", DiagnosisName = "Hypochondriac", DoctorId = "doc3", DoctorName = "U.B Retters", Date = "2014/04" } }, }; } /* Event Store Projections: DiagnosesByMonth: fromStream('diagnoses') .whenAny(function(state, ev) { var date = ev.data.Date.replace('/', ''); var diagnosisId = ev.data.DiagnosisId; linkTo('diagnosis-' + diagnosisId + '_' + date, ev); }); DiagnosesByMonthCounts: fromCategory('diagnosis') .foreachStream() .when({ $init : function(s,e) {return {count : 0}}, "diagnosis" : function(s,e) { s.count += 1} //mutate in place works }); Months: fromStream('diagnoses') .whenAny(function(state, ev) { var date = ev.data.Date.replace('/', ''); linkTo('month-' + date, ev); }); MonthsCounts: fromCategory('month') .foreachStream() .when({ $init : function(s,e) {return {count : 0}}, "diagnosis" : function(s,e) { s.count += 1 } //mutate in place works }); */ } ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/Controllers/LoyaltyReportQueryingDatastoreController.cs ================================================ using Dapper; using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; using System.Web; using System.Web.Mvc; // right-click on the "SportsStoreDatabase" project and choose "publish" // this will create a local version of the database on this machine namespace PPPDDD.Reporting.Controllers { public class LoyaltyReportQueryingDatastoreController : Controller { public ActionResult Index(DateTime start, DateTime end) { var report = new LoyaltyReportBuilder().Build(start, end); return View(report); } } // Application Service public class LoyaltyReportBuilder { // see SportsStoreDatabase project in this solution private string connString = ""; public LoyaltyReport Build(DateTime start, DateTime end) { IEnumerable profits; IEnumerable signups; IEnumerable settings; using(var con = new SqlConnection(connString)) { con.Open(); var pointsQuery = "select [Month], [PointsPerDollar] from loyaltySettings " + "where [Month] >= @start " + "and [Month] < @end"; settings = con.Query(pointsQuery, new { start = start, end = end }); var signupsQuery = "select count(*) from loyaltyAccounts" + "where isActive = true " + "and [created] >= @start " + "and [created] < @end "; signups = con.Query(signupsQuery, new { start = start, end = end } ); var profitQuery = "select " + " concat(month(o.[date]), '/', year(o.[date])) as Month, " + " (select ((cast(count(*) as decimal) / (" + " select count(*) from orders" + " where [date] >= @start" + " and [date] < @end" + " )) * 100)) as Purchases," + " (select ((sum(netProfit) / (" + " select sum(netProfit) from orders" + " where [date] >= @start" + " and [date] < @end " + " )) * 100)) as NetProfit" + " from orders o" + " join Users u on o.userId = u.id" + " join LoyaltyAccounts la on u.id = la.userId" + " where la.isActive = 1" + " and o.[date] >= @start" + " and o.[date] < @end" + " group by concat(month(o.[date]), '/', year(o.[date]))"; profits = con.Query(profitQuery, new { start = start, end = end }); } return Map(profits, signups, settings, start, end); } private LoyaltyReport Map(IEnumerable profits, IEnumerable signups, IEnumerable loyaltySettings, DateTime start, DateTime end) { var summaries = new List(); // Create a summary for each month in the report's range foreach (var month in MonthsBetweenInclusive(start, end)) { var monthsProfits = profits.Single(s => s.Month == month); var monthsSettings = loyaltySettings.Single(s => s.Month == month); var monthsSignups = signups.Single(s => s.Month == month); var summary = new LoyaltySummary { Month = month, NetProfit = monthsProfits.Profit, PointsPerDollar = monthsSettings.PointsPerDollar, Purchases = monthsProfits.Purchases, SignUps = monthsSignups.Signups }; summaries.Add(summary); } return new LoyaltyReport { Summarries = summaries }; } private IEnumerable MonthsBetweenInclusive(DateTime start, DateTime end) { var firstMonth = new DateTime(start.Year, start.Month, 1); var lastMonth = new DateTime(end.Year, end.Month, 1); var months = new List(); var currentMonth = firstMonth; while(currentMonth < lastMonth) { months.Add(currentMonth); currentMonth = currentMonth.AddMonths(1); } return months; } } // view / presentation models public class LoyaltyReport { public IEnumerable Summarries { get; set; } } public class LoyaltySummary { public DateTime Month { get; set; } public int PointsPerDollar { get; set; } public double NetProfit { get; set; } public int SignUps { get; set; } public int Purchases { get; set; } } // database models public class LoyaltySettings { public DateTime Month { get; set; } public int PointsPerDollar { get; set; } } public class SignupCount { public DateTime Month { get; set; } public int Signups { get; set; } } public class PurchasesAndProfit { public DateTime Month { get; set; } public int Purchases { get; set; } public double Profit { get; set; } } } ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/Global.asax ================================================ <%@ Application Codebehind="Global.asax.cs" Inherits="PPPDDD.Reporting.MvcApplication" Language="C#" %> ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/Global.asax.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace PPPDDD.Reporting { public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); } } } ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/PPPDDD.Reporting.csproj ================================================  Debug AnyCPU 2.0 {182A344B-3104-4158-A25E-1A5742944BF8} {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} Library Properties PPPDDD.Reporting PPPDDD.Reporting v4.5 true true full false bin\ DEBUG;TRACE prompt 4 pdbonly true bin\ TRACE prompt 4 ..\packages\Dapper.1.22\lib\net45\Dapper.dll ..\packages\Microsoft.AspNet.Razor.3.0.0\lib\net45\System.Web.Razor.dll ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Webpages.dll ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Webpages.Deployment.dll ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Webpages.Razor.dll ..\packages\Microsoft.AspNet.Webpages.3.0.0\lib\net45\System.Web.Helpers.dll ..\packages\Microsoft.AspNet.Mvc.5.0.0\lib\net45\System.Web.Mvc.dll Global.asax Web.config Web.config 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) True True 49645 / http://localhost:49645/ False False False ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/Properties/AssemblyInfo.cs ================================================ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("PPPDDD.Reporting")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PPPDDD.Reporting")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("86d22301-9c68-4217-9447-2e9b1952e792")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/Views/web.config ================================================ 
    ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/Web.Debug.config ================================================ ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/Web.Release.config ================================================ ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/Web.config ================================================  ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting/packages.config ================================================  ================================================ FILE: 26 - Queries Domain Reporting/PPPDDD.Reporting.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Express 2013 for Web VisualStudioVersion = 12.0.21005.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PPPDDD.Reporting", "PPPDDD.Reporting\PPPDDD.Reporting.csproj", "{182A344B-3104-4158-A25E-1A5742944BF8}" EndProject Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "SportsStoreDatabase", "SportsStoreDatabase\SportsStoreDatabase.sqlproj", "{5188E6CC-59AF-4993-B666-A1FA448D36C6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {182A344B-3104-4158-A25E-1A5742944BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {182A344B-3104-4158-A25E-1A5742944BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU {182A344B-3104-4158-A25E-1A5742944BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU {182A344B-3104-4158-A25E-1A5742944BF8}.Release|Any CPU.Build.0 = Release|Any CPU {5188E6CC-59AF-4993-B666-A1FA448D36C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5188E6CC-59AF-4993-B666-A1FA448D36C6}.Debug|Any CPU.Build.0 = Debug|Any CPU {5188E6CC-59AF-4993-B666-A1FA448D36C6}.Debug|Any CPU.Deploy.0 = Debug|Any CPU {5188E6CC-59AF-4993-B666-A1FA448D36C6}.Release|Any CPU.ActiveCfg = Release|Any CPU {5188E6CC-59AF-4993-B666-A1FA448D36C6}.Release|Any CPU.Build.0 = Release|Any CPU {5188E6CC-59AF-4993-B666-A1FA448D36C6}.Release|Any CPU.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ================================================ FILE: 26 - Queries Domain Reporting/README.md ================================================ PPPDDD ====== Sample code for the book Principles, Practices and Patterns of Domain-Driven Design. From the book http://www.amazon.com/Professional-Domain-Driven-Design-Patterns/dp/1118714709/ ================================================ FILE: 26 - Queries Domain Reporting/SportsStoreDatabase/LoyaltyAccounts.sql ================================================ CREATE TABLE [dbo].[LoyaltyAccounts] ( [Id] INT NOT NULL PRIMARY KEY, [UserId] INT NOT NULL, [IsActive] BIT NOT NULL, [Create] DATE NOT NULL, FOREIGN KEY (UserId) REFERENCES Users(Id) ) ================================================ FILE: 26 - Queries Domain Reporting/SportsStoreDatabase/LoyaltySettings.sql ================================================ CREATE TABLE [dbo].[LoyaltySettings] ( [Id] INT NOT NULL PRIMARY KEY, [Month] DATE NOT NULL, [PointsPerDollar] INT NOT NULL ) ================================================ FILE: 26 - Queries Domain Reporting/SportsStoreDatabase/Orders.sql ================================================ CREATE TABLE [dbo].[Orders] ( [Id] INT NOT NULL PRIMARY KEY, [Date] Date NOT NULL, [UserId] INT NOT NULL, [NetProfit] DECIMAL NOT NULL, FOREIGN KEY (UserId) REFERENCES Users(Id) ) ================================================ FILE: 26 - Queries Domain Reporting/SportsStoreDatabase/TestData.sql ================================================ /* Post-Deployment Script Template -------------------------------------------------------------------------------------- This file contains SQL statements that will be appended to the build script. Use SQLCMD syntax to include a file in the post-deployment script. Example: :r .\myfile.sql Use SQLCMD syntax to reference a variable in the post-deployment script. Example: :setvar TableName MyTable SELECT * FROM [$(TableName)] -------------------------------------------------------------------------------------- */ insert into Users values (1), (2) insert into LoyaltyAccounts (Id, UserId, IsActive) values (1, 1, 1), (2, 2, 0) insert into Orders (Id, UserId, [Date], NetProfit) values (1, 1, '2014-02-05', 25.25), (2, 2, '2014-02-10', 44.55) ================================================ FILE: 26 - Queries Domain Reporting/SportsStoreDatabase/Users.sql ================================================ CREATE TABLE [dbo].[Users] ( [Id] INT NOT NULL PRIMARY KEY ) ================================================ FILE: 26 - Queries Domain Reporting/SportsStoreDatabase/sportsstoredatabase.sqlproj ================================================  Debug AnyCPU SportsStoreDatabase 2.0 4.1 {5188e6cc-59af-4993-b666-a1fa448d36c6} Microsoft.Data.Tools.Schema.Sql.Sql110DatabaseSchemaProvider Database SportsStoreDatabase SportsStoreDatabase 1033, CI BySchemaAndSchemaType True v4.5 CS Properties False True True bin\Release\ $(MSBuildProjectName).sql False pdbonly true false true prompt 4 bin\Debug\ $(MSBuildProjectName).sql false true full false true true prompt 4 10.0 True 10.0 ================================================ FILE: README.md ================================================ PPPDDD ====== Sample code for the book Principles, Practices and Patterns of Domain-Driven Design. From the book http://www.amazon.com/Professional-Domain-Driven-Design-Patterns/dp/1118714709/ ================================================ FILE: eBidder Case Study/README.md ================================================ PPPDDD ====== Sample code for the book Principles, Practices and Patterns of Domain-Driven Design. From the book http://www.amazon.com/Professional-Domain-Driven-Design-Patterns/dp/1118714709/