Add samples from Web Flow distribution

This commit is contained in:
Rossen Stoyanchev
2012-05-25 16:44:45 -04:00
parent 86ae3828eb
commit 65fe46e524
255 changed files with 11428 additions and 7 deletions

18
booking-faces/build.xml Executable file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="swf-booking-faces">
<property name="source.version" value="1.5"/>
<property name="ivy.cache.dir" value="${basedir}/../../ivy-cache"/>
<property name="integration.repo.dir" value="${basedir}/../../integration-repo"/>
<property name="ivy.settings.file" value="${basedir}/../../build-spring-webflow/ivysettings.xml"/>
<property file="${basedir}/../../build.properties"/>
<import file="${basedir}/../../spring-build/war/default.xml"/>
<target name="publish"/>
<target name="publish-maven-central"/>
<target name="install-maven-central"/>
</project>

245
booking-faces/pom.xml Normal file
View File

@@ -0,0 +1,245 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.webflow.samples</groupId>
<artifactId>booking-faces</artifactId>
<packaging>war</packaging>
<name>Hotel Booking : Spring MVC + Web Flow + JSF/PrimeFaces</name>
<version>1.0.0.BUILD-SNAPSHOT</version>
<properties>
<springframework-version>3.1.1.RELEASE</springframework-version>
<springsecurity-version>3.0.2.RELEASE</springsecurity-version>
<webflow-version>2.3.1.RELEASE</webflow-version>
<slf4j-version>1.5.10</slf4j-version>
<mojarra-version>2.1.7</mojarra-version>
<primefaces-version>3.1.1</primefaces-version>
</properties>
<repositories>
<repository>
<id>spring-repository</id>
<name>Spring project snapshots, milestones, and releases</name>
<url>http://repo.springsource.org/snapshot</url>
</repository>
<repository>
<id>primefaces-repository</id>
<name>Prime Technology Maven Repository</name>
<url>http://repository.primefaces.org</url>
<layout>default</layout>
</repository>
</repositories>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-faces</artifactId>
<version>${webflow-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${springsecurity-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${springsecurity-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Database, JPA -->
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.10</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.5.0-Final</version>
</dependency>
<!-- JSF: Mojarra, PrimeFaces -->
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>${mojarra-version}</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>${mojarra-version}</version>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>${primefaces-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- JSR 303 with Hibernate Validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.0.2.GA</version>
</dependency>
<!--
JAXB is needed when running on Java 5. In this environment these dependencies have to be added
(unless xml configuration is explicitly disabled via Configuration.ignoreXmlConfiguration)
On Java 6 jaxb is part of the runtime environment.
-->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>2.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${springframework-version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>swf-booking-faces</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.1.12</version>
<configuration>
<junitArtifactName>junit:junit</junitArtifactName>
<includes>
<include>**/*Tests.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0-SNAPSHOT</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.8</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
<wtpversion>2.0</wtpversion>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,5 @@
package org.springframework.webflow.samples.booking;
public enum Amenity {
OCEAN_VIEW, LATE_CHECKOUT, MINIBAR;
}

View File

@@ -0,0 +1,226 @@
package org.springframework.webflow.samples.booking;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.validation.constraints.Future;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.binding.validation.ValidationContext;
/**
* A Hotel Booking made by a User.
*/
@Entity
public class Booking implements Serializable {
private static final long serialVersionUID = 1171567558348174963L;
private Long id;
private User user;
private Hotel hotel;
private Date checkinDate;
private Date checkoutDate;
private String creditCard;
private String creditCardName;
private int creditCardExpiryMonth;
private int creditCardExpiryYear;
private boolean smoking;
private int beds;
private Amenity[] amenities;
public Booking() {
}
public Booking(Hotel hotel, User user) {
this.hotel = hotel;
this.user = user;
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, 1);
setCheckinDate(calendar.getTime());
calendar.add(Calendar.DAY_OF_MONTH, 1);
setCheckoutDate(calendar.getTime());
}
@Transient
public BigDecimal getTotal() {
return hotel.getPrice().multiply(new BigDecimal(getNights()));
}
@Transient
public int getNights() {
if (checkinDate == null || checkoutDate == null) {
return 0;
} else {
return (int) (checkoutDate.getTime() - checkinDate.getTime()) / 1000 / 60 / 60 / 24;
}
}
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Basic
@Temporal(TemporalType.DATE)
@Future
@NotNull
public Date getCheckinDate() {
return checkinDate;
}
public void setCheckinDate(Date datetime) {
this.checkinDate = datetime;
}
@ManyToOne
public Hotel getHotel() {
return hotel;
}
public void setHotel(Hotel hotel) {
this.hotel = hotel;
}
@ManyToOne
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Basic
@Temporal(TemporalType.DATE)
@Future
@NotNull
public Date getCheckoutDate() {
return checkoutDate;
}
public void setCheckoutDate(Date checkoutDate) {
this.checkoutDate = checkoutDate;
}
@Pattern(regexp = "[0-9]{16}", message = "{invalidCreditCardPattern}")
public String getCreditCard() {
return creditCard;
}
public void setCreditCard(String creditCard) {
this.creditCard = creditCard;
}
@Transient
public String getDescription() {
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
return hotel == null ? null : hotel.getName() + ", " + df.format(getCheckinDate()) + " to "
+ df.format(getCheckoutDate());
}
public boolean isSmoking() {
return smoking;
}
public void setSmoking(boolean smoking) {
this.smoking = smoking;
}
public int getBeds() {
return beds;
}
public void setBeds(int beds) {
this.beds = beds;
}
@NotEmpty
public String getCreditCardName() {
return creditCardName;
}
public void setCreditCardName(String creditCardName) {
this.creditCardName = creditCardName;
}
public int getCreditCardExpiryMonth() {
return creditCardExpiryMonth;
}
public void setCreditCardExpiryMonth(int creditCardExpiryMonth) {
this.creditCardExpiryMonth = creditCardExpiryMonth;
}
public int getCreditCardExpiryYear() {
return creditCardExpiryYear;
}
public void setCreditCardExpiryYear(int creditCardExpiryYear) {
this.creditCardExpiryYear = creditCardExpiryYear;
}
@Transient
public Amenity[] getAmenities() {
return amenities;
}
public void setAmenities(Amenity[] amenities) {
this.amenities = amenities;
}
public void validateEnterBookingDetails(ValidationContext context) {
MessageContext messages = context.getMessageContext();
if (checkinDate.before(today())) {
messages.addMessage(new MessageBuilder().error().source("checkinDate")
.code("booking.checkinDate.beforeToday").build());
} else if (checkoutDate.before(checkinDate)) {
messages.addMessage(new MessageBuilder().error().source("checkoutDate")
.code("booking.checkoutDate.beforeCheckinDate").build());
}
}
private Date today() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, -1);
return calendar.getTime();
}
@Override
public String toString() {
return "Booking(" + user + "," + hotel + ")";
}
}

View File

@@ -0,0 +1,62 @@
package org.springframework.webflow.samples.booking;
import java.util.List;
/**
* A service interface for retrieving hotels and bookings from a backing repository. Also supports the ability to cancel
* a booking.
*/
public interface BookingService {
/**
* Find bookings made by the given user
* @param username the user's name
* @return their bookings
*/
public List<Booking> findBookings(String username);
/**
* Find hotels available for booking by some criteria.
* @param criteria the search criteria
* @param firstResult the index of the first result to return
* @param sortBy the field to sort by
* @param ascending true if the sorting should be in ascending order, false for descending
* @return a list of hotels meeting the criteria
*/
public List<Hotel> findHotels(SearchCriteria criteria, int firstResult, String sortBy, boolean ascending);
/**
* Find hotels by their identifier.
* @param id the hotel id
* @return the hotel
*/
public Hotel findHotelById(Long id);
/**
* Create a new, transient hotel booking instance for the given user.
* @param hotelId the hotelId
* @param userName the user name
* @return the new transient booking instance
*/
public Booking createBooking(Long hotelId, String userName);
/**
* Persist the booking to the database
* @param booking the booking
*/
public void persistBooking(Booking booking);
/**
* Cancel an existing booking.
* @param id the booking id
*/
public void cancelBooking(Booking booking);
/**
* Return the total number of hotels for the given criteria.
* @param criteria the criteria to use
* @return the number of matching hotels
*/
int getNumberOfHotels(SearchCriteria criteria);
}

View File

@@ -0,0 +1,110 @@
package org.springframework.webflow.samples.booking;
import java.io.Serializable;
import java.math.BigDecimal;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* A hotel where users may book stays.
*/
@Entity
public class Hotel implements Serializable {
private static final long serialVersionUID = 4011346719502656269L;
private Long id;
private String name;
private String address;
private String city;
private String state;
private String zip;
private String country;
private BigDecimal price;
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Column(precision = 6, scale = 2)
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public Booking createBooking(User user) {
return new Booking(this, user);
}
@Override
public String toString() {
return "Hotel(" + name + "," + address + "," + city + "," + zip + ")";
}
}

View File

@@ -0,0 +1,54 @@
/**
*
*/
package org.springframework.webflow.samples.booking;
import java.util.List;
import java.util.Map;
import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;
public class HotelLazyDataModel extends LazyDataModel<Hotel> {
private static final long serialVersionUID = -8832831134966938627L;
SearchCriteria searchCriteria;
BookingService bookingService;
private Hotel selected;
public HotelLazyDataModel(SearchCriteria searchCriteria, BookingService bookingService) {
this.searchCriteria = searchCriteria;
this.bookingService = bookingService;
}
@Override
public List<Hotel> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) {
searchCriteria.setCurrentPage(first / pageSize + 1);
return bookingService.findHotels(searchCriteria, first, sortField, sortOrder.equals(SortOrder.ASCENDING));
}
@Override
public int getRowCount() {
return bookingService.getNumberOfHotels(searchCriteria);
}
public Hotel getSelected() {
return selected;
}
public void setSelected(Hotel selected) {
this.selected = selected;
}
public int getCurrentPage() {
return this.searchCriteria.getCurrentPage();
}
public int getPageSize() {
return this.searchCriteria.getPageSize();
}
}

View File

@@ -0,0 +1,109 @@
package org.springframework.webflow.samples.booking;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
/**
* A JPA-based implementation of the Booking Service. Delegates to a JPA entity manager to issue data access calls
* against the backing repository. The EntityManager reference is provided by the managing container (Spring)
* automatically.
*/
@Service("bookingService")
@Repository
public class JpaBookingService implements BookingService, Serializable {
private static final long serialVersionUID = 1L;
private EntityManager em;
@PersistenceContext
public void setEntityManager(EntityManager em) {
this.em = em;
}
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<Booking> findBookings(String username) {
if (username != null) {
return em.createQuery("select b from Booking b where b.user.username = :username order by b.checkinDate")
.setParameter("username", username).getResultList();
} else {
return null;
}
}
@Transactional(readOnly = true)
@SuppressWarnings("unchecked")
public List<Hotel> findHotels(SearchCriteria criteria, int firstResult, String orderBy, boolean ascending) {
String pattern = getSearchPattern(criteria);
orderBy = (orderBy != null) ? orderBy : "name";
String orderDirection = (ascending) ? " ASC" : " DESC";
return em
.createQuery(
"select h from Hotel h where lower(h.name) like :pattern or lower(h.city) like :pattern "
+ "or lower(h.zip) like :pattern or lower(h.address) like :pattern order by h."
+ orderBy + orderDirection).setParameter("pattern", pattern)
.setMaxResults(criteria.getPageSize()).setFirstResult(firstResult).getResultList();
}
@Transactional(readOnly = true)
public int getNumberOfHotels(SearchCriteria criteria) {
String pattern = getSearchPattern(criteria);
Long count = (Long) em
.createQuery(
"select count(h.id) from Hotel h where lower(h.name) like :pattern or lower(h.city) like :pattern "
+ "or lower(h.zip) like :pattern or lower(h.address) like :pattern")
.setParameter("pattern", pattern).getSingleResult();
return count.intValue();
}
@Transactional(readOnly = true)
public Hotel findHotelById(Long id) {
return em.find(Hotel.class, id);
}
@Transactional(readOnly = true)
public Booking createBooking(Long hotelId, String username) {
Hotel hotel = em.find(Hotel.class, hotelId);
User user = findUser(username);
Booking booking = new Booking(hotel, user);
return booking;
}
@Transactional
public void persistBooking(Booking booking) {
em.persist(booking);
}
@Transactional
public void cancelBooking(Booking booking) {
booking = em.find(Booking.class, booking.getId());
if (booking != null) {
em.remove(booking);
}
}
// helpers
private String getSearchPattern(SearchCriteria criteria) {
if (StringUtils.hasText(criteria.getSearchString())) {
return "%" + criteria.getSearchString().toLowerCase().replace('*', '%') + "%";
} else {
return "%";
}
}
private User findUser(String username) {
return (User) em.createQuery("select u from User u where u.username = :username")
.setParameter("username", username).getSingleResult();
}
}

View File

@@ -0,0 +1,83 @@
package org.springframework.webflow.samples.booking;
import java.util.ArrayList;
import java.util.List;
import javax.faces.model.SelectItem;
import org.springframework.stereotype.Service;
@Service
public class ReferenceData {
private List<SelectItem> bedOptions;
private List<SelectItem> smokingOptions;
private List<SelectItem> creditCardExpMonths;
private List<SelectItem> creditCardExpYears;
private List<SelectItem> pageSizeOptions;
public List<SelectItem> getBedOptions() {
if (bedOptions == null) {
bedOptions = new ArrayList<SelectItem>();
bedOptions.add(new SelectItem(new Integer(1), "One king-size bed"));
bedOptions.add(new SelectItem(new Integer(2), "Two double beds"));
bedOptions.add(new SelectItem(new Integer(3), "Three beds"));
}
return bedOptions;
}
public List<SelectItem> getSmokingOptions() {
if (smokingOptions == null) {
smokingOptions = new ArrayList<SelectItem>();
smokingOptions.add(new SelectItem(Boolean.TRUE, "Smoking"));
smokingOptions.add(new SelectItem(Boolean.FALSE, "Non-Smoking"));
}
return smokingOptions;
}
public List<SelectItem> getCreditCardExpMonths() {
if (creditCardExpMonths == null) {
creditCardExpMonths = new ArrayList<SelectItem>();
creditCardExpMonths.add(new SelectItem(new Integer(1), "Jan"));
creditCardExpMonths.add(new SelectItem(new Integer(2), "Feb"));
creditCardExpMonths.add(new SelectItem(new Integer(3), "Mar"));
creditCardExpMonths.add(new SelectItem(new Integer(4), "Apr"));
creditCardExpMonths.add(new SelectItem(new Integer(5), "May"));
creditCardExpMonths.add(new SelectItem(new Integer(6), "Jun"));
creditCardExpMonths.add(new SelectItem(new Integer(7), "Jul"));
creditCardExpMonths.add(new SelectItem(new Integer(8), "Aug"));
creditCardExpMonths.add(new SelectItem(new Integer(9), "Sep"));
creditCardExpMonths.add(new SelectItem(new Integer(10), "Oct"));
creditCardExpMonths.add(new SelectItem(new Integer(11), "Nov"));
creditCardExpMonths.add(new SelectItem(new Integer(12), "Dec"));
}
return creditCardExpMonths;
}
public List<SelectItem> getCreditCardExpYears() {
if (creditCardExpYears == null) {
creditCardExpYears = new ArrayList<SelectItem>();
creditCardExpYears.add(new SelectItem(new Integer(2008), "2008"));
creditCardExpYears.add(new SelectItem(new Integer(2009), "2009"));
creditCardExpYears.add(new SelectItem(new Integer(2010), "2010"));
creditCardExpYears.add(new SelectItem(new Integer(2010), "2011"));
creditCardExpYears.add(new SelectItem(new Integer(2010), "2012"));
}
return creditCardExpYears;
}
public List<SelectItem> getPageSizeOptions() {
if (pageSizeOptions == null) {
pageSizeOptions = new ArrayList<SelectItem>();
pageSizeOptions.add(new SelectItem(new Integer(5), "5"));
pageSizeOptions.add(new SelectItem(new Integer(10), "10"));
pageSizeOptions.add(new SelectItem(new Integer(20), "20"));
}
return pageSizeOptions;
}
}

View File

@@ -0,0 +1,65 @@
package org.springframework.webflow.samples.booking;
import java.io.Serializable;
import javax.faces.model.DataModel;
/**
* A backing bean for the main hotel search form. Encapsulates the criteria needed to perform a hotel search.
*/
public class SearchCriteria implements Serializable {
private static final long serialVersionUID = 1L;
/**
* The user-provided search criteria for finding Hotels.
*/
private String searchString = "";
/**
* The maximum page size of the Hotel result list
*/
private int pageSize = 5;
/**
* The page the user is currently on.
*/
private int currentPage = 1;
/**
* Returns a {@link DataModel} based on the search criteria.
* @param bookingService the service to use to retrieve hotels.
*/
public DataModel<Hotel> getDataModel(BookingService bookingService) {
return new HotelLazyDataModel(this, bookingService);
}
public String getSearchString() {
return searchString;
}
public void setSearchString(String searchString) {
this.searchString = searchString;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public String toString() {
return "[Search Criteria searchString = '" + searchString + "'";
}
}

View File

@@ -0,0 +1,62 @@
package org.springframework.webflow.samples.booking;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* A user who can book hotels.
*/
@Entity
@Table(name = "Customer")
public class User implements Serializable {
private static final long serialVersionUID = -3652559447682574722L;
private String username;
private String password;
private String name;
public User() {
}
public User(String username, String password, String name) {
this.username = username;
this.password = password;
this.name = name;
}
@Id
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User(" + username + ")";
}
}

View File

@@ -0,0 +1,6 @@
#
# Overrides default pattern in JSF for Bean Validation messages from "{0}" to "{1} {0}" where
# the {0} is the Bean Validation constraint message (e.g. "may not be empty") and {1} is the
# field name or the field label if defined (e.g. "First name").
#
javax.faces.validator.BeanValidator.MESSAGE={1} {0}

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="bookingDatabase">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.springframework.webflow.samples.booking.User</class>
<class>org.springframework.webflow.samples.booking.Booking</class>
<class>org.springframework.webflow.samples.booking.Hotel</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/>
</properties>
</persistence-unit>
</persistence>

View File

@@ -0,0 +1,2 @@
# Custom messages for JSR-303 validation
invalidCreditCardPattern=is not a valid 16 digit card number.

View File

@@ -0,0 +1,27 @@
insert into Customer (username, name) values ('keith', 'Keith')
insert into Customer (username, name) values ('erwin', 'Erwin')
insert into Customer (username, name) values ('jeremy', 'Jeremy')
insert into Customer (username, name) values ('scott', 'Scott')
insert into Hotel (id, price, name, address, city, state, zip, country) values (1, 199, 'Westin Diplomat', '3555 S. Ocean Drive', 'Hollywood', 'FL', '33019', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (2, 60, 'Jameson Inn', '890 Palm Bay Rd NE', 'Palm Bay', 'FL', '32905', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (3, 199, 'Chilworth Manor', 'The Cottage, Southampton Business Park', 'Southampton', 'Hants', 'SO16 7JF', 'UK')
insert into Hotel (id, price, name, address, city, state, zip, country) values (4, 120, 'Marriott Courtyard', 'Tower Place, Buckhead', 'Atlanta', 'GA', '30305', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (5, 180, 'Doubletree', 'Tower Place, Buckhead', 'Atlanta', 'GA', '30305', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (6, 450, 'W Hotel', 'Union Square, Manhattan', 'NY', 'NY', '10011', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (7, 450, 'W Hotel', 'Lexington Ave, Manhattan', 'NY', 'NY', '10011', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (8, 250, 'Hotel Rouge', '1315 16th Street NW', 'Washington', 'DC', '20036', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (9, 300, '70 Park Avenue Hotel', '70 Park Avenue', 'NY', 'NY', '10011', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (10, 300, 'Conrad Miami', '1395 Brickell Ave', 'Miami', 'FL', '33131', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (11, 80, 'Sea Horse Inn', '2106 N Clairemont Ave', 'Eau Claire', 'WI', '54703', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (12, 90, 'Super 8 Eau Claire Campus Area', '1151 W Macarthur Ave', 'Eau Claire', 'WI', '54701', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (13, 160, 'Marriot Downtown', '55 Fourth Street', 'San Francisco', 'CA', '94103', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (14, 200, 'Hilton Diagonal Mar', 'Passeig del Taulat 262-264', 'Barcelona', 'Catalunya', '08019', 'Spain')
insert into Hotel (id, price, name, address, city, state, zip, country) values (15, 210, 'Hilton Tel Aviv', 'Independence Park', 'Tel Aviv', '', '63405', 'Israel')
insert into Hotel (id, price, name, address, city, state, zip, country) values (16, 240, 'InterContinental Tokyo Bay', 'Takeshiba Pier', 'Tokyo', '', '105', 'Japan')
insert into Hotel (id, price, name, address, city, state, zip, country) values (17, 130, 'Hotel Beaulac', ' Esplanade L<>opold-Robert 2', 'Neuchatel', '', '2000', 'Switzerland')
insert into Hotel (id, price, name, address, city, state, zip, country) values (18, 140, 'Conrad Treasury Place', 'William & George Streets', 'Brisbane', 'QLD', '4001', 'Australia')
insert into Hotel (id, price, name, address, city, state, zip, country) values (19, 230, 'Ritz Carlton', '1228 Sherbrooke St', 'West Montreal', 'Quebec', 'H3G1H6', 'Canada')
insert into Hotel (id, price, name, address, city, state, zip, country) values (20, 460, 'Ritz Carlton', 'Peachtree Rd, Buckhead', 'Atlanta', 'GA', '30326', 'USA')
insert into Hotel (id, price, name, address, city, state, zip, country) values (21, 220, 'Swissotel', '68 Market Street', 'Sydney', 'NSW', '2000', 'Australia')
insert into Hotel (id, price, name, address, city, state, zip, country) values (22, 250, 'Meli<EFBFBD> White House', 'Albany Street', 'Regents Park London', '', 'NW13UP', 'Great Britain')
insert into Hotel (id, price, name, address, city, state, zip, country) values (23, 210, 'Hotel Allegro', '171 West Randolph Street', 'Chicago', 'IL', '60601', 'USA')

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
</layout>
</appender>
<logger name="org.springframework.beans">
<level value="warn" />
</logger>
<logger name="org.springframework.binding">
<level value="debug" />
</logger>
<logger name="org.springframework.jdbc">
<level value="warn" />
</logger>
<logger name="org.springframework.transaction">
<level value="warn" />
</logger>
<logger name="org.springframework.orm">
<level value="warn" />
</logger>
<logger name="org.springframework.web">
<level value="debug" />
</logger>
<logger name="org.springframework.faces">
<level value="debug" />
</logger>
<logger name="org.springframework.webflow">
<level value="debug" />
</logger>
<!-- Root Logger -->
<root>
<priority value="warn" />
<appender-ref ref="console" />
</root>
</log4j:configuration>

View File

@@ -0,0 +1,2 @@
Manifest-Version: 1.0

View File

@@ -0,0 +1,11 @@
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
# Enable web flow logging
log4j.category.org.springframework.webflow=DEBUG
log4j.category.org.springframework.faces=DEBUG
log4j.category.org.springframework.binding=DEBUG
log4j.category.org.springframework.transaction=DEBUG

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- Instructs Spring to perfrom declarative transaction management on annotated classes -->
<tx:annotation-driven />
<!-- Drives transactions using local JPA APIs -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- Creates a EntityManagerFactory for use with the Hibernate JPA provider and a simple in-memory data source populated with test data -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<!-- Deploys a in-memory "booking" datasource populated -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:booking" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
</beans>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<!-- Configure Spring Security -->
<security:http auto-config="true" use-expressions="true">
<security:form-login login-page="/spring/login" login-processing-url="/spring/loginProcess"
default-target-url="/spring/main" authentication-failure-url="/spring/login?login_error=1" />
<security:logout logout-url="/spring/logout" logout-success-url="/spring/logoutSuccess" />
<security:intercept-url pattern="/secure" method="POST" access="hasRole('ROLE_SUPERVISOR')"/>
</security:http>
<!--
Define local authentication provider, a real app would use an external provider (JDBC, LDAP, CAS, etc)
usernames/passwords are:
keith/melbourne
erwin/leuven
jeremy/atlanta
scott/rochester
-->
<security:authentication-manager>
<security:authentication-provider>
<security:password-encoder hash="md5" />
<security:user-service>
<security:user name="keith" password="417c7382b16c395bc25b5da1398cf076" authorities="ROLE_USER, ROLE_SUPERVISOR" />
<security:user name="erwin" password="12430911a8af075c6f41c6976af22b09" authorities="ROLE_USER, ROLE_SUPERVISOR" />
<security:user name="jeremy" password="57c6cbff0d421449be820763f03139eb" authorities="ROLE_USER" />
<security:user name="scott" password="942f2339bf50796de535a384f0d1af3e" authorities="ROLE_USER" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Scans for application @Components to deploy -->
<context:component-scan base-package="org.springframework.webflow.samples.booking" />
<!-- Imports the configurations of the different infrastructure systems of the application -->
<import resource="webmvc-config.xml" />
<import resource="webflow-config.xml" />
<import resource="data-access-config.xml" />
<import resource="security-config.xml" />
</beans>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xmlns:faces="http://www.springframework.org/schema/faces"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd
http://www.springframework.org/schema/faces http://www.springframework.org/schema/faces/spring-faces-2.2.xsd">
<!-- Executes flows: the central entry point into the Spring Web Flow system -->
<webflow:flow-executor id="flowExecutor">
<webflow:flow-execution-listeners>
<webflow:listener ref="facesContextListener"/>
<webflow:listener ref="securityFlowExecutionListener" />
</webflow:flow-execution-listeners>
</webflow:flow-executor>
<!-- The registry of executable flow definitions -->
<webflow:flow-registry id="flowRegistry" flow-builder-services="facesFlowBuilderServices" base-path="/WEB-INF/flows">
<webflow:flow-location-pattern value="/**/*-flow.xml" />
</webflow:flow-registry>
<!-- Configures the Spring Web Flow JSF integration -->
<faces:flow-builder-services id="facesFlowBuilderServices" development="true" />
<!-- Installs a listener that creates and releases the FacesContext for each request. -->
<bean id="facesContextListener" class="org.springframework.faces.webflow.FlowFacesContextLifecycleListener"/>
<!-- Installs a listener to apply Spring Security authorities -->
<bean id="securityFlowExecutionListener" class="org.springframework.webflow.security.SecurityFlowExecutionListener" />
</beans>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:faces="http://www.springframework.org/schema/faces"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/faces http://www.springframework.org/schema/faces/spring-faces-2.2.xsd">
<faces:resources />
<!-- Maps request paths to flows in the flowRegistry; e.g. a path of /hotels/booking looks for a flow with id "hotels/booking" -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="order" value="1"/>
<property name="flowRegistry" ref="flowRegistry" />
<property name="defaultHandler">
<!-- If no flow match, map path to a view to render; e.g. the "/intro" path would map to the view named "intro" -->
<bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
</property>
</bean>
<!-- Maps logical view names to Facelet templates in /WEB-INF (e.g. 'search' to '/WEB-INF/search.xhtml' -->
<bean id="faceletsViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".xhtml" />
</bean>
<!-- Dispatches requests mapped to org.springframework.web.servlet.mvc.Controller implementations -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!-- Dispatches requests mapped to flows to FlowHandler implementations -->
<bean class="org.springframework.faces.webflow.JsfFlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor" />
</bean>
</beans>

View File

@@ -0,0 +1,11 @@
<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<application>
<message-bundle>JsfMessageResources</message-bundle>
</application>
</faces-config>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<secured attributes="ROLE_USER" />
<input name="hotelId" required="true" />
<on-start>
<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" result="flowScope.booking" />
</on-start>
<view-state id="enterBookingDetails" model="booking">
<transition on="proceed" to="reviewBooking" />
<transition on="cancel" to="bookingCancelled" bind="false" />
</view-state>
<view-state id="reviewBooking">
<transition on="confirm" to="bookingConfirmed">
<evaluate expression="bookingService.persistBooking(booking)" />
</transition>
<transition on="revise" to="enterBookingDetails" />
<transition on="cancel" to="bookingCancelled" />
</view-state>
<end-state id="bookingConfirmed" />
<end-state id="bookingCancelled" />
</flow>

View File

@@ -0,0 +1,141 @@
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
template="/WEB-INF/layouts/standard.xhtml">
<ui:define name="notes">
<p>
Check the calendar widget and the tooltips on the credit card fields.
The form uses Ajax-based validations to redisplay server-side errors without refreshing the entire page.
The booking bean backing the form is a flow-scoped object (see <strong>booking-flow.xml</strong>).
</p>
</ui:define>
<ui:define name="content">
<h:form id="bookingForm">
<p:fieldset legend="Hotel Reservation Form">
<p:messages />
<div class="large">
${booking.hotel.name},
${booking.hotel.address}
${booking.hotel.city}, ${booking.hotel.state}, ${booking.hotel.zip}
${booking.hotel.country}
</div>
<hr/>
<div>
<div class="span-4 label">
<h:outputLabel for="price">Nightly Rate:</h:outputLabel>
</div>
<div class="span-14 last">
<p>
<h:outputText id="price" value="#{booking.hotel.price}">
<f:convertNumber type="currency" currencySymbol="$"/>
</h:outputText>
</p>
</div>
</div>
<div class="field">
<div class="span-4">
<h:outputLabel for="checkinDate">Check In:</h:outputLabel>
</div>
<div class="span-5">
<p>
<p:calendar id="checkinDate" label="Check in date"
value="#{booking.checkinDate}" pattern="MM-dd-yyyy" timeZone="EST" required="true" />
</p>
</div>
<div class="span-4">
<h:outputLabel for="checkoutDate">Check Out:</h:outputLabel>
</div>
<div class="span-5 last">
<p>
<p:calendar id="checkoutDate" label="Check out date"
value="#{booking.checkoutDate}" pattern="MM-dd-yyyy" timeZone="EST" required="true" />
</p>
</div>
</div>
<div class="field">
<div class="span-4">
<h:outputLabel for="beds">Room Preference:</h:outputLabel>
</div>
<div class="span-5">
<p>
<h:selectOneMenu id="beds" value="#{booking.beds}">
<f:selectItems value="#{referenceData.bedOptions}"/>
</h:selectOneMenu>
</p>
</div>
<div class="span-4">
<h:outputLabel for="smoking">Smoking:</h:outputLabel>
</div>
<div id="radio" class="span-5 last">
<h:selectOneRadio id="smoking" value="#{booking.smoking}" layout="pageDirection">
<f:selectItems value="#{referenceData.smokingOptions}"/>
</h:selectOneRadio>
</div>
</div>
<!--
The "amenities" section commented out due to the following issue:
https://issues.apache.org/jira/browse/MYFACES-2739
https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=817
https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=1694
<div class="field">
<div class="span-4">
<h:outputLabel for="amenities">Amenities:</h:outputLabel>
</div>
<div class="span-11 last">
<h:selectManyCheckbox id="amenities" value="#{booking.amenities}" layout="pageDirection">
<f:selectItem itemValue="OCEAN_VIEW" itemLabel="Ocean View" />
<f:selectItem itemValue="LATE_CHECKOUT" itemLabel="Late Checkout" />
<f:selectItem itemValue="MINIBAR" itemLabel="Minibar" />
</h:selectManyCheckbox>
</div>
</div>
-->
<div class="field">
<div class="span-4">
<h:outputLabel for="creditCard">Credit Card Number:</h:outputLabel>
</div>
<div class="span-5">
<p>
<h:inputText id="creditCard" label="Credit card number" value="#{booking.creditCard}" />
<p:tooltip for="creditCard" value="16-digit credit card number." style="cream" position="bottomLeft" />
</p>
</div>
<div class="span-4">
<h:outputLabel for="creditCardName">Credit Card Name:</h:outputLabel>
</div>
<div class="span-5 last">
<p>
<h:inputText id="creditCardName" label="Credit card name" value="#{booking.creditCardName}"/>
<p:tooltip for="creditCardName" value="The name as it appears on the credit card" style="cream" />
</p>
</div>
</div>
<div class="field">
<div class="span-4">
<h:outputLabel for="creditCardExpiryMonth">Expiration Date:</h:outputLabel>
</div>
<div class="span-14 last">
<p>
<h:selectOneMenu id="creditCardExpiryMonth" value="#{booking.creditCardExpiryMonth}">
<f:selectItems value="#{referenceData.creditCardExpMonths}" />
</h:selectOneMenu>&nbsp;
<h:selectOneMenu id="creditCardExpiryYear" value="#{booking.creditCardExpiryYear}">
<f:selectItems value="#{referenceData.creditCardExpYears}"/>
</h:selectOneMenu>
</p>
</div>
</div>
<div>
<p:commandButton id="proceed" action="proceed" value="Proceed" update="@form" />
<p:commandButton id="cancel" value="Cancel" action="cancel" immediate="true" />
</div>
</p:fieldset>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,2 @@
booking.checkinDate.beforeToday=The Check In Date must be a future date
booking.checkoutDate.beforeCheckinDate=The Check Out Date must be later than the Check In Date

View File

@@ -0,0 +1,83 @@
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
template="/WEB-INF/layouts/standard.xhtml">
<ui:define name="notes">
<p>
Note that the command button actions raise events (e.g. "revise") instead of specifying method expressions.
The events result in transitions on the server side (see reviewBooking state in <strong>booking-flow.xml</strong>).
</p>
</ui:define>
<ui:define name="content">
<div class="span-5">
<h3>${booking.hotel.name}</h3>
<address>
${booking.hotel.address}
<br/>
${booking.hotel.city}, ${booking.hotel.state}, ${booking.hotel.zip}
<br/>
${booking.hotel.country}
</address>
</div>
<div class="span-12 last">
<h:form>
<p:fieldset legend="Confirm Booking Details">
<div>
<div class="span-3">Check In:</div>
<div class="span-8 last">
<p>
<h:outputText value="#{booking.checkinDate}">
<f:convertDateTime dateStyle="short"/>
</h:outputText>
</p>
</div>
</div>
<div>
<div class="span-3">Check Out:</div>
<div class="span-8 last">
<p>
<h:outputText value="#{booking.checkoutDate}">
<f:convertDateTime dateStyle="short"/>
</h:outputText>
</p>
</div>
</div>
<div>
<div class="span-3">Nights:</div>
<div class="span-8 last">
<p>
<h:outputText value="#{booking.nights}"/>
</p>
</div>
</div>
<div>
<div class="span-3">Total payment:</div>
<div class="span-8 last">
<p>
<h:outputText value="#{booking.total}">
<f:convertNumber type="currency" currencySymbol="$"/>
</h:outputText>
</p>
</div>
</div>
<div>
<div class="span-3">Credit Card:</div>
<div class="span-8 last">
<p>
#{booking.creditCard}
</p>
</div>
</div>
<div>
<p:commandButton id="confirm" value="Confirm" action="confirm"/>&#160;
<p:commandButton id="revise" value="Revise" action="revise"/>&#160;
<p:commandButton id="cancel" value="Cancel" action="cancel" />
</div>
</p:fieldset>
</h:form>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,74 @@
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
template="/WEB-INF/layouts/standard.xhtml">
<ui:define name="notes">
<p>
This page uses the PrimeFaces panel component to display a search form.
Mouse over the "Search String" field to see its tooltip.
If you are logged a second panel will show your current bookings.
Both panels can be toggled on and off.
</p>
</ui:define>
<ui:define name="content">
<p:panel header="Search Hotels" toggleable="true" toggleSpeed="100">
<h:form>
<p:messages globalOnly="true" />
<h:panelGrid columns="2">
<h:outputLabel for="searchString">Search String: </h:outputLabel>
<h:inputText id="searchString" value="#{searchCriteria.searchString}" />
<h:outputLabel for="pageSize">Maximum Results: </h:outputLabel>
<h:selectOneMenu id="pageSize" value="#{searchCriteria.pageSize}">
<f:selectItems value="#{referenceData.pageSizeOptions}" />
</h:selectOneMenu>
<p:commandButton id="findHotels" value="Find Hotels" action="search" update="@form" />
</h:panelGrid>
<p:tooltip for="searchString" targetPosition="topRight" position="bottomLeft"
value="Search hotels by name, address, city, or zip." style="cream" />
</h:form>
</p:panel>
<p:panel id="bookings" header="Your Hotel Bookings" rendered="#{currentUser!=null}" toggleable="true" toggleSpeed="100" style="margin-top: 10px">
<h:outputText value="No Bookings Found" rendered="#{bookings.rowCount==0}"/>
<h:form rendered="#{bookings.rowCount > 0}">
<p:outputPanel id="bookingsContent">
<p:dataTable value="#{bookings}" var="booking">
<p:column>
<f:facet name="header">Hotel</f:facet>
#{booking.hotel.name}<br/>
#{booking.hotel.address}<br/>
#{booking.hotel.city}, #{booking.hotel.state}
</p:column>
<p:column>
<f:facet name="header">Check in</f:facet>
<h:outputText value="#{booking.checkinDate}">
<f:convertDateTime dateStyle="short"/>
</h:outputText>
</p:column>
<p:column>
<f:facet name="header">Check out</f:facet>
<h:outputText value="#{booking.checkoutDate}">
<f:convertDateTime dateStyle="short"/>
</h:outputText>
</p:column>
<p:column>
<f:facet name="header">Confirmation #</f:facet>
#{booking.id}
</p:column>
<p:column>
<f:facet name="header">Action</f:facet>
<p:commandButton id="cancel" value="Cancel" action="cancelBooking" update=":bookings"/>
</p:column>
</p:dataTable>
</p:outputPanel>
</h:form>
</p:panel>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<var name="searchCriteria" class="org.springframework.webflow.samples.booking.SearchCriteria" />
<view-state id="enterSearchCriteria">
<on-render>
<evaluate expression="bookingService.findBookings(currentUser?.name)" result="viewScope.bookings" result-type="dataModel" />
</on-render>
<transition on="search" to="reviewHotels"/>
<transition on="cancelBooking">
<evaluate expression="bookingService.cancelBooking(bookings.selectedRow)" />
</transition>
</view-state>
<view-state id="reviewHotels">
<on-entry>
<set name="viewScope.hotels" value="searchCriteria.getDataModel(bookingService)" />
</on-entry>
<transition on="select" to="reviewHotel">
<set name="flowScope.hotel" value="hotels.selected" />
</transition>
<transition on="changeSearch" to="enterSearchCriteria" />
</view-state>
<view-state id="reviewHotel">
<transition on="book" to="bookHotel" />
<transition on="cancel" to="reviewHotels" />
</view-state>
<subflow-state id="bookHotel" subflow="booking">
<input name="hotelId" value="hotel.id" />
<transition on="bookingConfirmed" to="finish" />
<transition on="bookingCancelled" to="enterSearchCriteria" />
</subflow-state>
<end-state id="finish" />
</flow>

View File

@@ -0,0 +1,43 @@
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
template="/WEB-INF/layouts/standard.xhtml">
<ui:define name="notes">
<p>
Clicking "Book" will launch the booking sub-flow (see the subflow state in <strong>main-flow.xml</strong>).
</p>
<p>
The booking flow is protected with Spring Security (see the secured attribute in <strong>booking-flow.xml</strong>).
</p>
<p>
Clicking "Back to Search" will take you to the stateful search results.
</p>
</ui:define>
<ui:define name="content">
<h1>${hotel.name}</h1>
<address>
${hotel.address}
<br />
${hotel.city}
<br />
${hotel.state} ${hotel.zip}
<br />
${hotel.country}
</address>
<h:form id="hotel">
<div>
Nightly Rate:&#160;
<h:outputText value="#{hotel.price}">
<f:convertNumber type="currency" currencySymbol="$"/>
</h:outputText>
</div>
<div>
<p:commandButton id="book" action="book" value="Book Hotel" ajax="false" />
<p:commandButton id="cancel" action="cancel" value="Back to Search"/>
</div>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,52 @@
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
template="/WEB-INF/layouts/standard.xhtml">
<ui:define name="notes">
<p>
This page uses the PrimeFaces data table backed by a lazily loaded DataModel (see <strong>HotelLazyDataModel.java</strong>).
Page navigation is Ajax-based and uses JSF 2 partial rendering.
The name and city columns support forward and reverse sorting.
</p>
<p>
The DataModel is created and stored in view scope when the view is first entered (see <strong>main-flow.xml</strong>).
When the user makes a selection, the selection is stored in a flow-scoped "hotel" variable before transitioning to the detail page.
</p>
</ui:define>
<ui:define name="content">
<h:form>
<p:dataTable id="hotels" var="h" value="#{hotels}" paginator="true" dynamic="true"
rows="#{hotels.pageSize}" page="#{hotels.currentPage}">
<f:facet name="header">
Hotel Search Results<br/>
<p:commandLink value="Modify or start search again" action="changeSearch" styleClass="alt" />
</f:facet>
<p:column sortBy="#{h.name}">
<f:facet name="header">Name</f:facet>
#{h.name}
</p:column>
<p:column>
<f:facet name="header">Address</f:facet>
#{h.address}
</p:column>
<p:column sortBy="#{h.city}">
<f:facet name="header">City, State</f:facet>
#{h.city}, #{h.state}, #{h.country}
</p:column>
<p:column>
<f:facet name="header">Zip</f:facet>
#{h.zip}
</p:column>
<p:column>
<f:facet name="header">Action</f:facet>
<p:commandButton id="viewHotelLink" value="View" action="select" icon="ui-icon-search">
<f:setPropertyActionListener value="#{h}" target="#{hotels.selected}" />
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,44 @@
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:sf="http://www.springframework.org/tags/faces"
template="layouts/standard.xhtml">
<ui:define name="notes">
<p>
This is a simple standalone JSF page.
</p>
<p>
Clicking the "Start" link below will launch the main to search for hotels (see <strong>main-flow.xml</strong>).
The main flow in turn launches the booking sub-flow to book the hotel (see <strong>booking-flow.xml</strong>).
</p>
<p>
The main flow is accessible without logging in while the booking flow requires authentication.
</p>
</ui:define>
<ui:define name="content">
<div>
<h1>Welcome to Spring Travel</h1>
<h3 class="alt">Spring Web Flow and JSF 2 with PrimeFaces components</h3>
<hr />
<p>
Key features illustrated in this sample:
</p>
<ul>
<li>A declarative navigation model enabling full browser button support and dynamic navigation rules</li>
<li>A fine-grained state management model, including support for conversation, view, and flash scopes</li>
<li>Partial page rendering via Ajax with JSF 2</li>
<li>Modularization of web application functionality by domain use case, illustrating project structure best-practices</li>
<li>Spring Security integration</li>
<li>Page layout with Blueprint CSS</li>
<li>Exception handling support across all layers of the application</li>
</ul>
<p>
<a href="main">Start your Spring Travel experience</a>
</p>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,63 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<f:view contentType="text/html">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Spring Faces: Hotel Booking Sample Application</title>
<link rel="stylesheet" href="${request.contextPath}/styles/blueprint/screen.css" type="text/css" media="screen, projection" />
<link rel="stylesheet" href="${request.contextPath}/styles/blueprint/print.css" type="text/css" media="print" />
<!--[if lt IE 8]>
<link rel="stylesheet" href="${request.contextPath}/styles/blueprint/ie.css" type="text/css" media="screen, projection" />
<![endif]-->
<link rel="stylesheet" href="${request.contextPath}/styles/le-frog/jquery-ui-1.8.2.custom.css" type="text/css" media="screen" />
<ui:insert name="headIncludes"/>
<style>
<!--
div.ui-datatable > table {
margin-bottom: 0;
}
-->
</style>
</h:head>
<h:body>
<div class="container">
<div>
<h4 class="alt bottom">
<c:if test="${not empty currentUser.name}">
Welcome, ${currentUser.name} | <a href="${request.contextPath}/spring/logout">Logout</a>
</c:if>
<c:if test="${empty currentUser.name}">
<a href="${request.contextPath}/spring/login">Login</a>
</c:if>
</h4>
</div>
<div>
<a href="#{request.contextPath}"><img src="${request.contextPath}/images/header.jpg" height="200" width="950" alt="Spring Travel"/></a>
</div>
<hr class="space" />
<div>
<div id="local" class="span-4 colborder">
<h3>Comments:</h3>
<ui:insert name="notes"/>
</div>
<div class="span-19 last">
<ui:insert name="content"/>
</div>
</div>
<hr class="space" />
<div>
<a href="http://www.springframework.org">
<img src="${request.contextPath}/images/powered-by-spring.png" alt="Powered by Spring" />
</a>
</div>
</div>
</h:body>
</f:view>
</html>

View File

@@ -0,0 +1,58 @@
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core"
template="layouts/standard.xhtml">
<ui:define name="notes">
<p>
Form-based authentication with Spring Security.
Spring Security is first enabled in web.xml via DelegatingFilterProxy.
It's configuration is located in <strong>security-config.xml</strong>.
Flow definitions can further be protected using the secured attribute (see <strong>booking-flow.xml</strong>).
</p>
</ui:define>
<ui:define name="content">
<div class="span-5">
<p>Valid username/passwords are:</p>
<ul>
<li>keith/melbourne</li>
<li>erwin/leuven</li>
<li>jeremy/atlanta</li>
<li>scott/rochester</li>
</ul>
</div>
<div class="span-10 append-2 last">
<c:if test="${not empty param.login_error}">
<div class="error">
Your login attempt was not successful, try again.<br />
Reason: #{sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}
</div>
</c:if>
<form name="f" action="${request.contextPath}/spring/loginProcess" method="post">
<fieldset>
<legend>Login Information</legend>
<p>
User:
<br />
<c:if test="${not empty param.login_error}">
<c:set var="username" value="${sessionScope.SPRING_SECURITY_LAST_USERNAME}"/>
</c:if>
<input type="text" name="j_username" value="#{username}"/>
</p>
<p>
Password:
<br />
<input type="password" name="j_password" />
</p>
<p>
<input type="checkbox" name="_spring_security_remember_me"/>
Don't ask for my password for two weeks:
</p>
<p>
<input name="submit" type="submit" value="Login" />
</p>
</fieldset>
</form>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,14 @@
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
template="layouts/standard.xhtml">
<ui:define name="content">
<div>
<h1>Logout</h1>
<p>You have successfully logged out.</p>
<hr />
<p><a href="#{request.contextPath}/spring/main">Continue</a></p>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
"http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
<facelet-taglib>
<namespace>http://www.springframework.org/security/tags</namespace>
<tag>
<tag-name>authorize</tag-name>
<handler-class>org.springframework.faces.security.FaceletsAuthorizeTagHandler</handler-class>
</tag>
<function>
<function-name>areAllGranted</function-name>
<function-class>org.springframework.faces.security.FaceletsAuthorizeTagUtils</function-class>
<function-signature>boolean areAllGranted(java.lang.String)</function-signature>
</function>
<function>
<function-name>areAnyGranted</function-name>
<function-class>org.springframework.faces.security.FaceletsAuthorizeTagUtils</function-class>
<function-signature>boolean areAnyGranted(java.lang.String)</function-signature>
</function>
<function>
<function-name>areNotGranted</function-name>
<function-class>org.springframework.faces.security.FaceletsAuthorizeTagUtils</function-class>
<function-signature>boolean areNotGranted(java.lang.String)</function-signature>
</function>
<function>
<function-name>isAllowed</function-name>
<function-class>org.springframework.faces.security.FaceletsAuthorizeTagUtils</function-class>
<function-signature>boolean isAllowed(java.lang.String, java.lang.String)</function-signature>
</function>
</facelet-taglib>

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<!-- The master configuration file for this Spring web application -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/web-application-config.xml
</param-value>
</context-param>
<!-- Use JSF view templates saved as *.xhtml, for use with Facelets -->
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<!-- Enables special Facelets debug output during development -->
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<!-- Causes Facelets to refresh templates during development -->
<context-param>
<param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>1</param-value>
</context-param>
<!--
Uncomment this to disable partial state saving when using Apache MyFaces 2 !!
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
-->
<!-- Declare Spring Security Facelets tag library -->
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/springsecurity.taglib.xml</param-value>
</context-param>
<!-- Enforce UTF-8 Character Encoding -->
<filter>
<filter-name>charEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>charEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Enables Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Loads the Spring web application context -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<!-- Map all /spring requests to the Dispatcher Servlet for handling -->
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/spring/*</url-pattern>
</servlet-mapping>
<!-- Just here so the JSF implementation can initialize, *not* used at runtime -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Just here so the JSF implementation can initialize -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,5 @@
<html>
<head>
<meta http-equiv="Refresh" content="0; URL=spring/intro">
</head>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

View File

@@ -0,0 +1,36 @@
/* -----------------------------------------------------------------------
Blueprint CSS Framework 0.9
http://blueprintcss.org
* Copyright (c) 2007-Present. See LICENSE for more info.
* See README for instructions on how to use Blueprint.
* For credits and origins, see AUTHORS.
* This is a compressed file. See the sources in the 'src' directory.
----------------------------------------------------------------------- */
/* ie.css */
body {text-align:center;}
.container {text-align:left;}
* html .column, * html div.span-1, * html div.span-2, * html div.span-3, * html div.span-4, * html div.span-5, * html div.span-6, * html div.span-7, * html div.span-8, * html div.span-9, * html div.span-10, * html div.span-11, * html div.span-12, * html div.span-13, * html div.span-14, * html div.span-15, * html div.span-16, * html div.span-17, * html div.span-18, * html div.span-19, * html div.span-20, * html div.span-21, * html div.span-22, * html div.span-23, * html div.span-24 {display:inline;overflow-x:hidden;}
* html legend {margin:0px -8px 16px 0;padding:0;}
ol {margin-left:2em;}
sup {vertical-align:text-top;}
sub {vertical-align:text-bottom;}
html>body p code {*white-space:normal;}
hr {margin:-8px auto 11px;}
img {-ms-interpolation-mode:bicubic;}
.clearfix, .container {display:inline-block;}
* html .clearfix, * html .container {height:1%;}
fieldset {padding-top:0;}
textarea {overflow:auto;}
input.text, input.title, textarea {background-color:#fff;border:1px solid #bbb;}
input.text:focus, input.title:focus {border-color:#666;}
input.text, input.title, textarea, select {margin:0.5em 0;}
input.checkbox, input.radio {position:relative;top:.25em;}
form.inline div, form.inline p {vertical-align:middle;}
form.inline label {position:relative;top:-0.25em;}
form.inline input.checkbox, form.inline input.radio, form.inline input.button, form.inline button {margin:0.5em 0;}
button, input.button {position:relative;top:0.25em;}

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

View File

@@ -0,0 +1,32 @@
Buttons
* Gives you great looking CSS buttons, for both <a> and <button>.
* Demo: particletree.com/features/rediscovering-the-button-element
Credits
----------------------------------------------------------------
* Created by Kevin Hale [particletree.com]
* Adapted for Blueprint by Olav Bjorkoy [bjorkoy.com]
Usage
----------------------------------------------------------------
1) Add this plugin to lib/settings.yml.
See compress.rb for instructions.
2) Use the following HTML code to place the buttons on your site:
<button type="submit" class="button positive">
<img src="css/blueprint/plugins/buttons/icons/tick.png" alt=""/> Save
</button>
<a class="button" href="/password/reset/">
<img src="css/blueprint/plugins/buttons/icons/key.png" alt=""/> Change Password
</a>
<a href="#" class="button negative">
<img src="css/blueprint/plugins/buttons/icons/cross.png" alt=""/> Cancel
</a>

View File

@@ -0,0 +1,97 @@
/* --------------------------------------------------------------
buttons.css
* Gives you some great CSS-only buttons.
Created by Kevin Hale [particletree.com]
* particletree.com/features/rediscovering-the-button-element
See Readme.txt in this folder for instructions.
-------------------------------------------------------------- */
a.button, button {
display:block;
float:left;
margin: 0.7em 0.5em 0.7em 0;
padding:5px 10px 5px 7px; /* Links */
border:1px solid #dedede;
border-top:1px solid #eee;
border-left:1px solid #eee;
background-color:#f5f5f5;
font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif;
font-size:100%;
line-height:130%;
text-decoration:none;
font-weight:bold;
color:#565656;
cursor:pointer;
}
button {
width:auto;
overflow:visible;
padding:4px 10px 3px 7px; /* IE6 */
}
button[type] {
padding:4px 10px 4px 7px; /* Firefox */
line-height:17px; /* Safari */
}
*:first-child+html button[type] {
padding:4px 10px 3px 7px; /* IE7 */
}
button img, a.button img{
margin:0 3px -3px 0 !important;
padding:0;
border:none;
width:16px;
height:16px;
float:none;
}
/* Button colors
-------------------------------------------------------------- */
/* Standard */
button:hover, a.button:hover{
background-color:#dff4ff;
border:1px solid #c2e1ef;
color:#336699;
}
a.button:active{
background-color:#6299c5;
border:1px solid #6299c5;
color:#fff;
}
/* Positive */
body .positive {
color:#529214;
}
a.positive:hover, button.positive:hover {
background-color:#E6EFC2;
border:1px solid #C6D880;
color:#529214;
}
a.positive:active {
background-color:#529214;
border:1px solid #529214;
color:#fff;
}
/* Negative */
body .negative {
color:#d12f19;
}
a.negative:hover, button.negative:hover {
background-color:#fbe3e4;
border:1px solid #fbc2c4;
color:#d12f19;
}
a.negative:active {
background-color:#d12f19;
border:1px solid #d12f19;
color:#fff;
}

View File

@@ -0,0 +1,14 @@
Fancy Type
* Gives you classes to use if you'd like some
extra fancy typography.
Credits and instructions are specified above each class
in the fancy-type.css file in this directory.
Usage
----------------------------------------------------------------
1) Add this plugin to lib/settings.yml.
See compress.rb for instructions.

View File

@@ -0,0 +1,71 @@
/* --------------------------------------------------------------
fancy-type.css
* Lots of pretty advanced classes for manipulating text.
See the Readme file in this folder for additional instructions.
-------------------------------------------------------------- */
/* Indentation instead of line shifts for sibling paragraphs. */
p + p { text-indent:2em; margin-top:-1.5em; }
form p + p { text-indent: 0; } /* Don't want this in forms. */
/* For great looking type, use this code instead of asdf:
<span class="alt">asdf</span>
Best used on prepositions and ampersands. */
.alt {
color: #666;
font-family: "Warnock Pro", "Goudy Old Style","Palatino","Book Antiqua", Georgia, serif;
font-style: italic;
font-weight: normal;
}
/* For great looking quote marks in titles, replace "asdf" with:
<span class="dquo">&#8220;</span>asdf&#8221;
(That is, when the title starts with a quote mark).
(You may have to change this value depending on your font size). */
.dquo { margin-left: -.5em; }
/* Reduced size type with incremental leading
(http://www.markboulton.co.uk/journal/comments/incremental_leading/)
This could be used for side notes. For smaller type, you don't necessarily want to
follow the 1.5x vertical rhythm -- the line-height is too much.
Using this class, it reduces your font size and line-height so that for
every four lines of normal sized type, there is five lines of the sidenote. eg:
New type size in em's:
10px (wanted side note size) / 12px (existing base size) = 0.8333 (new type size in ems)
New line-height value:
12px x 1.5 = 18px (old line-height)
18px x 4 = 72px
72px / 5 = 14.4px (new line height)
14.4px / 10px = 1.44 (new line height in em's) */
p.incr, .incr p {
font-size: 10px;
line-height: 1.44em;
margin-bottom: 1.5em;
}
/* Surround uppercase words and abbreviations with this class.
Based on work by Jørgen Arnor Gårdsø Lom [http://twistedintellect.com/] */
.caps {
font-variant: small-caps;
letter-spacing: 1px;
text-transform: lowercase;
font-size:1.2em;
line-height:1%;
font-weight:bold;
padding:0 2px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

View File

@@ -0,0 +1,18 @@
Link Icons
* Icons for links based on protocol or file type.
This is not supported in IE versions < 7.
Credits
----------------------------------------------------------------
* Marc Morgan
* Olav Bjorkoy [bjorkoy.com]
Usage
----------------------------------------------------------------
1) Add this line to your HTML:
<link rel="stylesheet" href="css/blueprint/plugins/link-icons/screen.css" type="text/css" media="screen, projection">

View File

@@ -0,0 +1,40 @@
/* --------------------------------------------------------------
link-icons.css
* Icons for links based on protocol or file type.
See the Readme file in this folder for additional instructions.
-------------------------------------------------------------- */
/* Use this class if a link gets an icon when it shouldn't. */
body a.noicon {
background:transparent none !important;
padding:0 !important;
margin:0 !important;
}
/* Make sure the icons are not cut */
a[href^="http:"], a[href^="mailto:"], a[href^="http:"]:visited,
a[href$=".pdf"], a[href$=".doc"], a[href$=".xls"], a[href$=".rss"],
a[href$=".rdf"], a[href^="aim:"] {
padding:2px 22px 2px 0;
margin:-2px 0;
background-repeat: no-repeat;
background-position: right center;
}
/* External links */
a[href^="http:"] { background-image: url(icons/external.png); }
a[href^="mailto:"] { background-image: url(icons/email.png); }
a[href^="http:"]:visited { background-image: url(icons/visited.png); }
/* Files */
a[href$=".pdf"] { background-image: url(icons/pdf.png); }
a[href$=".doc"] { background-image: url(icons/doc.png); }
a[href$=".xls"] { background-image: url(icons/xls.png); }
/* Misc */
a[href$=".rss"],
a[href$=".rdf"] { background-image: url(icons/feed.png); }
a[href^="aim:"] { background-image: url(icons/im.png); }

View File

@@ -0,0 +1,10 @@
RTL
* Mirrors Blueprint, so it can be used with Right-to-Left languages.
By Ran Yaniv Hartstein, ranh.co.il
Usage
----------------------------------------------------------------
1) Add this line to your HTML:
<link rel="stylesheet" href="css/blueprint/plugins/rtl/screen.css" type="text/css" media="screen, projection">

View File

@@ -0,0 +1,110 @@
/* --------------------------------------------------------------
rtl.css
* Mirrors Blueprint for left-to-right languages
By Ran Yaniv Hartstein [ranh.co.il]
-------------------------------------------------------------- */
body .container { direction: rtl; }
body .column, body div.span-1, body div.span-2, body div.span-3, body div.span-4, body div.span-5, body div.span-6, body div.span-7, body div.span-8, body div.span-9, body div.span-10, body div.span-11, body div.span-12, body div.span-13, body div.span-14, body div.span-15, body div.span-16, body div.span-17, body div.span-18, body div.span-19, body div.span-20, body div.span-21, body div.span-22, body div.span-23, body div.span-24 {
float: right;
margin-right: 0;
margin-left: 10px;
text-align:right;
}
body div.last { margin-left: 0; }
body table .last { padding-left: 0; }
body .append-1 { padding-right: 0; padding-left: 40px; }
body .append-2 { padding-right: 0; padding-left: 80px; }
body .append-3 { padding-right: 0; padding-left: 120px; }
body .append-4 { padding-right: 0; padding-left: 160px; }
body .append-5 { padding-right: 0; padding-left: 200px; }
body .append-6 { padding-right: 0; padding-left: 240px; }
body .append-7 { padding-right: 0; padding-left: 280px; }
body .append-8 { padding-right: 0; padding-left: 320px; }
body .append-9 { padding-right: 0; padding-left: 360px; }
body .append-10 { padding-right: 0; padding-left: 400px; }
body .append-11 { padding-right: 0; padding-left: 440px; }
body .append-12 { padding-right: 0; padding-left: 480px; }
body .append-13 { padding-right: 0; padding-left: 520px; }
body .append-14 { padding-right: 0; padding-left: 560px; }
body .append-15 { padding-right: 0; padding-left: 600px; }
body .append-16 { padding-right: 0; padding-left: 640px; }
body .append-17 { padding-right: 0; padding-left: 680px; }
body .append-18 { padding-right: 0; padding-left: 720px; }
body .append-19 { padding-right: 0; padding-left: 760px; }
body .append-20 { padding-right: 0; padding-left: 800px; }
body .append-21 { padding-right: 0; padding-left: 840px; }
body .append-22 { padding-right: 0; padding-left: 880px; }
body .append-23 { padding-right: 0; padding-left: 920px; }
body .prepend-1 { padding-left: 0; padding-right: 40px; }
body .prepend-2 { padding-left: 0; padding-right: 80px; }
body .prepend-3 { padding-left: 0; padding-right: 120px; }
body .prepend-4 { padding-left: 0; padding-right: 160px; }
body .prepend-5 { padding-left: 0; padding-right: 200px; }
body .prepend-6 { padding-left: 0; padding-right: 240px; }
body .prepend-7 { padding-left: 0; padding-right: 280px; }
body .prepend-8 { padding-left: 0; padding-right: 320px; }
body .prepend-9 { padding-left: 0; padding-right: 360px; }
body .prepend-10 { padding-left: 0; padding-right: 400px; }
body .prepend-11 { padding-left: 0; padding-right: 440px; }
body .prepend-12 { padding-left: 0; padding-right: 480px; }
body .prepend-13 { padding-left: 0; padding-right: 520px; }
body .prepend-14 { padding-left: 0; padding-right: 560px; }
body .prepend-15 { padding-left: 0; padding-right: 600px; }
body .prepend-16 { padding-left: 0; padding-right: 640px; }
body .prepend-17 { padding-left: 0; padding-right: 680px; }
body .prepend-18 { padding-left: 0; padding-right: 720px; }
body .prepend-19 { padding-left: 0; padding-right: 760px; }
body .prepend-20 { padding-left: 0; padding-right: 800px; }
body .prepend-21 { padding-left: 0; padding-right: 840px; }
body .prepend-22 { padding-left: 0; padding-right: 880px; }
body .prepend-23 { padding-left: 0; padding-right: 920px; }
body .border {
padding-right: 0;
padding-left: 4px;
margin-right: 0;
margin-left: 5px;
border-right: none;
border-left: 1px solid #eee;
}
body .colborder {
padding-right: 0;
padding-left: 24px;
margin-right: 0;
margin-left: 25px;
border-right: none;
border-left: 1px solid #eee;
}
body .pull-1 { margin-left: 0; margin-right: -40px; }
body .pull-2 { margin-left: 0; margin-right: -80px; }
body .pull-3 { margin-left: 0; margin-right: -120px; }
body .pull-4 { margin-left: 0; margin-right: -160px; }
body .push-0 { margin: 0 18px 0 0; }
body .push-1 { margin: 0 18px 0 -40px; }
body .push-2 { margin: 0 18px 0 -80px; }
body .push-3 { margin: 0 18px 0 -120px; }
body .push-4 { margin: 0 18px 0 -160px; }
body .push-0, body .push-1, body .push-2,
body .push-3, body .push-4 { float: left; }
/* Typography with RTL support */
body h1,body h2,body h3,
body h4,body h5,body h6 { font-family: Arial, sans-serif; }
html body { font-family: Arial, sans-serif; }
body pre,body code,body tt { font-family: monospace; }
/* Mirror floats and margins on typographic elements */
body p img { float: right; margin: 1.5em 0 1.5em 1.5em; }
body dd, body ul, body ol { margin-left: 0; margin-right: 1.5em;}
body td, body th { text-align:right; }

View File

@@ -0,0 +1,29 @@
/* -----------------------------------------------------------------------
Blueprint CSS Framework 0.9
http://blueprintcss.org
* Copyright (c) 2007-Present. See LICENSE for more info.
* See README for instructions on how to use Blueprint.
* For credits and origins, see AUTHORS.
* This is a compressed file. See the sources in the 'src' directory.
----------------------------------------------------------------------- */
/* print.css */
body {line-height:1.5;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;color:#000;background:none;font-size:10pt;}
.container {background:none;}
hr {background:#ccc;color:#ccc;width:100%;height:2px;margin:2em 0;padding:0;border:none;}
hr.space {background:#fff;color:#fff;visibility:hidden;}
h1, h2, h3, h4, h5, h6 {font-family:"Helvetica Neue", Arial, "Lucida Grande", sans-serif;}
code {font:.9em "Courier New", Monaco, Courier, monospace;}
a img {border:none;}
p img.top {margin-top:0;}
blockquote {margin:1.5em;padding:1em;font-style:italic;font-size:.9em;}
.small {font-size:.9em;}
.large {font-size:1.1em;}
.quiet {color:#999;}
.hide {display:none;}
a:link, a:visited {background:transparent;font-weight:700;text-decoration:underline;}
a:link:after, a:visited:after {content:" (" attr(href) ")";font-size:90%;}

View File

@@ -0,0 +1,280 @@
/* -----------------------------------------------------------------------
Blueprint CSS Framework 0.9
http://blueprintcss.org
* Copyright (c) 2007-Present. See LICENSE for more info.
* See README for instructions on how to use Blueprint.
* For credits and origins, see AUTHORS.
* This is a compressed file. See the sources in the 'src' directory.
----------------------------------------------------------------------- */
/* reset.css */
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;}
body {line-height:1.5;}
table {border-collapse:separate;border-spacing:0;}
caption, th, td {text-align:left;font-weight:normal;}
table, td, th {vertical-align:middle;}
blockquote:before, blockquote:after, q:before, q:after {content:"";}
blockquote, q {quotes:"" "";}
a img {border:none;}
/* typography.css */
html {font-size:100.01%;}
body {font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;}
h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;}
h1 {font-size:3em;line-height:1;margin-bottom:0.5em;}
h2 {font-size:2em;margin-bottom:0.75em;}
h3 {font-size:1.5em;line-height:1;margin-bottom:1em;}
h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;}
h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;}
h6 {font-size:1em;font-weight:bold;}
h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;}
p {margin:0 0 1.5em;}
p img.left {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;}
p img.right {float:right;margin:1.5em 0 1.5em 1.5em;}
a:focus, a:hover {color:#000;}
a {color:#009;text-decoration:underline;}
blockquote {margin:1.5em;color:#666;font-style:italic;}
strong {font-weight:bold;}
em, dfn {font-style:italic;}
dfn {font-weight:bold;}
sup, sub {line-height:0;}
abbr, acronym {border-bottom:1px dotted #666;}
address {margin:0 0 1.5em;font-style:italic;}
del {color:#666;}
pre {margin:1.5em 0;white-space:pre;}
pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;}
li ul, li ol {margin:0 1.5em;}
ul, ol {margin:0 1.5em 1.5em 1.5em;}
ul {list-style-type:disc;}
ol {list-style-type:decimal;}
dl {margin:0 0 1.5em 0;}
dl dt {font-weight:bold;}
dd {margin-left:1.5em;}
table {margin-bottom:1.4em;width:100%;}
th {font-weight:bold;}
thead th {background:#c3d9ff;}
th, td, caption {padding:4px 10px 4px 5px;}
tr.even td {background:#e5ecf9;}
tfoot {font-style:italic;}
caption {background:#eee;}
.small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;}
.large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;}
.hide {display:none;}
.quiet {color:#666;}
.loud {color:#000;}
.highlight {background:#ff0;}
.added {background:#060;color:#fff;}
.removed {background:#900;color:#fff;}
.first {margin-left:0;padding-left:0;}
.last {margin-right:0;padding-right:0;}
.top {margin-top:0;padding-top:0;}
.bottom {margin-bottom:0;padding-bottom:0;}
/* forms.css */
label {font-weight:bold;}
fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;}
legend {font-weight:bold;font-size:1.2em;}
input[type=text], input[type=password], input.text, input.title, textarea, select {background-color:#fff;border:1px solid #bbb;}
input[type=text]:focus, input[type=password]:focus, input.text:focus, input.title:focus, textarea:focus, select:focus {border-color:#666;}
input[type=text], input[type=password], input.text, input.title, textarea, select {margin:0.5em 0;}
input.text, input.title {width:300px;padding:5px;}
input.title {font-size:1.5em;}
textarea {width:390px;height:250px;padding:5px;}
input[type=checkbox], input[type=radio], input.checkbox, input.radio {position:relative;top:.25em;}
form.inline {line-height:3;}
form.inline p {margin-bottom:0;}
.error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;}
.error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;}
.notice {background:#FFF6BF;color:#514721;border-color:#FFD324;}
.success {background:#E6EFC2;color:#264409;border-color:#C6D880;}
.error a {color:#8a1f11;}
.notice a {color:#514721;}
.success a {color:#264409;}
/* grid.css */
.container {width:950px;margin:0 auto;}
.showgrid {background:url(src/grid.png);}
.column, div.span-1, div.span-2, div.span-3, div.span-4, div.span-5, div.span-6, div.span-7, div.span-8, div.span-9, div.span-10, div.span-11, div.span-12, div.span-13, div.span-14, div.span-15, div.span-16, div.span-17, div.span-18, div.span-19, div.span-20, div.span-21, div.span-22, div.span-23, div.span-24 {float:left;margin-right:10px;}
.last, div.last {margin-right:0;}
.span-1 {width:30px;}
.span-2 {width:70px;}
.span-3 {width:110px;}
.span-4 {width:150px;}
.span-5 {width:190px;}
.span-6 {width:230px;}
.span-7 {width:270px;}
.span-8 {width:310px;}
.span-9 {width:350px;}
.span-10 {width:390px;}
.span-11 {width:430px;}
.span-12 {width:470px;}
.span-13 {width:510px;}
.span-14 {width:550px;}
.span-15 {width:590px;}
.span-16 {width:630px;}
.span-17 {width:670px;}
.span-18 {width:710px;}
.span-19 {width:750px;}
.span-20 {width:790px;}
.span-21 {width:830px;}
.span-22 {width:870px;}
.span-23 {width:910px;}
.span-24, div.span-24 {width:950px;margin-right:0;}
input.span-1, textarea.span-1, input.span-2, textarea.span-2, input.span-3, textarea.span-3, input.span-4, textarea.span-4, input.span-5, textarea.span-5, input.span-6, textarea.span-6, input.span-7, textarea.span-7, input.span-8, textarea.span-8, input.span-9, textarea.span-9, input.span-10, textarea.span-10, input.span-11, textarea.span-11, input.span-12, textarea.span-12, input.span-13, textarea.span-13, input.span-14, textarea.span-14, input.span-15, textarea.span-15, input.span-16, textarea.span-16, input.span-17, textarea.span-17, input.span-18, textarea.span-18, input.span-19, textarea.span-19, input.span-20, textarea.span-20, input.span-21, textarea.span-21, input.span-22, textarea.span-22, input.span-23, textarea.span-23, input.span-24, textarea.span-24 {border-left-width:1px!important;border-right-width:1px!important;padding-left:5px!important;padding-right:5px!important;}
input.span-1, textarea.span-1 {width:18px!important;}
input.span-2, textarea.span-2 {width:58px!important;}
input.span-3, textarea.span-3 {width:98px!important;}
input.span-4, textarea.span-4 {width:138px!important;}
input.span-5, textarea.span-5 {width:178px!important;}
input.span-6, textarea.span-6 {width:218px!important;}
input.span-7, textarea.span-7 {width:258px!important;}
input.span-8, textarea.span-8 {width:298px!important;}
input.span-9, textarea.span-9 {width:338px!important;}
input.span-10, textarea.span-10 {width:378px!important;}
input.span-11, textarea.span-11 {width:418px!important;}
input.span-12, textarea.span-12 {width:458px!important;}
input.span-13, textarea.span-13 {width:498px!important;}
input.span-14, textarea.span-14 {width:538px!important;}
input.span-15, textarea.span-15 {width:578px!important;}
input.span-16, textarea.span-16 {width:618px!important;}
input.span-17, textarea.span-17 {width:658px!important;}
input.span-18, textarea.span-18 {width:698px!important;}
input.span-19, textarea.span-19 {width:738px!important;}
input.span-20, textarea.span-20 {width:778px!important;}
input.span-21, textarea.span-21 {width:818px!important;}
input.span-22, textarea.span-22 {width:858px!important;}
input.span-23, textarea.span-23 {width:898px!important;}
input.span-24, textarea.span-24 {width:938px!important;}
.append-1 {padding-right:40px;}
.append-2 {padding-right:80px;}
.append-3 {padding-right:120px;}
.append-4 {padding-right:160px;}
.append-5 {padding-right:200px;}
.append-6 {padding-right:240px;}
.append-7 {padding-right:280px;}
.append-8 {padding-right:320px;}
.append-9 {padding-right:360px;}
.append-10 {padding-right:400px;}
.append-11 {padding-right:440px;}
.append-12 {padding-right:480px;}
.append-13 {padding-right:520px;}
.append-14 {padding-right:560px;}
.append-15 {padding-right:600px;}
.append-16 {padding-right:640px;}
.append-17 {padding-right:680px;}
.append-18 {padding-right:720px;}
.append-19 {padding-right:760px;}
.append-20 {padding-right:800px;}
.append-21 {padding-right:840px;}
.append-22 {padding-right:880px;}
.append-23 {padding-right:920px;}
.prepend-1 {padding-left:40px;}
.prepend-2 {padding-left:80px;}
.prepend-3 {padding-left:120px;}
.prepend-4 {padding-left:160px;}
.prepend-5 {padding-left:200px;}
.prepend-6 {padding-left:240px;}
.prepend-7 {padding-left:280px;}
.prepend-8 {padding-left:320px;}
.prepend-9 {padding-left:360px;}
.prepend-10 {padding-left:400px;}
.prepend-11 {padding-left:440px;}
.prepend-12 {padding-left:480px;}
.prepend-13 {padding-left:520px;}
.prepend-14 {padding-left:560px;}
.prepend-15 {padding-left:600px;}
.prepend-16 {padding-left:640px;}
.prepend-17 {padding-left:680px;}
.prepend-18 {padding-left:720px;}
.prepend-19 {padding-left:760px;}
.prepend-20 {padding-left:800px;}
.prepend-21 {padding-left:840px;}
.prepend-22 {padding-left:880px;}
.prepend-23 {padding-left:920px;}
div.border {padding-right:4px;margin-right:5px;border-right:1px solid #eee;}
div.colborder {padding-right:24px;margin-right:25px;border-right:1px solid #eee;}
.pull-1 {margin-left:-40px;}
.pull-2 {margin-left:-80px;}
.pull-3 {margin-left:-120px;}
.pull-4 {margin-left:-160px;}
.pull-5 {margin-left:-200px;}
.pull-6 {margin-left:-240px;}
.pull-7 {margin-left:-280px;}
.pull-8 {margin-left:-320px;}
.pull-9 {margin-left:-360px;}
.pull-10 {margin-left:-400px;}
.pull-11 {margin-left:-440px;}
.pull-12 {margin-left:-480px;}
.pull-13 {margin-left:-520px;}
.pull-14 {margin-left:-560px;}
.pull-15 {margin-left:-600px;}
.pull-16 {margin-left:-640px;}
.pull-17 {margin-left:-680px;}
.pull-18 {margin-left:-720px;}
.pull-19 {margin-left:-760px;}
.pull-20 {margin-left:-800px;}
.pull-21 {margin-left:-840px;}
.pull-22 {margin-left:-880px;}
.pull-23 {margin-left:-920px;}
.pull-24 {margin-left:-960px;}
.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float:left;position:relative;}
.push-1 {margin:0 -40px 1.5em 40px;}
.push-2 {margin:0 -80px 1.5em 80px;}
.push-3 {margin:0 -120px 1.5em 120px;}
.push-4 {margin:0 -160px 1.5em 160px;}
.push-5 {margin:0 -200px 1.5em 200px;}
.push-6 {margin:0 -240px 1.5em 240px;}
.push-7 {margin:0 -280px 1.5em 280px;}
.push-8 {margin:0 -320px 1.5em 320px;}
.push-9 {margin:0 -360px 1.5em 360px;}
.push-10 {margin:0 -400px 1.5em 400px;}
.push-11 {margin:0 -440px 1.5em 440px;}
.push-12 {margin:0 -480px 1.5em 480px;}
.push-13 {margin:0 -520px 1.5em 520px;}
.push-14 {margin:0 -560px 1.5em 560px;}
.push-15 {margin:0 -600px 1.5em 600px;}
.push-16 {margin:0 -640px 1.5em 640px;}
.push-17 {margin:0 -680px 1.5em 680px;}
.push-18 {margin:0 -720px 1.5em 720px;}
.push-19 {margin:0 -760px 1.5em 760px;}
.push-20 {margin:0 -800px 1.5em 800px;}
.push-21 {margin:0 -840px 1.5em 840px;}
.push-22 {margin:0 -880px 1.5em 880px;}
.push-23 {margin:0 -920px 1.5em 920px;}
.push-24 {margin:0 -960px 1.5em 960px;}
.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float:right;position:relative;}
.prepend-top {margin-top:1.5em;}
.append-bottom {margin-bottom:1.5em;}
.box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;}
hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;}
hr.space {background:#fff;color:#fff;visibility:hidden;}
.clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;}
.clearfix, .container {display:block;}
.clear {clear:both;}
/* fancy-type */
p + p {text-indent:2em;margin-top:-1.5em;}
form p + p {text-indent:0;}
.alt {color:#666;font-family:"Warnock Pro", "Goudy Old Style","Palatino","Book Antiqua", Georgia, serif;font-style:italic;font-weight:normal;}
.dquo {margin-left:-.5em;}
p.incr, .incr p {font-size:10px;line-height:1.44em;margin-bottom:1.5em;}
.caps {font-variant:small-caps;letter-spacing:1px;text-transform:lowercase;font-size:1.2em;line-height:1%;font-weight:bold;padding:0 2px;}
/* buttons */
a.button, button {display:block;float:left;margin:0.7em 0.5em 0.7em 0;padding:5px 10px 5px 7px;border:1px solid #dedede;border-top:1px solid #eee;border-left:1px solid #eee;background-color:#f5f5f5;font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif;font-size:100%;line-height:130%;text-decoration:none;font-weight:bold;color:#565656;cursor:pointer;}
button {width:auto;overflow:visible;padding:4px 10px 3px 7px;}
button[type] {padding:4px 10px 4px 7px;line-height:17px;}
*:first-child+html button[type] {padding:4px 10px 3px 7px;}
button img, a.button img {margin:0 3px -3px 0 !important;padding:0;border:none;width:16px;height:16px;float:none;}
button:hover, a.button:hover {background-color:#dff4ff;border:1px solid #c2e1ef;color:#336699;}
a.button:active {background-color:#6299c5;border:1px solid #6299c5;color:#fff;}
body .positive {color:#529214;}
a.positive:hover, button.positive:hover {background-color:#E6EFC2;border:1px solid #C6D880;color:#529214;}
a.positive:active {background-color:#529214;border:1px solid #529214;color:#fff;}
body .negative {color:#d12f19;}
a.negative:hover, button.negative:hover {background-color:#fbe3e4;border:1px solid #fbc2c4;color:#d12f19;}
a.negative:active {background-color:#d12f19;border:1px solid #d12f19;color:#fff;}

View File

@@ -0,0 +1,65 @@
/* --------------------------------------------------------------
forms.css
* Sets up some default styling for forms
* Gives you classes to enhance your forms
Usage:
* For text fields, use class .title or .text
* For inline forms, use .inline (even when using columns)
-------------------------------------------------------------- */
label { font-weight: bold; }
fieldset { padding:1.4em; margin: 0 0 1.5em 0; border: 1px solid #ccc; }
legend { font-weight: bold; font-size:1.2em; }
/* Form fields
-------------------------------------------------------------- */
input[type=text], input[type=password],
input.text, input.title,
textarea, select {
background-color:#fff;
border:1px solid #bbb;
}
input[type=text]:focus, input[type=password]:focus,
input.text:focus, input.title:focus,
textarea:focus, select:focus {
border-color:#666;
}
input[type=text], input[type=password],
input.text, input.title,
textarea, select {
margin:0.5em 0;
}
input.text,
input.title { width: 300px; padding:5px; }
input.title { font-size:1.5em; }
textarea { width: 390px; height: 250px; padding:5px; }
input[type=checkbox], input[type=radio],
input.checkbox, input.radio {
position:relative; top:.25em;
}
form.inline { line-height:3; }
form.inline p { margin-bottom:0; }
/* Success, notice and error boxes
-------------------------------------------------------------- */
.error,
.notice,
.success { padding: .8em; margin-bottom: 1em; border: 2px solid #ddd; }
.error { background: #FBE3E4; color: #8a1f11; border-color: #FBC2C4; }
.notice { background: #FFF6BF; color: #514721; border-color: #FFD324; }
.success { background: #E6EFC2; color: #264409; border-color: #C6D880; }
.error a { color: #8a1f11; }
.notice a { color: #514721; }
.success a { color: #264409; }

View File

@@ -0,0 +1,281 @@
/* --------------------------------------------------------------
grid.css
* Sets up an easy-to-use grid of 24 columns.
By default, the grid is 950px wide, with 24 columns
spanning 30px, and a 10px margin between columns.
If you need fewer or more columns, namespaces or semantic
element names, use the compressor script (lib/compress.rb)
Note: Changes made in this file will not be applied when
using the compressor: make changes in lib/blueprint/grid.css.rb
-------------------------------------------------------------- */
/* A container should group all your columns. */
.container {
width: 950px;
margin: 0 auto;
}
/* Use this class on any div.span / container to see the grid. */
.showgrid {
background: url(src/grid.png);
}
/* Columns
-------------------------------------------------------------- */
/* Sets up basic grid floating and margin. */
.column, div.span-1, div.span-2, div.span-3, div.span-4, div.span-5, div.span-6, div.span-7, div.span-8, div.span-9, div.span-10, div.span-11, div.span-12, div.span-13, div.span-14, div.span-15, div.span-16, div.span-17, div.span-18, div.span-19, div.span-20, div.span-21, div.span-22, div.span-23, div.span-24 {
float: left;
margin-right: 10px;
}
/* The last column in a row needs this class. */
.last, div.last { margin-right: 0; }
/* Use these classes to set the width of a column. */
.span-1 {width: 30px;}
.span-2 {width: 70px;}
.span-3 {width: 110px;}
.span-4 {width: 150px;}
.span-5 {width: 190px;}
.span-6 {width: 230px;}
.span-7 {width: 270px;}
.span-8 {width: 310px;}
.span-9 {width: 350px;}
.span-10 {width: 390px;}
.span-11 {width: 430px;}
.span-12 {width: 470px;}
.span-13 {width: 510px;}
.span-14 {width: 550px;}
.span-15 {width: 590px;}
.span-16 {width: 630px;}
.span-17 {width: 670px;}
.span-18 {width: 710px;}
.span-19 {width: 750px;}
.span-20 {width: 790px;}
.span-21 {width: 830px;}
.span-22 {width: 870px;}
.span-23 {width: 910px;}
.span-24, div.span-24 { width:950px; margin-right:0; }
/* Use these classes to set the width of an input. */
input.span-1, textarea.span-1, input.span-2, textarea.span-2, input.span-3, textarea.span-3, input.span-4, textarea.span-4, input.span-5, textarea.span-5, input.span-6, textarea.span-6, input.span-7, textarea.span-7, input.span-8, textarea.span-8, input.span-9, textarea.span-9, input.span-10, textarea.span-10, input.span-11, textarea.span-11, input.span-12, textarea.span-12, input.span-13, textarea.span-13, input.span-14, textarea.span-14, input.span-15, textarea.span-15, input.span-16, textarea.span-16, input.span-17, textarea.span-17, input.span-18, textarea.span-18, input.span-19, textarea.span-19, input.span-20, textarea.span-20, input.span-21, textarea.span-21, input.span-22, textarea.span-22, input.span-23, textarea.span-23, input.span-24, textarea.span-24 {
border-left-width: 1px!important;
border-right-width: 1px!important;
padding-left: 5px!important;
padding-right: 5px!important;
}
input.span-1, textarea.span-1 { width: 18px!important; }
input.span-2, textarea.span-2 { width: 58px!important; }
input.span-3, textarea.span-3 { width: 98px!important; }
input.span-4, textarea.span-4 { width: 138px!important; }
input.span-5, textarea.span-5 { width: 178px!important; }
input.span-6, textarea.span-6 { width: 218px!important; }
input.span-7, textarea.span-7 { width: 258px!important; }
input.span-8, textarea.span-8 { width: 298px!important; }
input.span-9, textarea.span-9 { width: 338px!important; }
input.span-10, textarea.span-10 { width: 378px!important; }
input.span-11, textarea.span-11 { width: 418px!important; }
input.span-12, textarea.span-12 { width: 458px!important; }
input.span-13, textarea.span-13 { width: 498px!important; }
input.span-14, textarea.span-14 { width: 538px!important; }
input.span-15, textarea.span-15 { width: 578px!important; }
input.span-16, textarea.span-16 { width: 618px!important; }
input.span-17, textarea.span-17 { width: 658px!important; }
input.span-18, textarea.span-18 { width: 698px!important; }
input.span-19, textarea.span-19 { width: 738px!important; }
input.span-20, textarea.span-20 { width: 778px!important; }
input.span-21, textarea.span-21 { width: 818px!important; }
input.span-22, textarea.span-22 { width: 858px!important; }
input.span-23, textarea.span-23 { width: 898px!important; }
input.span-24, textarea.span-24 { width: 938px!important; }
/* Add these to a column to append empty cols. */
.append-1 { padding-right: 40px;}
.append-2 { padding-right: 80px;}
.append-3 { padding-right: 120px;}
.append-4 { padding-right: 160px;}
.append-5 { padding-right: 200px;}
.append-6 { padding-right: 240px;}
.append-7 { padding-right: 280px;}
.append-8 { padding-right: 320px;}
.append-9 { padding-right: 360px;}
.append-10 { padding-right: 400px;}
.append-11 { padding-right: 440px;}
.append-12 { padding-right: 480px;}
.append-13 { padding-right: 520px;}
.append-14 { padding-right: 560px;}
.append-15 { padding-right: 600px;}
.append-16 { padding-right: 640px;}
.append-17 { padding-right: 680px;}
.append-18 { padding-right: 720px;}
.append-19 { padding-right: 760px;}
.append-20 { padding-right: 800px;}
.append-21 { padding-right: 840px;}
.append-22 { padding-right: 880px;}
.append-23 { padding-right: 920px;}
/* Add these to a column to prepend empty cols. */
.prepend-1 { padding-left: 40px;}
.prepend-2 { padding-left: 80px;}
.prepend-3 { padding-left: 120px;}
.prepend-4 { padding-left: 160px;}
.prepend-5 { padding-left: 200px;}
.prepend-6 { padding-left: 240px;}
.prepend-7 { padding-left: 280px;}
.prepend-8 { padding-left: 320px;}
.prepend-9 { padding-left: 360px;}
.prepend-10 { padding-left: 400px;}
.prepend-11 { padding-left: 440px;}
.prepend-12 { padding-left: 480px;}
.prepend-13 { padding-left: 520px;}
.prepend-14 { padding-left: 560px;}
.prepend-15 { padding-left: 600px;}
.prepend-16 { padding-left: 640px;}
.prepend-17 { padding-left: 680px;}
.prepend-18 { padding-left: 720px;}
.prepend-19 { padding-left: 760px;}
.prepend-20 { padding-left: 800px;}
.prepend-21 { padding-left: 840px;}
.prepend-22 { padding-left: 880px;}
.prepend-23 { padding-left: 920px;}
/* Border on right hand side of a column. */
div.border {
padding-right: 4px;
margin-right: 5px;
border-right: 1px solid #eee;
}
/* Border with more whitespace, spans one column. */
div.colborder {
padding-right: 24px;
margin-right: 25px;
border-right: 1px solid #eee;
}
/* Use these classes on an element to push it into the
next column, or to pull it into the previous column. */
.pull-1 { margin-left: -40px; }
.pull-2 { margin-left: -80px; }
.pull-3 { margin-left: -120px; }
.pull-4 { margin-left: -160px; }
.pull-5 { margin-left: -200px; }
.pull-6 { margin-left: -240px; }
.pull-7 { margin-left: -280px; }
.pull-8 { margin-left: -320px; }
.pull-9 { margin-left: -360px; }
.pull-10 { margin-left: -400px; }
.pull-11 { margin-left: -440px; }
.pull-12 { margin-left: -480px; }
.pull-13 { margin-left: -520px; }
.pull-14 { margin-left: -560px; }
.pull-15 { margin-left: -600px; }
.pull-16 { margin-left: -640px; }
.pull-17 { margin-left: -680px; }
.pull-18 { margin-left: -720px; }
.pull-19 { margin-left: -760px; }
.pull-20 { margin-left: -800px; }
.pull-21 { margin-left: -840px; }
.pull-22 { margin-left: -880px; }
.pull-23 { margin-left: -920px; }
.pull-24 { margin-left: -960px; }
.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float: left; position:relative;}
.push-1 { margin: 0 -40px 1.5em 40px; }
.push-2 { margin: 0 -80px 1.5em 80px; }
.push-3 { margin: 0 -120px 1.5em 120px; }
.push-4 { margin: 0 -160px 1.5em 160px; }
.push-5 { margin: 0 -200px 1.5em 200px; }
.push-6 { margin: 0 -240px 1.5em 240px; }
.push-7 { margin: 0 -280px 1.5em 280px; }
.push-8 { margin: 0 -320px 1.5em 320px; }
.push-9 { margin: 0 -360px 1.5em 360px; }
.push-10 { margin: 0 -400px 1.5em 400px; }
.push-11 { margin: 0 -440px 1.5em 440px; }
.push-12 { margin: 0 -480px 1.5em 480px; }
.push-13 { margin: 0 -520px 1.5em 520px; }
.push-14 { margin: 0 -560px 1.5em 560px; }
.push-15 { margin: 0 -600px 1.5em 600px; }
.push-16 { margin: 0 -640px 1.5em 640px; }
.push-17 { margin: 0 -680px 1.5em 680px; }
.push-18 { margin: 0 -720px 1.5em 720px; }
.push-19 { margin: 0 -760px 1.5em 760px; }
.push-20 { margin: 0 -800px 1.5em 800px; }
.push-21 { margin: 0 -840px 1.5em 840px; }
.push-22 { margin: 0 -880px 1.5em 880px; }
.push-23 { margin: 0 -920px 1.5em 920px; }
.push-24 { margin: 0 -960px 1.5em 960px; }
.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float: right; position:relative;}
/* Misc classes and elements
-------------------------------------------------------------- */
/* In case you need to add a gutter above/below an element */
.prepend-top {
margin-top:1.5em;
}
.append-bottom {
margin-bottom:1.5em;
}
/* Use a .box to create a padded box inside a column. */
.box {
padding: 1.5em;
margin-bottom: 1.5em;
background: #E5ECF9;
}
/* Use this to create a horizontal ruler across a column. */
hr {
background: #ddd;
color: #ddd;
clear: both;
float: none;
width: 100%;
height: .1em;
margin: 0 0 1.45em;
border: none;
}
hr.space {
background: #fff;
color: #fff;
visibility: hidden;
}
/* Clearing floats without extra markup
Based on How To Clear Floats Without Structural Markup by PiE
[http://www.positioniseverything.net/easyclearing.html] */
.clearfix:after, .container:after {
content: "\0020";
display: block;
height: 0;
clear: both;
visibility: hidden;
overflow:hidden;
}
.clearfix, .container {display: block;}
/* Regular clearing
apply to column that should drop below previous ones. */
.clear { clear:both; }

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

View File

@@ -0,0 +1,76 @@
/* --------------------------------------------------------------
ie.css
Contains every hack for Internet Explorer,
so that our core files stay sweet and nimble.
-------------------------------------------------------------- */
/* Make sure the layout is centered in IE5 */
body { text-align: center; }
.container { text-align: left; }
/* Fixes IE margin bugs */
* html .column, * html div.span-1, * html div.span-2,
* html div.span-3, * html div.span-4, * html div.span-5,
* html div.span-6, * html div.span-7, * html div.span-8,
* html div.span-9, * html div.span-10, * html div.span-11,
* html div.span-12, * html div.span-13, * html div.span-14,
* html div.span-15, * html div.span-16, * html div.span-17,
* html div.span-18, * html div.span-19, * html div.span-20,
* html div.span-21, * html div.span-22, * html div.span-23,
* html div.span-24 { display:inline; overflow-x: hidden; }
/* Elements
-------------------------------------------------------------- */
/* Fixes incorrect styling of legend in IE6. */
* html legend { margin:0px -8px 16px 0; padding:0; }
/* Fixes wrong line-height on sup/sub in IE. */
sup { vertical-align:text-top; }
sub { vertical-align:text-bottom; }
/* Fixes IE7 missing wrapping of code elements. */
html>body p code { *white-space: normal; }
/* IE 6&7 has problems with setting proper <hr> margins. */
hr { margin:-8px auto 11px; }
/* Explicitly set interpolation, allowing dynamically resized images to not look horrible */
img { -ms-interpolation-mode:bicubic; }
/* Clearing
-------------------------------------------------------------- */
/* Makes clearfix actually work in IE */
.clearfix, .container { display:inline-block; }
* html .clearfix,
* html .container { height:1%; }
/* Forms
-------------------------------------------------------------- */
/* Fixes padding on fieldset */
fieldset { padding-top:0; }
/* Makes classic textareas in IE 6 resemble other browsers */
textarea { overflow:auto; }
/* Fixes rule that IE 6 ignores */
input.text, input.title, textarea { background-color:#fff; border:1px solid #bbb; }
input.text:focus, input.title:focus { border-color:#666; }
input.text, input.title, textarea, select { margin:0.5em 0; }
input.checkbox, input.radio { position:relative; top:.25em; }
/* Fixes alignment of inline form elements */
form.inline div, form.inline p { vertical-align:middle; }
form.inline label { position:relative;top:-0.25em; }
form.inline input.checkbox, form.inline input.radio,
form.inline input.button, form.inline button {
margin:0.5em 0;
}
button, input.button { position:relative;top:0.25em; }

View File

@@ -0,0 +1,85 @@
/* --------------------------------------------------------------
print.css
* Gives you some sensible styles for printing pages.
* See Readme file in this directory for further instructions.
Some additions you'll want to make, customized to your markup:
#header, #footer, #navigation { display:none; }
-------------------------------------------------------------- */
body {
line-height: 1.5;
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
color:#000;
background: none;
font-size: 10pt;
}
/* Layout
-------------------------------------------------------------- */
.container {
background: none;
}
hr {
background:#ccc;
color:#ccc;
width:100%;
height:2px;
margin:2em 0;
padding:0;
border:none;
}
hr.space {
background: #fff;
color: #fff;
visibility: hidden;
}
/* Text
-------------------------------------------------------------- */
h1,h2,h3,h4,h5,h6 { font-family: "Helvetica Neue", Arial, "Lucida Grande", sans-serif; }
code { font:.9em "Courier New", Monaco, Courier, monospace; }
a img { border:none; }
p img.top { margin-top: 0; }
blockquote {
margin:1.5em;
padding:1em;
font-style:italic;
font-size:.9em;
}
.small { font-size: .9em; }
.large { font-size: 1.1em; }
.quiet { color: #999; }
.hide { display:none; }
/* Links
-------------------------------------------------------------- */
a:link, a:visited {
background: transparent;
font-weight:700;
text-decoration: underline;
}
a:link:after, a:visited:after {
content: " (" attr(href) ")";
font-size: 90%;
}
/* If you're having trouble printing relative links, uncomment and customize this:
(note: This is valid CSS3, but it still won't go through the W3C CSS Validator) */
/* a[href^="/"]:after {
content: " (http://www.yourdomain.com" attr(href) ") ";
} */

View File

@@ -0,0 +1,38 @@
/* --------------------------------------------------------------
reset.css
* Resets default browser CSS.
-------------------------------------------------------------- */
html, body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, code,
del, dfn, em, img, q, dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
font-family: inherit;
vertical-align: baseline;
}
body {
line-height: 1.5;
}
/* Tables still need 'cellspacing="0"' in the markup. */
table { border-collapse: separate; border-spacing: 0; }
caption, th, td { text-align: left; font-weight: normal; }
table, td, th { vertical-align: middle; }
/* Remove possible quote marks (") from <q>, <blockquote>. */
blockquote:before, blockquote:after, q:before, q:after { content: ""; }
blockquote, q { quotes: "" ""; }
/* Remove annoying border on linked images. */
a img { border: none; }

View File

@@ -0,0 +1,106 @@
/* --------------------------------------------------------------
typography.css
* Sets up some sensible default typography.
-------------------------------------------------------------- */
/* Default font settings.
The font-size percentage is of 16px. (0.75 * 16px = 12px) */
html { font-size:100.01%; }
body {
font-size: 75%;
color: #222;
background: #fff;
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
}
/* Headings
-------------------------------------------------------------- */
h1,h2,h3,h4,h5,h6 { font-weight: normal; color: #111; }
h1 { font-size: 3em; line-height: 1; margin-bottom: 0.5em; }
h2 { font-size: 2em; margin-bottom: 0.75em; }
h3 { font-size: 1.5em; line-height: 1; margin-bottom: 1em; }
h4 { font-size: 1.2em; line-height: 1.25; margin-bottom: 1.25em; }
h5 { font-size: 1em; font-weight: bold; margin-bottom: 1.5em; }
h6 { font-size: 1em; font-weight: bold; }
h1 img, h2 img, h3 img,
h4 img, h5 img, h6 img {
margin: 0;
}
/* Text elements
-------------------------------------------------------------- */
p { margin: 0 0 1.5em; }
p img.left { float: left; margin: 1.5em 1.5em 1.5em 0; padding: 0; }
p img.right { float: right; margin: 1.5em 0 1.5em 1.5em; }
a:focus,
a:hover { color: #000; }
a { color: #009; text-decoration: underline; }
blockquote { margin: 1.5em; color: #666; font-style: italic; }
strong { font-weight: bold; }
em,dfn { font-style: italic; }
dfn { font-weight: bold; }
sup, sub { line-height: 0; }
abbr,
acronym { border-bottom: 1px dotted #666; }
address { margin: 0 0 1.5em; font-style: italic; }
del { color:#666; }
pre { margin: 1.5em 0; white-space: pre; }
pre,code,tt { font: 1em 'andale mono', 'lucida console', monospace; line-height: 1.5; }
/* Lists
-------------------------------------------------------------- */
li ul,
li ol { margin: 0; }
ul, ol { margin: 0 1.5em 1.5em 0; padding-left: 3.333em; }
ul { list-style-type: disc; }
ol { list-style-type: decimal; }
dl { margin: 0 0 1.5em 0; }
dl dt { font-weight: bold; }
dd { margin-left: 1.5em;}
/* Tables
-------------------------------------------------------------- */
table { margin-bottom: 1.4em; width:100%; }
th { font-weight: bold; }
thead th { background: #c3d9ff; }
th,td,caption { padding: 4px 10px 4px 5px; }
tr.even td { background: #e5ecf9; }
tfoot { font-style: italic; }
caption { background: #eee; }
/* Misc classes
-------------------------------------------------------------- */
.small { font-size: .8em; margin-bottom: 1.875em; line-height: 1.875em; }
.large { font-size: 1.2em; line-height: 2.5em; margin-bottom: 1.25em; }
.hide { display: none; }
.quiet { color: #666; }
.loud { color: #000; }
.highlight { background:#ff0; }
.added { background:#060; color: #fff; }
.removed { background:#900; color: #fff; }
.first { margin-left:0; padding-left:0; }
.last { margin-right:0; padding-right:0; }
.top { margin-top:0; padding-top:0; }
.bottom { margin-bottom:0; padding-bottom:0; }

View File

@@ -0,0 +1,59 @@
a,a:visited,a:link,a:active {
color: #59924B;
background-color: transparent;
text-decoration: none;
font-weight: bold;
}
a:hover {
color: white;
background-color: #65a242;
text-decoration: none;
font-weight: bold;
}
input[type=submit] {
color: #fff;
background: #fff url(../images/btn.bg.gif) 0 0 repeat-x;
border-style: none;
margin:0.4em 0.4em 0.4em 0;
height: 1.8em;
}
input[type=submit]:hover {
color: yellow;
background: #fff url(../images/btn.bg.gif) 0 0 repeat-x;
border-style: none;
}
label {
margin-right: 0.5em;
}
.summary {
width: 100%;
border: 1px solid #414f23;
border-collapse: collapse;
}
.summary thead th {
border-left: 1px solid #414f23;
background: #fff url(../images/th.bg.gif) 0 100% repeat-x;
border-bottom: 1px solid #414f23;
padding: 6px;
text-align: left;
font-size: small;
}
.summary tbody td {
border-left: 1px solid #9cac7c;
padding: 4px;
border-bottom: 1px solid #9cac7c;
font-size: 8pt;
}
.label {
font-weight: bold;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -0,0 +1,489 @@
/*
* jQuery UI CSS Framework
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
*/
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; }
/* required comment for clearfix to work in Opera \*/
* html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; }
/* end clearfix */
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/*
* jQuery UI CSS Framework
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=10px&bgColorHeader=3a8104&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=33&borderColorHeader=3f7506&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=285c00&bgTextureContent=05_inset_soft.png&bgImgOpacityContent=10&borderColorContent=72b42d&fcContent=ffffff&iconColorContent=72b42d&bgColorDefault=4ca20b&bgTextureDefault=03_highlight_soft.png&bgImgOpacityDefault=60&borderColorDefault=45930b&fcDefault=ffffff&iconColorDefault=ffffff&bgColorHover=4eb305&bgTextureHover=03_highlight_soft.png&bgImgOpacityHover=50&borderColorHover=8bd83b&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=285c00&bgTextureActive=04_highlight_hard.png&bgImgOpacityActive=30&borderColorActive=72b42d&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=fbf5d0&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=f9dd34&fcHighlight=363636&iconColorHighlight=4eb305&bgColorError=ffdc2e&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=95&borderColorError=fad000&fcError=2b2b2b&iconColorError=cd0a0a&bgColorOverlay=444444&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=15&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=07_diagonals_small.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=0px&offsetTopShadow=4px&offsetLeftShadow=4px&cornerRadiusShadow=4px
*/
/* Component containers
----------------------------------*/
.ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #72b42d; background: #285c00 url(images/ui-bg_inset-soft_10_285c00_1x100.png) 50% bottom repeat-x; color: #ffffff; }
.ui-widget-content a { color: #ffffff; }
.ui-widget-header { border: 1px solid #3f7506; background: #3a8104 url(images/ui-bg_highlight-soft_33_3a8104_1x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
.ui-widget-header a { color: #ffffff; }
/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #45930b; background: #4ca20b url(images/ui-bg_highlight-soft_60_4ca20b_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #ffffff; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #8bd83b; background: #4eb305 url(images/ui-bg_highlight-soft_50_4eb305_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; }
.ui-state-hover a, .ui-state-hover a:hover { color: #ffffff; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #72b42d; background: #285c00 url(images/ui-bg_highlight-hard_30_285c00_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #ffffff; text-decoration: none; }
.ui-widget :active { outline: none; }
/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #f9dd34; background: #fbf5d0 url(images/ui-bg_glass_55_fbf5d0_1x400.png) 50% 50% repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #fad000; background: #ffdc2e url(images/ui-bg_diagonals-thick_95_ffdc2e_40x40.png) 50% 50% repeat; color: #2b2b2b; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #2b2b2b; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #2b2b2b; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_72b42d_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_72b42d_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_4eb305_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-tl { -moz-border-radius-topleft: 10px; -webkit-border-top-left-radius: 10px; border-top-left-radius: 10px; }
.ui-corner-tr { -moz-border-radius-topright: 10px; -webkit-border-top-right-radius: 10px; border-top-right-radius: 10px; }
.ui-corner-bl { -moz-border-radius-bottomleft: 10px; -webkit-border-bottom-left-radius: 10px; border-bottom-left-radius: 10px; }
.ui-corner-br { -moz-border-radius-bottomright: 10px; -webkit-border-bottom-right-radius: 10px; border-bottom-right-radius: 10px; }
.ui-corner-top { -moz-border-radius-topleft: 10px; -webkit-border-top-left-radius: 10px; border-top-left-radius: 10px; -moz-border-radius-topright: 10px; -webkit-border-top-right-radius: 10px; border-top-right-radius: 10px; }
.ui-corner-bottom { -moz-border-radius-bottomleft: 10px; -webkit-border-bottom-left-radius: 10px; border-bottom-left-radius: 10px; -moz-border-radius-bottomright: 10px; -webkit-border-bottom-right-radius: 10px; border-bottom-right-radius: 10px; }
.ui-corner-right { -moz-border-radius-topright: 10px; -webkit-border-top-right-radius: 10px; border-top-right-radius: 10px; -moz-border-radius-bottomright: 10px; -webkit-border-bottom-right-radius: 10px; border-bottom-right-radius: 10px; }
.ui-corner-left { -moz-border-radius-topleft: 10px; -webkit-border-top-left-radius: 10px; border-top-left-radius: 10px; -moz-border-radius-bottomleft: 10px; -webkit-border-bottom-left-radius: 10px; border-bottom-left-radius: 10px; }
.ui-corner-all { -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; }
/* Overlays */
.ui-widget-overlay { background: #444444 url(images/ui-bg_diagonals-thick_15_444444_40x40.png) 50% 50% repeat; opacity: .30;filter:Alpha(Opacity=30); }
.ui-widget-shadow { margin: 4px 0 0 4px; padding: 0px; background: #aaaaaa url(images/ui-bg_diagonals-small_0_aaaaaa_40x40.png) 50% 50% repeat; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }/* Resizable
----------------------------------*/
.ui-resizable { position: relative;}
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Selectable
----------------------------------*/
.ui-selectable-helper { border:1px dotted black }
/* Accordion
----------------------------------*/
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
.ui-accordion .ui-accordion-li-fix { display: inline; }
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
/* IE7-/Win - Fix extra vertical space in lists */
.ui-accordion a { zoom: 1; }
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
.ui-accordion .ui-accordion-content-active { display: block; }/* Autocomplete
----------------------------------*/
.ui-autocomplete { position: absolute; cursor: default; }
.ui-autocomplete-loading { background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; }
/* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
/* Menu
----------------------------------*/
.ui-menu {
list-style:none;
padding: 2px;
margin: 0;
display:block;
}
.ui-menu .ui-menu {
margin-top: -3px;
}
.ui-menu .ui-menu-item {
margin:0;
padding: 0;
zoom: 1;
float: left;
clear: left;
width: 100%;
}
.ui-menu .ui-menu-item a {
text-decoration:none;
display:block;
padding:.2em .4em;
line-height:1.5;
zoom:1;
}
.ui-menu .ui-menu-item a.ui-state-hover,
.ui-menu .ui-menu-item a.ui-state-active {
font-weight: normal;
margin: -1px;
}
/* Button
----------------------------------*/
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
.ui-button-icons-only { width: 3.4em; }
button.ui-button-icons-only { width: 3.7em; }
/*button text element */
.ui-button .ui-button-text { display: block; line-height: 1.4; }
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
.ui-button-text-icon .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
/* no icon support for input elements, provide padding by default */
input.ui-button { padding: .4em 1em; }
/*button icon element(s) */
.ui-button-icon-only .ui-icon, .ui-button-text-icon .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
.ui-button-text-icon .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
/*button sets*/
.ui-buttonset { margin-right: 7px; }
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
/* workarounds */
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
/* Dialog
----------------------------------*/
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; }
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
.ui-draggable .ui-dialog-titlebar { cursor: move; }
/* Slider
----------------------------------*/
.ui-slider { position: relative; text-align: left; }
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
.ui-slider-horizontal { height: .8em; }
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
.ui-slider-vertical { width: .8em; height: 100px; }
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
----------------------------------*/
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
.ui-tabs .ui-tabs-hide { display: none !important; }
/* Datepicker
----------------------------------*/
.ui-datepicker { width: 17em; padding: .2em .2em 0; }
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; }
/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
display: none; /*sorry for IE5*/
display/**/: block; /*sorry for IE5*/
position: absolute; /*must have*/
z-index: -1; /*must have*/
filter: mask(); /*must have*/
top: -4px; /*must have*/
left: -4px; /*must have*/
width: 200px; /*must have*/
height: 200px; /*must have*/
}/* Progressbar
----------------------------------*/
.ui-progressbar { height:2em; text-align: left; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }

View File

@@ -0,0 +1,83 @@
package org.springframework.webflow.samples.booking;
import org.easymock.EasyMock;
import org.springframework.faces.model.converter.FacesConversionService;
import org.springframework.webflow.config.FlowDefinitionResource;
import org.springframework.webflow.config.FlowDefinitionResourceFactory;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.test.MockExternalContext;
import org.springframework.webflow.test.MockFlowBuilderContext;
import org.springframework.webflow.test.execution.AbstractXmlFlowExecutionTests;
public class BookingFlowExecutionTests extends AbstractXmlFlowExecutionTests {
private BookingService bookingService;
protected void setUp() {
bookingService = EasyMock.createMock(BookingService.class);
}
@Override
protected FlowDefinitionResource getResource(FlowDefinitionResourceFactory resourceFactory) {
return resourceFactory.createFileResource("src/main/webapp/WEB-INF/flows/booking/booking-flow.xml");
}
@Override
protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext) {
builderContext.registerBean("bookingService", bookingService);
builderContext.getFlowBuilderServices().setConversionService(new FacesConversionService());
}
public void testStartBookingFlow() {
Booking booking = createTestBooking();
EasyMock.expect(bookingService.createBooking(1L, "keith")).andReturn(booking);
EasyMock.replay(bookingService);
MutableAttributeMap input = new LocalAttributeMap();
input.put("hotelId", "1");
MockExternalContext context = new MockExternalContext();
context.setCurrentUser("keith");
startFlow(input, context);
assertCurrentStateEquals("enterBookingDetails");
assertResponseWrittenEquals("enterBookingDetails", context);
assertTrue(getRequiredFlowAttribute("booking") instanceof Booking);
EasyMock.verify(bookingService);
}
public void testEnterBookingDetails_Proceed() {
setCurrentState("enterBookingDetails");
getFlowScope().put("booking", createTestBooking());
MockExternalContext context = new MockExternalContext();
context.setEventId("proceed");
resumeFlow(context);
assertCurrentStateEquals("reviewBooking");
assertResponseWrittenEquals("reviewBooking", context);
}
public void testReviewBooking_Confirm() {
setCurrentState("reviewBooking");
getFlowScope().put("booking", createTestBooking());
MockExternalContext context = new MockExternalContext();
context.setEventId("confirm");
resumeFlow(context);
assertFlowExecutionEnded();
assertFlowExecutionOutcomeEquals("bookingConfirmed");
}
private Booking createTestBooking() {
Hotel hotel = new Hotel();
hotel.setId(1L);
hotel.setName("Jameson Inn");
User user = new User("keith", "pass", "Keith Donald");
Booking booking = new Booking(hotel, user);
return booking;
}
}

View File

@@ -0,0 +1,119 @@
package org.springframework.webflow.samples.booking;
import java.util.ArrayList;
import java.util.List;
import javax.faces.model.DataModel;
import org.easymock.EasyMock;
import org.springframework.binding.mapping.Mapper;
import org.springframework.binding.mapping.MappingResults;
import org.springframework.faces.model.converter.FacesConversionService;
import org.springframework.webflow.config.FlowDefinitionResource;
import org.springframework.webflow.config.FlowDefinitionResourceFactory;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.engine.EndState;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.test.MockExternalContext;
import org.springframework.webflow.test.MockFlowBuilderContext;
import org.springframework.webflow.test.execution.AbstractXmlFlowExecutionTests;
public class MainFlowExecutionTests extends AbstractXmlFlowExecutionTests {
private BookingService bookingService;
protected void setUp() {
bookingService = EasyMock.createMock(BookingService.class);
}
@Override
protected FlowDefinitionResource getResource(FlowDefinitionResourceFactory resourceFactory) {
return resourceFactory.createFileResource("src/main/webapp/WEB-INF/flows/main/main-flow.xml");
}
@Override
protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext) {
builderContext.registerBean("bookingService", bookingService);
builderContext.getFlowBuilderServices().setConversionService(new FacesConversionService());
}
public void testStartMainFlow() {
List<Booking> bookings = new ArrayList<Booking>();
bookings.add(new Booking(new Hotel(), new User("keith", "password", "Keith Donald")));
EasyMock.expect(bookingService.findBookings("keith")).andReturn(bookings);
EasyMock.replay(bookingService);
MockExternalContext context = new MockExternalContext();
context.setCurrentUser("keith");
startFlow(context);
assertCurrentStateEquals("enterSearchCriteria");
assertResponseWrittenEquals("enterSearchCriteria", context);
assertTrue(getRequiredFlowAttribute("searchCriteria") instanceof SearchCriteria);
assertTrue(getRequiredViewAttribute("bookings") instanceof DataModel);
EasyMock.verify(bookingService);
}
public void testSearchHotels() {
setCurrentState("enterSearchCriteria");
SearchCriteria criteria = new SearchCriteria();
criteria.setSearchString("Jameson");
getFlowScope().put("searchCriteria", criteria);
MockExternalContext context = new MockExternalContext();
context.setEventId("search");
resumeFlow(context);
assertCurrentStateEquals("reviewHotels");
assertResponseWrittenEquals("reviewHotels", context);
assertTrue(getRequiredViewAttribute("hotels") instanceof HotelLazyDataModel);
}
public void testSelectHotel() {
setCurrentState("reviewHotels");
List<Hotel> hotels = new ArrayList<Hotel>();
Hotel hotel = new Hotel();
hotel.setId(1L);
hotel.setName("Jameson Inn");
hotels.add(hotel);
HotelLazyDataModel dataModel = new HotelLazyDataModel(null, null);
dataModel.setSelected(hotel);
getViewScope().put("hotels", dataModel);
MockExternalContext context = new MockExternalContext();
context.setEventId("select");
resumeFlow(context);
assertCurrentStateEquals("reviewHotel");
assertNull(getFlowAttribute("hotels"));
assertSame(hotel, getFlowAttribute("hotel"));
}
public void testBookHotel() {
setCurrentState("reviewHotel");
Hotel hotel = new Hotel();
hotel.setId(1L);
hotel.setName("Jameson Inn");
getFlowScope().put("hotel", hotel);
Flow mockBookingFlow = new Flow("booking");
mockBookingFlow.setInputMapper(new Mapper() {
public MappingResults map(Object source, Object target) {
assertEquals(new Long(1), ((AttributeMap) source).get("hotelId"));
return null;
}
});
new EndState(mockBookingFlow, "bookingConfirmed");
getFlowDefinitionRegistry().registerFlowDefinition(mockBookingFlow);
MockExternalContext context = new MockExternalContext();
context.setEventId("book");
resumeFlow(context);
assertFlowExecutionEnded();
assertFlowExecutionOutcomeEquals("finish");
}
}

View File