removed account chooser java implementation
|
@ -1,10 +0,0 @@
|
|||
local-values.conf
|
||||
target
|
||||
*~
|
||||
bin
|
||||
*.idea
|
||||
*.iml
|
||||
*.eml
|
||||
.project
|
||||
.settings
|
||||
.classpath
|
|
@ -1,61 +0,0 @@
|
|||
# Account Choooser UI Application
|
||||
|
||||
## Overview
|
||||
|
||||
This is Web application created in response to [Issue #39] to permit the Client AuthenticationFilter to speak to multiple OpenID Connect Servers. The protocol between the Clinent and the Account Chooser UI application is documented the README.md of the openid-connect-client submodule.
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
Configure AccountChooserController via configuring a AccountChooserConfig bean in the spring-servlet.xml like so:
|
||||
|
||||
<bean name="AccountChooserConfig" class="org.mitre.account_chooser.AccountChooserConfig">
|
||||
<property name="issuers">
|
||||
<map>
|
||||
<entry key="http://sever.example.com:8080/openid-connect-server">
|
||||
<bean class="org.mitre.account_chooser.OIDCServer">
|
||||
<property name="name" value="Example Server" />
|
||||
</bean>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
<property name="validClientIds" value="FGWEUIASJK, IUYTTYEV, GFHDSFYD" />
|
||||
</bean>
|
||||
|
||||
|
||||
The keys must match those found in the OpenIdConnectAuthenticationFilter's configuration like so:
|
||||
|
||||
<bean id="openIdConnectAuthenticationFilter"
|
||||
class="org.mitre.openid.connect.client.OpenIdConnectAuthenticationFilter">
|
||||
<property name="errorRedirectURI" value="/login.jsp?authfail=openid" />
|
||||
<property name="authenticationManager" ref="authenticationManager" />
|
||||
<property name="accountChooserURI"
|
||||
value="http://sever.example.com:8080/account-chooser" />
|
||||
<property name="accountChooserClientID" value="FGWEUIASJK" />
|
||||
<property name="oidcServerConfigs">
|
||||
<map>
|
||||
<entry key="http://sever.example.com:8080/Fopenid-connect-server">
|
||||
<bean class="org.mitre.openid.connect.client.OIDCServerConfiguration">
|
||||
<property name="authorizationEndpointURI"
|
||||
value="http://sever.example.com:8080/openid-connect-server/oauth/authorize" />
|
||||
<property name="tokenEndpointURI"
|
||||
value="http://sever.example.com:8080/openid-connect-server/oauth/token" />
|
||||
<property name="checkIDEndpointURI"
|
||||
value="http://sever.example.com:8080/openid-connect-server/checkid" />
|
||||
<property name="clientId"
|
||||
value="someClientId" />
|
||||
<property name="clientSecret" value="someClientSecret" />
|
||||
</bean>
|
||||
</entry>
|
||||
. . .
|
||||
|
||||
|
||||
## Test the Default Configuration
|
||||
|
||||
To test the default config, deploy to a servlet container, and request:
|
||||
|
||||
http://localhost:8080/account-chooser/?redirect_uri=http://www.google.com&client_id=FGWEUIASJK
|
||||
|
||||
Click **Submit** or **Cancel**, and Google will open. Study the URL parameters of each.
|
||||
|
||||
[Issue #39]: http://github.com/jricher/OpenID-Connect-Java-Spring-Server/issues/39 "Issue #39 -- Multiple Point Client"
|
|
@ -1 +0,0 @@
|
|||
protocol.md
|
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 48 KiB |
|
@ -1,127 +0,0 @@
|
|||
# OpenID Connect Client - Account Chooser UI Application Protocol
|
||||
|
||||
## Overview
|
||||
|
||||
This Client - Account Chooser Protocol proposed in response to [Issue #39].
|
||||
|
||||
|
||||
#### Authorization when using Account Chooser Code Flow
|
||||
|
||||
The Authorization when using Account Chooser Code Flow goes through the following steps:
|
||||
|
||||
1. Client prepares an Account Chooser Request containing the desired request parameters.
|
||||
2. Client sends a request to the Account Chooser.
|
||||
3. Account Chooser presents a selection of OpenID Connect (OIDC) Servers from which the End-User must select from.
|
||||
4. End-User selects an OIDC.
|
||||
5. Account Chooser Sends the End-User back to the Client with key value of the OIDC End-User selected.
|
||||
6. The Client begins the Authorization flow described in [Authorization Code Flow][OpenID Connect Standard] of the [OpenID Connect Standard].
|
||||
|
||||
#### Account Chooser Request
|
||||
|
||||
When the End-User wishes to access a Protected Resource and the End-User Authorization has not yet been obtained, the Client will redirect the End-User to Account Chooser.
|
||||
|
||||
Account Chooser MUST support the use of the HTTP "GET" and "POST" methods defined in RFC 2616 [RFC2616].
|
||||
|
||||
Clients MAY use the HTTP "GET" or "POST" method to send the Account Chooser Request to the Account Chooser. If using the HTTP "GET" method, the request parameters are serialized using URI query string serialization. If using the HTTP "POST" method, the request parameters are serialized using form serialization.
|
||||
|
||||
#### Client Prepares an Account Chooser Request
|
||||
|
||||
The Client prepares an Account Chooser Request to the Account Chooser with the request parameters using the HTTP "GET" or "POST" method.
|
||||
|
||||
The required Account Chooser Request parameters are as follows:
|
||||
|
||||
* redirect_uri - REQUIRED. A redirection URI where the response will be sent.
|
||||
* client_id - REQUIRED. An identifier used to identify the Client to the Account Chooser UI application.
|
||||
|
||||
There is one method to construct and send the request to the Account Chooser:
|
||||
|
||||
* Simple Request Method
|
||||
|
||||
#### Simple Request Method
|
||||
|
||||
The Client prepares an Account Chooser Request to the Account Chooser using the appropriate parameters. If using the HTTP "GET" method, the request parameters are serialized using URI query string serialization. If using the HTTP "POST" method, the request parameters are serialized using form serialization.
|
||||
|
||||
The following is a non-normative example of an Account Chooser Request URL. Line wraps are for display purposes only.
|
||||
|
||||
http://server.example.com/chooser?
|
||||
redirect_uri=https%3A%2F%2Fclient.example.com%2Fopenid_connect_login
|
||||
&client_id=FGWEUIASJK
|
||||
|
||||
#### Client sends a request to the Account Chooser
|
||||
|
||||
Having constructed the Account Chooser Request, the Client sends it to the Account Chooser. This MAY happen via redirect, hyperlinking, or any other means of directing the User-Agent to the Account Chooser URL.
|
||||
|
||||
Following is a non-normative example using HTTP redirect. Line wraps are for display purposes only.
|
||||
|
||||
HTTP/1.1 302 Found
|
||||
Location: https://server.example.com/chooser?
|
||||
redirect_uri=https%3A%2F%2Fclient.example.com%2Fopenid_connect_login
|
||||
&client_id=FGWEUIASJK
|
||||
|
||||
#### Account Chooser Sends the End-User back to the Client
|
||||
|
||||
After the End-User has select an OpenID Connect Server, the Client issues an Account Chooser Response and delivers it to the Client by adding the response parameters to redirect_uri specified in the Account Choose Request using the "application/x-www-form-urlencoded" format.
|
||||
|
||||
The following response parameters are included:
|
||||
|
||||
* issuer - REQUIRED. The [Issuer Identifier] describing the selected account.
|
||||
|
||||
The following is non-normative example of a responses. Line wraps are for display purposes only.
|
||||
|
||||
HTTP/1.1 302 Found
|
||||
Location: https://client.example.com/openid_connect_login?
|
||||
issuer=http%3A%2F%2Fsever.example.com%3A8080%2Fopenid-connect-server
|
||||
|
||||
A sequence diagram of a successful interaction would be:
|
||||
|
||||

|
||||
|
||||
#### The Client ID is not Supported by the Account Chooser Application
|
||||
|
||||
If the Client sends a Client identifier that is not supported by the Account Chooser UI application, the Account Chooser MUST return an error response back to the End-User by issuing a HTTP Response with a message concerning the error. The Account Chooser MUST NOT directly return to the Client via the redirection URI specified in the Account Chooser Request automatically.
|
||||
|
||||
The error message the Account Chooser presents to the End-User MAY give the End-User the means to return the indication of an error to the Client, e.g., via the End-User clicking on a HTML link built from adding the error parameters to the query component of the redirection URI. No other parameters SHOULD be returned.
|
||||
|
||||
The error response parameters are the following:
|
||||
|
||||
* error - REQUIRED. The error code.
|
||||
* error_description - OPTIONAL. A human-readable UTF-8 encoded text description of the error.
|
||||
|
||||
The response parameters are added to the query component of the redirection URI specified in the Account Chooser Request.
|
||||
|
||||
The following is a non-normative example. Line wraps after the second line are for the display purposes only.
|
||||
|
||||
https://client.example.com/openid_connect_login?
|
||||
error=not_supported
|
||||
&error_description=The%20client_id%20is%20not%20supported%20by%20the%20AccountChooser%20UI%20application.
|
||||
|
||||
A sequence diagram of the interaction where the Account Chooser was not configured to support the Client would be:
|
||||
|
||||

|
||||
|
||||
#### End-User refuses to select an Account
|
||||
|
||||
If the End-User refuses to select an Account, the Account Chooser MUST return an error response. The Account Chooser returns the Client via the redirection URI specified in the Account Chooser Request with the appropriate error parameters. No other parameters SHOULD be returned.
|
||||
|
||||
The error response parameters are the following:
|
||||
|
||||
* error - REQUIRED. The error code.
|
||||
* error_description - OPTIONAL. A human-readable UTF-8 encoded text description of the error.
|
||||
|
||||
The response parameters are added to the query component of the redirection URI specified in the Account Chooser Request.
|
||||
|
||||
The following is a non-normative example. Line wraps after the second line are for the display purposes only.
|
||||
|
||||
HTTP/1.1 302 Found
|
||||
Location: https://client.example.com/openid_connect_login?
|
||||
error=end_user_cancelled
|
||||
&error_description=The%20end%2Duser%20refused%20to%20select%20an%20Account.
|
||||
|
||||
A sequence diagram of an interaction where the End-User refused to select an Account would be:
|
||||
|
||||

|
||||
|
||||
[OpenID Connect Standard]: http://openid.net/specs/openid-connect-standard-1_0.html "OpenID Connect Standard 1.0"
|
||||
[OpenID Connect Standard]: http://openid.net/specs/openid-connect-standard-1_0.html#code_flow "Authorization Code Flow, OpenID Connect Standard"
|
||||
[Issuer Identifier]: http://openid.net/specs/openid-connect-messages-1_0.html#issuer_identifier "Issuer Identifier"
|
||||
[Issue #39]: http://github.com/jricher/OpenID-Connect-Java-Spring-Server/issues/39 "Issue #39 -- Multiple Point Client"
|
Before Width: | Height: | Size: 33 KiB |
|
@ -1,50 +0,0 @@
|
|||
Text used to create sequence diagrams @ http://www.websequencediagrams.com/
|
||||
|
||||
|
||||
A Successful Client and Account Chooser Interaction
|
||||
|
||||
Client->End-User Browser: HTTP-Redirect\n to Account\n Chooser URL\nwith redirect_uri,\n and client_id\n parameters
|
||||
activate End-User Browser
|
||||
End-User Browser->Account Chooser:HTTP Get/Put\n Request containing\n redirect_uri\n and client_id
|
||||
note right of "Account Chooser": Client Id\n is verified as\n supported, and the\n End-User selects\n an Account
|
||||
deactivate End-User Browser
|
||||
activate Account Chooser
|
||||
Account Chooser->End-User Browser:HTTP-Redirect to \nAccount Chooser URL\n with issuer parameters
|
||||
activate End-User Browser
|
||||
deactivate Account Chooser
|
||||
End-User Browser->Client: HTTP Get\n Request containing the\n issuer parameter
|
||||
activate Client
|
||||
deactivate End-User Browser
|
||||
|
||||
|
||||
The Client ID is not Supported by the Account Chooser Application
|
||||
|
||||
Client->End-User Browser: HTTP-Redirect to\n Account Chooser URL\n w/ redirect_uri,\n and client_id parameters
|
||||
activate End-User Browser
|
||||
End-User Browser->Account Chooser:HTTP Get/Put\n Request containing\n redirect_uri and client_id
|
||||
note right of "Account Chooser": Client Id is\nnot supported.\nSo, an error must\nbe returned.
|
||||
activate Account Chooser
|
||||
deactivate End-User Browser
|
||||
Account Chooser->End-User Browser:Returns an\nHTTP Response\ncontaining an\nerror message.
|
||||
deactivate Account Chooser
|
||||
note right of "End-User Browser":The End-User is presented\nan error message\nthus ending the interaction.\n\nOptionally, the message\nMAY contain a HTML link\nto return the End-User\nback to the Client with\nan error and error description\nadded to the query component\nof the redirect_uri.
|
||||
activate End-User Browser
|
||||
End-User Browser->Client: If the End-User\nis presented and clicks\non a HTML link,\na HTTP "GET"\n Request containing the\nerror, and error_description\nparameter
|
||||
activate Client
|
||||
deactivate Account Chooser
|
||||
|
||||
|
||||
End-User Cancels Account Selection
|
||||
|
||||
Client->End-User Browser: HTTP-Redirect to\n Account Chooser URL\nwith redirect_uri,\nand client_id parameters
|
||||
activate End-User Browser
|
||||
End-User Browser->Account Chooser:HTTP Get/Put\n Request containing\nredirect_uri and client_id
|
||||
note right of "Account Chooser": End-User refuses\nto select an\naccount via\ncancelling.
|
||||
deactivate End-User Browser
|
||||
activate Account Chooser
|
||||
Account Chooser->End-User Browser:HTTP-Redirect\n to Account Chooser\n URL with error,\nand error_description\nparameters
|
||||
activate End-User Browser
|
||||
deactivate Account Chooser
|
||||
End-User Browser->Client: HTTP Get Request\ncontaining the error,\nand error_description\nparameter
|
||||
activate Client
|
||||
deactivate End-User Browser
|
|
@ -1,103 +0,0 @@
|
|||
<?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.mitre</groupId>
|
||||
<artifactId>account-chooser</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>Account Chooser UI</name>
|
||||
<packaging>war</packaging>
|
||||
<parent>
|
||||
<groupId>org.mitre</groupId>
|
||||
<artifactId>openid-connect-parent</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
<description>A Spring MVC Web Application written in response to Issue #39.
|
||||
</description>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${java-version}</source>
|
||||
<target>${java-version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>prepare-war</id>
|
||||
<phase>prepare-package</phase>
|
||||
<goals>
|
||||
<goal>exploded</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<warName>account-chooser</warName>
|
||||
<useCache>true</useCache>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>install</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>sources</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<junitArtifactName>junit:junit</junitArtifactName>
|
||||
<excludes>
|
||||
<exclude>**/*_Roo_*</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>tomcat-maven-plugin</artifactId>
|
||||
<version>1.0-beta-1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>cobertura-maven-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<configuration>
|
||||
<formats>
|
||||
<format>xml</format>
|
||||
</formats>
|
||||
<instrumentation>
|
||||
<ignores>
|
||||
<ignore>org.apache.log4j.*</ignore>
|
||||
</ignores>
|
||||
<excludes>
|
||||
</excludes>
|
||||
</instrumentation>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>cobertura</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>cobertura</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -1,49 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright 2012 The MITRE Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
package org.mitre.account_chooser;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Used to the configure AccountChooserController
|
||||
*
|
||||
* @author nemonik
|
||||
*
|
||||
*/
|
||||
public class AccountChooserConfig {
|
||||
|
||||
private String[] validClientIds;
|
||||
|
||||
private Map<String, ? extends OIDCServer> issuers = new HashMap<String, OIDCServer>();
|
||||
|
||||
public Map<String, ? extends OIDCServer> getIssuers() {
|
||||
return issuers;
|
||||
}
|
||||
|
||||
public String[] getValidClientIds() {
|
||||
return validClientIds;
|
||||
}
|
||||
|
||||
public void setIssuers(Map<String, ? extends OIDCServer> issuers) {
|
||||
this.issuers = issuers;
|
||||
}
|
||||
|
||||
public void setValidClientIds(String[] validClientIds) {
|
||||
|
||||
this.validClientIds = validClientIds;
|
||||
}
|
||||
}
|
|
@ -1,203 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright 2012 The MITRE Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
package org.mitre.account_chooser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Account Chooser UI application
|
||||
*
|
||||
* @author nemonik
|
||||
*
|
||||
* See README.md for configuration.
|
||||
*
|
||||
*/
|
||||
@Controller
|
||||
public class AccountChooserController {
|
||||
|
||||
/**
|
||||
* Return the URL w/ GET parameters
|
||||
*
|
||||
* @param baseURI
|
||||
* A String containing the protocol, server address, path, and
|
||||
* program as per "http://server/path/program"
|
||||
* @param queryStringFields
|
||||
* A map where each key is the field name and the associated
|
||||
* key's value is the field value used to populate the URL's
|
||||
* query string
|
||||
* @return A String representing the URL in form of
|
||||
* http://server/path/program?query_string from the messaged
|
||||
* parameters.
|
||||
*/
|
||||
public static String buildURL(String baseURI,
|
||||
Map<String, String> queryStringFields) {
|
||||
|
||||
StringBuilder URLBuilder = new StringBuilder(baseURI);
|
||||
|
||||
char appendChar = '?';
|
||||
|
||||
for (Map.Entry<String, String> param : queryStringFields.entrySet()) {
|
||||
try {
|
||||
URLBuilder.append(appendChar).append(param.getKey())
|
||||
.append('=')
|
||||
.append(URLEncoder.encode(param.getValue(), "UTF-8"));
|
||||
} catch (UnsupportedEncodingException uee) {
|
||||
throw new IllegalStateException(uee);
|
||||
}
|
||||
appendChar = '&';
|
||||
}
|
||||
|
||||
return URLBuilder.toString();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
AccountChooserConfig accountChooserConfig;
|
||||
|
||||
private static Logger logger = LoggerFactory
|
||||
.getLogger(AccountChooserController.class);
|
||||
|
||||
/**
|
||||
* Handles request to choose an Account
|
||||
*
|
||||
* @param redirectUri
|
||||
* A redirection URI where the response will be sent
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
@RequestMapping(value = "/", method = { RequestMethod.GET,
|
||||
RequestMethod.POST })
|
||||
public ModelAndView handleChooserRequest(
|
||||
@RequestParam("redirect_uri") String redirectUri,
|
||||
@RequestParam("client_id") String clientId,
|
||||
HttpServletResponse response) throws IOException {
|
||||
|
||||
ModelAndView modelAndView = null;
|
||||
|
||||
if (Arrays.asList(accountChooserConfig.getValidClientIds()).contains(
|
||||
clientId)) {
|
||||
|
||||
// client_id supported
|
||||
|
||||
modelAndView = new ModelAndView("chooser");
|
||||
modelAndView
|
||||
.addObject("issuers", accountChooserConfig.getIssuers());
|
||||
modelAndView.addObject("redirect_uri", redirectUri);
|
||||
modelAndView.addObject("client_id", clientId);
|
||||
|
||||
} else {
|
||||
|
||||
// client_id not supported
|
||||
|
||||
Map<String, String> urlVariables = new HashMap<String, String>();
|
||||
|
||||
urlVariables.put("error", "not_supported");
|
||||
urlVariables
|
||||
.put("error_description",
|
||||
"The client_id is not supported by the Account Chooser UI application.");
|
||||
|
||||
modelAndView = new ModelAndView("error");
|
||||
|
||||
modelAndView.addObject("error", urlVariables.get("error"));
|
||||
modelAndView.addObject("error_description",
|
||||
urlVariables.get("error_description"));
|
||||
modelAndView.addObject("client_uri", AccountChooserController
|
||||
.buildURL(redirectUri, urlVariables));
|
||||
|
||||
}
|
||||
|
||||
return modelAndView;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles form submits
|
||||
*
|
||||
* @param redirectUri
|
||||
* A redirection URI where the response will be sent.
|
||||
* @param alias
|
||||
* The OIDC alias selected.
|
||||
* @param response
|
||||
* Provide the HTTP-specific functionality for sending a
|
||||
* response. In this case a redirect to redirect the End-User
|
||||
* back to the OpenID Connect Client.
|
||||
* @throws IOException
|
||||
* If an output exception occurs in sending the redirect.
|
||||
*/
|
||||
@RequestMapping(value = "/selected")
|
||||
public void processSubmit(@RequestParam("redirect_uri") String redirectUri,
|
||||
@RequestParam("issuer") String issuer,
|
||||
@RequestParam("client_id") String clientId,
|
||||
HttpServletResponse response)
|
||||
throws IOException {
|
||||
|
||||
// Handle Submit
|
||||
|
||||
Map<String, String> urlVariables = new HashMap<String, String>();
|
||||
urlVariables.put("issuer", issuer);
|
||||
|
||||
response.sendRedirect(AccountChooserController.buildURL(redirectUri,
|
||||
urlVariables));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles form submits
|
||||
*
|
||||
* @param redirectUri
|
||||
* A redirection URI where the response will be sent.
|
||||
* @param alias
|
||||
* The OIDC alias selected.
|
||||
* @param response
|
||||
* Provide the HTTP-specific functionality for sending a
|
||||
* response. In this case a redirect to redirect the End-User
|
||||
* back to the OpenID Connect Client.
|
||||
* @throws IOException
|
||||
* If an output exception occurs in sending the redirect.
|
||||
*/
|
||||
@RequestMapping(value = "/cancel")
|
||||
public void processCancel(@RequestParam("redirect_uri") String redirectUri,
|
||||
@RequestParam("issuer") String issuer,
|
||||
@RequestParam("client_id") String clientId,
|
||||
HttpServletResponse response)
|
||||
throws IOException {
|
||||
|
||||
// Handle Cancel
|
||||
|
||||
Map<String, String> urlVariables = new HashMap<String, String>();
|
||||
urlVariables.put("error", "end_user_cancelled");
|
||||
urlVariables.put("error_description",
|
||||
"The end-user refused to select an Account.");
|
||||
|
||||
response.sendRedirect(AccountChooserController.buildURL(redirectUri,
|
||||
urlVariables));
|
||||
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright 2012 The MITRE Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
package org.mitre.account_chooser;
|
||||
|
||||
/**
|
||||
* @author nemonik
|
||||
*
|
||||
* Holdes properties of the Issuer, e.g. name, icon URL, description, et cetera
|
||||
*
|
||||
*/
|
||||
public class OIDCServer {
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OIDCServer [name=" + name + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:task="http://www.springframework.org/schema/task"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
|
||||
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
|
||||
|
||||
|
||||
<!-- Scan for components -->
|
||||
<context:component-scan annotation-config="true" base-package="org.mitre.account_chooser"/>
|
||||
|
||||
<!-- Enables the Spring MVC @Controller programming model -->
|
||||
<tx:annotation-driven transaction-manager="transactionManager" />
|
||||
<mvc:annotation-driven />
|
||||
<mvc:default-servlet-handler />
|
||||
|
||||
<!-- View configuration -->
|
||||
|
||||
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
|
||||
<mvc:resources mapping="/resources/**" location="/resources/" />
|
||||
|
||||
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
|
||||
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
|
||||
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
|
||||
<property name="prefix" value="/WEB-INF/views/" />
|
||||
<property name="suffix" value=".jsp" />
|
||||
<property name="order" value="2"/>
|
||||
</bean>
|
||||
|
||||
<!-- End view configuration -->
|
||||
|
||||
<bean name="AccountChooserConfig" class="org.mitre.account_chooser.AccountChooserConfig">
|
||||
<property name="issuers">
|
||||
<map>
|
||||
<entry key="http://server.example.com:8080/openid-connect-server">
|
||||
<bean class="org.mitre.account_chooser.OIDCServer">
|
||||
<property name="name" value="Example Server" />
|
||||
</bean>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
<property name="validClientIds" value="FGWEUIASJK, IUYTTYEV, GFHDSFYD" />
|
||||
</bean>
|
||||
|
||||
</beans>
|
|
@ -1,105 +0,0 @@
|
|||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
||||
pageEncoding="ISO-8859-1"%>
|
||||
<%@page import="org.mitre.account_chooser.OIDCServer"%>
|
||||
<%@page import="java.util.Map"%>
|
||||
<%@page import="java.util.Iterator"%>
|
||||
|
||||
<jsp:useBean id="issuers" type="java.util.Map"
|
||||
scope="request" />
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Account Chooser</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Account Chooser GUI">
|
||||
<meta name="author" content="nemonik">
|
||||
<link href="resources/bootstrap/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="resources/bootstrap/css/bootstrap-responsive.css"
|
||||
rel="stylesheet">
|
||||
<link href="resources/bootstrap/css/docs.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
body {
|
||||
padding-top: 60px;
|
||||
/* 60px to make the container go all the way to the bottom of the topbar */
|
||||
}
|
||||
</style>
|
||||
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<form name="chooser" class="form-horizontal" action="selected" method="get">
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="select01">Account:</label>
|
||||
<div class="controls">
|
||||
<select name="issuer">
|
||||
<%
|
||||
Iterator entries = issuers.entrySet().iterator();
|
||||
|
||||
while (entries.hasNext()) {
|
||||
Map.Entry entry = (Map.Entry) entries.next();
|
||||
|
||||
String id = (String) entry.getKey();
|
||||
OIDCServer issuer = (OIDCServer) entry.getValue();
|
||||
%>
|
||||
<option value="<%= id %>"><%= issuer.getName() %></option>
|
||||
<%
|
||||
}
|
||||
%>
|
||||
</select>
|
||||
<p class="help-block">Select the Account you'd like to authenticate with.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<input name="redirect_uri" type="hidden" value="${redirect_uri}">
|
||||
<input name="client_id" type="hidden" value="${client_id}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<a class="btn btn-primary" href="javascript: submitForm('selected')">Submit</a>
|
||||
<a class="btn" href="javascript: submitForm('cancel')">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--/container-->
|
||||
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="resources/bootstrap/js/jquery.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-transition.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-alert.js"></script>
|
||||
|
||||
<script src="resources/bootstrap/js/bootstrap-modal.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-dropdown.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-scrollspy.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-tab.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-tooltip.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-popover.js"></script>
|
||||
|
||||
<script src="resources/bootstrap/js/bootstrap-button.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-collapse.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-carousel.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-typeahead.js"></script>
|
||||
|
||||
<script type="text/javascript" language="JavaScript">
|
||||
// <![CDATA [
|
||||
|
||||
function submitForm(action){
|
||||
$('.form-horizontal').attr( 'action' , action );
|
||||
$('.form-horizontal').submit();
|
||||
}
|
||||
|
||||
// ]]>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,70 +0,0 @@
|
|||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
||||
pageEncoding="ISO-8859-1"%>
|
||||
<%@page import="org.mitre.account_chooser.OIDCServer"%>
|
||||
<%@page import="java.util.Map"%>
|
||||
<%@page import="java.util.Iterator"%>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Account Chooser</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Account Chooser GUI">
|
||||
<meta name="author" content="nemonik">
|
||||
<link href="resources/bootstrap/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="resources/bootstrap/css/bootstrap-responsive.css"
|
||||
rel="stylesheet">
|
||||
<link href="resources/bootstrap/css/docs.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
body {
|
||||
padding-top: 60px;
|
||||
/* 60px to make the container go all the way to the bottom of the topbar */
|
||||
}
|
||||
</style>
|
||||
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<h1>
|
||||
${error}<br>
|
||||
<small>${error_description}</small>
|
||||
</h1>
|
||||
|
||||
<a href="${client_uri}">Return to client</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--/container-->
|
||||
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="resources/bootstrap/js/jquery.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-transition.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-alert.js"></script>
|
||||
|
||||
<script src="resources/bootstrap/js/bootstrap-modal.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-dropdown.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-scrollspy.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-tab.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-tooltip.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-popover.js"></script>
|
||||
|
||||
<script src="resources/bootstrap/js/bootstrap-button.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-collapse.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-carousel.js"></script>
|
||||
<script src="resources/bootstrap/js/bootstrap-typeahead.js"></script>
|
||||
|
||||
<script type="text/javascript" language="JavaScript">
|
||||
// <![CDATA [
|
||||
|
||||
// ]]>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,23 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app version="2.5" 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-app_2_5.xsd">
|
||||
<servlet>
|
||||
<servlet-name>spring</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>spring</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<jsp-config>
|
||||
<jsp-property-group>
|
||||
<url-pattern>*.jsp</url-pattern>
|
||||
<trim-directive-whitespaces>true</trim-directive-whitespaces>
|
||||
</jsp-property-group>
|
||||
</jsp-config>
|
||||
</web-app>
|
|
@ -1,686 +0,0 @@
|
|||
/*!
|
||||
* Bootstrap Responsive v2.0.2
|
||||
*
|
||||
* Copyright 2012 Twitter, Inc
|
||||
* Licensed under the Apache License v2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Designed and built with all the love in the world @twitter by @mdo and @fat.
|
||||
*/
|
||||
.clearfix {
|
||||
*zoom: 1;
|
||||
}
|
||||
.clearfix:before,
|
||||
.clearfix:after {
|
||||
display: table;
|
||||
content: "";
|
||||
}
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
.hide-text {
|
||||
overflow: hidden;
|
||||
text-indent: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.input-block-level {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-height: 28px;
|
||||
/* Make inputs at least the height of their button counterpart */
|
||||
|
||||
/* Makes inputs behave like true block-level elements */
|
||||
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
.visible-phone {
|
||||
display: none;
|
||||
}
|
||||
.visible-tablet {
|
||||
display: none;
|
||||
}
|
||||
.visible-desktop {
|
||||
display: block;
|
||||
}
|
||||
.hidden-phone {
|
||||
display: block;
|
||||
}
|
||||
.hidden-tablet {
|
||||
display: block;
|
||||
}
|
||||
.hidden-desktop {
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.visible-phone {
|
||||
display: block;
|
||||
}
|
||||
.hidden-phone {
|
||||
display: none;
|
||||
}
|
||||
.hidden-desktop {
|
||||
display: block;
|
||||
}
|
||||
.visible-desktop {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) and (max-width: 979px) {
|
||||
.visible-tablet {
|
||||
display: block;
|
||||
}
|
||||
.hidden-tablet {
|
||||
display: none;
|
||||
}
|
||||
.hidden-desktop {
|
||||
display: block;
|
||||
}
|
||||
.visible-desktop {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.nav-collapse {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
}
|
||||
.page-header h1 small {
|
||||
display: block;
|
||||
line-height: 18px;
|
||||
}
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
.form-horizontal .control-group > label {
|
||||
float: none;
|
||||
width: auto;
|
||||
padding-top: 0;
|
||||
text-align: left;
|
||||
}
|
||||
.form-horizontal .controls {
|
||||
margin-left: 0;
|
||||
}
|
||||
.form-horizontal .control-list {
|
||||
padding-top: 0;
|
||||
}
|
||||
.form-horizontal .form-actions {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.modal {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
right: 10px;
|
||||
width: auto;
|
||||
margin: 0;
|
||||
}
|
||||
.modal.fade.in {
|
||||
top: auto;
|
||||
}
|
||||
.modal-header .close {
|
||||
padding: 10px;
|
||||
margin: -10px;
|
||||
}
|
||||
.carousel-caption {
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
body {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
.navbar-fixed-top {
|
||||
margin-left: -20px;
|
||||
margin-right: -20px;
|
||||
}
|
||||
.container {
|
||||
width: auto;
|
||||
}
|
||||
.row-fluid {
|
||||
width: 100%;
|
||||
}
|
||||
.row {
|
||||
margin-left: 0;
|
||||
}
|
||||
.row > [class*="span"],
|
||||
.row-fluid > [class*="span"] {
|
||||
float: none;
|
||||
display: block;
|
||||
width: auto;
|
||||
margin: 0;
|
||||
}
|
||||
.thumbnails [class*="span"] {
|
||||
width: auto;
|
||||
}
|
||||
input[class*="span"],
|
||||
select[class*="span"],
|
||||
textarea[class*="span"],
|
||||
.uneditable-input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-height: 28px;
|
||||
/* Make inputs at least the height of their button counterpart */
|
||||
|
||||
/* Makes inputs behave like true block-level elements */
|
||||
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.input-prepend input[class*="span"],
|
||||
.input-append input[class*="span"] {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) and (max-width: 979px) {
|
||||
.row {
|
||||
margin-left: -20px;
|
||||
*zoom: 1;
|
||||
}
|
||||
.row:before,
|
||||
.row:after {
|
||||
display: table;
|
||||
content: "";
|
||||
}
|
||||
.row:after {
|
||||
clear: both;
|
||||
}
|
||||
[class*="span"] {
|
||||
float: left;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.container,
|
||||
.navbar-fixed-top .container,
|
||||
.navbar-fixed-bottom .container {
|
||||
width: 724px;
|
||||
}
|
||||
.span12 {
|
||||
width: 724px;
|
||||
}
|
||||
.span11 {
|
||||
width: 662px;
|
||||
}
|
||||
.span10 {
|
||||
width: 600px;
|
||||
}
|
||||
.span9 {
|
||||
width: 538px;
|
||||
}
|
||||
.span8 {
|
||||
width: 476px;
|
||||
}
|
||||
.span7 {
|
||||
width: 414px;
|
||||
}
|
||||
.span6 {
|
||||
width: 352px;
|
||||
}
|
||||
.span5 {
|
||||
width: 290px;
|
||||
}
|
||||
.span4 {
|
||||
width: 228px;
|
||||
}
|
||||
.span3 {
|
||||
width: 166px;
|
||||
}
|
||||
.span2 {
|
||||
width: 104px;
|
||||
}
|
||||
.span1 {
|
||||
width: 42px;
|
||||
}
|
||||
.offset12 {
|
||||
margin-left: 764px;
|
||||
}
|
||||
.offset11 {
|
||||
margin-left: 702px;
|
||||
}
|
||||
.offset10 {
|
||||
margin-left: 640px;
|
||||
}
|
||||
.offset9 {
|
||||
margin-left: 578px;
|
||||
}
|
||||
.offset8 {
|
||||
margin-left: 516px;
|
||||
}
|
||||
.offset7 {
|
||||
margin-left: 454px;
|
||||
}
|
||||
.offset6 {
|
||||
margin-left: 392px;
|
||||
}
|
||||
.offset5 {
|
||||
margin-left: 330px;
|
||||
}
|
||||
.offset4 {
|
||||
margin-left: 268px;
|
||||
}
|
||||
.offset3 {
|
||||
margin-left: 206px;
|
||||
}
|
||||
.offset2 {
|
||||
margin-left: 144px;
|
||||
}
|
||||
.offset1 {
|
||||
margin-left: 82px;
|
||||
}
|
||||
.row-fluid {
|
||||
width: 100%;
|
||||
*zoom: 1;
|
||||
}
|
||||
.row-fluid:before,
|
||||
.row-fluid:after {
|
||||
display: table;
|
||||
content: "";
|
||||
}
|
||||
.row-fluid:after {
|
||||
clear: both;
|
||||
}
|
||||
.row-fluid > [class*="span"] {
|
||||
float: left;
|
||||
margin-left: 2.762430939%;
|
||||
}
|
||||
.row-fluid > [class*="span"]:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
.row-fluid > .span12 {
|
||||
width: 99.999999993%;
|
||||
}
|
||||
.row-fluid > .span11 {
|
||||
width: 91.436464082%;
|
||||
}
|
||||
.row-fluid > .span10 {
|
||||
width: 82.87292817100001%;
|
||||
}
|
||||
.row-fluid > .span9 {
|
||||
width: 74.30939226%;
|
||||
}
|
||||
.row-fluid > .span8 {
|
||||
width: 65.74585634900001%;
|
||||
}
|
||||
.row-fluid > .span7 {
|
||||
width: 57.182320438000005%;
|
||||
}
|
||||
.row-fluid > .span6 {
|
||||
width: 48.618784527%;
|
||||
}
|
||||
.row-fluid > .span5 {
|
||||
width: 40.055248616%;
|
||||
}
|
||||
.row-fluid > .span4 {
|
||||
width: 31.491712705%;
|
||||
}
|
||||
.row-fluid > .span3 {
|
||||
width: 22.928176794%;
|
||||
}
|
||||
.row-fluid > .span2 {
|
||||
width: 14.364640883%;
|
||||
}
|
||||
.row-fluid > .span1 {
|
||||
width: 5.801104972%;
|
||||
}
|
||||
input,
|
||||
textarea,
|
||||
.uneditable-input {
|
||||
margin-left: 0;
|
||||
}
|
||||
input.span12, textarea.span12, .uneditable-input.span12 {
|
||||
width: 714px;
|
||||
}
|
||||
input.span11, textarea.span11, .uneditable-input.span11 {
|
||||
width: 652px;
|
||||
}
|
||||
input.span10, textarea.span10, .uneditable-input.span10 {
|
||||
width: 590px;
|
||||
}
|
||||
input.span9, textarea.span9, .uneditable-input.span9 {
|
||||
width: 528px;
|
||||
}
|
||||
input.span8, textarea.span8, .uneditable-input.span8 {
|
||||
width: 466px;
|
||||
}
|
||||
input.span7, textarea.span7, .uneditable-input.span7 {
|
||||
width: 404px;
|
||||
}
|
||||
input.span6, textarea.span6, .uneditable-input.span6 {
|
||||
width: 342px;
|
||||
}
|
||||
input.span5, textarea.span5, .uneditable-input.span5 {
|
||||
width: 280px;
|
||||
}
|
||||
input.span4, textarea.span4, .uneditable-input.span4 {
|
||||
width: 218px;
|
||||
}
|
||||
input.span3, textarea.span3, .uneditable-input.span3 {
|
||||
width: 156px;
|
||||
}
|
||||
input.span2, textarea.span2, .uneditable-input.span2 {
|
||||
width: 94px;
|
||||
}
|
||||
input.span1, textarea.span1, .uneditable-input.span1 {
|
||||
width: 32px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 979px) {
|
||||
body {
|
||||
padding-top: 0;
|
||||
}
|
||||
.navbar-fixed-top {
|
||||
position: static;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.navbar-fixed-top .navbar-inner {
|
||||
padding: 5px;
|
||||
}
|
||||
.navbar .container {
|
||||
width: auto;
|
||||
padding: 0;
|
||||
}
|
||||
.navbar .brand {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
margin: 0 0 0 -5px;
|
||||
}
|
||||
.navbar .nav-collapse {
|
||||
clear: left;
|
||||
}
|
||||
.navbar .nav {
|
||||
float: none;
|
||||
margin: 0 0 9px;
|
||||
}
|
||||
.navbar .nav > li {
|
||||
float: none;
|
||||
}
|
||||
.navbar .nav > li > a {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.navbar .nav > .divider-vertical {
|
||||
display: none;
|
||||
}
|
||||
.navbar .nav .nav-header {
|
||||
color: #999999;
|
||||
text-shadow: none;
|
||||
}
|
||||
.navbar .nav > li > a,
|
||||
.navbar .dropdown-menu a {
|
||||
padding: 6px 15px;
|
||||
font-weight: bold;
|
||||
color: #999999;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.navbar .dropdown-menu li + li a {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.navbar .nav > li > a:hover,
|
||||
.navbar .dropdown-menu a:hover {
|
||||
background-color: #222222;
|
||||
}
|
||||
.navbar .dropdown-menu {
|
||||
position: static;
|
||||
top: auto;
|
||||
left: auto;
|
||||
float: none;
|
||||
display: block;
|
||||
max-width: none;
|
||||
margin: 0 15px;
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.navbar .dropdown-menu:before,
|
||||
.navbar .dropdown-menu:after {
|
||||
display: none;
|
||||
}
|
||||
.navbar .dropdown-menu .divider {
|
||||
display: none;
|
||||
}
|
||||
.navbar-form,
|
||||
.navbar-search {
|
||||
float: none;
|
||||
padding: 9px 15px;
|
||||
margin: 9px 0;
|
||||
border-top: 1px solid #222222;
|
||||
border-bottom: 1px solid #222222;
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.navbar .nav.pull-right {
|
||||
float: none;
|
||||
margin-left: 0;
|
||||
}
|
||||
.navbar-static .navbar-inner {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.btn-navbar {
|
||||
display: block;
|
||||
}
|
||||
.nav-collapse {
|
||||
overflow: hidden;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
@media (min-width: 980px) {
|
||||
.nav-collapse.collapse {
|
||||
height: auto !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
.row {
|
||||
margin-left: -30px;
|
||||
*zoom: 1;
|
||||
}
|
||||
.row:before,
|
||||
.row:after {
|
||||
display: table;
|
||||
content: "";
|
||||
}
|
||||
.row:after {
|
||||
clear: both;
|
||||
}
|
||||
[class*="span"] {
|
||||
float: left;
|
||||
margin-left: 30px;
|
||||
}
|
||||
.container,
|
||||
.navbar-fixed-top .container,
|
||||
.navbar-fixed-bottom .container {
|
||||
width: 1170px;
|
||||
}
|
||||
.span12 {
|
||||
width: 1170px;
|
||||
}
|
||||
.span11 {
|
||||
width: 1070px;
|
||||
}
|
||||
.span10 {
|
||||
width: 970px;
|
||||
}
|
||||
.span9 {
|
||||
width: 870px;
|
||||
}
|
||||
.span8 {
|
||||
width: 770px;
|
||||
}
|
||||
.span7 {
|
||||
width: 670px;
|
||||
}
|
||||
.span6 {
|
||||
width: 570px;
|
||||
}
|
||||
.span5 {
|
||||
width: 470px;
|
||||
}
|
||||
.span4 {
|
||||
width: 370px;
|
||||
}
|
||||
.span3 {
|
||||
width: 270px;
|
||||
}
|
||||
.span2 {
|
||||
width: 170px;
|
||||
}
|
||||
.span1 {
|
||||
width: 70px;
|
||||
}
|
||||
.offset12 {
|
||||
margin-left: 1230px;
|
||||
}
|
||||
.offset11 {
|
||||
margin-left: 1130px;
|
||||
}
|
||||
.offset10 {
|
||||
margin-left: 1030px;
|
||||
}
|
||||
.offset9 {
|
||||
margin-left: 930px;
|
||||
}
|
||||
.offset8 {
|
||||
margin-left: 830px;
|
||||
}
|
||||
.offset7 {
|
||||
margin-left: 730px;
|
||||
}
|
||||
.offset6 {
|
||||
margin-left: 630px;
|
||||
}
|
||||
.offset5 {
|
||||
margin-left: 530px;
|
||||
}
|
||||
.offset4 {
|
||||
margin-left: 430px;
|
||||
}
|
||||
.offset3 {
|
||||
margin-left: 330px;
|
||||
}
|
||||
.offset2 {
|
||||
margin-left: 230px;
|
||||
}
|
||||
.offset1 {
|
||||
margin-left: 130px;
|
||||
}
|
||||
.row-fluid {
|
||||
width: 100%;
|
||||
*zoom: 1;
|
||||
}
|
||||
.row-fluid:before,
|
||||
.row-fluid:after {
|
||||
display: table;
|
||||
content: "";
|
||||
}
|
||||
.row-fluid:after {
|
||||
clear: both;
|
||||
}
|
||||
.row-fluid > [class*="span"] {
|
||||
float: left;
|
||||
margin-left: 2.564102564%;
|
||||
}
|
||||
.row-fluid > [class*="span"]:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
.row-fluid > .span12 {
|
||||
width: 100%;
|
||||
}
|
||||
.row-fluid > .span11 {
|
||||
width: 91.45299145300001%;
|
||||
}
|
||||
.row-fluid > .span10 {
|
||||
width: 82.905982906%;
|
||||
}
|
||||
.row-fluid > .span9 {
|
||||
width: 74.358974359%;
|
||||
}
|
||||
.row-fluid > .span8 {
|
||||
width: 65.81196581200001%;
|
||||
}
|
||||
.row-fluid > .span7 {
|
||||
width: 57.264957265%;
|
||||
}
|
||||
.row-fluid > .span6 {
|
||||
width: 48.717948718%;
|
||||
}
|
||||
.row-fluid > .span5 {
|
||||
width: 40.170940171000005%;
|
||||
}
|
||||
.row-fluid > .span4 {
|
||||
width: 31.623931624%;
|
||||
}
|
||||
.row-fluid > .span3 {
|
||||
width: 23.076923077%;
|
||||
}
|
||||
.row-fluid > .span2 {
|
||||
width: 14.529914530000001%;
|
||||
}
|
||||
.row-fluid > .span1 {
|
||||
width: 5.982905983%;
|
||||
}
|
||||
input,
|
||||
textarea,
|
||||
.uneditable-input {
|
||||
margin-left: 0;
|
||||
}
|
||||
input.span12, textarea.span12, .uneditable-input.span12 {
|
||||
width: 1160px;
|
||||
}
|
||||
input.span11, textarea.span11, .uneditable-input.span11 {
|
||||
width: 1060px;
|
||||
}
|
||||
input.span10, textarea.span10, .uneditable-input.span10 {
|
||||
width: 960px;
|
||||
}
|
||||
input.span9, textarea.span9, .uneditable-input.span9 {
|
||||
width: 860px;
|
||||
}
|
||||
input.span8, textarea.span8, .uneditable-input.span8 {
|
||||
width: 760px;
|
||||
}
|
||||
input.span7, textarea.span7, .uneditable-input.span7 {
|
||||
width: 660px;
|
||||
}
|
||||
input.span6, textarea.span6, .uneditable-input.span6 {
|
||||
width: 560px;
|
||||
}
|
||||
input.span5, textarea.span5, .uneditable-input.span5 {
|
||||
width: 460px;
|
||||
}
|
||||
input.span4, textarea.span4, .uneditable-input.span4 {
|
||||
width: 360px;
|
||||
}
|
||||
input.span3, textarea.span3, .uneditable-input.span3 {
|
||||
width: 260px;
|
||||
}
|
||||
input.span2, textarea.span2, .uneditable-input.span2 {
|
||||
width: 160px;
|
||||
}
|
||||
input.span1, textarea.span1, .uneditable-input.span1 {
|
||||
width: 60px;
|
||||
}
|
||||
.thumbnails {
|
||||
margin-left: -30px;
|
||||
}
|
||||
.thumbnails > li {
|
||||
margin-left: 30px;
|
||||
}
|
||||
}
|
|
@ -1,845 +0,0 @@
|
|||
/* Add additional stylesheets below
|
||||
-------------------------------------------------- */
|
||||
/*
|
||||
Bootstrap's documentation styles
|
||||
Special styles for presenting Bootstrap's documentation and examples
|
||||
*/
|
||||
|
||||
|
||||
/* Body and structure
|
||||
-------------------------------------------------- */
|
||||
body {
|
||||
position: relative;
|
||||
padding-top: 90px;
|
||||
background-color: #fff;
|
||||
background-image: url(../img/grid-18px-masked.png);
|
||||
background-repeat: repeat-x;
|
||||
background-position: 0 40px;
|
||||
}
|
||||
|
||||
|
||||
/* Tweak navbar brand link to be super sleek
|
||||
-------------------------------------------------- */
|
||||
.navbar-fixed-top .brand {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
margin-left: 20px;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
text-shadow: 0 1px 0 rgba(255,255,255,.1), 0 0 30px rgba(255,255,255,.125);
|
||||
-webkit-transition: all .2s linear;
|
||||
-moz-transition: all .2s linear;
|
||||
transition: all .2s linear;
|
||||
}
|
||||
.navbar-fixed-top .brand:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
/* Space out sub-sections more
|
||||
-------------------------------------------------- */
|
||||
section {
|
||||
padding-top: 60px;
|
||||
}
|
||||
|
||||
/* Faded out hr */
|
||||
hr.soften {
|
||||
height: 1px;
|
||||
margin: 54px 0;
|
||||
background-image: -webkit-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0));
|
||||
background-image: -moz-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0));
|
||||
background-image: -ms-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0));
|
||||
background-image: -o-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,.1), rgba(0,0,0,0));
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
||||
/* Jumbotrons
|
||||
-------------------------------------------------- */
|
||||
.jumbotron {
|
||||
position: relative;
|
||||
}
|
||||
.jumbotron h1 {
|
||||
margin-bottom: 9px;
|
||||
font-size: 81px;
|
||||
font-weight: bold;
|
||||
letter-spacing: -1px;
|
||||
line-height: 1;
|
||||
}
|
||||
.jumbotron p {
|
||||
margin-bottom: 18px;
|
||||
font-weight: 300;
|
||||
}
|
||||
.jumbotron .btn-large {
|
||||
font-size: 20px;
|
||||
font-weight: normal;
|
||||
padding: 14px 24px;
|
||||
margin-right: 10px;
|
||||
-webkit-border-radius: 6px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.jumbotron .btn-large small {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Masthead (docs home) */
|
||||
.masthead {
|
||||
padding-top: 36px;
|
||||
margin-bottom: 72px;
|
||||
}
|
||||
.masthead h1,
|
||||
.masthead p {
|
||||
text-align: center;
|
||||
}
|
||||
.masthead h1 {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.masthead p {
|
||||
margin-left: 5%;
|
||||
margin-right: 5%;
|
||||
font-size: 30px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
|
||||
/* Specific jumbotrons
|
||||
------------------------- */
|
||||
/* supporting docs pages */
|
||||
.subhead {
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
.subhead h1 {
|
||||
font-size: 54px;
|
||||
}
|
||||
|
||||
/* Subnav */
|
||||
.subnav {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
background-color: #eeeeee; /* Old browsers */
|
||||
background-repeat: repeat-x; /* Repeat the gradient */
|
||||
background-image: -moz-linear-gradient(top, #f5f5f5 0%, #eeeeee 100%); /* FF3.6+ */
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f5f5f5), color-stop(100%,#eeeeee)); /* Chrome,Safari4+ */
|
||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%,#eeeeee 100%); /* Chrome 10+,Safari 5.1+ */
|
||||
background-image: -ms-linear-gradient(top, #f5f5f5 0%,#eeeeee 100%); /* IE10+ */
|
||||
background-image: -o-linear-gradient(top, #f5f5f5 0%,#eeeeee 100%); /* Opera 11.10+ */
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f5f5f5', endColorstr='#eeeeee',GradientType=0 ); /* IE6-9 */
|
||||
background-image: linear-gradient(top, #f5f5f5 0%,#eeeeee 100%); /* W3C */
|
||||
border: 1px solid #e5e5e5;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.subnav .nav {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.subnav .nav > li > a {
|
||||
margin: 0;
|
||||
padding-top: 11px;
|
||||
padding-bottom: 11px;
|
||||
border-left: 1px solid #f5f5f5;
|
||||
border-right: 1px solid #e5e5e5;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.subnav .nav > .active > a,
|
||||
.subnav .nav > .active > a:hover {
|
||||
padding-left: 13px;
|
||||
color: #777;
|
||||
background-color: #e9e9e9;
|
||||
border-right-color: #ddd;
|
||||
border-left: 0;
|
||||
-webkit-box-shadow: inset 0 3px 5px rgba(0,0,0,.05);
|
||||
-moz-box-shadow: inset 0 3px 5px rgba(0,0,0,.05);
|
||||
box-shadow: inset 0 3px 5px rgba(0,0,0,.05);
|
||||
}
|
||||
.subnav .nav > .active > a .caret,
|
||||
.subnav .nav > .active > a:hover .caret {
|
||||
border-top-color: #777;
|
||||
}
|
||||
.subnav .nav > li:first-child > a,
|
||||
.subnav .nav > li:first-child > a:hover {
|
||||
border-left: 0;
|
||||
padding-left: 12px;
|
||||
-webkit-border-radius: 4px 0 0 4px;
|
||||
-moz-border-radius: 4px 0 0 4px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
.subnav .nav > li:last-child > a {
|
||||
border-right: 0;
|
||||
}
|
||||
.subnav .dropdown-menu {
|
||||
-webkit-border-radius: 0 0 4px 4px;
|
||||
-moz-border-radius: 0 0 4px 4px;
|
||||
border-radius: 0 0 4px 4px;
|
||||
}
|
||||
|
||||
/* Fixed subnav on scroll, but only for 980px and up (sorry IE!) */
|
||||
@media (min-width: 980px) {
|
||||
.subnav-fixed {
|
||||
position: fixed;
|
||||
top: 40px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1020; /* 10 less than .navbar-fixed to prevent any overlap */
|
||||
border-color: #d5d5d5;
|
||||
border-width: 0 0 1px; /* drop the border on the fixed edges */
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
-webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1);
|
||||
-moz-box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1);
|
||||
box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); /* IE6-9 */
|
||||
}
|
||||
.subnav-fixed .nav {
|
||||
width: 938px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1px;
|
||||
}
|
||||
.subnav .nav > li:first-child > a,
|
||||
.subnav .nav > li:first-child > a:hover {
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Quick links
|
||||
-------------------------------------------------- */
|
||||
.bs-links {
|
||||
margin: 36px 0;
|
||||
}
|
||||
.quick-links {
|
||||
min-height: 30px;
|
||||
margin: 0;
|
||||
padding: 5px 20px;
|
||||
list-style: none;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
.quick-links:first-child {
|
||||
min-height: 0;
|
||||
}
|
||||
.quick-links li {
|
||||
display: inline;
|
||||
margin: 0 5px;
|
||||
color: #999;
|
||||
}
|
||||
.quick-links .github-btn,
|
||||
.quick-links .tweet-btn,
|
||||
.quick-links .follow-btn {
|
||||
position: relative;
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
|
||||
/* Marketing section of Overview
|
||||
-------------------------------------------------- */
|
||||
.marketing .row {
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
.marketing h1 {
|
||||
margin: 36px 0 27px;
|
||||
font-size: 40px;
|
||||
font-weight: 300;
|
||||
text-align: center;
|
||||
}
|
||||
.marketing h2,
|
||||
.marketing h3 {
|
||||
font-weight: 300;
|
||||
}
|
||||
.marketing h2 {
|
||||
font-size: 22px;
|
||||
}
|
||||
.marketing p {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.marketing .bs-icon {
|
||||
float: left;
|
||||
margin: 7px 10px 0 0;
|
||||
opacity: .8;
|
||||
}
|
||||
.marketing .small-bs-icon {
|
||||
float: left;
|
||||
margin: 4px 5px 0 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Footer
|
||||
-------------------------------------------------- */
|
||||
.footer {
|
||||
margin-top: 45px;
|
||||
padding: 35px 0 36px;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
}
|
||||
.footer p {
|
||||
margin-bottom: 0;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Special grid styles
|
||||
-------------------------------------------------- */
|
||||
.show-grid {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.show-grid [class*="span"] {
|
||||
background-color: #eee;
|
||||
text-align: center;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
min-height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.show-grid:hover [class*="span"] {
|
||||
background: #ddd;
|
||||
}
|
||||
.show-grid .show-grid {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.show-grid .show-grid [class*="span"] {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
|
||||
/* Render mini layout previews
|
||||
-------------------------------------------------- */
|
||||
.mini-layout {
|
||||
border: 1px solid #ddd;
|
||||
-webkit-border-radius: 6px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.075);
|
||||
-moz-box-shadow: 0 1px 2px rgba(0,0,0,.075);
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,.075);
|
||||
}
|
||||
.mini-layout {
|
||||
height: 240px;
|
||||
margin-bottom: 20px;
|
||||
padding: 9px;
|
||||
}
|
||||
.mini-layout div {
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.mini-layout .mini-layout-body {
|
||||
background-color: #dceaf4;
|
||||
margin: 0 auto;
|
||||
width: 70%;
|
||||
height: 240px;
|
||||
}
|
||||
.mini-layout.fluid .mini-layout-sidebar,
|
||||
.mini-layout.fluid .mini-layout-header,
|
||||
.mini-layout.fluid .mini-layout-body {
|
||||
float: left;
|
||||
}
|
||||
.mini-layout.fluid .mini-layout-sidebar {
|
||||
background-color: #bbd8e9;
|
||||
width: 20%;
|
||||
height: 240px;
|
||||
}
|
||||
.mini-layout.fluid .mini-layout-body {
|
||||
width: 77.5%;
|
||||
margin-left: 2.5%;
|
||||
}
|
||||
|
||||
|
||||
/* Popover docs
|
||||
-------------------------------------------------- */
|
||||
.popover-well {
|
||||
min-height: 160px;
|
||||
}
|
||||
.popover-well .popover {
|
||||
display: block;
|
||||
}
|
||||
.popover-well .popover-wrapper {
|
||||
width: 50%;
|
||||
height: 160px;
|
||||
float: left;
|
||||
margin-left: 55px;
|
||||
position: relative;
|
||||
}
|
||||
.popover-well .popover-menu-wrapper {
|
||||
height: 80px;
|
||||
}
|
||||
.large-bird {
|
||||
margin: 5px 0 0 310px;
|
||||
opacity: .1;
|
||||
}
|
||||
|
||||
|
||||
/* Download page
|
||||
-------------------------------------------------- */
|
||||
.download .page-header {
|
||||
margin-top: 36px;
|
||||
}
|
||||
.page-header .toggle-all {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/* Space out h3s when following a section */
|
||||
.download h3 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.download-builder input + h3,
|
||||
.download-builder .checkbox + h3 {
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
/* Fields for variables */
|
||||
.download-builder input[type=text] {
|
||||
margin-bottom: 9px;
|
||||
font-family: Menlo, Monaco, "Courier New", monospace;
|
||||
font-size: 12px;
|
||||
color: #d14;
|
||||
}
|
||||
.download-builder input[type=text]:focus {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* Custom, larger checkbox labels */
|
||||
.download .checkbox {
|
||||
padding: 6px 10px 6px 25px;
|
||||
color: #555;
|
||||
background-color: #f9f9f9;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.download .checkbox:hover {
|
||||
color: #333;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.download .checkbox small {
|
||||
font-size: 12px;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
/* Variables section */
|
||||
#variables label {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Giant download button */
|
||||
.download-btn {
|
||||
margin: 36px 0 108px;
|
||||
}
|
||||
#download p,
|
||||
#download h4 {
|
||||
max-width: 50%;
|
||||
margin: 0 auto;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
#download h4 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#download p {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.download-btn .btn {
|
||||
display: block;
|
||||
width: auto;
|
||||
padding: 19px 24px;
|
||||
margin-bottom: 27px;
|
||||
font-size: 30px;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
-webkit-border-radius: 6px;
|
||||
-moz-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Color swatches on LESS docs page
|
||||
-------------------------------------------------- */
|
||||
/* Sets the width of the td */
|
||||
.swatch-col {
|
||||
width: 30px;
|
||||
}
|
||||
/* Le swatch */
|
||||
.swatch {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 20px;
|
||||
margin: -6px 0;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
/* For white swatches, give a border */
|
||||
.swatch-bordered {
|
||||
width: 28px;
|
||||
height: 18px;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
|
||||
/* Misc
|
||||
-------------------------------------------------- */
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Make tables spaced out a bit more */
|
||||
h2 + table,
|
||||
h3 + table,
|
||||
h4 + table,
|
||||
h2 + .row {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/* Example sites showcase */
|
||||
.example-sites img {
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.marketing-byline {
|
||||
margin: -18px 0 27px;
|
||||
font-size: 18px;
|
||||
font-weight: 300;
|
||||
line-height: 24px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.scrollspy-example {
|
||||
height: 200px;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Remove bottom margin on example forms in wells */
|
||||
form.well {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
/* Tighten up spacing */
|
||||
.well hr {
|
||||
margin: 18px 0;
|
||||
}
|
||||
|
||||
/* Fake the :focus state to demo it */
|
||||
.focused {
|
||||
border-color: rgba(82,168,236,.8);
|
||||
-webkit-box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6);
|
||||
-moz-box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6);
|
||||
box-shadow: inset 0 1px 3px rgba(0,0,0,.1), 0 0 8px rgba(82,168,236,.6);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* For input sizes, make them display block */
|
||||
.docs-input-sizes select,
|
||||
.docs-input-sizes input[type=text] {
|
||||
display: block;
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
|
||||
/* Icons
|
||||
------------------------- */
|
||||
.the-icons {
|
||||
margin-left: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.the-icons i:hover {
|
||||
background-color: rgba(255,0,0,.25);
|
||||
}
|
||||
|
||||
/* Eaxmples page
|
||||
------------------------- */
|
||||
.bootstrap-examples .thumbnail {
|
||||
margin-bottom: 9px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* Responsive table
|
||||
------------------------- */
|
||||
.responsive-utilities th small {
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
color: #999;
|
||||
}
|
||||
.responsive-utilities tbody th {
|
||||
font-weight: normal;
|
||||
}
|
||||
.responsive-utilities td {
|
||||
text-align: center;
|
||||
}
|
||||
.responsive-utilities td.is-visible {
|
||||
color: #468847;
|
||||
background-color: #dff0d8 !important;
|
||||
}
|
||||
.responsive-utilities td.is-hidden {
|
||||
color: #ccc;
|
||||
background-color: #f9f9f9 !important;
|
||||
}
|
||||
|
||||
/* Responsive tests
|
||||
------------------------- */
|
||||
.responsive-utilities-test {
|
||||
margin-top: 5px;
|
||||
margin-left: 0;
|
||||
list-style: none;
|
||||
overflow: hidden; /* clear floats */
|
||||
}
|
||||
.responsive-utilities-test li {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 25%;
|
||||
height: 43px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
line-height: 43px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
border: 1px solid #ddd;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.responsive-utilities-test li + li {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.responsive-utilities-test span {
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
right: -1px;
|
||||
bottom: -1px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.responsive-utilities-test span {
|
||||
color: #468847;
|
||||
background-color: #dff0d8;
|
||||
border: 1px solid #d6e9c6;
|
||||
}
|
||||
|
||||
|
||||
/* Responsive Docs
|
||||
-------------------------------------------------- */
|
||||
@media (max-width: 480px) {
|
||||
|
||||
/* Reduce padding above jumbotron */
|
||||
body {
|
||||
padding-top: 70px;
|
||||
}
|
||||
|
||||
/* Change up some type stuff */
|
||||
h2 {
|
||||
margin-top: 27px;
|
||||
}
|
||||
h2 small {
|
||||
display: block;
|
||||
line-height: 18px;
|
||||
}
|
||||
h3 {
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
/* Adjust the jumbotron */
|
||||
.jumbotron h1,
|
||||
.jumbotron p {
|
||||
text-align: center;
|
||||
margin-right: 0;
|
||||
}
|
||||
.jumbotron h1 {
|
||||
font-size: 45px;
|
||||
margin-right: 0;
|
||||
}
|
||||
.jumbotron p {
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
font-size: 18px;
|
||||
line-height: 24px;
|
||||
}
|
||||
.jumbotron .btn {
|
||||
display: block;
|
||||
font-size: 18px;
|
||||
padding: 10px 14px;
|
||||
margin: 0 auto 10px;
|
||||
}
|
||||
/* Masthead (home page jumbotron) */
|
||||
.masthead {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
/* Don't space out quick links so much */
|
||||
.quick-links {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
/* hide the bullets on mobile since our horizontal space is limited */
|
||||
.quick-links .divider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* center example sites */
|
||||
.example-sites {
|
||||
margin-left: 0;
|
||||
}
|
||||
.example-sites > li {
|
||||
float: none;
|
||||
display: block;
|
||||
max-width: 280px;
|
||||
margin: 0 auto 18px;
|
||||
text-align: center;
|
||||
}
|
||||
.example-sites .thumbnail > img {
|
||||
max-width: 270px;
|
||||
}
|
||||
|
||||
table code {
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* Modal example */
|
||||
.modal-example .modal {
|
||||
position: relative;
|
||||
top: auto;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
||||
/* Remove any padding from the body */
|
||||
body {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
/* Jumbotron buttons */
|
||||
.jumbotron .btn {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Subnav */
|
||||
.subnav {
|
||||
position: static;
|
||||
top: auto;
|
||||
z-index: auto;
|
||||
width: auto;
|
||||
height: auto;
|
||||
background: #fff; /* whole background property since we use a background-image for gradient */
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.subnav .nav > li {
|
||||
float: none;
|
||||
}
|
||||
.subnav .nav > li > a {
|
||||
border: 0;
|
||||
}
|
||||
.subnav .nav > li + li > a {
|
||||
border-top: 1px solid #e5e5e5;
|
||||
}
|
||||
.subnav .nav > li:first-child > a,
|
||||
.subnav .nav > li:first-child > a:hover {
|
||||
-webkit-border-radius: 4px 4px 0 0;
|
||||
-moz-border-radius: 4px 4px 0 0;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
/* Popovers */
|
||||
.large-bird {
|
||||
display: none;
|
||||
}
|
||||
.popover-well .popover-wrapper {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
/* Space out the show-grid examples */
|
||||
.show-grid [class*="span"] {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
/* Unfloat the back to top link in footer */
|
||||
.footer .pull-right {
|
||||
float: none;
|
||||
}
|
||||
.footer p {
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 480px) and (max-width: 768px) {
|
||||
|
||||
/* Scale down the jumbotron content */
|
||||
.jumbotron h1 {
|
||||
font-size: 54px;
|
||||
}
|
||||
.jumbotron p {
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 768px) and (max-width: 980px) {
|
||||
|
||||
/* Remove any padding from the body */
|
||||
body {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
/* Scale down the jumbotron content */
|
||||
.jumbotron h1 {
|
||||
font-size: 72px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 980px) {
|
||||
|
||||
/* Unfloat brand */
|
||||
.navbar-fixed-top .brand {
|
||||
float: left;
|
||||
margin-left: 0;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
/* Inline-block quick links for more spacing */
|
||||
.quick-links li {
|
||||
display: inline-block;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* LARGE DESKTOP SCREENS */
|
||||
@media (min-width: 1210px) {
|
||||
|
||||
/* Update subnav container */
|
||||
.subnav-fixed .nav {
|
||||
width: 1168px; /* 2px less to account for left/right borders being removed when in fixed mode */
|
||||
}
|
||||
|
||||
}
|
Before Width: | Height: | Size: 316 B |
Before Width: | Height: | Size: 305 B |
Before Width: | Height: | Size: 213 B |
Before Width: | Height: | Size: 345 B |
Before Width: | Height: | Size: 117 B |
Before Width: | Height: | Size: 172 B |
Before Width: | Height: | Size: 301 B |
Before Width: | Height: | Size: 292 B |
|
@ -1,106 +0,0 @@
|
|||
## 2.0 BOOTSTRAP JS PHILOSOPHY
|
||||
These are the high-level design rules which guide the development of Bootstrap's plugin apis.
|
||||
|
||||
---
|
||||
|
||||
### DATA-ATTRIBUTE API
|
||||
|
||||
We believe you should be able to use all plugins provided by Bootstrap purely through the markup API without writing a single line of javascript.
|
||||
|
||||
We acknowledge that this isn't always the most performant and sometimes it may be desirable to turn this functionality off altogether. Therefore, as of 2.0 we provide the ability to disable the data attribute API by unbinding all events on the body namespaced with `'data-api'`. This looks like this:
|
||||
|
||||
$('body').off('.data-api')
|
||||
|
||||
To target a specific plugin, just include the plugins name as a namespace along with the data-api namespace like this:
|
||||
|
||||
$('body').off('.alert.data-api')
|
||||
|
||||
---
|
||||
|
||||
### PROGRAMATIC API
|
||||
|
||||
We also believe you should be able to use all plugins provided by Bootstrap purely through the JS API.
|
||||
|
||||
All public APIs should be single, chainable methods, and return the collection acted upon.
|
||||
|
||||
$(".btn.danger").button("toggle").addClass("fat")
|
||||
|
||||
All methods should accept an optional options object, a string which targets a particular method, or null which initiates the default behavior:
|
||||
|
||||
$("#myModal").modal() // initialized with defaults
|
||||
$("#myModal").modal({ keyboard: false }) // initialized with now keyboard
|
||||
$("#myModal").modal('show') // initializes and invokes show immediately afterqwe2
|
||||
|
||||
---
|
||||
|
||||
### OPTIONS
|
||||
|
||||
Options should be sparse and add universal value. We should pick the right defaults.
|
||||
|
||||
All plugins should have a default object which can be modified to effect all instance's default options. The defaults object should be available via `$.fn.plugin.defaults`.
|
||||
|
||||
$.fn.modal.defaults = { … }
|
||||
|
||||
An options definition should take the following form:
|
||||
|
||||
*noun*: *adjective* - describes or modifies a quality of an instance
|
||||
|
||||
examples:
|
||||
|
||||
backdrop: true
|
||||
keyboard: false
|
||||
placement: 'top'
|
||||
|
||||
---
|
||||
|
||||
### EVENTS
|
||||
|
||||
All events should have an infinitive and past participle form. The infinitive is fired just before an action takes place, the past participle on completion of the action.
|
||||
|
||||
show | shown
|
||||
hide | hidden
|
||||
|
||||
---
|
||||
|
||||
### CONSTRUCTORS
|
||||
|
||||
Each plugin should expose it's raw constructor on a `Constructor` property -- accessed in the following way:
|
||||
|
||||
|
||||
$.fn.popover.Constructor
|
||||
|
||||
---
|
||||
|
||||
### DATA ACCESSOR
|
||||
|
||||
Each plugin stores a copy of the invoked class on an object. This class instance can be accessed directly through jQuery's data API like this:
|
||||
|
||||
$('[rel=popover]').data('popover') instanceof $.fn.popover.Constructor
|
||||
|
||||
---
|
||||
|
||||
### DATA ATTRIBUTES
|
||||
|
||||
Data attributes should take the following form:
|
||||
|
||||
- data-{{verb}}={{plugin}} - defines main interaction
|
||||
- data-target || href^=# - defined on "control" element (if element controls an element other than self)
|
||||
- data-{{noun}} - defines class instance options
|
||||
|
||||
examples:
|
||||
|
||||
// control other targets
|
||||
data-toggle="modal" data-target="#foo"
|
||||
data-toggle="collapse" data-target="#foo" data-parent="#bar"
|
||||
|
||||
// defined on element they control
|
||||
data-spy="scroll"
|
||||
|
||||
data-dismiss="modal"
|
||||
data-dismiss="alert"
|
||||
|
||||
data-toggle="dropdown"
|
||||
|
||||
data-toggle="button"
|
||||
data-toggle="buttons-checkbox"
|
||||
data-toggle="buttons-radio"
|
|
@ -1,94 +0,0 @@
|
|||
/* ==========================================================
|
||||
* bootstrap-alert.js v2.0.2
|
||||
* http://twitter.github.com/bootstrap/javascript.html#alerts
|
||||
* ==========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ========================================================== */
|
||||
|
||||
|
||||
!function( $ ){
|
||||
|
||||
"use strict"
|
||||
|
||||
/* ALERT CLASS DEFINITION
|
||||
* ====================== */
|
||||
|
||||
var dismiss = '[data-dismiss="alert"]'
|
||||
, Alert = function ( el ) {
|
||||
$(el).on('click', dismiss, this.close)
|
||||
}
|
||||
|
||||
Alert.prototype = {
|
||||
|
||||
constructor: Alert
|
||||
|
||||
, close: function ( e ) {
|
||||
var $this = $(this)
|
||||
, selector = $this.attr('data-target')
|
||||
, $parent
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href')
|
||||
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
|
||||
}
|
||||
|
||||
$parent = $(selector)
|
||||
$parent.trigger('close')
|
||||
|
||||
e && e.preventDefault()
|
||||
|
||||
$parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
|
||||
|
||||
$parent
|
||||
.trigger('close')
|
||||
.removeClass('in')
|
||||
|
||||
function removeElement() {
|
||||
$parent
|
||||
.trigger('closed')
|
||||
.remove()
|
||||
}
|
||||
|
||||
$.support.transition && $parent.hasClass('fade') ?
|
||||
$parent.on($.support.transition.end, removeElement) :
|
||||
removeElement()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ALERT PLUGIN DEFINITION
|
||||
* ======================= */
|
||||
|
||||
$.fn.alert = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('alert')
|
||||
if (!data) $this.data('alert', (data = new Alert(this)))
|
||||
if (typeof option == 'string') data[option].call($this)
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.alert.Constructor = Alert
|
||||
|
||||
|
||||
/* ALERT DATA-API
|
||||
* ============== */
|
||||
|
||||
$(function () {
|
||||
$('body').on('click.alert.data-api', dismiss, Alert.prototype.close)
|
||||
})
|
||||
|
||||
}( window.jQuery );
|
|
@ -1,100 +0,0 @@
|
|||
/* ============================================================
|
||||
* bootstrap-button.js v2.0.2
|
||||
* http://twitter.github.com/bootstrap/javascript.html#buttons
|
||||
* ============================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ============================================================ */
|
||||
|
||||
!function( $ ){
|
||||
|
||||
"use strict"
|
||||
|
||||
/* BUTTON PUBLIC CLASS DEFINITION
|
||||
* ============================== */
|
||||
|
||||
var Button = function ( element, options ) {
|
||||
this.$element = $(element)
|
||||
this.options = $.extend({}, $.fn.button.defaults, options)
|
||||
}
|
||||
|
||||
Button.prototype = {
|
||||
|
||||
constructor: Button
|
||||
|
||||
, setState: function ( state ) {
|
||||
var d = 'disabled'
|
||||
, $el = this.$element
|
||||
, data = $el.data()
|
||||
, val = $el.is('input') ? 'val' : 'html'
|
||||
|
||||
state = state + 'Text'
|
||||
data.resetText || $el.data('resetText', $el[val]())
|
||||
|
||||
$el[val](data[state] || this.options[state])
|
||||
|
||||
// push to event loop to allow forms to submit
|
||||
setTimeout(function () {
|
||||
state == 'loadingText' ?
|
||||
$el.addClass(d).attr(d, d) :
|
||||
$el.removeClass(d).removeAttr(d)
|
||||
}, 0)
|
||||
}
|
||||
|
||||
, toggle: function () {
|
||||
var $parent = this.$element.parent('[data-toggle="buttons-radio"]')
|
||||
|
||||
$parent && $parent
|
||||
.find('.active')
|
||||
.removeClass('active')
|
||||
|
||||
this.$element.toggleClass('active')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* BUTTON PLUGIN DEFINITION
|
||||
* ======================== */
|
||||
|
||||
$.fn.button = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('button')
|
||||
, options = typeof option == 'object' && option
|
||||
if (!data) $this.data('button', (data = new Button(this, options)))
|
||||
if (option == 'toggle') data.toggle()
|
||||
else if (option) data.setState(option)
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.button.defaults = {
|
||||
loadingText: 'loading...'
|
||||
}
|
||||
|
||||
$.fn.button.Constructor = Button
|
||||
|
||||
|
||||
/* BUTTON DATA-API
|
||||
* =============== */
|
||||
|
||||
$(function () {
|
||||
$('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) {
|
||||
var $btn = $(e.target)
|
||||
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
|
||||
$btn.button('toggle')
|
||||
})
|
||||
})
|
||||
|
||||
}( window.jQuery );
|
|
@ -1,161 +0,0 @@
|
|||
/* ==========================================================
|
||||
* bootstrap-carousel.js v2.0.2
|
||||
* http://twitter.github.com/bootstrap/javascript.html#carousel
|
||||
* ==========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ========================================================== */
|
||||
|
||||
|
||||
!function( $ ){
|
||||
|
||||
"use strict"
|
||||
|
||||
/* CAROUSEL CLASS DEFINITION
|
||||
* ========================= */
|
||||
|
||||
var Carousel = function (element, options) {
|
||||
this.$element = $(element)
|
||||
this.options = $.extend({}, $.fn.carousel.defaults, options)
|
||||
this.options.slide && this.slide(this.options.slide)
|
||||
this.options.pause == 'hover' && this.$element
|
||||
.on('mouseenter', $.proxy(this.pause, this))
|
||||
.on('mouseleave', $.proxy(this.cycle, this))
|
||||
}
|
||||
|
||||
Carousel.prototype = {
|
||||
|
||||
cycle: function () {
|
||||
this.interval = setInterval($.proxy(this.next, this), this.options.interval)
|
||||
return this
|
||||
}
|
||||
|
||||
, to: function (pos) {
|
||||
var $active = this.$element.find('.active')
|
||||
, children = $active.parent().children()
|
||||
, activePos = children.index($active)
|
||||
, that = this
|
||||
|
||||
if (pos > (children.length - 1) || pos < 0) return
|
||||
|
||||
if (this.sliding) {
|
||||
return this.$element.one('slid', function () {
|
||||
that.to(pos)
|
||||
})
|
||||
}
|
||||
|
||||
if (activePos == pos) {
|
||||
return this.pause().cycle()
|
||||
}
|
||||
|
||||
return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos]))
|
||||
}
|
||||
|
||||
, pause: function () {
|
||||
clearInterval(this.interval)
|
||||
this.interval = null
|
||||
return this
|
||||
}
|
||||
|
||||
, next: function () {
|
||||
if (this.sliding) return
|
||||
return this.slide('next')
|
||||
}
|
||||
|
||||
, prev: function () {
|
||||
if (this.sliding) return
|
||||
return this.slide('prev')
|
||||
}
|
||||
|
||||
, slide: function (type, next) {
|
||||
var $active = this.$element.find('.active')
|
||||
, $next = next || $active[type]()
|
||||
, isCycling = this.interval
|
||||
, direction = type == 'next' ? 'left' : 'right'
|
||||
, fallback = type == 'next' ? 'first' : 'last'
|
||||
, that = this
|
||||
|
||||
this.sliding = true
|
||||
|
||||
isCycling && this.pause()
|
||||
|
||||
$next = $next.length ? $next : this.$element.find('.item')[fallback]()
|
||||
|
||||
if ($next.hasClass('active')) return
|
||||
|
||||
if (!$.support.transition && this.$element.hasClass('slide')) {
|
||||
this.$element.trigger('slide')
|
||||
$active.removeClass('active')
|
||||
$next.addClass('active')
|
||||
this.sliding = false
|
||||
this.$element.trigger('slid')
|
||||
} else {
|
||||
$next.addClass(type)
|
||||
$next[0].offsetWidth // force reflow
|
||||
$active.addClass(direction)
|
||||
$next.addClass(direction)
|
||||
this.$element.trigger('slide')
|
||||
this.$element.one($.support.transition.end, function () {
|
||||
$next.removeClass([type, direction].join(' ')).addClass('active')
|
||||
$active.removeClass(['active', direction].join(' '))
|
||||
that.sliding = false
|
||||
setTimeout(function () { that.$element.trigger('slid') }, 0)
|
||||
})
|
||||
}
|
||||
|
||||
isCycling && this.cycle()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* CAROUSEL PLUGIN DEFINITION
|
||||
* ========================== */
|
||||
|
||||
$.fn.carousel = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('carousel')
|
||||
, options = typeof option == 'object' && option
|
||||
if (!data) $this.data('carousel', (data = new Carousel(this, options)))
|
||||
if (typeof option == 'number') data.to(option)
|
||||
else if (typeof option == 'string' || (option = options.slide)) data[option]()
|
||||
else data.cycle()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.carousel.defaults = {
|
||||
interval: 5000
|
||||
, pause: 'hover'
|
||||
}
|
||||
|
||||
$.fn.carousel.Constructor = Carousel
|
||||
|
||||
|
||||
/* CAROUSEL DATA-API
|
||||
* ================= */
|
||||
|
||||
$(function () {
|
||||
$('body').on('click.carousel.data-api', '[data-slide]', function ( e ) {
|
||||
var $this = $(this), href
|
||||
, $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
|
||||
, options = !$target.data('modal') && $.extend({}, $target.data(), $this.data())
|
||||
$target.carousel(options)
|
||||
e.preventDefault()
|
||||
})
|
||||
})
|
||||
|
||||
}( window.jQuery );
|
|
@ -1,138 +0,0 @@
|
|||
/* =============================================================
|
||||
* bootstrap-collapse.js v2.0.2
|
||||
* http://twitter.github.com/bootstrap/javascript.html#collapse
|
||||
* =============================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ============================================================ */
|
||||
|
||||
!function( $ ){
|
||||
|
||||
"use strict"
|
||||
|
||||
var Collapse = function ( element, options ) {
|
||||
this.$element = $(element)
|
||||
this.options = $.extend({}, $.fn.collapse.defaults, options)
|
||||
|
||||
if (this.options["parent"]) {
|
||||
this.$parent = $(this.options["parent"])
|
||||
}
|
||||
|
||||
this.options.toggle && this.toggle()
|
||||
}
|
||||
|
||||
Collapse.prototype = {
|
||||
|
||||
constructor: Collapse
|
||||
|
||||
, dimension: function () {
|
||||
var hasWidth = this.$element.hasClass('width')
|
||||
return hasWidth ? 'width' : 'height'
|
||||
}
|
||||
|
||||
, show: function () {
|
||||
var dimension = this.dimension()
|
||||
, scroll = $.camelCase(['scroll', dimension].join('-'))
|
||||
, actives = this.$parent && this.$parent.find('.in')
|
||||
, hasData
|
||||
|
||||
if (actives && actives.length) {
|
||||
hasData = actives.data('collapse')
|
||||
actives.collapse('hide')
|
||||
hasData || actives.data('collapse', null)
|
||||
}
|
||||
|
||||
this.$element[dimension](0)
|
||||
this.transition('addClass', 'show', 'shown')
|
||||
this.$element[dimension](this.$element[0][scroll])
|
||||
|
||||
}
|
||||
|
||||
, hide: function () {
|
||||
var dimension = this.dimension()
|
||||
this.reset(this.$element[dimension]())
|
||||
this.transition('removeClass', 'hide', 'hidden')
|
||||
this.$element[dimension](0)
|
||||
}
|
||||
|
||||
, reset: function ( size ) {
|
||||
var dimension = this.dimension()
|
||||
|
||||
this.$element
|
||||
.removeClass('collapse')
|
||||
[dimension](size || 'auto')
|
||||
[0].offsetWidth
|
||||
|
||||
this.$element[size ? 'addClass' : 'removeClass']('collapse')
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
, transition: function ( method, startEvent, completeEvent ) {
|
||||
var that = this
|
||||
, complete = function () {
|
||||
if (startEvent == 'show') that.reset()
|
||||
that.$element.trigger(completeEvent)
|
||||
}
|
||||
|
||||
this.$element
|
||||
.trigger(startEvent)
|
||||
[method]('in')
|
||||
|
||||
$.support.transition && this.$element.hasClass('collapse') ?
|
||||
this.$element.one($.support.transition.end, complete) :
|
||||
complete()
|
||||
}
|
||||
|
||||
, toggle: function () {
|
||||
this[this.$element.hasClass('in') ? 'hide' : 'show']()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* COLLAPSIBLE PLUGIN DEFINITION
|
||||
* ============================== */
|
||||
|
||||
$.fn.collapse = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('collapse')
|
||||
, options = typeof option == 'object' && option
|
||||
if (!data) $this.data('collapse', (data = new Collapse(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.collapse.defaults = {
|
||||
toggle: true
|
||||
}
|
||||
|
||||
$.fn.collapse.Constructor = Collapse
|
||||
|
||||
|
||||
/* COLLAPSIBLE DATA-API
|
||||
* ==================== */
|
||||
|
||||
$(function () {
|
||||
$('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) {
|
||||
var $this = $(this), href
|
||||
, target = $this.attr('data-target')
|
||||
|| e.preventDefault()
|
||||
|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
|
||||
, option = $(target).data('collapse') ? 'toggle' : $this.data()
|
||||
$(target).collapse(option)
|
||||
})
|
||||
})
|
||||
|
||||
}( window.jQuery );
|
|
@ -1,92 +0,0 @@
|
|||
/* ============================================================
|
||||
* bootstrap-dropdown.js v2.0.2
|
||||
* http://twitter.github.com/bootstrap/javascript.html#dropdowns
|
||||
* ============================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ============================================================ */
|
||||
|
||||
|
||||
!function( $ ){
|
||||
|
||||
"use strict"
|
||||
|
||||
/* DROPDOWN CLASS DEFINITION
|
||||
* ========================= */
|
||||
|
||||
var toggle = '[data-toggle="dropdown"]'
|
||||
, Dropdown = function ( element ) {
|
||||
var $el = $(element).on('click.dropdown.data-api', this.toggle)
|
||||
$('html').on('click.dropdown.data-api', function () {
|
||||
$el.parent().removeClass('open')
|
||||
})
|
||||
}
|
||||
|
||||
Dropdown.prototype = {
|
||||
|
||||
constructor: Dropdown
|
||||
|
||||
, toggle: function ( e ) {
|
||||
var $this = $(this)
|
||||
, selector = $this.attr('data-target')
|
||||
, $parent
|
||||
, isActive
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href')
|
||||
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
|
||||
}
|
||||
|
||||
$parent = $(selector)
|
||||
$parent.length || ($parent = $this.parent())
|
||||
|
||||
isActive = $parent.hasClass('open')
|
||||
|
||||
clearMenus()
|
||||
!isActive && $parent.toggleClass('open')
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function clearMenus() {
|
||||
$(toggle).parent().removeClass('open')
|
||||
}
|
||||
|
||||
|
||||
/* DROPDOWN PLUGIN DEFINITION
|
||||
* ========================== */
|
||||
|
||||
$.fn.dropdown = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('dropdown')
|
||||
if (!data) $this.data('dropdown', (data = new Dropdown(this)))
|
||||
if (typeof option == 'string') data[option].call($this)
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.dropdown.Constructor = Dropdown
|
||||
|
||||
|
||||
/* APPLY TO STANDARD DROPDOWN ELEMENTS
|
||||
* =================================== */
|
||||
|
||||
$(function () {
|
||||
$('html').on('click.dropdown.data-api', clearMenus)
|
||||
$('body').on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle)
|
||||
})
|
||||
|
||||
}( window.jQuery );
|
|
@ -1,210 +0,0 @@
|
|||
/* =========================================================
|
||||
* bootstrap-modal.js v2.0.2
|
||||
* http://twitter.github.com/bootstrap/javascript.html#modals
|
||||
* =========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ========================================================= */
|
||||
|
||||
|
||||
!function( $ ){
|
||||
|
||||
"use strict"
|
||||
|
||||
/* MODAL CLASS DEFINITION
|
||||
* ====================== */
|
||||
|
||||
var Modal = function ( content, options ) {
|
||||
this.options = options
|
||||
this.$element = $(content)
|
||||
.delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
|
||||
}
|
||||
|
||||
Modal.prototype = {
|
||||
|
||||
constructor: Modal
|
||||
|
||||
, toggle: function () {
|
||||
return this[!this.isShown ? 'show' : 'hide']()
|
||||
}
|
||||
|
||||
, show: function () {
|
||||
var that = this
|
||||
|
||||
if (this.isShown) return
|
||||
|
||||
$('body').addClass('modal-open')
|
||||
|
||||
this.isShown = true
|
||||
this.$element.trigger('show')
|
||||
|
||||
escape.call(this)
|
||||
backdrop.call(this, function () {
|
||||
var transition = $.support.transition && that.$element.hasClass('fade')
|
||||
|
||||
!that.$element.parent().length && that.$element.appendTo(document.body) //don't move modals dom position
|
||||
|
||||
that.$element
|
||||
.show()
|
||||
|
||||
if (transition) {
|
||||
that.$element[0].offsetWidth // force reflow
|
||||
}
|
||||
|
||||
that.$element.addClass('in')
|
||||
|
||||
transition ?
|
||||
that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
|
||||
that.$element.trigger('shown')
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
, hide: function ( e ) {
|
||||
e && e.preventDefault()
|
||||
|
||||
if (!this.isShown) return
|
||||
|
||||
var that = this
|
||||
this.isShown = false
|
||||
|
||||
$('body').removeClass('modal-open')
|
||||
|
||||
escape.call(this)
|
||||
|
||||
this.$element
|
||||
.trigger('hide')
|
||||
.removeClass('in')
|
||||
|
||||
$.support.transition && this.$element.hasClass('fade') ?
|
||||
hideWithTransition.call(this) :
|
||||
hideModal.call(this)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* MODAL PRIVATE METHODS
|
||||
* ===================== */
|
||||
|
||||
function hideWithTransition() {
|
||||
var that = this
|
||||
, timeout = setTimeout(function () {
|
||||
that.$element.off($.support.transition.end)
|
||||
hideModal.call(that)
|
||||
}, 500)
|
||||
|
||||
this.$element.one($.support.transition.end, function () {
|
||||
clearTimeout(timeout)
|
||||
hideModal.call(that)
|
||||
})
|
||||
}
|
||||
|
||||
function hideModal( that ) {
|
||||
this.$element
|
||||
.hide()
|
||||
.trigger('hidden')
|
||||
|
||||
backdrop.call(this)
|
||||
}
|
||||
|
||||
function backdrop( callback ) {
|
||||
var that = this
|
||||
, animate = this.$element.hasClass('fade') ? 'fade' : ''
|
||||
|
||||
if (this.isShown && this.options.backdrop) {
|
||||
var doAnimate = $.support.transition && animate
|
||||
|
||||
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
|
||||
.appendTo(document.body)
|
||||
|
||||
if (this.options.backdrop != 'static') {
|
||||
this.$backdrop.click($.proxy(this.hide, this))
|
||||
}
|
||||
|
||||
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
|
||||
|
||||
this.$backdrop.addClass('in')
|
||||
|
||||
doAnimate ?
|
||||
this.$backdrop.one($.support.transition.end, callback) :
|
||||
callback()
|
||||
|
||||
} else if (!this.isShown && this.$backdrop) {
|
||||
this.$backdrop.removeClass('in')
|
||||
|
||||
$.support.transition && this.$element.hasClass('fade')?
|
||||
this.$backdrop.one($.support.transition.end, $.proxy(removeBackdrop, this)) :
|
||||
removeBackdrop.call(this)
|
||||
|
||||
} else if (callback) {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
function removeBackdrop() {
|
||||
this.$backdrop.remove()
|
||||
this.$backdrop = null
|
||||
}
|
||||
|
||||
function escape() {
|
||||
var that = this
|
||||
if (this.isShown && this.options.keyboard) {
|
||||
$(document).on('keyup.dismiss.modal', function ( e ) {
|
||||
e.which == 27 && that.hide()
|
||||
})
|
||||
} else if (!this.isShown) {
|
||||
$(document).off('keyup.dismiss.modal')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* MODAL PLUGIN DEFINITION
|
||||
* ======================= */
|
||||
|
||||
$.fn.modal = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('modal')
|
||||
, options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
|
||||
if (!data) $this.data('modal', (data = new Modal(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
else if (options.show) data.show()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.modal.defaults = {
|
||||
backdrop: true
|
||||
, keyboard: true
|
||||
, show: true
|
||||
}
|
||||
|
||||
$.fn.modal.Constructor = Modal
|
||||
|
||||
|
||||
/* MODAL DATA-API
|
||||
* ============== */
|
||||
|
||||
$(function () {
|
||||
$('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
|
||||
var $this = $(this), href
|
||||
, $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
|
||||
, option = $target.data('modal') ? 'toggle' : $.extend({}, $target.data(), $this.data())
|
||||
|
||||
e.preventDefault()
|
||||
$target.modal(option)
|
||||
})
|
||||
})
|
||||
|
||||
}( window.jQuery );
|
|
@ -1,95 +0,0 @@
|
|||
/* ===========================================================
|
||||
* bootstrap-popover.js v2.0.2
|
||||
* http://twitter.github.com/bootstrap/javascript.html#popovers
|
||||
* ===========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* =========================================================== */
|
||||
|
||||
|
||||
!function( $ ) {
|
||||
|
||||
"use strict"
|
||||
|
||||
var Popover = function ( element, options ) {
|
||||
this.init('popover', element, options)
|
||||
}
|
||||
|
||||
/* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
|
||||
========================================== */
|
||||
|
||||
Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
|
||||
|
||||
constructor: Popover
|
||||
|
||||
, setContent: function () {
|
||||
var $tip = this.tip()
|
||||
, title = this.getTitle()
|
||||
, content = this.getContent()
|
||||
|
||||
$tip.find('.popover-title')[ $.type(title) == 'object' ? 'append' : 'html' ](title)
|
||||
$tip.find('.popover-content > *')[ $.type(content) == 'object' ? 'append' : 'html' ](content)
|
||||
|
||||
$tip.removeClass('fade top bottom left right in')
|
||||
}
|
||||
|
||||
, hasContent: function () {
|
||||
return this.getTitle() || this.getContent()
|
||||
}
|
||||
|
||||
, getContent: function () {
|
||||
var content
|
||||
, $e = this.$element
|
||||
, o = this.options
|
||||
|
||||
content = $e.attr('data-content')
|
||||
|| (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
|
||||
|
||||
content = content.toString().replace(/(^\s*|\s*$)/, "")
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
, tip: function() {
|
||||
if (!this.$tip) {
|
||||
this.$tip = $(this.options.template)
|
||||
}
|
||||
return this.$tip
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
/* POPOVER PLUGIN DEFINITION
|
||||
* ======================= */
|
||||
|
||||
$.fn.popover = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('popover')
|
||||
, options = typeof option == 'object' && option
|
||||
if (!data) $this.data('popover', (data = new Popover(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.popover.Constructor = Popover
|
||||
|
||||
$.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
|
||||
placement: 'right'
|
||||
, content: ''
|
||||
, template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
|
||||
})
|
||||
|
||||
}( window.jQuery );
|
|
@ -1,125 +0,0 @@
|
|||
/* =============================================================
|
||||
* bootstrap-scrollspy.js v2.0.2
|
||||
* http://twitter.github.com/bootstrap/javascript.html#scrollspy
|
||||
* =============================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ============================================================== */
|
||||
|
||||
!function ( $ ) {
|
||||
|
||||
"use strict"
|
||||
|
||||
/* SCROLLSPY CLASS DEFINITION
|
||||
* ========================== */
|
||||
|
||||
function ScrollSpy( element, options) {
|
||||
var process = $.proxy(this.process, this)
|
||||
, $element = $(element).is('body') ? $(window) : $(element)
|
||||
, href
|
||||
this.options = $.extend({}, $.fn.scrollspy.defaults, options)
|
||||
this.$scrollElement = $element.on('scroll.scroll.data-api', process)
|
||||
this.selector = (this.options.target
|
||||
|| ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
|
||||
|| '') + ' .nav li > a'
|
||||
this.$body = $('body').on('click.scroll.data-api', this.selector, process)
|
||||
this.refresh()
|
||||
this.process()
|
||||
}
|
||||
|
||||
ScrollSpy.prototype = {
|
||||
|
||||
constructor: ScrollSpy
|
||||
|
||||
, refresh: function () {
|
||||
this.targets = this.$body
|
||||
.find(this.selector)
|
||||
.map(function () {
|
||||
var href = $(this).attr('href')
|
||||
return /^#\w/.test(href) && $(href).length ? href : null
|
||||
})
|
||||
|
||||
this.offsets = $.map(this.targets, function (id) {
|
||||
return $(id).position().top
|
||||
})
|
||||
}
|
||||
|
||||
, process: function () {
|
||||
var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
|
||||
, offsets = this.offsets
|
||||
, targets = this.targets
|
||||
, activeTarget = this.activeTarget
|
||||
, i
|
||||
|
||||
for (i = offsets.length; i--;) {
|
||||
activeTarget != targets[i]
|
||||
&& scrollTop >= offsets[i]
|
||||
&& (!offsets[i + 1] || scrollTop <= offsets[i + 1])
|
||||
&& this.activate( targets[i] )
|
||||
}
|
||||
}
|
||||
|
||||
, activate: function (target) {
|
||||
var active
|
||||
|
||||
this.activeTarget = target
|
||||
|
||||
this.$body
|
||||
.find(this.selector).parent('.active')
|
||||
.removeClass('active')
|
||||
|
||||
active = this.$body
|
||||
.find(this.selector + '[href="' + target + '"]')
|
||||
.parent('li')
|
||||
.addClass('active')
|
||||
|
||||
if ( active.parent('.dropdown-menu') ) {
|
||||
active.closest('li.dropdown').addClass('active')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* SCROLLSPY PLUGIN DEFINITION
|
||||
* =========================== */
|
||||
|
||||
$.fn.scrollspy = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('scrollspy')
|
||||
, options = typeof option == 'object' && option
|
||||
if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.scrollspy.Constructor = ScrollSpy
|
||||
|
||||
$.fn.scrollspy.defaults = {
|
||||
offset: 10
|
||||
}
|
||||
|
||||
|
||||
/* SCROLLSPY DATA-API
|
||||
* ================== */
|
||||
|
||||
$(function () {
|
||||
$('[data-spy="scroll"]').each(function () {
|
||||
var $spy = $(this)
|
||||
$spy.scrollspy($spy.data())
|
||||
})
|
||||
})
|
||||
|
||||
}( window.jQuery );
|
|
@ -1,130 +0,0 @@
|
|||
/* ========================================================
|
||||
* bootstrap-tab.js v2.0.2
|
||||
* http://twitter.github.com/bootstrap/javascript.html#tabs
|
||||
* ========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ======================================================== */
|
||||
|
||||
|
||||
!function( $ ){
|
||||
|
||||
"use strict"
|
||||
|
||||
/* TAB CLASS DEFINITION
|
||||
* ==================== */
|
||||
|
||||
var Tab = function ( element ) {
|
||||
this.element = $(element)
|
||||
}
|
||||
|
||||
Tab.prototype = {
|
||||
|
||||
constructor: Tab
|
||||
|
||||
, show: function () {
|
||||
var $this = this.element
|
||||
, $ul = $this.closest('ul:not(.dropdown-menu)')
|
||||
, selector = $this.attr('data-target')
|
||||
, previous
|
||||
, $target
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href')
|
||||
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
|
||||
}
|
||||
|
||||
if ( $this.parent('li').hasClass('active') ) return
|
||||
|
||||
previous = $ul.find('.active a').last()[0]
|
||||
|
||||
$this.trigger({
|
||||
type: 'show'
|
||||
, relatedTarget: previous
|
||||
})
|
||||
|
||||
$target = $(selector)
|
||||
|
||||
this.activate($this.parent('li'), $ul)
|
||||
this.activate($target, $target.parent(), function () {
|
||||
$this.trigger({
|
||||
type: 'shown'
|
||||
, relatedTarget: previous
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
, activate: function ( element, container, callback) {
|
||||
var $active = container.find('> .active')
|
||||
, transition = callback
|
||||
&& $.support.transition
|
||||
&& $active.hasClass('fade')
|
||||
|
||||
function next() {
|
||||
$active
|
||||
.removeClass('active')
|
||||
.find('> .dropdown-menu > .active')
|
||||
.removeClass('active')
|
||||
|
||||
element.addClass('active')
|
||||
|
||||
if (transition) {
|
||||
element[0].offsetWidth // reflow for transition
|
||||
element.addClass('in')
|
||||
} else {
|
||||
element.removeClass('fade')
|
||||
}
|
||||
|
||||
if ( element.parent('.dropdown-menu') ) {
|
||||
element.closest('li.dropdown').addClass('active')
|
||||
}
|
||||
|
||||
callback && callback()
|
||||
}
|
||||
|
||||
transition ?
|
||||
$active.one($.support.transition.end, next) :
|
||||
next()
|
||||
|
||||
$active.removeClass('in')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* TAB PLUGIN DEFINITION
|
||||
* ===================== */
|
||||
|
||||
$.fn.tab = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('tab')
|
||||
if (!data) $this.data('tab', (data = new Tab(this)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.tab.Constructor = Tab
|
||||
|
||||
|
||||
/* TAB DATA-API
|
||||
* ============ */
|
||||
|
||||
$(function () {
|
||||
$('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
|
||||
e.preventDefault()
|
||||
$(this).tab('show')
|
||||
})
|
||||
})
|
||||
|
||||
}( window.jQuery );
|
|
@ -1,270 +0,0 @@
|
|||
/* ===========================================================
|
||||
* bootstrap-tooltip.js v2.0.2
|
||||
* http://twitter.github.com/bootstrap/javascript.html#tooltips
|
||||
* Inspired by the original jQuery.tipsy by Jason Frame
|
||||
* ===========================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ========================================================== */
|
||||
|
||||
!function( $ ) {
|
||||
|
||||
"use strict"
|
||||
|
||||
/* TOOLTIP PUBLIC CLASS DEFINITION
|
||||
* =============================== */
|
||||
|
||||
var Tooltip = function ( element, options ) {
|
||||
this.init('tooltip', element, options)
|
||||
}
|
||||
|
||||
Tooltip.prototype = {
|
||||
|
||||
constructor: Tooltip
|
||||
|
||||
, init: function ( type, element, options ) {
|
||||
var eventIn
|
||||
, eventOut
|
||||
|
||||
this.type = type
|
||||
this.$element = $(element)
|
||||
this.options = this.getOptions(options)
|
||||
this.enabled = true
|
||||
|
||||
if (this.options.trigger != 'manual') {
|
||||
eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
|
||||
eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
|
||||
this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))
|
||||
this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
|
||||
}
|
||||
|
||||
this.options.selector ?
|
||||
(this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
|
||||
this.fixTitle()
|
||||
}
|
||||
|
||||
, getOptions: function ( options ) {
|
||||
options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
|
||||
|
||||
if (options.delay && typeof options.delay == 'number') {
|
||||
options.delay = {
|
||||
show: options.delay
|
||||
, hide: options.delay
|
||||
}
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
, enter: function ( e ) {
|
||||
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
|
||||
|
||||
if (!self.options.delay || !self.options.delay.show) {
|
||||
self.show()
|
||||
} else {
|
||||
self.hoverState = 'in'
|
||||
setTimeout(function() {
|
||||
if (self.hoverState == 'in') {
|
||||
self.show()
|
||||
}
|
||||
}, self.options.delay.show)
|
||||
}
|
||||
}
|
||||
|
||||
, leave: function ( e ) {
|
||||
var self = $(e.currentTarget)[this.type](this._options).data(this.type)
|
||||
|
||||
if (!self.options.delay || !self.options.delay.hide) {
|
||||
self.hide()
|
||||
} else {
|
||||
self.hoverState = 'out'
|
||||
setTimeout(function() {
|
||||
if (self.hoverState == 'out') {
|
||||
self.hide()
|
||||
}
|
||||
}, self.options.delay.hide)
|
||||
}
|
||||
}
|
||||
|
||||
, show: function () {
|
||||
var $tip
|
||||
, inside
|
||||
, pos
|
||||
, actualWidth
|
||||
, actualHeight
|
||||
, placement
|
||||
, tp
|
||||
|
||||
if (this.hasContent() && this.enabled) {
|
||||
$tip = this.tip()
|
||||
this.setContent()
|
||||
|
||||
if (this.options.animation) {
|
||||
$tip.addClass('fade')
|
||||
}
|
||||
|
||||
placement = typeof this.options.placement == 'function' ?
|
||||
this.options.placement.call(this, $tip[0], this.$element[0]) :
|
||||
this.options.placement
|
||||
|
||||
inside = /in/.test(placement)
|
||||
|
||||
$tip
|
||||
.remove()
|
||||
.css({ top: 0, left: 0, display: 'block' })
|
||||
.appendTo(inside ? this.$element : document.body)
|
||||
|
||||
pos = this.getPosition(inside)
|
||||
|
||||
actualWidth = $tip[0].offsetWidth
|
||||
actualHeight = $tip[0].offsetHeight
|
||||
|
||||
switch (inside ? placement.split(' ')[1] : placement) {
|
||||
case 'bottom':
|
||||
tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
|
||||
break
|
||||
case 'top':
|
||||
tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
|
||||
break
|
||||
case 'left':
|
||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
|
||||
break
|
||||
case 'right':
|
||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
|
||||
break
|
||||
}
|
||||
|
||||
$tip
|
||||
.css(tp)
|
||||
.addClass(placement)
|
||||
.addClass('in')
|
||||
}
|
||||
}
|
||||
|
||||
, setContent: function () {
|
||||
var $tip = this.tip()
|
||||
$tip.find('.tooltip-inner').html(this.getTitle())
|
||||
$tip.removeClass('fade in top bottom left right')
|
||||
}
|
||||
|
||||
, hide: function () {
|
||||
var that = this
|
||||
, $tip = this.tip()
|
||||
|
||||
$tip.removeClass('in')
|
||||
|
||||
function removeWithAnimation() {
|
||||
var timeout = setTimeout(function () {
|
||||
$tip.off($.support.transition.end).remove()
|
||||
}, 500)
|
||||
|
||||
$tip.one($.support.transition.end, function () {
|
||||
clearTimeout(timeout)
|
||||
$tip.remove()
|
||||
})
|
||||
}
|
||||
|
||||
$.support.transition && this.$tip.hasClass('fade') ?
|
||||
removeWithAnimation() :
|
||||
$tip.remove()
|
||||
}
|
||||
|
||||
, fixTitle: function () {
|
||||
var $e = this.$element
|
||||
if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
|
||||
$e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
|
||||
}
|
||||
}
|
||||
|
||||
, hasContent: function () {
|
||||
return this.getTitle()
|
||||
}
|
||||
|
||||
, getPosition: function (inside) {
|
||||
return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
|
||||
width: this.$element[0].offsetWidth
|
||||
, height: this.$element[0].offsetHeight
|
||||
})
|
||||
}
|
||||
|
||||
, getTitle: function () {
|
||||
var title
|
||||
, $e = this.$element
|
||||
, o = this.options
|
||||
|
||||
title = $e.attr('data-original-title')
|
||||
|| (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
|
||||
|
||||
title = (title || '').toString().replace(/(^\s*|\s*$)/, "")
|
||||
|
||||
return title
|
||||
}
|
||||
|
||||
, tip: function () {
|
||||
return this.$tip = this.$tip || $(this.options.template)
|
||||
}
|
||||
|
||||
, validate: function () {
|
||||
if (!this.$element[0].parentNode) {
|
||||
this.hide()
|
||||
this.$element = null
|
||||
this.options = null
|
||||
}
|
||||
}
|
||||
|
||||
, enable: function () {
|
||||
this.enabled = true
|
||||
}
|
||||
|
||||
, disable: function () {
|
||||
this.enabled = false
|
||||
}
|
||||
|
||||
, toggleEnabled: function () {
|
||||
this.enabled = !this.enabled
|
||||
}
|
||||
|
||||
, toggle: function () {
|
||||
this[this.tip().hasClass('in') ? 'hide' : 'show']()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* TOOLTIP PLUGIN DEFINITION
|
||||
* ========================= */
|
||||
|
||||
$.fn.tooltip = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('tooltip')
|
||||
, options = typeof option == 'object' && option
|
||||
if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.tooltip.Constructor = Tooltip
|
||||
|
||||
$.fn.tooltip.defaults = {
|
||||
animation: true
|
||||
, delay: 0
|
||||
, selector: false
|
||||
, placement: 'top'
|
||||
, trigger: 'hover'
|
||||
, title: ''
|
||||
, template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
|
||||
}
|
||||
|
||||
}( window.jQuery );
|
|
@ -1,51 +0,0 @@
|
|||
/* ===================================================
|
||||
* bootstrap-transition.js v2.0.2
|
||||
* http://twitter.github.com/bootstrap/javascript.html#transitions
|
||||
* ===================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ========================================================== */
|
||||
|
||||
!function( $ ) {
|
||||
|
||||
$(function () {
|
||||
|
||||
"use strict"
|
||||
|
||||
/* CSS TRANSITION SUPPORT (https://gist.github.com/373874)
|
||||
* ======================================================= */
|
||||
|
||||
$.support.transition = (function () {
|
||||
var thisBody = document.body || document.documentElement
|
||||
, thisStyle = thisBody.style
|
||||
, support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined
|
||||
|
||||
return support && {
|
||||
end: (function () {
|
||||
var transitionEnd = "TransitionEnd"
|
||||
if ( $.browser.webkit ) {
|
||||
transitionEnd = "webkitTransitionEnd"
|
||||
} else if ( $.browser.mozilla ) {
|
||||
transitionEnd = "transitionend"
|
||||
} else if ( $.browser.opera ) {
|
||||
transitionEnd = "oTransitionEnd"
|
||||
}
|
||||
return transitionEnd
|
||||
}())
|
||||
}
|
||||
})()
|
||||
|
||||
})
|
||||
|
||||
}( window.jQuery );
|
|
@ -1,271 +0,0 @@
|
|||
/* =============================================================
|
||||
* bootstrap-typeahead.js v2.0.2
|
||||
* http://twitter.github.com/bootstrap/javascript.html#typeahead
|
||||
* =============================================================
|
||||
* Copyright 2012 Twitter, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ============================================================ */
|
||||
|
||||
!function( $ ){
|
||||
|
||||
"use strict"
|
||||
|
||||
var Typeahead = function ( element, options ) {
|
||||
this.$element = $(element)
|
||||
this.options = $.extend({}, $.fn.typeahead.defaults, options)
|
||||
this.matcher = this.options.matcher || this.matcher
|
||||
this.sorter = this.options.sorter || this.sorter
|
||||
this.highlighter = this.options.highlighter || this.highlighter
|
||||
this.$menu = $(this.options.menu).appendTo('body')
|
||||
this.source = this.options.source
|
||||
this.shown = false
|
||||
this.listen()
|
||||
}
|
||||
|
||||
Typeahead.prototype = {
|
||||
|
||||
constructor: Typeahead
|
||||
|
||||
, select: function () {
|
||||
var val = this.$menu.find('.active').attr('data-value')
|
||||
this.$element.val(val)
|
||||
this.$element.change();
|
||||
return this.hide()
|
||||
}
|
||||
|
||||
, show: function () {
|
||||
var pos = $.extend({}, this.$element.offset(), {
|
||||
height: this.$element[0].offsetHeight
|
||||
})
|
||||
|
||||
this.$menu.css({
|
||||
top: pos.top + pos.height
|
||||
, left: pos.left
|
||||
})
|
||||
|
||||
this.$menu.show()
|
||||
this.shown = true
|
||||
return this
|
||||
}
|
||||
|
||||
, hide: function () {
|
||||
this.$menu.hide()
|
||||
this.shown = false
|
||||
return this
|
||||
}
|
||||
|
||||
, lookup: function (event) {
|
||||
var that = this
|
||||
, items
|
||||
, q
|
||||
|
||||
this.query = this.$element.val()
|
||||
|
||||
if (!this.query) {
|
||||
return this.shown ? this.hide() : this
|
||||
}
|
||||
|
||||
items = $.grep(this.source, function (item) {
|
||||
if (that.matcher(item)) return item
|
||||
})
|
||||
|
||||
items = this.sorter(items)
|
||||
|
||||
if (!items.length) {
|
||||
return this.shown ? this.hide() : this
|
||||
}
|
||||
|
||||
return this.render(items.slice(0, this.options.items)).show()
|
||||
}
|
||||
|
||||
, matcher: function (item) {
|
||||
return ~item.toLowerCase().indexOf(this.query.toLowerCase())
|
||||
}
|
||||
|
||||
, sorter: function (items) {
|
||||
var beginswith = []
|
||||
, caseSensitive = []
|
||||
, caseInsensitive = []
|
||||
, item
|
||||
|
||||
while (item = items.shift()) {
|
||||
if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
|
||||
else if (~item.indexOf(this.query)) caseSensitive.push(item)
|
||||
else caseInsensitive.push(item)
|
||||
}
|
||||
|
||||
return beginswith.concat(caseSensitive, caseInsensitive)
|
||||
}
|
||||
|
||||
, highlighter: function (item) {
|
||||
return item.replace(new RegExp('(' + this.query + ')', 'ig'), function ($1, match) {
|
||||
return '<strong>' + match + '</strong>'
|
||||
})
|
||||
}
|
||||
|
||||
, render: function (items) {
|
||||
var that = this
|
||||
|
||||
items = $(items).map(function (i, item) {
|
||||
i = $(that.options.item).attr('data-value', item)
|
||||
i.find('a').html(that.highlighter(item))
|
||||
return i[0]
|
||||
})
|
||||
|
||||
items.first().addClass('active')
|
||||
this.$menu.html(items)
|
||||
return this
|
||||
}
|
||||
|
||||
, next: function (event) {
|
||||
var active = this.$menu.find('.active').removeClass('active')
|
||||
, next = active.next()
|
||||
|
||||
if (!next.length) {
|
||||
next = $(this.$menu.find('li')[0])
|
||||
}
|
||||
|
||||
next.addClass('active')
|
||||
}
|
||||
|
||||
, prev: function (event) {
|
||||
var active = this.$menu.find('.active').removeClass('active')
|
||||
, prev = active.prev()
|
||||
|
||||
if (!prev.length) {
|
||||
prev = this.$menu.find('li').last()
|
||||
}
|
||||
|
||||
prev.addClass('active')
|
||||
}
|
||||
|
||||
, listen: function () {
|
||||
this.$element
|
||||
.on('blur', $.proxy(this.blur, this))
|
||||
.on('keypress', $.proxy(this.keypress, this))
|
||||
.on('keyup', $.proxy(this.keyup, this))
|
||||
|
||||
if ($.browser.webkit || $.browser.msie) {
|
||||
this.$element.on('keydown', $.proxy(this.keypress, this))
|
||||
}
|
||||
|
||||
this.$menu
|
||||
.on('click', $.proxy(this.click, this))
|
||||
.on('mouseenter', 'li', $.proxy(this.mouseenter, this))
|
||||
}
|
||||
|
||||
, keyup: function (e) {
|
||||
switch(e.keyCode) {
|
||||
case 40: // down arrow
|
||||
case 38: // up arrow
|
||||
break
|
||||
|
||||
case 9: // tab
|
||||
case 13: // enter
|
||||
if (!this.shown) return
|
||||
this.select()
|
||||
break
|
||||
|
||||
case 27: // escape
|
||||
if (!this.shown) return
|
||||
this.hide()
|
||||
break
|
||||
|
||||
default:
|
||||
this.lookup()
|
||||
}
|
||||
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
, keypress: function (e) {
|
||||
if (!this.shown) return
|
||||
|
||||
switch(e.keyCode) {
|
||||
case 9: // tab
|
||||
case 13: // enter
|
||||
case 27: // escape
|
||||
e.preventDefault()
|
||||
break
|
||||
|
||||
case 38: // up arrow
|
||||
e.preventDefault()
|
||||
this.prev()
|
||||
break
|
||||
|
||||
case 40: // down arrow
|
||||
e.preventDefault()
|
||||
this.next()
|
||||
break
|
||||
}
|
||||
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
, blur: function (e) {
|
||||
var that = this
|
||||
setTimeout(function () { that.hide() }, 150)
|
||||
}
|
||||
|
||||
, click: function (e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.select()
|
||||
}
|
||||
|
||||
, mouseenter: function (e) {
|
||||
this.$menu.find('.active').removeClass('active')
|
||||
$(e.currentTarget).addClass('active')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* TYPEAHEAD PLUGIN DEFINITION
|
||||
* =========================== */
|
||||
|
||||
$.fn.typeahead = function ( option ) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
, data = $this.data('typeahead')
|
||||
, options = typeof option == 'object' && option
|
||||
if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
|
||||
if (typeof option == 'string') data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.typeahead.defaults = {
|
||||
source: []
|
||||
, items: 8
|
||||
, menu: '<ul class="typeahead dropdown-menu"></ul>'
|
||||
, item: '<li><a href="#"></a></li>'
|
||||
}
|
||||
|
||||
$.fn.typeahead.Constructor = Typeahead
|
||||
|
||||
|
||||
/* TYPEAHEAD DATA-API
|
||||
* ================== */
|
||||
|
||||
$(function () {
|
||||
$('body').on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
|
||||
var $this = $(this)
|
||||
if ($this.data('typeahead')) return
|
||||
e.preventDefault()
|
||||
$this.typeahead($this.data())
|
||||
})
|
||||
})
|
||||
|
||||
}( window.jQuery );
|