├── .gitignore
├── LICENSE-2.0.txt
├── NOTICE.txt
├── README.textile
├── project.clj
├── resources
└── cascade
│ ├── bootstrap-alerts.js
│ ├── bootstrap-buttons.js
│ ├── bootstrap-dropdown.js
│ ├── bootstrap-modal.js
│ ├── bootstrap-popover.js
│ ├── bootstrap-scrollspy.js
│ ├── bootstrap-tabs.js
│ ├── bootstrap-twipsy.js
│ ├── bootstrap.css
│ ├── exception-report.js
│ ├── exception.css
│ ├── init.js
│ └── require-jquery.js
├── src
├── cascade.clj
├── cascade
│ ├── asset.clj
│ ├── dom.clj
│ ├── exception.clj
│ ├── fail.clj
│ ├── import.clj
│ ├── internal
│ │ ├── parser.clj
│ │ └── viewbuilder.clj
│ ├── request.clj
│ └── utils.clj
├── main.clj
└── test_app.clj
├── test-resources
├── cascade
│ └── internal
│ │ ├── ns.xml
│ │ └── resource.txt
├── expected
│ ├── attribute-rendering.txt
│ ├── block-macro.txt
│ ├── entity-template.txt
│ ├── implicit-attributes.txt
│ ├── inline-macro.txt
│ ├── simple-defview.txt
│ ├── special-attribute-values.txt
│ ├── template-comments.txt
│ ├── template-for.txt
│ ├── use-of-symbol.txt
│ └── zen-elements-view.txt
└── log4j.properties
├── test
└── cascade
│ ├── test_cascade.clj
│ ├── test_dom.clj
│ ├── test_parser.clj
│ ├── test_utils.clj
│ └── test_viewbuilder.clj
└── webapp
├── app.css
└── images
└── clojure-logo.png
/.gitignore:
--------------------------------------------------------------------------------
1 | *.jar
2 | .DS_Store
3 | bin/
4 | build/
5 | target/
6 | classes/
7 | .settings/
8 | *.tmproj
9 | .classpath
10 | .project
11 | *~
12 | lib/
13 | pom.xml
14 | .gradle
15 | *.iml
16 | *.ipr
17 | *.iws
18 | .lein-failures
--------------------------------------------------------------------------------
/LICENSE-2.0.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/NOTICE.txt:
--------------------------------------------------------------------------------
1 | This project includes jQuery 1.7, dual licensed under the MIT or GPL Version 2 licenses.
2 | http://jquery.org/
3 |
4 | This project includes RequireJS 1.0.1, dual licensed under new BSD, and MIT licenses.
5 | http://requirejs.org/
6 |
--------------------------------------------------------------------------------
/README.textile:
--------------------------------------------------------------------------------
1 | h1. Cascade
2 |
3 | Welcome to Cascade! Cascade is a web application view library for "Clojure":http://clojure.org/ that emphasizes idiomatic use of Clojure while drawing inspiration from the "Apache Tapesty":http://tapestry.apache.org web framework.
4 |
5 | Cascade templates are an embedded DSL directly in the Clojure code; this takes some getting used to but ensures that you can take maximum advantage of Clojure when creating your application. Templates are converted to functions.
6 |
7 | Cascade converts templates to function, but the output of functions is not markup text; instead, Cascade uses an internal DOM structure as an intermediate format prior to streaming markup. This has some significant advantages,
8 | in that the final output can be manipulated between the rendering stage and the streaming stage.
9 |
10 | Cascade is designed to be used as a view technology with "Ring":https://github.com/mmcgrana/ring and "Compojure":https://github.com/weavejester/compojure.
11 |
12 | See the "Cascade Wiki":http://wiki.github.com/hlship/cascade/ for more information.
13 |
14 | h1. Status
15 |
16 | So where's the progress? Sorry folks, I've been busy with several large Tapestry projects, plus Tapestry 5.3, plus Project Jacob (my now 19 month old son) to make any progress on Cascade. I still have high hopes for Cascade, but I'm in the chicken-and-the-egg problem of finding a client that can directly or indirectly support its development.
17 |
18 | Cascade started as a full web framework, but has evolved into a view technology that plugs into existing frameworks (Ring and Compojure).
19 |
20 | h1. Authors
21 |
22 | Cascade is a itty-bitty side project of Howard M. Lewis Ship, who should be spending more time on Tapestry.
23 |
24 | Care to contribute? Drop me a line!
25 |
26 | h1. License
27 |
28 | Cascade is released under the terms of the Apache Software License 2.0.
29 |
30 | Cascade bundles the following libraries:
31 |
32 | * "JQuery":http://jquery.com/ library (version 1.7), distributed under "dual MIT and GPL licenses":http://docs.jquery.com/Licensing
33 | * "RequireJS":http://requirejs.org (version 1.0.1), distributed under the dual licenses: MIT and "new" BSD license
34 | * "Bootstrap":http://twitter.github.com/bootstrap/ (version 1.4.0), distributed under the "Apache Software License 2.0":http://www.apache.org/licenses/
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/project.clj:
--------------------------------------------------------------------------------
1 | (defproject cascade "0.2-SNAPSHOT"
2 | :description "Simple, fast, easy web applications in idiomatic Clojure"
3 | :url "http://github.com/hlship/cascade"
4 | :warn-on-reflection true
5 | :dependencies [[org.clojure/clojure "1.3.0"]
6 | [clj-json "0.4.3"]
7 | [compojure "0.6.5"]]
8 | :dev-dependencies [[ring/ring-jetty-adapter "0.3.11"]
9 | [hiccup "0.3.7"]
10 | [swank-clojure "1.3.1"]
11 | [midje "1.1.1"]
12 | [lein-ring "0.4.6"]]
13 | :ring {:handler test-app/app})
14 |
--------------------------------------------------------------------------------
/resources/cascade/bootstrap-alerts.js:
--------------------------------------------------------------------------------
1 | /* ==========================================================
2 | * bootstrap-alerts.js v1.4.0
3 | * http://twitter.github.com/bootstrap/javascript.html#alerts
4 | * ==========================================================
5 | * Copyright 2011 Twitter, Inc.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | * ========================================================== */
19 |
20 |
21 | !function( $ ){
22 |
23 | "use strict"
24 |
25 | /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)
26 | * ======================================================= */
27 |
28 | var transitionEnd
29 |
30 | $(document).ready(function () {
31 |
32 | $.support.transition = (function () {
33 | var thisBody = document.body || document.documentElement
34 | , thisStyle = thisBody.style
35 | , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined
36 | return support
37 | })()
38 |
39 | // set CSS transition event type
40 | if ( $.support.transition ) {
41 | transitionEnd = "TransitionEnd"
42 | if ( $.browser.webkit ) {
43 | transitionEnd = "webkitTransitionEnd"
44 | } else if ( $.browser.mozilla ) {
45 | transitionEnd = "transitionend"
46 | } else if ( $.browser.opera ) {
47 | transitionEnd = "oTransitionEnd"
48 | }
49 | }
50 |
51 | })
52 |
53 | /* ALERT CLASS DEFINITION
54 | * ====================== */
55 |
56 | var Alert = function ( content, options ) {
57 | this.settings = $.extend({}, $.fn.alert.defaults, options)
58 | this.$element = $(content)
59 | .delegate(this.settings.selector, 'click', this.close)
60 | }
61 |
62 | Alert.prototype = {
63 |
64 | close: function (e) {
65 | var $element = $(this).parent('.alert-message')
66 |
67 | e && e.preventDefault()
68 | $element.removeClass('in')
69 |
70 | function removeElement () {
71 | $element.remove()
72 | }
73 |
74 | $.support.transition && $element.hasClass('fade') ?
75 | $element.bind(transitionEnd, removeElement) :
76 | removeElement()
77 | }
78 |
79 | }
80 |
81 |
82 | /* ALERT PLUGIN DEFINITION
83 | * ======================= */
84 |
85 | $.fn.alert = function ( options ) {
86 |
87 | if ( options === true ) {
88 | return this.data('alert')
89 | }
90 |
91 | return this.each(function () {
92 | var $this = $(this)
93 |
94 | if ( typeof options == 'string' ) {
95 | return $this.data('alert')[options]()
96 | }
97 |
98 | $(this).data('alert', new Alert( this, options ))
99 |
100 | })
101 | }
102 |
103 | $.fn.alert.defaults = {
104 | selector: '.close'
105 | }
106 |
107 | $(document).ready(function () {
108 | new Alert($('body'), {
109 | selector: '.alert-message[data-alert] .close'
110 | })
111 | })
112 |
113 | }( window.jQuery || window.ender );
--------------------------------------------------------------------------------
/resources/cascade/bootstrap-buttons.js:
--------------------------------------------------------------------------------
1 | /* ============================================================
2 | * bootstrap-dropdown.js v1.4.0
3 | * http://twitter.github.com/bootstrap/javascript.html#dropdown
4 | * ============================================================
5 | * Copyright 2011 Twitter, Inc.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | * ============================================================ */
19 |
20 | !function( $ ){
21 |
22 | "use strict"
23 |
24 | function setState(el, state) {
25 | var d = 'disabled'
26 | , $el = $(el)
27 | , data = $el.data()
28 |
29 | state = state + 'Text'
30 | data.resetText || $el.data('resetText', $el.html())
31 |
32 | $el.html( data[state] || $.fn.button.defaults[state] )
33 |
34 | state == 'loadingText' ?
35 | $el.addClass(d).attr(d, d) :
36 | $el.removeClass(d).removeAttr(d)
37 | }
38 |
39 | function toggle(el) {
40 | $(el).toggleClass('active')
41 | }
42 |
43 | $.fn.button = function(options) {
44 | return this.each(function () {
45 | if (options == 'toggle') {
46 | return toggle(this)
47 | }
48 | options && setState(this, options)
49 | })
50 | }
51 |
52 | $.fn.button.defaults = {
53 | loadingText: 'loading...'
54 | }
55 |
56 | $(function () {
57 | $('body').delegate('.btn[data-toggle]', 'click', function () {
58 | $(this).button('toggle')
59 | })
60 | })
61 |
62 | }( window.jQuery || window.ender );
--------------------------------------------------------------------------------
/resources/cascade/bootstrap-dropdown.js:
--------------------------------------------------------------------------------
1 | /* ============================================================
2 | * bootstrap-dropdown.js v1.4.0
3 | * http://twitter.github.com/bootstrap/javascript.html#dropdown
4 | * ============================================================
5 | * Copyright 2011 Twitter, Inc.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | * ============================================================ */
19 |
20 |
21 | !function( $ ){
22 |
23 | "use strict"
24 |
25 | /* DROPDOWN PLUGIN DEFINITION
26 | * ========================== */
27 |
28 | $.fn.dropdown = function ( selector ) {
29 | return this.each(function () {
30 | $(this).delegate(selector || d, 'click', function (e) {
31 | var li = $(this).parent('li')
32 | , isActive = li.hasClass('open')
33 |
34 | clearMenus()
35 | !isActive && li.toggleClass('open')
36 | return false
37 | })
38 | })
39 | }
40 |
41 | /* APPLY TO STANDARD DROPDOWN ELEMENTS
42 | * =================================== */
43 |
44 | var d = 'a.menu, .dropdown-toggle'
45 |
46 | function clearMenus() {
47 | $(d).parent('li').removeClass('open')
48 | }
49 |
50 | $(function () {
51 | $('html').bind("click", clearMenus)
52 | $('body').dropdown( '[data-dropdown] a.menu, [data-dropdown] .dropdown-toggle' )
53 | })
54 |
55 | }( window.jQuery || window.ender );
56 |
--------------------------------------------------------------------------------
/resources/cascade/bootstrap-modal.js:
--------------------------------------------------------------------------------
1 | /* =========================================================
2 | * bootstrap-modal.js v1.4.0
3 | * http://twitter.github.com/bootstrap/javascript.html#modal
4 | * =========================================================
5 | * Copyright 2011 Twitter, Inc.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | * ========================================================= */
19 |
20 |
21 | !function( $ ){
22 |
23 | "use strict"
24 |
25 | /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)
26 | * ======================================================= */
27 |
28 | var transitionEnd
29 |
30 | $(document).ready(function () {
31 |
32 | $.support.transition = (function () {
33 | var thisBody = document.body || document.documentElement
34 | , thisStyle = thisBody.style
35 | , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined
36 | return support
37 | })()
38 |
39 | // set CSS transition event type
40 | if ( $.support.transition ) {
41 | transitionEnd = "TransitionEnd"
42 | if ( $.browser.webkit ) {
43 | transitionEnd = "webkitTransitionEnd"
44 | } else if ( $.browser.mozilla ) {
45 | transitionEnd = "transitionend"
46 | } else if ( $.browser.opera ) {
47 | transitionEnd = "oTransitionEnd"
48 | }
49 | }
50 |
51 | })
52 |
53 |
54 | /* MODAL PUBLIC CLASS DEFINITION
55 | * ============================= */
56 |
57 | var Modal = function ( content, options ) {
58 | this.settings = $.extend({}, $.fn.modal.defaults, options)
59 | this.$element = $(content)
60 | .delegate('.close', 'click.modal', $.proxy(this.hide, this))
61 |
62 | if ( this.settings.show ) {
63 | this.show()
64 | }
65 |
66 | return this
67 | }
68 |
69 | Modal.prototype = {
70 |
71 | toggle: function () {
72 | return this[!this.isShown ? 'show' : 'hide']()
73 | }
74 |
75 | , show: function () {
76 | var that = this
77 | this.isShown = true
78 | this.$element.trigger('show')
79 |
80 | escape.call(this)
81 | backdrop.call(this, function () {
82 | var transition = $.support.transition && that.$element.hasClass('fade')
83 |
84 | that.$element
85 | .appendTo(document.body)
86 | .show()
87 |
88 | if (transition) {
89 | that.$element[0].offsetWidth // force reflow
90 | }
91 |
92 | that.$element.addClass('in')
93 |
94 | transition ?
95 | that.$element.one(transitionEnd, function () { that.$element.trigger('shown') }) :
96 | that.$element.trigger('shown')
97 |
98 | })
99 |
100 | return this
101 | }
102 |
103 | , hide: function (e) {
104 | e && e.preventDefault()
105 |
106 | if ( !this.isShown ) {
107 | return this
108 | }
109 |
110 | var that = this
111 | this.isShown = false
112 |
113 | escape.call(this)
114 |
115 | this.$element
116 | .trigger('hide')
117 | .removeClass('in')
118 |
119 | $.support.transition && this.$element.hasClass('fade') ?
120 | hideWithTransition.call(this) :
121 | hideModal.call(this)
122 |
123 | return this
124 | }
125 |
126 | }
127 |
128 |
129 | /* MODAL PRIVATE METHODS
130 | * ===================== */
131 |
132 | function hideWithTransition() {
133 | // firefox drops transitionEnd events :{o
134 | var that = this
135 | , timeout = setTimeout(function () {
136 | that.$element.unbind(transitionEnd)
137 | hideModal.call(that)
138 | }, 500)
139 |
140 | this.$element.one(transitionEnd, function () {
141 | clearTimeout(timeout)
142 | hideModal.call(that)
143 | })
144 | }
145 |
146 | function hideModal (that) {
147 | this.$element
148 | .hide()
149 | .trigger('hidden')
150 |
151 | backdrop.call(this)
152 | }
153 |
154 | function backdrop ( callback ) {
155 | var that = this
156 | , animate = this.$element.hasClass('fade') ? 'fade' : ''
157 | if ( this.isShown && this.settings.backdrop ) {
158 | var doAnimate = $.support.transition && animate
159 |
160 | this.$backdrop = $('
')
161 | .appendTo(document.body)
162 |
163 | if ( this.settings.backdrop != 'static' ) {
164 | this.$backdrop.click($.proxy(this.hide, this))
165 | }
166 |
167 | if ( doAnimate ) {
168 | this.$backdrop[0].offsetWidth // force reflow
169 | }
170 |
171 | this.$backdrop.addClass('in')
172 |
173 | doAnimate ?
174 | this.$backdrop.one(transitionEnd, callback) :
175 | callback()
176 |
177 | } else if ( !this.isShown && this.$backdrop ) {
178 | this.$backdrop.removeClass('in')
179 |
180 | $.support.transition && this.$element.hasClass('fade')?
181 | this.$backdrop.one(transitionEnd, $.proxy(removeBackdrop, this)) :
182 | removeBackdrop.call(this)
183 |
184 | } else if ( callback ) {
185 | callback()
186 | }
187 | }
188 |
189 | function removeBackdrop() {
190 | this.$backdrop.remove()
191 | this.$backdrop = null
192 | }
193 |
194 | function escape() {
195 | var that = this
196 | if ( this.isShown && this.settings.keyboard ) {
197 | $(document).bind('keyup.modal', function ( e ) {
198 | if ( e.which == 27 ) {
199 | that.hide()
200 | }
201 | })
202 | } else if ( !this.isShown ) {
203 | $(document).unbind('keyup.modal')
204 | }
205 | }
206 |
207 |
208 | /* MODAL PLUGIN DEFINITION
209 | * ======================= */
210 |
211 | $.fn.modal = function ( options ) {
212 | var modal = this.data('modal')
213 |
214 | if (!modal) {
215 |
216 | if (typeof options == 'string') {
217 | options = {
218 | show: /show|toggle/.test(options)
219 | }
220 | }
221 |
222 | return this.each(function () {
223 | $(this).data('modal', new Modal(this, options))
224 | })
225 | }
226 |
227 | if ( options === true ) {
228 | return modal
229 | }
230 |
231 | if ( typeof options == 'string' ) {
232 | modal[options]()
233 | } else if ( modal ) {
234 | modal.toggle()
235 | }
236 |
237 | return this
238 | }
239 |
240 | $.fn.modal.Modal = Modal
241 |
242 | $.fn.modal.defaults = {
243 | backdrop: false
244 | , keyboard: false
245 | , show: false
246 | }
247 |
248 |
249 | /* MODAL DATA- IMPLEMENTATION
250 | * ========================== */
251 |
252 | $(document).ready(function () {
253 | $('body').delegate('[data-controls-modal]', 'click', function (e) {
254 | e.preventDefault()
255 | var $this = $(this).data('show', true)
256 | $('#' + $this.attr('data-controls-modal')).modal( $this.data() )
257 | })
258 | })
259 |
260 | }( window.jQuery || window.ender );
261 |
--------------------------------------------------------------------------------
/resources/cascade/bootstrap-popover.js:
--------------------------------------------------------------------------------
1 | /* ===========================================================
2 | * bootstrap-popover.js v1.4.0
3 | * http://twitter.github.com/bootstrap/javascript.html#popover
4 | * ===========================================================
5 | * Copyright 2011 Twitter, Inc.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | * =========================================================== */
19 |
20 |
21 | !function( $ ) {
22 |
23 | "use strict"
24 |
25 | var Popover = function ( element, options ) {
26 | this.$element = $(element)
27 | this.options = options
28 | this.enabled = true
29 | this.fixTitle()
30 | }
31 |
32 | /* NOTE: POPOVER EXTENDS BOOTSTRAP-TWIPSY.js
33 | ========================================= */
34 |
35 | Popover.prototype = $.extend({}, $.fn.twipsy.Twipsy.prototype, {
36 |
37 | setContent: function () {
38 | var $tip = this.tip()
39 | $tip.find('.title')[this.options.html ? 'html' : 'text'](this.getTitle())
40 | $tip.find('.content p')[this.options.html ? 'html' : 'text'](this.getContent())
41 | $tip[0].className = 'popover'
42 | }
43 |
44 | , hasContent: function () {
45 | return this.getTitle() || this.getContent()
46 | }
47 |
48 | , getContent: function () {
49 | var content
50 | , $e = this.$element
51 | , o = this.options
52 |
53 | if (typeof this.options.content == 'string') {
54 | content = this.options.content
55 | } else if (typeof this.options.content == 'function') {
56 | content = this.options.content.call(this.$element[0])
57 | }
58 | return content
59 | }
60 |
61 | , tip: function() {
62 | if (!this.$tip) {
63 | this.$tip = $('
')
64 | .html(this.options.template)
65 | }
66 | return this.$tip
67 | }
68 |
69 | })
70 |
71 |
72 | /* POPOVER PLUGIN DEFINITION
73 | * ======================= */
74 |
75 | $.fn.popover = function (options) {
76 | if (typeof options == 'object') options = $.extend({}, $.fn.popover.defaults, options)
77 | $.fn.twipsy.initWith.call(this, options, Popover, 'popover')
78 | return this
79 | }
80 |
81 | $.fn.popover.defaults = $.extend({} , $.fn.twipsy.defaults, {
82 | placement: 'right'
83 | , template: '
'
84 | })
85 |
86 | }( window.jQuery || window.ender );
--------------------------------------------------------------------------------
/resources/cascade/bootstrap-scrollspy.js:
--------------------------------------------------------------------------------
1 | /* =============================================================
2 | * bootstrap-scrollspy.js v1.4.0
3 | * http://twitter.github.com/bootstrap/javascript.html#scrollspy
4 | * =============================================================
5 | * Copyright 2011 Twitter, Inc.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | * ============================================================== */
19 |
20 |
21 | !function ( $ ) {
22 |
23 | "use strict"
24 |
25 | var $window = $(window)
26 |
27 | function ScrollSpy( topbar, selector ) {
28 | var processScroll = $.proxy(this.processScroll, this)
29 | this.$topbar = $(topbar)
30 | this.selector = selector || 'li > a'
31 | this.refresh()
32 | this.$topbar.delegate(this.selector, 'click', processScroll)
33 | $window.scroll(processScroll)
34 | this.processScroll()
35 | }
36 |
37 | ScrollSpy.prototype = {
38 |
39 | refresh: function () {
40 | this.targets = this.$topbar.find(this.selector).map(function () {
41 | var href = $(this).attr('href')
42 | return /^#\w/.test(href) && $(href).length ? href : null
43 | })
44 |
45 | this.offsets = $.map(this.targets, function (id) {
46 | return $(id).offset().top
47 | })
48 | }
49 |
50 | , processScroll: function () {
51 | var scrollTop = $window.scrollTop() + 10
52 | , offsets = this.offsets
53 | , targets = this.targets
54 | , activeTarget = this.activeTarget
55 | , i
56 |
57 | for (i = offsets.length; i--;) {
58 | activeTarget != targets[i]
59 | && scrollTop >= offsets[i]
60 | && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
61 | && this.activateButton( targets[i] )
62 | }
63 | }
64 |
65 | , activateButton: function (target) {
66 | this.activeTarget = target
67 |
68 | this.$topbar
69 | .find(this.selector).parent('.active')
70 | .removeClass('active')
71 |
72 | this.$topbar
73 | .find(this.selector + '[href="' + target + '"]')
74 | .parent('li')
75 | .addClass('active')
76 | }
77 |
78 | }
79 |
80 | /* SCROLLSPY PLUGIN DEFINITION
81 | * =========================== */
82 |
83 | $.fn.scrollSpy = function( options ) {
84 | var scrollspy = this.data('scrollspy')
85 |
86 | if (!scrollspy) {
87 | return this.each(function () {
88 | $(this).data('scrollspy', new ScrollSpy( this, options ))
89 | })
90 | }
91 |
92 | if ( options === true ) {
93 | return scrollspy
94 | }
95 |
96 | if ( typeof options == 'string' ) {
97 | scrollspy[options]()
98 | }
99 |
100 | return this
101 | }
102 |
103 | $(document).ready(function () {
104 | $('body').scrollSpy('[data-scrollspy] li > a')
105 | })
106 |
107 | }( window.jQuery || window.ender );
--------------------------------------------------------------------------------
/resources/cascade/bootstrap-tabs.js:
--------------------------------------------------------------------------------
1 | /* ========================================================
2 | * bootstrap-tabs.js v1.4.0
3 | * http://twitter.github.com/bootstrap/javascript.html#tabs
4 | * ========================================================
5 | * Copyright 2011 Twitter, Inc.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | * ======================================================== */
19 |
20 |
21 | !function( $ ){
22 |
23 | "use strict"
24 |
25 | function activate ( element, container ) {
26 | container
27 | .find('> .active')
28 | .removeClass('active')
29 | .find('> .dropdown-menu > .active')
30 | .removeClass('active')
31 |
32 | element.addClass('active')
33 |
34 | if ( element.parent('.dropdown-menu') ) {
35 | element.closest('li.dropdown').addClass('active')
36 | }
37 | }
38 |
39 | function tab( e ) {
40 | var $this = $(this)
41 | , $ul = $this.closest('ul:not(.dropdown-menu)')
42 | , href = $this.attr('href')
43 | , previous
44 | , $href
45 |
46 | if ( /^#\w+/.test(href) ) {
47 | e.preventDefault()
48 |
49 | if ( $this.parent('li').hasClass('active') ) {
50 | return
51 | }
52 |
53 | previous = $ul.find('.active a').last()[0]
54 | $href = $(href)
55 |
56 | activate($this.parent('li'), $ul)
57 | activate($href, $href.parent())
58 |
59 | $this.trigger({
60 | type: 'change'
61 | , relatedTarget: previous
62 | })
63 | }
64 | }
65 |
66 |
67 | /* TABS/PILLS PLUGIN DEFINITION
68 | * ============================ */
69 |
70 | $.fn.tabs = $.fn.pills = function ( selector ) {
71 | return this.each(function () {
72 | $(this).delegate(selector || '.tabs li > a, .pills > li > a', 'click', tab)
73 | })
74 | }
75 |
76 | $(document).ready(function () {
77 | $('body').tabs('ul[data-tabs] li > a, ul[data-pills] > li > a')
78 | })
79 |
80 | }( window.jQuery || window.ender );
81 |
--------------------------------------------------------------------------------
/resources/cascade/bootstrap-twipsy.js:
--------------------------------------------------------------------------------
1 | /* ==========================================================
2 | * bootstrap-twipsy.js v1.4.0
3 | * http://twitter.github.com/bootstrap/javascript.html#twipsy
4 | * Adapted from the original jQuery.tipsy by Jason Frame
5 | * ==========================================================
6 | * Copyright 2011 Twitter, Inc.
7 | *
8 | * Licensed under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | * ========================================================== */
20 |
21 |
22 | !function( $ ) {
23 |
24 | "use strict"
25 |
26 | /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)
27 | * ======================================================= */
28 |
29 | var transitionEnd
30 |
31 | $(document).ready(function () {
32 |
33 | $.support.transition = (function () {
34 | var thisBody = document.body || document.documentElement
35 | , thisStyle = thisBody.style
36 | , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined
37 | return support
38 | })()
39 |
40 | // set CSS transition event type
41 | if ( $.support.transition ) {
42 | transitionEnd = "TransitionEnd"
43 | if ( $.browser.webkit ) {
44 | transitionEnd = "webkitTransitionEnd"
45 | } else if ( $.browser.mozilla ) {
46 | transitionEnd = "transitionend"
47 | } else if ( $.browser.opera ) {
48 | transitionEnd = "oTransitionEnd"
49 | }
50 | }
51 |
52 | })
53 |
54 |
55 | /* TWIPSY PUBLIC CLASS DEFINITION
56 | * ============================== */
57 |
58 | var Twipsy = function ( element, options ) {
59 | this.$element = $(element)
60 | this.options = options
61 | this.enabled = true
62 | this.fixTitle()
63 | }
64 |
65 | Twipsy.prototype = {
66 |
67 | show: function() {
68 | var pos
69 | , actualWidth
70 | , actualHeight
71 | , placement
72 | , $tip
73 | , tp
74 |
75 | if (this.hasContent() && this.enabled) {
76 | $tip = this.tip()
77 | this.setContent()
78 |
79 | if (this.options.animate) {
80 | $tip.addClass('fade')
81 | }
82 |
83 | $tip
84 | .remove()
85 | .css({ top: 0, left: 0, display: 'block' })
86 | .prependTo(document.body)
87 |
88 | pos = $.extend({}, this.$element.offset(), {
89 | width: this.$element[0].offsetWidth
90 | , height: this.$element[0].offsetHeight
91 | })
92 |
93 | actualWidth = $tip[0].offsetWidth
94 | actualHeight = $tip[0].offsetHeight
95 |
96 | placement = maybeCall(this.options.placement, this, [ $tip[0], this.$element[0] ])
97 |
98 | switch (placement) {
99 | case 'below':
100 | tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}
101 | break
102 | case 'above':
103 | tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2}
104 | break
105 | case 'left':
106 | tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset}
107 | break
108 | case 'right':
109 | tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset}
110 | break
111 | }
112 |
113 | $tip
114 | .css(tp)
115 | .addClass(placement)
116 | .addClass('in')
117 | }
118 | }
119 |
120 | , setContent: function () {
121 | var $tip = this.tip()
122 | $tip.find('.twipsy-inner')[this.options.html ? 'html' : 'text'](this.getTitle())
123 | $tip[0].className = 'twipsy'
124 | }
125 |
126 | , hide: function() {
127 | var that = this
128 | , $tip = this.tip()
129 |
130 | $tip.removeClass('in')
131 |
132 | function removeElement () {
133 | $tip.remove()
134 | }
135 |
136 | $.support.transition && this.$tip.hasClass('fade') ?
137 | $tip.bind(transitionEnd, removeElement) :
138 | removeElement()
139 | }
140 |
141 | , fixTitle: function() {
142 | var $e = this.$element
143 | if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
144 | $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
145 | }
146 | }
147 |
148 | , hasContent: function () {
149 | return this.getTitle()
150 | }
151 |
152 | , getTitle: function() {
153 | var title
154 | , $e = this.$element
155 | , o = this.options
156 |
157 | this.fixTitle()
158 |
159 | if (typeof o.title == 'string') {
160 | title = $e.attr(o.title == 'title' ? 'data-original-title' : o.title)
161 | } else if (typeof o.title == 'function') {
162 | title = o.title.call($e[0])
163 | }
164 |
165 | title = ('' + title).replace(/(^\s*|\s*$)/, "")
166 |
167 | return title || o.fallback
168 | }
169 |
170 | , tip: function() {
171 | if (!this.$tip) {
172 | this.$tip = $('
').html(this.options.template)
173 | }
174 | return this.$tip
175 | }
176 |
177 | , validate: function() {
178 | if (!this.$element[0].parentNode) {
179 | this.hide()
180 | this.$element = null
181 | this.options = null
182 | }
183 | }
184 |
185 | , enable: function() {
186 | this.enabled = true
187 | }
188 |
189 | , disable: function() {
190 | this.enabled = false
191 | }
192 |
193 | , toggleEnabled: function() {
194 | this.enabled = !this.enabled
195 | }
196 |
197 | }
198 |
199 |
200 | /* TWIPSY PRIVATE METHODS
201 | * ====================== */
202 |
203 | function maybeCall ( thing, ctx, args ) {
204 | return typeof thing == 'function' ? thing.apply(ctx, args) : thing
205 | }
206 |
207 | /* TWIPSY PLUGIN DEFINITION
208 | * ======================== */
209 |
210 | $.fn.twipsy = function (options) {
211 | $.fn.twipsy.initWith.call(this, options, Twipsy, 'twipsy')
212 | return this
213 | }
214 |
215 | $.fn.twipsy.initWith = function (options, Constructor, name) {
216 | var twipsy
217 | , binder
218 | , eventIn
219 | , eventOut
220 |
221 | if (options === true) {
222 | return this.data(name)
223 | } else if (typeof options == 'string') {
224 | twipsy = this.data(name)
225 | if (twipsy) {
226 | twipsy[options]()
227 | }
228 | return this
229 | }
230 |
231 | options = $.extend({}, $.fn[name].defaults, options)
232 |
233 | function get(ele) {
234 | var twipsy = $.data(ele, name)
235 |
236 | if (!twipsy) {
237 | twipsy = new Constructor(ele, $.fn.twipsy.elementOptions(ele, options))
238 | $.data(ele, name, twipsy)
239 | }
240 |
241 | return twipsy
242 | }
243 |
244 | function enter() {
245 | var twipsy = get(this)
246 | twipsy.hoverState = 'in'
247 |
248 | if (options.delayIn == 0) {
249 | twipsy.show()
250 | } else {
251 | twipsy.fixTitle()
252 | setTimeout(function() {
253 | if (twipsy.hoverState == 'in') {
254 | twipsy.show()
255 | }
256 | }, options.delayIn)
257 | }
258 | }
259 |
260 | function leave() {
261 | var twipsy = get(this)
262 | twipsy.hoverState = 'out'
263 | if (options.delayOut == 0) {
264 | twipsy.hide()
265 | } else {
266 | setTimeout(function() {
267 | if (twipsy.hoverState == 'out') {
268 | twipsy.hide()
269 | }
270 | }, options.delayOut)
271 | }
272 | }
273 |
274 | if (!options.live) {
275 | this.each(function() {
276 | get(this)
277 | })
278 | }
279 |
280 | if (options.trigger != 'manual') {
281 | binder = options.live ? 'live' : 'bind'
282 | eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus'
283 | eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur'
284 | this[binder](eventIn, enter)[binder](eventOut, leave)
285 | }
286 |
287 | return this
288 | }
289 |
290 | $.fn.twipsy.Twipsy = Twipsy
291 |
292 | $.fn.twipsy.defaults = {
293 | animate: true
294 | , delayIn: 0
295 | , delayOut: 0
296 | , fallback: ''
297 | , placement: 'above'
298 | , html: false
299 | , live: false
300 | , offset: 0
301 | , title: 'title'
302 | , trigger: 'hover'
303 | , template: '
'
304 | }
305 |
306 | $.fn.twipsy.elementOptions = function(ele, options) {
307 | return $.extend({}, options, $(ele).data())
308 | }
309 |
310 | }( window.jQuery || window.ender );
--------------------------------------------------------------------------------
/resources/cascade/bootstrap.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v1.4.0
3 | *
4 | * Copyright 2011 Twitter, Inc
5 | * Licensed under the Apache License v2.0
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Designed and built with all the love in the world @twitter by @mdo and @fat.
9 | * Date: Thu Nov 3 17:06:17 PDT 2011
10 | */
11 | /* Reset.less
12 | * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc).
13 | * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
14 | html, body {
15 | margin: 0;
16 | padding: 0;
17 | }
18 | h1,
19 | h2,
20 | h3,
21 | h4,
22 | h5,
23 | h6,
24 | p,
25 | blockquote,
26 | pre,
27 | a,
28 | abbr,
29 | acronym,
30 | address,
31 | cite,
32 | code,
33 | del,
34 | dfn,
35 | em,
36 | img,
37 | q,
38 | s,
39 | samp,
40 | small,
41 | strike,
42 | strong,
43 | sub,
44 | sup,
45 | tt,
46 | var,
47 | dd,
48 | dl,
49 | dt,
50 | li,
51 | ol,
52 | ul,
53 | fieldset,
54 | form,
55 | label,
56 | legend,
57 | button,
58 | table,
59 | caption,
60 | tbody,
61 | tfoot,
62 | thead,
63 | tr,
64 | th,
65 | td {
66 | margin: 0;
67 | padding: 0;
68 | border: 0;
69 | font-weight: normal;
70 | font-style: normal;
71 | font-size: 100%;
72 | line-height: 1;
73 | font-family: inherit;
74 | }
75 | table {
76 | border-collapse: collapse;
77 | border-spacing: 0;
78 | }
79 | ol, ul {
80 | list-style: none;
81 | }
82 | q:before,
83 | q:after,
84 | blockquote:before,
85 | blockquote:after {
86 | content: "";
87 | }
88 | html {
89 | overflow-y: scroll;
90 | font-size: 100%;
91 | -webkit-text-size-adjust: 100%;
92 | -ms-text-size-adjust: 100%;
93 | }
94 | a:focus {
95 | outline: thin dotted;
96 | }
97 | a:hover, a:active {
98 | outline: 0;
99 | }
100 | article,
101 | aside,
102 | details,
103 | figcaption,
104 | figure,
105 | footer,
106 | header,
107 | hgroup,
108 | nav,
109 | section {
110 | display: block;
111 | }
112 | audio, canvas, video {
113 | display: inline-block;
114 | *display: inline;
115 | *zoom: 1;
116 | }
117 | audio:not([controls]) {
118 | display: none;
119 | }
120 | sub, sup {
121 | font-size: 75%;
122 | line-height: 0;
123 | position: relative;
124 | vertical-align: baseline;
125 | }
126 | sup {
127 | top: -0.5em;
128 | }
129 | sub {
130 | bottom: -0.25em;
131 | }
132 | img {
133 | border: 0;
134 | -ms-interpolation-mode: bicubic;
135 | }
136 | button,
137 | input,
138 | select,
139 | textarea {
140 | font-size: 100%;
141 | margin: 0;
142 | vertical-align: baseline;
143 | *vertical-align: middle;
144 | }
145 | button, input {
146 | line-height: normal;
147 | *overflow: visible;
148 | }
149 | button::-moz-focus-inner, input::-moz-focus-inner {
150 | border: 0;
151 | padding: 0;
152 | }
153 | button,
154 | input[type="button"],
155 | input[type="reset"],
156 | input[type="submit"] {
157 | cursor: pointer;
158 | -webkit-appearance: button;
159 | }
160 | input[type="search"] {
161 | -webkit-appearance: textfield;
162 | -webkit-box-sizing: content-box;
163 | -moz-box-sizing: content-box;
164 | box-sizing: content-box;
165 | }
166 | input[type="search"]::-webkit-search-decoration {
167 | -webkit-appearance: none;
168 | }
169 | textarea {
170 | overflow: auto;
171 | vertical-align: top;
172 | }
173 | /* Variables.less
174 | * Variables to customize the look and feel of Bootstrap
175 | * ----------------------------------------------------- */
176 | /* Mixins.less
177 | * Snippets of reusable CSS to develop faster and keep code readable
178 | * ----------------------------------------------------------------- */
179 | /*
180 | * Scaffolding
181 | * Basic and global styles for generating a grid system, structural layout, and page templates
182 | * ------------------------------------------------------------------------------------------- */
183 | body {
184 | background-color: #ffffff;
185 | margin: 0;
186 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
187 | font-size: 13px;
188 | font-weight: normal;
189 | line-height: 18px;
190 | color: #404040;
191 | }
192 | .container {
193 | width: 940px;
194 | margin-left: auto;
195 | margin-right: auto;
196 | zoom: 1;
197 | }
198 | .container:before, .container:after {
199 | display: table;
200 | content: "";
201 | zoom: 1;
202 | }
203 | .container:after {
204 | clear: both;
205 | }
206 | .container-fluid {
207 | position: relative;
208 | min-width: 940px;
209 | padding-left: 20px;
210 | padding-right: 20px;
211 | zoom: 1;
212 | }
213 | .container-fluid:before, .container-fluid:after {
214 | display: table;
215 | content: "";
216 | zoom: 1;
217 | }
218 | .container-fluid:after {
219 | clear: both;
220 | }
221 | .container-fluid > .sidebar {
222 | position: absolute;
223 | top: 0;
224 | left: 20px;
225 | width: 220px;
226 | }
227 | .container-fluid > .content {
228 | margin-left: 240px;
229 | }
230 | a {
231 | color: #0069d6;
232 | text-decoration: none;
233 | line-height: inherit;
234 | font-weight: inherit;
235 | }
236 | a:hover {
237 | color: #00438a;
238 | text-decoration: underline;
239 | }
240 | .pull-right {
241 | float: right;
242 | }
243 | .pull-left {
244 | float: left;
245 | }
246 | .hide {
247 | display: none;
248 | }
249 | .show {
250 | display: block;
251 | }
252 | .row {
253 | zoom: 1;
254 | margin-left: -20px;
255 | }
256 | .row:before, .row:after {
257 | display: table;
258 | content: "";
259 | zoom: 1;
260 | }
261 | .row:after {
262 | clear: both;
263 | }
264 | .row > [class*="span"] {
265 | display: inline;
266 | float: left;
267 | margin-left: 20px;
268 | }
269 | .span1 {
270 | width: 40px;
271 | }
272 | .span2 {
273 | width: 100px;
274 | }
275 | .span3 {
276 | width: 160px;
277 | }
278 | .span4 {
279 | width: 220px;
280 | }
281 | .span5 {
282 | width: 280px;
283 | }
284 | .span6 {
285 | width: 340px;
286 | }
287 | .span7 {
288 | width: 400px;
289 | }
290 | .span8 {
291 | width: 460px;
292 | }
293 | .span9 {
294 | width: 520px;
295 | }
296 | .span10 {
297 | width: 580px;
298 | }
299 | .span11 {
300 | width: 640px;
301 | }
302 | .span12 {
303 | width: 700px;
304 | }
305 | .span13 {
306 | width: 760px;
307 | }
308 | .span14 {
309 | width: 820px;
310 | }
311 | .span15 {
312 | width: 880px;
313 | }
314 | .span16 {
315 | width: 940px;
316 | }
317 | .span17 {
318 | width: 1000px;
319 | }
320 | .span18 {
321 | width: 1060px;
322 | }
323 | .span19 {
324 | width: 1120px;
325 | }
326 | .span20 {
327 | width: 1180px;
328 | }
329 | .span21 {
330 | width: 1240px;
331 | }
332 | .span22 {
333 | width: 1300px;
334 | }
335 | .span23 {
336 | width: 1360px;
337 | }
338 | .span24 {
339 | width: 1420px;
340 | }
341 | .row > .offset1 {
342 | margin-left: 80px;
343 | }
344 | .row > .offset2 {
345 | margin-left: 140px;
346 | }
347 | .row > .offset3 {
348 | margin-left: 200px;
349 | }
350 | .row > .offset4 {
351 | margin-left: 260px;
352 | }
353 | .row > .offset5 {
354 | margin-left: 320px;
355 | }
356 | .row > .offset6 {
357 | margin-left: 380px;
358 | }
359 | .row > .offset7 {
360 | margin-left: 440px;
361 | }
362 | .row > .offset8 {
363 | margin-left: 500px;
364 | }
365 | .row > .offset9 {
366 | margin-left: 560px;
367 | }
368 | .row > .offset10 {
369 | margin-left: 620px;
370 | }
371 | .row > .offset11 {
372 | margin-left: 680px;
373 | }
374 | .row > .offset12 {
375 | margin-left: 740px;
376 | }
377 | .span-one-third {
378 | width: 300px;
379 | }
380 | .span-two-thirds {
381 | width: 620px;
382 | }
383 | .offset-one-third {
384 | margin-left: 340px;
385 | }
386 | .offset-two-thirds {
387 | margin-left: 660px;
388 | }
389 | /* Typography.less
390 | * Headings, body text, lists, code, and more for a versatile and durable typography system
391 | * ---------------------------------------------------------------------------------------- */
392 | p {
393 | font-size: 13px;
394 | font-weight: normal;
395 | line-height: 18px;
396 | margin-bottom: 9px;
397 | }
398 | p small {
399 | font-size: 11px;
400 | color: #bfbfbf;
401 | }
402 | h1,
403 | h2,
404 | h3,
405 | h4,
406 | h5,
407 | h6 {
408 | font-weight: bold;
409 | color: #404040;
410 | }
411 | h1 small,
412 | h2 small,
413 | h3 small,
414 | h4 small,
415 | h5 small,
416 | h6 small {
417 | color: #bfbfbf;
418 | }
419 | h1 {
420 | margin-bottom: 18px;
421 | font-size: 30px;
422 | line-height: 36px;
423 | }
424 | h1 small {
425 | font-size: 18px;
426 | }
427 | h2 {
428 | font-size: 24px;
429 | line-height: 36px;
430 | }
431 | h2 small {
432 | font-size: 14px;
433 | }
434 | h3,
435 | h4,
436 | h5,
437 | h6 {
438 | line-height: 36px;
439 | }
440 | h3 {
441 | font-size: 18px;
442 | }
443 | h3 small {
444 | font-size: 14px;
445 | }
446 | h4 {
447 | font-size: 16px;
448 | }
449 | h4 small {
450 | font-size: 12px;
451 | }
452 | h5 {
453 | font-size: 14px;
454 | }
455 | h6 {
456 | font-size: 13px;
457 | color: #bfbfbf;
458 | text-transform: uppercase;
459 | }
460 | ul, ol {
461 | margin: 0 0 18px 25px;
462 | }
463 | ul ul,
464 | ul ol,
465 | ol ol,
466 | ol ul {
467 | margin-bottom: 0;
468 | }
469 | ul {
470 | list-style: disc;
471 | }
472 | ol {
473 | list-style: decimal;
474 | }
475 | li {
476 | line-height: 18px;
477 | color: #808080;
478 | }
479 | ul.unstyled {
480 | list-style: none;
481 | margin-left: 0;
482 | }
483 | dl {
484 | margin-bottom: 18px;
485 | }
486 | dl dt, dl dd {
487 | line-height: 18px;
488 | }
489 | dl dt {
490 | font-weight: bold;
491 | }
492 | dl dd {
493 | margin-left: 9px;
494 | }
495 | hr {
496 | margin: 20px 0 19px;
497 | border: 0;
498 | border-bottom: 1px solid #eee;
499 | }
500 | strong {
501 | font-style: inherit;
502 | font-weight: bold;
503 | }
504 | em {
505 | font-style: italic;
506 | font-weight: inherit;
507 | line-height: inherit;
508 | }
509 | .muted {
510 | color: #bfbfbf;
511 | }
512 | blockquote {
513 | margin-bottom: 18px;
514 | border-left: 5px solid #eee;
515 | padding-left: 15px;
516 | }
517 | blockquote p {
518 | font-size: 14px;
519 | font-weight: 300;
520 | line-height: 18px;
521 | margin-bottom: 0;
522 | }
523 | blockquote small {
524 | display: block;
525 | font-size: 12px;
526 | font-weight: 300;
527 | line-height: 18px;
528 | color: #bfbfbf;
529 | }
530 | blockquote small:before {
531 | content: '\2014 \00A0';
532 | }
533 | address {
534 | display: block;
535 | line-height: 18px;
536 | margin-bottom: 18px;
537 | }
538 | code, pre {
539 | padding: 0 3px 2px;
540 | font-family: Monaco, Andale Mono, Courier New, monospace;
541 | font-size: 12px;
542 | -webkit-border-radius: 3px;
543 | -moz-border-radius: 3px;
544 | border-radius: 3px;
545 | }
546 | code {
547 | background-color: #fee9cc;
548 | color: rgba(0, 0, 0, 0.75);
549 | padding: 1px 3px;
550 | }
551 | pre {
552 | background-color: #f5f5f5;
553 | display: block;
554 | padding: 8.5px;
555 | margin: 0 0 18px;
556 | line-height: 18px;
557 | font-size: 12px;
558 | border: 1px solid #ccc;
559 | border: 1px solid rgba(0, 0, 0, 0.15);
560 | -webkit-border-radius: 3px;
561 | -moz-border-radius: 3px;
562 | border-radius: 3px;
563 | white-space: pre;
564 | white-space: pre-wrap;
565 | word-wrap: break-word;
566 | }
567 | /* Forms.less
568 | * Base styles for various input types, form layouts, and states
569 | * ------------------------------------------------------------- */
570 | form {
571 | margin-bottom: 18px;
572 | }
573 | fieldset {
574 | margin-bottom: 18px;
575 | padding-top: 18px;
576 | }
577 | fieldset legend {
578 | display: block;
579 | padding-left: 150px;
580 | font-size: 19.5px;
581 | line-height: 1;
582 | color: #404040;
583 | *padding: 0 0 5px 145px;
584 | /* IE6-7 */
585 |
586 | *line-height: 1.5;
587 | /* IE6-7 */
588 |
589 | }
590 | form .clearfix {
591 | margin-bottom: 18px;
592 | zoom: 1;
593 | }
594 | form .clearfix:before, form .clearfix:after {
595 | display: table;
596 | content: "";
597 | zoom: 1;
598 | }
599 | form .clearfix:after {
600 | clear: both;
601 | }
602 | label,
603 | input,
604 | select,
605 | textarea {
606 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
607 | font-size: 13px;
608 | font-weight: normal;
609 | line-height: normal;
610 | }
611 | label {
612 | padding-top: 6px;
613 | font-size: 13px;
614 | line-height: 18px;
615 | float: left;
616 | width: 130px;
617 | text-align: right;
618 | color: #404040;
619 | }
620 | form .input {
621 | margin-left: 150px;
622 | }
623 | input[type=checkbox], input[type=radio] {
624 | cursor: pointer;
625 | }
626 | input,
627 | textarea,
628 | select,
629 | .uneditable-input {
630 | display: inline-block;
631 | width: 210px;
632 | height: 18px;
633 | padding: 4px;
634 | font-size: 13px;
635 | line-height: 18px;
636 | color: #808080;
637 | border: 1px solid #ccc;
638 | -webkit-border-radius: 3px;
639 | -moz-border-radius: 3px;
640 | border-radius: 3px;
641 | }
642 | select {
643 | padding: initial;
644 | }
645 | input[type=checkbox], input[type=radio] {
646 | width: auto;
647 | height: auto;
648 | padding: 0;
649 | margin: 3px 0;
650 | *margin-top: 0;
651 | /* IE6-7 */
652 |
653 | line-height: normal;
654 | border: none;
655 | }
656 | input[type=file] {
657 | background-color: #ffffff;
658 | padding: initial;
659 | border: initial;
660 | line-height: initial;
661 | -webkit-box-shadow: none;
662 | -moz-box-shadow: none;
663 | box-shadow: none;
664 | }
665 | input[type=button], input[type=reset], input[type=submit] {
666 | width: auto;
667 | height: auto;
668 | }
669 | select, input[type=file] {
670 | height: 27px;
671 | *height: auto;
672 | line-height: 27px;
673 | *margin-top: 4px;
674 | /* For IE7, add top margin to align select with labels */
675 |
676 | }
677 | select[multiple] {
678 | height: inherit;
679 | background-color: #ffffff;
680 | }
681 | textarea {
682 | height: auto;
683 | }
684 | .uneditable-input {
685 | background-color: #ffffff;
686 | display: block;
687 | border-color: #eee;
688 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
689 | -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
690 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
691 | cursor: not-allowed;
692 | }
693 | :-moz-placeholder {
694 | color: #bfbfbf;
695 | }
696 | ::-webkit-input-placeholder {
697 | color: #bfbfbf;
698 | }
699 | input, textarea {
700 | -webkit-transform-style: preserve-3d;
701 | -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
702 | -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
703 | -ms-transition: border linear 0.2s, box-shadow linear 0.2s;
704 | -o-transition: border linear 0.2s, box-shadow linear 0.2s;
705 | transition: border linear 0.2s, box-shadow linear 0.2s;
706 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
707 | -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
708 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
709 | }
710 | input:focus, textarea:focus {
711 | outline: 0;
712 | border-color: rgba(82, 168, 236, 0.8);
713 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
714 | -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
715 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
716 | }
717 | input[type=file]:focus, input[type=checkbox]:focus, select:focus {
718 | -webkit-box-shadow: none;
719 | -moz-box-shadow: none;
720 | box-shadow: none;
721 | outline: 1px dotted #666;
722 | }
723 | form .clearfix.error > label, form .clearfix.error .help-block, form .clearfix.error .help-inline {
724 | color: #b94a48;
725 | }
726 | form .clearfix.error input, form .clearfix.error textarea {
727 | color: #b94a48;
728 | border-color: #ee5f5b;
729 | }
730 | form .clearfix.error input:focus, form .clearfix.error textarea:focus {
731 | border-color: #e9322d;
732 | -webkit-box-shadow: 0 0 6px #f8b9b7;
733 | -moz-box-shadow: 0 0 6px #f8b9b7;
734 | box-shadow: 0 0 6px #f8b9b7;
735 | }
736 | form .clearfix.error .input-prepend .add-on, form .clearfix.error .input-append .add-on {
737 | color: #b94a48;
738 | background-color: #fce6e6;
739 | border-color: #b94a48;
740 | }
741 | form .clearfix.warning > label, form .clearfix.warning .help-block, form .clearfix.warning .help-inline {
742 | color: #c09853;
743 | }
744 | form .clearfix.warning input, form .clearfix.warning textarea {
745 | color: #c09853;
746 | border-color: #ccae64;
747 | }
748 | form .clearfix.warning input:focus, form .clearfix.warning textarea:focus {
749 | border-color: #be9a3f;
750 | -webkit-box-shadow: 0 0 6px #e5d6b1;
751 | -moz-box-shadow: 0 0 6px #e5d6b1;
752 | box-shadow: 0 0 6px #e5d6b1;
753 | }
754 | form .clearfix.warning .input-prepend .add-on, form .clearfix.warning .input-append .add-on {
755 | color: #c09853;
756 | background-color: #d2b877;
757 | border-color: #c09853;
758 | }
759 | form .clearfix.success > label, form .clearfix.success .help-block, form .clearfix.success .help-inline {
760 | color: #468847;
761 | }
762 | form .clearfix.success input, form .clearfix.success textarea {
763 | color: #468847;
764 | border-color: #57a957;
765 | }
766 | form .clearfix.success input:focus, form .clearfix.success textarea:focus {
767 | border-color: #458845;
768 | -webkit-box-shadow: 0 0 6px #9acc9a;
769 | -moz-box-shadow: 0 0 6px #9acc9a;
770 | box-shadow: 0 0 6px #9acc9a;
771 | }
772 | form .clearfix.success .input-prepend .add-on, form .clearfix.success .input-append .add-on {
773 | color: #468847;
774 | background-color: #bcddbc;
775 | border-color: #468847;
776 | }
777 | .input-mini,
778 | input.mini,
779 | textarea.mini,
780 | select.mini {
781 | width: 60px;
782 | }
783 | .input-small,
784 | input.small,
785 | textarea.small,
786 | select.small {
787 | width: 90px;
788 | }
789 | .input-medium,
790 | input.medium,
791 | textarea.medium,
792 | select.medium {
793 | width: 150px;
794 | }
795 | .input-large,
796 | input.large,
797 | textarea.large,
798 | select.large {
799 | width: 210px;
800 | }
801 | .input-xlarge,
802 | input.xlarge,
803 | textarea.xlarge,
804 | select.xlarge {
805 | width: 270px;
806 | }
807 | .input-xxlarge,
808 | input.xxlarge,
809 | textarea.xxlarge,
810 | select.xxlarge {
811 | width: 530px;
812 | }
813 | textarea.xxlarge {
814 | overflow-y: auto;
815 | }
816 | input.span1, textarea.span1 {
817 | display: inline-block;
818 | float: none;
819 | width: 30px;
820 | margin-left: 0;
821 | }
822 | input.span2, textarea.span2 {
823 | display: inline-block;
824 | float: none;
825 | width: 90px;
826 | margin-left: 0;
827 | }
828 | input.span3, textarea.span3 {
829 | display: inline-block;
830 | float: none;
831 | width: 150px;
832 | margin-left: 0;
833 | }
834 | input.span4, textarea.span4 {
835 | display: inline-block;
836 | float: none;
837 | width: 210px;
838 | margin-left: 0;
839 | }
840 | input.span5, textarea.span5 {
841 | display: inline-block;
842 | float: none;
843 | width: 270px;
844 | margin-left: 0;
845 | }
846 | input.span6, textarea.span6 {
847 | display: inline-block;
848 | float: none;
849 | width: 330px;
850 | margin-left: 0;
851 | }
852 | input.span7, textarea.span7 {
853 | display: inline-block;
854 | float: none;
855 | width: 390px;
856 | margin-left: 0;
857 | }
858 | input.span8, textarea.span8 {
859 | display: inline-block;
860 | float: none;
861 | width: 450px;
862 | margin-left: 0;
863 | }
864 | input.span9, textarea.span9 {
865 | display: inline-block;
866 | float: none;
867 | width: 510px;
868 | margin-left: 0;
869 | }
870 | input.span10, textarea.span10 {
871 | display: inline-block;
872 | float: none;
873 | width: 570px;
874 | margin-left: 0;
875 | }
876 | input.span11, textarea.span11 {
877 | display: inline-block;
878 | float: none;
879 | width: 630px;
880 | margin-left: 0;
881 | }
882 | input.span12, textarea.span12 {
883 | display: inline-block;
884 | float: none;
885 | width: 690px;
886 | margin-left: 0;
887 | }
888 | input.span13, textarea.span13 {
889 | display: inline-block;
890 | float: none;
891 | width: 750px;
892 | margin-left: 0;
893 | }
894 | input.span14, textarea.span14 {
895 | display: inline-block;
896 | float: none;
897 | width: 810px;
898 | margin-left: 0;
899 | }
900 | input.span15, textarea.span15 {
901 | display: inline-block;
902 | float: none;
903 | width: 870px;
904 | margin-left: 0;
905 | }
906 | input.span16, textarea.span16 {
907 | display: inline-block;
908 | float: none;
909 | width: 930px;
910 | margin-left: 0;
911 | }
912 | input[disabled],
913 | select[disabled],
914 | textarea[disabled],
915 | input[readonly],
916 | select[readonly],
917 | textarea[readonly] {
918 | background-color: #f5f5f5;
919 | border-color: #ddd;
920 | cursor: not-allowed;
921 | }
922 | .actions {
923 | background: #f5f5f5;
924 | margin-top: 18px;
925 | margin-bottom: 18px;
926 | padding: 17px 20px 18px 150px;
927 | border-top: 1px solid #ddd;
928 | -webkit-border-radius: 0 0 3px 3px;
929 | -moz-border-radius: 0 0 3px 3px;
930 | border-radius: 0 0 3px 3px;
931 | }
932 | .actions .secondary-action {
933 | float: right;
934 | }
935 | .actions .secondary-action a {
936 | line-height: 30px;
937 | }
938 | .actions .secondary-action a:hover {
939 | text-decoration: underline;
940 | }
941 | .help-inline, .help-block {
942 | font-size: 13px;
943 | line-height: 18px;
944 | color: #bfbfbf;
945 | }
946 | .help-inline {
947 | padding-left: 5px;
948 | *position: relative;
949 | /* IE6-7 */
950 |
951 | *top: -5px;
952 | /* IE6-7 */
953 |
954 | }
955 | .help-block {
956 | display: block;
957 | max-width: 600px;
958 | }
959 | .inline-inputs {
960 | color: #808080;
961 | }
962 | .inline-inputs span {
963 | padding: 0 2px 0 1px;
964 | }
965 | .input-prepend input, .input-append input {
966 | -webkit-border-radius: 0 3px 3px 0;
967 | -moz-border-radius: 0 3px 3px 0;
968 | border-radius: 0 3px 3px 0;
969 | }
970 | .input-prepend .add-on, .input-append .add-on {
971 | position: relative;
972 | background: #f5f5f5;
973 | border: 1px solid #ccc;
974 | z-index: 2;
975 | float: left;
976 | display: block;
977 | width: auto;
978 | min-width: 16px;
979 | height: 18px;
980 | padding: 4px 4px 4px 5px;
981 | margin-right: -1px;
982 | font-weight: normal;
983 | line-height: 18px;
984 | color: #bfbfbf;
985 | text-align: center;
986 | text-shadow: 0 1px 0 #ffffff;
987 | -webkit-border-radius: 3px 0 0 3px;
988 | -moz-border-radius: 3px 0 0 3px;
989 | border-radius: 3px 0 0 3px;
990 | }
991 | .input-prepend .active, .input-append .active {
992 | background: #a9dba9;
993 | border-color: #46a546;
994 | }
995 | .input-prepend .add-on {
996 | *margin-top: 1px;
997 | /* IE6-7 */
998 |
999 | }
1000 | .input-append input {
1001 | float: left;
1002 | -webkit-border-radius: 3px 0 0 3px;
1003 | -moz-border-radius: 3px 0 0 3px;
1004 | border-radius: 3px 0 0 3px;
1005 | }
1006 | .input-append .add-on {
1007 | -webkit-border-radius: 0 3px 3px 0;
1008 | -moz-border-radius: 0 3px 3px 0;
1009 | border-radius: 0 3px 3px 0;
1010 | margin-right: 0;
1011 | margin-left: -1px;
1012 | }
1013 | .inputs-list {
1014 | margin: 0 0 5px;
1015 | width: 100%;
1016 | }
1017 | .inputs-list li {
1018 | display: block;
1019 | padding: 0;
1020 | width: 100%;
1021 | }
1022 | .inputs-list label {
1023 | display: block;
1024 | float: none;
1025 | width: auto;
1026 | padding: 0;
1027 | margin-left: 20px;
1028 | line-height: 18px;
1029 | text-align: left;
1030 | white-space: normal;
1031 | }
1032 | .inputs-list label strong {
1033 | color: #808080;
1034 | }
1035 | .inputs-list label small {
1036 | font-size: 11px;
1037 | font-weight: normal;
1038 | }
1039 | .inputs-list .inputs-list {
1040 | margin-left: 25px;
1041 | margin-bottom: 10px;
1042 | padding-top: 0;
1043 | }
1044 | .inputs-list:first-child {
1045 | padding-top: 6px;
1046 | }
1047 | .inputs-list li + li {
1048 | padding-top: 2px;
1049 | }
1050 | .inputs-list input[type=radio], .inputs-list input[type=checkbox] {
1051 | margin-bottom: 0;
1052 | margin-left: -20px;
1053 | float: left;
1054 | }
1055 | .form-stacked {
1056 | padding-left: 20px;
1057 | }
1058 | .form-stacked fieldset {
1059 | padding-top: 9px;
1060 | }
1061 | .form-stacked legend {
1062 | padding-left: 0;
1063 | }
1064 | .form-stacked label {
1065 | display: block;
1066 | float: none;
1067 | width: auto;
1068 | font-weight: bold;
1069 | text-align: left;
1070 | line-height: 20px;
1071 | padding-top: 0;
1072 | }
1073 | .form-stacked .clearfix {
1074 | margin-bottom: 9px;
1075 | }
1076 | .form-stacked .clearfix div.input {
1077 | margin-left: 0;
1078 | }
1079 | .form-stacked .inputs-list {
1080 | margin-bottom: 0;
1081 | }
1082 | .form-stacked .inputs-list li {
1083 | padding-top: 0;
1084 | }
1085 | .form-stacked .inputs-list li label {
1086 | font-weight: normal;
1087 | padding-top: 0;
1088 | }
1089 | .form-stacked div.clearfix.error {
1090 | padding-top: 10px;
1091 | padding-bottom: 10px;
1092 | padding-left: 10px;
1093 | margin-top: 0;
1094 | margin-left: -10px;
1095 | }
1096 | .form-stacked .actions {
1097 | margin-left: -20px;
1098 | padding-left: 20px;
1099 | }
1100 | /*
1101 | * Tables.less
1102 | * Tables for, you guessed it, tabular data
1103 | * ---------------------------------------- */
1104 | table {
1105 | width: 100%;
1106 | margin-bottom: 18px;
1107 | padding: 0;
1108 | font-size: 13px;
1109 | border-collapse: collapse;
1110 | }
1111 | table th, table td {
1112 | padding: 10px 10px 9px;
1113 | line-height: 18px;
1114 | text-align: left;
1115 | }
1116 | table th {
1117 | padding-top: 9px;
1118 | font-weight: bold;
1119 | vertical-align: middle;
1120 | }
1121 | table td {
1122 | vertical-align: top;
1123 | border-top: 1px solid #ddd;
1124 | }
1125 | table tbody th {
1126 | border-top: 1px solid #ddd;
1127 | vertical-align: top;
1128 | }
1129 | .condensed-table th, .condensed-table td {
1130 | padding: 5px 5px 4px;
1131 | }
1132 | .bordered-table {
1133 | border: 1px solid #ddd;
1134 | border-collapse: separate;
1135 | *border-collapse: collapse;
1136 | /* IE7, collapse table to remove spacing */
1137 |
1138 | -webkit-border-radius: 4px;
1139 | -moz-border-radius: 4px;
1140 | border-radius: 4px;
1141 | }
1142 | .bordered-table th + th, .bordered-table td + td, .bordered-table th + td {
1143 | border-left: 1px solid #ddd;
1144 | }
1145 | .bordered-table thead tr:first-child th:first-child, .bordered-table tbody tr:first-child td:first-child {
1146 | -webkit-border-radius: 4px 0 0 0;
1147 | -moz-border-radius: 4px 0 0 0;
1148 | border-radius: 4px 0 0 0;
1149 | }
1150 | .bordered-table thead tr:first-child th:last-child, .bordered-table tbody tr:first-child td:last-child {
1151 | -webkit-border-radius: 0 4px 0 0;
1152 | -moz-border-radius: 0 4px 0 0;
1153 | border-radius: 0 4px 0 0;
1154 | }
1155 | .bordered-table tbody tr:last-child td:first-child {
1156 | -webkit-border-radius: 0 0 0 4px;
1157 | -moz-border-radius: 0 0 0 4px;
1158 | border-radius: 0 0 0 4px;
1159 | }
1160 | .bordered-table tbody tr:last-child td:last-child {
1161 | -webkit-border-radius: 0 0 4px 0;
1162 | -moz-border-radius: 0 0 4px 0;
1163 | border-radius: 0 0 4px 0;
1164 | }
1165 | table .span1 {
1166 | width: 20px;
1167 | }
1168 | table .span2 {
1169 | width: 60px;
1170 | }
1171 | table .span3 {
1172 | width: 100px;
1173 | }
1174 | table .span4 {
1175 | width: 140px;
1176 | }
1177 | table .span5 {
1178 | width: 180px;
1179 | }
1180 | table .span6 {
1181 | width: 220px;
1182 | }
1183 | table .span7 {
1184 | width: 260px;
1185 | }
1186 | table .span8 {
1187 | width: 300px;
1188 | }
1189 | table .span9 {
1190 | width: 340px;
1191 | }
1192 | table .span10 {
1193 | width: 380px;
1194 | }
1195 | table .span11 {
1196 | width: 420px;
1197 | }
1198 | table .span12 {
1199 | width: 460px;
1200 | }
1201 | table .span13 {
1202 | width: 500px;
1203 | }
1204 | table .span14 {
1205 | width: 540px;
1206 | }
1207 | table .span15 {
1208 | width: 580px;
1209 | }
1210 | table .span16 {
1211 | width: 620px;
1212 | }
1213 | .zebra-striped tbody tr:nth-child(odd) td, .zebra-striped tbody tr:nth-child(odd) th {
1214 | background-color: #f9f9f9;
1215 | }
1216 | .zebra-striped tbody tr:hover td, .zebra-striped tbody tr:hover th {
1217 | background-color: #f5f5f5;
1218 | }
1219 | table .header {
1220 | cursor: pointer;
1221 | }
1222 | table .header:after {
1223 | content: "";
1224 | float: right;
1225 | margin-top: 7px;
1226 | border-width: 0 4px 4px;
1227 | border-style: solid;
1228 | border-color: #000 transparent;
1229 | visibility: hidden;
1230 | }
1231 | table .headerSortUp, table .headerSortDown {
1232 | background-color: rgba(141, 192, 219, 0.25);
1233 | text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
1234 | }
1235 | table .header:hover:after {
1236 | visibility: visible;
1237 | }
1238 | table .headerSortDown:after, table .headerSortDown:hover:after {
1239 | visibility: visible;
1240 | filter: alpha(opacity=60);
1241 | -khtml-opacity: 0.6;
1242 | -moz-opacity: 0.6;
1243 | opacity: 0.6;
1244 | }
1245 | table .headerSortUp:after {
1246 | border-bottom: none;
1247 | border-left: 4px solid transparent;
1248 | border-right: 4px solid transparent;
1249 | border-top: 4px solid #000;
1250 | visibility: visible;
1251 | -webkit-box-shadow: none;
1252 | -moz-box-shadow: none;
1253 | box-shadow: none;
1254 | filter: alpha(opacity=60);
1255 | -khtml-opacity: 0.6;
1256 | -moz-opacity: 0.6;
1257 | opacity: 0.6;
1258 | }
1259 | table .blue {
1260 | color: #049cdb;
1261 | border-bottom-color: #049cdb;
1262 | }
1263 | table .headerSortUp.blue, table .headerSortDown.blue {
1264 | background-color: #ade6fe;
1265 | }
1266 | table .green {
1267 | color: #46a546;
1268 | border-bottom-color: #46a546;
1269 | }
1270 | table .headerSortUp.green, table .headerSortDown.green {
1271 | background-color: #cdeacd;
1272 | }
1273 | table .red {
1274 | color: #9d261d;
1275 | border-bottom-color: #9d261d;
1276 | }
1277 | table .headerSortUp.red, table .headerSortDown.red {
1278 | background-color: #f4c8c5;
1279 | }
1280 | table .yellow {
1281 | color: #ffc40d;
1282 | border-bottom-color: #ffc40d;
1283 | }
1284 | table .headerSortUp.yellow, table .headerSortDown.yellow {
1285 | background-color: #fff6d9;
1286 | }
1287 | table .orange {
1288 | color: #f89406;
1289 | border-bottom-color: #f89406;
1290 | }
1291 | table .headerSortUp.orange, table .headerSortDown.orange {
1292 | background-color: #fee9cc;
1293 | }
1294 | table .purple {
1295 | color: #7a43b6;
1296 | border-bottom-color: #7a43b6;
1297 | }
1298 | table .headerSortUp.purple, table .headerSortDown.purple {
1299 | background-color: #e2d5f0;
1300 | }
1301 | /* Patterns.less
1302 | * Repeatable UI elements outside the base styles provided from the scaffolding
1303 | * ---------------------------------------------------------------------------- */
1304 | .topbar {
1305 | height: 40px;
1306 | position: fixed;
1307 | top: 0;
1308 | left: 0;
1309 | right: 0;
1310 | z-index: 10000;
1311 | overflow: visible;
1312 | }
1313 | .topbar a {
1314 | color: #bfbfbf;
1315 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
1316 | }
1317 | .topbar h3 a:hover, .topbar .brand:hover, .topbar ul .active > a {
1318 | background-color: #333;
1319 | background-color: rgba(255, 255, 255, 0.05);
1320 | color: #ffffff;
1321 | text-decoration: none;
1322 | }
1323 | .topbar h3 {
1324 | position: relative;
1325 | }
1326 | .topbar h3 a, .topbar .brand {
1327 | float: left;
1328 | display: block;
1329 | padding: 8px 20px 12px;
1330 | margin-left: -20px;
1331 | color: #ffffff;
1332 | font-size: 20px;
1333 | font-weight: 200;
1334 | line-height: 1;
1335 | }
1336 | .topbar p {
1337 | margin: 0;
1338 | line-height: 40px;
1339 | }
1340 | .topbar p a:hover {
1341 | background-color: transparent;
1342 | color: #ffffff;
1343 | }
1344 | .topbar form {
1345 | float: left;
1346 | margin: 5px 0 0 0;
1347 | position: relative;
1348 | filter: alpha(opacity=100);
1349 | -khtml-opacity: 1;
1350 | -moz-opacity: 1;
1351 | opacity: 1;
1352 | }
1353 | .topbar form.pull-right {
1354 | float: right;
1355 | }
1356 | .topbar input {
1357 | background-color: #444;
1358 | background-color: rgba(255, 255, 255, 0.3);
1359 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
1360 | font-size: normal;
1361 | font-weight: 13px;
1362 | line-height: 1;
1363 | padding: 4px 9px;
1364 | color: #ffffff;
1365 | color: rgba(255, 255, 255, 0.75);
1366 | border: 1px solid #111;
1367 | -webkit-border-radius: 4px;
1368 | -moz-border-radius: 4px;
1369 | border-radius: 4px;
1370 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25);
1371 | -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25);
1372 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25);
1373 | -webkit-transform-style: preserve-3d;
1374 | -webkit-transition: none;
1375 | -moz-transition: none;
1376 | -ms-transition: none;
1377 | -o-transition: none;
1378 | transition: none;
1379 | }
1380 | .topbar input:-moz-placeholder {
1381 | color: #e6e6e6;
1382 | }
1383 | .topbar input::-webkit-input-placeholder {
1384 | color: #e6e6e6;
1385 | }
1386 | .topbar input:hover {
1387 | background-color: #bfbfbf;
1388 | background-color: rgba(255, 255, 255, 0.5);
1389 | color: #ffffff;
1390 | }
1391 | .topbar input:focus, .topbar input.focused {
1392 | outline: 0;
1393 | background-color: #ffffff;
1394 | color: #404040;
1395 | text-shadow: 0 1px 0 #ffffff;
1396 | border: 0;
1397 | padding: 5px 10px;
1398 | -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
1399 | -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
1400 | box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
1401 | }
1402 | .topbar-inner, .topbar .fill {
1403 | background-color: #222;
1404 | background-color: #222222;
1405 | background-repeat: repeat-x;
1406 | background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222));
1407 | background-image: -moz-linear-gradient(top, #333333, #222222);
1408 | background-image: -ms-linear-gradient(top, #333333, #222222);
1409 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222));
1410 | background-image: -webkit-linear-gradient(top, #333333, #222222);
1411 | background-image: -o-linear-gradient(top, #333333, #222222);
1412 | background-image: linear-gradient(top, #333333, #222222);
1413 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);
1414 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
1415 | -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
1416 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
1417 | }
1418 | .topbar div > ul, .nav {
1419 | display: block;
1420 | float: left;
1421 | margin: 0 10px 0 0;
1422 | position: relative;
1423 | left: 0;
1424 | }
1425 | .topbar div > ul > li, .nav > li {
1426 | display: block;
1427 | float: left;
1428 | }
1429 | .topbar div > ul a, .nav a {
1430 | display: block;
1431 | float: none;
1432 | padding: 10px 10px 11px;
1433 | line-height: 19px;
1434 | text-decoration: none;
1435 | }
1436 | .topbar div > ul a:hover, .nav a:hover {
1437 | color: #ffffff;
1438 | text-decoration: none;
1439 | }
1440 | .topbar div > ul .active > a, .nav .active > a {
1441 | background-color: #222;
1442 | background-color: rgba(0, 0, 0, 0.5);
1443 | }
1444 | .topbar div > ul.secondary-nav, .nav.secondary-nav {
1445 | float: right;
1446 | margin-left: 10px;
1447 | margin-right: 0;
1448 | }
1449 | .topbar div > ul.secondary-nav .menu-dropdown,
1450 | .nav.secondary-nav .menu-dropdown,
1451 | .topbar div > ul.secondary-nav .dropdown-menu,
1452 | .nav.secondary-nav .dropdown-menu {
1453 | right: 0;
1454 | border: 0;
1455 | }
1456 | .topbar div > ul a.menu:hover,
1457 | .nav a.menu:hover,
1458 | .topbar div > ul li.open .menu,
1459 | .nav li.open .menu,
1460 | .topbar div > ul .dropdown-toggle:hover,
1461 | .nav .dropdown-toggle:hover,
1462 | .topbar div > ul .dropdown.open .dropdown-toggle,
1463 | .nav .dropdown.open .dropdown-toggle {
1464 | background: #444;
1465 | background: rgba(255, 255, 255, 0.05);
1466 | }
1467 | .topbar div > ul .menu-dropdown,
1468 | .nav .menu-dropdown,
1469 | .topbar div > ul .dropdown-menu,
1470 | .nav .dropdown-menu {
1471 | background-color: #333;
1472 | }
1473 | .topbar div > ul .menu-dropdown a.menu,
1474 | .nav .menu-dropdown a.menu,
1475 | .topbar div > ul .dropdown-menu a.menu,
1476 | .nav .dropdown-menu a.menu,
1477 | .topbar div > ul .menu-dropdown .dropdown-toggle,
1478 | .nav .menu-dropdown .dropdown-toggle,
1479 | .topbar div > ul .dropdown-menu .dropdown-toggle,
1480 | .nav .dropdown-menu .dropdown-toggle {
1481 | color: #ffffff;
1482 | }
1483 | .topbar div > ul .menu-dropdown a.menu.open,
1484 | .nav .menu-dropdown a.menu.open,
1485 | .topbar div > ul .dropdown-menu a.menu.open,
1486 | .nav .dropdown-menu a.menu.open,
1487 | .topbar div > ul .menu-dropdown .dropdown-toggle.open,
1488 | .nav .menu-dropdown .dropdown-toggle.open,
1489 | .topbar div > ul .dropdown-menu .dropdown-toggle.open,
1490 | .nav .dropdown-menu .dropdown-toggle.open {
1491 | background: #444;
1492 | background: rgba(255, 255, 255, 0.05);
1493 | }
1494 | .topbar div > ul .menu-dropdown li a,
1495 | .nav .menu-dropdown li a,
1496 | .topbar div > ul .dropdown-menu li a,
1497 | .nav .dropdown-menu li a {
1498 | color: #999;
1499 | text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
1500 | }
1501 | .topbar div > ul .menu-dropdown li a:hover,
1502 | .nav .menu-dropdown li a:hover,
1503 | .topbar div > ul .dropdown-menu li a:hover,
1504 | .nav .dropdown-menu li a:hover {
1505 | background-color: #191919;
1506 | background-repeat: repeat-x;
1507 | background-image: -khtml-gradient(linear, left top, left bottom, from(#292929), to(#191919));
1508 | background-image: -moz-linear-gradient(top, #292929, #191919);
1509 | background-image: -ms-linear-gradient(top, #292929, #191919);
1510 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #292929), color-stop(100%, #191919));
1511 | background-image: -webkit-linear-gradient(top, #292929, #191919);
1512 | background-image: -o-linear-gradient(top, #292929, #191919);
1513 | background-image: linear-gradient(top, #292929, #191919);
1514 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#292929', endColorstr='#191919', GradientType=0);
1515 | color: #ffffff;
1516 | }
1517 | .topbar div > ul .menu-dropdown .active a,
1518 | .nav .menu-dropdown .active a,
1519 | .topbar div > ul .dropdown-menu .active a,
1520 | .nav .dropdown-menu .active a {
1521 | color: #ffffff;
1522 | }
1523 | .topbar div > ul .menu-dropdown .divider,
1524 | .nav .menu-dropdown .divider,
1525 | .topbar div > ul .dropdown-menu .divider,
1526 | .nav .dropdown-menu .divider {
1527 | background-color: #222;
1528 | border-color: #444;
1529 | }
1530 | .topbar ul .menu-dropdown li a, .topbar ul .dropdown-menu li a {
1531 | padding: 4px 15px;
1532 | }
1533 | li.menu, .dropdown {
1534 | position: relative;
1535 | }
1536 | a.menu:after, .dropdown-toggle:after {
1537 | width: 0;
1538 | height: 0;
1539 | display: inline-block;
1540 | content: "↓";
1541 | text-indent: -99999px;
1542 | vertical-align: top;
1543 | margin-top: 8px;
1544 | margin-left: 4px;
1545 | border-left: 4px solid transparent;
1546 | border-right: 4px solid transparent;
1547 | border-top: 4px solid #ffffff;
1548 | filter: alpha(opacity=50);
1549 | -khtml-opacity: 0.5;
1550 | -moz-opacity: 0.5;
1551 | opacity: 0.5;
1552 | }
1553 | .menu-dropdown, .dropdown-menu {
1554 | background-color: #ffffff;
1555 | float: left;
1556 | display: none;
1557 | position: absolute;
1558 | top: 40px;
1559 | z-index: 900;
1560 | min-width: 160px;
1561 | max-width: 220px;
1562 | _width: 160px;
1563 | margin-left: 0;
1564 | margin-right: 0;
1565 | padding: 6px 0;
1566 | zoom: 1;
1567 | border-color: #999;
1568 | border-color: rgba(0, 0, 0, 0.2);
1569 | border-style: solid;
1570 | border-width: 0 1px 1px;
1571 | -webkit-border-radius: 0 0 6px 6px;
1572 | -moz-border-radius: 0 0 6px 6px;
1573 | border-radius: 0 0 6px 6px;
1574 | -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
1575 | -moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
1576 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
1577 | -webkit-background-clip: padding-box;
1578 | -moz-background-clip: padding-box;
1579 | background-clip: padding-box;
1580 | }
1581 | .menu-dropdown li, .dropdown-menu li {
1582 | float: none;
1583 | display: block;
1584 | background-color: none;
1585 | }
1586 | .menu-dropdown .divider, .dropdown-menu .divider {
1587 | height: 1px;
1588 | margin: 5px 0;
1589 | overflow: hidden;
1590 | background-color: #eee;
1591 | border-bottom: 1px solid #ffffff;
1592 | }
1593 | .topbar .dropdown-menu a, .dropdown-menu a {
1594 | display: block;
1595 | padding: 4px 15px;
1596 | clear: both;
1597 | font-weight: normal;
1598 | line-height: 18px;
1599 | color: #808080;
1600 | text-shadow: 0 1px 0 #ffffff;
1601 | }
1602 | .topbar .dropdown-menu a:hover,
1603 | .dropdown-menu a:hover,
1604 | .topbar .dropdown-menu a.hover,
1605 | .dropdown-menu a.hover {
1606 | background-color: #dddddd;
1607 | background-repeat: repeat-x;
1608 | background-image: -khtml-gradient(linear, left top, left bottom, from(#eeeeee), to(#dddddd));
1609 | background-image: -moz-linear-gradient(top, #eeeeee, #dddddd);
1610 | background-image: -ms-linear-gradient(top, #eeeeee, #dddddd);
1611 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, #dddddd));
1612 | background-image: -webkit-linear-gradient(top, #eeeeee, #dddddd);
1613 | background-image: -o-linear-gradient(top, #eeeeee, #dddddd);
1614 | background-image: linear-gradient(top, #eeeeee, #dddddd);
1615 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#dddddd', GradientType=0);
1616 | color: #404040;
1617 | text-decoration: none;
1618 | -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025);
1619 | -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025);
1620 | box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025);
1621 | }
1622 | .open .menu,
1623 | .dropdown.open .menu,
1624 | .open .dropdown-toggle,
1625 | .dropdown.open .dropdown-toggle {
1626 | color: #ffffff;
1627 | background: #ccc;
1628 | background: rgba(0, 0, 0, 0.3);
1629 | }
1630 | .open .menu-dropdown,
1631 | .dropdown.open .menu-dropdown,
1632 | .open .dropdown-menu,
1633 | .dropdown.open .dropdown-menu {
1634 | display: block;
1635 | }
1636 | .tabs, .pills {
1637 | margin: 0 0 18px;
1638 | padding: 0;
1639 | list-style: none;
1640 | zoom: 1;
1641 | }
1642 | .tabs:before,
1643 | .pills:before,
1644 | .tabs:after,
1645 | .pills:after {
1646 | display: table;
1647 | content: "";
1648 | zoom: 1;
1649 | }
1650 | .tabs:after, .pills:after {
1651 | clear: both;
1652 | }
1653 | .tabs > li, .pills > li {
1654 | float: left;
1655 | }
1656 | .tabs > li > a, .pills > li > a {
1657 | display: block;
1658 | }
1659 | .tabs {
1660 | border-color: #ddd;
1661 | border-style: solid;
1662 | border-width: 0 0 1px;
1663 | }
1664 | .tabs > li {
1665 | position: relative;
1666 | margin-bottom: -1px;
1667 | }
1668 | .tabs > li > a {
1669 | padding: 0 15px;
1670 | margin-right: 2px;
1671 | line-height: 34px;
1672 | border: 1px solid transparent;
1673 | -webkit-border-radius: 4px 4px 0 0;
1674 | -moz-border-radius: 4px 4px 0 0;
1675 | border-radius: 4px 4px 0 0;
1676 | }
1677 | .tabs > li > a:hover {
1678 | text-decoration: none;
1679 | background-color: #eee;
1680 | border-color: #eee #eee #ddd;
1681 | }
1682 | .tabs .active > a, .tabs .active > a:hover {
1683 | color: #808080;
1684 | background-color: #ffffff;
1685 | border: 1px solid #ddd;
1686 | border-bottom-color: transparent;
1687 | cursor: default;
1688 | }
1689 | .tabs .menu-dropdown, .tabs .dropdown-menu {
1690 | top: 35px;
1691 | border-width: 1px;
1692 | -webkit-border-radius: 0 6px 6px 6px;
1693 | -moz-border-radius: 0 6px 6px 6px;
1694 | border-radius: 0 6px 6px 6px;
1695 | }
1696 | .tabs a.menu:after, .tabs .dropdown-toggle:after {
1697 | border-top-color: #999;
1698 | margin-top: 15px;
1699 | margin-left: 5px;
1700 | }
1701 | .tabs li.open.menu .menu, .tabs .open.dropdown .dropdown-toggle {
1702 | border-color: #999;
1703 | }
1704 | .tabs li.open a.menu:after, .tabs .dropdown.open .dropdown-toggle:after {
1705 | border-top-color: #555;
1706 | }
1707 | .pills a {
1708 | margin: 5px 3px 5px 0;
1709 | padding: 0 15px;
1710 | line-height: 30px;
1711 | text-shadow: 0 1px 1px #ffffff;
1712 | -webkit-border-radius: 15px;
1713 | -moz-border-radius: 15px;
1714 | border-radius: 15px;
1715 | }
1716 | .pills a:hover {
1717 | color: #ffffff;
1718 | text-decoration: none;
1719 | text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
1720 | background-color: #00438a;
1721 | }
1722 | .pills .active a {
1723 | color: #ffffff;
1724 | text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
1725 | background-color: #0069d6;
1726 | }
1727 | .pills-vertical > li {
1728 | float: none;
1729 | }
1730 | .tab-content > .tab-pane, .pill-content > .pill-pane {
1731 | display: none;
1732 | }
1733 | .tab-content > .active, .pill-content > .active {
1734 | display: block;
1735 | }
1736 | .breadcrumb {
1737 | padding: 7px 14px;
1738 | margin: 0 0 18px;
1739 | background-color: #f5f5f5;
1740 | background-repeat: repeat-x;
1741 | background-image: -khtml-gradient(linear, left top, left bottom, from(#ffffff), to(#f5f5f5));
1742 | background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5);
1743 | background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5);
1744 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f5f5f5));
1745 | background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5);
1746 | background-image: -o-linear-gradient(top, #ffffff, #f5f5f5);
1747 | background-image: linear-gradient(top, #ffffff, #f5f5f5);
1748 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);
1749 | border: 1px solid #ddd;
1750 | -webkit-border-radius: 3px;
1751 | -moz-border-radius: 3px;
1752 | border-radius: 3px;
1753 | -webkit-box-shadow: inset 0 1px 0 #ffffff;
1754 | -moz-box-shadow: inset 0 1px 0 #ffffff;
1755 | box-shadow: inset 0 1px 0 #ffffff;
1756 | }
1757 | .breadcrumb li {
1758 | display: inline;
1759 | text-shadow: 0 1px 0 #ffffff;
1760 | }
1761 | .breadcrumb .divider {
1762 | padding: 0 5px;
1763 | color: #bfbfbf;
1764 | }
1765 | .breadcrumb .active a {
1766 | color: #404040;
1767 | }
1768 | .hero-unit {
1769 | background-color: #f5f5f5;
1770 | margin-bottom: 30px;
1771 | padding: 60px;
1772 | -webkit-border-radius: 6px;
1773 | -moz-border-radius: 6px;
1774 | border-radius: 6px;
1775 | }
1776 | .hero-unit h1 {
1777 | margin-bottom: 0;
1778 | font-size: 60px;
1779 | line-height: 1;
1780 | letter-spacing: -1px;
1781 | }
1782 | .hero-unit p {
1783 | font-size: 18px;
1784 | font-weight: 200;
1785 | line-height: 27px;
1786 | }
1787 | footer {
1788 | margin-top: 17px;
1789 | padding-top: 17px;
1790 | border-top: 1px solid #eee;
1791 | }
1792 | .page-header {
1793 | margin-bottom: 17px;
1794 | border-bottom: 1px solid #ddd;
1795 | -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
1796 | -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
1797 | box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
1798 | }
1799 | .page-header h1 {
1800 | margin-bottom: 8px;
1801 | }
1802 | .btn.danger,
1803 | .alert-message.danger,
1804 | .btn.danger:hover,
1805 | .alert-message.danger:hover,
1806 | .btn.error,
1807 | .alert-message.error,
1808 | .btn.error:hover,
1809 | .alert-message.error:hover,
1810 | .btn.success,
1811 | .alert-message.success,
1812 | .btn.success:hover,
1813 | .alert-message.success:hover,
1814 | .btn.info,
1815 | .alert-message.info,
1816 | .btn.info:hover,
1817 | .alert-message.info:hover {
1818 | color: #ffffff;
1819 | }
1820 | .btn .close, .alert-message .close {
1821 | font-family: Arial, sans-serif;
1822 | line-height: 18px;
1823 | }
1824 | .btn.danger,
1825 | .alert-message.danger,
1826 | .btn.error,
1827 | .alert-message.error {
1828 | background-color: #c43c35;
1829 | background-repeat: repeat-x;
1830 | background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));
1831 | background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
1832 | background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
1833 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));
1834 | background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
1835 | background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
1836 | background-image: linear-gradient(top, #ee5f5b, #c43c35);
1837 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);
1838 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
1839 | border-color: #c43c35 #c43c35 #882a25;
1840 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
1841 | }
1842 | .btn.success, .alert-message.success {
1843 | background-color: #57a957;
1844 | background-repeat: repeat-x;
1845 | background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));
1846 | background-image: -moz-linear-gradient(top, #62c462, #57a957);
1847 | background-image: -ms-linear-gradient(top, #62c462, #57a957);
1848 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));
1849 | background-image: -webkit-linear-gradient(top, #62c462, #57a957);
1850 | background-image: -o-linear-gradient(top, #62c462, #57a957);
1851 | background-image: linear-gradient(top, #62c462, #57a957);
1852 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);
1853 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
1854 | border-color: #57a957 #57a957 #3d773d;
1855 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
1856 | }
1857 | .btn.info, .alert-message.info {
1858 | background-color: #339bb9;
1859 | background-repeat: repeat-x;
1860 | background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9));
1861 | background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
1862 | background-image: -ms-linear-gradient(top, #5bc0de, #339bb9);
1863 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));
1864 | background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
1865 | background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
1866 | background-image: linear-gradient(top, #5bc0de, #339bb9);
1867 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);
1868 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
1869 | border-color: #339bb9 #339bb9 #22697d;
1870 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
1871 | }
1872 | .btn {
1873 | cursor: pointer;
1874 | display: inline-block;
1875 | background-color: #e6e6e6;
1876 | background-repeat: no-repeat;
1877 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));
1878 | background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
1879 | background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);
1880 | background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
1881 | background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
1882 | background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
1883 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);
1884 | padding: 5px 14px 6px;
1885 | text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
1886 | color: #333;
1887 | font-size: 13px;
1888 | line-height: normal;
1889 | border: 1px solid #ccc;
1890 | border-bottom-color: #bbb;
1891 | -webkit-border-radius: 4px;
1892 | -moz-border-radius: 4px;
1893 | border-radius: 4px;
1894 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
1895 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
1896 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
1897 | -webkit-transform-style: preserve-3d;
1898 | -webkit-transition: 0.1s linear all;
1899 | -moz-transition: 0.1s linear all;
1900 | -ms-transition: 0.1s linear all;
1901 | -o-transition: 0.1s linear all;
1902 | transition: 0.1s linear all;
1903 | }
1904 | .btn:hover {
1905 | background-position: 0 -15px;
1906 | color: #333;
1907 | text-decoration: none;
1908 | }
1909 | .btn:focus {
1910 | outline: 1px dotted #666;
1911 | }
1912 | .btn.primary {
1913 | color: #ffffff;
1914 | background-color: #0064cd;
1915 | background-repeat: repeat-x;
1916 | background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
1917 | background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
1918 | background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
1919 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
1920 | background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
1921 | background-image: -o-linear-gradient(top, #049cdb, #0064cd);
1922 | background-image: linear-gradient(top, #049cdb, #0064cd);
1923 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);
1924 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
1925 | border-color: #0064cd #0064cd #003f81;
1926 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
1927 | }
1928 | .btn.active, .btn :active {
1929 | -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
1930 | -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
1931 | box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
1932 | }
1933 | .btn.disabled {
1934 | cursor: default;
1935 | background-image: none;
1936 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
1937 | filter: alpha(opacity=65);
1938 | -khtml-opacity: 0.65;
1939 | -moz-opacity: 0.65;
1940 | opacity: 0.65;
1941 | -webkit-box-shadow: none;
1942 | -moz-box-shadow: none;
1943 | box-shadow: none;
1944 | }
1945 | .btn[disabled] {
1946 | cursor: default;
1947 | background-image: none;
1948 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
1949 | filter: alpha(opacity=65);
1950 | -khtml-opacity: 0.65;
1951 | -moz-opacity: 0.65;
1952 | opacity: 0.65;
1953 | -webkit-box-shadow: none;
1954 | -moz-box-shadow: none;
1955 | box-shadow: none;
1956 | }
1957 | .btn.large {
1958 | font-size: 15px;
1959 | line-height: normal;
1960 | padding: 9px 14px 9px;
1961 | -webkit-border-radius: 6px;
1962 | -moz-border-radius: 6px;
1963 | border-radius: 6px;
1964 | }
1965 | .btn.small {
1966 | padding: 7px 9px 7px;
1967 | font-size: 11px;
1968 | }
1969 | :root .alert-message, :root .btn {
1970 | border-radius: 0 \0;
1971 | }
1972 | button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner {
1973 | padding: 0;
1974 | border: 0;
1975 | }
1976 | .close {
1977 | float: right;
1978 | color: #000000;
1979 | font-size: 20px;
1980 | font-weight: bold;
1981 | line-height: 13.5px;
1982 | text-shadow: 0 1px 0 #ffffff;
1983 | filter: alpha(opacity=25);
1984 | -khtml-opacity: 0.25;
1985 | -moz-opacity: 0.25;
1986 | opacity: 0.25;
1987 | }
1988 | .close:hover {
1989 | color: #000000;
1990 | text-decoration: none;
1991 | filter: alpha(opacity=40);
1992 | -khtml-opacity: 0.4;
1993 | -moz-opacity: 0.4;
1994 | opacity: 0.4;
1995 | }
1996 | .alert-message {
1997 | position: relative;
1998 | padding: 7px 15px;
1999 | margin-bottom: 18px;
2000 | color: #404040;
2001 | background-color: #eedc94;
2002 | background-repeat: repeat-x;
2003 | background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94));
2004 | background-image: -moz-linear-gradient(top, #fceec1, #eedc94);
2005 | background-image: -ms-linear-gradient(top, #fceec1, #eedc94);
2006 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94));
2007 | background-image: -webkit-linear-gradient(top, #fceec1, #eedc94);
2008 | background-image: -o-linear-gradient(top, #fceec1, #eedc94);
2009 | background-image: linear-gradient(top, #fceec1, #eedc94);
2010 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0);
2011 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2012 | border-color: #eedc94 #eedc94 #e4c652;
2013 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2014 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
2015 | border-width: 1px;
2016 | border-style: solid;
2017 | -webkit-border-radius: 4px;
2018 | -moz-border-radius: 4px;
2019 | border-radius: 4px;
2020 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
2021 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
2022 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
2023 | }
2024 | .alert-message .close {
2025 | margin-top: 1px;
2026 | *margin-top: 0;
2027 | }
2028 | .alert-message a {
2029 | font-weight: bold;
2030 | color: #404040;
2031 | }
2032 | .alert-message.danger p a,
2033 | .alert-message.error p a,
2034 | .alert-message.success p a,
2035 | .alert-message.info p a {
2036 | color: #ffffff;
2037 | }
2038 | .alert-message h5 {
2039 | line-height: 18px;
2040 | }
2041 | .alert-message p {
2042 | margin-bottom: 0;
2043 | }
2044 | .alert-message div {
2045 | margin-top: 5px;
2046 | margin-bottom: 2px;
2047 | line-height: 28px;
2048 | }
2049 | .alert-message .btn {
2050 | -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
2051 | -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
2052 | box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
2053 | }
2054 | .alert-message.block-message {
2055 | background-image: none;
2056 | background-color: #fdf5d9;
2057 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2058 | padding: 14px;
2059 | border-color: #fceec1;
2060 | -webkit-box-shadow: none;
2061 | -moz-box-shadow: none;
2062 | box-shadow: none;
2063 | }
2064 | .alert-message.block-message ul, .alert-message.block-message p {
2065 | margin-right: 30px;
2066 | }
2067 | .alert-message.block-message ul {
2068 | margin-bottom: 0;
2069 | }
2070 | .alert-message.block-message li {
2071 | color: #404040;
2072 | }
2073 | .alert-message.block-message .alert-actions {
2074 | margin-top: 5px;
2075 | }
2076 | .alert-message.block-message.error, .alert-message.block-message.success, .alert-message.block-message.info {
2077 | color: #404040;
2078 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
2079 | }
2080 | .alert-message.block-message.error {
2081 | background-color: #fddfde;
2082 | border-color: #fbc7c6;
2083 | }
2084 | .alert-message.block-message.success {
2085 | background-color: #d1eed1;
2086 | border-color: #bfe7bf;
2087 | }
2088 | .alert-message.block-message.info {
2089 | background-color: #ddf4fb;
2090 | border-color: #c6edf9;
2091 | }
2092 | .alert-message.block-message.danger p a,
2093 | .alert-message.block-message.error p a,
2094 | .alert-message.block-message.success p a,
2095 | .alert-message.block-message.info p a {
2096 | color: #404040;
2097 | }
2098 | .pagination {
2099 | height: 36px;
2100 | margin: 18px 0;
2101 | }
2102 | .pagination ul {
2103 | float: left;
2104 | margin: 0;
2105 | border: 1px solid #ddd;
2106 | border: 1px solid rgba(0, 0, 0, 0.15);
2107 | -webkit-border-radius: 3px;
2108 | -moz-border-radius: 3px;
2109 | border-radius: 3px;
2110 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
2111 | -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
2112 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
2113 | }
2114 | .pagination li {
2115 | display: inline;
2116 | }
2117 | .pagination a {
2118 | float: left;
2119 | padding: 0 14px;
2120 | line-height: 34px;
2121 | border-right: 1px solid;
2122 | border-right-color: #ddd;
2123 | border-right-color: rgba(0, 0, 0, 0.15);
2124 | *border-right-color: #ddd;
2125 | /* IE6-7 */
2126 |
2127 | text-decoration: none;
2128 | }
2129 | .pagination a:hover, .pagination .active a {
2130 | background-color: #c7eefe;
2131 | }
2132 | .pagination .disabled a, .pagination .disabled a:hover {
2133 | background-color: transparent;
2134 | color: #bfbfbf;
2135 | }
2136 | .pagination .next a {
2137 | border: 0;
2138 | }
2139 | .well {
2140 | background-color: #f5f5f5;
2141 | margin-bottom: 20px;
2142 | padding: 19px;
2143 | min-height: 20px;
2144 | border: 1px solid #eee;
2145 | border: 1px solid rgba(0, 0, 0, 0.05);
2146 | -webkit-border-radius: 4px;
2147 | -moz-border-radius: 4px;
2148 | border-radius: 4px;
2149 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
2150 | -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
2151 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
2152 | }
2153 | .well blockquote {
2154 | border-color: #ddd;
2155 | border-color: rgba(0, 0, 0, 0.15);
2156 | }
2157 | .modal-backdrop {
2158 | background-color: #000000;
2159 | position: fixed;
2160 | top: 0;
2161 | left: 0;
2162 | right: 0;
2163 | bottom: 0;
2164 | z-index: 10000;
2165 | }
2166 | .modal-backdrop.fade {
2167 | opacity: 0;
2168 | }
2169 | .modal-backdrop, .modal-backdrop.fade.in {
2170 | filter: alpha(opacity=80);
2171 | -khtml-opacity: 0.8;
2172 | -moz-opacity: 0.8;
2173 | opacity: 0.8;
2174 | }
2175 | .modal {
2176 | position: fixed;
2177 | top: 50%;
2178 | left: 50%;
2179 | z-index: 11000;
2180 | width: 560px;
2181 | margin: -250px 0 0 -280px;
2182 | background-color: #ffffff;
2183 | border: 1px solid #999;
2184 | border: 1px solid rgba(0, 0, 0, 0.3);
2185 | *border: 1px solid #999;
2186 | /* IE6-7 */
2187 |
2188 | -webkit-border-radius: 6px;
2189 | -moz-border-radius: 6px;
2190 | border-radius: 6px;
2191 | -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
2192 | -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
2193 | box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
2194 | -webkit-background-clip: padding-box;
2195 | -moz-background-clip: padding-box;
2196 | background-clip: padding-box;
2197 | }
2198 | .modal .close {
2199 | margin-top: 7px;
2200 | }
2201 | .modal.fade {
2202 | -webkit-transform-style: preserve-3d;
2203 | -webkit-transition: opacity .3s linear, top .3s ease-out;
2204 | -moz-transition: opacity .3s linear, top .3s ease-out;
2205 | -ms-transition: opacity .3s linear, top .3s ease-out;
2206 | -o-transition: opacity .3s linear, top .3s ease-out;
2207 | transition: opacity .3s linear, top .3s ease-out;
2208 | top: -25%;
2209 | }
2210 | .modal.fade.in {
2211 | top: 50%;
2212 | }
2213 | .modal-header {
2214 | border-bottom: 1px solid #eee;
2215 | padding: 5px 15px;
2216 | }
2217 | .modal-body {
2218 | padding: 15px;
2219 | }
2220 | .modal-body form {
2221 | margin-bottom: 0;
2222 | }
2223 | .modal-footer {
2224 | background-color: #f5f5f5;
2225 | padding: 14px 15px 15px;
2226 | border-top: 1px solid #ddd;
2227 | -webkit-border-radius: 0 0 6px 6px;
2228 | -moz-border-radius: 0 0 6px 6px;
2229 | border-radius: 0 0 6px 6px;
2230 | -webkit-box-shadow: inset 0 1px 0 #ffffff;
2231 | -moz-box-shadow: inset 0 1px 0 #ffffff;
2232 | box-shadow: inset 0 1px 0 #ffffff;
2233 | zoom: 1;
2234 | margin-bottom: 0;
2235 | }
2236 | .modal-footer:before, .modal-footer:after {
2237 | display: table;
2238 | content: "";
2239 | zoom: 1;
2240 | }
2241 | .modal-footer:after {
2242 | clear: both;
2243 | }
2244 | .modal-footer .btn {
2245 | float: right;
2246 | margin-left: 5px;
2247 | }
2248 | .modal .popover, .modal .twipsy {
2249 | z-index: 12000;
2250 | }
2251 | .twipsy {
2252 | display: block;
2253 | position: absolute;
2254 | visibility: visible;
2255 | padding: 5px;
2256 | font-size: 11px;
2257 | z-index: 1000;
2258 | filter: alpha(opacity=80);
2259 | -khtml-opacity: 0.8;
2260 | -moz-opacity: 0.8;
2261 | opacity: 0.8;
2262 | }
2263 | .twipsy.fade.in {
2264 | filter: alpha(opacity=80);
2265 | -khtml-opacity: 0.8;
2266 | -moz-opacity: 0.8;
2267 | opacity: 0.8;
2268 | }
2269 | .twipsy.above .twipsy-arrow {
2270 | bottom: 0;
2271 | left: 50%;
2272 | margin-left: -5px;
2273 | border-left: 5px solid transparent;
2274 | border-right: 5px solid transparent;
2275 | border-top: 5px solid #000000;
2276 | }
2277 | .twipsy.left .twipsy-arrow {
2278 | top: 50%;
2279 | right: 0;
2280 | margin-top: -5px;
2281 | border-top: 5px solid transparent;
2282 | border-bottom: 5px solid transparent;
2283 | border-left: 5px solid #000000;
2284 | }
2285 | .twipsy.below .twipsy-arrow {
2286 | top: 0;
2287 | left: 50%;
2288 | margin-left: -5px;
2289 | border-left: 5px solid transparent;
2290 | border-right: 5px solid transparent;
2291 | border-bottom: 5px solid #000000;
2292 | }
2293 | .twipsy.right .twipsy-arrow {
2294 | top: 50%;
2295 | left: 0;
2296 | margin-top: -5px;
2297 | border-top: 5px solid transparent;
2298 | border-bottom: 5px solid transparent;
2299 | border-right: 5px solid #000000;
2300 | }
2301 | .twipsy-inner {
2302 | padding: 3px 8px;
2303 | background-color: #000000;
2304 | color: white;
2305 | text-align: center;
2306 | max-width: 200px;
2307 | text-decoration: none;
2308 | -webkit-border-radius: 4px;
2309 | -moz-border-radius: 4px;
2310 | border-radius: 4px;
2311 | }
2312 | .twipsy-arrow {
2313 | position: absolute;
2314 | width: 0;
2315 | height: 0;
2316 | }
2317 | .popover {
2318 | position: absolute;
2319 | top: 0;
2320 | left: 0;
2321 | z-index: 1000;
2322 | padding: 5px;
2323 | display: none;
2324 | }
2325 | .popover.above .arrow {
2326 | bottom: 0;
2327 | left: 50%;
2328 | margin-left: -5px;
2329 | border-left: 5px solid transparent;
2330 | border-right: 5px solid transparent;
2331 | border-top: 5px solid #000000;
2332 | }
2333 | .popover.right .arrow {
2334 | top: 50%;
2335 | left: 0;
2336 | margin-top: -5px;
2337 | border-top: 5px solid transparent;
2338 | border-bottom: 5px solid transparent;
2339 | border-right: 5px solid #000000;
2340 | }
2341 | .popover.below .arrow {
2342 | top: 0;
2343 | left: 50%;
2344 | margin-left: -5px;
2345 | border-left: 5px solid transparent;
2346 | border-right: 5px solid transparent;
2347 | border-bottom: 5px solid #000000;
2348 | }
2349 | .popover.left .arrow {
2350 | top: 50%;
2351 | right: 0;
2352 | margin-top: -5px;
2353 | border-top: 5px solid transparent;
2354 | border-bottom: 5px solid transparent;
2355 | border-left: 5px solid #000000;
2356 | }
2357 | .popover .arrow {
2358 | position: absolute;
2359 | width: 0;
2360 | height: 0;
2361 | }
2362 | .popover .inner {
2363 | background: #000000;
2364 | background: rgba(0, 0, 0, 0.8);
2365 | padding: 3px;
2366 | overflow: hidden;
2367 | width: 280px;
2368 | -webkit-border-radius: 6px;
2369 | -moz-border-radius: 6px;
2370 | border-radius: 6px;
2371 | -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
2372 | -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
2373 | box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
2374 | }
2375 | .popover .title {
2376 | background-color: #f5f5f5;
2377 | padding: 9px 15px;
2378 | line-height: 1;
2379 | -webkit-border-radius: 3px 3px 0 0;
2380 | -moz-border-radius: 3px 3px 0 0;
2381 | border-radius: 3px 3px 0 0;
2382 | border-bottom: 1px solid #eee;
2383 | }
2384 | .popover .content {
2385 | background-color: #ffffff;
2386 | padding: 14px;
2387 | -webkit-border-radius: 0 0 3px 3px;
2388 | -moz-border-radius: 0 0 3px 3px;
2389 | border-radius: 0 0 3px 3px;
2390 | -webkit-background-clip: padding-box;
2391 | -moz-background-clip: padding-box;
2392 | background-clip: padding-box;
2393 | }
2394 | .popover .content p, .popover .content ul, .popover .content ol {
2395 | margin-bottom: 0;
2396 | }
2397 | .fade {
2398 | -webkit-transform-style: preserve-3d;
2399 | -webkit-transition: opacity 0.15s linear;
2400 | -moz-transition: opacity 0.15s linear;
2401 | -ms-transition: opacity 0.15s linear;
2402 | -o-transition: opacity 0.15s linear;
2403 | transition: opacity 0.15s linear;
2404 | opacity: 0;
2405 | }
2406 | .fade.in {
2407 | opacity: 1;
2408 | }
2409 | .label {
2410 | padding: 1px 3px 2px;
2411 | font-size: 9.75px;
2412 | font-weight: bold;
2413 | color: #ffffff;
2414 | text-transform: uppercase;
2415 | white-space: nowrap;
2416 | background-color: #bfbfbf;
2417 | -webkit-border-radius: 3px;
2418 | -moz-border-radius: 3px;
2419 | border-radius: 3px;
2420 | }
2421 | .label.important {
2422 | background-color: #c43c35;
2423 | }
2424 | .label.warning {
2425 | background-color: #f89406;
2426 | }
2427 | .label.success {
2428 | background-color: #46a546;
2429 | }
2430 | .label.notice {
2431 | background-color: #62cffc;
2432 | }
2433 | .media-grid {
2434 | margin-left: -20px;
2435 | margin-bottom: 0;
2436 | zoom: 1;
2437 | }
2438 | .media-grid:before, .media-grid:after {
2439 | display: table;
2440 | content: "";
2441 | zoom: 1;
2442 | }
2443 | .media-grid:after {
2444 | clear: both;
2445 | }
2446 | .media-grid li {
2447 | display: inline;
2448 | }
2449 | .media-grid a {
2450 | float: left;
2451 | padding: 4px;
2452 | margin: 0 0 18px 20px;
2453 | border: 1px solid #ddd;
2454 | -webkit-border-radius: 4px;
2455 | -moz-border-radius: 4px;
2456 | border-radius: 4px;
2457 | -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
2458 | -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
2459 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
2460 | }
2461 | .media-grid a img {
2462 | display: block;
2463 | }
2464 | .media-grid a:hover {
2465 | border-color: #0069d6;
2466 | -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
2467 | -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
2468 | box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
2469 | }
2470 |
--------------------------------------------------------------------------------
/resources/cascade/exception-report.js:
--------------------------------------------------------------------------------
1 | // Copyright 2009, 2011 Howard M. Lewis Ship
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 | // implied. See the License for the specific language governing permissions
13 | // and limitations under the License.
14 |
15 | // Used by exception-report view to toggle the visibility of ommitted stack frames and other
16 | // details. Note good form: using jQuery for the call, but mapping it to $ for the duration
17 | // of the function. This helps when jQuery is mixed with libraries like Prototype.
18 |
19 | require(["jquery"], function($) {
20 |
21 | $(function() {
22 | $("#omitted-toggle").on("click", function() {
23 | $(".c-omitted").toggle();
24 | });
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/resources/cascade/exception.css:
--------------------------------------------------------------------------------
1 | /* Default stylesheet for Cascade. */
2 |
3 | /* Something initially invisible that may be revealed (but is still displayed as grey text). */
4 | .c-omitted {
5 | display: none;
6 | color: gray !important;
7 | }
8 |
9 | .c-exception-controls {
10 | float: right;
11 | }
12 |
13 | .c-exception-controls label {
14 | width: auto;
15 | line-height: 20px;
16 | }
17 |
18 | .c-exception-message {
19 | font-weight: bold;
20 | }
21 |
22 | div.c-exception {
23 | margin-top: 20px;
24 | }
25 |
26 | div.c-exception dl {
27 | margin-top: 10px;
28 | }
29 |
30 | ul.c-stack-trace li {
31 | color: black;
32 | }
--------------------------------------------------------------------------------
/resources/cascade/init.js:
--------------------------------------------------------------------------------
1 | define(['jquery'], function($) {
2 |
3 | function doInit(moduleName, functionName, initArgs) {
4 | require([moduleName], function(module) {
5 | module[functionName].apply(null, [initArgs]);
6 | });
7 | }
8 |
9 | function executeInitTuple(tuple) {
10 | doInit(tuple[0], tuple[1], tuple[2]);
11 | }
12 |
13 | function init(initializations) {
14 | // Now, wait for the DOM to load before executing the initializations.
15 | $(function() {
16 | // For want of a better word, I call each one a tuple
17 | // which consists of a module name, a functionName, and
18 | // a list of arguments to the function.
19 | $.each(initializations, function(_, tuple) {
20 | executeInitTuple(tuple);
21 | });
22 | });
23 | }
24 |
25 | function doInvoke(dependencies, selector, functionName, args) {
26 |
27 | var targetArguments = $.makeArray(arguments).slice(3);
28 |
29 | require(dependencies, function() {
30 | var selection = $(selector);
31 | selection[functionName].apply(selection, targetArguments);
32 | });
33 | }
34 |
35 | /**
36 | * Invoke an arbitrary jQuery method on a selector.
37 | * @param args dependencies, selector, functionName, args to pass to the function
38 | */
39 | function invoke(invokeArgs) {
40 | doInvoke.apply(null, invokeArgs);
41 | }
42 |
43 |
44 | return {
45 | pageInit : init,
46 | invoke : invoke
47 | };
48 | });
--------------------------------------------------------------------------------
/src/cascade.clj:
--------------------------------------------------------------------------------
1 | ; Copyright 2009, 2010, 2011 Howard M. Lewis Ship
2 | ;
3 | ; Licensed under the Apache License, Version 2.0 (the "License");
4 | ; you may not use this file except in compliance with the License.
5 | ; You may obtain a copy of the License at
6 | ;
7 | ; http://www.apache.org/licenses/LICENSE-2.0
8 | ;
9 | ; Unless required by applicable law or agreed to in writing, software
10 | ; distributed under the License is distributed on an "AS IS" BASIS,
11 | ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 | ; implied. See the License for the specific language governing permissions
13 | ; and limitations under the License.
14 |
15 | (ns
16 | cascade
17 | "Core functions and macros used when implementing Cascade views"
18 | (:use
19 | [cascade dom]
20 | [cascade.internal viewbuilder parser]
21 | ring.util.response))
22 |
23 | (defmacro markup
24 | "Defines a block of the template DSL, which is converted into code that renders a seq of DOM nodes."
25 | [& forms]
26 | (parse-markup forms))
27 |
28 | (defmacro defview
29 | "Defines a Cascade view function, which uses an embedded template. A view function may have a doc string and meta data
30 | preceding the parameters vector. The function's forms are an implicit inline block. The function returns a Ring response
31 | map, consisting of a single key, :body, consisting of the DOM nodes rendering by the implicit template."
32 | [& forms]
33 | (let [[fn-name fn-params template-forms] (parse-function-def forms)]
34 | `(defn ~fn-name ~(or (meta fn-name) {}) ~fn-params
35 | (~response (markup ~@template-forms)))))
36 |
37 | (defmacro defragment
38 | "Defines a Cascade view fragment function, which uses an embedded template. A fragment function may have a doc string and meta data
39 | preceding the parameters vector. The function's forms are an implicit inline block. The function returns a seq of DOM nodes."
40 | [& forms]
41 | (let [[fn-name fn-params template-forms] (parse-function-def forms)]
42 | `(defn ~fn-name ~(or (meta fn-name) {}) ~fn-params
43 | (markup ~@template-forms))))
44 |
45 | (defmacro block
46 | "Encapsulates a block of template forms as a function with parameters, typically used as
47 | a callback. The function, when invoked, returns a seq of DOM nodes."
48 | [fn-params & template-forms]
49 | `(fn ~fn-params (markup ~@template-forms)))
50 |
51 | (defmacro markup-for
52 | "Executes a for list comprehension on the bindings, with the forms evaluated as an implicit markup block."
53 | [bindings & markup-forms]
54 | `(combine (for ~bindings (markup ~@markup-forms))))
55 |
56 | (def linebreak
57 | "A DOM text node for a line break."
58 | (text-node "\r"))
59 |
60 | (defn raw
61 | "Wraps a string as a Static DOM node, but does not do any filtering of the value."
62 | [s]
63 | (raw-node s))
64 |
65 | (defn "]))
131 |
132 | ;;; Most outside code will use these standard constructor functions, rather than using the records' constructors.
133 |
134 | (defn element-node
135 | [name attributes content]
136 | (->Element name attributes content))
137 |
138 | (defn raw-node
139 | "Wraps a string as a Static DOM node, but does not do any encoding of the value."
140 | [s]
141 | (->Static s))
142 |
143 | (defn text-node
144 | "Creates a Static DOM node from the string. The string is encoded when the node is constructed."
145 | [text]
146 | (raw-node (encode-string text)))
147 |
148 | (defn comment-node
149 | "Creates a Comment DOM node from the string, providing the comment prefix and suffix. "
150 | [comment]
151 | (->Comment comment))
152 |
153 | (def xml-strategy {
154 | :serialize-attribute-pair (create-serialize-attribute-pair "\"")
155 | :write-empty-element-close (constantly ["/>"])
156 | })
157 |
158 | (defn serialize-xml
159 | "Serializes a seq of DOM nodes representing a complete document into a lazy seq of strings. Generally the dom-nodes seq will include just
160 | a single root element node, but text and comments and the like may come into play as well."
161 | [dom-nodes]
162 | (serialize dom-nodes xml-strategy))
163 |
164 | (def html-must-close-elements #{"script"})
165 |
166 | (defn html-empty-element-writer
167 | [element-name]
168 | (if (contains? html-must-close-elements element-name)
169 | [">" element-name ">"]
170 | [">"]))
171 |
172 | (def html-strategy {
173 | :serialize-attribute-pair (create-serialize-attribute-pair "\"")
174 | :write-empty-element-close html-empty-element-writer
175 | })
176 |
177 | (defn serialize-html
178 | "Serializes a seq of DOM nodes representing a complete document (as with serialize-xml) but with HTML
179 | output semantics: attributes are still quoted, but tags may not be balanced (the end tag
180 | may be ommitted if the element has no content). Result is a seq of strings that can be concatinated to provide the
181 | full response."
182 | [nodes]
183 | (serialize-nodes nodes html-strategy))
184 |
185 | (defn element?
186 | "Is the node a DOM Element?"
187 | [node]
188 | (instance? Element node))
189 |
190 | (defn dom-node?
191 | "Is the object some kind of DOM node?"
192 | [node]
193 | (or (element? node)
194 | (instance? Static node)
195 | (instance? Comment node)))
196 |
197 | (defn dom-zipper
198 | [root-node]
199 | (fail-unless (element? root-node) "Root node for dom-zipper must be an element node.")
200 | (z/zipper
201 | element? ; can have children
202 | :content ; children are (already) a seq in the :content key
203 | (fn [node children] (assoc node :content children))
204 | root-node))
205 |
206 | (defn navigate-dom-path
207 | "Starting from the root location (from dom-zipper) search for the first element child
208 | that matches the first element in the path. The search continues looking for a child that
209 | matches each successive keyword in the path. Returns the zipper loc for the final match or
210 | nil if the path could not be resolved."
211 | [root-loc path]
212 | (fail-if (empty? path) "Must supply at least one keyword as the path.")
213 | (loop [loc root-loc
214 | target-element (first path)
215 | remaining-path (rest path)]
216 | (lcond
217 | (nil? loc) nil
218 | :let [n (z/node loc)]
219 | ; if matching element?
220 | (and (element? n) (= (:name n) target-element))
221 | ; then either we've found it, or we need to go into the element and continue searching down.
222 | (if (empty? remaining-path)
223 | loc
224 | (recur (z/down loc) (first remaining-path) (rest remaining-path)))
225 | true (recur (z/right loc) target-element remaining-path))))
226 |
227 | (defn update-dom
228 | "Updates the DOM using a DOM zipper, a position (:before, :after, :top, :bottom)
229 | and a seq of new nodes. Returns a DOM zipper loc from which the entire DOM tree can
230 | be retrieved."
231 | [loc position new-nodes]
232 | (cond
233 | (= position :before) (reduce z/insert-left loc new-nodes)
234 | (= position :top) (reduce z/insert-child loc (reverse new-nodes))
235 | (= position :after) (reduce z/insert-right loc (reverse new-nodes))
236 | (= position :bottom) (reduce z/append-child loc new-nodes)
237 | :else (fail "Unexpected position: %s" position)))
238 |
239 | (defn extend-root-element
240 | "Extends the DOM from the root DOM element, returning a new DOM.
241 | The path is a seq of keywords, used to walk down to a specifc element in
242 | the DOM. The new nodes (often via the template macro) will be inserted
243 | according to position. :before, :after, :top (left-most, first children)
244 | :bottom (right-most, last children). Returns the modified root DOM node, or
245 | (if the path was unable to locate a specific element), nil."
246 | [dom-node path position new-nodes]
247 | (let [root-loc (dom-zipper dom-node)
248 | loc (navigate-dom-path root-loc path)]
249 | (and loc (z/root (update-dom loc position new-nodes)))))
250 |
251 | (defn apply-extend-dom-rules
252 | "Invoked from extend-dom, once the root element is known. Returns the modified node, if any rule
253 | is viable, or the root-node, if no rule is viable.
254 | root-node
255 | Root element DOM node.
256 | rules
257 | seq of rules definining where the nodes are to be inserted.
258 | new-nodes
259 | New DOM nodes to insert."
260 | [root-node rules new-nodes]
261 | (or
262 | (->>
263 | (map (fn [[path position]]
264 | (extend-root-element root-node path position new-nodes)) rules)
265 | (remove nil?)
266 | first)
267 | root-node))
268 |
269 | (defn extend-dom
270 | "Extends a DOM (a set of root DOM nodes), adding new nodes at a specific position. Uses the path
271 | (a seq of keywords, representing elements) to locate an element within the DOM
272 | then adds the new nodes at the position (position can be :top :bottom :before :after).
273 | Assumes that the first element node in dom-nodes
274 | is the root of the element tree (other nodes are possibly text or comments).
275 | Does nothing if the targetted node can't be found. Returns a new
276 | sequence of dom nodes.
277 | dom-nodes
278 | A seq of nodes representing the document. The first element node is considered the root.
279 | rules
280 | A seq of rules identifying where to place the new nodes. Each rule is a pair of values.
281 | The first value is a seq of element types (as keywords) to navigate down. The second
282 | value is a position (:before, :after:, :top, or :bottom). The first matching rule
283 | is used.
284 | new-nodes
285 | The new nodes to insert in a position within the document."
286 | [dom-nodes rules new-nodes]
287 | (loop [result []
288 | queue dom-nodes]
289 | (lcond
290 | ; Never found an element node? Return the original nodes unchanged.
291 | (empty? queue) dom-nodes
292 | :let [node (first queue)]
293 | (element? node) (concat result [(apply-extend-dom-rules node rules new-nodes)] (rest queue))
294 | :else (recur (conj result node) (rest queue)))))
295 |
296 |
297 |
298 |
--------------------------------------------------------------------------------
/src/cascade/exception.clj:
--------------------------------------------------------------------------------
1 | ;;; Copyright 2009, 2010 Howard M. Lewis Ship
2 | ;;;
3 | ;;; Licensed under the Apache License, Version 2.0 (the "License");;;
4 | ;;; you may not use this file except in compliance with the License.
5 | ;;; You may obtain a copy of the License at
6 | ;;;
7 | ;;; http://www.apache.org/licenses/LICENSE-2.0
8 | ;;;
9 | ;;; Unless required by applicable law or agreed to in writing, software
10 | ;;; distributed under the License is distributed on an "AS IS" BASIS,
11 | ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 | ;;; implied. See the License for the specific language governing permissions
13 | ;;; and limitations under the License.
14 |
15 | (ns
16 | cascade.exception
17 | "Support for analyzing and exceptions and rendering an exception report page"
18 | (:import
19 | (java.lang Throwable StackTraceElement))
20 | (:require
21 | (clojure.contrib [str-utils2 :as s2]))
22 | (:use
23 | clojure.stacktrace
24 | cascade
25 | (cascade utils import asset)))
26 |
27 | ;; Identifies the properties of Throwable that are excluded from each exception-map's set of properties
28 |
29 | (def throwable-properties (keys (bean (Throwable.))))
30 |
31 | (defn class-name-for-element
32 | "Returns the CSS class name for a stack frame element, or nil. Useful values are :c-omitted-frame
33 | or :c-usercode-frame."
34 | [^StackTraceElement element]
35 | (lcond
36 | :let [class-name (.getClassName element)]
37 | (or
38 | (.startsWith class-name "clojure.lang.")
39 | (.startsWith class-name "sun.")
40 | (.startsWith class-name "java.lang.reflect.")) :c-omitted))
41 |
42 | (defn convert-clojure-frame
43 | "Converts a stack frame into DOM nodes representing the Clojure namespace and function name(s),
44 | or returns nil if the stack frame is not for a Clojure call frame."
45 | [class-name method-name]
46 | (when (contains? #{"invoke" "doInvoke"} method-name)
47 | (let [[namespace-name & raw-function-ids] (s2/split class-name #"\$")
48 | function-ids (map #(or (nth (first (re-seq #"([\w|.|-]+)__\d+?" %)) 1 nil) %) raw-function-ids)
49 | function-names (map #(s2/replace % \_ \-) function-ids)]
50 | (if-not (empty? raw-function-ids)
51 | (markup
52 | namespace-name "/" (s2/join "/" function-names)
53 | [:span {:class :c-omitted} :  class-name "." method-name])))))
54 |
55 | (defn transform-stack-frame
56 | [^StackTraceElement element]
57 | {
58 | :element element
59 | :method-name
60 | (let [file-name (.getFileName element)
61 | line-number (.getLineNumber element)
62 | class-name (.getClassName element)
63 | method-name (.getMethodName element)]
64 | (markup
65 | (or
66 | (convert-clojure-frame class-name method-name)
67 | (str class-name "." method-name))
68 | " "
69 | (cond
70 | (.isNativeMethod element) (markup [:em "(Native Method)"])
71 | (and (not (nil? file-name)) (< 0 line-number)) (str "(" file-name ":" line-number ")")
72 | (not (nil? file-name)) (str "(" file-name ")")
73 | true (markup [:em "(Unknown Source)"]))))
74 | :class-name (class-name-for-element element)
75 | })
76 |
77 | (defn transform-stack-trace
78 | "Transforms a primitive array of StackTraceElements into individual maps;
79 | :method-name is a seq of DOM nodes to describe the method and location
80 | :element is the original StackTraceElement
81 | :class-name is a keyword (may be nil) used when rendering the frame as an :li element"
82 | [elements]
83 | (loop [seen-filter false
84 | queue (map transform-stack-frame (seq elements))
85 | result []]
86 | (let [first-frame (first queue)
87 | ^StackTraceElement element (get first-frame :element)]
88 | (cond
89 | (nil? first-frame) result
90 | seen-filter (recur true (rest queue) (conj result (assoc first-frame :class-name :c-omitted-frame)))
91 | true (recur (= (.getClassName element) "cascade.filter") (rest queue) (conj result first-frame))))))
92 |
93 | (defn expand-exception-stack
94 | "Expands a simple exception into a seq of exception maps, representing the stack of exceptions (the first or outer
95 | exceptions wrap the later, inner, deeper exceptions). Each map has keys :class-name, :message, :stack-trace and :properties.
96 | :class-name is the name of the exception class, :message is the message associated with the exception,
97 | :stack-trace is via transform-stack-trace (and will only be present in the last, or deepest, exception map),
98 | and :properties is a map of additional JavaBean properties of the map that should be presented to the user. The values
99 | of the :properties map are Java objects, not necesarilly strings, and will need further transformation to be
100 | presented."
101 | [^Throwable thrown-exception]
102 | (loop [^Throwable current thrown-exception
103 | stack []]
104 | (let [bean-properties (bean current)
105 | next-exception (.getCause current)
106 | is-deepest (nil? next-exception)
107 | exception-map {:class-name (.. current getClass getName)
108 | :message (.getMessage current)
109 | :properties (apply dissoc bean-properties throwable-properties)}]
110 | (if is-deepest
111 | (conj stack (assoc exception-map :stack-trace (transform-stack-trace (.getStackTrace current))))
112 | (recur next-exception (conj stack exception-map))))))
113 |
114 | (def exception-banner "An unexpected exception has occurred.")
115 |
116 | (defn render-exception-map
117 | "Renders an individual exception map."
118 | [{:keys [class-name message properties stack-trace]}]
119 | (let [deepest (not (nil? stack-trace))
120 | has-properties (not (empty? properties))
121 | render-dl (or has-properties deepest)]
122 | (markup
123 | [:div.c-exception
124 | [:div.alert-message.error class-name]
125 | (if-not (nil? message)
126 | (markup [:div.c-exception-message message]))
127 | (when render-dl
128 | (markup
129 | [ :dl
130 | (markup-for [k (sort (keys properties))]
131 | [:dt (name k)]
132 | [:dd (str (get properties k))])
133 | (when deepest
134 | (markup
135 | [:dt "Stack Trace"]
136 | [:ul.c-stack-trace
137 | (markup-for [frame stack-trace]
138 | [:li {:class (frame :class-name)} (frame :method-name)])
139 | ]))
140 | ]))
141 | ])))
142 |
143 | (defn render-system-properties
144 | []
145 | (let [path-sep (System/getProperty "path.separator")
146 | property-names (sort (seq (.keySet (System/getProperties))))]
147 | (markup
148 | [:dl
149 | (for [^String name property-names]
150 | (let [value (System/getProperty name)]
151 | (markup
152 | [:dt name]
153 | [:dd
154 | (if (or (.endsWith name "path") (.endsWith name "dirs"))
155 | (markup [:ul
156 | (markup-for [v (.split value path-sep)]
157 | [:li v])
158 | ])
159 | value)
160 | ])))
161 | ])))
162 |
163 | (defragment render-environment
164 | []
165 | [:h2 "Environment"]
166 | [:dl
167 | [:dt "Clojure Version"]
168 | [:dd (str *clojure-version*)]
169 | [:dt "Cascade Version"]
170 | [:dd "TBD"]
171 | [:dt "Application Version"]
172 | [:dd "TBD"]
173 | ]
174 | [:h2 "System Properties"]
175 | (render-system-properties))
176 |
177 | (defragment render-exception-report-detail
178 | [exception]
179 | (import-stylesheet classpath-asset "cascade/exception.css")
180 | (import-module "cascade/exception-report")
181 | [:div.c-exception-controls>label
182 | [ :input#omitted-toggle {:type :checkbox}
183 | " Display hidden detail"
184 | ]
185 | ]
186 | [:br]
187 | (markup-for [m (expand-exception-stack exception)]
188 | ; TODO: Smarter logic about which frames to be hidden
189 | ; Currently, assumes only the deepest is interesting.
190 | ; When we add some additional levels of try/catch & report
191 | ; it may be useful to display some of the outer exceptions as well
192 | (render-exception-map m))
193 | (render-environment))
194 |
195 | (defview exception-report
196 | "The default exception report view. The top-most thrown exception is expected in the [:cascade :exception] key of the environment.
197 | Formats a detailed HTML report of the exception and the overall environment."
198 | [req exception]
199 | (import-stylesheet classpath-asset "cascade/bootstrap.css")
200 | [:html
201 | [:head>title exception-banner]
202 | [:body>div.container
203 | [:h1 exception-banner]
204 | (render-exception-report-detail exception)
205 | ]
206 | ])
--------------------------------------------------------------------------------
/src/cascade/fail.clj:
--------------------------------------------------------------------------------
1 | ; Copyright 2009, 2010, 2011 Howard M. Lewis Ship
2 | ;
3 | ; Licensed under the Apache License, Version 2.0 (the "License");
4 | ; you may not use this file except in compliance with the License.
5 | ; You may obtain a copy of the License at
6 | ; http://www.apache.org/licenses/LICENSE-2.0
7 | ;
8 | ; Unless required by applicable law or agreed to in writing, software
9 | ; distributed under the License is distributed on an "AS IS" BASIS,
10 | ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
11 | ; implied. See the License for the specific language governing permissions
12 | ; and limitations under the License.
13 | (ns
14 | cascade.fail
15 | "Assert-like failures")
16 |
17 | (defn fail
18 | "A quick way to throw a RuntimeException."
19 | [^String fmt & args]
20 | (let [^String msg (apply format fmt args)]
21 | (throw (RuntimeException. msg))))
22 |
23 | (defmacro fail-unless
24 | "Throws a runtime exception if the condition is false. The message is generated from the format
25 | and additional arguments and is only evaluated if a failure occurs."
26 | [condition fmt & args ]
27 | `(if-not ~condition (fail ~fmt ~@args)))
28 |
29 | (defmacro fail-if
30 | "Throws a runtime exception if the condition is true. The message is generated from the format
31 | and additional arguments and is only evaluated if a failure occurs."
32 | [condition fmt & args]
33 | `(if ~condition (fail ~fmt ~@args)))
--------------------------------------------------------------------------------
/src/cascade/import.clj:
--------------------------------------------------------------------------------
1 | ;;; Copyright 2011 Howard M. Lewis Ship
2 | ;;;
3 | ;;; Licensed under the Apache License, Version 2.0 (the "License");;;
4 | ;;; you may not use this file except in compliance with the License.
5 | ;;; You may obtain a copy of the License at
6 | ;;;
7 | ;;; http://www.apache.org/licenses/LICENSE-2.0
8 | ;;;
9 | ;;; Unless required by applicable law or agreed to in writing, software
10 | ;;; distributed under the License is distributed on an "AS IS" BASIS,
11 | ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 | ;;; implied. See the License for the specific language governing permissions
13 | ;;; and limitations under the License.
14 |
15 | (ns cascade.import
16 | "Support for importing assets and JavaScript initialization code into the document, during the DOM rendering phase."
17 | (:use
18 | cascade
19 | [cascade dom asset])
20 | (:require
21 | [clojure.string :as s2]
22 | [clj-json.core :as json]))
23 |
24 | (def ^{:dynamic true}
25 | *active-imports*
26 | "Stores a per-thread map used to track what's been imported."
27 | nil)
28 |
29 | (defn wrap-setup-active-imports [handler]
30 | "Binds the *active-imports* var so that it may be updated by the downstream handlers."
31 | (fn [req]
32 | (binding [*active-imports* {:stylesheets [] :javascript []}]
33 | (handler req))))
34 |
35 | (defn add-if-not-present
36 | [list value]
37 | (if (contains? list value)
38 | list
39 | ; Dependent on the list being a vector that conj-es at the end
40 | (conj list value)))
41 |
42 | (defn import-into-keyed-list
43 | "Updates that map in *active-imports*, adding the value to the list storted under the
44 | given key, if not already present. Returns nil."
45 | [key value]
46 | (set! *active-imports* (update-in *active-imports* [key] add-if-not-present value))
47 | nil)
48 |
49 | (defn import-stylesheet
50 | "Imports a stylesheet for a CSS asset. The stylesheet may be specified as an asset. Alternately, a stylesheet factory
51 | function and a path passed to that factory may be provided (which reads nicely). Returns nil."
52 | ; TODO: Naming and explicit ordering!
53 | ([stylesheet-asset]
54 | (import-into-keyed-list :stylesheets stylesheet-asset))
55 | ([factory-fn asset-path]
56 | (import-stylesheet (factory-fn asset-path))))
57 |
58 | (defn import-module
59 | "Imports a module by module name. Returns nil"
60 | [module-name]
61 | (import-into-keyed-list :javascript [module-name]))
62 |
63 | (defn javascript
64 | "Imports initialization JavaScript that will be executed when the page loads.
65 | module-name
66 | Name of module exposing the initialization function. The module should return a JavaScript object that maps names to functions.
67 | initializer-fn-name
68 | Name of a function exposed by the module that will be invoked.
69 | arguments
70 | Arguments passed to the client-side function. The arguments will be converted to JSON before being streamed to the client. Typically,
71 | a single value (a string, or a JSON Object) is passed."
72 | [module-name initializer-fn-name & arguments]
73 | ; TODO: this may change a bit when we implement Ajax partial rendering.
74 | (import-into-keyed-list :javascript [module-name initializer-fn-name arguments]))
75 |
76 | (defn javascript-invoke
77 | "Builds a very particular kinds of call to the javascript function:
78 | dependencies
79 | List of RequireJS module dependencies necessary to invoke the function. These are typically dependencies that extend
80 | jQuery.
81 | selector
82 | A CSS selector string passed to the jQuery main function.
83 | function-name
84 | Name of a jQuery function to invoke on the selection.
85 | arguments
86 | Arguments to pass to the jQuery function."
87 | [dependencies selector function-name & arguments]
88 | (apply javascript "cascade/init" "invoke" dependencies selector function-name arguments))
89 |
90 | (defn to-element-node
91 | "Converts an asset into a element node."
92 | [asset]
93 | (element-node :link {:rel :stylesheet :type "text/css" :href asset} nil))
94 |
95 | (defn add-stylesheet-nodes
96 | [dom-nodes stylesheet-assets]
97 | ; TODO: optimize when no assets
98 | (extend-dom dom-nodes [[[:html :head :script] :before]
99 | [[:html :head :link] :before]
100 | [[:html :head] :bottom]] (map to-element-node stylesheet-assets)))
101 |
102 | (defn apply-response-transformation
103 | [handler key transform-fn]
104 | (fn [req]
105 | (let [response (handler req)]
106 | (and response
107 | (update-in response [:body] transform-fn (*active-imports* key))))))
108 |
109 | (defn wrap-import-stylesheets
110 | "Middleware that expects the rendered body to be a seq of DOM nodes. The DOM nodes are
111 | post-processed to add new elements for any imported stylesheets."
112 | [handler]
113 | (apply-response-transformation handler :stylesheets add-stylesheet-nodes))
114 |
115 | (defn add-javascript
116 | "Updates the DOM with new body text