Show More
@@ -1,566 +1,552 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // Cell |
|
9 | // Cell | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 | /** |
|
11 | /** | |
12 | * An extendable module that provide base functionnality to create cell for notebook. |
|
12 | * An extendable module that provide base functionnality to create cell for notebook. | |
13 | * @module IPython |
|
13 | * @module IPython | |
14 | * @namespace IPython |
|
14 | * @namespace IPython | |
15 | * @submodule Cell |
|
15 | * @submodule Cell | |
16 | */ |
|
16 | */ | |
17 |
|
17 | |||
18 | var IPython = (function (IPython) { |
|
18 | var IPython = (function (IPython) { | |
19 | "use strict"; |
|
19 | "use strict"; | |
20 |
|
20 | |||
21 | var utils = IPython.utils; |
|
21 | var utils = IPython.utils; | |
22 | var keycodes = IPython.keyboard.keycodes; |
|
22 | var keycodes = IPython.keyboard.keycodes; | |
23 |
|
23 | |||
24 | /** |
|
24 | /** | |
25 | * The Base `Cell` class from which to inherit |
|
25 | * The Base `Cell` class from which to inherit | |
26 | * @class Cell |
|
26 | * @class Cell | |
27 | **/ |
|
27 | **/ | |
28 |
|
28 | |||
29 | /* |
|
29 | /* | |
30 | * @constructor |
|
30 | * @constructor | |
31 | * |
|
31 | * | |
32 | * @param {object|undefined} [options] |
|
32 | * @param {object|undefined} [options] | |
33 | * @param [options.cm_config] {object} config to pass to CodeMirror, will extend default parameters |
|
33 | * @param [options.cm_config] {object} config to pass to CodeMirror, will extend default parameters | |
34 | */ |
|
34 | */ | |
35 | var Cell = function (options) { |
|
35 | var Cell = function (options) { | |
36 |
|
36 | |||
37 | options = this.mergeopt(Cell, options); |
|
37 | options = this.mergeopt(Cell, options); | |
38 | // superclass default overwrite our default |
|
38 | // superclass default overwrite our default | |
39 |
|
39 | |||
40 | this.placeholder = options.placeholder || ''; |
|
40 | this.placeholder = options.placeholder || ''; | |
41 | this.read_only = options.cm_config.readOnly; |
|
41 | this.read_only = options.cm_config.readOnly; | |
42 | this.selected = false; |
|
42 | this.selected = false; | |
43 | this.rendered = false; |
|
43 | this.rendered = false; | |
44 | this.mode = 'command'; |
|
44 | this.mode = 'command'; | |
45 | this.metadata = {}; |
|
45 | this.metadata = {}; | |
46 | // load this from metadata later ? |
|
46 | // load this from metadata later ? | |
47 | this.user_highlight = 'auto'; |
|
47 | this.user_highlight = 'auto'; | |
48 | this.cm_config = options.cm_config; |
|
48 | this.cm_config = options.cm_config; | |
49 | this.cell_id = utils.uuid(); |
|
49 | this.cell_id = utils.uuid(); | |
50 | this._options = options; |
|
50 | this._options = options; | |
51 |
|
51 | |||
52 | // For JS VM engines optimization, attributes should be all set (even |
|
52 | // For JS VM engines optimization, attributes should be all set (even | |
53 | // to null) in the constructor, and if possible, if different subclass |
|
53 | // to null) in the constructor, and if possible, if different subclass | |
54 | // have new attributes with same name, they should be created in the |
|
54 | // have new attributes with same name, they should be created in the | |
55 | // same order. Easiest is to create and set to null in parent class. |
|
55 | // same order. Easiest is to create and set to null in parent class. | |
56 |
|
56 | |||
57 | this.element = null; |
|
57 | this.element = null; | |
58 | this.cell_type = this.cell_type || null; |
|
58 | this.cell_type = this.cell_type || null; | |
59 | this.code_mirror = null; |
|
59 | this.code_mirror = null; | |
60 |
|
60 | |||
61 | this.create_element(); |
|
61 | this.create_element(); | |
62 | if (this.element !== null) { |
|
62 | if (this.element !== null) { | |
63 | this.element.data("cell", this); |
|
63 | this.element.data("cell", this); | |
64 | this.bind_events(); |
|
64 | this.bind_events(); | |
65 | this.init_classes(); |
|
65 | this.init_classes(); | |
66 | } |
|
66 | } | |
67 | }; |
|
67 | }; | |
68 |
|
68 | |||
69 | Cell.options_default = { |
|
69 | Cell.options_default = { | |
70 | cm_config : { |
|
70 | cm_config : { | |
71 | indentUnit : 4, |
|
71 | indentUnit : 4, | |
72 | readOnly: false, |
|
72 | readOnly: false, | |
73 | theme: "default" |
|
73 | theme: "default" | |
74 | } |
|
74 | } | |
75 | }; |
|
75 | }; | |
76 |
|
76 | |||
77 | // FIXME: Workaround CM Bug #332 (Safari segfault on drag) |
|
77 | // FIXME: Workaround CM Bug #332 (Safari segfault on drag) | |
78 | // by disabling drag/drop altogether on Safari |
|
78 | // by disabling drag/drop altogether on Safari | |
79 | // https://github.com/marijnh/CodeMirror/issues/332 |
|
79 | // https://github.com/marijnh/CodeMirror/issues/332 | |
80 | if (utils.browser[0] == "Safari") { |
|
80 | if (utils.browser[0] == "Safari") { | |
81 | Cell.options_default.cm_config.dragDrop = false; |
|
81 | Cell.options_default.cm_config.dragDrop = false; | |
82 | } |
|
82 | } | |
83 |
|
83 | |||
84 | Cell.prototype.mergeopt = function(_class, options, overwrite){ |
|
84 | Cell.prototype.mergeopt = function(_class, options, overwrite){ | |
85 | options = options || {}; |
|
85 | options = options || {}; | |
86 | overwrite = overwrite || {}; |
|
86 | overwrite = overwrite || {}; | |
87 | return $.extend(true, {}, _class.options_default, options, overwrite); |
|
87 | return $.extend(true, {}, _class.options_default, options, overwrite); | |
88 | }; |
|
88 | }; | |
89 |
|
89 | |||
90 | /** |
|
90 | /** | |
91 | * Empty. Subclasses must implement create_element. |
|
91 | * Empty. Subclasses must implement create_element. | |
92 | * This should contain all the code to create the DOM element in notebook |
|
92 | * This should contain all the code to create the DOM element in notebook | |
93 | * and will be called by Base Class constructor. |
|
93 | * and will be called by Base Class constructor. | |
94 | * @method create_element |
|
94 | * @method create_element | |
95 | */ |
|
95 | */ | |
96 | Cell.prototype.create_element = function () { |
|
96 | Cell.prototype.create_element = function () { | |
97 | }; |
|
97 | }; | |
98 |
|
98 | |||
99 | Cell.prototype.init_classes = function () { |
|
99 | Cell.prototype.init_classes = function () { | |
100 | // Call after this.element exists to initialize the css classes |
|
100 | // Call after this.element exists to initialize the css classes | |
101 | // related to selected, rendered and mode. |
|
101 | // related to selected, rendered and mode. | |
102 | if (this.selected) { |
|
102 | if (this.selected) { | |
103 | this.element.addClass('selected'); |
|
103 | this.element.addClass('selected'); | |
104 | } else { |
|
104 | } else { | |
105 | this.element.addClass('unselected'); |
|
105 | this.element.addClass('unselected'); | |
106 | } |
|
106 | } | |
107 | if (this.rendered) { |
|
107 | if (this.rendered) { | |
108 | this.element.addClass('rendered'); |
|
108 | this.element.addClass('rendered'); | |
109 | } else { |
|
109 | } else { | |
110 | this.element.addClass('unrendered'); |
|
110 | this.element.addClass('unrendered'); | |
111 | } |
|
111 | } | |
112 | if (this.mode === 'edit') { |
|
112 | if (this.mode === 'edit') { | |
113 | this.element.addClass('edit_mode'); |
|
113 | this.element.addClass('edit_mode'); | |
114 | } else { |
|
114 | } else { | |
115 | this.element.addClass('command_mode'); |
|
115 | this.element.addClass('command_mode'); | |
116 | } |
|
116 | } | |
117 | }; |
|
117 | }; | |
118 |
|
118 | |||
119 | /** |
|
119 | /** | |
120 | * Subclasses can implement override bind_events. |
|
120 | * Subclasses can implement override bind_events. | |
121 | * Be carefull to call the parent method when overwriting as it fires event. |
|
121 | * Be carefull to call the parent method when overwriting as it fires event. | |
122 | * this will be triggerd after create_element in constructor. |
|
122 | * this will be triggerd after create_element in constructor. | |
123 | * @method bind_events |
|
123 | * @method bind_events | |
124 | */ |
|
124 | */ | |
125 | Cell.prototype.bind_events = function () { |
|
125 | Cell.prototype.bind_events = function () { | |
126 | var that = this; |
|
126 | var that = this; | |
127 | // We trigger events so that Cell doesn't have to depend on Notebook. |
|
127 | // We trigger events so that Cell doesn't have to depend on Notebook. | |
128 | that.element.click(function (event) { |
|
128 | that.element.click(function (event) { | |
129 | if (!that.selected) { |
|
129 | if (!that.selected) { | |
130 | $([IPython.events]).trigger('select.Cell', {'cell':that}); |
|
130 | $([IPython.events]).trigger('select.Cell', {'cell':that}); | |
131 | } |
|
131 | } | |
132 | }); |
|
132 | }); | |
133 | that.element.focusin(function (event) { |
|
133 | that.element.focusin(function (event) { | |
134 | if (!that.selected) { |
|
134 | if (!that.selected) { | |
135 | $([IPython.events]).trigger('select.Cell', {'cell':that}); |
|
135 | $([IPython.events]).trigger('select.Cell', {'cell':that}); | |
136 | } |
|
136 | } | |
137 | }); |
|
137 | }); | |
138 | if (this.code_mirror) { |
|
138 | if (this.code_mirror) { | |
139 | this.code_mirror.on("change", function(cm, change) { |
|
139 | this.code_mirror.on("change", function(cm, change) { | |
140 | $([IPython.events]).trigger("set_dirty.Notebook", {value: true}); |
|
140 | $([IPython.events]).trigger("set_dirty.Notebook", {value: true}); | |
141 | }); |
|
141 | }); | |
142 | } |
|
142 | } | |
143 | if (this.code_mirror) { |
|
143 | if (this.code_mirror) { | |
144 | this.code_mirror.on('focus', function(cm, change) { |
|
144 | this.code_mirror.on('focus', function(cm, change) { | |
145 | $([IPython.events]).trigger('edit_mode.Cell', {cell: that}); |
|
145 | $([IPython.events]).trigger('edit_mode.Cell', {cell: that}); | |
146 | }); |
|
146 | }); | |
147 | } |
|
147 | } | |
148 | if (this.code_mirror) { |
|
148 | if (this.code_mirror) { | |
149 | this.code_mirror.on('blur', function(cm, change) { |
|
149 | this.code_mirror.on('blur', function(cm, change) { | |
150 | // Check if this unfocus event is legit. |
|
150 | $([IPython.events]).trigger('command_mode.Cell', {cell: that}); | |
151 | if (!that.should_cancel_blur()) { |
|
|||
152 | $([IPython.events]).trigger('command_mode.Cell', {cell: that}); |
|
|||
153 | } |
|
|||
154 | }); |
|
151 | }); | |
155 | } |
|
152 | } | |
156 | }; |
|
153 | }; | |
157 |
|
154 | |||
158 | /** |
|
155 | /** | |
159 | * This method gets called in CodeMirror's onKeyDown/onKeyPress |
|
156 | * This method gets called in CodeMirror's onKeyDown/onKeyPress | |
160 | * handlers and is used to provide custom key handling. |
|
157 | * handlers and is used to provide custom key handling. | |
161 | * |
|
158 | * | |
162 | * To have custom handling, subclasses should override this method, but still call it |
|
159 | * To have custom handling, subclasses should override this method, but still call it | |
163 | * in order to process the Edit mode keyboard shortcuts. |
|
160 | * in order to process the Edit mode keyboard shortcuts. | |
164 | * |
|
161 | * | |
165 | * @method handle_codemirror_keyevent |
|
162 | * @method handle_codemirror_keyevent | |
166 | * @param {CodeMirror} editor - The codemirror instance bound to the cell |
|
163 | * @param {CodeMirror} editor - The codemirror instance bound to the cell | |
167 | * @param {event} event - key press event which either should or should not be handled by CodeMirror |
|
164 | * @param {event} event - key press event which either should or should not be handled by CodeMirror | |
168 | * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise |
|
165 | * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise | |
169 | */ |
|
166 | */ | |
170 | Cell.prototype.handle_codemirror_keyevent = function (editor, event) { |
|
167 | Cell.prototype.handle_codemirror_keyevent = function (editor, event) { | |
171 | var that = this; |
|
168 | var that = this; | |
172 | var shortcuts = IPython.keyboard_manager.edit_shortcuts; |
|
169 | var shortcuts = IPython.keyboard_manager.edit_shortcuts; | |
173 |
|
170 | |||
174 | // if this is an edit_shortcuts shortcut, the global keyboard/shortcut |
|
171 | // if this is an edit_shortcuts shortcut, the global keyboard/shortcut | |
175 | // manager will handle it |
|
172 | // manager will handle it | |
176 | if (shortcuts.handles(event)) { return true; } |
|
173 | if (shortcuts.handles(event)) { return true; } | |
177 |
|
174 | |||
178 | return false; |
|
175 | return false; | |
179 | }; |
|
176 | }; | |
180 |
|
177 | |||
181 |
|
178 | |||
182 | /** |
|
179 | /** | |
183 | * Triger typsetting of math by mathjax on current cell element |
|
180 | * Triger typsetting of math by mathjax on current cell element | |
184 | * @method typeset |
|
181 | * @method typeset | |
185 | */ |
|
182 | */ | |
186 | Cell.prototype.typeset = function () { |
|
183 | Cell.prototype.typeset = function () { | |
187 | if (window.MathJax) { |
|
184 | if (window.MathJax) { | |
188 | var cell_math = this.element.get(0); |
|
185 | var cell_math = this.element.get(0); | |
189 | MathJax.Hub.Queue(["Typeset", MathJax.Hub, cell_math]); |
|
186 | MathJax.Hub.Queue(["Typeset", MathJax.Hub, cell_math]); | |
190 | } |
|
187 | } | |
191 | }; |
|
188 | }; | |
192 |
|
189 | |||
193 | /** |
|
190 | /** | |
194 | * handle cell level logic when a cell is selected |
|
191 | * handle cell level logic when a cell is selected | |
195 | * @method select |
|
192 | * @method select | |
196 | * @return is the action being taken |
|
193 | * @return is the action being taken | |
197 | */ |
|
194 | */ | |
198 | Cell.prototype.select = function () { |
|
195 | Cell.prototype.select = function () { | |
199 | if (!this.selected) { |
|
196 | if (!this.selected) { | |
200 | this.element.addClass('selected'); |
|
197 | this.element.addClass('selected'); | |
201 | this.element.removeClass('unselected'); |
|
198 | this.element.removeClass('unselected'); | |
202 | this.selected = true; |
|
199 | this.selected = true; | |
203 | return true; |
|
200 | return true; | |
204 | } else { |
|
201 | } else { | |
205 | return false; |
|
202 | return false; | |
206 | } |
|
203 | } | |
207 | }; |
|
204 | }; | |
208 |
|
205 | |||
209 | /** |
|
206 | /** | |
210 | * handle cell level logic when a cell is unselected |
|
207 | * handle cell level logic when a cell is unselected | |
211 | * @method unselect |
|
208 | * @method unselect | |
212 | * @return is the action being taken |
|
209 | * @return is the action being taken | |
213 | */ |
|
210 | */ | |
214 | Cell.prototype.unselect = function () { |
|
211 | Cell.prototype.unselect = function () { | |
215 | if (this.selected) { |
|
212 | if (this.selected) { | |
216 | this.element.addClass('unselected'); |
|
213 | this.element.addClass('unselected'); | |
217 | this.element.removeClass('selected'); |
|
214 | this.element.removeClass('selected'); | |
218 | this.selected = false; |
|
215 | this.selected = false; | |
219 | return true; |
|
216 | return true; | |
220 | } else { |
|
217 | } else { | |
221 | return false; |
|
218 | return false; | |
222 | } |
|
219 | } | |
223 | }; |
|
220 | }; | |
224 |
|
221 | |||
225 | /** |
|
222 | /** | |
226 | * handle cell level logic when a cell is rendered |
|
223 | * handle cell level logic when a cell is rendered | |
227 | * @method render |
|
224 | * @method render | |
228 | * @return is the action being taken |
|
225 | * @return is the action being taken | |
229 | */ |
|
226 | */ | |
230 | Cell.prototype.render = function () { |
|
227 | Cell.prototype.render = function () { | |
231 | if (!this.rendered) { |
|
228 | if (!this.rendered) { | |
232 | this.element.addClass('rendered'); |
|
229 | this.element.addClass('rendered'); | |
233 | this.element.removeClass('unrendered'); |
|
230 | this.element.removeClass('unrendered'); | |
234 | this.rendered = true; |
|
231 | this.rendered = true; | |
235 | return true; |
|
232 | return true; | |
236 | } else { |
|
233 | } else { | |
237 | return false; |
|
234 | return false; | |
238 | } |
|
235 | } | |
239 | }; |
|
236 | }; | |
240 |
|
237 | |||
241 | /** |
|
238 | /** | |
242 | * handle cell level logic when a cell is unrendered |
|
239 | * handle cell level logic when a cell is unrendered | |
243 | * @method unrender |
|
240 | * @method unrender | |
244 | * @return is the action being taken |
|
241 | * @return is the action being taken | |
245 | */ |
|
242 | */ | |
246 | Cell.prototype.unrender = function () { |
|
243 | Cell.prototype.unrender = function () { | |
247 | if (this.rendered) { |
|
244 | if (this.rendered) { | |
248 | this.element.addClass('unrendered'); |
|
245 | this.element.addClass('unrendered'); | |
249 | this.element.removeClass('rendered'); |
|
246 | this.element.removeClass('rendered'); | |
250 | this.rendered = false; |
|
247 | this.rendered = false; | |
251 | return true; |
|
248 | return true; | |
252 | } else { |
|
249 | } else { | |
253 | return false; |
|
250 | return false; | |
254 | } |
|
251 | } | |
255 | }; |
|
252 | }; | |
256 |
|
253 | |||
257 | /** |
|
254 | /** | |
258 | * Delegates keyboard shortcut handling to either IPython keyboard |
|
255 | * Delegates keyboard shortcut handling to either IPython keyboard | |
259 | * manager when in command mode, or CodeMirror when in edit mode |
|
256 | * manager when in command mode, or CodeMirror when in edit mode | |
260 | * |
|
257 | * | |
261 | * @method handle_keyevent |
|
258 | * @method handle_keyevent | |
262 | * @param {CodeMirror} editor - The codemirror instance bound to the cell |
|
259 | * @param {CodeMirror} editor - The codemirror instance bound to the cell | |
263 | * @param {event} - key event to be handled |
|
260 | * @param {event} - key event to be handled | |
264 | * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise |
|
261 | * @return {Boolean} `true` if CodeMirror should ignore the event, `false` Otherwise | |
265 | */ |
|
262 | */ | |
266 | Cell.prototype.handle_keyevent = function (editor, event) { |
|
263 | Cell.prototype.handle_keyevent = function (editor, event) { | |
267 |
|
264 | |||
268 | // console.log('CM', this.mode, event.which, event.type) |
|
265 | // console.log('CM', this.mode, event.which, event.type) | |
269 |
|
266 | |||
270 | if (this.mode === 'command') { |
|
267 | if (this.mode === 'command') { | |
271 | return true; |
|
268 | return true; | |
272 | } else if (this.mode === 'edit') { |
|
269 | } else if (this.mode === 'edit') { | |
273 | return this.handle_codemirror_keyevent(editor, event); |
|
270 | return this.handle_codemirror_keyevent(editor, event); | |
274 | } |
|
271 | } | |
275 | }; |
|
272 | }; | |
276 |
|
273 | |||
277 | /** |
|
274 | /** | |
278 | * @method at_top |
|
275 | * @method at_top | |
279 | * @return {Boolean} |
|
276 | * @return {Boolean} | |
280 | */ |
|
277 | */ | |
281 | Cell.prototype.at_top = function () { |
|
278 | Cell.prototype.at_top = function () { | |
282 | var cm = this.code_mirror; |
|
279 | var cm = this.code_mirror; | |
283 | var cursor = cm.getCursor(); |
|
280 | var cursor = cm.getCursor(); | |
284 | if (cursor.line === 0 && cursor.ch === 0) { |
|
281 | if (cursor.line === 0 && cursor.ch === 0) { | |
285 | return true; |
|
282 | return true; | |
286 | } |
|
283 | } | |
287 | return false; |
|
284 | return false; | |
288 | }; |
|
285 | }; | |
289 |
|
286 | |||
290 | /** |
|
287 | /** | |
291 | * @method at_bottom |
|
288 | * @method at_bottom | |
292 | * @return {Boolean} |
|
289 | * @return {Boolean} | |
293 | * */ |
|
290 | * */ | |
294 | Cell.prototype.at_bottom = function () { |
|
291 | Cell.prototype.at_bottom = function () { | |
295 | var cm = this.code_mirror; |
|
292 | var cm = this.code_mirror; | |
296 | var cursor = cm.getCursor(); |
|
293 | var cursor = cm.getCursor(); | |
297 | if (cursor.line === (cm.lineCount()-1) && cursor.ch === cm.getLine(cursor.line).length) { |
|
294 | if (cursor.line === (cm.lineCount()-1) && cursor.ch === cm.getLine(cursor.line).length) { | |
298 | return true; |
|
295 | return true; | |
299 | } |
|
296 | } | |
300 | return false; |
|
297 | return false; | |
301 | }; |
|
298 | }; | |
302 |
|
299 | |||
303 | /** |
|
300 | /** | |
304 | * enter the command mode for the cell |
|
301 | * enter the command mode for the cell | |
305 | * @method command_mode |
|
302 | * @method command_mode | |
306 | * @return is the action being taken |
|
303 | * @return is the action being taken | |
307 | */ |
|
304 | */ | |
308 | Cell.prototype.command_mode = function () { |
|
305 | Cell.prototype.command_mode = function () { | |
309 | if (this.mode !== 'command') { |
|
306 | if (this.mode !== 'command') { | |
310 | this.element.addClass('command_mode'); |
|
307 | this.element.addClass('command_mode'); | |
311 | this.element.removeClass('edit_mode'); |
|
308 | this.element.removeClass('edit_mode'); | |
312 | this.mode = 'command'; |
|
309 | this.mode = 'command'; | |
313 | return true; |
|
310 | return true; | |
314 | } else { |
|
311 | } else { | |
315 | return false; |
|
312 | return false; | |
316 | } |
|
313 | } | |
317 | }; |
|
314 | }; | |
318 |
|
315 | |||
319 | /** |
|
316 | /** | |
320 | * enter the edit mode for the cell |
|
317 | * enter the edit mode for the cell | |
321 | * @method command_mode |
|
318 | * @method command_mode | |
322 | * @return is the action being taken |
|
319 | * @return is the action being taken | |
323 | */ |
|
320 | */ | |
324 | Cell.prototype.edit_mode = function () { |
|
321 | Cell.prototype.edit_mode = function () { | |
325 | if (this.mode !== 'edit') { |
|
322 | if (this.mode !== 'edit') { | |
326 | this.element.addClass('edit_mode'); |
|
323 | this.element.addClass('edit_mode'); | |
327 | this.element.removeClass('command_mode'); |
|
324 | this.element.removeClass('command_mode'); | |
328 | this.mode = 'edit'; |
|
325 | this.mode = 'edit'; | |
329 | return true; |
|
326 | return true; | |
330 | } else { |
|
327 | } else { | |
331 | return false; |
|
328 | return false; | |
332 | } |
|
329 | } | |
333 | }; |
|
330 | }; | |
334 |
|
331 | |||
335 | /** |
|
|||
336 | * Determine whether or not the unfocus event should be aknowledged. |
|
|||
337 | * |
|
|||
338 | * @method should_cancel_blur |
|
|||
339 | * |
|
|||
340 | * @return results {bool} Whether or not to ignore the cell's blur event. |
|
|||
341 | **/ |
|
|||
342 | Cell.prototype.should_cancel_blur = function () { |
|
|||
343 | return false; |
|
|||
344 | }; |
|
|||
345 |
|
||||
346 | /** |
|
332 | /** | |
347 | * Focus the cell in the DOM sense |
|
333 | * Focus the cell in the DOM sense | |
348 | * @method focus_cell |
|
334 | * @method focus_cell | |
349 | */ |
|
335 | */ | |
350 | Cell.prototype.focus_cell = function () { |
|
336 | Cell.prototype.focus_cell = function () { | |
351 | this.element.focus(); |
|
337 | this.element.focus(); | |
352 | }; |
|
338 | }; | |
353 |
|
339 | |||
354 | /** |
|
340 | /** | |
355 | * Focus the editor area so a user can type |
|
341 | * Focus the editor area so a user can type | |
356 | * |
|
342 | * | |
357 | * NOTE: If codemirror is focused via a mouse click event, you don't want to |
|
343 | * NOTE: If codemirror is focused via a mouse click event, you don't want to | |
358 | * call this because it will cause a page jump. |
|
344 | * call this because it will cause a page jump. | |
359 | * @method focus_editor |
|
345 | * @method focus_editor | |
360 | */ |
|
346 | */ | |
361 | Cell.prototype.focus_editor = function () { |
|
347 | Cell.prototype.focus_editor = function () { | |
362 | this.refresh(); |
|
348 | this.refresh(); | |
363 | this.code_mirror.focus(); |
|
349 | this.code_mirror.focus(); | |
364 | }; |
|
350 | }; | |
365 |
|
351 | |||
366 | /** |
|
352 | /** | |
367 | * Refresh codemirror instance |
|
353 | * Refresh codemirror instance | |
368 | * @method refresh |
|
354 | * @method refresh | |
369 | */ |
|
355 | */ | |
370 | Cell.prototype.refresh = function () { |
|
356 | Cell.prototype.refresh = function () { | |
371 | this.code_mirror.refresh(); |
|
357 | this.code_mirror.refresh(); | |
372 | }; |
|
358 | }; | |
373 |
|
359 | |||
374 | /** |
|
360 | /** | |
375 | * should be overritten by subclass |
|
361 | * should be overritten by subclass | |
376 | * @method get_text |
|
362 | * @method get_text | |
377 | */ |
|
363 | */ | |
378 | Cell.prototype.get_text = function () { |
|
364 | Cell.prototype.get_text = function () { | |
379 | }; |
|
365 | }; | |
380 |
|
366 | |||
381 | /** |
|
367 | /** | |
382 | * should be overritten by subclass |
|
368 | * should be overritten by subclass | |
383 | * @method set_text |
|
369 | * @method set_text | |
384 | * @param {string} text |
|
370 | * @param {string} text | |
385 | */ |
|
371 | */ | |
386 | Cell.prototype.set_text = function (text) { |
|
372 | Cell.prototype.set_text = function (text) { | |
387 | }; |
|
373 | }; | |
388 |
|
374 | |||
389 | /** |
|
375 | /** | |
390 | * should be overritten by subclass |
|
376 | * should be overritten by subclass | |
391 | * serialise cell to json. |
|
377 | * serialise cell to json. | |
392 | * @method toJSON |
|
378 | * @method toJSON | |
393 | **/ |
|
379 | **/ | |
394 | Cell.prototype.toJSON = function () { |
|
380 | Cell.prototype.toJSON = function () { | |
395 | var data = {}; |
|
381 | var data = {}; | |
396 | data.metadata = this.metadata; |
|
382 | data.metadata = this.metadata; | |
397 | data.cell_type = this.cell_type; |
|
383 | data.cell_type = this.cell_type; | |
398 | return data; |
|
384 | return data; | |
399 | }; |
|
385 | }; | |
400 |
|
386 | |||
401 |
|
387 | |||
402 | /** |
|
388 | /** | |
403 | * should be overritten by subclass |
|
389 | * should be overritten by subclass | |
404 | * @method fromJSON |
|
390 | * @method fromJSON | |
405 | **/ |
|
391 | **/ | |
406 | Cell.prototype.fromJSON = function (data) { |
|
392 | Cell.prototype.fromJSON = function (data) { | |
407 | if (data.metadata !== undefined) { |
|
393 | if (data.metadata !== undefined) { | |
408 | this.metadata = data.metadata; |
|
394 | this.metadata = data.metadata; | |
409 | } |
|
395 | } | |
410 | this.celltoolbar.rebuild(); |
|
396 | this.celltoolbar.rebuild(); | |
411 | }; |
|
397 | }; | |
412 |
|
398 | |||
413 |
|
399 | |||
414 | /** |
|
400 | /** | |
415 | * can the cell be split into two cells |
|
401 | * can the cell be split into two cells | |
416 | * @method is_splittable |
|
402 | * @method is_splittable | |
417 | **/ |
|
403 | **/ | |
418 | Cell.prototype.is_splittable = function () { |
|
404 | Cell.prototype.is_splittable = function () { | |
419 | return true; |
|
405 | return true; | |
420 | }; |
|
406 | }; | |
421 |
|
407 | |||
422 |
|
408 | |||
423 | /** |
|
409 | /** | |
424 | * can the cell be merged with other cells |
|
410 | * can the cell be merged with other cells | |
425 | * @method is_mergeable |
|
411 | * @method is_mergeable | |
426 | **/ |
|
412 | **/ | |
427 | Cell.prototype.is_mergeable = function () { |
|
413 | Cell.prototype.is_mergeable = function () { | |
428 | return true; |
|
414 | return true; | |
429 | }; |
|
415 | }; | |
430 |
|
416 | |||
431 |
|
417 | |||
432 | /** |
|
418 | /** | |
433 | * @return {String} - the text before the cursor |
|
419 | * @return {String} - the text before the cursor | |
434 | * @method get_pre_cursor |
|
420 | * @method get_pre_cursor | |
435 | **/ |
|
421 | **/ | |
436 | Cell.prototype.get_pre_cursor = function () { |
|
422 | Cell.prototype.get_pre_cursor = function () { | |
437 | var cursor = this.code_mirror.getCursor(); |
|
423 | var cursor = this.code_mirror.getCursor(); | |
438 | var text = this.code_mirror.getRange({line:0, ch:0}, cursor); |
|
424 | var text = this.code_mirror.getRange({line:0, ch:0}, cursor); | |
439 | text = text.replace(/^\n+/, '').replace(/\n+$/, ''); |
|
425 | text = text.replace(/^\n+/, '').replace(/\n+$/, ''); | |
440 | return text; |
|
426 | return text; | |
441 | }; |
|
427 | }; | |
442 |
|
428 | |||
443 |
|
429 | |||
444 | /** |
|
430 | /** | |
445 | * @return {String} - the text after the cursor |
|
431 | * @return {String} - the text after the cursor | |
446 | * @method get_post_cursor |
|
432 | * @method get_post_cursor | |
447 | **/ |
|
433 | **/ | |
448 | Cell.prototype.get_post_cursor = function () { |
|
434 | Cell.prototype.get_post_cursor = function () { | |
449 | var cursor = this.code_mirror.getCursor(); |
|
435 | var cursor = this.code_mirror.getCursor(); | |
450 | var last_line_num = this.code_mirror.lineCount()-1; |
|
436 | var last_line_num = this.code_mirror.lineCount()-1; | |
451 | var last_line_len = this.code_mirror.getLine(last_line_num).length; |
|
437 | var last_line_len = this.code_mirror.getLine(last_line_num).length; | |
452 | var end = {line:last_line_num, ch:last_line_len}; |
|
438 | var end = {line:last_line_num, ch:last_line_len}; | |
453 | var text = this.code_mirror.getRange(cursor, end); |
|
439 | var text = this.code_mirror.getRange(cursor, end); | |
454 | text = text.replace(/^\n+/, '').replace(/\n+$/, ''); |
|
440 | text = text.replace(/^\n+/, '').replace(/\n+$/, ''); | |
455 | return text; |
|
441 | return text; | |
456 | }; |
|
442 | }; | |
457 |
|
443 | |||
458 | /** |
|
444 | /** | |
459 | * Show/Hide CodeMirror LineNumber |
|
445 | * Show/Hide CodeMirror LineNumber | |
460 | * @method show_line_numbers |
|
446 | * @method show_line_numbers | |
461 | * |
|
447 | * | |
462 | * @param value {Bool} show (true), or hide (false) the line number in CodeMirror |
|
448 | * @param value {Bool} show (true), or hide (false) the line number in CodeMirror | |
463 | **/ |
|
449 | **/ | |
464 | Cell.prototype.show_line_numbers = function (value) { |
|
450 | Cell.prototype.show_line_numbers = function (value) { | |
465 | this.code_mirror.setOption('lineNumbers', value); |
|
451 | this.code_mirror.setOption('lineNumbers', value); | |
466 | this.code_mirror.refresh(); |
|
452 | this.code_mirror.refresh(); | |
467 | }; |
|
453 | }; | |
468 |
|
454 | |||
469 | /** |
|
455 | /** | |
470 | * Toggle CodeMirror LineNumber |
|
456 | * Toggle CodeMirror LineNumber | |
471 | * @method toggle_line_numbers |
|
457 | * @method toggle_line_numbers | |
472 | **/ |
|
458 | **/ | |
473 | Cell.prototype.toggle_line_numbers = function () { |
|
459 | Cell.prototype.toggle_line_numbers = function () { | |
474 | var val = this.code_mirror.getOption('lineNumbers'); |
|
460 | var val = this.code_mirror.getOption('lineNumbers'); | |
475 | this.show_line_numbers(!val); |
|
461 | this.show_line_numbers(!val); | |
476 | }; |
|
462 | }; | |
477 |
|
463 | |||
478 | /** |
|
464 | /** | |
479 | * Force codemirror highlight mode |
|
465 | * Force codemirror highlight mode | |
480 | * @method force_highlight |
|
466 | * @method force_highlight | |
481 | * @param {object} - CodeMirror mode |
|
467 | * @param {object} - CodeMirror mode | |
482 | **/ |
|
468 | **/ | |
483 | Cell.prototype.force_highlight = function(mode) { |
|
469 | Cell.prototype.force_highlight = function(mode) { | |
484 | this.user_highlight = mode; |
|
470 | this.user_highlight = mode; | |
485 | this.auto_highlight(); |
|
471 | this.auto_highlight(); | |
486 | }; |
|
472 | }; | |
487 |
|
473 | |||
488 | /** |
|
474 | /** | |
489 | * Try to autodetect cell highlight mode, or use selected mode |
|
475 | * Try to autodetect cell highlight mode, or use selected mode | |
490 | * @methods _auto_highlight |
|
476 | * @methods _auto_highlight | |
491 | * @private |
|
477 | * @private | |
492 | * @param {String|object|undefined} - CodeMirror mode | 'auto' |
|
478 | * @param {String|object|undefined} - CodeMirror mode | 'auto' | |
493 | **/ |
|
479 | **/ | |
494 | Cell.prototype._auto_highlight = function (modes) { |
|
480 | Cell.prototype._auto_highlight = function (modes) { | |
495 | //Here we handle manually selected modes |
|
481 | //Here we handle manually selected modes | |
496 | var mode; |
|
482 | var mode; | |
497 | if( this.user_highlight !== undefined && this.user_highlight != 'auto' ) |
|
483 | if( this.user_highlight !== undefined && this.user_highlight != 'auto' ) | |
498 | { |
|
484 | { | |
499 | mode = this.user_highlight; |
|
485 | mode = this.user_highlight; | |
500 | CodeMirror.autoLoadMode(this.code_mirror, mode); |
|
486 | CodeMirror.autoLoadMode(this.code_mirror, mode); | |
501 | this.code_mirror.setOption('mode', mode); |
|
487 | this.code_mirror.setOption('mode', mode); | |
502 | return; |
|
488 | return; | |
503 | } |
|
489 | } | |
504 | var current_mode = this.code_mirror.getOption('mode', mode); |
|
490 | var current_mode = this.code_mirror.getOption('mode', mode); | |
505 | var first_line = this.code_mirror.getLine(0); |
|
491 | var first_line = this.code_mirror.getLine(0); | |
506 | // loop on every pairs |
|
492 | // loop on every pairs | |
507 | for(mode in modes) { |
|
493 | for(mode in modes) { | |
508 | var regs = modes[mode].reg; |
|
494 | var regs = modes[mode].reg; | |
509 | // only one key every time but regexp can't be keys... |
|
495 | // only one key every time but regexp can't be keys... | |
510 | for(var i=0; i<regs.length; i++) { |
|
496 | for(var i=0; i<regs.length; i++) { | |
511 | // here we handle non magic_modes |
|
497 | // here we handle non magic_modes | |
512 | if(first_line.match(regs[i]) !== null) { |
|
498 | if(first_line.match(regs[i]) !== null) { | |
513 | if(current_mode == mode){ |
|
499 | if(current_mode == mode){ | |
514 | return; |
|
500 | return; | |
515 | } |
|
501 | } | |
516 | if (mode.search('magic_') !== 0) { |
|
502 | if (mode.search('magic_') !== 0) { | |
517 | this.code_mirror.setOption('mode', mode); |
|
503 | this.code_mirror.setOption('mode', mode); | |
518 | CodeMirror.autoLoadMode(this.code_mirror, mode); |
|
504 | CodeMirror.autoLoadMode(this.code_mirror, mode); | |
519 | return; |
|
505 | return; | |
520 | } |
|
506 | } | |
521 | var open = modes[mode].open || "%%"; |
|
507 | var open = modes[mode].open || "%%"; | |
522 | var close = modes[mode].close || "%%end"; |
|
508 | var close = modes[mode].close || "%%end"; | |
523 | var mmode = mode; |
|
509 | var mmode = mode; | |
524 | mode = mmode.substr(6); |
|
510 | mode = mmode.substr(6); | |
525 | if(current_mode == mode){ |
|
511 | if(current_mode == mode){ | |
526 | return; |
|
512 | return; | |
527 | } |
|
513 | } | |
528 | CodeMirror.autoLoadMode(this.code_mirror, mode); |
|
514 | CodeMirror.autoLoadMode(this.code_mirror, mode); | |
529 | // create on the fly a mode that swhitch between |
|
515 | // create on the fly a mode that swhitch between | |
530 | // plain/text and smth else otherwise `%%` is |
|
516 | // plain/text and smth else otherwise `%%` is | |
531 | // source of some highlight issues. |
|
517 | // source of some highlight issues. | |
532 | // we use patchedGetMode to circumvent a bug in CM |
|
518 | // we use patchedGetMode to circumvent a bug in CM | |
533 | CodeMirror.defineMode(mmode , function(config) { |
|
519 | CodeMirror.defineMode(mmode , function(config) { | |
534 | return CodeMirror.multiplexingMode( |
|
520 | return CodeMirror.multiplexingMode( | |
535 | CodeMirror.patchedGetMode(config, 'text/plain'), |
|
521 | CodeMirror.patchedGetMode(config, 'text/plain'), | |
536 | // always set someting on close |
|
522 | // always set someting on close | |
537 | {open: open, close: close, |
|
523 | {open: open, close: close, | |
538 | mode: CodeMirror.patchedGetMode(config, mode), |
|
524 | mode: CodeMirror.patchedGetMode(config, mode), | |
539 | delimStyle: "delimit" |
|
525 | delimStyle: "delimit" | |
540 | } |
|
526 | } | |
541 | ); |
|
527 | ); | |
542 | }); |
|
528 | }); | |
543 | this.code_mirror.setOption('mode', mmode); |
|
529 | this.code_mirror.setOption('mode', mmode); | |
544 | return; |
|
530 | return; | |
545 | } |
|
531 | } | |
546 | } |
|
532 | } | |
547 | } |
|
533 | } | |
548 | // fallback on default |
|
534 | // fallback on default | |
549 | var default_mode; |
|
535 | var default_mode; | |
550 | try { |
|
536 | try { | |
551 | default_mode = this._options.cm_config.mode; |
|
537 | default_mode = this._options.cm_config.mode; | |
552 | } catch(e) { |
|
538 | } catch(e) { | |
553 | default_mode = 'text/plain'; |
|
539 | default_mode = 'text/plain'; | |
554 | } |
|
540 | } | |
555 | if( current_mode === default_mode){ |
|
541 | if( current_mode === default_mode){ | |
556 | return; |
|
542 | return; | |
557 | } |
|
543 | } | |
558 | this.code_mirror.setOption('mode', default_mode); |
|
544 | this.code_mirror.setOption('mode', default_mode); | |
559 | }; |
|
545 | }; | |
560 |
|
546 | |||
561 | IPython.Cell = Cell; |
|
547 | IPython.Cell = Cell; | |
562 |
|
548 | |||
563 | return IPython; |
|
549 | return IPython; | |
564 |
|
550 | |||
565 | }(IPython)); |
|
551 | }(IPython)); | |
566 |
|
552 |
@@ -1,515 +1,517 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2008-2011 The IPython Development Team |
|
2 | // Copyright (C) 2008-2011 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // CodeCell |
|
9 | // CodeCell | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 | /** |
|
11 | /** | |
12 | * An extendable module that provide base functionnality to create cell for notebook. |
|
12 | * An extendable module that provide base functionnality to create cell for notebook. | |
13 | * @module IPython |
|
13 | * @module IPython | |
14 | * @namespace IPython |
|
14 | * @namespace IPython | |
15 | * @submodule CodeCell |
|
15 | * @submodule CodeCell | |
16 | */ |
|
16 | */ | |
17 |
|
17 | |||
18 |
|
18 | |||
19 | /* local util for codemirror */ |
|
19 | /* local util for codemirror */ | |
20 | var posEq = function(a, b) {return a.line == b.line && a.ch == b.ch;}; |
|
20 | var posEq = function(a, b) {return a.line == b.line && a.ch == b.ch;}; | |
21 |
|
21 | |||
22 | /** |
|
22 | /** | |
23 | * |
|
23 | * | |
24 | * function to delete until previous non blanking space character |
|
24 | * function to delete until previous non blanking space character | |
25 | * or first multiple of 4 tabstop. |
|
25 | * or first multiple of 4 tabstop. | |
26 | * @private |
|
26 | * @private | |
27 | */ |
|
27 | */ | |
28 | CodeMirror.commands.delSpaceToPrevTabStop = function(cm){ |
|
28 | CodeMirror.commands.delSpaceToPrevTabStop = function(cm){ | |
29 | var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to); |
|
29 | var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to); | |
30 | if (!posEq(from, to)) { cm.replaceRange("", from, to); return; } |
|
30 | if (!posEq(from, to)) { cm.replaceRange("", from, to); return; } | |
31 | var cur = cm.getCursor(), line = cm.getLine(cur.line); |
|
31 | var cur = cm.getCursor(), line = cm.getLine(cur.line); | |
32 | var tabsize = cm.getOption('tabSize'); |
|
32 | var tabsize = cm.getOption('tabSize'); | |
33 | var chToPrevTabStop = cur.ch-(Math.ceil(cur.ch/tabsize)-1)*tabsize; |
|
33 | var chToPrevTabStop = cur.ch-(Math.ceil(cur.ch/tabsize)-1)*tabsize; | |
34 | from = {ch:cur.ch-chToPrevTabStop,line:cur.line}; |
|
34 | from = {ch:cur.ch-chToPrevTabStop,line:cur.line}; | |
35 | var select = cm.getRange(from,cur); |
|
35 | var select = cm.getRange(from,cur); | |
36 | if( select.match(/^\ +$/) !== null){ |
|
36 | if( select.match(/^\ +$/) !== null){ | |
37 | cm.replaceRange("",from,cur); |
|
37 | cm.replaceRange("",from,cur); | |
38 | } else { |
|
38 | } else { | |
39 | cm.deleteH(-1,"char"); |
|
39 | cm.deleteH(-1,"char"); | |
40 | } |
|
40 | } | |
41 | }; |
|
41 | }; | |
42 |
|
42 | |||
43 |
|
43 | |||
44 | var IPython = (function (IPython) { |
|
44 | var IPython = (function (IPython) { | |
45 | "use strict"; |
|
45 | "use strict"; | |
46 |
|
46 | |||
47 | var utils = IPython.utils; |
|
47 | var utils = IPython.utils; | |
48 | var keycodes = IPython.keyboard.keycodes; |
|
48 | var keycodes = IPython.keyboard.keycodes; | |
49 |
|
49 | |||
50 | /** |
|
50 | /** | |
51 | * A Cell conceived to write code. |
|
51 | * A Cell conceived to write code. | |
52 | * |
|
52 | * | |
53 | * The kernel doesn't have to be set at creation time, in that case |
|
53 | * The kernel doesn't have to be set at creation time, in that case | |
54 | * it will be null and set_kernel has to be called later. |
|
54 | * it will be null and set_kernel has to be called later. | |
55 | * @class CodeCell |
|
55 | * @class CodeCell | |
56 | * @extends IPython.Cell |
|
56 | * @extends IPython.Cell | |
57 | * |
|
57 | * | |
58 | * @constructor |
|
58 | * @constructor | |
59 | * @param {Object|null} kernel |
|
59 | * @param {Object|null} kernel | |
60 | * @param {object|undefined} [options] |
|
60 | * @param {object|undefined} [options] | |
61 | * @param [options.cm_config] {object} config to pass to CodeMirror |
|
61 | * @param [options.cm_config] {object} config to pass to CodeMirror | |
62 | */ |
|
62 | */ | |
63 | var CodeCell = function (kernel, options) { |
|
63 | var CodeCell = function (kernel, options) { | |
64 | this.kernel = kernel || null; |
|
64 | this.kernel = kernel || null; | |
65 | this.collapsed = false; |
|
65 | this.collapsed = false; | |
66 |
|
66 | |||
67 | // create all attributed in constructor function |
|
67 | // create all attributed in constructor function | |
68 | // even if null for V8 VM optimisation |
|
68 | // even if null for V8 VM optimisation | |
69 | this.input_prompt_number = null; |
|
69 | this.input_prompt_number = null; | |
70 | this.celltoolbar = null; |
|
70 | this.celltoolbar = null; | |
71 | this.output_area = null; |
|
71 | this.output_area = null; | |
72 | this.last_msg_id = null; |
|
72 | this.last_msg_id = null; | |
73 | this.completer = null; |
|
73 | this.completer = null; | |
74 |
|
74 | |||
75 |
|
75 | |||
76 | var cm_overwrite_options = { |
|
76 | var cm_overwrite_options = { | |
77 | onKeyEvent: $.proxy(this.handle_keyevent,this) |
|
77 | onKeyEvent: $.proxy(this.handle_keyevent,this) | |
78 | }; |
|
78 | }; | |
79 |
|
79 | |||
80 | options = this.mergeopt(CodeCell, options, {cm_config:cm_overwrite_options}); |
|
80 | options = this.mergeopt(CodeCell, options, {cm_config:cm_overwrite_options}); | |
81 |
|
81 | |||
82 | IPython.Cell.apply(this,[options]); |
|
82 | IPython.Cell.apply(this,[options]); | |
83 |
|
83 | |||
84 | // Attributes we want to override in this subclass. |
|
84 | // Attributes we want to override in this subclass. | |
85 | this.cell_type = "code"; |
|
85 | this.cell_type = "code"; | |
86 |
|
86 | |||
87 | var that = this; |
|
87 | var that = this; | |
88 | this.element.focusout( |
|
88 | this.element.focusout( | |
89 | function() { that.auto_highlight(); } |
|
89 | function() { that.auto_highlight(); } | |
90 | ); |
|
90 | ); | |
91 | }; |
|
91 | }; | |
92 |
|
92 | |||
93 | CodeCell.options_default = { |
|
93 | CodeCell.options_default = { | |
94 | cm_config : { |
|
94 | cm_config : { | |
95 | extraKeys: { |
|
95 | extraKeys: { | |
96 | "Tab" : "indentMore", |
|
96 | "Tab" : "indentMore", | |
97 | "Shift-Tab" : "indentLess", |
|
97 | "Shift-Tab" : "indentLess", | |
98 | "Backspace" : "delSpaceToPrevTabStop", |
|
98 | "Backspace" : "delSpaceToPrevTabStop", | |
99 | "Cmd-/" : "toggleComment", |
|
99 | "Cmd-/" : "toggleComment", | |
100 | "Ctrl-/" : "toggleComment" |
|
100 | "Ctrl-/" : "toggleComment" | |
101 | }, |
|
101 | }, | |
102 | mode: 'ipython', |
|
102 | mode: 'ipython', | |
103 | theme: 'ipython', |
|
103 | theme: 'ipython', | |
104 | matchBrackets: true, |
|
104 | matchBrackets: true, | |
105 | // don't auto-close strings because of CodeMirror #2385 |
|
105 | // don't auto-close strings because of CodeMirror #2385 | |
106 | autoCloseBrackets: "()[]{}" |
|
106 | autoCloseBrackets: "()[]{}" | |
107 | } |
|
107 | } | |
108 | }; |
|
108 | }; | |
109 |
|
109 | |||
110 | CodeCell.msg_cells = {}; |
|
110 | CodeCell.msg_cells = {}; | |
111 |
|
111 | |||
112 | CodeCell.prototype = new IPython.Cell(); |
|
112 | CodeCell.prototype = new IPython.Cell(); | |
113 |
|
113 | |||
114 | /** |
|
114 | /** | |
115 | * @method auto_highlight |
|
115 | * @method auto_highlight | |
116 | */ |
|
116 | */ | |
117 | CodeCell.prototype.auto_highlight = function () { |
|
117 | CodeCell.prototype.auto_highlight = function () { | |
118 | this._auto_highlight(IPython.config.cell_magic_highlight); |
|
118 | this._auto_highlight(IPython.config.cell_magic_highlight); | |
119 | }; |
|
119 | }; | |
120 |
|
120 | |||
121 | /** @method create_element */ |
|
121 | /** @method create_element */ | |
122 | CodeCell.prototype.create_element = function () { |
|
122 | CodeCell.prototype.create_element = function () { | |
123 | IPython.Cell.prototype.create_element.apply(this, arguments); |
|
123 | IPython.Cell.prototype.create_element.apply(this, arguments); | |
124 |
|
124 | |||
125 | var cell = $('<div></div>').addClass('cell border-box-sizing code_cell'); |
|
125 | var cell = $('<div></div>').addClass('cell border-box-sizing code_cell'); | |
126 | cell.attr('tabindex','2'); |
|
126 | cell.attr('tabindex','2'); | |
127 |
|
127 | |||
128 | var input = $('<div></div>').addClass('input'); |
|
128 | var input = $('<div></div>').addClass('input'); | |
129 | var prompt = $('<div/>').addClass('prompt input_prompt'); |
|
129 | var prompt = $('<div/>').addClass('prompt input_prompt'); | |
130 | var inner_cell = $('<div/>').addClass('inner_cell'); |
|
130 | var inner_cell = $('<div/>').addClass('inner_cell'); | |
131 | this.celltoolbar = new IPython.CellToolbar(this); |
|
131 | this.celltoolbar = new IPython.CellToolbar(this); | |
132 | inner_cell.append(this.celltoolbar.element); |
|
132 | inner_cell.append(this.celltoolbar.element); | |
133 | var input_area = $('<div/>').addClass('input_area'); |
|
133 | var input_area = $('<div/>').addClass('input_area'); | |
134 | this.code_mirror = CodeMirror(input_area.get(0), this.cm_config); |
|
134 | this.code_mirror = CodeMirror(input_area.get(0), this.cm_config); | |
135 | $(this.code_mirror.getInputField()).attr("spellcheck", "false"); |
|
135 | $(this.code_mirror.getInputField()).attr("spellcheck", "false"); | |
136 | inner_cell.append(input_area); |
|
136 | inner_cell.append(input_area); | |
137 | input.append(prompt).append(inner_cell); |
|
137 | input.append(prompt).append(inner_cell); | |
138 |
|
138 | |||
139 | var widget_area = $('<div/>') |
|
139 | var widget_area = $('<div/>') | |
140 | .addClass('widget-area') |
|
140 | .addClass('widget-area') | |
141 | .hide(); |
|
141 | .hide(); | |
142 | this.widget_area = widget_area; |
|
142 | this.widget_area = widget_area; | |
143 | var widget_prompt = $('<div/>') |
|
143 | var widget_prompt = $('<div/>') | |
144 | .addClass('prompt') |
|
144 | .addClass('prompt') | |
145 | .appendTo(widget_area); |
|
145 | .appendTo(widget_area); | |
146 | var widget_subarea = $('<div/>') |
|
146 | var widget_subarea = $('<div/>') | |
147 | .addClass('widget-subarea') |
|
147 | .addClass('widget-subarea') | |
148 | .appendTo(widget_area); |
|
148 | .appendTo(widget_area); | |
149 | this.widget_subarea = widget_subarea; |
|
149 | this.widget_subarea = widget_subarea; | |
150 | var widget_clear_buton = $('<button />') |
|
150 | var widget_clear_buton = $('<button />') | |
151 | .addClass('close') |
|
151 | .addClass('close') | |
152 | .html('×') |
|
152 | .html('×') | |
153 | .click(function() { |
|
153 | .click(function() { | |
154 | widget_area.slideUp('', function(){ widget_subarea.html(''); }); |
|
154 | widget_area.slideUp('', function(){ widget_subarea.html(''); }); | |
155 | }) |
|
155 | }) | |
156 | .appendTo(widget_prompt); |
|
156 | .appendTo(widget_prompt); | |
157 |
|
157 | |||
158 | var output = $('<div></div>'); |
|
158 | var output = $('<div></div>'); | |
159 | cell.append(input).append(widget_area).append(output); |
|
159 | cell.append(input).append(widget_area).append(output); | |
160 | this.element = cell; |
|
160 | this.element = cell; | |
161 | this.output_area = new IPython.OutputArea(output, true); |
|
161 | this.output_area = new IPython.OutputArea(output, true); | |
162 | this.completer = new IPython.Completer(this); |
|
162 | this.completer = new IPython.Completer(this); | |
163 | }; |
|
163 | }; | |
164 |
|
164 | |||
165 | /** @method bind_events */ |
|
165 | /** @method bind_events */ | |
166 | CodeCell.prototype.bind_events = function () { |
|
166 | CodeCell.prototype.bind_events = function () { | |
167 | IPython.Cell.prototype.bind_events.apply(this); |
|
167 | IPython.Cell.prototype.bind_events.apply(this); | |
168 | var that = this; |
|
168 | var that = this; | |
169 |
|
169 | |||
170 | this.element.focusout( |
|
170 | this.element.focusout( | |
171 | function() { that.auto_highlight(); } |
|
171 | function() { that.auto_highlight(); } | |
172 | ); |
|
172 | ); | |
173 | }; |
|
173 | }; | |
174 |
|
174 | |||
175 |
|
175 | |||
176 | /** |
|
176 | /** | |
177 | * This method gets called in CodeMirror's onKeyDown/onKeyPress |
|
177 | * This method gets called in CodeMirror's onKeyDown/onKeyPress | |
178 | * handlers and is used to provide custom key handling. Its return |
|
178 | * handlers and is used to provide custom key handling. Its return | |
179 | * value is used to determine if CodeMirror should ignore the event: |
|
179 | * value is used to determine if CodeMirror should ignore the event: | |
180 | * true = ignore, false = don't ignore. |
|
180 | * true = ignore, false = don't ignore. | |
181 | * @method handle_codemirror_keyevent |
|
181 | * @method handle_codemirror_keyevent | |
182 | */ |
|
182 | */ | |
183 | CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) { |
|
183 | CodeCell.prototype.handle_codemirror_keyevent = function (editor, event) { | |
184 |
|
184 | |||
185 | var that = this; |
|
185 | var that = this; | |
186 | // whatever key is pressed, first, cancel the tooltip request before |
|
186 | // whatever key is pressed, first, cancel the tooltip request before | |
187 | // they are sent, and remove tooltip if any, except for tab again |
|
187 | // they are sent, and remove tooltip if any, except for tab again | |
188 | var tooltip_closed = null; |
|
188 | var tooltip_closed = null; | |
189 | if (event.type === 'keydown' && event.which != keycodes.tab ) { |
|
189 | if (event.type === 'keydown' && event.which != keycodes.tab ) { | |
190 | tooltip_closed = IPython.tooltip.remove_and_cancel_tooltip(); |
|
190 | tooltip_closed = IPython.tooltip.remove_and_cancel_tooltip(); | |
191 | } |
|
191 | } | |
192 |
|
192 | |||
193 | var cur = editor.getCursor(); |
|
193 | var cur = editor.getCursor(); | |
194 | if (event.keyCode === keycodes.enter){ |
|
194 | if (event.keyCode === keycodes.enter){ | |
195 | this.auto_highlight(); |
|
195 | this.auto_highlight(); | |
196 | } |
|
196 | } | |
197 |
|
197 | |||
198 | if (event.which === keycodes.down && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) { |
|
198 | if (event.which === keycodes.down && event.type === 'keypress' && IPython.tooltip.time_before_tooltip >= 0) { | |
199 | // triger on keypress (!) otherwise inconsistent event.which depending on plateform |
|
199 | // triger on keypress (!) otherwise inconsistent event.which depending on plateform | |
200 | // browser and keyboard layout ! |
|
200 | // browser and keyboard layout ! | |
201 | // Pressing '(' , request tooltip, don't forget to reappend it |
|
201 | // Pressing '(' , request tooltip, don't forget to reappend it | |
202 | // The second argument says to hide the tooltip if the docstring |
|
202 | // The second argument says to hide the tooltip if the docstring | |
203 | // is actually empty |
|
203 | // is actually empty | |
204 | IPython.tooltip.pending(that, true); |
|
204 | IPython.tooltip.pending(that, true); | |
205 | } else if ( tooltip_closed && event.which === keycodes.esc && event.type === 'keydown') { |
|
205 | } else if ( tooltip_closed && event.which === keycodes.esc && event.type === 'keydown') { | |
206 | // If tooltip is active, cancel it. The call to |
|
206 | // If tooltip is active, cancel it. The call to | |
207 | // remove_and_cancel_tooltip above doesn't pass, force=true. |
|
207 | // remove_and_cancel_tooltip above doesn't pass, force=true. | |
208 | // Because of this it won't actually close the tooltip |
|
208 | // Because of this it won't actually close the tooltip | |
209 | // if it is in sticky mode. Thus, we have to check again if it is open |
|
209 | // if it is in sticky mode. Thus, we have to check again if it is open | |
210 | // and close it with force=true. |
|
210 | // and close it with force=true. | |
211 | if (!IPython.tooltip._hidden) { |
|
211 | if (!IPython.tooltip._hidden) { | |
212 | IPython.tooltip.remove_and_cancel_tooltip(true); |
|
212 | IPython.tooltip.remove_and_cancel_tooltip(true); | |
213 | } |
|
213 | } | |
214 | // If we closed the tooltip, don't let CM or the global handlers |
|
214 | // If we closed the tooltip, don't let CM or the global handlers | |
215 | // handle this event. |
|
215 | // handle this event. | |
216 | event.stop(); |
|
216 | event.stop(); | |
217 | return true; |
|
217 | return true; | |
218 | } else if (event.keyCode === keycodes.tab && event.type === 'keydown' && event.shiftKey) { |
|
218 | } else if (event.keyCode === keycodes.tab && event.type === 'keydown' && event.shiftKey) { | |
219 | if (editor.somethingSelected()){ |
|
219 | if (editor.somethingSelected()){ | |
220 | var anchor = editor.getCursor("anchor"); |
|
220 | var anchor = editor.getCursor("anchor"); | |
221 | var head = editor.getCursor("head"); |
|
221 | var head = editor.getCursor("head"); | |
222 | if( anchor.line != head.line){ |
|
222 | if( anchor.line != head.line){ | |
223 | return false; |
|
223 | return false; | |
224 | } |
|
224 | } | |
225 | } |
|
225 | } | |
226 | IPython.tooltip.request(that); |
|
226 | IPython.tooltip.request(that); | |
227 | event.stop(); |
|
227 | event.stop(); | |
228 | return true; |
|
228 | return true; | |
229 | } else if (event.keyCode === keycodes.tab && event.type == 'keydown') { |
|
229 | } else if (event.keyCode === keycodes.tab && event.type == 'keydown') { | |
230 | // Tab completion. |
|
230 | // Tab completion. | |
231 | IPython.tooltip.remove_and_cancel_tooltip(); |
|
231 | IPython.tooltip.remove_and_cancel_tooltip(); | |
232 | if (editor.somethingSelected()) { |
|
232 | if (editor.somethingSelected()) { | |
233 | return false; |
|
233 | return false; | |
234 | } |
|
234 | } | |
235 | var pre_cursor = editor.getRange({line:cur.line,ch:0},cur); |
|
235 | var pre_cursor = editor.getRange({line:cur.line,ch:0},cur); | |
236 | if (pre_cursor.trim() === "") { |
|
236 | if (pre_cursor.trim() === "") { | |
237 | // Don't autocomplete if the part of the line before the cursor |
|
237 | // Don't autocomplete if the part of the line before the cursor | |
238 | // is empty. In this case, let CodeMirror handle indentation. |
|
238 | // is empty. In this case, let CodeMirror handle indentation. | |
239 | return false; |
|
239 | return false; | |
240 | } else { |
|
240 | } else { | |
241 | event.stop(); |
|
241 | event.stop(); | |
242 | this.completer.startCompletion(); |
|
242 | this.completer.startCompletion(); | |
243 | return true; |
|
243 | return true; | |
244 | } |
|
244 | } | |
245 | } |
|
245 | } | |
246 |
|
246 | |||
247 | // keyboard event wasn't one of those unique to code cells, let's see |
|
247 | // keyboard event wasn't one of those unique to code cells, let's see | |
248 | // if it's one of the generic ones (i.e. check edit mode shortcuts) |
|
248 | // if it's one of the generic ones (i.e. check edit mode shortcuts) | |
249 | return IPython.Cell.prototype.handle_codemirror_keyevent.apply(this, [editor, event]); |
|
249 | return IPython.Cell.prototype.handle_codemirror_keyevent.apply(this, [editor, event]); | |
250 | }; |
|
250 | }; | |
251 |
|
251 | |||
252 | // Kernel related calls. |
|
252 | // Kernel related calls. | |
253 |
|
253 | |||
254 | CodeCell.prototype.set_kernel = function (kernel) { |
|
254 | CodeCell.prototype.set_kernel = function (kernel) { | |
255 | this.kernel = kernel; |
|
255 | this.kernel = kernel; | |
256 | }; |
|
256 | }; | |
257 |
|
257 | |||
258 | /** |
|
258 | /** | |
259 | * Execute current code cell to the kernel |
|
259 | * Execute current code cell to the kernel | |
260 | * @method execute |
|
260 | * @method execute | |
261 | */ |
|
261 | */ | |
262 | CodeCell.prototype.execute = function () { |
|
262 | CodeCell.prototype.execute = function () { | |
263 | this.output_area.clear_output(); |
|
263 | this.output_area.clear_output(); | |
264 |
|
264 | |||
265 | // Clear widget area |
|
265 | // Clear widget area | |
266 | this.widget_subarea.html(''); |
|
266 | this.widget_subarea.html(''); | |
267 | this.widget_subarea.height(''); |
|
267 | this.widget_subarea.height(''); | |
268 | this.widget_area.height(''); |
|
268 | this.widget_area.height(''); | |
269 | this.widget_area.hide(); |
|
269 | this.widget_area.hide(); | |
270 |
|
270 | |||
271 | this.set_input_prompt('*'); |
|
271 | this.set_input_prompt('*'); | |
272 | this.element.addClass("running"); |
|
272 | this.element.addClass("running"); | |
273 | if (this.last_msg_id) { |
|
273 | if (this.last_msg_id) { | |
274 | this.kernel.clear_callbacks_for_msg(this.last_msg_id); |
|
274 | this.kernel.clear_callbacks_for_msg(this.last_msg_id); | |
275 | } |
|
275 | } | |
276 | var callbacks = this.get_callbacks(); |
|
276 | var callbacks = this.get_callbacks(); | |
277 |
|
277 | |||
278 | var old_msg_id = this.last_msg_id; |
|
278 | var old_msg_id = this.last_msg_id; | |
279 | this.last_msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false, store_history: true}); |
|
279 | this.last_msg_id = this.kernel.execute(this.get_text(), callbacks, {silent: false, store_history: true}); | |
280 | if (old_msg_id) { |
|
280 | if (old_msg_id) { | |
281 | delete CodeCell.msg_cells[old_msg_id]; |
|
281 | delete CodeCell.msg_cells[old_msg_id]; | |
282 | } |
|
282 | } | |
283 | CodeCell.msg_cells[this.last_msg_id] = this; |
|
283 | CodeCell.msg_cells[this.last_msg_id] = this; | |
284 | }; |
|
284 | }; | |
285 |
|
285 | |||
286 | /** |
|
286 | /** | |
287 | * Construct the default callbacks for |
|
287 | * Construct the default callbacks for | |
288 | * @method get_callbacks |
|
288 | * @method get_callbacks | |
289 | */ |
|
289 | */ | |
290 | CodeCell.prototype.get_callbacks = function () { |
|
290 | CodeCell.prototype.get_callbacks = function () { | |
291 | return { |
|
291 | return { | |
292 | shell : { |
|
292 | shell : { | |
293 | reply : $.proxy(this._handle_execute_reply, this), |
|
293 | reply : $.proxy(this._handle_execute_reply, this), | |
294 | payload : { |
|
294 | payload : { | |
295 | set_next_input : $.proxy(this._handle_set_next_input, this), |
|
295 | set_next_input : $.proxy(this._handle_set_next_input, this), | |
296 | page : $.proxy(this._open_with_pager, this) |
|
296 | page : $.proxy(this._open_with_pager, this) | |
297 | } |
|
297 | } | |
298 | }, |
|
298 | }, | |
299 | iopub : { |
|
299 | iopub : { | |
300 | output : $.proxy(this.output_area.handle_output, this.output_area), |
|
300 | output : $.proxy(this.output_area.handle_output, this.output_area), | |
301 | clear_output : $.proxy(this.output_area.handle_clear_output, this.output_area), |
|
301 | clear_output : $.proxy(this.output_area.handle_clear_output, this.output_area), | |
302 | }, |
|
302 | }, | |
303 | input : $.proxy(this._handle_input_request, this) |
|
303 | input : $.proxy(this._handle_input_request, this) | |
304 | }; |
|
304 | }; | |
305 | }; |
|
305 | }; | |
306 |
|
306 | |||
307 | CodeCell.prototype._open_with_pager = function (payload) { |
|
307 | CodeCell.prototype._open_with_pager = function (payload) { | |
308 | $([IPython.events]).trigger('open_with_text.Pager', payload); |
|
308 | $([IPython.events]).trigger('open_with_text.Pager', payload); | |
309 | }; |
|
309 | }; | |
310 |
|
310 | |||
311 | /** |
|
311 | /** | |
312 | * @method _handle_execute_reply |
|
312 | * @method _handle_execute_reply | |
313 | * @private |
|
313 | * @private | |
314 | */ |
|
314 | */ | |
315 | CodeCell.prototype._handle_execute_reply = function (msg) { |
|
315 | CodeCell.prototype._handle_execute_reply = function (msg) { | |
316 | this.set_input_prompt(msg.content.execution_count); |
|
316 | this.set_input_prompt(msg.content.execution_count); | |
317 | this.element.removeClass("running"); |
|
317 | this.element.removeClass("running"); | |
318 | $([IPython.events]).trigger('set_dirty.Notebook', {value: true}); |
|
318 | $([IPython.events]).trigger('set_dirty.Notebook', {value: true}); | |
319 | }; |
|
319 | }; | |
320 |
|
320 | |||
321 | /** |
|
321 | /** | |
322 | * @method _handle_set_next_input |
|
322 | * @method _handle_set_next_input | |
323 | * @private |
|
323 | * @private | |
324 | */ |
|
324 | */ | |
325 | CodeCell.prototype._handle_set_next_input = function (payload) { |
|
325 | CodeCell.prototype._handle_set_next_input = function (payload) { | |
326 | var data = {'cell': this, 'text': payload.text}; |
|
326 | var data = {'cell': this, 'text': payload.text}; | |
327 | $([IPython.events]).trigger('set_next_input.Notebook', data); |
|
327 | $([IPython.events]).trigger('set_next_input.Notebook', data); | |
328 | }; |
|
328 | }; | |
329 |
|
329 | |||
330 | /** |
|
330 | /** | |
331 | * @method _handle_input_request |
|
331 | * @method _handle_input_request | |
332 | * @private |
|
332 | * @private | |
333 | */ |
|
333 | */ | |
334 | CodeCell.prototype._handle_input_request = function (msg) { |
|
334 | CodeCell.prototype._handle_input_request = function (msg) { | |
335 | this.output_area.append_raw_input(msg); |
|
335 | this.output_area.append_raw_input(msg); | |
336 | }; |
|
336 | }; | |
337 |
|
337 | |||
338 |
|
338 | |||
339 | // Basic cell manipulation. |
|
339 | // Basic cell manipulation. | |
340 |
|
340 | |||
341 | CodeCell.prototype.select = function () { |
|
341 | CodeCell.prototype.select = function () { | |
342 | var cont = IPython.Cell.prototype.select.apply(this); |
|
342 | var cont = IPython.Cell.prototype.select.apply(this); | |
343 | if (cont) { |
|
343 | if (cont) { | |
344 | this.code_mirror.refresh(); |
|
344 | this.code_mirror.refresh(); | |
345 | this.auto_highlight(); |
|
345 | this.auto_highlight(); | |
346 | } |
|
346 | } | |
347 | return cont; |
|
347 | return cont; | |
348 | }; |
|
348 | }; | |
349 |
|
349 | |||
350 | CodeCell.prototype.render = function () { |
|
350 | CodeCell.prototype.render = function () { | |
351 | var cont = IPython.Cell.prototype.render.apply(this); |
|
351 | var cont = IPython.Cell.prototype.render.apply(this); | |
352 | // Always execute, even if we are already in the rendered state |
|
352 | // Always execute, even if we are already in the rendered state | |
353 | return cont; |
|
353 | return cont; | |
354 | }; |
|
354 | }; | |
355 |
|
355 | |||
356 | CodeCell.prototype.unrender = function () { |
|
356 | CodeCell.prototype.unrender = function () { | |
357 | // CodeCell is always rendered |
|
357 | // CodeCell is always rendered | |
358 | return false; |
|
358 | return false; | |
359 | }; |
|
359 | }; | |
360 |
|
360 | |||
361 | /** |
|
|||
362 | * Determine whether or not the unfocus event should be aknowledged. |
|
|||
363 | * |
|
|||
364 | * @method should_cancel_blur |
|
|||
365 | * |
|
|||
366 | * @return results {bool} Whether or not to ignore the cell's blur event. |
|
|||
367 | **/ |
|
|||
368 | CodeCell.prototype.should_cancel_blur = function () { |
|
|||
369 | // Cancel this unfocus event if the base wants to cancel or the cell |
|
|||
370 | // completer is open or the tooltip is open. |
|
|||
371 | return IPython.Cell.prototype.should_cancel_blur.apply(this) || |
|
|||
372 | (this.completer && this.completer.is_visible()) || |
|
|||
373 | (IPython.tooltip && IPython.tooltip.is_visible()); |
|
|||
374 | }; |
|
|||
375 |
|
||||
376 | CodeCell.prototype.select_all = function () { |
|
361 | CodeCell.prototype.select_all = function () { | |
377 | var start = {line: 0, ch: 0}; |
|
362 | var start = {line: 0, ch: 0}; | |
378 | var nlines = this.code_mirror.lineCount(); |
|
363 | var nlines = this.code_mirror.lineCount(); | |
379 | var last_line = this.code_mirror.getLine(nlines-1); |
|
364 | var last_line = this.code_mirror.getLine(nlines-1); | |
380 | var end = {line: nlines-1, ch: last_line.length}; |
|
365 | var end = {line: nlines-1, ch: last_line.length}; | |
381 | this.code_mirror.setSelection(start, end); |
|
366 | this.code_mirror.setSelection(start, end); | |
382 | }; |
|
367 | }; | |
383 |
|
368 | |||
384 |
|
369 | |||
385 | CodeCell.prototype.collapse_output = function () { |
|
370 | CodeCell.prototype.collapse_output = function () { | |
386 | this.collapsed = true; |
|
371 | this.collapsed = true; | |
387 | this.output_area.collapse(); |
|
372 | this.output_area.collapse(); | |
388 | }; |
|
373 | }; | |
389 |
|
374 | |||
390 |
|
375 | |||
391 | CodeCell.prototype.expand_output = function () { |
|
376 | CodeCell.prototype.expand_output = function () { | |
392 | this.collapsed = false; |
|
377 | this.collapsed = false; | |
393 | this.output_area.expand(); |
|
378 | this.output_area.expand(); | |
394 | this.output_area.unscroll_area(); |
|
379 | this.output_area.unscroll_area(); | |
395 | }; |
|
380 | }; | |
396 |
|
381 | |||
397 | CodeCell.prototype.scroll_output = function () { |
|
382 | CodeCell.prototype.scroll_output = function () { | |
398 | this.output_area.expand(); |
|
383 | this.output_area.expand(); | |
399 | this.output_area.scroll_if_long(); |
|
384 | this.output_area.scroll_if_long(); | |
400 | }; |
|
385 | }; | |
401 |
|
386 | |||
402 | CodeCell.prototype.toggle_output = function () { |
|
387 | CodeCell.prototype.toggle_output = function () { | |
403 | this.collapsed = Boolean(1 - this.collapsed); |
|
388 | this.collapsed = Boolean(1 - this.collapsed); | |
404 | this.output_area.toggle_output(); |
|
389 | this.output_area.toggle_output(); | |
405 | }; |
|
390 | }; | |
406 |
|
391 | |||
407 | CodeCell.prototype.toggle_output_scroll = function () { |
|
392 | CodeCell.prototype.toggle_output_scroll = function () { | |
408 | this.output_area.toggle_scroll(); |
|
393 | this.output_area.toggle_scroll(); | |
409 | }; |
|
394 | }; | |
410 |
|
395 | |||
411 |
|
396 | |||
412 | CodeCell.input_prompt_classical = function (prompt_value, lines_number) { |
|
397 | CodeCell.input_prompt_classical = function (prompt_value, lines_number) { | |
413 | var ns; |
|
398 | var ns; | |
414 | if (prompt_value === undefined) { |
|
399 | if (prompt_value === undefined) { | |
415 | ns = " "; |
|
400 | ns = " "; | |
416 | } else { |
|
401 | } else { | |
417 | ns = encodeURIComponent(prompt_value); |
|
402 | ns = encodeURIComponent(prompt_value); | |
418 | } |
|
403 | } | |
419 | return 'In [' + ns + ']:'; |
|
404 | return 'In [' + ns + ']:'; | |
420 | }; |
|
405 | }; | |
421 |
|
406 | |||
422 | CodeCell.input_prompt_continuation = function (prompt_value, lines_number) { |
|
407 | CodeCell.input_prompt_continuation = function (prompt_value, lines_number) { | |
423 | var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)]; |
|
408 | var html = [CodeCell.input_prompt_classical(prompt_value, lines_number)]; | |
424 | for(var i=1; i < lines_number; i++) { |
|
409 | for(var i=1; i < lines_number; i++) { | |
425 | html.push(['...:']); |
|
410 | html.push(['...:']); | |
426 | } |
|
411 | } | |
427 | return html.join('<br/>'); |
|
412 | return html.join('<br/>'); | |
428 | }; |
|
413 | }; | |
429 |
|
414 | |||
430 | CodeCell.input_prompt_function = CodeCell.input_prompt_classical; |
|
415 | CodeCell.input_prompt_function = CodeCell.input_prompt_classical; | |
431 |
|
416 | |||
432 |
|
417 | |||
433 | CodeCell.prototype.set_input_prompt = function (number) { |
|
418 | CodeCell.prototype.set_input_prompt = function (number) { | |
434 | var nline = 1; |
|
419 | var nline = 1; | |
435 | if (this.code_mirror !== undefined) { |
|
420 | if (this.code_mirror !== undefined) { | |
436 | nline = this.code_mirror.lineCount(); |
|
421 | nline = this.code_mirror.lineCount(); | |
437 | } |
|
422 | } | |
438 | this.input_prompt_number = number; |
|
423 | this.input_prompt_number = number; | |
439 | var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline); |
|
424 | var prompt_html = CodeCell.input_prompt_function(this.input_prompt_number, nline); | |
440 | // This HTML call is okay because the user contents are escaped. |
|
425 | // This HTML call is okay because the user contents are escaped. | |
441 | this.element.find('div.input_prompt').html(prompt_html); |
|
426 | this.element.find('div.input_prompt').html(prompt_html); | |
442 | }; |
|
427 | }; | |
443 |
|
428 | |||
444 |
|
429 | |||
445 | CodeCell.prototype.clear_input = function () { |
|
430 | CodeCell.prototype.clear_input = function () { | |
446 | this.code_mirror.setValue(''); |
|
431 | this.code_mirror.setValue(''); | |
447 | }; |
|
432 | }; | |
448 |
|
433 | |||
449 |
|
434 | |||
450 | CodeCell.prototype.get_text = function () { |
|
435 | CodeCell.prototype.get_text = function () { | |
451 | return this.code_mirror.getValue(); |
|
436 | return this.code_mirror.getValue(); | |
452 | }; |
|
437 | }; | |
453 |
|
438 | |||
454 |
|
439 | |||
455 | CodeCell.prototype.set_text = function (code) { |
|
440 | CodeCell.prototype.set_text = function (code) { | |
456 | return this.code_mirror.setValue(code); |
|
441 | return this.code_mirror.setValue(code); | |
457 | }; |
|
442 | }; | |
458 |
|
443 | |||
459 |
|
444 | |||
460 | CodeCell.prototype.clear_output = function (wait) { |
|
445 | CodeCell.prototype.clear_output = function (wait) { | |
461 | this.output_area.clear_output(wait); |
|
446 | this.output_area.clear_output(wait); | |
462 | this.set_input_prompt(); |
|
447 | this.set_input_prompt(); | |
463 | }; |
|
448 | }; | |
464 |
|
449 | |||
465 |
|
450 | |||
466 | // JSON serialization |
|
451 | // JSON serialization | |
467 |
|
452 | |||
468 | CodeCell.prototype.fromJSON = function (data) { |
|
453 | CodeCell.prototype.fromJSON = function (data) { | |
469 | IPython.Cell.prototype.fromJSON.apply(this, arguments); |
|
454 | IPython.Cell.prototype.fromJSON.apply(this, arguments); | |
470 | if (data.cell_type === 'code') { |
|
455 | if (data.cell_type === 'code') { | |
471 | if (data.input !== undefined) { |
|
456 | if (data.input !== undefined) { | |
472 | this.set_text(data.input); |
|
457 | this.set_text(data.input); | |
473 | // make this value the starting point, so that we can only undo |
|
458 | // make this value the starting point, so that we can only undo | |
474 | // to this state, instead of a blank cell |
|
459 | // to this state, instead of a blank cell | |
475 | this.code_mirror.clearHistory(); |
|
460 | this.code_mirror.clearHistory(); | |
476 | this.auto_highlight(); |
|
461 | this.auto_highlight(); | |
477 | } |
|
462 | } | |
478 | if (data.prompt_number !== undefined) { |
|
463 | if (data.prompt_number !== undefined) { | |
479 | this.set_input_prompt(data.prompt_number); |
|
464 | this.set_input_prompt(data.prompt_number); | |
480 | } else { |
|
465 | } else { | |
481 | this.set_input_prompt(); |
|
466 | this.set_input_prompt(); | |
482 | } |
|
467 | } | |
483 | this.output_area.trusted = data.trusted || false; |
|
468 | this.output_area.trusted = data.trusted || false; | |
484 | this.output_area.fromJSON(data.outputs); |
|
469 | this.output_area.fromJSON(data.outputs); | |
485 | if (data.collapsed !== undefined) { |
|
470 | if (data.collapsed !== undefined) { | |
486 | if (data.collapsed) { |
|
471 | if (data.collapsed) { | |
487 | this.collapse_output(); |
|
472 | this.collapse_output(); | |
488 | } else { |
|
473 | } else { | |
489 | this.expand_output(); |
|
474 | this.expand_output(); | |
490 | } |
|
475 | } | |
491 | } |
|
476 | } | |
492 | } |
|
477 | } | |
493 | }; |
|
478 | }; | |
494 |
|
479 | |||
495 |
|
480 | |||
496 | CodeCell.prototype.toJSON = function () { |
|
481 | CodeCell.prototype.toJSON = function () { | |
497 | var data = IPython.Cell.prototype.toJSON.apply(this); |
|
482 | var data = IPython.Cell.prototype.toJSON.apply(this); | |
498 | data.input = this.get_text(); |
|
483 | data.input = this.get_text(); | |
499 | // is finite protect against undefined and '*' value |
|
484 | // is finite protect against undefined and '*' value | |
500 | if (isFinite(this.input_prompt_number)) { |
|
485 | if (isFinite(this.input_prompt_number)) { | |
501 | data.prompt_number = this.input_prompt_number; |
|
486 | data.prompt_number = this.input_prompt_number; | |
502 | } |
|
487 | } | |
503 | var outputs = this.output_area.toJSON(); |
|
488 | var outputs = this.output_area.toJSON(); | |
504 | data.outputs = outputs; |
|
489 | data.outputs = outputs; | |
505 | data.language = 'python'; |
|
490 | data.language = 'python'; | |
506 | data.trusted = this.output_area.trusted; |
|
491 | data.trusted = this.output_area.trusted; | |
507 | data.collapsed = this.collapsed; |
|
492 | data.collapsed = this.collapsed; | |
508 | return data; |
|
493 | return data; | |
509 | }; |
|
494 | }; | |
510 |
|
495 | |||
|
496 | /** | |||
|
497 | * handle cell level logic when a cell is unselected | |||
|
498 | * @method unselect | |||
|
499 | * @return is the action being taken | |||
|
500 | */ | |||
|
501 | CodeCell.prototype.unselect = function () { | |||
|
502 | var cont = IPython.Cell.prototype.unselect.apply(this); | |||
|
503 | if (cont) { | |||
|
504 | // When a code cell is usnelected, make sure that the corresponding | |||
|
505 | // tooltip and completer to that cell is closed. | |||
|
506 | IPython.tooltip.remove_and_cancel_tooltip(true); | |||
|
507 | if (this.completer !== null) { | |||
|
508 | this.completer.close(); | |||
|
509 | } | |||
|
510 | } | |||
|
511 | return cont; | |||
|
512 | }; | |||
511 |
|
513 | |||
512 | IPython.CodeCell = CodeCell; |
|
514 | IPython.CodeCell = CodeCell; | |
513 |
|
515 | |||
514 | return IPython; |
|
516 | return IPython; | |
515 | }(IPython)); |
|
517 | }(IPython)); |
@@ -1,384 +1,369 b'' | |||||
1 | // function completer. |
|
1 | // function completer. | |
2 | // |
|
2 | // | |
3 | // completer should be a class that takes an cell instance |
|
3 | // completer should be a class that takes an cell instance | |
4 | var IPython = (function (IPython) { |
|
4 | var IPython = (function (IPython) { | |
5 | // that will prevent us from misspelling |
|
5 | // that will prevent us from misspelling | |
6 | "use strict"; |
|
6 | "use strict"; | |
7 |
|
7 | |||
8 | // easier key mapping |
|
8 | // easier key mapping | |
9 | var keycodes = IPython.keyboard.keycodes; |
|
9 | var keycodes = IPython.keyboard.keycodes; | |
10 |
|
10 | |||
11 | function prepend_n_prc(str, n) { |
|
11 | function prepend_n_prc(str, n) { | |
12 | for( var i =0 ; i< n ; i++){ |
|
12 | for( var i =0 ; i< n ; i++){ | |
13 | str = '%'+str ; |
|
13 | str = '%'+str ; | |
14 | } |
|
14 | } | |
15 | return str; |
|
15 | return str; | |
16 | } |
|
16 | } | |
17 |
|
17 | |||
18 | function _existing_completion(item, completion_array){ |
|
18 | function _existing_completion(item, completion_array){ | |
19 | for( var c in completion_array ) { |
|
19 | for( var c in completion_array ) { | |
20 | if(completion_array[c].trim().substr(-item.length) == item) |
|
20 | if(completion_array[c].trim().substr(-item.length) == item) | |
21 | { return true; } |
|
21 | { return true; } | |
22 | } |
|
22 | } | |
23 | return false; |
|
23 | return false; | |
24 | } |
|
24 | } | |
25 |
|
25 | |||
26 | // what is the common start of all completions |
|
26 | // what is the common start of all completions | |
27 | function shared_start(B, drop_prct) { |
|
27 | function shared_start(B, drop_prct) { | |
28 | if (B.length == 1) { |
|
28 | if (B.length == 1) { | |
29 | return B[0]; |
|
29 | return B[0]; | |
30 | } |
|
30 | } | |
31 | var A = []; |
|
31 | var A = []; | |
32 | var common; |
|
32 | var common; | |
33 | var min_lead_prct = 10; |
|
33 | var min_lead_prct = 10; | |
34 | for (var i = 0; i < B.length; i++) { |
|
34 | for (var i = 0; i < B.length; i++) { | |
35 | var str = B[i].str; |
|
35 | var str = B[i].str; | |
36 | var localmin = 0; |
|
36 | var localmin = 0; | |
37 | if(drop_prct === true){ |
|
37 | if(drop_prct === true){ | |
38 | while ( str.substr(0, 1) == '%') { |
|
38 | while ( str.substr(0, 1) == '%') { | |
39 | localmin = localmin+1; |
|
39 | localmin = localmin+1; | |
40 | str = str.substring(1); |
|
40 | str = str.substring(1); | |
41 | } |
|
41 | } | |
42 | } |
|
42 | } | |
43 | min_lead_prct = Math.min(min_lead_prct, localmin); |
|
43 | min_lead_prct = Math.min(min_lead_prct, localmin); | |
44 | A.push(str); |
|
44 | A.push(str); | |
45 | } |
|
45 | } | |
46 |
|
46 | |||
47 | if (A.length > 1) { |
|
47 | if (A.length > 1) { | |
48 | var tem1, tem2, s; |
|
48 | var tem1, tem2, s; | |
49 | A = A.slice(0).sort(); |
|
49 | A = A.slice(0).sort(); | |
50 | tem1 = A[0]; |
|
50 | tem1 = A[0]; | |
51 | s = tem1.length; |
|
51 | s = tem1.length; | |
52 | tem2 = A.pop(); |
|
52 | tem2 = A.pop(); | |
53 | while (s && tem2.indexOf(tem1) == -1) { |
|
53 | while (s && tem2.indexOf(tem1) == -1) { | |
54 | tem1 = tem1.substring(0, --s); |
|
54 | tem1 = tem1.substring(0, --s); | |
55 | } |
|
55 | } | |
56 | if (tem1 === "" || tem2.indexOf(tem1) !== 0) { |
|
56 | if (tem1 === "" || tem2.indexOf(tem1) !== 0) { | |
57 | return { |
|
57 | return { | |
58 | str:prepend_n_prc('', min_lead_prct), |
|
58 | str:prepend_n_prc('', min_lead_prct), | |
59 | type: "computed", |
|
59 | type: "computed", | |
60 | from: B[0].from, |
|
60 | from: B[0].from, | |
61 | to: B[0].to |
|
61 | to: B[0].to | |
62 | }; |
|
62 | }; | |
63 | } |
|
63 | } | |
64 | return { |
|
64 | return { | |
65 | str: prepend_n_prc(tem1, min_lead_prct), |
|
65 | str: prepend_n_prc(tem1, min_lead_prct), | |
66 | type: "computed", |
|
66 | type: "computed", | |
67 | from: B[0].from, |
|
67 | from: B[0].from, | |
68 | to: B[0].to |
|
68 | to: B[0].to | |
69 | }; |
|
69 | }; | |
70 | } |
|
70 | } | |
71 | return null; |
|
71 | return null; | |
72 | } |
|
72 | } | |
73 |
|
73 | |||
74 |
|
74 | |||
75 | var Completer = function (cell) { |
|
75 | var Completer = function (cell) { | |
76 | this._visible = false; |
|
|||
77 | this.cell = cell; |
|
76 | this.cell = cell; | |
78 | this.editor = cell.code_mirror; |
|
77 | this.editor = cell.code_mirror; | |
79 | var that = this; |
|
78 | var that = this; | |
80 | $([IPython.events]).on('status_busy.Kernel', function () { |
|
79 | $([IPython.events]).on('status_busy.Kernel', function () { | |
81 | that.skip_kernel_completion = true; |
|
80 | that.skip_kernel_completion = true; | |
82 | }); |
|
81 | }); | |
83 | $([IPython.events]).on('status_idle.Kernel', function () { |
|
82 | $([IPython.events]).on('status_idle.Kernel', function () { | |
84 | that.skip_kernel_completion = false; |
|
83 | that.skip_kernel_completion = false; | |
85 | }); |
|
84 | }); | |
86 | }; |
|
85 | }; | |
87 |
|
86 | |||
88 | Completer.prototype.is_visible = function () { |
|
|||
89 | // Return whether or not the completer is visible. |
|
|||
90 | return this._visible; |
|
|||
91 | }; |
|
|||
92 |
|
||||
93 | Completer.prototype.startCompletion = function () { |
|
87 | Completer.prototype.startCompletion = function () { | |
94 | // call for a 'first' completion, that will set the editor and do some |
|
88 | // call for a 'first' completion, that will set the editor and do some | |
95 |
// special behavio |
|
89 | // special behavior like autopicking if only one completion available. | |
96 | // |
|
|||
97 | if (this.editor.somethingSelected()) return; |
|
90 | if (this.editor.somethingSelected()) return; | |
98 | this.done = false; |
|
91 | this.done = false; | |
99 | // use to get focus back on opera |
|
92 | // use to get focus back on opera | |
100 | this.carry_on_completion(true); |
|
93 | this.carry_on_completion(true); | |
101 | }; |
|
94 | }; | |
102 |
|
95 | |||
103 |
|
96 | |||
104 | // easy access for julia to monkeypatch |
|
97 | // easy access for julia to monkeypatch | |
105 | // |
|
98 | // | |
106 | Completer.reinvoke_re = /[%0-9a-z._/\\:~-]/i; |
|
99 | Completer.reinvoke_re = /[%0-9a-z._/\\:~-]/i; | |
107 |
|
100 | |||
108 | Completer.prototype.reinvoke= function(pre_cursor, block, cursor){ |
|
101 | Completer.prototype.reinvoke= function(pre_cursor, block, cursor){ | |
109 | return Completer.reinvoke_re.test(pre_cursor); |
|
102 | return Completer.reinvoke_re.test(pre_cursor); | |
110 | }; |
|
103 | }; | |
111 |
|
104 | |||
112 | /** |
|
105 | /** | |
113 | * |
|
106 | * | |
114 | * pass true as parameter if this is the first invocation of the completer |
|
107 | * pass true as parameter if this is the first invocation of the completer | |
115 | * this will prevent the completer to dissmiss itself if it is not on a |
|
108 | * this will prevent the completer to dissmiss itself if it is not on a | |
116 | * word boundary like pressing tab after a space, and make it autopick the |
|
109 | * word boundary like pressing tab after a space, and make it autopick the | |
117 | * only choice if there is only one which prevent from popping the UI. as |
|
110 | * only choice if there is only one which prevent from popping the UI. as | |
118 | * well as fast-forwarding the typing if all completion have a common |
|
111 | * well as fast-forwarding the typing if all completion have a common | |
119 | * shared start |
|
112 | * shared start | |
120 | **/ |
|
113 | **/ | |
121 | Completer.prototype.carry_on_completion = function (first_invocation) { |
|
114 | Completer.prototype.carry_on_completion = function (first_invocation) { | |
122 | // Pass true as parameter if you want the completer to autopick when |
|
115 | // Pass true as parameter if you want the completer to autopick when | |
123 | // only one completion. This function is automatically reinvoked at |
|
116 | // only one completion. This function is automatically reinvoked at | |
124 | // each keystroke with first_invocation = false |
|
117 | // each keystroke with first_invocation = false | |
125 | var cur = this.editor.getCursor(); |
|
118 | var cur = this.editor.getCursor(); | |
126 | var line = this.editor.getLine(cur.line); |
|
119 | var line = this.editor.getLine(cur.line); | |
127 | var pre_cursor = this.editor.getRange({ |
|
120 | var pre_cursor = this.editor.getRange({ | |
128 | line: cur.line, |
|
121 | line: cur.line, | |
129 | ch: cur.ch - 1 |
|
122 | ch: cur.ch - 1 | |
130 | }, cur); |
|
123 | }, cur); | |
131 |
|
124 | |||
132 | // we need to check that we are still on a word boundary |
|
125 | // we need to check that we are still on a word boundary | |
133 | // because while typing the completer is still reinvoking itself |
|
126 | // because while typing the completer is still reinvoking itself | |
134 | // so dismiss if we are on a "bad" caracter |
|
127 | // so dismiss if we are on a "bad" caracter | |
135 | if (!this.reinvoke(pre_cursor) && !first_invocation) { |
|
128 | if (!this.reinvoke(pre_cursor) && !first_invocation) { | |
136 | this.close(); |
|
129 | this.close(); | |
137 | return; |
|
130 | return; | |
138 | } |
|
131 | } | |
139 |
|
132 | |||
140 | this.autopick = false; |
|
133 | this.autopick = false; | |
141 | if (first_invocation) { |
|
134 | if (first_invocation) { | |
142 | this.autopick = true; |
|
135 | this.autopick = true; | |
143 | } |
|
136 | } | |
144 |
|
137 | |||
145 | // We want a single cursor position. |
|
138 | // We want a single cursor position. | |
146 | if (this.editor.somethingSelected()) { |
|
139 | if (this.editor.somethingSelected()) { | |
147 | return; |
|
140 | return; | |
148 | } |
|
141 | } | |
149 |
|
142 | |||
150 | // one kernel completion came back, finish_completing will be called with the results |
|
143 | // one kernel completion came back, finish_completing will be called with the results | |
151 | // we fork here and directly call finish completing if kernel is busy |
|
144 | // we fork here and directly call finish completing if kernel is busy | |
152 | if (this.skip_kernel_completion) { |
|
145 | if (this.skip_kernel_completion) { | |
153 | this.finish_completing({ |
|
146 | this.finish_completing({ | |
154 | 'matches': [], |
|
147 | 'matches': [], | |
155 | matched_text: "" |
|
148 | matched_text: "" | |
156 | }); |
|
149 | }); | |
157 | } else { |
|
150 | } else { | |
158 | this.cell.kernel.complete(line, cur.ch, $.proxy(this.finish_completing, this)); |
|
151 | this.cell.kernel.complete(line, cur.ch, $.proxy(this.finish_completing, this)); | |
159 | } |
|
152 | } | |
160 | }; |
|
153 | }; | |
161 |
|
154 | |||
162 | Completer.prototype.finish_completing = function (msg) { |
|
155 | Completer.prototype.finish_completing = function (msg) { | |
163 | // let's build a function that wrap all that stuff into what is needed |
|
156 | // let's build a function that wrap all that stuff into what is needed | |
164 | // for the new completer: |
|
157 | // for the new completer: | |
165 | var content = msg.content; |
|
158 | var content = msg.content; | |
166 | var matched_text = content.matched_text; |
|
159 | var matched_text = content.matched_text; | |
167 | var matches = content.matches; |
|
160 | var matches = content.matches; | |
168 |
|
161 | |||
169 | var cur = this.editor.getCursor(); |
|
162 | var cur = this.editor.getCursor(); | |
170 | var results = CodeMirror.contextHint(this.editor); |
|
163 | var results = CodeMirror.contextHint(this.editor); | |
171 | var filtered_results = []; |
|
164 | var filtered_results = []; | |
172 | //remove results from context completion |
|
165 | //remove results from context completion | |
173 | //that are already in kernel completion |
|
166 | //that are already in kernel completion | |
174 | for (var elm in results) { |
|
167 | for (var elm in results) { | |
175 | if (!_existing_completion(results[elm].str, matches)) { |
|
168 | if (!_existing_completion(results[elm].str, matches)) { | |
176 | filtered_results.push(results[elm]); |
|
169 | filtered_results.push(results[elm]); | |
177 | } |
|
170 | } | |
178 | } |
|
171 | } | |
179 |
|
172 | |||
180 | // append the introspection result, in order, at at the beginning of |
|
173 | // append the introspection result, in order, at at the beginning of | |
181 | // the table and compute the replacement range from current cursor |
|
174 | // the table and compute the replacement range from current cursor | |
182 | // positon and matched_text length. |
|
175 | // positon and matched_text length. | |
183 | for (var i = matches.length - 1; i >= 0; --i) { |
|
176 | for (var i = matches.length - 1; i >= 0; --i) { | |
184 | filtered_results.unshift({ |
|
177 | filtered_results.unshift({ | |
185 | str: matches[i], |
|
178 | str: matches[i], | |
186 | type: "introspection", |
|
179 | type: "introspection", | |
187 | from: { |
|
180 | from: { | |
188 | line: cur.line, |
|
181 | line: cur.line, | |
189 | ch: cur.ch - matched_text.length |
|
182 | ch: cur.ch - matched_text.length | |
190 | }, |
|
183 | }, | |
191 | to: { |
|
184 | to: { | |
192 | line: cur.line, |
|
185 | line: cur.line, | |
193 | ch: cur.ch |
|
186 | ch: cur.ch | |
194 | } |
|
187 | } | |
195 | }); |
|
188 | }); | |
196 | } |
|
189 | } | |
197 |
|
190 | |||
198 | // one the 2 sources results have been merge, deal with it |
|
191 | // one the 2 sources results have been merge, deal with it | |
199 | this.raw_result = filtered_results; |
|
192 | this.raw_result = filtered_results; | |
200 |
|
193 | |||
201 | // if empty result return |
|
194 | // if empty result return | |
202 | if (!this.raw_result || !this.raw_result.length) return; |
|
195 | if (!this.raw_result || !this.raw_result.length) return; | |
203 |
|
196 | |||
204 | // When there is only one completion, use it directly. |
|
197 | // When there is only one completion, use it directly. | |
205 | if (this.autopick && this.raw_result.length == 1) { |
|
198 | if (this.autopick && this.raw_result.length == 1) { | |
206 | this.insert(this.raw_result[0]); |
|
199 | this.insert(this.raw_result[0]); | |
207 | return; |
|
200 | return; | |
208 | } |
|
201 | } | |
209 |
|
202 | |||
210 | if (this.raw_result.length == 1) { |
|
203 | if (this.raw_result.length == 1) { | |
211 | // test if first and only completion totally matches |
|
204 | // test if first and only completion totally matches | |
212 | // what is typed, in this case dismiss |
|
205 | // what is typed, in this case dismiss | |
213 | var str = this.raw_result[0].str; |
|
206 | var str = this.raw_result[0].str; | |
214 | var pre_cursor = this.editor.getRange({ |
|
207 | var pre_cursor = this.editor.getRange({ | |
215 | line: cur.line, |
|
208 | line: cur.line, | |
216 | ch: cur.ch - str.length |
|
209 | ch: cur.ch - str.length | |
217 | }, cur); |
|
210 | }, cur); | |
218 | if (pre_cursor == str) { |
|
211 | if (pre_cursor == str) { | |
219 | this.close(); |
|
212 | this.close(); | |
220 | return; |
|
213 | return; | |
221 | } |
|
214 | } | |
222 | } |
|
215 | } | |
223 |
|
216 | |||
224 | this.complete = $('<div/>').addClass('completions'); |
|
217 | if (!this.visible) { | |
225 |
this.complete.a |
|
218 | this.complete = $('<div/>').addClass('completions'); | |
226 |
|
219 | this.complete.attr('id', 'complete'); | ||
227 | // Currently webkit doesn't use the size attr correctly. See: |
|
220 | ||
228 | // https://code.google.com/p/chromium/issues/detail?id=4579 |
|
221 | // Currently webkit doesn't use the size attr correctly. See: | |
229 | this.sel = $('<select style="width: auto"/>') |
|
222 | // https://code.google.com/p/chromium/issues/detail?id=4579 | |
230 | .attr('multiple', 'true') |
|
223 | this.sel = $('<select/>') | |
231 | .attr('size', Math.min(10, this.raw_result.length)); |
|
224 | .attr('tabindex', -1) | |
232 | this.complete.append(this.sel); |
|
225 | .attr('multiple', 'true'); | |
233 | this._visible = true; |
|
226 | this.complete.append(this.sel); | |
234 | $('body').append(this.complete); |
|
227 | this.visible = true; | |
|
228 | $('body').append(this.complete); | |||
|
229 | ||||
|
230 | //build the container | |||
|
231 | var that = this; | |||
|
232 | this.sel.dblclick(function () { | |||
|
233 | that.pick(); | |||
|
234 | }); | |||
|
235 | this.sel.focus(function () { | |||
|
236 | that.editor.focus(); | |||
|
237 | }); | |||
|
238 | this._handle_keydown = function (cm, event) { | |||
|
239 | that.keydown(event); | |||
|
240 | }; | |||
|
241 | this.editor.on('keydown', this._handle_keydown); | |||
|
242 | this._handle_keypress = function (cm, event) { | |||
|
243 | that.keypress(event); | |||
|
244 | }; | |||
|
245 | this.editor.on('keypress', this._handle_keypress); | |||
|
246 | } | |||
|
247 | this.sel.attr('size', Math.min(10, this.raw_result.length)); | |||
235 |
|
248 | |||
236 | // After everything is on the page, compute the postion. |
|
249 | // After everything is on the page, compute the postion. | |
237 | // We put it above the code if it is too close to the bottom of the page. |
|
250 | // We put it above the code if it is too close to the bottom of the page. | |
238 | cur.ch = cur.ch-matched_text.length; |
|
251 | cur.ch = cur.ch-matched_text.length; | |
239 | var pos = this.editor.cursorCoords(cur); |
|
252 | var pos = this.editor.cursorCoords(cur); | |
240 | var left = pos.left-3; |
|
253 | var left = pos.left-3; | |
241 | var top; |
|
254 | var top; | |
242 | var cheight = this.complete.height(); |
|
255 | var cheight = this.complete.height(); | |
243 | var wheight = $(window).height(); |
|
256 | var wheight = $(window).height(); | |
244 | if (pos.bottom+cheight+5 > wheight) { |
|
257 | if (pos.bottom+cheight+5 > wheight) { | |
245 | top = pos.top-cheight-4; |
|
258 | top = pos.top-cheight-4; | |
246 | } else { |
|
259 | } else { | |
247 | top = pos.bottom+1; |
|
260 | top = pos.bottom+1; | |
248 | } |
|
261 | } | |
249 | this.complete.css('left', left + 'px'); |
|
262 | this.complete.css('left', left + 'px'); | |
250 | this.complete.css('top', top + 'px'); |
|
263 | this.complete.css('top', top + 'px'); | |
251 |
|
264 | |||
252 |
|
265 | // Clear and fill the list. | ||
253 | //build the container |
|
266 | this.sel.text(''); | |
254 | var that = this; |
|
|||
255 | this.sel.dblclick(function () { |
|
|||
256 | that.pick(); |
|
|||
257 | }); |
|
|||
258 | this.sel.blur(this.close); |
|
|||
259 | this.sel.keydown(function (event) { |
|
|||
260 | that.keydown(event); |
|
|||
261 | }); |
|
|||
262 | this.sel.keypress(function (event) { |
|
|||
263 | that.keypress(event); |
|
|||
264 | }); |
|
|||
265 |
|
||||
266 | this.build_gui_list(this.raw_result); |
|
267 | this.build_gui_list(this.raw_result); | |
267 |
|
||||
268 | this.sel.focus(); |
|
|||
269 | IPython.keyboard_manager.disable(); |
|
|||
270 | // Opera sometimes ignores focusing a freshly created node |
|
|||
271 | if (window.opera) setTimeout(function () { |
|
|||
272 | if (!this.done) this.sel.focus(); |
|
|||
273 | }, 100); |
|
|||
274 | return true; |
|
268 | return true; | |
275 | }; |
|
269 | }; | |
276 |
|
270 | |||
277 | Completer.prototype.insert = function (completion) { |
|
271 | Completer.prototype.insert = function (completion) { | |
278 | this.editor.replaceRange(completion.str, completion.from, completion.to); |
|
272 | this.editor.replaceRange(completion.str, completion.from, completion.to); | |
279 | }; |
|
273 | }; | |
280 |
|
274 | |||
281 | Completer.prototype.build_gui_list = function (completions) { |
|
275 | Completer.prototype.build_gui_list = function (completions) { | |
282 | for (var i = 0; i < completions.length; ++i) { |
|
276 | for (var i = 0; i < completions.length; ++i) { | |
283 | var opt = $('<option/>').text(completions[i].str).addClass(completions[i].type); |
|
277 | var opt = $('<option/>').text(completions[i].str).addClass(completions[i].type); | |
284 | this.sel.append(opt); |
|
278 | this.sel.append(opt); | |
285 | } |
|
279 | } | |
286 | this.sel.children().first().attr('selected', 'true'); |
|
280 | this.sel.children().first().attr('selected', 'true'); | |
287 | this.sel.scrollTop(0); |
|
281 | this.sel.scrollTop(0); | |
288 | }; |
|
282 | }; | |
289 |
|
283 | |||
290 | Completer.prototype.close = function () { |
|
284 | Completer.prototype.close = function () { | |
291 | this._visible = false; |
|
|||
292 | if (this.done) return; |
|
|||
293 | this.done = true; |
|
285 | this.done = true; | |
294 |
$(' |
|
286 | $('#complete').remove(); | |
295 | IPython.keyboard_manager.enable(); |
|
287 | this.editor.off('keydown', this._handle_keydown); | |
|
288 | this.editor.off('keypress', this._handle_keypress); | |||
|
289 | this.visible = false; | |||
296 | }; |
|
290 | }; | |
297 |
|
291 | |||
298 | Completer.prototype.pick = function () { |
|
292 | Completer.prototype.pick = function () { | |
299 | this.insert(this.raw_result[this.sel[0].selectedIndex]); |
|
293 | this.insert(this.raw_result[this.sel[0].selectedIndex]); | |
300 | this.close(); |
|
294 | this.close(); | |
301 | var that = this; |
|
|||
302 | setTimeout(function () { |
|
|||
303 | that.editor.focus(); |
|
|||
304 | }, 50); |
|
|||
305 | }; |
|
295 | }; | |
306 |
|
296 | |||
307 | Completer.prototype.keydown = function (event) { |
|
297 | Completer.prototype.keydown = function (event) { | |
308 | var code = event.keyCode; |
|
298 | var code = event.keyCode; | |
309 | var that = this; |
|
299 | var that = this; | |
310 |
|
300 | |||
311 | // Enter |
|
301 | // Enter | |
312 | if (code == keycodes.enter) { |
|
302 | if (code == keycodes.enter) { | |
313 | CodeMirror.e_stop(event); |
|
303 | CodeMirror.e_stop(event); | |
314 | this.pick(); |
|
304 | this.pick(); | |
315 | } |
|
|||
316 | // Escape or backspace |
|
305 | // Escape or backspace | |
317 | else if (code == keycodes.esc) { |
|
306 | } else if (code == keycodes.esc || code == keycodes.backspace) { | |
318 | CodeMirror.e_stop(event); |
|
307 | CodeMirror.e_stop(event); | |
319 | this.close(); |
|
308 | this.close(); | |
320 | this.editor.focus(); |
|
|||
321 |
|
||||
322 | } else if (code == keycodes.backspace) { |
|
|||
323 | this.close(); |
|
|||
324 | this.editor.focus(); |
|
|||
325 | } else if (code == keycodes.tab) { |
|
309 | } else if (code == keycodes.tab) { | |
326 | //all the fastforwarding operation, |
|
310 | //all the fastforwarding operation, | |
327 | //Check that shared start is not null which can append with prefixed completion |
|
311 | //Check that shared start is not null which can append with prefixed completion | |
328 | // like %pylab , pylab have no shred start, and ff will result in py<tab><tab> |
|
312 | // like %pylab , pylab have no shred start, and ff will result in py<tab><tab> | |
329 | // to erase py |
|
313 | // to erase py | |
330 | var sh = shared_start(this.raw_result, true); |
|
314 | var sh = shared_start(this.raw_result, true); | |
331 | if (sh) { |
|
315 | if (sh) { | |
332 | this.insert(sh); |
|
316 | this.insert(sh); | |
333 | } |
|
317 | } | |
334 | this.close(); |
|
318 | this.close(); | |
335 | CodeMirror.e_stop(event); |
|
|||
336 | this.editor.focus(); |
|
|||
337 | //reinvoke self |
|
319 | //reinvoke self | |
338 | setTimeout(function () { |
|
320 | setTimeout(function () { | |
339 | that.carry_on_completion(); |
|
321 | that.carry_on_completion(); | |
340 | }, 50); |
|
322 | }, 50); | |
341 | } else if (code == keycodes.up || code == keycodes.down) { |
|
323 | } else if (code == keycodes.up || code == keycodes.down) { | |
342 | // need to do that to be able to move the arrow |
|
324 | // need to do that to be able to move the arrow | |
343 | // when on the first or last line ofo a code cell |
|
325 | // when on the first or last line ofo a code cell | |
344 | event.stopPropagation(); |
|
326 | CodeMirror.e_stop(event); | |
|
327 | ||||
|
328 | var options = this.sel.find('option'); | |||
|
329 | var index = this.sel[0].selectedIndex; | |||
|
330 | if (code == keycodes.up) { | |||
|
331 | index--; | |||
|
332 | } | |||
|
333 | if (code == keycodes.down) { | |||
|
334 | index++; | |||
|
335 | } | |||
|
336 | index = Math.min(Math.max(index, 0), options.length-1); | |||
|
337 | this.sel[0].selectedIndex = index; | |||
|
338 | } else if (code == keycodes.left || code == keycodes.right) { | |||
|
339 | this.close(); | |||
345 | } |
|
340 | } | |
346 | }; |
|
341 | }; | |
347 |
|
342 | |||
348 | Completer.prototype.keypress = function (event) { |
|
343 | Completer.prototype.keypress = function (event) { | |
349 | // FIXME: This is a band-aid. |
|
344 | // FIXME: This is a band-aid. | |
350 | // on keypress, trigger insertion of a single character. |
|
345 | // on keypress, trigger insertion of a single character. | |
351 | // This simulates the old behavior of completion as you type, |
|
346 | // This simulates the old behavior of completion as you type, | |
352 | // before events were disconnected and CodeMirror stopped |
|
347 | // before events were disconnected and CodeMirror stopped | |
353 | // receiving events while the completer is focused. |
|
348 | // receiving events while the completer is focused. | |
354 |
|
349 | |||
355 | var that = this; |
|
350 | var that = this; | |
356 | var code = event.keyCode; |
|
351 | var code = event.keyCode; | |
357 |
|
352 | |||
358 | // don't handle keypress if it's not a character (arrows on FF) |
|
353 | // don't handle keypress if it's not a character (arrows on FF) | |
359 | // or ENTER/TAB |
|
354 | // or ENTER/TAB | |
360 | if (event.charCode === 0 || |
|
355 | if (event.charCode === 0 || | |
361 |
code == keycodes. |
|
356 | code == keycodes.tab || | |
362 |
code == keycodes. |
|
357 | code == keycodes.enter | |
363 | ) return; |
|
358 | ) return; | |
364 |
|
359 | |||
365 | var cur = this.editor.getCursor(); |
|
|||
366 | var completion = { |
|
|||
367 | str: String.fromCharCode(event.which), |
|
|||
368 | type: "introspection", |
|
|||
369 | from: cur, |
|
|||
370 | to: cur, |
|
|||
371 | }; |
|
|||
372 | this.insert(completion); |
|
|||
373 |
|
||||
374 | this.close(); |
|
360 | this.close(); | |
375 | this.editor.focus(); |
|
361 | this.editor.focus(); | |
376 | setTimeout(function () { |
|
362 | setTimeout(function () { | |
377 | that.carry_on_completion(); |
|
363 | that.carry_on_completion(); | |
378 | }, 50); |
|
364 | }, 50); | |
379 | }; |
|
365 | }; | |
380 |
|
||||
381 | IPython.Completer = Completer; |
|
366 | IPython.Completer = Completer; | |
382 |
|
367 | |||
383 | return IPython; |
|
368 | return IPython; | |
384 | }(IPython)); |
|
369 | }(IPython)); |
@@ -1,24 +1,25 b'' | |||||
1 | .completions { |
|
1 | .completions { | |
2 | position: absolute; |
|
2 | position: absolute; | |
3 | z-index: 10; |
|
3 | z-index: 10; | |
4 | overflow: hidden; |
|
4 | overflow: hidden; | |
5 | border: 1px solid @border_color; |
|
5 | border: 1px solid @border_color; | |
6 | .corner-all; |
|
6 | .corner-all; | |
7 | .box-shadow(0px 6px 10px -1px #adadad); |
|
7 | .box-shadow(0px 6px 10px -1px #adadad); | |
8 | } |
|
8 | } | |
9 |
|
9 | |||
10 | .completions select { |
|
10 | .completions select { | |
11 | background: white; |
|
11 | background: white; | |
12 | outline: none; |
|
12 | outline: none; | |
13 | border: none; |
|
13 | border: none; | |
14 | padding: 0px; |
|
14 | padding: 0px; | |
15 | margin: 0px; |
|
15 | margin: 0px; | |
16 | overflow: auto; |
|
16 | overflow: auto; | |
17 | font-family: @monoFontFamily; |
|
17 | font-family: @monoFontFamily; | |
18 | font-size: 110%; |
|
18 | font-size: 110%; | |
19 | color: @textColor; |
|
19 | color: @textColor; | |
|
20 | width: auto; | |||
20 | } |
|
21 | } | |
21 |
|
22 | |||
22 | .completions select option.context { |
|
23 | .completions select option.context { | |
23 | color: @blueDark; |
|
24 | color: @blueDark; | |
24 | } |
|
25 | } |
@@ -1,1536 +1,1536 b'' | |||||
1 | .clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0} |
|
|||
2 | .clearfix:after{clear:both} |
|
|||
3 | .hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0} |
|
|||
4 | .input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} |
|
|||
5 | article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block} |
|
1 | article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block} | |
6 | audio,canvas,video{display:inline-block;*display:inline;*zoom:1} |
|
2 | audio,canvas,video{display:inline-block;*display:inline;*zoom:1} | |
7 | audio:not([controls]){display:none} |
|
3 | audio:not([controls]){display:none} | |
8 | html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%} |
|
4 | html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%} | |
9 | a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px} |
|
5 | a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px} | |
10 | a:hover,a:active{outline:0} |
|
6 | a:hover,a:active{outline:0} | |
11 | sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline} |
|
7 | sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline} | |
12 | sup{top:-0.5em} |
|
8 | sup{top:-0.5em} | |
13 | sub{bottom:-0.25em} |
|
9 | sub{bottom:-0.25em} | |
14 | img{max-width:100%;width:auto\9;height:auto;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic} |
|
10 | img{max-width:100%;width:auto\9;height:auto;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic} | |
15 | #map_canvas img,.google-maps img{max-width:none} |
|
11 | #map_canvas img,.google-maps img{max-width:none} | |
16 | button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle} |
|
12 | button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle} | |
17 | button,input{*overflow:visible;line-height:normal} |
|
13 | button,input{*overflow:visible;line-height:normal} | |
18 | button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0} |
|
14 | button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0} | |
19 | button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} |
|
15 | button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} | |
20 | label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer} |
|
16 | label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer} | |
21 | input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield} |
|
17 | input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield} | |
22 | input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none} |
|
18 | input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none} | |
23 | textarea{overflow:auto;vertical-align:top} |
|
19 | textarea{overflow:auto;vertical-align:top} | |
24 | @media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important} a,a:visited{text-decoration:underline} a[href]:after{content:" (" attr(href) ")"} abbr[title]:after{content:" (" attr(title) ")"} .ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""} pre,blockquote{border:1px solid #999;page-break-inside:avoid} thead{display:table-header-group} tr,img{page-break-inside:avoid} img{max-width:100% !important} @page {margin:.5cm}p,h2,h3{orphans:3;widows:3} h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:20px;color:#000;background-color:#fff} |
|
20 | @media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important} a,a:visited{text-decoration:underline} a[href]:after{content:" (" attr(href) ")"} abbr[title]:after{content:" (" attr(title) ")"} .ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""} pre,blockquote{border:1px solid #999;page-break-inside:avoid} thead{display:table-header-group} tr,img{page-break-inside:avoid} img{max-width:100% !important} @page {margin:.5cm}p,h2,h3{orphans:3;widows:3} h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:20px;color:#000;background-color:#fff} | |
25 | a{color:#08c;text-decoration:none} |
|
21 | a{color:#08c;text-decoration:none} | |
26 | a:hover,a:focus{color:#005580;text-decoration:underline} |
|
22 | a:hover,a:focus{color:#005580;text-decoration:underline} | |
27 | .img-rounded{border-radius:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px} |
|
23 | .img-rounded{border-radius:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px} | |
28 | .img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)} |
|
24 | .img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)} | |
29 | .img-circle{border-radius:500px;-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px} |
|
25 | .img-circle{border-radius:500px;-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px} | |
30 | .row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;content:"";line-height:0} |
|
26 | .row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;content:"";line-height:0} | |
31 | .row:after{clear:both} |
|
27 | .row:after{clear:both} | |
32 | [class*="span"]{float:left;min-height:1px;margin-left:20px} |
|
28 | [class*="span"]{float:left;min-height:1px;margin-left:20px} | |
33 | .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px} |
|
29 | .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px} | |
34 | .span12{width:940px} |
|
30 | .span12{width:940px} | |
35 | .span11{width:860px} |
|
31 | .span11{width:860px} | |
36 | .span10{width:780px} |
|
32 | .span10{width:780px} | |
37 | .span9{width:700px} |
|
33 | .span9{width:700px} | |
38 | .span8{width:620px} |
|
34 | .span8{width:620px} | |
39 | .span7{width:540px} |
|
35 | .span7{width:540px} | |
40 | .span6{width:460px} |
|
36 | .span6{width:460px} | |
41 | .span5{width:380px} |
|
37 | .span5{width:380px} | |
42 | .span4{width:300px} |
|
38 | .span4{width:300px} | |
43 | .span3{width:220px} |
|
39 | .span3{width:220px} | |
44 | .span2{width:140px} |
|
40 | .span2{width:140px} | |
45 | .span1{width:60px} |
|
41 | .span1{width:60px} | |
46 | .offset12{margin-left:980px} |
|
42 | .offset12{margin-left:980px} | |
47 | .offset11{margin-left:900px} |
|
43 | .offset11{margin-left:900px} | |
48 | .offset10{margin-left:820px} |
|
44 | .offset10{margin-left:820px} | |
49 | .offset9{margin-left:740px} |
|
45 | .offset9{margin-left:740px} | |
50 | .offset8{margin-left:660px} |
|
46 | .offset8{margin-left:660px} | |
51 | .offset7{margin-left:580px} |
|
47 | .offset7{margin-left:580px} | |
52 | .offset6{margin-left:500px} |
|
48 | .offset6{margin-left:500px} | |
53 | .offset5{margin-left:420px} |
|
49 | .offset5{margin-left:420px} | |
54 | .offset4{margin-left:340px} |
|
50 | .offset4{margin-left:340px} | |
55 | .offset3{margin-left:260px} |
|
51 | .offset3{margin-left:260px} | |
56 | .offset2{margin-left:180px} |
|
52 | .offset2{margin-left:180px} | |
57 | .offset1{margin-left:100px} |
|
53 | .offset1{margin-left:100px} | |
58 | .row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0} |
|
54 | .row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0} | |
59 | .row-fluid:after{clear:both} |
|
55 | .row-fluid:after{clear:both} | |
60 | .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.127659574468085%;*margin-left:2.074468085106383%} |
|
56 | .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.127659574468085%;*margin-left:2.074468085106383%} | |
61 | .row-fluid [class*="span"]:first-child{margin-left:0} |
|
57 | .row-fluid [class*="span"]:first-child{margin-left:0} | |
62 | .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%} |
|
58 | .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%} | |
63 | .row-fluid .span12{width:100%;*width:99.94680851063829%} |
|
59 | .row-fluid .span12{width:100%;*width:99.94680851063829%} | |
64 | .row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%} |
|
60 | .row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%} | |
65 | .row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%} |
|
61 | .row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%} | |
66 | .row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%} |
|
62 | .row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%} | |
67 | .row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%} |
|
63 | .row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%} | |
68 | .row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%} |
|
64 | .row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%} | |
69 | .row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%} |
|
65 | .row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%} | |
70 | .row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%} |
|
66 | .row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%} | |
71 | .row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%} |
|
67 | .row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%} | |
72 | .row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%} |
|
68 | .row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%} | |
73 | .row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%} |
|
69 | .row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%} | |
74 | .row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%} |
|
70 | .row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%} | |
75 | .row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%} |
|
71 | .row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%} | |
76 | .row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%} |
|
72 | .row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%} | |
77 | .row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%} |
|
73 | .row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%} | |
78 | .row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%} |
|
74 | .row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%} | |
79 | .row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%} |
|
75 | .row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%} | |
80 | .row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%} |
|
76 | .row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%} | |
81 | .row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%} |
|
77 | .row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%} | |
82 | .row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%} |
|
78 | .row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%} | |
83 | .row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%} |
|
79 | .row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%} | |
84 | .row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%} |
|
80 | .row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%} | |
85 | .row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%} |
|
81 | .row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%} | |
86 | .row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%} |
|
82 | .row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%} | |
87 | .row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%} |
|
83 | .row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%} | |
88 | .row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%} |
|
84 | .row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%} | |
89 | .row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%} |
|
85 | .row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%} | |
90 | .row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%} |
|
86 | .row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%} | |
91 | .row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%} |
|
87 | .row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%} | |
92 | .row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%} |
|
88 | .row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%} | |
93 | .row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%} |
|
89 | .row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%} | |
94 | .row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%} |
|
90 | .row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%} | |
95 | .row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%} |
|
91 | .row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%} | |
96 | .row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%} |
|
92 | .row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%} | |
97 | .row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%} |
|
93 | .row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%} | |
98 | .row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%} |
|
94 | .row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%} | |
99 | [class*="span"].hide,.row-fluid [class*="span"].hide{display:none} |
|
95 | [class*="span"].hide,.row-fluid [class*="span"].hide{display:none} | |
100 | [class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right} |
|
96 | [class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right} | |
101 | .container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;content:"";line-height:0} |
|
97 | .container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;content:"";line-height:0} | |
102 | .container:after{clear:both} |
|
98 | .container:after{clear:both} | |
103 | .container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;content:"";line-height:0} |
|
99 | .container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;content:"";line-height:0} | |
104 | .container-fluid:after{clear:both} |
|
100 | .container-fluid:after{clear:both} | |
105 | p{margin:0 0 10px} |
|
101 | p{margin:0 0 10px} | |
106 | .lead{margin-bottom:20px;font-size:19.5px;font-weight:200;line-height:30px} |
|
102 | .lead{margin-bottom:20px;font-size:19.5px;font-weight:200;line-height:30px} | |
107 | small{font-size:85%} |
|
103 | small{font-size:85%} | |
108 | strong{font-weight:bold} |
|
104 | strong{font-weight:bold} | |
109 | em{font-style:italic} |
|
105 | em{font-style:italic} | |
110 | cite{font-style:normal} |
|
106 | cite{font-style:normal} | |
111 | .muted{color:#999} |
|
107 | .muted{color:#999} | |
112 | a.muted:hover,a.muted:focus{color:#808080} |
|
108 | a.muted:hover,a.muted:focus{color:#808080} | |
113 | .text-warning{color:#c09853} |
|
109 | .text-warning{color:#c09853} | |
114 | a.text-warning:hover,a.text-warning:focus{color:#a47e3c} |
|
110 | a.text-warning:hover,a.text-warning:focus{color:#a47e3c} | |
115 | .text-error{color:#b94a48} |
|
111 | .text-error{color:#b94a48} | |
116 | a.text-error:hover,a.text-error:focus{color:#953b39} |
|
112 | a.text-error:hover,a.text-error:focus{color:#953b39} | |
117 | .text-info{color:#3a87ad} |
|
113 | .text-info{color:#3a87ad} | |
118 | a.text-info:hover,a.text-info:focus{color:#2d6987} |
|
114 | a.text-info:hover,a.text-info:focus{color:#2d6987} | |
119 | .text-success{color:#468847} |
|
115 | .text-success{color:#468847} | |
120 | a.text-success:hover,a.text-success:focus{color:#356635} |
|
116 | a.text-success:hover,a.text-success:focus{color:#356635} | |
121 | .text-left{text-align:left} |
|
117 | .text-left{text-align:left} | |
122 | .text-right{text-align:right} |
|
118 | .text-right{text-align:right} | |
123 | .text-center{text-align:center} |
|
119 | .text-center{text-align:center} | |
124 | h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999} |
|
120 | h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999} | |
125 | h1,h2,h3{line-height:40px} |
|
121 | h1,h2,h3{line-height:40px} | |
126 | h1{font-size:35.75px} |
|
122 | h1{font-size:35.75px} | |
127 | h2{font-size:29.25px} |
|
123 | h2{font-size:29.25px} | |
128 | h3{font-size:22.75px} |
|
124 | h3{font-size:22.75px} | |
129 | h4{font-size:16.25px} |
|
125 | h4{font-size:16.25px} | |
130 | h5{font-size:13px} |
|
126 | h5{font-size:13px} | |
131 | h6{font-size:11.049999999999999px} |
|
127 | h6{font-size:11.049999999999999px} | |
132 | h1 small{font-size:22.75px} |
|
128 | h1 small{font-size:22.75px} | |
133 | h2 small{font-size:16.25px} |
|
129 | h2 small{font-size:16.25px} | |
134 | h3 small{font-size:13px} |
|
130 | h3 small{font-size:13px} | |
135 | h4 small{font-size:13px} |
|
131 | h4 small{font-size:13px} | |
136 | .page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee} |
|
132 | .page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee} | |
137 | ul,ol{padding:0;margin:0 0 10px 25px} |
|
133 | ul,ol{padding:0;margin:0 0 10px 25px} | |
138 | ul ul,ul ol,ol ol,ol ul{margin-bottom:0} |
|
134 | ul ul,ul ol,ol ol,ol ul{margin-bottom:0} | |
139 | li{line-height:20px} |
|
135 | li{line-height:20px} | |
140 | ul.unstyled,ol.unstyled{margin-left:0;list-style:none} |
|
136 | ul.unstyled,ol.unstyled{margin-left:0;list-style:none} | |
141 | ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;*zoom:1;padding-left:5px;padding-right:5px} |
|
137 | ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;*zoom:1;padding-left:5px;padding-right:5px} | |
142 | dl{margin-bottom:20px} |
|
138 | dl{margin-bottom:20px} | |
143 | dt,dd{line-height:20px} |
|
139 | dt,dd{line-height:20px} | |
144 | dt{font-weight:bold} |
|
140 | dt{font-weight:bold} | |
145 | dd{margin-left:10px} |
|
141 | dd{margin-left:10px} | |
146 | .dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;content:"";line-height:0} |
|
142 | .dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;content:"";line-height:0} | |
147 | .dl-horizontal:after{clear:both} |
|
143 | .dl-horizontal:after{clear:both} | |
148 | .dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} |
|
144 | .dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} | |
149 | .dl-horizontal dd{margin-left:180px} |
|
145 | .dl-horizontal dd{margin-left:180px} | |
150 | hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff} |
|
146 | hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff} | |
151 | abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999} |
|
147 | abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999} | |
152 | abbr.initialism{font-size:90%;text-transform:uppercase} |
|
148 | abbr.initialism{font-size:90%;text-transform:uppercase} | |
153 | blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:16.25px;font-weight:300;line-height:1.25} |
|
149 | blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:16.25px;font-weight:300;line-height:1.25} | |
154 | blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'} |
|
150 | blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'} | |
155 | blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right} |
|
151 | blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right} | |
156 | blockquote.pull-right small:before{content:''} |
|
152 | blockquote.pull-right small:before{content:''} | |
157 | blockquote.pull-right small:after{content:'\00A0 \2014'} |
|
153 | blockquote.pull-right small:after{content:'\00A0 \2014'} | |
158 | q:before,q:after,blockquote:before,blockquote:after{content:""} |
|
154 | q:before,q:after,blockquote:before,blockquote:after{content:""} | |
159 | address{display:block;margin-bottom:20px;font-style:normal;line-height:20px} |
|
155 | address{display:block;margin-bottom:20px;font-style:normal;line-height:20px} | |
160 | code,pre{padding:0 3px 2px;font-family:monospace;font-size:11px;color:#333;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} |
|
156 | code,pre{padding:0 3px 2px;font-family:monospace;font-size:11px;color:#333;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} | |
161 | code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;white-space:nowrap} |
|
157 | code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;white-space:nowrap} | |
162 | pre{display:block;padding:9.5px;margin:0 0 10px;font-size:12px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px} |
|
158 | pre{display:block;padding:9.5px;margin:0 0 10px;font-size:12px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px} | |
163 | pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0} |
|
159 | pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0} | |
164 | .pre-scrollable{max-height:340px;overflow-y:scroll} |
|
160 | .pre-scrollable{max-height:340px;overflow-y:scroll} | |
165 | form{margin:0 0 20px} |
|
161 | form{margin:0 0 20px} | |
166 | fieldset{padding:0;margin:0;border:0} |
|
162 | fieldset{padding:0;margin:0;border:0} | |
167 | legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:19.5px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999} |
|
163 | legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:19.5px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999} | |
168 | label,input,button,select,textarea{font-size:13px;font-weight:normal;line-height:20px} |
|
164 | label,input,button,select,textarea{font-size:13px;font-weight:normal;line-height:20px} | |
169 | input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif} |
|
165 | input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif} | |
170 | label{display:block;margin-bottom:5px} |
|
166 | label{display:block;margin-bottom:5px} | |
171 | select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:13px;line-height:20px;color:#555;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;vertical-align:middle} |
|
167 | select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:13px;line-height:20px;color:#555;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;vertical-align:middle} | |
172 | input,textarea,.uneditable-input{width:206px} |
|
168 | input,textarea,.uneditable-input{width:206px} | |
173 | textarea{height:auto} |
|
169 | textarea{height:auto} | |
174 | textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s, box-shadow linear .2s;-moz-transition:border linear .2s, box-shadow linear .2s;-o-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6)} |
|
170 | textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s, box-shadow linear .2s;-moz-transition:border linear .2s, box-shadow linear .2s;-o-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6)} | |
175 | input[type="radio"],input[type="checkbox"]{margin:4px 0 0;*margin-top:0;margin-top:1px \9;line-height:normal} |
|
171 | input[type="radio"],input[type="checkbox"]{margin:4px 0 0;*margin-top:0;margin-top:1px \9;line-height:normal} | |
176 | input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto} |
|
172 | input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto} | |
177 | select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px} |
|
173 | select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px} | |
178 | select{width:220px;border:1px solid #ccc;background-color:#fff} |
|
174 | select{width:220px;border:1px solid #ccc;background-color:#fff} | |
179 | select[multiple],select[size]{height:auto} |
|
175 | select[multiple],select[size]{height:auto} | |
180 | select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px} |
|
176 | select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px} | |
181 | .uneditable-input,.uneditable-textarea{color:#999;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);cursor:not-allowed} |
|
177 | .uneditable-input,.uneditable-textarea{color:#999;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);cursor:not-allowed} | |
182 | .uneditable-input{overflow:hidden;white-space:nowrap} |
|
178 | .uneditable-input{overflow:hidden;white-space:nowrap} | |
183 | .uneditable-textarea{width:auto;height:auto} |
|
179 | .uneditable-textarea{width:auto;height:auto} | |
184 | input:-moz-placeholder,textarea:-moz-placeholder{color:#999} |
|
180 | input:-moz-placeholder,textarea:-moz-placeholder{color:#999} | |
185 | input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999} |
|
181 | input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999} | |
186 | input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999} |
|
182 | input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999} | |
187 | .radio,.checkbox{min-height:20px;padding-left:20px} |
|
183 | .radio,.checkbox{min-height:20px;padding-left:20px} | |
188 | .radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px} |
|
184 | .radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px} | |
189 | .controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px} |
|
185 | .controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px} | |
190 | .radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle} |
|
186 | .radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle} | |
191 | .radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px} |
|
187 | .radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px} | |
192 | .input-mini{width:60px} |
|
188 | .input-mini{width:60px} | |
193 | .input-small{width:90px} |
|
189 | .input-small{width:90px} | |
194 | .input-medium{width:150px} |
|
190 | .input-medium{width:150px} | |
195 | .input-large{width:210px} |
|
191 | .input-large{width:210px} | |
196 | .input-xlarge{width:270px} |
|
192 | .input-xlarge{width:270px} | |
197 | .input-xxlarge{width:530px} |
|
193 | .input-xxlarge{width:530px} | |
198 | input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0} |
|
194 | input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0} | |
199 | .input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block} |
|
195 | .input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block} | |
200 | input,textarea,.uneditable-input{margin-left:0} |
|
196 | input,textarea,.uneditable-input{margin-left:0} | |
201 | .controls-row [class*="span"]+[class*="span"]{margin-left:20px} |
|
197 | .controls-row [class*="span"]+[class*="span"]{margin-left:20px} | |
202 | input.span12,textarea.span12,.uneditable-input.span12{width:926px} |
|
198 | input.span12,textarea.span12,.uneditable-input.span12{width:926px} | |
203 | input.span11,textarea.span11,.uneditable-input.span11{width:846px} |
|
199 | input.span11,textarea.span11,.uneditable-input.span11{width:846px} | |
204 | input.span10,textarea.span10,.uneditable-input.span10{width:766px} |
|
200 | input.span10,textarea.span10,.uneditable-input.span10{width:766px} | |
205 | input.span9,textarea.span9,.uneditable-input.span9{width:686px} |
|
201 | input.span9,textarea.span9,.uneditable-input.span9{width:686px} | |
206 | input.span8,textarea.span8,.uneditable-input.span8{width:606px} |
|
202 | input.span8,textarea.span8,.uneditable-input.span8{width:606px} | |
207 | input.span7,textarea.span7,.uneditable-input.span7{width:526px} |
|
203 | input.span7,textarea.span7,.uneditable-input.span7{width:526px} | |
208 | input.span6,textarea.span6,.uneditable-input.span6{width:446px} |
|
204 | input.span6,textarea.span6,.uneditable-input.span6{width:446px} | |
209 | input.span5,textarea.span5,.uneditable-input.span5{width:366px} |
|
205 | input.span5,textarea.span5,.uneditable-input.span5{width:366px} | |
210 | input.span4,textarea.span4,.uneditable-input.span4{width:286px} |
|
206 | input.span4,textarea.span4,.uneditable-input.span4{width:286px} | |
211 | input.span3,textarea.span3,.uneditable-input.span3{width:206px} |
|
207 | input.span3,textarea.span3,.uneditable-input.span3{width:206px} | |
212 | input.span2,textarea.span2,.uneditable-input.span2{width:126px} |
|
208 | input.span2,textarea.span2,.uneditable-input.span2{width:126px} | |
213 | input.span1,textarea.span1,.uneditable-input.span1{width:46px} |
|
209 | input.span1,textarea.span1,.uneditable-input.span1{width:46px} | |
214 | .controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;content:"";line-height:0} |
|
210 | .controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;content:"";line-height:0} | |
215 | .controls-row:after{clear:both} |
|
211 | .controls-row:after{clear:both} | |
216 | .controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left} |
|
212 | .controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left} | |
217 | .controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px} |
|
213 | .controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px} | |
218 | input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee} |
|
214 | input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee} | |
219 | input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent} |
|
215 | input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent} | |
220 | .control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853} |
|
216 | .control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853} | |
221 | .control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853} |
|
217 | .control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853} | |
222 | .control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e} |
|
218 | .control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e} | |
223 | .control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853} |
|
219 | .control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853} | |
224 | .control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48} |
|
220 | .control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48} | |
225 | .control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48} |
|
221 | .control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48} | |
226 | .control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392} |
|
222 | .control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392} | |
227 | .control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48} |
|
223 | .control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48} | |
228 | .control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847} |
|
224 | .control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847} | |
229 | .control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847} |
|
225 | .control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847} | |
230 | .control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b} |
|
226 | .control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b} | |
231 | .control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847} |
|
227 | .control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847} | |
232 | .control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad} |
|
228 | .control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad} | |
233 | .control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad} |
|
229 | .control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad} | |
234 | .control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3} |
|
230 | .control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3} | |
235 | .control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad} |
|
231 | .control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad} | |
236 | input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7} |
|
232 | input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7} | |
237 | .form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;content:"";line-height:0} |
|
233 | .form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;content:"";line-height:0} | |
238 | .form-actions:after{clear:both} |
|
234 | .form-actions:after{clear:both} | |
239 | .help-block,.help-inline{color:#262626} |
|
235 | .help-block,.help-inline{color:#262626} | |
240 | .help-block{display:block;margin-bottom:10px} |
|
236 | .help-block{display:block;margin-bottom:10px} | |
241 | .help-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding-left:5px} |
|
237 | .help-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding-left:5px} | |
242 | .input-append,.input-prepend{display:inline-block;margin-bottom:10px;vertical-align:middle;font-size:0;white-space:nowrap}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:13px} |
|
238 | .input-append,.input-prepend{display:inline-block;margin-bottom:10px;vertical-align:middle;font-size:0;white-space:nowrap}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:13px} | |
243 | .input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2} |
|
239 | .input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2} | |
244 | .input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:13px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc} |
|
240 | .input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:13px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc} | |
245 | .input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} |
|
241 | .input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} | |
246 | .input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546} |
|
242 | .input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546} | |
247 | .input-prepend .add-on,.input-prepend .btn{margin-right:-1px} |
|
243 | .input-prepend .add-on,.input-prepend .btn{margin-right:-1px} | |
248 | .input-prepend .add-on:first-child,.input-prepend .btn:first-child{border-radius:4px 0 0 4px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px} |
|
244 | .input-prepend .add-on:first-child,.input-prepend .btn:first-child{border-radius:4px 0 0 4px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px} | |
249 | .input-append input,.input-append select,.input-append .uneditable-input{border-radius:4px 0 0 4px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0} |
|
245 | .input-append input,.input-append select,.input-append .uneditable-input{border-radius:4px 0 0 4px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0} | |
250 | .input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px} |
|
246 | .input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px} | |
251 | .input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0} |
|
247 | .input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0} | |
252 | .input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0} |
|
248 | .input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0} | |
253 | .input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;border-radius:4px 0 0 4px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px} |
|
249 | .input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;border-radius:4px 0 0 4px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px} | |
254 | .input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0} |
|
250 | .input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0} | |
255 | .input-prepend.input-append .btn-group:first-child{margin-left:0} |
|
251 | .input-prepend.input-append .btn-group:first-child{margin-left:0} | |
256 | input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;border-radius:15px;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px} |
|
252 | input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;border-radius:15px;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px} | |
257 | .form-search .input-append .search-query,.form-search .input-prepend .search-query{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} |
|
253 | .form-search .input-append .search-query,.form-search .input-prepend .search-query{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} | |
258 | .form-search .input-append .search-query{border-radius:14px 0 0 14px;-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px} |
|
254 | .form-search .input-append .search-query{border-radius:14px 0 0 14px;-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px} | |
259 | .form-search .input-append .btn{border-radius:0 14px 14px 0;-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0} |
|
255 | .form-search .input-append .btn{border-radius:0 14px 14px 0;-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0} | |
260 | .form-search .input-prepend .search-query{border-radius:0 14px 14px 0;-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0} |
|
256 | .form-search .input-prepend .search-query{border-radius:0 14px 14px 0;-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0} | |
261 | .form-search .input-prepend .btn{border-radius:14px 0 0 14px;-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px} |
|
257 | .form-search .input-prepend .btn{border-radius:14px 0 0 14px;-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px} | |
262 | .form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;*zoom:1;margin-bottom:0;vertical-align:middle} |
|
258 | .form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;*zoom:1;margin-bottom:0;vertical-align:middle} | |
263 | .form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none} |
|
259 | .form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none} | |
264 | .form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block} |
|
260 | .form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block} | |
265 | .form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0} |
|
261 | .form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0} | |
266 | .form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle} |
|
262 | .form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle} | |
267 | .form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0} |
|
263 | .form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0} | |
268 | .control-group{margin-bottom:10px} |
|
264 | .control-group{margin-bottom:10px} | |
269 | legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate} |
|
265 | legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate} | |
270 | .form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:"";line-height:0} |
|
266 | .form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:"";line-height:0} | |
271 | .form-horizontal .control-group:after{clear:both} |
|
267 | .form-horizontal .control-group:after{clear:both} | |
272 | .form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right} |
|
268 | .form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right} | |
273 | .form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px} |
|
269 | .form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px} | |
274 | .form-horizontal .help-block{margin-bottom:0} |
|
270 | .form-horizontal .help-block{margin-bottom:0} | |
275 | .form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px} |
|
271 | .form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px} | |
276 | .form-horizontal .form-actions{padding-left:180px} |
|
272 | .form-horizontal .form-actions{padding-left:180px} | |
277 | table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0} |
|
273 | table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0} | |
278 | .table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd} |
|
274 | .table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd} | |
279 | .table th{font-weight:bold} |
|
275 | .table th{font-weight:bold} | |
280 | .table thead th{vertical-align:bottom} |
|
276 | .table thead th{vertical-align:bottom} | |
281 | .table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0} |
|
277 | .table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0} | |
282 | .table tbody+tbody{border-top:2px solid #ddd} |
|
278 | .table tbody+tbody{border-top:2px solid #ddd} | |
283 | .table .table{background-color:#fff} |
|
279 | .table .table{background-color:#fff} | |
284 | .table-condensed th,.table-condensed td{padding:4px 5px} |
|
280 | .table-condensed th,.table-condensed td{padding:4px 5px} | |
285 | .table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd} |
|
281 | .table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd} | |
286 | .table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0} |
|
282 | .table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0} | |
287 | .table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px} |
|
283 | .table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px} | |
288 | .table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px} |
|
284 | .table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px} | |
289 | .table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px} |
|
285 | .table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px} | |
290 | .table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px} |
|
286 | .table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px} | |
291 | .table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomleft:0;border-bottom-left-radius:0} |
|
287 | .table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;-moz-border-radius-bottomleft:0;border-bottom-left-radius:0} | |
292 | .table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;-moz-border-radius-bottomright:0;border-bottom-right-radius:0} |
|
288 | .table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;-moz-border-radius-bottomright:0;border-bottom-right-radius:0} | |
293 | .table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px} |
|
289 | .table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px} | |
294 | .table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px} |
|
290 | .table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px} | |
295 | .table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9} |
|
291 | .table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9} | |
296 | .table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5} |
|
292 | .table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5} | |
297 | table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0} |
|
293 | table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0} | |
298 | .table td.span1,.table th.span1{float:none;width:44px;margin-left:0} |
|
294 | .table td.span1,.table th.span1{float:none;width:44px;margin-left:0} | |
299 | .table td.span2,.table th.span2{float:none;width:124px;margin-left:0} |
|
295 | .table td.span2,.table th.span2{float:none;width:124px;margin-left:0} | |
300 | .table td.span3,.table th.span3{float:none;width:204px;margin-left:0} |
|
296 | .table td.span3,.table th.span3{float:none;width:204px;margin-left:0} | |
301 | .table td.span4,.table th.span4{float:none;width:284px;margin-left:0} |
|
297 | .table td.span4,.table th.span4{float:none;width:284px;margin-left:0} | |
302 | .table td.span5,.table th.span5{float:none;width:364px;margin-left:0} |
|
298 | .table td.span5,.table th.span5{float:none;width:364px;margin-left:0} | |
303 | .table td.span6,.table th.span6{float:none;width:444px;margin-left:0} |
|
299 | .table td.span6,.table th.span6{float:none;width:444px;margin-left:0} | |
304 | .table td.span7,.table th.span7{float:none;width:524px;margin-left:0} |
|
300 | .table td.span7,.table th.span7{float:none;width:524px;margin-left:0} | |
305 | .table td.span8,.table th.span8{float:none;width:604px;margin-left:0} |
|
301 | .table td.span8,.table th.span8{float:none;width:604px;margin-left:0} | |
306 | .table td.span9,.table th.span9{float:none;width:684px;margin-left:0} |
|
302 | .table td.span9,.table th.span9{float:none;width:684px;margin-left:0} | |
307 | .table td.span10,.table th.span10{float:none;width:764px;margin-left:0} |
|
303 | .table td.span10,.table th.span10{float:none;width:764px;margin-left:0} | |
308 | .table td.span11,.table th.span11{float:none;width:844px;margin-left:0} |
|
304 | .table td.span11,.table th.span11{float:none;width:844px;margin-left:0} | |
309 | .table td.span12,.table th.span12{float:none;width:924px;margin-left:0} |
|
305 | .table td.span12,.table th.span12{float:none;width:924px;margin-left:0} | |
310 | .table tbody tr.success>td{background-color:#dff0d8} |
|
306 | .table tbody tr.success>td{background-color:#dff0d8} | |
311 | .table tbody tr.error>td{background-color:#f2dede} |
|
307 | .table tbody tr.error>td{background-color:#f2dede} | |
312 | .table tbody tr.warning>td{background-color:#fcf8e3} |
|
308 | .table tbody tr.warning>td{background-color:#fcf8e3} | |
313 | .table tbody tr.info>td{background-color:#d9edf7} |
|
309 | .table tbody tr.info>td{background-color:#d9edf7} | |
314 | .table-hover tbody tr.success:hover>td{background-color:#d0e9c6} |
|
310 | .table-hover tbody tr.success:hover>td{background-color:#d0e9c6} | |
315 | .table-hover tbody tr.error:hover>td{background-color:#ebcccc} |
|
311 | .table-hover tbody tr.error:hover>td{background-color:#ebcccc} | |
316 | .table-hover tbody tr.warning:hover>td{background-color:#faf2cc} |
|
312 | .table-hover tbody tr.warning:hover>td{background-color:#faf2cc} | |
317 | .table-hover tbody tr.info:hover>td{background-color:#c4e3f3} |
|
313 | .table-hover tbody tr.info:hover>td{background-color:#c4e3f3} | |
318 | [class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat;margin-top:1px} |
|
314 | [class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat;margin-top:1px} | |
319 | .icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")} |
|
315 | .icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")} | |
320 | .icon-glass{background-position:0 0} |
|
316 | .icon-glass{background-position:0 0} | |
321 | .icon-music{background-position:-24px 0} |
|
317 | .icon-music{background-position:-24px 0} | |
322 | .icon-search{background-position:-48px 0} |
|
318 | .icon-search{background-position:-48px 0} | |
323 | .icon-envelope{background-position:-72px 0} |
|
319 | .icon-envelope{background-position:-72px 0} | |
324 | .icon-heart{background-position:-96px 0} |
|
320 | .icon-heart{background-position:-96px 0} | |
325 | .icon-star{background-position:-120px 0} |
|
321 | .icon-star{background-position:-120px 0} | |
326 | .icon-star-empty{background-position:-144px 0} |
|
322 | .icon-star-empty{background-position:-144px 0} | |
327 | .icon-user{background-position:-168px 0} |
|
323 | .icon-user{background-position:-168px 0} | |
328 | .icon-film{background-position:-192px 0} |
|
324 | .icon-film{background-position:-192px 0} | |
329 | .icon-th-large{background-position:-216px 0} |
|
325 | .icon-th-large{background-position:-216px 0} | |
330 | .icon-th{background-position:-240px 0} |
|
326 | .icon-th{background-position:-240px 0} | |
331 | .icon-th-list{background-position:-264px 0} |
|
327 | .icon-th-list{background-position:-264px 0} | |
332 | .icon-ok{background-position:-288px 0} |
|
328 | .icon-ok{background-position:-288px 0} | |
333 | .icon-remove{background-position:-312px 0} |
|
329 | .icon-remove{background-position:-312px 0} | |
334 | .icon-zoom-in{background-position:-336px 0} |
|
330 | .icon-zoom-in{background-position:-336px 0} | |
335 | .icon-zoom-out{background-position:-360px 0} |
|
331 | .icon-zoom-out{background-position:-360px 0} | |
336 | .icon-off{background-position:-384px 0} |
|
332 | .icon-off{background-position:-384px 0} | |
337 | .icon-signal{background-position:-408px 0} |
|
333 | .icon-signal{background-position:-408px 0} | |
338 | .icon-cog{background-position:-432px 0} |
|
334 | .icon-cog{background-position:-432px 0} | |
339 | .icon-trash{background-position:-456px 0} |
|
335 | .icon-trash{background-position:-456px 0} | |
340 | .icon-home{background-position:0 -24px} |
|
336 | .icon-home{background-position:0 -24px} | |
341 | .icon-file{background-position:-24px -24px} |
|
337 | .icon-file{background-position:-24px -24px} | |
342 | .icon-time{background-position:-48px -24px} |
|
338 | .icon-time{background-position:-48px -24px} | |
343 | .icon-road{background-position:-72px -24px} |
|
339 | .icon-road{background-position:-72px -24px} | |
344 | .icon-download-alt{background-position:-96px -24px} |
|
340 | .icon-download-alt{background-position:-96px -24px} | |
345 | .icon-download{background-position:-120px -24px} |
|
341 | .icon-download{background-position:-120px -24px} | |
346 | .icon-upload{background-position:-144px -24px} |
|
342 | .icon-upload{background-position:-144px -24px} | |
347 | .icon-inbox{background-position:-168px -24px} |
|
343 | .icon-inbox{background-position:-168px -24px} | |
348 | .icon-play-circle{background-position:-192px -24px} |
|
344 | .icon-play-circle{background-position:-192px -24px} | |
349 | .icon-repeat{background-position:-216px -24px} |
|
345 | .icon-repeat{background-position:-216px -24px} | |
350 | .icon-refresh{background-position:-240px -24px} |
|
346 | .icon-refresh{background-position:-240px -24px} | |
351 | .icon-list-alt{background-position:-264px -24px} |
|
347 | .icon-list-alt{background-position:-264px -24px} | |
352 | .icon-lock{background-position:-287px -24px} |
|
348 | .icon-lock{background-position:-287px -24px} | |
353 | .icon-flag{background-position:-312px -24px} |
|
349 | .icon-flag{background-position:-312px -24px} | |
354 | .icon-headphones{background-position:-336px -24px} |
|
350 | .icon-headphones{background-position:-336px -24px} | |
355 | .icon-volume-off{background-position:-360px -24px} |
|
351 | .icon-volume-off{background-position:-360px -24px} | |
356 | .icon-volume-down{background-position:-384px -24px} |
|
352 | .icon-volume-down{background-position:-384px -24px} | |
357 | .icon-volume-up{background-position:-408px -24px} |
|
353 | .icon-volume-up{background-position:-408px -24px} | |
358 | .icon-qrcode{background-position:-432px -24px} |
|
354 | .icon-qrcode{background-position:-432px -24px} | |
359 | .icon-barcode{background-position:-456px -24px} |
|
355 | .icon-barcode{background-position:-456px -24px} | |
360 | .icon-tag{background-position:0 -48px} |
|
356 | .icon-tag{background-position:0 -48px} | |
361 | .icon-tags{background-position:-25px -48px} |
|
357 | .icon-tags{background-position:-25px -48px} | |
362 | .icon-book{background-position:-48px -48px} |
|
358 | .icon-book{background-position:-48px -48px} | |
363 | .icon-bookmark{background-position:-72px -48px} |
|
359 | .icon-bookmark{background-position:-72px -48px} | |
364 | .icon-print{background-position:-96px -48px} |
|
360 | .icon-print{background-position:-96px -48px} | |
365 | .icon-camera{background-position:-120px -48px} |
|
361 | .icon-camera{background-position:-120px -48px} | |
366 | .icon-font{background-position:-144px -48px} |
|
362 | .icon-font{background-position:-144px -48px} | |
367 | .icon-bold{background-position:-167px -48px} |
|
363 | .icon-bold{background-position:-167px -48px} | |
368 | .icon-italic{background-position:-192px -48px} |
|
364 | .icon-italic{background-position:-192px -48px} | |
369 | .icon-text-height{background-position:-216px -48px} |
|
365 | .icon-text-height{background-position:-216px -48px} | |
370 | .icon-text-width{background-position:-240px -48px} |
|
366 | .icon-text-width{background-position:-240px -48px} | |
371 | .icon-align-left{background-position:-264px -48px} |
|
367 | .icon-align-left{background-position:-264px -48px} | |
372 | .icon-align-center{background-position:-288px -48px} |
|
368 | .icon-align-center{background-position:-288px -48px} | |
373 | .icon-align-right{background-position:-312px -48px} |
|
369 | .icon-align-right{background-position:-312px -48px} | |
374 | .icon-align-justify{background-position:-336px -48px} |
|
370 | .icon-align-justify{background-position:-336px -48px} | |
375 | .icon-list{background-position:-360px -48px} |
|
371 | .icon-list{background-position:-360px -48px} | |
376 | .icon-indent-left{background-position:-384px -48px} |
|
372 | .icon-indent-left{background-position:-384px -48px} | |
377 | .icon-indent-right{background-position:-408px -48px} |
|
373 | .icon-indent-right{background-position:-408px -48px} | |
378 | .icon-facetime-video{background-position:-432px -48px} |
|
374 | .icon-facetime-video{background-position:-432px -48px} | |
379 | .icon-picture{background-position:-456px -48px} |
|
375 | .icon-picture{background-position:-456px -48px} | |
380 | .icon-pencil{background-position:0 -72px} |
|
376 | .icon-pencil{background-position:0 -72px} | |
381 | .icon-map-marker{background-position:-24px -72px} |
|
377 | .icon-map-marker{background-position:-24px -72px} | |
382 | .icon-adjust{background-position:-48px -72px} |
|
378 | .icon-adjust{background-position:-48px -72px} | |
383 | .icon-tint{background-position:-72px -72px} |
|
379 | .icon-tint{background-position:-72px -72px} | |
384 | .icon-edit{background-position:-96px -72px} |
|
380 | .icon-edit{background-position:-96px -72px} | |
385 | .icon-share{background-position:-120px -72px} |
|
381 | .icon-share{background-position:-120px -72px} | |
386 | .icon-check{background-position:-144px -72px} |
|
382 | .icon-check{background-position:-144px -72px} | |
387 | .icon-move{background-position:-168px -72px} |
|
383 | .icon-move{background-position:-168px -72px} | |
388 | .icon-step-backward{background-position:-192px -72px} |
|
384 | .icon-step-backward{background-position:-192px -72px} | |
389 | .icon-fast-backward{background-position:-216px -72px} |
|
385 | .icon-fast-backward{background-position:-216px -72px} | |
390 | .icon-backward{background-position:-240px -72px} |
|
386 | .icon-backward{background-position:-240px -72px} | |
391 | .icon-play{background-position:-264px -72px} |
|
387 | .icon-play{background-position:-264px -72px} | |
392 | .icon-pause{background-position:-288px -72px} |
|
388 | .icon-pause{background-position:-288px -72px} | |
393 | .icon-stop{background-position:-312px -72px} |
|
389 | .icon-stop{background-position:-312px -72px} | |
394 | .icon-forward{background-position:-336px -72px} |
|
390 | .icon-forward{background-position:-336px -72px} | |
395 | .icon-fast-forward{background-position:-360px -72px} |
|
391 | .icon-fast-forward{background-position:-360px -72px} | |
396 | .icon-step-forward{background-position:-384px -72px} |
|
392 | .icon-step-forward{background-position:-384px -72px} | |
397 | .icon-eject{background-position:-408px -72px} |
|
393 | .icon-eject{background-position:-408px -72px} | |
398 | .icon-chevron-left{background-position:-432px -72px} |
|
394 | .icon-chevron-left{background-position:-432px -72px} | |
399 | .icon-chevron-right{background-position:-456px -72px} |
|
395 | .icon-chevron-right{background-position:-456px -72px} | |
400 | .icon-plus-sign{background-position:0 -96px} |
|
396 | .icon-plus-sign{background-position:0 -96px} | |
401 | .icon-minus-sign{background-position:-24px -96px} |
|
397 | .icon-minus-sign{background-position:-24px -96px} | |
402 | .icon-remove-sign{background-position:-48px -96px} |
|
398 | .icon-remove-sign{background-position:-48px -96px} | |
403 | .icon-ok-sign{background-position:-72px -96px} |
|
399 | .icon-ok-sign{background-position:-72px -96px} | |
404 | .icon-question-sign{background-position:-96px -96px} |
|
400 | .icon-question-sign{background-position:-96px -96px} | |
405 | .icon-info-sign{background-position:-120px -96px} |
|
401 | .icon-info-sign{background-position:-120px -96px} | |
406 | .icon-screenshot{background-position:-144px -96px} |
|
402 | .icon-screenshot{background-position:-144px -96px} | |
407 | .icon-remove-circle{background-position:-168px -96px} |
|
403 | .icon-remove-circle{background-position:-168px -96px} | |
408 | .icon-ok-circle{background-position:-192px -96px} |
|
404 | .icon-ok-circle{background-position:-192px -96px} | |
409 | .icon-ban-circle{background-position:-216px -96px} |
|
405 | .icon-ban-circle{background-position:-216px -96px} | |
410 | .icon-arrow-left{background-position:-240px -96px} |
|
406 | .icon-arrow-left{background-position:-240px -96px} | |
411 | .icon-arrow-right{background-position:-264px -96px} |
|
407 | .icon-arrow-right{background-position:-264px -96px} | |
412 | .icon-arrow-up{background-position:-289px -96px} |
|
408 | .icon-arrow-up{background-position:-289px -96px} | |
413 | .icon-arrow-down{background-position:-312px -96px} |
|
409 | .icon-arrow-down{background-position:-312px -96px} | |
414 | .icon-share-alt{background-position:-336px -96px} |
|
410 | .icon-share-alt{background-position:-336px -96px} | |
415 | .icon-resize-full{background-position:-360px -96px} |
|
411 | .icon-resize-full{background-position:-360px -96px} | |
416 | .icon-resize-small{background-position:-384px -96px} |
|
412 | .icon-resize-small{background-position:-384px -96px} | |
417 | .icon-plus{background-position:-408px -96px} |
|
413 | .icon-plus{background-position:-408px -96px} | |
418 | .icon-minus{background-position:-433px -96px} |
|
414 | .icon-minus{background-position:-433px -96px} | |
419 | .icon-asterisk{background-position:-456px -96px} |
|
415 | .icon-asterisk{background-position:-456px -96px} | |
420 | .icon-exclamation-sign{background-position:0 -120px} |
|
416 | .icon-exclamation-sign{background-position:0 -120px} | |
421 | .icon-gift{background-position:-24px -120px} |
|
417 | .icon-gift{background-position:-24px -120px} | |
422 | .icon-leaf{background-position:-48px -120px} |
|
418 | .icon-leaf{background-position:-48px -120px} | |
423 | .icon-fire{background-position:-72px -120px} |
|
419 | .icon-fire{background-position:-72px -120px} | |
424 | .icon-eye-open{background-position:-96px -120px} |
|
420 | .icon-eye-open{background-position:-96px -120px} | |
425 | .icon-eye-close{background-position:-120px -120px} |
|
421 | .icon-eye-close{background-position:-120px -120px} | |
426 | .icon-warning-sign{background-position:-144px -120px} |
|
422 | .icon-warning-sign{background-position:-144px -120px} | |
427 | .icon-plane{background-position:-168px -120px} |
|
423 | .icon-plane{background-position:-168px -120px} | |
428 | .icon-calendar{background-position:-192px -120px} |
|
424 | .icon-calendar{background-position:-192px -120px} | |
429 | .icon-random{background-position:-216px -120px;width:16px} |
|
425 | .icon-random{background-position:-216px -120px;width:16px} | |
430 | .icon-comment{background-position:-240px -120px} |
|
426 | .icon-comment{background-position:-240px -120px} | |
431 | .icon-magnet{background-position:-264px -120px} |
|
427 | .icon-magnet{background-position:-264px -120px} | |
432 | .icon-chevron-up{background-position:-288px -120px} |
|
428 | .icon-chevron-up{background-position:-288px -120px} | |
433 | .icon-chevron-down{background-position:-313px -119px} |
|
429 | .icon-chevron-down{background-position:-313px -119px} | |
434 | .icon-retweet{background-position:-336px -120px} |
|
430 | .icon-retweet{background-position:-336px -120px} | |
435 | .icon-shopping-cart{background-position:-360px -120px} |
|
431 | .icon-shopping-cart{background-position:-360px -120px} | |
436 | .icon-folder-close{background-position:-384px -120px;width:16px} |
|
432 | .icon-folder-close{background-position:-384px -120px;width:16px} | |
437 | .icon-folder-open{background-position:-408px -120px;width:16px} |
|
433 | .icon-folder-open{background-position:-408px -120px;width:16px} | |
438 | .icon-resize-vertical{background-position:-432px -119px} |
|
434 | .icon-resize-vertical{background-position:-432px -119px} | |
439 | .icon-resize-horizontal{background-position:-456px -118px} |
|
435 | .icon-resize-horizontal{background-position:-456px -118px} | |
440 | .icon-hdd{background-position:0 -144px} |
|
436 | .icon-hdd{background-position:0 -144px} | |
441 | .icon-bullhorn{background-position:-24px -144px} |
|
437 | .icon-bullhorn{background-position:-24px -144px} | |
442 | .icon-bell{background-position:-48px -144px} |
|
438 | .icon-bell{background-position:-48px -144px} | |
443 | .icon-certificate{background-position:-72px -144px} |
|
439 | .icon-certificate{background-position:-72px -144px} | |
444 | .icon-thumbs-up{background-position:-96px -144px} |
|
440 | .icon-thumbs-up{background-position:-96px -144px} | |
445 | .icon-thumbs-down{background-position:-120px -144px} |
|
441 | .icon-thumbs-down{background-position:-120px -144px} | |
446 | .icon-hand-right{background-position:-144px -144px} |
|
442 | .icon-hand-right{background-position:-144px -144px} | |
447 | .icon-hand-left{background-position:-168px -144px} |
|
443 | .icon-hand-left{background-position:-168px -144px} | |
448 | .icon-hand-up{background-position:-192px -144px} |
|
444 | .icon-hand-up{background-position:-192px -144px} | |
449 | .icon-hand-down{background-position:-216px -144px} |
|
445 | .icon-hand-down{background-position:-216px -144px} | |
450 | .icon-circle-arrow-right{background-position:-240px -144px} |
|
446 | .icon-circle-arrow-right{background-position:-240px -144px} | |
451 | .icon-circle-arrow-left{background-position:-264px -144px} |
|
447 | .icon-circle-arrow-left{background-position:-264px -144px} | |
452 | .icon-circle-arrow-up{background-position:-288px -144px} |
|
448 | .icon-circle-arrow-up{background-position:-288px -144px} | |
453 | .icon-circle-arrow-down{background-position:-312px -144px} |
|
449 | .icon-circle-arrow-down{background-position:-312px -144px} | |
454 | .icon-globe{background-position:-336px -144px} |
|
450 | .icon-globe{background-position:-336px -144px} | |
455 | .icon-wrench{background-position:-360px -144px} |
|
451 | .icon-wrench{background-position:-360px -144px} | |
456 | .icon-tasks{background-position:-384px -144px} |
|
452 | .icon-tasks{background-position:-384px -144px} | |
457 | .icon-filter{background-position:-408px -144px} |
|
453 | .icon-filter{background-position:-408px -144px} | |
458 | .icon-briefcase{background-position:-432px -144px} |
|
454 | .icon-briefcase{background-position:-432px -144px} | |
459 | .icon-fullscreen{background-position:-456px -144px} |
|
455 | .icon-fullscreen{background-position:-456px -144px} | |
460 | .dropup,.dropdown{position:relative} |
|
456 | .dropup,.dropdown{position:relative} | |
461 | .dropdown-toggle{*margin-bottom:-3px} |
|
457 | .dropdown-toggle{*margin-bottom:-3px} | |
462 | .dropdown-toggle:active,.open .dropdown-toggle{outline:0} |
|
458 | .dropdown-toggle:active,.open .dropdown-toggle{outline:0} | |
463 | .caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""} |
|
459 | .caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""} | |
464 | .dropdown .caret{margin-top:8px;margin-left:2px} |
|
460 | .dropdown .caret{margin-top:8px;margin-left:2px} | |
465 | .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto} |
|
461 | .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto} | |
466 | .dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff} |
|
462 | .dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff} | |
467 | .dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap} |
|
463 | .dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap} | |
468 | .dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{text-decoration:none;color:#fff;background-color:#0081c2;background-image:-moz-linear-gradient(top, #08c, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0077b3));background-image:-webkit-linear-gradient(top, #08c, #0077b3);background-image:-o-linear-gradient(top, #08c, #0077b3);background-image:linear-gradient(to bottom, #08c, #0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0)} |
|
464 | .dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{text-decoration:none;color:#fff;background-color:#0081c2;background-image:-moz-linear-gradient(top, #08c, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0077b3));background-image:-webkit-linear-gradient(top, #08c, #0077b3);background-image:-o-linear-gradient(top, #08c, #0077b3);background-image:linear-gradient(to bottom, #08c, #0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0)} | |
469 | .dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#0081c2;background-image:-moz-linear-gradient(top, #08c, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0077b3));background-image:-webkit-linear-gradient(top, #08c, #0077b3);background-image:-o-linear-gradient(top, #08c, #0077b3);background-image:linear-gradient(to bottom, #08c, #0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0)} |
|
465 | .dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#0081c2;background-image:-moz-linear-gradient(top, #08c, #0077b3);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#0077b3));background-image:-webkit-linear-gradient(top, #08c, #0077b3);background-image:-o-linear-gradient(top, #08c, #0077b3);background-image:linear-gradient(to bottom, #08c, #0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0)} | |
470 | .dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999} |
|
466 | .dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999} | |
471 | .dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:default} |
|
467 | .dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:default} | |
472 | .open{*z-index:1000}.open>.dropdown-menu{display:block} |
|
468 | .open{*z-index:1000}.open>.dropdown-menu{display:block} | |
473 | .dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990} |
|
469 | .dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990} | |
474 | .pull-right>.dropdown-menu{right:0;left:auto} |
|
470 | .pull-right>.dropdown-menu{right:0;left:auto} | |
475 | .dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""} |
|
471 | .dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""} | |
476 | .dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px} |
|
472 | .dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px} | |
477 | .dropdown-submenu{position:relative} |
|
473 | .dropdown-submenu{position:relative} | |
478 | .dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;border-radius:0 6px 6px 6px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px} |
|
474 | .dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;border-radius:0 6px 6px 6px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px} | |
479 | .dropdown-submenu:hover>.dropdown-menu{display:block} |
|
475 | .dropdown-submenu:hover>.dropdown-menu{display:block} | |
480 | .dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;border-radius:5px 5px 5px 0;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0} |
|
476 | .dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;border-radius:5px 5px 5px 0;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0} | |
481 | .dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#ccc;margin-top:5px;margin-right:-10px} |
|
477 | .dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#ccc;margin-top:5px;margin-right:-10px} | |
482 | .dropdown-submenu:hover>a:after{border-left-color:#fff} |
|
478 | .dropdown-submenu:hover>a:after{border-left-color:#fff} | |
483 | .dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;border-radius:6px 0 6px 6px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px} |
|
479 | .dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;border-radius:6px 0 6px 6px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px} | |
484 | .dropdown .dropdown-menu .nav-header{padding-left:20px;padding-right:20px} |
|
480 | .dropdown .dropdown-menu .nav-header{padding-left:20px;padding-right:20px} | |
485 | .typeahead{z-index:1051;margin-top:2px;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} |
|
481 | .typeahead{z-index:1051;margin-top:2px;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} | |
486 | .well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)} |
|
482 | .well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)} | |
487 | .well-large{padding:24px;border-radius:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px} |
|
483 | .well-large{padding:24px;border-radius:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px} | |
488 | .well-small{padding:9px;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} |
|
484 | .well-small{padding:9px;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} | |
489 | .fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1} |
|
485 | .fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1} | |
490 | .collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto} |
|
486 | .collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto} | |
491 | .close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)} |
|
487 | .close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)} | |
492 | button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none} |
|
488 | button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none} | |
493 | .btn{display:inline-block;*display:inline;*zoom:1;padding:4px 12px;margin-bottom:0;font-size:13px;line-height:20px;text-align:center;vertical-align:middle;cursor:pointer;color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#f5f5f5;background-image:-moz-linear-gradient(top, #fff, #e6e6e6);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#e6e6e6));background-image:-webkit-linear-gradient(top, #fff, #e6e6e6);background-image:-o-linear-gradient(top, #fff, #e6e6e6);background-image:linear-gradient(to bottom, #fff, #e6e6e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#e6e6e6;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border:1px solid #ccc;*border:0;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*margin-left:.3em;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9} |
|
489 | .btn{display:inline-block;*display:inline;*zoom:1;padding:4px 12px;margin-bottom:0;font-size:13px;line-height:20px;text-align:center;vertical-align:middle;cursor:pointer;color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#f5f5f5;background-image:-moz-linear-gradient(top, #fff, #e6e6e6);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#e6e6e6));background-image:-webkit-linear-gradient(top, #fff, #e6e6e6);background-image:-o-linear-gradient(top, #fff, #e6e6e6);background-image:linear-gradient(to bottom, #fff, #e6e6e6);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#e6e6e6;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border:1px solid #ccc;*border:0;border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*margin-left:.3em;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9} | |
494 | .btn:active,.btn.active{background-color:#ccc \9} |
|
490 | .btn:active,.btn.active{background-color:#ccc \9} | |
495 | .btn:first-child{*margin-left:0} |
|
491 | .btn:first-child{*margin-left:0} | |
496 | .btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear} |
|
492 | .btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear} | |
497 | .btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px} |
|
493 | .btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px} | |
498 | .btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)} |
|
494 | .btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)} | |
499 | .btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none} |
|
495 | .btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none} | |
500 | .btn-large{padding:11px 19px;font-size:16.25px;border-radius:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px} |
|
496 | .btn-large{padding:11px 19px;font-size:16.25px;border-radius:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px} | |
501 | .btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px} |
|
497 | .btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px} | |
502 | .btn-small{padding:2px 10px;font-size:11.049999999999999px;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} |
|
498 | .btn-small{padding:2px 10px;font-size:11.049999999999999px;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} | |
503 | .btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0} |
|
499 | .btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0} | |
504 | .btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px} |
|
500 | .btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px} | |
505 | .btn-mini{padding:0 6px;font-size:9.75px;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} |
|
501 | .btn-mini{padding:0 6px;font-size:9.75px;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} | |
506 | .btn-block{display:block;width:100%;padding-left:0;padding-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} |
|
502 | .btn-block{display:block;width:100%;padding-left:0;padding-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} | |
507 | .btn-block+.btn-block{margin-top:5px} |
|
503 | .btn-block+.btn-block{margin-top:5px} | |
508 | input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%} |
|
504 | input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%} | |
509 | .btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)} |
|
505 | .btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)} | |
510 | .btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #08c, #04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#04c;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3} |
|
506 | .btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;background-image:-moz-linear-gradient(top, #08c, #04c);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#08c), to(#04c));background-image:-webkit-linear-gradient(top, #08c, #04c);background-image:-o-linear-gradient(top, #08c, #04c);background-image:linear-gradient(to bottom, #08c, #04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#04c;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3} | |
511 | .btn-primary:active,.btn-primary.active{background-color:#039 \9} |
|
507 | .btn-primary:active,.btn-primary.active{background-color:#039 \9} | |
512 | .btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(to bottom, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#f89406;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505} |
|
508 | .btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(to bottom, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#f89406;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505} | |
513 | .btn-warning:active,.btn-warning.active{background-color:#c67605 \9} |
|
509 | .btn-warning:active,.btn-warning.active{background-color:#c67605 \9} | |
514 | .btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;background-image:-moz-linear-gradient(top, #ee5f5b, #bd362f);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));background-image:-webkit-linear-gradient(top, #ee5f5b, #bd362f);background-image:-o-linear-gradient(top, #ee5f5b, #bd362f);background-image:linear-gradient(to bottom, #ee5f5b, #bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#bd362f;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a} |
|
510 | .btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;background-image:-moz-linear-gradient(top, #ee5f5b, #bd362f);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));background-image:-webkit-linear-gradient(top, #ee5f5b, #bd362f);background-image:-o-linear-gradient(top, #ee5f5b, #bd362f);background-image:linear-gradient(to bottom, #ee5f5b, #bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#bd362f;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a} | |
515 | .btn-danger:active,.btn-danger.active{background-color:#942a25 \9} |
|
511 | .btn-danger:active,.btn-danger.active{background-color:#942a25 \9} | |
516 | .btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;background-image:-moz-linear-gradient(top, #62c462, #51a351);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));background-image:-webkit-linear-gradient(top, #62c462, #51a351);background-image:-o-linear-gradient(top, #62c462, #51a351);background-image:linear-gradient(to bottom, #62c462, #51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#51a351;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249} |
|
512 | .btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;background-image:-moz-linear-gradient(top, #62c462, #51a351);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));background-image:-webkit-linear-gradient(top, #62c462, #51a351);background-image:-o-linear-gradient(top, #62c462, #51a351);background-image:linear-gradient(to bottom, #62c462, #51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#51a351;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249} | |
517 | .btn-success:active,.btn-success.active{background-color:#408140 \9} |
|
513 | .btn-success:active,.btn-success.active{background-color:#408140 \9} | |
518 | .btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;background-image:-moz-linear-gradient(top, #5bc0de, #2f96b4);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));background-image:-webkit-linear-gradient(top, #5bc0de, #2f96b4);background-image:-o-linear-gradient(top, #5bc0de, #2f96b4);background-image:linear-gradient(to bottom, #5bc0de, #2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#2f96b4;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0} |
|
514 | .btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;background-image:-moz-linear-gradient(top, #5bc0de, #2f96b4);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));background-image:-webkit-linear-gradient(top, #5bc0de, #2f96b4);background-image:-o-linear-gradient(top, #5bc0de, #2f96b4);background-image:linear-gradient(to bottom, #5bc0de, #2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#2f96b4;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0} | |
519 | .btn-info:active,.btn-info.active{background-color:#24748c \9} |
|
515 | .btn-info:active,.btn-info.active{background-color:#24748c \9} | |
520 | .btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;background-image:-moz-linear-gradient(top, #444, #222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#444), to(#222));background-image:-webkit-linear-gradient(top, #444, #222);background-image:-o-linear-gradient(top, #444, #222);background-image:linear-gradient(to bottom, #444, #222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#222;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515} |
|
516 | .btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;background-image:-moz-linear-gradient(top, #444, #222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#444), to(#222));background-image:-webkit-linear-gradient(top, #444, #222);background-image:-o-linear-gradient(top, #444, #222);background-image:linear-gradient(to bottom, #444, #222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#222;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515} | |
521 | .btn-inverse:active,.btn-inverse.active{background-color:#080808 \9} |
|
517 | .btn-inverse:active,.btn-inverse.active{background-color:#080808 \9} | |
522 | button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0} |
|
518 | button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0} | |
523 | button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px} |
|
519 | button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px} | |
524 | button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px} |
|
520 | button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px} | |
525 | button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px} |
|
521 | button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px} | |
526 | .btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none} |
|
522 | .btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none} | |
527 | .btn-link{border-color:transparent;cursor:pointer;color:#08c;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} |
|
523 | .btn-link{border-color:transparent;cursor:pointer;color:#08c;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} | |
528 | .btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent} |
|
524 | .btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent} | |
529 | .btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333;text-decoration:none} |
|
525 | .btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333;text-decoration:none} | |
530 | .btn-group{position:relative;display:inline-block;*display:inline;*zoom:1;font-size:0;vertical-align:middle;white-space:nowrap;*margin-left:.3em}.btn-group:first-child{*margin-left:0} |
|
526 | .btn-group{position:relative;display:inline-block;*display:inline;*zoom:1;font-size:0;vertical-align:middle;white-space:nowrap;*margin-left:.3em}.btn-group:first-child{*margin-left:0} | |
531 | .btn-group+.btn-group{margin-left:5px} |
|
527 | .btn-group+.btn-group{margin-left:5px} | |
532 | .btn-toolbar{font-size:0;margin-top:10px;margin-bottom:10px}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px} |
|
528 | .btn-toolbar{font-size:0;margin-top:10px;margin-bottom:10px}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px} | |
533 | .btn-group>.btn{position:relative;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} |
|
529 | .btn-group>.btn{position:relative;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} | |
534 | .btn-group>.btn+.btn{margin-left:-1px} |
|
530 | .btn-group>.btn+.btn{margin-left:-1px} | |
535 | .btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:13px} |
|
531 | .btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:13px} | |
536 | .btn-group>.btn-mini{font-size:9.75px} |
|
532 | .btn-group>.btn-mini{font-size:9.75px} | |
537 | .btn-group>.btn-small{font-size:11.049999999999999px} |
|
533 | .btn-group>.btn-small{font-size:11.049999999999999px} | |
538 | .btn-group>.btn-large{font-size:16.25px} |
|
534 | .btn-group>.btn-large{font-size:16.25px} | |
539 | .btn-group>.btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px} |
|
535 | .btn-group>.btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px} | |
540 | .btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px} |
|
536 | .btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px} | |
541 | .btn-group>.btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px} |
|
537 | .btn-group>.btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px} | |
542 | .btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px} |
|
538 | .btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px} | |
543 | .btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2} |
|
539 | .btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2} | |
544 | .btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0} |
|
540 | .btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0} | |
545 | .btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);*padding-top:5px;*padding-bottom:5px} |
|
541 | .btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);*padding-top:5px;*padding-bottom:5px} | |
546 | .btn-group>.btn-mini+.dropdown-toggle{padding-left:5px;padding-right:5px;*padding-top:2px;*padding-bottom:2px} |
|
542 | .btn-group>.btn-mini+.dropdown-toggle{padding-left:5px;padding-right:5px;*padding-top:2px;*padding-bottom:2px} | |
547 | .btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px} |
|
543 | .btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px} | |
548 | .btn-group>.btn-large+.dropdown-toggle{padding-left:12px;padding-right:12px;*padding-top:7px;*padding-bottom:7px} |
|
544 | .btn-group>.btn-large+.dropdown-toggle{padding-left:12px;padding-right:12px;*padding-top:7px;*padding-bottom:7px} | |
549 | .btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)} |
|
545 | .btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)} | |
550 | .btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6} |
|
546 | .btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6} | |
551 | .btn-group.open .btn-primary.dropdown-toggle{background-color:#04c} |
|
547 | .btn-group.open .btn-primary.dropdown-toggle{background-color:#04c} | |
552 | .btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406} |
|
548 | .btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406} | |
553 | .btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f} |
|
549 | .btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f} | |
554 | .btn-group.open .btn-success.dropdown-toggle{background-color:#51a351} |
|
550 | .btn-group.open .btn-success.dropdown-toggle{background-color:#51a351} | |
555 | .btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4} |
|
551 | .btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4} | |
556 | .btn-group.open .btn-inverse.dropdown-toggle{background-color:#222} |
|
552 | .btn-group.open .btn-inverse.dropdown-toggle{background-color:#222} | |
557 | .btn .caret{margin-top:8px;margin-left:0} |
|
553 | .btn .caret{margin-top:8px;margin-left:0} | |
558 | .btn-large .caret{margin-top:6px} |
|
554 | .btn-large .caret{margin-top:6px} | |
559 | .btn-large .caret{border-left-width:5px;border-right-width:5px;border-top-width:5px} |
|
555 | .btn-large .caret{border-left-width:5px;border-right-width:5px;border-top-width:5px} | |
560 | .btn-mini .caret,.btn-small .caret{margin-top:8px} |
|
556 | .btn-mini .caret,.btn-small .caret{margin-top:8px} | |
561 | .dropup .btn-large .caret{border-bottom-width:5px} |
|
557 | .dropup .btn-large .caret{border-bottom-width:5px} | |
562 | .btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff} |
|
558 | .btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff} | |
563 | .btn-group-vertical{display:inline-block;*display:inline;*zoom:1} |
|
559 | .btn-group-vertical{display:inline-block;*display:inline;*zoom:1} | |
564 | .btn-group-vertical>.btn{display:block;float:none;max-width:100%;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} |
|
560 | .btn-group-vertical>.btn{display:block;float:none;max-width:100%;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} | |
565 | .btn-group-vertical>.btn+.btn{margin-left:0;margin-top:-1px} |
|
561 | .btn-group-vertical>.btn+.btn{margin-left:0;margin-top:-1px} | |
566 | .btn-group-vertical>.btn:first-child{border-radius:4px 4px 0 0;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0} |
|
562 | .btn-group-vertical>.btn:first-child{border-radius:4px 4px 0 0;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0} | |
567 | .btn-group-vertical>.btn:last-child{border-radius:0 0 4px 4px;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px} |
|
563 | .btn-group-vertical>.btn:last-child{border-radius:0 0 4px 4px;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px} | |
568 | .btn-group-vertical>.btn-large:first-child{border-radius:6px 6px 0 0;-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0} |
|
564 | .btn-group-vertical>.btn-large:first-child{border-radius:6px 6px 0 0;-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0} | |
569 | .btn-group-vertical>.btn-large:last-child{border-radius:0 0 6px 6px;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px} |
|
565 | .btn-group-vertical>.btn-large:last-child{border-radius:0 0 6px 6px;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px} | |
570 | .alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} |
|
566 | .alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} | |
571 | .alert,.alert h4{color:#c09853} |
|
567 | .alert,.alert h4{color:#c09853} | |
572 | .alert h4{margin:0} |
|
568 | .alert h4{margin:0} | |
573 | .alert .close{position:relative;top:-2px;right:-21px;line-height:20px} |
|
569 | .alert .close{position:relative;top:-2px;right:-21px;line-height:20px} | |
574 | .alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#468847} |
|
570 | .alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#468847} | |
575 | .alert-success h4{color:#468847} |
|
571 | .alert-success h4{color:#468847} | |
576 | .alert-danger,.alert-error{background-color:#f2dede;border-color:#eed3d7;color:#b94a48} |
|
572 | .alert-danger,.alert-error{background-color:#f2dede;border-color:#eed3d7;color:#b94a48} | |
577 | .alert-danger h4,.alert-error h4{color:#b94a48} |
|
573 | .alert-danger h4,.alert-error h4{color:#b94a48} | |
578 | .alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#3a87ad} |
|
574 | .alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#3a87ad} | |
579 | .alert-info h4{color:#3a87ad} |
|
575 | .alert-info h4{color:#3a87ad} | |
580 | .alert-block{padding-top:14px;padding-bottom:14px} |
|
576 | .alert-block{padding-top:14px;padding-bottom:14px} | |
581 | .alert-block>p,.alert-block>ul{margin-bottom:0} |
|
577 | .alert-block>p,.alert-block>ul{margin-bottom:0} | |
582 | .alert-block p+p{margin-top:5px} |
|
578 | .alert-block p+p{margin-top:5px} | |
583 | .nav{margin-left:0;margin-bottom:20px;list-style:none} |
|
579 | .nav{margin-left:0;margin-bottom:20px;list-style:none} | |
584 | .nav>li>a{display:block} |
|
580 | .nav>li>a{display:block} | |
585 | .nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee} |
|
581 | .nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee} | |
586 | .nav>li>a>img{max-width:none} |
|
582 | .nav>li>a>img{max-width:none} | |
587 | .nav>.pull-right{float:right} |
|
583 | .nav>.pull-right{float:right} | |
588 | .nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase} |
|
584 | .nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase} | |
589 | .nav li+.nav-header{margin-top:9px} |
|
585 | .nav li+.nav-header{margin-top:9px} | |
590 | .nav-list{padding-left:15px;padding-right:15px;margin-bottom:0} |
|
586 | .nav-list{padding-left:15px;padding-right:15px;margin-bottom:0} | |
591 | .nav-list>li>a,.nav-list .nav-header{margin-left:-15px;margin-right:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)} |
|
587 | .nav-list>li>a,.nav-list .nav-header{margin-left:-15px;margin-right:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)} | |
592 | .nav-list>li>a{padding:3px 15px} |
|
588 | .nav-list>li>a{padding:3px 15px} | |
593 | .nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c} |
|
589 | .nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c} | |
594 | .nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px} |
|
590 | .nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px} | |
595 | .nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff} |
|
591 | .nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff} | |
596 | .nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:"";line-height:0} |
|
592 | .nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:"";line-height:0} | |
597 | .nav-tabs:after,.nav-pills:after{clear:both} |
|
593 | .nav-tabs:after,.nav-pills:after{clear:both} | |
598 | .nav-tabs>li,.nav-pills>li{float:left} |
|
594 | .nav-tabs>li,.nav-pills>li{float:left} | |
599 | .nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px} |
|
595 | .nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px} | |
600 | .nav-tabs{border-bottom:1px solid #ddd} |
|
596 | .nav-tabs{border-bottom:1px solid #ddd} | |
601 | .nav-tabs>li{margin-bottom:-1px} |
|
597 | .nav-tabs>li{margin-bottom:-1px} | |
602 | .nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;border-radius:4px 4px 0 0;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd} |
|
598 | .nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;border-radius:4px 4px 0 0;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd} | |
603 | .nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default} |
|
599 | .nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default} | |
604 | .nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;border-radius:5px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px} |
|
600 | .nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;border-radius:5px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px} | |
605 | .nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#fff;background-color:#08c} |
|
601 | .nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#fff;background-color:#08c} | |
606 | .nav-stacked>li{float:none} |
|
602 | .nav-stacked>li{float:none} | |
607 | .nav-stacked>li>a{margin-right:0} |
|
603 | .nav-stacked>li>a{margin-right:0} | |
608 | .nav-tabs.nav-stacked{border-bottom:0} |
|
604 | .nav-tabs.nav-stacked{border-bottom:0} | |
609 | .nav-tabs.nav-stacked>li>a{border:1px solid #ddd;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} |
|
605 | .nav-tabs.nav-stacked>li>a{border:1px solid #ddd;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} | |
610 | .nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px} |
|
606 | .nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px} | |
611 | .nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px} |
|
607 | .nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px} | |
612 | .nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{border-color:#ddd;z-index:2} |
|
608 | .nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{border-color:#ddd;z-index:2} | |
613 | .nav-pills.nav-stacked>li>a{margin-bottom:3px} |
|
609 | .nav-pills.nav-stacked>li>a{margin-bottom:3px} | |
614 | .nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px} |
|
610 | .nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px} | |
615 | .nav-tabs .dropdown-menu{border-radius:0 0 6px 6px;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px} |
|
611 | .nav-tabs .dropdown-menu{border-radius:0 0 6px 6px;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px} | |
616 | .nav-pills .dropdown-menu{border-radius:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px} |
|
612 | .nav-pills .dropdown-menu{border-radius:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px} | |
617 | .nav .dropdown-toggle .caret{border-top-color:#08c;border-bottom-color:#08c;margin-top:6px} |
|
613 | .nav .dropdown-toggle .caret{border-top-color:#08c;border-bottom-color:#08c;margin-top:6px} | |
618 | .nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580} |
|
614 | .nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580} | |
619 | .nav-tabs .dropdown-toggle .caret{margin-top:8px} |
|
615 | .nav-tabs .dropdown-toggle .caret{margin-top:8px} | |
620 | .nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff} |
|
616 | .nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff} | |
621 | .nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555} |
|
617 | .nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555} | |
622 | .nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer} |
|
618 | .nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer} | |
623 | .nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999} |
|
619 | .nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999} | |
624 | .nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)} |
|
620 | .nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)} | |
625 | .tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999} |
|
621 | .tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999} | |
626 | .tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;content:"";line-height:0} |
|
622 | .tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;content:"";line-height:0} | |
627 | .tabbable:after{clear:both} |
|
623 | .tabbable:after{clear:both} | |
628 | .tab-content{overflow:auto} |
|
624 | .tab-content{overflow:auto} | |
629 | .tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0} |
|
625 | .tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0} | |
630 | .tab-content>.tab-pane,.pill-content>.pill-pane{display:none} |
|
626 | .tab-content>.tab-pane,.pill-content>.pill-pane{display:none} | |
631 | .tab-content>.active,.pill-content>.active{display:block} |
|
627 | .tab-content>.active,.pill-content>.active{display:block} | |
632 | .tabs-below>.nav-tabs{border-top:1px solid #ddd} |
|
628 | .tabs-below>.nav-tabs{border-top:1px solid #ddd} | |
633 | .tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0} |
|
629 | .tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0} | |
634 | .tabs-below>.nav-tabs>li>a{border-radius:0 0 4px 4px;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-bottom-color:transparent;border-top-color:#ddd} |
|
630 | .tabs-below>.nav-tabs>li>a{border-radius:0 0 4px 4px;-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-bottom-color:transparent;border-top-color:#ddd} | |
635 | .tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd} |
|
631 | .tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd} | |
636 | .tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none} |
|
632 | .tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none} | |
637 | .tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px} |
|
633 | .tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px} | |
638 | .tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd} |
|
634 | .tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd} | |
639 | .tabs-left>.nav-tabs>li>a{margin-right:-1px;border-radius:4px 0 0 4px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px} |
|
635 | .tabs-left>.nav-tabs>li>a{margin-right:-1px;border-radius:4px 0 0 4px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px} | |
640 | .tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee} |
|
636 | .tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee} | |
641 | .tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff} |
|
637 | .tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff} | |
642 | .tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd} |
|
638 | .tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd} | |
643 | .tabs-right>.nav-tabs>li>a{margin-left:-1px;border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0} |
|
639 | .tabs-right>.nav-tabs>li>a{margin-left:-1px;border-radius:0 4px 4px 0;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0} | |
644 | .tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd} |
|
640 | .tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd} | |
645 | .tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff} |
|
641 | .tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff} | |
646 | .nav>.disabled>a{color:#999} |
|
642 | .nav>.disabled>a{color:#999} | |
647 | .nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;background-color:transparent;cursor:default} |
|
643 | .nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;background-color:transparent;cursor:default} | |
648 | .navbar{overflow:visible;margin-bottom:20px;*position:relative;*z-index:2} |
|
644 | .navbar{overflow:visible;margin-bottom:20px;*position:relative;*z-index:2} | |
649 | .navbar-inner{min-height:36px;padding-left:20px;padding-right:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top, #fff, #f2f2f2);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#f2f2f2));background-image:-webkit-linear-gradient(top, #fff, #f2f2f2);background-image:-o-linear-gradient(top, #fff, #f2f2f2);background-image:linear-gradient(to bottom, #fff, #f2f2f2);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065);*zoom:1}.navbar-inner:before,.navbar-inner:after{display:table;content:"";line-height:0} |
|
645 | .navbar-inner{min-height:36px;padding-left:20px;padding-right:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top, #fff, #f2f2f2);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#f2f2f2));background-image:-webkit-linear-gradient(top, #fff, #f2f2f2);background-image:-o-linear-gradient(top, #fff, #f2f2f2);background-image:linear-gradient(to bottom, #fff, #f2f2f2);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065);*zoom:1}.navbar-inner:before,.navbar-inner:after{display:table;content:"";line-height:0} | |
650 | .navbar-inner:after{clear:both} |
|
646 | .navbar-inner:after{clear:both} | |
651 | .navbar .container{width:auto} |
|
647 | .navbar .container{width:auto} | |
652 | .nav-collapse.collapse{height:auto;overflow:visible} |
|
648 | .nav-collapse.collapse{height:auto;overflow:visible} | |
653 | .navbar .brand{float:left;display:block;padding:8px 20px 8px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none} |
|
649 | .navbar .brand{float:left;display:block;padding:8px 20px 8px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none} | |
654 | .navbar-text{margin-bottom:0;line-height:36px;color:#777} |
|
650 | .navbar-text{margin-bottom:0;line-height:36px;color:#777} | |
655 | .navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333} |
|
651 | .navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333} | |
656 | .navbar .divider-vertical{height:36px;margin:0 9px;border-left:1px solid #f2f2f2;border-right:1px solid #fff} |
|
652 | .navbar .divider-vertical{height:36px;margin:0 9px;border-left:1px solid #f2f2f2;border-right:1px solid #fff} | |
657 | .navbar .btn,.navbar .btn-group{margin-top:3px} |
|
653 | .navbar .btn,.navbar .btn-group{margin-top:3px} | |
658 | .navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0} |
|
654 | .navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0} | |
659 | .navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;content:"";line-height:0} |
|
655 | .navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;content:"";line-height:0} | |
660 | .navbar-form:after{clear:both} |
|
656 | .navbar-form:after{clear:both} | |
661 | .navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:3px} |
|
657 | .navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:3px} | |
662 | .navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0} |
|
658 | .navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0} | |
663 | .navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px} |
|
659 | .navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px} | |
664 | .navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0} |
|
660 | .navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0} | |
665 | .navbar-search{position:relative;float:left;margin-top:3px;margin-bottom:0}.navbar-search .search-query{margin-bottom:0;padding:4px 14px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;border-radius:15px;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px} |
|
661 | .navbar-search{position:relative;float:left;margin-top:3px;margin-bottom:0}.navbar-search .search-query{margin-bottom:0;padding:4px 14px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;border-radius:15px;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px} | |
666 | .navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} |
|
662 | .navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} | |
667 | .navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0} |
|
663 | .navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0} | |
668 | .navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px} |
|
664 | .navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px} | |
669 | .navbar-fixed-bottom .navbar-inner{border-width:1px 0 0} |
|
665 | .navbar-fixed-bottom .navbar-inner{border-width:1px 0 0} | |
670 | .navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-left:0;padding-right:0;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} |
|
666 | .navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-left:0;padding-right:0;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} | |
671 | .navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px} |
|
667 | .navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px} | |
672 | .navbar-fixed-top{top:0} |
|
668 | .navbar-fixed-top{top:0} | |
673 | .navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,.1);box-shadow:0 1px 10px rgba(0,0,0,.1)} |
|
669 | .navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,.1);box-shadow:0 1px 10px rgba(0,0,0,.1)} | |
674 | .navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,.1);box-shadow:0 -1px 10px rgba(0,0,0,.1)} |
|
670 | .navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,.1);box-shadow:0 -1px 10px rgba(0,0,0,.1)} | |
675 | .navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0} |
|
671 | .navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0} | |
676 | .navbar .nav.pull-right{float:right;margin-right:0} |
|
672 | .navbar .nav.pull-right{float:right;margin-right:0} | |
677 | .navbar .nav>li{float:left} |
|
673 | .navbar .nav>li{float:left} | |
678 | .navbar .nav>li>a{float:none;padding:8px 15px 8px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff} |
|
674 | .navbar .nav>li>a{float:none;padding:8px 15px 8px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff} | |
679 | .navbar .nav .dropdown-toggle .caret{margin-top:8px} |
|
675 | .navbar .nav .dropdown-toggle .caret{margin-top:8px} | |
680 | .navbar .nav>li>a:focus,.navbar .nav>li>a:hover{background-color:transparent;color:#333;text-decoration:none} |
|
676 | .navbar .nav>li>a:focus,.navbar .nav>li>a:hover{background-color:transparent;color:#333;text-decoration:none} | |
681 | .navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)} |
|
677 | .navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)} | |
682 | .navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-left:5px;margin-right:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;background-image:-moz-linear-gradient(top, #f2f2f2, #e5e5e5);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));background-image:-webkit-linear-gradient(top, #f2f2f2, #e5e5e5);background-image:-o-linear-gradient(top, #f2f2f2, #e5e5e5);background-image:linear-gradient(to bottom, #f2f2f2, #e5e5e5);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#e5e5e5;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9} |
|
678 | .navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-left:5px;margin-right:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;background-image:-moz-linear-gradient(top, #f2f2f2, #e5e5e5);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));background-image:-webkit-linear-gradient(top, #f2f2f2, #e5e5e5);background-image:-o-linear-gradient(top, #f2f2f2, #e5e5e5);background-image:linear-gradient(to bottom, #f2f2f2, #e5e5e5);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#e5e5e5;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9} | |
683 | .navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9} |
|
679 | .navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9} | |
684 | .navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)} |
|
680 | .navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)} | |
685 | .btn-navbar .icon-bar+.icon-bar{margin-top:3px} |
|
681 | .btn-navbar .icon-bar+.icon-bar{margin-top:3px} | |
686 | .navbar .nav>li>.dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute;top:-7px;left:9px} |
|
682 | .navbar .nav>li>.dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);position:absolute;top:-7px;left:9px} | |
687 | .navbar .nav>li>.dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;top:-6px;left:10px} |
|
683 | .navbar .nav>li>.dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;top:-6px;left:10px} | |
688 | .navbar-fixed-bottom .nav>li>.dropdown-menu:before{border-top:7px solid #ccc;border-top-color:rgba(0,0,0,0.2);border-bottom:0;bottom:-7px;top:auto} |
|
684 | .navbar-fixed-bottom .nav>li>.dropdown-menu:before{border-top:7px solid #ccc;border-top-color:rgba(0,0,0,0.2);border-bottom:0;bottom:-7px;top:auto} | |
689 | .navbar-fixed-bottom .nav>li>.dropdown-menu:after{border-top:6px solid #fff;border-bottom:0;bottom:-6px;top:auto} |
|
685 | .navbar-fixed-bottom .nav>li>.dropdown-menu:after{border-top:6px solid #fff;border-bottom:0;bottom:-6px;top:auto} | |
690 | .navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333} |
|
686 | .navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333} | |
691 | .navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{background-color:#e5e5e5;color:#555} |
|
687 | .navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{background-color:#e5e5e5;color:#555} | |
692 | .navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777} |
|
688 | .navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777} | |
693 | .navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555} |
|
689 | .navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555} | |
694 | .navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{left:auto;right:0}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{left:auto;right:12px} |
|
690 | .navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{left:auto;right:0}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{left:auto;right:12px} | |
695 | .navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{left:auto;right:13px} |
|
691 | .navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{left:auto;right:13px} | |
696 | .navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{left:auto;right:100%;margin-left:0;margin-right:-1px;border-radius:6px 0 6px 6px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px} |
|
692 | .navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{left:auto;right:100%;margin-left:0;margin-right:-1px;border-radius:6px 0 6px 6px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px} | |
697 | .navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top, #222, #111);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#222), to(#111));background-image:-webkit-linear-gradient(top, #222, #111);background-image:-o-linear-gradient(top, #222, #111);background-image:linear-gradient(to bottom, #222, #111);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);border-color:#252525} |
|
693 | .navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top, #222, #111);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#222), to(#111));background-image:-webkit-linear-gradient(top, #222, #111);background-image:-o-linear-gradient(top, #222, #111);background-image:linear-gradient(to bottom, #222, #111);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);border-color:#252525} | |
698 | .navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff} |
|
694 | .navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff} | |
699 | .navbar-inverse .brand{color:#999} |
|
695 | .navbar-inverse .brand{color:#999} | |
700 | .navbar-inverse .navbar-text{color:#999} |
|
696 | .navbar-inverse .navbar-text{color:#999} | |
701 | .navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{background-color:transparent;color:#fff} |
|
697 | .navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{background-color:transparent;color:#fff} | |
702 | .navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111} |
|
698 | .navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111} | |
703 | .navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff} |
|
699 | .navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff} | |
704 | .navbar-inverse .divider-vertical{border-left-color:#111;border-right-color:#222} |
|
700 | .navbar-inverse .divider-vertical{border-left-color:#111;border-right-color:#222} | |
705 | .navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{background-color:#111;color:#fff} |
|
701 | .navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{background-color:#111;color:#fff} | |
706 | .navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff} |
|
702 | .navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff} | |
707 | .navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999} |
|
703 | .navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999} | |
708 | .navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff} |
|
704 | .navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff} | |
709 | .navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);box-shadow:inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc} |
|
705 | .navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);box-shadow:inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc} | |
710 | .navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc} |
|
706 | .navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc} | |
711 | .navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc} |
|
707 | .navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc} | |
712 | .navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15);outline:0} |
|
708 | .navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15);outline:0} | |
713 | .navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;background-image:-moz-linear-gradient(top, #151515, #040404);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));background-image:-webkit-linear-gradient(top, #151515, #040404);background-image:-o-linear-gradient(top, #151515, #040404);background-image:linear-gradient(to bottom, #151515, #040404);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#040404;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000} |
|
709 | .navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;background-image:-moz-linear-gradient(top, #151515, #040404);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));background-image:-webkit-linear-gradient(top, #151515, #040404);background-image:-o-linear-gradient(top, #151515, #040404);background-image:linear-gradient(to bottom, #151515, #040404);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);*background-color:#040404;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000} | |
714 | .navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9} |
|
710 | .navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9} | |
715 | .breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 0 #fff}.breadcrumb>li>.divider{padding:0 5px;color:#ccc} |
|
711 | .breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 0 #fff}.breadcrumb>li>.divider{padding:0 5px;color:#ccc} | |
716 | .breadcrumb>.active{color:#999} |
|
712 | .breadcrumb>.active{color:#999} | |
717 | .pagination{margin:20px 0} |
|
713 | .pagination{margin:20px 0} | |
718 | .pagination ul{display:inline-block;*display:inline;*zoom:1;margin-left:0;margin-bottom:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)} |
|
714 | .pagination ul{display:inline-block;*display:inline;*zoom:1;margin-left:0;margin-bottom:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)} | |
719 | .pagination ul>li{display:inline} |
|
715 | .pagination ul>li{display:inline} | |
720 | .pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0} |
|
716 | .pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0} | |
721 | .pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5} |
|
717 | .pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5} | |
722 | .pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default} |
|
718 | .pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default} | |
723 | .pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;background-color:transparent;cursor:default} |
|
719 | .pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;background-color:transparent;cursor:default} | |
724 | .pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px} |
|
720 | .pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px} | |
725 | .pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px} |
|
721 | .pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px} | |
726 | .pagination-centered{text-align:center} |
|
722 | .pagination-centered{text-align:center} | |
727 | .pagination-right{text-align:right} |
|
723 | .pagination-right{text-align:right} | |
728 | .pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:16.25px} |
|
724 | .pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:16.25px} | |
729 | .pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px} |
|
725 | .pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px} | |
730 | .pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px} |
|
726 | .pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px} | |
731 | .pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-top-left-radius:3px;-moz-border-radius-topleft:3px;border-top-left-radius:3px;-webkit-border-bottom-left-radius:3px;-moz-border-radius-bottomleft:3px;border-bottom-left-radius:3px} |
|
727 | .pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-top-left-radius:3px;-moz-border-radius-topleft:3px;border-top-left-radius:3px;-webkit-border-bottom-left-radius:3px;-moz-border-radius-bottomleft:3px;border-bottom-left-radius:3px} | |
732 | .pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;-moz-border-radius-topright:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;-moz-border-radius-bottomright:3px;border-bottom-right-radius:3px} |
|
728 | .pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;-moz-border-radius-topright:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;-moz-border-radius-bottomright:3px;border-bottom-right-radius:3px} | |
733 | .pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.049999999999999px} |
|
729 | .pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.049999999999999px} | |
734 | .pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:9.75px} |
|
730 | .pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:9.75px} | |
735 | .pager{margin:20px 0;list-style:none;text-align:center;*zoom:1}.pager:before,.pager:after{display:table;content:"";line-height:0} |
|
731 | .pager{margin:20px 0;list-style:none;text-align:center;*zoom:1}.pager:before,.pager:after{display:table;content:"";line-height:0} | |
736 | .pager:after{clear:both} |
|
732 | .pager:after{clear:both} | |
737 | .pager li{display:inline} |
|
733 | .pager li{display:inline} | |
738 | .pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px} |
|
734 | .pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px} | |
739 | .pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5} |
|
735 | .pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5} | |
740 | .pager .next>a,.pager .next>span{float:right} |
|
736 | .pager .next>a,.pager .next>span{float:right} | |
741 | .pager .previous>a,.pager .previous>span{float:left} |
|
737 | .pager .previous>a,.pager .previous>span{float:left} | |
742 | .pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;background-color:#fff;cursor:default} |
|
738 | .pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;background-color:#fff;cursor:default} | |
743 | .modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0} |
|
739 | .modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0} | |
744 | .modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)} |
|
740 | .modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)} | |
745 | .modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;outline:none}.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%} |
|
741 | .modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;outline:none}.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%} | |
746 | .modal.fade.in{top:10%} |
|
742 | .modal.fade.in{top:10%} | |
747 | .modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px} |
|
743 | .modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px} | |
748 | .modal-header h3{margin:0;line-height:30px} |
|
744 | .modal-header h3{margin:0;line-height:30px} | |
749 | .modal-body{position:relative;overflow-y:auto;max-height:400px;padding:15px} |
|
745 | .modal-body{position:relative;overflow-y:auto;max-height:400px;padding:15px} | |
750 | .modal-form{margin-bottom:0} |
|
746 | .modal-form{margin-bottom:0} | |
751 | .modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff;*zoom:1}.modal-footer:before,.modal-footer:after{display:table;content:"";line-height:0} |
|
747 | .modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff;*zoom:1}.modal-footer:before,.modal-footer:after{display:table;content:"";line-height:0} | |
752 | .modal-footer:after{clear:both} |
|
748 | .modal-footer:after{clear:both} | |
753 | .modal-footer .btn+.btn{margin-left:5px;margin-bottom:0} |
|
749 | .modal-footer .btn+.btn{margin-left:5px;margin-bottom:0} | |
754 | .modal-footer .btn-group .btn+.btn{margin-left:-1px} |
|
750 | .modal-footer .btn-group .btn+.btn{margin-left:-1px} | |
755 | .modal-footer .btn-block+.btn-block{margin-left:0} |
|
751 | .modal-footer .btn-block+.btn-block{margin-left:0} | |
756 | .tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.8;filter:alpha(opacity=80)} |
|
752 | .tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.8;filter:alpha(opacity=80)} | |
757 | .tooltip.top{margin-top:-3px;padding:5px 0} |
|
753 | .tooltip.top{margin-top:-3px;padding:5px 0} | |
758 | .tooltip.right{margin-left:3px;padding:0 5px} |
|
754 | .tooltip.right{margin-left:3px;padding:0 5px} | |
759 | .tooltip.bottom{margin-top:3px;padding:5px 0} |
|
755 | .tooltip.bottom{margin-top:3px;padding:5px 0} | |
760 | .tooltip.left{margin-left:-3px;padding:0 5px} |
|
756 | .tooltip.left{margin-left:-3px;padding:0 5px} | |
761 | .tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} |
|
757 | .tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} | |
762 | .tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid} |
|
758 | .tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid} | |
763 | .tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000} |
|
759 | .tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000} | |
764 | .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000} |
|
760 | .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000} | |
765 | .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000} |
|
761 | .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000} | |
766 | .tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000} |
|
762 | .tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000} | |
767 | .popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#fff;-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);white-space:normal}.popover.top{margin-top:-10px} |
|
763 | .popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#fff;-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);white-space:normal}.popover.top{margin-top:-10px} | |
768 | .popover.right{margin-left:10px} |
|
764 | .popover.right{margin-left:10px} | |
769 | .popover.bottom{margin-top:10px} |
|
765 | .popover.bottom{margin-top:10px} | |
770 | .popover.left{margin-left:-10px} |
|
766 | .popover.left{margin-left:-10px} | |
771 | .popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-title:empty{display:none} |
|
767 | .popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-title:empty{display:none} | |
772 | .popover-content{padding:9px 14px} |
|
768 | .popover-content{padding:9px 14px} | |
773 | .popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid} |
|
769 | .popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid} | |
774 | .popover .arrow{border-width:11px} |
|
770 | .popover .arrow{border-width:11px} | |
775 | .popover .arrow:after{border-width:10px;content:""} |
|
771 | .popover .arrow:after{border-width:10px;content:""} | |
776 | .popover.top .arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff} |
|
772 | .popover.top .arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff} | |
777 | .popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,0.25)}.popover.right .arrow:after{left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff} |
|
773 | .popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,0.25)}.popover.right .arrow:after{left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff} | |
778 | .popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff} |
|
774 | .popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff} | |
779 | .popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,0.25)}.popover.left .arrow:after{right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px} |
|
775 | .popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,0.25)}.popover.left .arrow:after{right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px} | |
780 | .thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;content:"";line-height:0} |
|
776 | .thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;content:"";line-height:0} | |
781 | .thumbnails:after{clear:both} |
|
777 | .thumbnails:after{clear:both} | |
782 | .row-fluid .thumbnails{margin-left:0} |
|
778 | .row-fluid .thumbnails{margin-left:0} | |
783 | .thumbnails>li{float:left;margin-bottom:20px;margin-left:20px} |
|
779 | .thumbnails>li{float:left;margin-bottom:20px;margin-left:20px} | |
784 | .thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out} |
|
780 | .thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out} | |
785 | a.thumbnail:hover,a.thumbnail:focus{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)} |
|
781 | a.thumbnail:hover,a.thumbnail:focus{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)} | |
786 | .thumbnail>img{display:block;max-width:100%;margin-left:auto;margin-right:auto} |
|
782 | .thumbnail>img{display:block;max-width:100%;margin-left:auto;margin-right:auto} | |
787 | .thumbnail .caption{padding:9px;color:#555} |
|
783 | .thumbnail .caption{padding:9px;color:#555} | |
788 | .media,.media-body{overflow:hidden;*overflow:visible;zoom:1} |
|
784 | .media,.media-body{overflow:hidden;*overflow:visible;zoom:1} | |
789 | .media,.media .media{margin-top:15px} |
|
785 | .media,.media .media{margin-top:15px} | |
790 | .media:first-child{margin-top:0} |
|
786 | .media:first-child{margin-top:0} | |
791 | .media-object{display:block} |
|
787 | .media-object{display:block} | |
792 | .media-heading{margin:0 0 5px} |
|
788 | .media-heading{margin:0 0 5px} | |
793 | .media>.pull-left{margin-right:10px} |
|
789 | .media>.pull-left{margin-right:10px} | |
794 | .media>.pull-right{margin-left:10px} |
|
790 | .media>.pull-right{margin-left:10px} | |
795 | .media-list{margin-left:0;list-style:none} |
|
791 | .media-list{margin-left:0;list-style:none} | |
796 | .label,.badge{display:inline-block;padding:2px 4px;font-size:10.998px;font-weight:bold;line-height:14px;color:#fff;vertical-align:baseline;white-space:nowrap;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#999} |
|
792 | .label,.badge{display:inline-block;padding:2px 4px;font-size:10.998px;font-weight:bold;line-height:14px;color:#fff;vertical-align:baseline;white-space:nowrap;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#999} | |
797 | .label{border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} |
|
793 | .label{border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} | |
798 | .badge{padding-left:9px;padding-right:9px;border-radius:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px} |
|
794 | .badge{padding-left:9px;padding-right:9px;border-radius:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px} | |
799 | .label:empty,.badge:empty{display:none} |
|
795 | .label:empty,.badge:empty{display:none} | |
800 | a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer} |
|
796 | a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer} | |
801 | .label-important,.badge-important{background-color:#b94a48} |
|
797 | .label-important,.badge-important{background-color:#b94a48} | |
802 | .label-important[href],.badge-important[href]{background-color:#953b39} |
|
798 | .label-important[href],.badge-important[href]{background-color:#953b39} | |
803 | .label-warning,.badge-warning{background-color:#f89406} |
|
799 | .label-warning,.badge-warning{background-color:#f89406} | |
804 | .label-warning[href],.badge-warning[href]{background-color:#c67605} |
|
800 | .label-warning[href],.badge-warning[href]{background-color:#c67605} | |
805 | .label-success,.badge-success{background-color:#468847} |
|
801 | .label-success,.badge-success{background-color:#468847} | |
806 | .label-success[href],.badge-success[href]{background-color:#356635} |
|
802 | .label-success[href],.badge-success[href]{background-color:#356635} | |
807 | .label-info,.badge-info{background-color:#3a87ad} |
|
803 | .label-info,.badge-info{background-color:#3a87ad} | |
808 | .label-info[href],.badge-info[href]{background-color:#2d6987} |
|
804 | .label-info[href],.badge-info[href]{background-color:#2d6987} | |
809 | .label-inverse,.badge-inverse{background-color:#333} |
|
805 | .label-inverse,.badge-inverse{background-color:#333} | |
810 | .label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a} |
|
806 | .label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a} | |
811 | .btn .label,.btn .badge{position:relative;top:-1px} |
|
807 | .btn .label,.btn .badge{position:relative;top:-1px} | |
812 | .btn-mini .label,.btn-mini .badge{top:0} |
|
808 | .btn-mini .label,.btn-mini .badge{top:0} | |
813 | @-webkit-keyframes progress-bar-stripes{from{background-position:40px 0} to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0} to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0} to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0} to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0} to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f7f7f7;background-image:-moz-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));background-image:-webkit-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-o-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:linear-gradient(to bottom, #f5f5f5, #f9f9f9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} |
|
809 | @-webkit-keyframes progress-bar-stripes{from{background-position:40px 0} to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0} to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0} to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0} to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0} to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f7f7f7;background-image:-moz-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));background-image:-webkit-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-o-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:linear-gradient(to bottom, #f5f5f5, #f9f9f9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} | |
814 | .progress .bar{width:0;height:100%;color:#fff;float:left;font-size:12px;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top, #149bdf, #0480be);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));background-image:-webkit-linear-gradient(top, #149bdf, #0480be);background-image:-o-linear-gradient(top, #149bdf, #0480be);background-image:linear-gradient(to bottom, #149bdf, #0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease} |
|
810 | .progress .bar{width:0;height:100%;color:#fff;float:left;font-size:12px;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top, #149bdf, #0480be);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));background-image:-webkit-linear-gradient(top, #149bdf, #0480be);background-image:-o-linear-gradient(top, #149bdf, #0480be);background-image:linear-gradient(to bottom, #149bdf, #0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease} | |
815 | .progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15)} |
|
811 | .progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15)} | |
816 | .progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px} |
|
812 | .progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px} | |
817 | .progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite} |
|
813 | .progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite} | |
818 | .progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(to bottom, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0)} |
|
814 | .progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(to bottom, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0)} | |
819 | .progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)} |
|
815 | .progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)} | |
820 | .progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(to bottom, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0)} |
|
816 | .progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(to bottom, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0)} | |
821 | .progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)} |
|
817 | .progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)} | |
822 | .progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(to bottom, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0)} |
|
818 | .progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(to bottom, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0)} | |
823 | .progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)} |
|
819 | .progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)} | |
824 | .progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(to bottom, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0)} |
|
820 | .progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(to bottom, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0)} | |
825 | .progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)} |
|
821 | .progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)} | |
826 | .accordion{margin-bottom:20px} |
|
822 | .accordion{margin-bottom:20px} | |
827 | .accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} |
|
823 | .accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} | |
828 | .accordion-heading{border-bottom:0} |
|
824 | .accordion-heading{border-bottom:0} | |
829 | .accordion-heading .accordion-toggle{display:block;padding:8px 15px} |
|
825 | .accordion-heading .accordion-toggle{display:block;padding:8px 15px} | |
830 | .accordion-toggle{cursor:pointer} |
|
826 | .accordion-toggle{cursor:pointer} | |
831 | .accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5} |
|
827 | .accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5} | |
832 | .carousel{position:relative;margin-bottom:20px;line-height:1} |
|
828 | .carousel{position:relative;margin-bottom:20px;line-height:1} | |
833 | .carousel-inner{overflow:hidden;width:100%;position:relative} |
|
829 | .carousel-inner{overflow:hidden;width:100%;position:relative} | |
834 | .carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;line-height:1} |
|
830 | .carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;line-height:1} | |
835 | .carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block} |
|
831 | .carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block} | |
836 | .carousel-inner>.active{left:0} |
|
832 | .carousel-inner>.active{left:0} | |
837 | .carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%} |
|
833 | .carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%} | |
838 | .carousel-inner>.next{left:100%} |
|
834 | .carousel-inner>.next{left:100%} | |
839 | .carousel-inner>.prev{left:-100%} |
|
835 | .carousel-inner>.prev{left:-100%} | |
840 | .carousel-inner>.next.left,.carousel-inner>.prev.right{left:0} |
|
836 | .carousel-inner>.next.left,.carousel-inner>.prev.right{left:0} | |
841 | .carousel-inner>.active.left{left:-100%} |
|
837 | .carousel-inner>.active.left{left:-100%} | |
842 | .carousel-inner>.active.right{left:100%} |
|
838 | .carousel-inner>.active.right{left:100%} | |
843 | .carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{left:auto;right:15px} |
|
839 | .carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{left:auto;right:15px} | |
844 | .carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)} |
|
840 | .carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)} | |
845 | .carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,0.25);border-radius:5px} |
|
841 | .carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,0.25);border-radius:5px} | |
846 | .carousel-indicators .active{background-color:#fff} |
|
842 | .carousel-indicators .active{background-color:#fff} | |
847 | .carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)} |
|
843 | .carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)} | |
848 | .carousel-caption h4,.carousel-caption p{color:#fff;line-height:20px} |
|
844 | .carousel-caption h4,.carousel-caption p{color:#fff;line-height:20px} | |
849 | .carousel-caption h4{margin:0 0 5px} |
|
845 | .carousel-caption h4{margin:0 0 5px} | |
850 | .carousel-caption p{margin-bottom:0} |
|
846 | .carousel-caption p{margin-bottom:0} | |
851 | .hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;border-radius:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;color:inherit;letter-spacing:-1px} |
|
847 | .hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;border-radius:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;color:inherit;letter-spacing:-1px} | |
852 | .hero-unit li{line-height:30px} |
|
848 | .hero-unit li{line-height:30px} | |
853 | .pull-right{float:right} |
|
849 | .pull-right{float:right} | |
854 | .pull-left{float:left} |
|
850 | .pull-left{float:left} | |
855 | .hide{display:none} |
|
851 | .hide{display:none} | |
856 | .show{display:block} |
|
852 | .show{display:block} | |
857 | .invisible{visibility:hidden} |
|
853 | .invisible{visibility:hidden} | |
858 | .affix{position:fixed} |
|
854 | .affix{position:fixed} | |
|
855 | .clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0} | |||
|
856 | .clearfix:after{clear:both} | |||
|
857 | .hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0} | |||
|
858 | .input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} | |||
859 | @-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden} |
|
859 | @-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden} | |
860 | .visible-phone{display:none !important} |
|
860 | .visible-phone{display:none !important} | |
861 | .visible-tablet{display:none !important} |
|
861 | .visible-tablet{display:none !important} | |
862 | .hidden-desktop{display:none !important} |
|
862 | .hidden-desktop{display:none !important} | |
863 | .visible-desktop{display:inherit !important} |
|
863 | .visible-desktop{display:inherit !important} | |
864 | @media (min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit !important} .visible-desktop{display:none !important} .visible-tablet{display:inherit !important} .hidden-tablet{display:none !important}}@media (max-width:767px){.hidden-desktop{display:inherit !important} .visible-desktop{display:none !important} .visible-phone{display:inherit !important} .hidden-phone{display:none !important}}.visible-print{display:none !important} |
|
864 | @media (min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit !important} .visible-desktop{display:none !important} .visible-tablet{display:inherit !important} .hidden-tablet{display:none !important}}@media (max-width:767px){.hidden-desktop{display:inherit !important} .visible-desktop{display:none !important} .visible-phone{display:inherit !important} .hidden-phone{display:none !important}}.visible-print{display:none !important} | |
865 | @media print{.visible-print{display:inherit !important} .hidden-print{display:none !important}}@media (min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;content:"";line-height:0} .row:after{clear:both} [class*="span"]{float:left;min-height:1px;margin-left:30px} .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px} .span12{width:1170px} .span11{width:1070px} .span10{width:970px} .span9{width:870px} .span8{width:770px} .span7{width:670px} .span6{width:570px} .span5{width:470px} .span4{width:370px} .span3{width:270px} .span2{width:170px} .span1{width:70px} .offset12{margin-left:1230px} .offset11{margin-left:1130px} .offset10{margin-left:1030px} .offset9{margin-left:930px} .offset8{margin-left:830px} .offset7{margin-left:730px} .offset6{margin-left:630px} .offset5{margin-left:530px} .offset4{margin-left:430px} .offset3{margin-left:330px} .offset2{margin-left:230px} .offset1{margin-left:130px} .row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0} .row-fluid:after{clear:both} .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%} .row-fluid [class*="span"]:first-child{margin-left:0} .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%} .row-fluid .span12{width:100%;*width:99.94680851063829%} .row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%} .row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%} .row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%} .row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%} .row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%} .row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%} .row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%} .row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%} .row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%} .row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%} .row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%} .row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%} .row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%} .row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%} .row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%} .row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%} .row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%} .row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%} .row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%} .row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%} .row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%} .row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%} .row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%} .row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%} .row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%} .row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%} .row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%} .row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%} .row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%} .row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%} .row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%} .row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%} .row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%} .row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%} .row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%} input,textarea,.uneditable-input{margin-left:0} .controls-row [class*="span"]+[class*="span"]{margin-left:30px} input.span12,textarea.span12,.uneditable-input.span12{width:1156px} input.span11,textarea.span11,.uneditable-input.span11{width:1056px} input.span10,textarea.span10,.uneditable-input.span10{width:956px} input.span9,textarea.span9,.uneditable-input.span9{width:856px} input.span8,textarea.span8,.uneditable-input.span8{width:756px} input.span7,textarea.span7,.uneditable-input.span7{width:656px} input.span6,textarea.span6,.uneditable-input.span6{width:556px} input.span5,textarea.span5,.uneditable-input.span5{width:456px} input.span4,textarea.span4,.uneditable-input.span4{width:356px} input.span3,textarea.span3,.uneditable-input.span3{width:256px} input.span2,textarea.span2,.uneditable-input.span2{width:156px} input.span1,textarea.span1,.uneditable-input.span1{width:56px} .thumbnails{margin-left:-30px} .thumbnails>li{margin-left:30px} .row-fluid .thumbnails{margin-left:0}}@media (min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;content:"";line-height:0} .row:after{clear:both} [class*="span"]{float:left;min-height:1px;margin-left:20px} .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px} .span12{width:724px} .span11{width:662px} .span10{width:600px} .span9{width:538px} .span8{width:476px} .span7{width:414px} .span6{width:352px} .span5{width:290px} .span4{width:228px} .span3{width:166px} .span2{width:104px} .span1{width:42px} .offset12{margin-left:764px} .offset11{margin-left:702px} .offset10{margin-left:640px} .offset9{margin-left:578px} .offset8{margin-left:516px} .offset7{margin-left:454px} .offset6{margin-left:392px} .offset5{margin-left:330px} .offset4{margin-left:268px} .offset3{margin-left:206px} .offset2{margin-left:144px} .offset1{margin-left:82px} .row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0} .row-fluid:after{clear:both} .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%} .row-fluid [class*="span"]:first-child{margin-left:0} .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%} .row-fluid .span12{width:100%;*width:99.94680851063829%} .row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%} .row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%} .row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%} .row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%} .row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%} .row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%} .row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%} .row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%} .row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%} .row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%} .row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%} .row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%} .row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%} .row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%} .row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%} .row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%} .row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%} .row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%} .row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%} .row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%} .row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%} .row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%} .row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%} .row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%} .row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%} .row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%} .row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%} .row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%} .row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%} .row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%} .row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%} .row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%} .row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%} .row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%} .row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%} input,textarea,.uneditable-input{margin-left:0} .controls-row [class*="span"]+[class*="span"]{margin-left:20px} input.span12,textarea.span12,.uneditable-input.span12{width:710px} input.span11,textarea.span11,.uneditable-input.span11{width:648px} input.span10,textarea.span10,.uneditable-input.span10{width:586px} input.span9,textarea.span9,.uneditable-input.span9{width:524px} input.span8,textarea.span8,.uneditable-input.span8{width:462px} input.span7,textarea.span7,.uneditable-input.span7{width:400px} input.span6,textarea.span6,.uneditable-input.span6{width:338px} input.span5,textarea.span5,.uneditable-input.span5{width:276px} input.span4,textarea.span4,.uneditable-input.span4{width:214px} input.span3,textarea.span3,.uneditable-input.span3{width:152px} input.span2,textarea.span2,.uneditable-input.span2{width:90px} input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media (max-width:767px){body{padding-left:20px;padding-right:20px} .navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-left:-20px;margin-right:-20px} .container-fluid{padding:0} .dl-horizontal dt{float:none;clear:none;width:auto;text-align:left} .dl-horizontal dd{margin-left:0} .container{width:auto} .row-fluid{width:100%} .row,.thumbnails{margin-left:0} .thumbnails>li{float:none;margin-left:0} [class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{float:none;display:block;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} .span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} .row-fluid [class*="offset"]:first-child{margin-left:0} .input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} .input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto} .controls-row [class*="span"]+[class*="span"]{margin-left:0} .modal{position:fixed;top:20px;left:20px;right:20px;width:auto;margin:0}.modal.fade{top:-100px} .modal.fade.in{top:20px}}@media (max-width:480px){.nav-collapse{-webkit-transform:translate3d(0, 0, 0)} .page-header h1 small{display:block;line-height:20px} input[type="checkbox"],input[type="radio"]{border:1px solid #ccc} .form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left} .form-horizontal .controls{margin-left:0} .form-horizontal .control-list{padding-top:0} .form-horizontal .form-actions{padding-left:10px;padding-right:10px} .media .pull-left,.media .pull-right{float:none;display:block;margin-bottom:10px} .media-object{margin-right:0;margin-left:0} .modal{top:10px;left:10px;right:10px} .modal-header .close{padding:10px;margin:-10px} .carousel-caption{position:static}}@media (max-width:979px){body{padding-top:0} .navbar-fixed-top,.navbar-fixed-bottom{position:static} .navbar-fixed-top{margin-bottom:20px} .navbar-fixed-bottom{margin-top:20px} .navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px} .navbar .container{width:auto;padding:0} .navbar .brand{padding-left:10px;padding-right:10px;margin:0 0 0 -5px} .nav-collapse{clear:both} .nav-collapse .nav{float:none;margin:0 0 10px} .nav-collapse .nav>li{float:none} .nav-collapse .nav>li>a{margin-bottom:2px} .nav-collapse .nav>.divider-vertical{display:none} .nav-collapse .nav .nav-header{color:#777;text-shadow:none} .nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} .nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} .nav-collapse .dropdown-menu li+li a{margin-bottom:2px} .nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2} .navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999} .navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111} .nav-collapse.in .btn-group{margin-top:5px;padding:0} .nav-collapse .dropdown-menu{position:static;top:auto;left:auto;float:none;display:none;max-width:none;margin:0 15px;padding:0;background-color:transparent;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none} .nav-collapse .open>.dropdown-menu{display:block} .nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none} .nav-collapse .dropdown-menu .divider{display:none} .nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none} .nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1)} .navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111} .navbar .nav-collapse .nav.pull-right{float:none;margin-left:0} .nav-collapse,.nav-collapse.collapse{overflow:hidden;height:0} .navbar .btn-navbar{display:block} .navbar-static .navbar-inner{padding-left:10px;padding-right:10px}}@media (min-width:979px + 1){.nav-collapse.collapse{height:auto !important;overflow:visible !important}}@font-face{font-family:'FontAwesome';src:url('../components/font-awesome/font/fontawesome-webfont.eot?v=3.2.1');src:url('../components/font-awesome/font/fontawesome-webfont.eot?#iefix&v=3.2.1') format('embedded-opentype'),url('../components/font-awesome/font/fontawesome-webfont.woff?v=3.2.1') format('woff'),url('../components/font-awesome/font/fontawesome-webfont.ttf?v=3.2.1') format('truetype'),url('../components/font-awesome/font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg');font-weight:normal;font-style:normal}[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em} |
|
865 | @media print{.visible-print{display:inherit !important} .hidden-print{display:none !important}}@media (min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;content:"";line-height:0} .row:after{clear:both} [class*="span"]{float:left;min-height:1px;margin-left:30px} .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px} .span12{width:1170px} .span11{width:1070px} .span10{width:970px} .span9{width:870px} .span8{width:770px} .span7{width:670px} .span6{width:570px} .span5{width:470px} .span4{width:370px} .span3{width:270px} .span2{width:170px} .span1{width:70px} .offset12{margin-left:1230px} .offset11{margin-left:1130px} .offset10{margin-left:1030px} .offset9{margin-left:930px} .offset8{margin-left:830px} .offset7{margin-left:730px} .offset6{margin-left:630px} .offset5{margin-left:530px} .offset4{margin-left:430px} .offset3{margin-left:330px} .offset2{margin-left:230px} .offset1{margin-left:130px} .row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0} .row-fluid:after{clear:both} .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%} .row-fluid [class*="span"]:first-child{margin-left:0} .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%} .row-fluid .span12{width:100%;*width:99.94680851063829%} .row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%} .row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%} .row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%} .row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%} .row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%} .row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%} .row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%} .row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%} .row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%} .row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%} .row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%} .row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%} .row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%} .row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%} .row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%} .row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%} .row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%} .row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%} .row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%} .row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%} .row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%} .row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%} .row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%} .row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%} .row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%} .row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%} .row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%} .row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%} .row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%} .row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%} .row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%} .row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%} .row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%} .row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%} .row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%} input,textarea,.uneditable-input{margin-left:0} .controls-row [class*="span"]+[class*="span"]{margin-left:30px} input.span12,textarea.span12,.uneditable-input.span12{width:1156px} input.span11,textarea.span11,.uneditable-input.span11{width:1056px} input.span10,textarea.span10,.uneditable-input.span10{width:956px} input.span9,textarea.span9,.uneditable-input.span9{width:856px} input.span8,textarea.span8,.uneditable-input.span8{width:756px} input.span7,textarea.span7,.uneditable-input.span7{width:656px} input.span6,textarea.span6,.uneditable-input.span6{width:556px} input.span5,textarea.span5,.uneditable-input.span5{width:456px} input.span4,textarea.span4,.uneditable-input.span4{width:356px} input.span3,textarea.span3,.uneditable-input.span3{width:256px} input.span2,textarea.span2,.uneditable-input.span2{width:156px} input.span1,textarea.span1,.uneditable-input.span1{width:56px} .thumbnails{margin-left:-30px} .thumbnails>li{margin-left:30px} .row-fluid .thumbnails{margin-left:0}}@media (min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;content:"";line-height:0} .row:after{clear:both} [class*="span"]{float:left;min-height:1px;margin-left:20px} .container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px} .span12{width:724px} .span11{width:662px} .span10{width:600px} .span9{width:538px} .span8{width:476px} .span7{width:414px} .span6{width:352px} .span5{width:290px} .span4{width:228px} .span3{width:166px} .span2{width:104px} .span1{width:42px} .offset12{margin-left:764px} .offset11{margin-left:702px} .offset10{margin-left:640px} .offset9{margin-left:578px} .offset8{margin-left:516px} .offset7{margin-left:454px} .offset6{margin-left:392px} .offset5{margin-left:330px} .offset4{margin-left:268px} .offset3{margin-left:206px} .offset2{margin-left:144px} .offset1{margin-left:82px} .row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0} .row-fluid:after{clear:both} .row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%} .row-fluid [class*="span"]:first-child{margin-left:0} .row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%} .row-fluid .span12{width:100%;*width:99.94680851063829%} .row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%} .row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%} .row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%} .row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%} .row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%} .row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%} .row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%} .row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%} .row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%} .row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%} .row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%} .row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%} .row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%} .row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%} .row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%} .row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%} .row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%} .row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%} .row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%} .row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%} .row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%} .row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%} .row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%} .row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%} .row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%} .row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%} .row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%} .row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%} .row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%} .row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%} .row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%} .row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%} .row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%} .row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%} .row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%} input,textarea,.uneditable-input{margin-left:0} .controls-row [class*="span"]+[class*="span"]{margin-left:20px} input.span12,textarea.span12,.uneditable-input.span12{width:710px} input.span11,textarea.span11,.uneditable-input.span11{width:648px} input.span10,textarea.span10,.uneditable-input.span10{width:586px} input.span9,textarea.span9,.uneditable-input.span9{width:524px} input.span8,textarea.span8,.uneditable-input.span8{width:462px} input.span7,textarea.span7,.uneditable-input.span7{width:400px} input.span6,textarea.span6,.uneditable-input.span6{width:338px} input.span5,textarea.span5,.uneditable-input.span5{width:276px} input.span4,textarea.span4,.uneditable-input.span4{width:214px} input.span3,textarea.span3,.uneditable-input.span3{width:152px} input.span2,textarea.span2,.uneditable-input.span2{width:90px} input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media (max-width:767px){body{padding-left:20px;padding-right:20px} .navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-left:-20px;margin-right:-20px} .container-fluid{padding:0} .dl-horizontal dt{float:none;clear:none;width:auto;text-align:left} .dl-horizontal dd{margin-left:0} .container{width:auto} .row-fluid{width:100%} .row,.thumbnails{margin-left:0} .thumbnails>li{float:none;margin-left:0} [class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{float:none;display:block;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} .span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} .row-fluid [class*="offset"]:first-child{margin-left:0} .input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} .input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto} .controls-row [class*="span"]+[class*="span"]{margin-left:0} .modal{position:fixed;top:20px;left:20px;right:20px;width:auto;margin:0}.modal.fade{top:-100px} .modal.fade.in{top:20px}}@media (max-width:480px){.nav-collapse{-webkit-transform:translate3d(0, 0, 0)} .page-header h1 small{display:block;line-height:20px} input[type="checkbox"],input[type="radio"]{border:1px solid #ccc} .form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left} .form-horizontal .controls{margin-left:0} .form-horizontal .control-list{padding-top:0} .form-horizontal .form-actions{padding-left:10px;padding-right:10px} .media .pull-left,.media .pull-right{float:none;display:block;margin-bottom:10px} .media-object{margin-right:0;margin-left:0} .modal{top:10px;left:10px;right:10px} .modal-header .close{padding:10px;margin:-10px} .carousel-caption{position:static}}@media (max-width:979px){body{padding-top:0} .navbar-fixed-top,.navbar-fixed-bottom{position:static} .navbar-fixed-top{margin-bottom:20px} .navbar-fixed-bottom{margin-top:20px} .navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px} .navbar .container{width:auto;padding:0} .navbar .brand{padding-left:10px;padding-right:10px;margin:0 0 0 -5px} .nav-collapse{clear:both} .nav-collapse .nav{float:none;margin:0 0 10px} .nav-collapse .nav>li{float:none} .nav-collapse .nav>li>a{margin-bottom:2px} .nav-collapse .nav>.divider-vertical{display:none} .nav-collapse .nav .nav-header{color:#777;text-shadow:none} .nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} .nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} .nav-collapse .dropdown-menu li+li a{margin-bottom:2px} .nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2} .navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999} .navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111} .nav-collapse.in .btn-group{margin-top:5px;padding:0} .nav-collapse .dropdown-menu{position:static;top:auto;left:auto;float:none;display:none;max-width:none;margin:0 15px;padding:0;background-color:transparent;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none} .nav-collapse .open>.dropdown-menu{display:block} .nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none} .nav-collapse .dropdown-menu .divider{display:none} .nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none} .nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1)} .navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111} .navbar .nav-collapse .nav.pull-right{float:none;margin-left:0} .nav-collapse,.nav-collapse.collapse{overflow:hidden;height:0} .navbar .btn-navbar{display:block} .navbar-static .navbar-inner{padding-left:10px;padding-right:10px}}@media (min-width:979px + 1){.nav-collapse.collapse{height:auto !important;overflow:visible !important}}@font-face{font-family:'FontAwesome';src:url('../components/font-awesome/font/fontawesome-webfont.eot?v=3.2.1');src:url('../components/font-awesome/font/fontawesome-webfont.eot?#iefix&v=3.2.1') format('embedded-opentype'),url('../components/font-awesome/font/fontawesome-webfont.woff?v=3.2.1') format('woff'),url('../components/font-awesome/font/fontawesome-webfont.ttf?v=3.2.1') format('truetype'),url('../components/font-awesome/font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg');font-weight:normal;font-style:normal}[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em} | |
866 | [class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none} |
|
866 | [class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none} | |
867 | .icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em} |
|
867 | .icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em} | |
868 | a [class^="icon-"],a [class*=" icon-"]{display:inline} |
|
868 | a [class^="icon-"],a [class*=" icon-"]{display:inline} | |
869 | [class^="icon-"].icon-fixed-width,[class*=" icon-"].icon-fixed-width{display:inline-block;width:1.1428571428571428em;text-align:right;padding-right:.2857142857142857em}[class^="icon-"].icon-fixed-width.icon-large,[class*=" icon-"].icon-fixed-width.icon-large{width:1.4285714285714286em} |
|
869 | [class^="icon-"].icon-fixed-width,[class*=" icon-"].icon-fixed-width{display:inline-block;width:1.1428571428571428em;text-align:right;padding-right:.2857142857142857em}[class^="icon-"].icon-fixed-width.icon-large,[class*=" icon-"].icon-fixed-width.icon-large{width:1.4285714285714286em} | |
870 | .icons-ul{margin-left:2.142857142857143em;list-style-type:none}.icons-ul>li{position:relative} |
|
870 | .icons-ul{margin-left:2.142857142857143em;list-style-type:none}.icons-ul>li{position:relative} | |
871 | .icons-ul .icon-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;text-align:center;line-height:inherit} |
|
871 | .icons-ul .icon-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;text-align:center;line-height:inherit} | |
872 | [class^="icon-"].hide,[class*=" icon-"].hide{display:none} |
|
872 | [class^="icon-"].hide,[class*=" icon-"].hide{display:none} | |
873 | .icon-muted{color:#eee} |
|
873 | .icon-muted{color:#eee} | |
874 | .icon-light{color:#fff} |
|
874 | .icon-light{color:#fff} | |
875 | .icon-dark{color:#333} |
|
875 | .icon-dark{color:#333} | |
876 | .icon-border{border:solid 1px #eee;padding:.2em .25em .15em;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} |
|
876 | .icon-border{border:solid 1px #eee;padding:.2em .25em .15em;border-radius:3px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} | |
877 | .icon-2x{font-size:2em}.icon-2x.icon-border{border-width:2px;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} |
|
877 | .icon-2x{font-size:2em}.icon-2x.icon-border{border-width:2px;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px} | |
878 | .icon-3x{font-size:3em}.icon-3x.icon-border{border-width:3px;border-radius:5px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px} |
|
878 | .icon-3x{font-size:3em}.icon-3x.icon-border{border-width:3px;border-radius:5px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px} | |
879 | .icon-4x{font-size:4em}.icon-4x.icon-border{border-width:4px;border-radius:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px} |
|
879 | .icon-4x{font-size:4em}.icon-4x.icon-border{border-width:4px;border-radius:6px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px} | |
880 | .icon-5x{font-size:5em}.icon-5x.icon-border{border-width:5px;border-radius:7px;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px} |
|
880 | .icon-5x{font-size:5em}.icon-5x.icon-border{border-width:5px;border-radius:7px;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px} | |
881 | .pull-right{float:right} |
|
881 | .pull-right{float:right} | |
882 | .pull-left{float:left} |
|
882 | .pull-left{float:left} | |
883 | [class^="icon-"].pull-left,[class*=" icon-"].pull-left{margin-right:.3em} |
|
883 | [class^="icon-"].pull-left,[class*=" icon-"].pull-left{margin-right:.3em} | |
884 | [class^="icon-"].pull-right,[class*=" icon-"].pull-right{margin-left:.3em} |
|
884 | [class^="icon-"].pull-right,[class*=" icon-"].pull-right{margin-left:.3em} | |
885 | [class^="icon-"],[class*=" icon-"]{display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0 0;background-repeat:repeat;margin-top:0} |
|
885 | [class^="icon-"],[class*=" icon-"]{display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0 0;background-repeat:repeat;margin-top:0} | |
886 | .icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:none} |
|
886 | .icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:none} | |
887 | .btn [class^="icon-"].icon-large,.nav [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large,.nav [class*=" icon-"].icon-large{line-height:.9em} |
|
887 | .btn [class^="icon-"].icon-large,.nav [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large,.nav [class*=" icon-"].icon-large{line-height:.9em} | |
888 | .btn [class^="icon-"].icon-spin,.nav [class^="icon-"].icon-spin,.btn [class*=" icon-"].icon-spin,.nav [class*=" icon-"].icon-spin{display:inline-block} |
|
888 | .btn [class^="icon-"].icon-spin,.nav [class^="icon-"].icon-spin,.btn [class*=" icon-"].icon-spin,.nav [class*=" icon-"].icon-spin{display:inline-block} | |
889 | .nav-tabs [class^="icon-"],.nav-pills [class^="icon-"],.nav-tabs [class*=" icon-"],.nav-pills [class*=" icon-"],.nav-tabs [class^="icon-"].icon-large,.nav-pills [class^="icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large{line-height:.9em} |
|
889 | .nav-tabs [class^="icon-"],.nav-pills [class^="icon-"],.nav-tabs [class*=" icon-"],.nav-pills [class*=" icon-"],.nav-tabs [class^="icon-"].icon-large,.nav-pills [class^="icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large{line-height:.9em} | |
890 | .btn [class^="icon-"].pull-left.icon-2x,.btn [class*=" icon-"].pull-left.icon-2x,.btn [class^="icon-"].pull-right.icon-2x,.btn [class*=" icon-"].pull-right.icon-2x{margin-top:.18em} |
|
890 | .btn [class^="icon-"].pull-left.icon-2x,.btn [class*=" icon-"].pull-left.icon-2x,.btn [class^="icon-"].pull-right.icon-2x,.btn [class*=" icon-"].pull-right.icon-2x{margin-top:.18em} | |
891 | .btn [class^="icon-"].icon-spin.icon-large,.btn [class*=" icon-"].icon-spin.icon-large{line-height:.8em} |
|
891 | .btn [class^="icon-"].icon-spin.icon-large,.btn [class*=" icon-"].icon-spin.icon-large{line-height:.8em} | |
892 | .btn.btn-small [class^="icon-"].pull-left.icon-2x,.btn.btn-small [class*=" icon-"].pull-left.icon-2x,.btn.btn-small [class^="icon-"].pull-right.icon-2x,.btn.btn-small [class*=" icon-"].pull-right.icon-2x{margin-top:.25em} |
|
892 | .btn.btn-small [class^="icon-"].pull-left.icon-2x,.btn.btn-small [class*=" icon-"].pull-left.icon-2x,.btn.btn-small [class^="icon-"].pull-right.icon-2x,.btn.btn-small [class*=" icon-"].pull-right.icon-2x{margin-top:.25em} | |
893 | .btn.btn-large [class^="icon-"],.btn.btn-large [class*=" icon-"]{margin-top:0}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x,.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-top:.05em} |
|
893 | .btn.btn-large [class^="icon-"],.btn.btn-large [class*=" icon-"]{margin-top:0}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x,.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-top:.05em} | |
894 | .btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x{margin-right:.2em} |
|
894 | .btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x{margin-right:.2em} | |
895 | .btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-left:.2em} |
|
895 | .btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-left:.2em} | |
896 | .nav-list [class^="icon-"],.nav-list [class*=" icon-"]{line-height:inherit} |
|
896 | .nav-list [class^="icon-"],.nav-list [class*=" icon-"]{line-height:inherit} | |
897 | .icon-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:-35%}.icon-stack [class^="icon-"],.icon-stack [class*=" icon-"]{display:block;text-align:center;position:absolute;width:100%;height:100%;font-size:1em;line-height:inherit;*line-height:2em} |
|
897 | .icon-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:-35%}.icon-stack [class^="icon-"],.icon-stack [class*=" icon-"]{display:block;text-align:center;position:absolute;width:100%;height:100%;font-size:1em;line-height:inherit;*line-height:2em} | |
898 | .icon-stack .icon-stack-base{font-size:2em;*line-height:1em} |
|
898 | .icon-stack .icon-stack-base{font-size:2em;*line-height:1em} | |
899 | .icon-spin{display:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear} |
|
899 | .icon-spin{display:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear} | |
900 | a .icon-stack,a .icon-spin{display:inline-block;text-decoration:none} |
|
900 | a .icon-stack,a .icon-spin{display:inline-block;text-decoration:none} | |
901 | @-moz-keyframes spin{0%{-moz-transform:rotate(0deg)} 100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)} 100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)} 100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)} 100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)} 100%{transform:rotate(359deg)}}.icon-rotate-90:before{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1)} |
|
901 | @-moz-keyframes spin{0%{-moz-transform:rotate(0deg)} 100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)} 100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)} 100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)} 100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)} 100%{transform:rotate(359deg)}}.icon-rotate-90:before{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1)} | |
902 | .icon-rotate-180:before{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2)} |
|
902 | .icon-rotate-180:before{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2)} | |
903 | .icon-rotate-270:before{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3)} |
|
903 | .icon-rotate-270:before{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3)} | |
904 | .icon-flip-horizontal:before{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)} |
|
904 | .icon-flip-horizontal:before{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)} | |
905 | .icon-flip-vertical:before{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)} |
|
905 | .icon-flip-vertical:before{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)} | |
906 | a .icon-rotate-90:before,a .icon-rotate-180:before,a .icon-rotate-270:before,a .icon-flip-horizontal:before,a .icon-flip-vertical:before{display:inline-block} |
|
906 | a .icon-rotate-90:before,a .icon-rotate-180:before,a .icon-rotate-270:before,a .icon-flip-horizontal:before,a .icon-flip-vertical:before{display:inline-block} | |
907 | .icon-glass:before{content:"\f000"} |
|
907 | .icon-glass:before{content:"\f000"} | |
908 | .icon-music:before{content:"\f001"} |
|
908 | .icon-music:before{content:"\f001"} | |
909 | .icon-search:before{content:"\f002"} |
|
909 | .icon-search:before{content:"\f002"} | |
910 | .icon-envelope-alt:before{content:"\f003"} |
|
910 | .icon-envelope-alt:before{content:"\f003"} | |
911 | .icon-heart:before{content:"\f004"} |
|
911 | .icon-heart:before{content:"\f004"} | |
912 | .icon-star:before{content:"\f005"} |
|
912 | .icon-star:before{content:"\f005"} | |
913 | .icon-star-empty:before{content:"\f006"} |
|
913 | .icon-star-empty:before{content:"\f006"} | |
914 | .icon-user:before{content:"\f007"} |
|
914 | .icon-user:before{content:"\f007"} | |
915 | .icon-film:before{content:"\f008"} |
|
915 | .icon-film:before{content:"\f008"} | |
916 | .icon-th-large:before{content:"\f009"} |
|
916 | .icon-th-large:before{content:"\f009"} | |
917 | .icon-th:before{content:"\f00a"} |
|
917 | .icon-th:before{content:"\f00a"} | |
918 | .icon-th-list:before{content:"\f00b"} |
|
918 | .icon-th-list:before{content:"\f00b"} | |
919 | .icon-ok:before{content:"\f00c"} |
|
919 | .icon-ok:before{content:"\f00c"} | |
920 | .icon-remove:before{content:"\f00d"} |
|
920 | .icon-remove:before{content:"\f00d"} | |
921 | .icon-zoom-in:before{content:"\f00e"} |
|
921 | .icon-zoom-in:before{content:"\f00e"} | |
922 | .icon-zoom-out:before{content:"\f010"} |
|
922 | .icon-zoom-out:before{content:"\f010"} | |
923 | .icon-power-off:before,.icon-off:before{content:"\f011"} |
|
923 | .icon-power-off:before,.icon-off:before{content:"\f011"} | |
924 | .icon-signal:before{content:"\f012"} |
|
924 | .icon-signal:before{content:"\f012"} | |
925 | .icon-gear:before,.icon-cog:before{content:"\f013"} |
|
925 | .icon-gear:before,.icon-cog:before{content:"\f013"} | |
926 | .icon-trash:before{content:"\f014"} |
|
926 | .icon-trash:before{content:"\f014"} | |
927 | .icon-home:before{content:"\f015"} |
|
927 | .icon-home:before{content:"\f015"} | |
928 | .icon-file-alt:before{content:"\f016"} |
|
928 | .icon-file-alt:before{content:"\f016"} | |
929 | .icon-time:before{content:"\f017"} |
|
929 | .icon-time:before{content:"\f017"} | |
930 | .icon-road:before{content:"\f018"} |
|
930 | .icon-road:before{content:"\f018"} | |
931 | .icon-download-alt:before{content:"\f019"} |
|
931 | .icon-download-alt:before{content:"\f019"} | |
932 | .icon-download:before{content:"\f01a"} |
|
932 | .icon-download:before{content:"\f01a"} | |
933 | .icon-upload:before{content:"\f01b"} |
|
933 | .icon-upload:before{content:"\f01b"} | |
934 | .icon-inbox:before{content:"\f01c"} |
|
934 | .icon-inbox:before{content:"\f01c"} | |
935 | .icon-play-circle:before{content:"\f01d"} |
|
935 | .icon-play-circle:before{content:"\f01d"} | |
936 | .icon-rotate-right:before,.icon-repeat:before{content:"\f01e"} |
|
936 | .icon-rotate-right:before,.icon-repeat:before{content:"\f01e"} | |
937 | .icon-refresh:before{content:"\f021"} |
|
937 | .icon-refresh:before{content:"\f021"} | |
938 | .icon-list-alt:before{content:"\f022"} |
|
938 | .icon-list-alt:before{content:"\f022"} | |
939 | .icon-lock:before{content:"\f023"} |
|
939 | .icon-lock:before{content:"\f023"} | |
940 | .icon-flag:before{content:"\f024"} |
|
940 | .icon-flag:before{content:"\f024"} | |
941 | .icon-headphones:before{content:"\f025"} |
|
941 | .icon-headphones:before{content:"\f025"} | |
942 | .icon-volume-off:before{content:"\f026"} |
|
942 | .icon-volume-off:before{content:"\f026"} | |
943 | .icon-volume-down:before{content:"\f027"} |
|
943 | .icon-volume-down:before{content:"\f027"} | |
944 | .icon-volume-up:before{content:"\f028"} |
|
944 | .icon-volume-up:before{content:"\f028"} | |
945 | .icon-qrcode:before{content:"\f029"} |
|
945 | .icon-qrcode:before{content:"\f029"} | |
946 | .icon-barcode:before{content:"\f02a"} |
|
946 | .icon-barcode:before{content:"\f02a"} | |
947 | .icon-tag:before{content:"\f02b"} |
|
947 | .icon-tag:before{content:"\f02b"} | |
948 | .icon-tags:before{content:"\f02c"} |
|
948 | .icon-tags:before{content:"\f02c"} | |
949 | .icon-book:before{content:"\f02d"} |
|
949 | .icon-book:before{content:"\f02d"} | |
950 | .icon-bookmark:before{content:"\f02e"} |
|
950 | .icon-bookmark:before{content:"\f02e"} | |
951 | .icon-print:before{content:"\f02f"} |
|
951 | .icon-print:before{content:"\f02f"} | |
952 | .icon-camera:before{content:"\f030"} |
|
952 | .icon-camera:before{content:"\f030"} | |
953 | .icon-font:before{content:"\f031"} |
|
953 | .icon-font:before{content:"\f031"} | |
954 | .icon-bold:before{content:"\f032"} |
|
954 | .icon-bold:before{content:"\f032"} | |
955 | .icon-italic:before{content:"\f033"} |
|
955 | .icon-italic:before{content:"\f033"} | |
956 | .icon-text-height:before{content:"\f034"} |
|
956 | .icon-text-height:before{content:"\f034"} | |
957 | .icon-text-width:before{content:"\f035"} |
|
957 | .icon-text-width:before{content:"\f035"} | |
958 | .icon-align-left:before{content:"\f036"} |
|
958 | .icon-align-left:before{content:"\f036"} | |
959 | .icon-align-center:before{content:"\f037"} |
|
959 | .icon-align-center:before{content:"\f037"} | |
960 | .icon-align-right:before{content:"\f038"} |
|
960 | .icon-align-right:before{content:"\f038"} | |
961 | .icon-align-justify:before{content:"\f039"} |
|
961 | .icon-align-justify:before{content:"\f039"} | |
962 | .icon-list:before{content:"\f03a"} |
|
962 | .icon-list:before{content:"\f03a"} | |
963 | .icon-indent-left:before{content:"\f03b"} |
|
963 | .icon-indent-left:before{content:"\f03b"} | |
964 | .icon-indent-right:before{content:"\f03c"} |
|
964 | .icon-indent-right:before{content:"\f03c"} | |
965 | .icon-facetime-video:before{content:"\f03d"} |
|
965 | .icon-facetime-video:before{content:"\f03d"} | |
966 | .icon-picture:before{content:"\f03e"} |
|
966 | .icon-picture:before{content:"\f03e"} | |
967 | .icon-pencil:before{content:"\f040"} |
|
967 | .icon-pencil:before{content:"\f040"} | |
968 | .icon-map-marker:before{content:"\f041"} |
|
968 | .icon-map-marker:before{content:"\f041"} | |
969 | .icon-adjust:before{content:"\f042"} |
|
969 | .icon-adjust:before{content:"\f042"} | |
970 | .icon-tint:before{content:"\f043"} |
|
970 | .icon-tint:before{content:"\f043"} | |
971 | .icon-edit:before{content:"\f044"} |
|
971 | .icon-edit:before{content:"\f044"} | |
972 | .icon-share:before{content:"\f045"} |
|
972 | .icon-share:before{content:"\f045"} | |
973 | .icon-check:before{content:"\f046"} |
|
973 | .icon-check:before{content:"\f046"} | |
974 | .icon-move:before{content:"\f047"} |
|
974 | .icon-move:before{content:"\f047"} | |
975 | .icon-step-backward:before{content:"\f048"} |
|
975 | .icon-step-backward:before{content:"\f048"} | |
976 | .icon-fast-backward:before{content:"\f049"} |
|
976 | .icon-fast-backward:before{content:"\f049"} | |
977 | .icon-backward:before{content:"\f04a"} |
|
977 | .icon-backward:before{content:"\f04a"} | |
978 | .icon-play:before{content:"\f04b"} |
|
978 | .icon-play:before{content:"\f04b"} | |
979 | .icon-pause:before{content:"\f04c"} |
|
979 | .icon-pause:before{content:"\f04c"} | |
980 | .icon-stop:before{content:"\f04d"} |
|
980 | .icon-stop:before{content:"\f04d"} | |
981 | .icon-forward:before{content:"\f04e"} |
|
981 | .icon-forward:before{content:"\f04e"} | |
982 | .icon-fast-forward:before{content:"\f050"} |
|
982 | .icon-fast-forward:before{content:"\f050"} | |
983 | .icon-step-forward:before{content:"\f051"} |
|
983 | .icon-step-forward:before{content:"\f051"} | |
984 | .icon-eject:before{content:"\f052"} |
|
984 | .icon-eject:before{content:"\f052"} | |
985 | .icon-chevron-left:before{content:"\f053"} |
|
985 | .icon-chevron-left:before{content:"\f053"} | |
986 | .icon-chevron-right:before{content:"\f054"} |
|
986 | .icon-chevron-right:before{content:"\f054"} | |
987 | .icon-plus-sign:before{content:"\f055"} |
|
987 | .icon-plus-sign:before{content:"\f055"} | |
988 | .icon-minus-sign:before{content:"\f056"} |
|
988 | .icon-minus-sign:before{content:"\f056"} | |
989 | .icon-remove-sign:before{content:"\f057"} |
|
989 | .icon-remove-sign:before{content:"\f057"} | |
990 | .icon-ok-sign:before{content:"\f058"} |
|
990 | .icon-ok-sign:before{content:"\f058"} | |
991 | .icon-question-sign:before{content:"\f059"} |
|
991 | .icon-question-sign:before{content:"\f059"} | |
992 | .icon-info-sign:before{content:"\f05a"} |
|
992 | .icon-info-sign:before{content:"\f05a"} | |
993 | .icon-screenshot:before{content:"\f05b"} |
|
993 | .icon-screenshot:before{content:"\f05b"} | |
994 | .icon-remove-circle:before{content:"\f05c"} |
|
994 | .icon-remove-circle:before{content:"\f05c"} | |
995 | .icon-ok-circle:before{content:"\f05d"} |
|
995 | .icon-ok-circle:before{content:"\f05d"} | |
996 | .icon-ban-circle:before{content:"\f05e"} |
|
996 | .icon-ban-circle:before{content:"\f05e"} | |
997 | .icon-arrow-left:before{content:"\f060"} |
|
997 | .icon-arrow-left:before{content:"\f060"} | |
998 | .icon-arrow-right:before{content:"\f061"} |
|
998 | .icon-arrow-right:before{content:"\f061"} | |
999 | .icon-arrow-up:before{content:"\f062"} |
|
999 | .icon-arrow-up:before{content:"\f062"} | |
1000 | .icon-arrow-down:before{content:"\f063"} |
|
1000 | .icon-arrow-down:before{content:"\f063"} | |
1001 | .icon-mail-forward:before,.icon-share-alt:before{content:"\f064"} |
|
1001 | .icon-mail-forward:before,.icon-share-alt:before{content:"\f064"} | |
1002 | .icon-resize-full:before{content:"\f065"} |
|
1002 | .icon-resize-full:before{content:"\f065"} | |
1003 | .icon-resize-small:before{content:"\f066"} |
|
1003 | .icon-resize-small:before{content:"\f066"} | |
1004 | .icon-plus:before{content:"\f067"} |
|
1004 | .icon-plus:before{content:"\f067"} | |
1005 | .icon-minus:before{content:"\f068"} |
|
1005 | .icon-minus:before{content:"\f068"} | |
1006 | .icon-asterisk:before{content:"\f069"} |
|
1006 | .icon-asterisk:before{content:"\f069"} | |
1007 | .icon-exclamation-sign:before{content:"\f06a"} |
|
1007 | .icon-exclamation-sign:before{content:"\f06a"} | |
1008 | .icon-gift:before{content:"\f06b"} |
|
1008 | .icon-gift:before{content:"\f06b"} | |
1009 | .icon-leaf:before{content:"\f06c"} |
|
1009 | .icon-leaf:before{content:"\f06c"} | |
1010 | .icon-fire:before{content:"\f06d"} |
|
1010 | .icon-fire:before{content:"\f06d"} | |
1011 | .icon-eye-open:before{content:"\f06e"} |
|
1011 | .icon-eye-open:before{content:"\f06e"} | |
1012 | .icon-eye-close:before{content:"\f070"} |
|
1012 | .icon-eye-close:before{content:"\f070"} | |
1013 | .icon-warning-sign:before{content:"\f071"} |
|
1013 | .icon-warning-sign:before{content:"\f071"} | |
1014 | .icon-plane:before{content:"\f072"} |
|
1014 | .icon-plane:before{content:"\f072"} | |
1015 | .icon-calendar:before{content:"\f073"} |
|
1015 | .icon-calendar:before{content:"\f073"} | |
1016 | .icon-random:before{content:"\f074"} |
|
1016 | .icon-random:before{content:"\f074"} | |
1017 | .icon-comment:before{content:"\f075"} |
|
1017 | .icon-comment:before{content:"\f075"} | |
1018 | .icon-magnet:before{content:"\f076"} |
|
1018 | .icon-magnet:before{content:"\f076"} | |
1019 | .icon-chevron-up:before{content:"\f077"} |
|
1019 | .icon-chevron-up:before{content:"\f077"} | |
1020 | .icon-chevron-down:before{content:"\f078"} |
|
1020 | .icon-chevron-down:before{content:"\f078"} | |
1021 | .icon-retweet:before{content:"\f079"} |
|
1021 | .icon-retweet:before{content:"\f079"} | |
1022 | .icon-shopping-cart:before{content:"\f07a"} |
|
1022 | .icon-shopping-cart:before{content:"\f07a"} | |
1023 | .icon-folder-close:before{content:"\f07b"} |
|
1023 | .icon-folder-close:before{content:"\f07b"} | |
1024 | .icon-folder-open:before{content:"\f07c"} |
|
1024 | .icon-folder-open:before{content:"\f07c"} | |
1025 | .icon-resize-vertical:before{content:"\f07d"} |
|
1025 | .icon-resize-vertical:before{content:"\f07d"} | |
1026 | .icon-resize-horizontal:before{content:"\f07e"} |
|
1026 | .icon-resize-horizontal:before{content:"\f07e"} | |
1027 | .icon-bar-chart:before{content:"\f080"} |
|
1027 | .icon-bar-chart:before{content:"\f080"} | |
1028 | .icon-twitter-sign:before{content:"\f081"} |
|
1028 | .icon-twitter-sign:before{content:"\f081"} | |
1029 | .icon-facebook-sign:before{content:"\f082"} |
|
1029 | .icon-facebook-sign:before{content:"\f082"} | |
1030 | .icon-camera-retro:before{content:"\f083"} |
|
1030 | .icon-camera-retro:before{content:"\f083"} | |
1031 | .icon-key:before{content:"\f084"} |
|
1031 | .icon-key:before{content:"\f084"} | |
1032 | .icon-gears:before,.icon-cogs:before{content:"\f085"} |
|
1032 | .icon-gears:before,.icon-cogs:before{content:"\f085"} | |
1033 | .icon-comments:before{content:"\f086"} |
|
1033 | .icon-comments:before{content:"\f086"} | |
1034 | .icon-thumbs-up-alt:before{content:"\f087"} |
|
1034 | .icon-thumbs-up-alt:before{content:"\f087"} | |
1035 | .icon-thumbs-down-alt:before{content:"\f088"} |
|
1035 | .icon-thumbs-down-alt:before{content:"\f088"} | |
1036 | .icon-star-half:before{content:"\f089"} |
|
1036 | .icon-star-half:before{content:"\f089"} | |
1037 | .icon-heart-empty:before{content:"\f08a"} |
|
1037 | .icon-heart-empty:before{content:"\f08a"} | |
1038 | .icon-signout:before{content:"\f08b"} |
|
1038 | .icon-signout:before{content:"\f08b"} | |
1039 | .icon-linkedin-sign:before{content:"\f08c"} |
|
1039 | .icon-linkedin-sign:before{content:"\f08c"} | |
1040 | .icon-pushpin:before{content:"\f08d"} |
|
1040 | .icon-pushpin:before{content:"\f08d"} | |
1041 | .icon-external-link:before{content:"\f08e"} |
|
1041 | .icon-external-link:before{content:"\f08e"} | |
1042 | .icon-signin:before{content:"\f090"} |
|
1042 | .icon-signin:before{content:"\f090"} | |
1043 | .icon-trophy:before{content:"\f091"} |
|
1043 | .icon-trophy:before{content:"\f091"} | |
1044 | .icon-github-sign:before{content:"\f092"} |
|
1044 | .icon-github-sign:before{content:"\f092"} | |
1045 | .icon-upload-alt:before{content:"\f093"} |
|
1045 | .icon-upload-alt:before{content:"\f093"} | |
1046 | .icon-lemon:before{content:"\f094"} |
|
1046 | .icon-lemon:before{content:"\f094"} | |
1047 | .icon-phone:before{content:"\f095"} |
|
1047 | .icon-phone:before{content:"\f095"} | |
1048 | .icon-unchecked:before,.icon-check-empty:before{content:"\f096"} |
|
1048 | .icon-unchecked:before,.icon-check-empty:before{content:"\f096"} | |
1049 | .icon-bookmark-empty:before{content:"\f097"} |
|
1049 | .icon-bookmark-empty:before{content:"\f097"} | |
1050 | .icon-phone-sign:before{content:"\f098"} |
|
1050 | .icon-phone-sign:before{content:"\f098"} | |
1051 | .icon-twitter:before{content:"\f099"} |
|
1051 | .icon-twitter:before{content:"\f099"} | |
1052 | .icon-facebook:before{content:"\f09a"} |
|
1052 | .icon-facebook:before{content:"\f09a"} | |
1053 | .icon-github:before{content:"\f09b"} |
|
1053 | .icon-github:before{content:"\f09b"} | |
1054 | .icon-unlock:before{content:"\f09c"} |
|
1054 | .icon-unlock:before{content:"\f09c"} | |
1055 | .icon-credit-card:before{content:"\f09d"} |
|
1055 | .icon-credit-card:before{content:"\f09d"} | |
1056 | .icon-rss:before{content:"\f09e"} |
|
1056 | .icon-rss:before{content:"\f09e"} | |
1057 | .icon-hdd:before{content:"\f0a0"} |
|
1057 | .icon-hdd:before{content:"\f0a0"} | |
1058 | .icon-bullhorn:before{content:"\f0a1"} |
|
1058 | .icon-bullhorn:before{content:"\f0a1"} | |
1059 | .icon-bell:before{content:"\f0a2"} |
|
1059 | .icon-bell:before{content:"\f0a2"} | |
1060 | .icon-certificate:before{content:"\f0a3"} |
|
1060 | .icon-certificate:before{content:"\f0a3"} | |
1061 | .icon-hand-right:before{content:"\f0a4"} |
|
1061 | .icon-hand-right:before{content:"\f0a4"} | |
1062 | .icon-hand-left:before{content:"\f0a5"} |
|
1062 | .icon-hand-left:before{content:"\f0a5"} | |
1063 | .icon-hand-up:before{content:"\f0a6"} |
|
1063 | .icon-hand-up:before{content:"\f0a6"} | |
1064 | .icon-hand-down:before{content:"\f0a7"} |
|
1064 | .icon-hand-down:before{content:"\f0a7"} | |
1065 | .icon-circle-arrow-left:before{content:"\f0a8"} |
|
1065 | .icon-circle-arrow-left:before{content:"\f0a8"} | |
1066 | .icon-circle-arrow-right:before{content:"\f0a9"} |
|
1066 | .icon-circle-arrow-right:before{content:"\f0a9"} | |
1067 | .icon-circle-arrow-up:before{content:"\f0aa"} |
|
1067 | .icon-circle-arrow-up:before{content:"\f0aa"} | |
1068 | .icon-circle-arrow-down:before{content:"\f0ab"} |
|
1068 | .icon-circle-arrow-down:before{content:"\f0ab"} | |
1069 | .icon-globe:before{content:"\f0ac"} |
|
1069 | .icon-globe:before{content:"\f0ac"} | |
1070 | .icon-wrench:before{content:"\f0ad"} |
|
1070 | .icon-wrench:before{content:"\f0ad"} | |
1071 | .icon-tasks:before{content:"\f0ae"} |
|
1071 | .icon-tasks:before{content:"\f0ae"} | |
1072 | .icon-filter:before{content:"\f0b0"} |
|
1072 | .icon-filter:before{content:"\f0b0"} | |
1073 | .icon-briefcase:before{content:"\f0b1"} |
|
1073 | .icon-briefcase:before{content:"\f0b1"} | |
1074 | .icon-fullscreen:before{content:"\f0b2"} |
|
1074 | .icon-fullscreen:before{content:"\f0b2"} | |
1075 | .icon-group:before{content:"\f0c0"} |
|
1075 | .icon-group:before{content:"\f0c0"} | |
1076 | .icon-link:before{content:"\f0c1"} |
|
1076 | .icon-link:before{content:"\f0c1"} | |
1077 | .icon-cloud:before{content:"\f0c2"} |
|
1077 | .icon-cloud:before{content:"\f0c2"} | |
1078 | .icon-beaker:before{content:"\f0c3"} |
|
1078 | .icon-beaker:before{content:"\f0c3"} | |
1079 | .icon-cut:before{content:"\f0c4"} |
|
1079 | .icon-cut:before{content:"\f0c4"} | |
1080 | .icon-copy:before{content:"\f0c5"} |
|
1080 | .icon-copy:before{content:"\f0c5"} | |
1081 | .icon-paperclip:before,.icon-paper-clip:before{content:"\f0c6"} |
|
1081 | .icon-paperclip:before,.icon-paper-clip:before{content:"\f0c6"} | |
1082 | .icon-save:before{content:"\f0c7"} |
|
1082 | .icon-save:before{content:"\f0c7"} | |
1083 | .icon-sign-blank:before{content:"\f0c8"} |
|
1083 | .icon-sign-blank:before{content:"\f0c8"} | |
1084 | .icon-reorder:before{content:"\f0c9"} |
|
1084 | .icon-reorder:before{content:"\f0c9"} | |
1085 | .icon-list-ul:before{content:"\f0ca"} |
|
1085 | .icon-list-ul:before{content:"\f0ca"} | |
1086 | .icon-list-ol:before{content:"\f0cb"} |
|
1086 | .icon-list-ol:before{content:"\f0cb"} | |
1087 | .icon-strikethrough:before{content:"\f0cc"} |
|
1087 | .icon-strikethrough:before{content:"\f0cc"} | |
1088 | .icon-underline:before{content:"\f0cd"} |
|
1088 | .icon-underline:before{content:"\f0cd"} | |
1089 | .icon-table:before{content:"\f0ce"} |
|
1089 | .icon-table:before{content:"\f0ce"} | |
1090 | .icon-magic:before{content:"\f0d0"} |
|
1090 | .icon-magic:before{content:"\f0d0"} | |
1091 | .icon-truck:before{content:"\f0d1"} |
|
1091 | .icon-truck:before{content:"\f0d1"} | |
1092 | .icon-pinterest:before{content:"\f0d2"} |
|
1092 | .icon-pinterest:before{content:"\f0d2"} | |
1093 | .icon-pinterest-sign:before{content:"\f0d3"} |
|
1093 | .icon-pinterest-sign:before{content:"\f0d3"} | |
1094 | .icon-google-plus-sign:before{content:"\f0d4"} |
|
1094 | .icon-google-plus-sign:before{content:"\f0d4"} | |
1095 | .icon-google-plus:before{content:"\f0d5"} |
|
1095 | .icon-google-plus:before{content:"\f0d5"} | |
1096 | .icon-money:before{content:"\f0d6"} |
|
1096 | .icon-money:before{content:"\f0d6"} | |
1097 | .icon-caret-down:before{content:"\f0d7"} |
|
1097 | .icon-caret-down:before{content:"\f0d7"} | |
1098 | .icon-caret-up:before{content:"\f0d8"} |
|
1098 | .icon-caret-up:before{content:"\f0d8"} | |
1099 | .icon-caret-left:before{content:"\f0d9"} |
|
1099 | .icon-caret-left:before{content:"\f0d9"} | |
1100 | .icon-caret-right:before{content:"\f0da"} |
|
1100 | .icon-caret-right:before{content:"\f0da"} | |
1101 | .icon-columns:before{content:"\f0db"} |
|
1101 | .icon-columns:before{content:"\f0db"} | |
1102 | .icon-sort:before{content:"\f0dc"} |
|
1102 | .icon-sort:before{content:"\f0dc"} | |
1103 | .icon-sort-down:before{content:"\f0dd"} |
|
1103 | .icon-sort-down:before{content:"\f0dd"} | |
1104 | .icon-sort-up:before{content:"\f0de"} |
|
1104 | .icon-sort-up:before{content:"\f0de"} | |
1105 | .icon-envelope:before{content:"\f0e0"} |
|
1105 | .icon-envelope:before{content:"\f0e0"} | |
1106 | .icon-linkedin:before{content:"\f0e1"} |
|
1106 | .icon-linkedin:before{content:"\f0e1"} | |
1107 | .icon-rotate-left:before,.icon-undo:before{content:"\f0e2"} |
|
1107 | .icon-rotate-left:before,.icon-undo:before{content:"\f0e2"} | |
1108 | .icon-legal:before{content:"\f0e3"} |
|
1108 | .icon-legal:before{content:"\f0e3"} | |
1109 | .icon-dashboard:before{content:"\f0e4"} |
|
1109 | .icon-dashboard:before{content:"\f0e4"} | |
1110 | .icon-comment-alt:before{content:"\f0e5"} |
|
1110 | .icon-comment-alt:before{content:"\f0e5"} | |
1111 | .icon-comments-alt:before{content:"\f0e6"} |
|
1111 | .icon-comments-alt:before{content:"\f0e6"} | |
1112 | .icon-bolt:before{content:"\f0e7"} |
|
1112 | .icon-bolt:before{content:"\f0e7"} | |
1113 | .icon-sitemap:before{content:"\f0e8"} |
|
1113 | .icon-sitemap:before{content:"\f0e8"} | |
1114 | .icon-umbrella:before{content:"\f0e9"} |
|
1114 | .icon-umbrella:before{content:"\f0e9"} | |
1115 | .icon-paste:before{content:"\f0ea"} |
|
1115 | .icon-paste:before{content:"\f0ea"} | |
1116 | .icon-lightbulb:before{content:"\f0eb"} |
|
1116 | .icon-lightbulb:before{content:"\f0eb"} | |
1117 | .icon-exchange:before{content:"\f0ec"} |
|
1117 | .icon-exchange:before{content:"\f0ec"} | |
1118 | .icon-cloud-download:before{content:"\f0ed"} |
|
1118 | .icon-cloud-download:before{content:"\f0ed"} | |
1119 | .icon-cloud-upload:before{content:"\f0ee"} |
|
1119 | .icon-cloud-upload:before{content:"\f0ee"} | |
1120 | .icon-user-md:before{content:"\f0f0"} |
|
1120 | .icon-user-md:before{content:"\f0f0"} | |
1121 | .icon-stethoscope:before{content:"\f0f1"} |
|
1121 | .icon-stethoscope:before{content:"\f0f1"} | |
1122 | .icon-suitcase:before{content:"\f0f2"} |
|
1122 | .icon-suitcase:before{content:"\f0f2"} | |
1123 | .icon-bell-alt:before{content:"\f0f3"} |
|
1123 | .icon-bell-alt:before{content:"\f0f3"} | |
1124 | .icon-coffee:before{content:"\f0f4"} |
|
1124 | .icon-coffee:before{content:"\f0f4"} | |
1125 | .icon-food:before{content:"\f0f5"} |
|
1125 | .icon-food:before{content:"\f0f5"} | |
1126 | .icon-file-text-alt:before{content:"\f0f6"} |
|
1126 | .icon-file-text-alt:before{content:"\f0f6"} | |
1127 | .icon-building:before{content:"\f0f7"} |
|
1127 | .icon-building:before{content:"\f0f7"} | |
1128 | .icon-hospital:before{content:"\f0f8"} |
|
1128 | .icon-hospital:before{content:"\f0f8"} | |
1129 | .icon-ambulance:before{content:"\f0f9"} |
|
1129 | .icon-ambulance:before{content:"\f0f9"} | |
1130 | .icon-medkit:before{content:"\f0fa"} |
|
1130 | .icon-medkit:before{content:"\f0fa"} | |
1131 | .icon-fighter-jet:before{content:"\f0fb"} |
|
1131 | .icon-fighter-jet:before{content:"\f0fb"} | |
1132 | .icon-beer:before{content:"\f0fc"} |
|
1132 | .icon-beer:before{content:"\f0fc"} | |
1133 | .icon-h-sign:before{content:"\f0fd"} |
|
1133 | .icon-h-sign:before{content:"\f0fd"} | |
1134 | .icon-plus-sign-alt:before{content:"\f0fe"} |
|
1134 | .icon-plus-sign-alt:before{content:"\f0fe"} | |
1135 | .icon-double-angle-left:before{content:"\f100"} |
|
1135 | .icon-double-angle-left:before{content:"\f100"} | |
1136 | .icon-double-angle-right:before{content:"\f101"} |
|
1136 | .icon-double-angle-right:before{content:"\f101"} | |
1137 | .icon-double-angle-up:before{content:"\f102"} |
|
1137 | .icon-double-angle-up:before{content:"\f102"} | |
1138 | .icon-double-angle-down:before{content:"\f103"} |
|
1138 | .icon-double-angle-down:before{content:"\f103"} | |
1139 | .icon-angle-left:before{content:"\f104"} |
|
1139 | .icon-angle-left:before{content:"\f104"} | |
1140 | .icon-angle-right:before{content:"\f105"} |
|
1140 | .icon-angle-right:before{content:"\f105"} | |
1141 | .icon-angle-up:before{content:"\f106"} |
|
1141 | .icon-angle-up:before{content:"\f106"} | |
1142 | .icon-angle-down:before{content:"\f107"} |
|
1142 | .icon-angle-down:before{content:"\f107"} | |
1143 | .icon-desktop:before{content:"\f108"} |
|
1143 | .icon-desktop:before{content:"\f108"} | |
1144 | .icon-laptop:before{content:"\f109"} |
|
1144 | .icon-laptop:before{content:"\f109"} | |
1145 | .icon-tablet:before{content:"\f10a"} |
|
1145 | .icon-tablet:before{content:"\f10a"} | |
1146 | .icon-mobile-phone:before{content:"\f10b"} |
|
1146 | .icon-mobile-phone:before{content:"\f10b"} | |
1147 | .icon-circle-blank:before{content:"\f10c"} |
|
1147 | .icon-circle-blank:before{content:"\f10c"} | |
1148 | .icon-quote-left:before{content:"\f10d"} |
|
1148 | .icon-quote-left:before{content:"\f10d"} | |
1149 | .icon-quote-right:before{content:"\f10e"} |
|
1149 | .icon-quote-right:before{content:"\f10e"} | |
1150 | .icon-spinner:before{content:"\f110"} |
|
1150 | .icon-spinner:before{content:"\f110"} | |
1151 | .icon-circle:before{content:"\f111"} |
|
1151 | .icon-circle:before{content:"\f111"} | |
1152 | .icon-mail-reply:before,.icon-reply:before{content:"\f112"} |
|
1152 | .icon-mail-reply:before,.icon-reply:before{content:"\f112"} | |
1153 | .icon-github-alt:before{content:"\f113"} |
|
1153 | .icon-github-alt:before{content:"\f113"} | |
1154 | .icon-folder-close-alt:before{content:"\f114"} |
|
1154 | .icon-folder-close-alt:before{content:"\f114"} | |
1155 | .icon-folder-open-alt:before{content:"\f115"} |
|
1155 | .icon-folder-open-alt:before{content:"\f115"} | |
1156 | .icon-expand-alt:before{content:"\f116"} |
|
1156 | .icon-expand-alt:before{content:"\f116"} | |
1157 | .icon-collapse-alt:before{content:"\f117"} |
|
1157 | .icon-collapse-alt:before{content:"\f117"} | |
1158 | .icon-smile:before{content:"\f118"} |
|
1158 | .icon-smile:before{content:"\f118"} | |
1159 | .icon-frown:before{content:"\f119"} |
|
1159 | .icon-frown:before{content:"\f119"} | |
1160 | .icon-meh:before{content:"\f11a"} |
|
1160 | .icon-meh:before{content:"\f11a"} | |
1161 | .icon-gamepad:before{content:"\f11b"} |
|
1161 | .icon-gamepad:before{content:"\f11b"} | |
1162 | .icon-keyboard:before{content:"\f11c"} |
|
1162 | .icon-keyboard:before{content:"\f11c"} | |
1163 | .icon-flag-alt:before{content:"\f11d"} |
|
1163 | .icon-flag-alt:before{content:"\f11d"} | |
1164 | .icon-flag-checkered:before{content:"\f11e"} |
|
1164 | .icon-flag-checkered:before{content:"\f11e"} | |
1165 | .icon-terminal:before{content:"\f120"} |
|
1165 | .icon-terminal:before{content:"\f120"} | |
1166 | .icon-code:before{content:"\f121"} |
|
1166 | .icon-code:before{content:"\f121"} | |
1167 | .icon-reply-all:before{content:"\f122"} |
|
1167 | .icon-reply-all:before{content:"\f122"} | |
1168 | .icon-mail-reply-all:before{content:"\f122"} |
|
1168 | .icon-mail-reply-all:before{content:"\f122"} | |
1169 | .icon-star-half-full:before,.icon-star-half-empty:before{content:"\f123"} |
|
1169 | .icon-star-half-full:before,.icon-star-half-empty:before{content:"\f123"} | |
1170 | .icon-location-arrow:before{content:"\f124"} |
|
1170 | .icon-location-arrow:before{content:"\f124"} | |
1171 | .icon-crop:before{content:"\f125"} |
|
1171 | .icon-crop:before{content:"\f125"} | |
1172 | .icon-code-fork:before{content:"\f126"} |
|
1172 | .icon-code-fork:before{content:"\f126"} | |
1173 | .icon-unlink:before{content:"\f127"} |
|
1173 | .icon-unlink:before{content:"\f127"} | |
1174 | .icon-question:before{content:"\f128"} |
|
1174 | .icon-question:before{content:"\f128"} | |
1175 | .icon-info:before{content:"\f129"} |
|
1175 | .icon-info:before{content:"\f129"} | |
1176 | .icon-exclamation:before{content:"\f12a"} |
|
1176 | .icon-exclamation:before{content:"\f12a"} | |
1177 | .icon-superscript:before{content:"\f12b"} |
|
1177 | .icon-superscript:before{content:"\f12b"} | |
1178 | .icon-subscript:before{content:"\f12c"} |
|
1178 | .icon-subscript:before{content:"\f12c"} | |
1179 | .icon-eraser:before{content:"\f12d"} |
|
1179 | .icon-eraser:before{content:"\f12d"} | |
1180 | .icon-puzzle-piece:before{content:"\f12e"} |
|
1180 | .icon-puzzle-piece:before{content:"\f12e"} | |
1181 | .icon-microphone:before{content:"\f130"} |
|
1181 | .icon-microphone:before{content:"\f130"} | |
1182 | .icon-microphone-off:before{content:"\f131"} |
|
1182 | .icon-microphone-off:before{content:"\f131"} | |
1183 | .icon-shield:before{content:"\f132"} |
|
1183 | .icon-shield:before{content:"\f132"} | |
1184 | .icon-calendar-empty:before{content:"\f133"} |
|
1184 | .icon-calendar-empty:before{content:"\f133"} | |
1185 | .icon-fire-extinguisher:before{content:"\f134"} |
|
1185 | .icon-fire-extinguisher:before{content:"\f134"} | |
1186 | .icon-rocket:before{content:"\f135"} |
|
1186 | .icon-rocket:before{content:"\f135"} | |
1187 | .icon-maxcdn:before{content:"\f136"} |
|
1187 | .icon-maxcdn:before{content:"\f136"} | |
1188 | .icon-chevron-sign-left:before{content:"\f137"} |
|
1188 | .icon-chevron-sign-left:before{content:"\f137"} | |
1189 | .icon-chevron-sign-right:before{content:"\f138"} |
|
1189 | .icon-chevron-sign-right:before{content:"\f138"} | |
1190 | .icon-chevron-sign-up:before{content:"\f139"} |
|
1190 | .icon-chevron-sign-up:before{content:"\f139"} | |
1191 | .icon-chevron-sign-down:before{content:"\f13a"} |
|
1191 | .icon-chevron-sign-down:before{content:"\f13a"} | |
1192 | .icon-html5:before{content:"\f13b"} |
|
1192 | .icon-html5:before{content:"\f13b"} | |
1193 | .icon-css3:before{content:"\f13c"} |
|
1193 | .icon-css3:before{content:"\f13c"} | |
1194 | .icon-anchor:before{content:"\f13d"} |
|
1194 | .icon-anchor:before{content:"\f13d"} | |
1195 | .icon-unlock-alt:before{content:"\f13e"} |
|
1195 | .icon-unlock-alt:before{content:"\f13e"} | |
1196 | .icon-bullseye:before{content:"\f140"} |
|
1196 | .icon-bullseye:before{content:"\f140"} | |
1197 | .icon-ellipsis-horizontal:before{content:"\f141"} |
|
1197 | .icon-ellipsis-horizontal:before{content:"\f141"} | |
1198 | .icon-ellipsis-vertical:before{content:"\f142"} |
|
1198 | .icon-ellipsis-vertical:before{content:"\f142"} | |
1199 | .icon-rss-sign:before{content:"\f143"} |
|
1199 | .icon-rss-sign:before{content:"\f143"} | |
1200 | .icon-play-sign:before{content:"\f144"} |
|
1200 | .icon-play-sign:before{content:"\f144"} | |
1201 | .icon-ticket:before{content:"\f145"} |
|
1201 | .icon-ticket:before{content:"\f145"} | |
1202 | .icon-minus-sign-alt:before{content:"\f146"} |
|
1202 | .icon-minus-sign-alt:before{content:"\f146"} | |
1203 | .icon-check-minus:before{content:"\f147"} |
|
1203 | .icon-check-minus:before{content:"\f147"} | |
1204 | .icon-level-up:before{content:"\f148"} |
|
1204 | .icon-level-up:before{content:"\f148"} | |
1205 | .icon-level-down:before{content:"\f149"} |
|
1205 | .icon-level-down:before{content:"\f149"} | |
1206 | .icon-check-sign:before{content:"\f14a"} |
|
1206 | .icon-check-sign:before{content:"\f14a"} | |
1207 | .icon-edit-sign:before{content:"\f14b"} |
|
1207 | .icon-edit-sign:before{content:"\f14b"} | |
1208 | .icon-external-link-sign:before{content:"\f14c"} |
|
1208 | .icon-external-link-sign:before{content:"\f14c"} | |
1209 | .icon-share-sign:before{content:"\f14d"} |
|
1209 | .icon-share-sign:before{content:"\f14d"} | |
1210 | .icon-compass:before{content:"\f14e"} |
|
1210 | .icon-compass:before{content:"\f14e"} | |
1211 | .icon-collapse:before{content:"\f150"} |
|
1211 | .icon-collapse:before{content:"\f150"} | |
1212 | .icon-collapse-top:before{content:"\f151"} |
|
1212 | .icon-collapse-top:before{content:"\f151"} | |
1213 | .icon-expand:before{content:"\f152"} |
|
1213 | .icon-expand:before{content:"\f152"} | |
1214 | .icon-euro:before,.icon-eur:before{content:"\f153"} |
|
1214 | .icon-euro:before,.icon-eur:before{content:"\f153"} | |
1215 | .icon-gbp:before{content:"\f154"} |
|
1215 | .icon-gbp:before{content:"\f154"} | |
1216 | .icon-dollar:before,.icon-usd:before{content:"\f155"} |
|
1216 | .icon-dollar:before,.icon-usd:before{content:"\f155"} | |
1217 | .icon-rupee:before,.icon-inr:before{content:"\f156"} |
|
1217 | .icon-rupee:before,.icon-inr:before{content:"\f156"} | |
1218 | .icon-yen:before,.icon-jpy:before{content:"\f157"} |
|
1218 | .icon-yen:before,.icon-jpy:before{content:"\f157"} | |
1219 | .icon-renminbi:before,.icon-cny:before{content:"\f158"} |
|
1219 | .icon-renminbi:before,.icon-cny:before{content:"\f158"} | |
1220 | .icon-won:before,.icon-krw:before{content:"\f159"} |
|
1220 | .icon-won:before,.icon-krw:before{content:"\f159"} | |
1221 | .icon-bitcoin:before,.icon-btc:before{content:"\f15a"} |
|
1221 | .icon-bitcoin:before,.icon-btc:before{content:"\f15a"} | |
1222 | .icon-file:before{content:"\f15b"} |
|
1222 | .icon-file:before{content:"\f15b"} | |
1223 | .icon-file-text:before{content:"\f15c"} |
|
1223 | .icon-file-text:before{content:"\f15c"} | |
1224 | .icon-sort-by-alphabet:before{content:"\f15d"} |
|
1224 | .icon-sort-by-alphabet:before{content:"\f15d"} | |
1225 | .icon-sort-by-alphabet-alt:before{content:"\f15e"} |
|
1225 | .icon-sort-by-alphabet-alt:before{content:"\f15e"} | |
1226 | .icon-sort-by-attributes:before{content:"\f160"} |
|
1226 | .icon-sort-by-attributes:before{content:"\f160"} | |
1227 | .icon-sort-by-attributes-alt:before{content:"\f161"} |
|
1227 | .icon-sort-by-attributes-alt:before{content:"\f161"} | |
1228 | .icon-sort-by-order:before{content:"\f162"} |
|
1228 | .icon-sort-by-order:before{content:"\f162"} | |
1229 | .icon-sort-by-order-alt:before{content:"\f163"} |
|
1229 | .icon-sort-by-order-alt:before{content:"\f163"} | |
1230 | .icon-thumbs-up:before{content:"\f164"} |
|
1230 | .icon-thumbs-up:before{content:"\f164"} | |
1231 | .icon-thumbs-down:before{content:"\f165"} |
|
1231 | .icon-thumbs-down:before{content:"\f165"} | |
1232 | .icon-youtube-sign:before{content:"\f166"} |
|
1232 | .icon-youtube-sign:before{content:"\f166"} | |
1233 | .icon-youtube:before{content:"\f167"} |
|
1233 | .icon-youtube:before{content:"\f167"} | |
1234 | .icon-xing:before{content:"\f168"} |
|
1234 | .icon-xing:before{content:"\f168"} | |
1235 | .icon-xing-sign:before{content:"\f169"} |
|
1235 | .icon-xing-sign:before{content:"\f169"} | |
1236 | .icon-youtube-play:before{content:"\f16a"} |
|
1236 | .icon-youtube-play:before{content:"\f16a"} | |
1237 | .icon-dropbox:before{content:"\f16b"} |
|
1237 | .icon-dropbox:before{content:"\f16b"} | |
1238 | .icon-stackexchange:before{content:"\f16c"} |
|
1238 | .icon-stackexchange:before{content:"\f16c"} | |
1239 | .icon-instagram:before{content:"\f16d"} |
|
1239 | .icon-instagram:before{content:"\f16d"} | |
1240 | .icon-flickr:before{content:"\f16e"} |
|
1240 | .icon-flickr:before{content:"\f16e"} | |
1241 | .icon-adn:before{content:"\f170"} |
|
1241 | .icon-adn:before{content:"\f170"} | |
1242 | .icon-bitbucket:before{content:"\f171"} |
|
1242 | .icon-bitbucket:before{content:"\f171"} | |
1243 | .icon-bitbucket-sign:before{content:"\f172"} |
|
1243 | .icon-bitbucket-sign:before{content:"\f172"} | |
1244 | .icon-tumblr:before{content:"\f173"} |
|
1244 | .icon-tumblr:before{content:"\f173"} | |
1245 | .icon-tumblr-sign:before{content:"\f174"} |
|
1245 | .icon-tumblr-sign:before{content:"\f174"} | |
1246 | .icon-long-arrow-down:before{content:"\f175"} |
|
1246 | .icon-long-arrow-down:before{content:"\f175"} | |
1247 | .icon-long-arrow-up:before{content:"\f176"} |
|
1247 | .icon-long-arrow-up:before{content:"\f176"} | |
1248 | .icon-long-arrow-left:before{content:"\f177"} |
|
1248 | .icon-long-arrow-left:before{content:"\f177"} | |
1249 | .icon-long-arrow-right:before{content:"\f178"} |
|
1249 | .icon-long-arrow-right:before{content:"\f178"} | |
1250 | .icon-apple:before{content:"\f179"} |
|
1250 | .icon-apple:before{content:"\f179"} | |
1251 | .icon-windows:before{content:"\f17a"} |
|
1251 | .icon-windows:before{content:"\f17a"} | |
1252 | .icon-android:before{content:"\f17b"} |
|
1252 | .icon-android:before{content:"\f17b"} | |
1253 | .icon-linux:before{content:"\f17c"} |
|
1253 | .icon-linux:before{content:"\f17c"} | |
1254 | .icon-dribbble:before{content:"\f17d"} |
|
1254 | .icon-dribbble:before{content:"\f17d"} | |
1255 | .icon-skype:before{content:"\f17e"} |
|
1255 | .icon-skype:before{content:"\f17e"} | |
1256 | .icon-foursquare:before{content:"\f180"} |
|
1256 | .icon-foursquare:before{content:"\f180"} | |
1257 | .icon-trello:before{content:"\f181"} |
|
1257 | .icon-trello:before{content:"\f181"} | |
1258 | .icon-female:before{content:"\f182"} |
|
1258 | .icon-female:before{content:"\f182"} | |
1259 | .icon-male:before{content:"\f183"} |
|
1259 | .icon-male:before{content:"\f183"} | |
1260 | .icon-gittip:before{content:"\f184"} |
|
1260 | .icon-gittip:before{content:"\f184"} | |
1261 | .icon-sun:before{content:"\f185"} |
|
1261 | .icon-sun:before{content:"\f185"} | |
1262 | .icon-moon:before{content:"\f186"} |
|
1262 | .icon-moon:before{content:"\f186"} | |
1263 | .icon-archive:before{content:"\f187"} |
|
1263 | .icon-archive:before{content:"\f187"} | |
1264 | .icon-bug:before{content:"\f188"} |
|
1264 | .icon-bug:before{content:"\f188"} | |
1265 | .icon-vk:before{content:"\f189"} |
|
1265 | .icon-vk:before{content:"\f189"} | |
1266 | .icon-weibo:before{content:"\f18a"} |
|
1266 | .icon-weibo:before{content:"\f18a"} | |
1267 | .icon-renren:before{content:"\f18b"} |
|
1267 | .icon-renren:before{content:"\f18b"} | |
1268 | code{color:#000} |
|
1268 | code{color:#000} | |
1269 | .border-box-sizing{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box} |
|
1269 | .border-box-sizing{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box} | |
1270 | .corner-all{border-radius:4px} |
|
1270 | .corner-all{border-radius:4px} | |
1271 | .hbox{display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch} |
|
1271 | .hbox{display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch} | |
1272 | .hbox>*{-webkit-box-flex:0;-moz-box-flex:0;box-flex:0;flex:none} |
|
1272 | .hbox>*{-webkit-box-flex:0;-moz-box-flex:0;box-flex:0;flex:none} | |
1273 | .vbox{display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch} |
|
1273 | .vbox{display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch} | |
1274 | .vbox>*{-webkit-box-flex:0;-moz-box-flex:0;box-flex:0;flex:none} |
|
1274 | .vbox>*{-webkit-box-flex:0;-moz-box-flex:0;box-flex:0;flex:none} | |
1275 | .hbox.reverse,.vbox.reverse,.reverse{-webkit-box-direction:reverse;-moz-box-direction:reverse;box-direction:reverse;flex-direction:row-reverse} |
|
1275 | .hbox.reverse,.vbox.reverse,.reverse{-webkit-box-direction:reverse;-moz-box-direction:reverse;box-direction:reverse;flex-direction:row-reverse} | |
1276 | .hbox.box-flex0,.vbox.box-flex0,.box-flex0{-webkit-box-flex:0;-moz-box-flex:0;box-flex:0;flex:none;width:auto} |
|
1276 | .hbox.box-flex0,.vbox.box-flex0,.box-flex0{-webkit-box-flex:0;-moz-box-flex:0;box-flex:0;flex:none;width:auto} | |
1277 | .hbox.box-flex1,.vbox.box-flex1,.box-flex1{-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1} |
|
1277 | .hbox.box-flex1,.vbox.box-flex1,.box-flex1{-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1} | |
1278 | .hbox.box-flex,.vbox.box-flex,.box-flex{-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1} |
|
1278 | .hbox.box-flex,.vbox.box-flex,.box-flex{-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1} | |
1279 | .hbox.box-flex2,.vbox.box-flex2,.box-flex2{-webkit-box-flex:2;-moz-box-flex:2;box-flex:2;flex:2} |
|
1279 | .hbox.box-flex2,.vbox.box-flex2,.box-flex2{-webkit-box-flex:2;-moz-box-flex:2;box-flex:2;flex:2} | |
1280 | .box-group1{-webkit-box-flex-group:1;-moz-box-flex-group:1;box-flex-group:1} |
|
1280 | .box-group1{-webkit-box-flex-group:1;-moz-box-flex-group:1;box-flex-group:1} | |
1281 | .box-group2{-webkit-box-flex-group:2;-moz-box-flex-group:2;box-flex-group:2} |
|
1281 | .box-group2{-webkit-box-flex-group:2;-moz-box-flex-group:2;box-flex-group:2} | |
1282 | .hbox.start,.vbox.start,.start{-webkit-box-pack:start;-moz-box-pack:start;box-pack:start;justify-content:flex-start} |
|
1282 | .hbox.start,.vbox.start,.start{-webkit-box-pack:start;-moz-box-pack:start;box-pack:start;justify-content:flex-start} | |
1283 | .hbox.end,.vbox.end,.end{-webkit-box-pack:end;-moz-box-pack:end;box-pack:end;justify-content:flex-end} |
|
1283 | .hbox.end,.vbox.end,.end{-webkit-box-pack:end;-moz-box-pack:end;box-pack:end;justify-content:flex-end} | |
1284 | .hbox.center,.vbox.center,.center{-webkit-box-pack:center;-moz-box-pack:center;box-pack:center;justify-content:center} |
|
1284 | .hbox.center,.vbox.center,.center{-webkit-box-pack:center;-moz-box-pack:center;box-pack:center;justify-content:center} | |
1285 | .hbox.align-start,.vbox.align-start,.align-start{-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start} |
|
1285 | .hbox.align-start,.vbox.align-start,.align-start{-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start} | |
1286 | .hbox.align-end,.vbox.align-end,.align-end{-webkit-box-align:end;-moz-box-align:end;box-align:end;align-items:flex-end} |
|
1286 | .hbox.align-end,.vbox.align-end,.align-end{-webkit-box-align:end;-moz-box-align:end;box-align:end;align-items:flex-end} | |
1287 | .hbox.align-center,.vbox.align-center,.align-center{-webkit-box-align:center;-moz-box-align:center;box-align:center;align-items:center} |
|
1287 | .hbox.align-center,.vbox.align-center,.align-center{-webkit-box-align:center;-moz-box-align:center;box-align:center;align-items:center} | |
1288 | div.error{margin:2em;text-align:center} |
|
1288 | div.error{margin:2em;text-align:center} | |
1289 | div.error>h1{font-size:500%;line-height:normal} |
|
1289 | div.error>h1{font-size:500%;line-height:normal} | |
1290 | div.error>p{font-size:200%;line-height:normal} |
|
1290 | div.error>p{font-size:200%;line-height:normal} | |
1291 | div.traceback-wrapper{text-align:left;max-width:800px;margin:auto} |
|
1291 | div.traceback-wrapper{text-align:left;max-width:800px;margin:auto} | |
1292 | body{background-color:#fff;position:absolute;left:0;right:0;top:0;bottom:0;overflow:visible} |
|
1292 | body{background-color:#fff;position:absolute;left:0;right:0;top:0;bottom:0;overflow:visible} | |
1293 | div#header{display:none} |
|
1293 | div#header{display:none} | |
1294 | #ipython_notebook{padding-left:16px} |
|
1294 | #ipython_notebook{padding-left:16px} | |
1295 | #noscript{width:auto;padding-top:16px;padding-bottom:16px;text-align:center;font-size:22px;color:#f00;font-weight:bold} |
|
1295 | #noscript{width:auto;padding-top:16px;padding-bottom:16px;text-align:center;font-size:22px;color:#f00;font-weight:bold} | |
1296 | #ipython_notebook img{font-family:Verdana,"Helvetica Neue",Arial,Helvetica,Geneva,sans-serif;height:24px;text-decoration:none;color:#000} |
|
1296 | #ipython_notebook img{font-family:Verdana,"Helvetica Neue",Arial,Helvetica,Geneva,sans-serif;height:24px;text-decoration:none;color:#000} | |
1297 | #site{width:100%;display:none} |
|
1297 | #site{width:100%;display:none} | |
1298 | .ui-button .ui-button-text{padding:.2em .8em;font-size:77%} |
|
1298 | .ui-button .ui-button-text{padding:.2em .8em;font-size:77%} | |
1299 | input.ui-button{padding:.3em .9em} |
|
1299 | input.ui-button{padding:.3em .9em} | |
1300 | .navbar span{margin-top:3px} |
|
1300 | .navbar span{margin-top:3px} | |
1301 | span#login_widget{float:right} |
|
1301 | span#login_widget{float:right} | |
1302 | .nav-header{text-transform:none} |
|
1302 | .nav-header{text-transform:none} | |
1303 | .navbar-nobg{background-color:transparent;background-image:none} |
|
1303 | .navbar-nobg{background-color:transparent;background-image:none} | |
1304 | #header>span{margin-top:10px} |
|
1304 | #header>span{margin-top:10px} | |
1305 | .modal-body{max-height:500px} |
|
1305 | .modal-body{max-height:500px} | |
1306 | @media (min-width:768px){.modal{width:700px;margin-left:-350px}}.center-nav{display:inline-block;margin-bottom:-4px} |
|
1306 | @media (min-width:768px){.modal{width:700px;margin-left:-350px}}.center-nav{display:inline-block;margin-bottom:-4px} | |
1307 | .alternate_upload{background-color:none;display:inline} |
|
1307 | .alternate_upload{background-color:none;display:inline} | |
1308 | .alternate_upload.form{padding:0;margin:0} |
|
1308 | .alternate_upload.form{padding:0;margin:0} | |
1309 | .alternate_upload input.fileinput{background-color:#f00;position:relative;opacity:0;z-index:2;width:295px;margin-left:163px;cursor:pointer;height:26px} |
|
1309 | .alternate_upload input.fileinput{background-color:#f00;position:relative;opacity:0;z-index:2;width:295px;margin-left:163px;cursor:pointer;height:26px} | |
1310 | ul#tabs{margin-bottom:4px} |
|
1310 | ul#tabs{margin-bottom:4px} | |
1311 | ul#tabs a{padding-top:4px;padding-bottom:4px} |
|
1311 | ul#tabs a{padding-top:4px;padding-bottom:4px} | |
1312 | ul.breadcrumb a:focus,ul.breadcrumb a:hover{text-decoration:none} |
|
1312 | ul.breadcrumb a:focus,ul.breadcrumb a:hover{text-decoration:none} | |
1313 | ul.breadcrumb i.icon-home{font-size:16px;margin-right:4px} |
|
1313 | ul.breadcrumb i.icon-home{font-size:16px;margin-right:4px} | |
1314 | ul.breadcrumb span{color:#5e5e5e} |
|
1314 | ul.breadcrumb span{color:#5e5e5e} | |
1315 | .list_toolbar{padding:4px 0 4px 0} |
|
1315 | .list_toolbar{padding:4px 0 4px 0} | |
1316 | .list_toolbar [class*="span"]{min-height:26px} |
|
1316 | .list_toolbar [class*="span"]{min-height:26px} | |
1317 | .list_header{font-weight:bold} |
|
1317 | .list_header{font-weight:bold} | |
1318 | .list_container{margin-top:4px;margin-bottom:20px;border:1px solid #ababab;border-radius:4px} |
|
1318 | .list_container{margin-top:4px;margin-bottom:20px;border:1px solid #ababab;border-radius:4px} | |
1319 | .list_container>div{border-bottom:1px solid #ababab}.list_container>div:hover .list-item{background-color:#f00} |
|
1319 | .list_container>div{border-bottom:1px solid #ababab}.list_container>div:hover .list-item{background-color:#f00} | |
1320 | .list_container>div:last-child{border:none} |
|
1320 | .list_container>div:last-child{border:none} | |
1321 | .list_item:hover .list_item{background-color:#ddd} |
|
1321 | .list_item:hover .list_item{background-color:#ddd} | |
1322 | .list_item a{text-decoration:none} |
|
1322 | .list_item a{text-decoration:none} | |
1323 | .list_header>div,.list_item>div{padding-top:4px;padding-bottom:4px;padding-left:7px;padding-right:7px;height:22px;line-height:22px} |
|
1323 | .list_header>div,.list_item>div{padding-top:4px;padding-bottom:4px;padding-left:7px;padding-right:7px;height:22px;line-height:22px} | |
1324 | .item_name{line-height:22px;height:26px} |
|
1324 | .item_name{line-height:22px;height:26px} | |
1325 | .item_icon{font-size:14px;color:#5e5e5e;margin-right:7px} |
|
1325 | .item_icon{font-size:14px;color:#5e5e5e;margin-right:7px} | |
1326 | .item_buttons{line-height:1em} |
|
1326 | .item_buttons{line-height:1em} | |
1327 | .toolbar_info{height:26px;line-height:26px} |
|
1327 | .toolbar_info{height:26px;line-height:26px} | |
1328 | input.nbname_input,input.engine_num_input{padding-top:3px;padding-bottom:3px;height:14px;line-height:14px;margin:0} |
|
1328 | input.nbname_input,input.engine_num_input{padding-top:3px;padding-bottom:3px;height:14px;line-height:14px;margin:0} | |
1329 | input.engine_num_input{width:60px} |
|
1329 | input.engine_num_input{width:60px} | |
1330 | .highlight_text{color:#00f} |
|
1330 | .highlight_text{color:#00f} | |
1331 | #project_name>.breadcrumb{padding:0;margin-bottom:0;background-color:transparent;font-weight:bold} |
|
1331 | #project_name>.breadcrumb{padding:0;margin-bottom:0;background-color:transparent;font-weight:bold} | |
1332 | .ansibold{font-weight:bold} |
|
1332 | .ansibold{font-weight:bold} | |
1333 | .ansiblack{color:#000} |
|
1333 | .ansiblack{color:#000} | |
1334 | .ansired{color:#8b0000} |
|
1334 | .ansired{color:#8b0000} | |
1335 | .ansigreen{color:#006400} |
|
1335 | .ansigreen{color:#006400} | |
1336 | .ansiyellow{color:#a52a2a} |
|
1336 | .ansiyellow{color:#a52a2a} | |
1337 | .ansiblue{color:#00008b} |
|
1337 | .ansiblue{color:#00008b} | |
1338 | .ansipurple{color:#9400d3} |
|
1338 | .ansipurple{color:#9400d3} | |
1339 | .ansicyan{color:#4682b4} |
|
1339 | .ansicyan{color:#4682b4} | |
1340 | .ansigray{color:#808080} |
|
1340 | .ansigray{color:#808080} | |
1341 | .ansibgblack{background-color:#000} |
|
1341 | .ansibgblack{background-color:#000} | |
1342 | .ansibgred{background-color:#f00} |
|
1342 | .ansibgred{background-color:#f00} | |
1343 | .ansibggreen{background-color:#008000} |
|
1343 | .ansibggreen{background-color:#008000} | |
1344 | .ansibgyellow{background-color:#ff0} |
|
1344 | .ansibgyellow{background-color:#ff0} | |
1345 | .ansibgblue{background-color:#00f} |
|
1345 | .ansibgblue{background-color:#00f} | |
1346 | .ansibgpurple{background-color:#f0f} |
|
1346 | .ansibgpurple{background-color:#f0f} | |
1347 | .ansibgcyan{background-color:#0ff} |
|
1347 | .ansibgcyan{background-color:#0ff} | |
1348 | .ansibggray{background-color:#808080} |
|
1348 | .ansibggray{background-color:#808080} | |
1349 | div.cell{border:1px solid transparent;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch}div.cell.selected{border-radius:4px;border:thin #ababab solid} |
|
1349 | div.cell{border:1px solid transparent;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch}div.cell.selected{border-radius:4px;border:thin #ababab solid} | |
1350 | div.cell.edit_mode{border-radius:4px;border:thin #008000 solid} |
|
1350 | div.cell.edit_mode{border-radius:4px;border:thin #008000 solid} | |
1351 | div.cell{width:100%;padding:5px 5px 5px 0;margin:0;outline:none} |
|
1351 | div.cell{width:100%;padding:5px 5px 5px 0;margin:0;outline:none} | |
1352 | div.prompt{min-width:11ex;padding:.4em;margin:0;font-family:monospace;text-align:right;line-height:1.21429em} |
|
1352 | div.prompt{min-width:11ex;padding:.4em;margin:0;font-family:monospace;text-align:right;line-height:1.21429em} | |
1353 | div.inner_cell{display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1} |
|
1353 | div.inner_cell{display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1} | |
1354 | div.input_area{border:1px solid #cfcfcf;border-radius:4px;background:#f7f7f7} |
|
1354 | div.input_area{border:1px solid #cfcfcf;border-radius:4px;background:#f7f7f7} | |
1355 | div.prompt:empty{padding-top:0;padding-bottom:0} |
|
1355 | div.prompt:empty{padding-top:0;padding-bottom:0} | |
1356 | div.input{page-break-inside:avoid;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch} |
|
1356 | div.input{page-break-inside:avoid;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch} | |
1357 | div.input_prompt{color:#000080;border-top:1px solid transparent} |
|
1357 | div.input_prompt{color:#000080;border-top:1px solid transparent} | |
1358 | div.input_area>div.highlight{margin:.4em;border:none;padding:0;background-color:transparent} |
|
1358 | div.input_area>div.highlight{margin:.4em;border:none;padding:0;background-color:transparent} | |
1359 | div.input_area>div.highlight>pre{margin:0;border:0;padding:0;background-color:transparent;font-size:14px;line-height:1.21429em} |
|
1359 | div.input_area>div.highlight>pre{margin:0;border:0;padding:0;background-color:transparent;font-size:14px;line-height:1.21429em} | |
1360 | .CodeMirror{line-height:1.21429em;height:auto;background:none;} |
|
1360 | .CodeMirror{line-height:1.21429em;height:auto;background:none;} | |
1361 | .CodeMirror-scroll{overflow-y:hidden;overflow-x:auto} |
|
1361 | .CodeMirror-scroll{overflow-y:hidden;overflow-x:auto} | |
1362 | @-moz-document url-prefix(){.CodeMirror-scroll{overflow-x:hidden}}.CodeMirror-lines{padding:.4em} |
|
1362 | @-moz-document url-prefix(){.CodeMirror-scroll{overflow-x:hidden}}.CodeMirror-lines{padding:.4em} | |
1363 | .CodeMirror-linenumber{padding:0 8px 0 4px} |
|
1363 | .CodeMirror-linenumber{padding:0 8px 0 4px} | |
1364 | .CodeMirror-gutters{border-bottom-left-radius:4px;border-top-left-radius:4px} |
|
1364 | .CodeMirror-gutters{border-bottom-left-radius:4px;border-top-left-radius:4px} | |
1365 | .CodeMirror pre{padding:0;border:0;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} |
|
1365 | .CodeMirror pre{padding:0;border:0;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} | |
1366 | pre code{display:block;padding:.5em} |
|
1366 | pre code{display:block;padding:.5em} | |
1367 | .highlight-base,pre code,pre .subst,pre .tag .title,pre .lisp .title,pre .clojure .built_in,pre .nginx .title{color:#000} |
|
1367 | .highlight-base,pre code,pre .subst,pre .tag .title,pre .lisp .title,pre .clojure .built_in,pre .nginx .title{color:#000} | |
1368 | .highlight-string,pre .string,pre .constant,pre .parent,pre .tag .value,pre .rules .value,pre .rules .value .number,pre .preprocessor,pre .ruby .symbol,pre .ruby .symbol .string,pre .aggregate,pre .template_tag,pre .django .variable,pre .smalltalk .class,pre .addition,pre .flow,pre .stream,pre .bash .variable,pre .apache .tag,pre .apache .cbracket,pre .tex .command,pre .tex .special,pre .erlang_repl .function_or_atom,pre .markdown .header{color:#ba2121} |
|
1368 | .highlight-string,pre .string,pre .constant,pre .parent,pre .tag .value,pre .rules .value,pre .rules .value .number,pre .preprocessor,pre .ruby .symbol,pre .ruby .symbol .string,pre .aggregate,pre .template_tag,pre .django .variable,pre .smalltalk .class,pre .addition,pre .flow,pre .stream,pre .bash .variable,pre .apache .tag,pre .apache .cbracket,pre .tex .command,pre .tex .special,pre .erlang_repl .function_or_atom,pre .markdown .header{color:#ba2121} | |
1369 | .highlight-comment,pre .comment,pre .annotation,pre .template_comment,pre .diff .header,pre .chunk,pre .markdown .blockquote{color:#408080;font-style:italic} |
|
1369 | .highlight-comment,pre .comment,pre .annotation,pre .template_comment,pre .diff .header,pre .chunk,pre .markdown .blockquote{color:#408080;font-style:italic} | |
1370 | .highlight-number,pre .number,pre .date,pre .regexp,pre .literal,pre .smalltalk .symbol,pre .smalltalk .char,pre .go .constant,pre .change,pre .markdown .bullet,pre .markdown .link_url{color:#080} |
|
1370 | .highlight-number,pre .number,pre .date,pre .regexp,pre .literal,pre .smalltalk .symbol,pre .smalltalk .char,pre .go .constant,pre .change,pre .markdown .bullet,pre .markdown .link_url{color:#080} | |
1371 | pre .label,pre .javadoc,pre .ruby .string,pre .decorator,pre .filter .argument,pre .localvars,pre .array,pre .attr_selector,pre .important,pre .pseudo,pre .pi,pre .doctype,pre .deletion,pre .envvar,pre .shebang,pre .apache .sqbracket,pre .nginx .built_in,pre .tex .formula,pre .erlang_repl .reserved,pre .prompt,pre .markdown .link_label,pre .vhdl .attribute,pre .clojure .attribute,pre .coffeescript .property{color:#88f} |
|
1371 | pre .label,pre .javadoc,pre .ruby .string,pre .decorator,pre .filter .argument,pre .localvars,pre .array,pre .attr_selector,pre .important,pre .pseudo,pre .pi,pre .doctype,pre .deletion,pre .envvar,pre .shebang,pre .apache .sqbracket,pre .nginx .built_in,pre .tex .formula,pre .erlang_repl .reserved,pre .prompt,pre .markdown .link_label,pre .vhdl .attribute,pre .clojure .attribute,pre .coffeescript .property{color:#88f} | |
1372 | .highlight-keyword,pre .keyword,pre .id,pre .phpdoc,pre .aggregate,pre .css .tag,pre .javadoctag,pre .phpdoc,pre .yardoctag,pre .smalltalk .class,pre .winutils,pre .bash .variable,pre .apache .tag,pre .go .typename,pre .tex .command,pre .markdown .strong,pre .request,pre .status{color:#008000;font-weight:bold} |
|
1372 | .highlight-keyword,pre .keyword,pre .id,pre .phpdoc,pre .aggregate,pre .css .tag,pre .javadoctag,pre .phpdoc,pre .yardoctag,pre .smalltalk .class,pre .winutils,pre .bash .variable,pre .apache .tag,pre .go .typename,pre .tex .command,pre .markdown .strong,pre .request,pre .status{color:#008000;font-weight:bold} | |
1373 | .highlight-builtin,pre .built_in{color:#008000} |
|
1373 | .highlight-builtin,pre .built_in{color:#008000} | |
1374 | pre .markdown .emphasis{font-style:italic} |
|
1374 | pre .markdown .emphasis{font-style:italic} | |
1375 | pre .nginx .built_in{font-weight:normal} |
|
1375 | pre .nginx .built_in{font-weight:normal} | |
1376 | pre .coffeescript .javascript,pre .javascript .xml,pre .tex .formula,pre .xml .javascript,pre .xml .vbscript,pre .xml .css,pre .xml .cdata{opacity:.5} |
|
1376 | pre .coffeescript .javascript,pre .javascript .xml,pre .tex .formula,pre .xml .javascript,pre .xml .vbscript,pre .xml .css,pre .xml .cdata{opacity:.5} | |
1377 | .cm-s-ipython span.cm-variable{color:#000} |
|
1377 | .cm-s-ipython span.cm-variable{color:#000} | |
1378 | .cm-s-ipython span.cm-keyword{color:#008000;font-weight:bold} |
|
1378 | .cm-s-ipython span.cm-keyword{color:#008000;font-weight:bold} | |
1379 | .cm-s-ipython span.cm-number{color:#080} |
|
1379 | .cm-s-ipython span.cm-number{color:#080} | |
1380 | .cm-s-ipython span.cm-comment{color:#408080;font-style:italic} |
|
1380 | .cm-s-ipython span.cm-comment{color:#408080;font-style:italic} | |
1381 | .cm-s-ipython span.cm-string{color:#ba2121} |
|
1381 | .cm-s-ipython span.cm-string{color:#ba2121} | |
1382 | .cm-s-ipython span.cm-builtin{color:#008000} |
|
1382 | .cm-s-ipython span.cm-builtin{color:#008000} | |
1383 | .cm-s-ipython span.cm-error{color:#f00} |
|
1383 | .cm-s-ipython span.cm-error{color:#f00} | |
1384 | .cm-s-ipython span.cm-operator{color:#a2f;font-weight:bold} |
|
1384 | .cm-s-ipython span.cm-operator{color:#a2f;font-weight:bold} | |
1385 | .cm-s-ipython span.cm-meta{color:#a2f} |
|
1385 | .cm-s-ipython span.cm-meta{color:#a2f} | |
1386 | .cm-s-ipython span.cm-tab{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);background-position:right;background-repeat:no-repeat} |
|
1386 | .cm-s-ipython span.cm-tab{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);background-position:right;background-repeat:no-repeat} | |
1387 | div.output_wrapper{position:relative;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch} |
|
1387 | div.output_wrapper{position:relative;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch} | |
1388 | div.output_scroll{height:24em;width:100%;overflow:auto;border-radius:4px;-webkit-box-shadow:inset 0 2px 8px rgba(0,0,0,0.8);-moz-box-shadow:inset 0 2px 8px rgba(0,0,0,0.8);box-shadow:inset 0 2px 8px rgba(0,0,0,0.8);display:block} |
|
1388 | div.output_scroll{height:24em;width:100%;overflow:auto;border-radius:4px;-webkit-box-shadow:inset 0 2px 8px rgba(0,0,0,0.8);-moz-box-shadow:inset 0 2px 8px rgba(0,0,0,0.8);box-shadow:inset 0 2px 8px rgba(0,0,0,0.8);display:block} | |
1389 | div.output_collapsed{margin:0;padding:0;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch} |
|
1389 | div.output_collapsed{margin:0;padding:0;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch} | |
1390 | div.out_prompt_overlay{height:100%;padding:0 .4em;position:absolute;border-radius:4px} |
|
1390 | div.out_prompt_overlay{height:100%;padding:0 .4em;position:absolute;border-radius:4px} | |
1391 | div.out_prompt_overlay:hover{-webkit-box-shadow:inset 0 0 1px #000;-moz-box-shadow:inset 0 0 1px #000;box-shadow:inset 0 0 1px #000;background:rgba(240,240,240,0.5)} |
|
1391 | div.out_prompt_overlay:hover{-webkit-box-shadow:inset 0 0 1px #000;-moz-box-shadow:inset 0 0 1px #000;box-shadow:inset 0 0 1px #000;background:rgba(240,240,240,0.5)} | |
1392 | div.output_prompt{color:#8b0000} |
|
1392 | div.output_prompt{color:#8b0000} | |
1393 | div.output_area{padding:0;page-break-inside:avoid;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch}div.output_area .MathJax_Display{text-align:left !important} |
|
1393 | div.output_area{padding:0;page-break-inside:avoid;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch}div.output_area .MathJax_Display{text-align:left !important} | |
1394 | div.output_area .rendered_html table{margin-left:0;margin-right:0} |
|
1394 | div.output_area .rendered_html table{margin-left:0;margin-right:0} | |
1395 | div.output_area .rendered_html img{margin-left:0;margin-right:0} |
|
1395 | div.output_area .rendered_html img{margin-left:0;margin-right:0} | |
1396 | .output{display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch} |
|
1396 | .output{display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch} | |
1397 | div.output_area pre{margin:0;padding:0;border:0;font-size:100%;vertical-align:baseline;color:#000;background-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;line-height:inherit} |
|
1397 | div.output_area pre{margin:0;padding:0;border:0;font-size:100%;vertical-align:baseline;color:#000;background-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;line-height:inherit} | |
1398 | div.output_subarea{padding:.4em .4em 0 .4em;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1} |
|
1398 | div.output_subarea{padding:.4em .4em 0 .4em;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1} | |
1399 | div.output_text{text-align:left;color:#000;line-height:1.21429em} |
|
1399 | div.output_text{text-align:left;color:#000;line-height:1.21429em} | |
1400 | div.output_stderr{background:#fdd;} |
|
1400 | div.output_stderr{background:#fdd;} | |
1401 | div.output_latex{text-align:left} |
|
1401 | div.output_latex{text-align:left} | |
1402 | div.output_javascript:empty{padding:0} |
|
1402 | div.output_javascript:empty{padding:0} | |
1403 | .js-error{color:#8b0000} |
|
1403 | .js-error{color:#8b0000} | |
1404 | div.raw_input_container{font-family:monospace;padding-top:5px} |
|
1404 | div.raw_input_container{font-family:monospace;padding-top:5px} | |
1405 | span.raw_input_prompt{} |
|
1405 | span.raw_input_prompt{} | |
1406 | input.raw_input{font-family:inherit;font-size:inherit;color:inherit;width:auto;vertical-align:baseline;padding:0 .25em;margin:0 .25em} |
|
1406 | input.raw_input{font-family:inherit;font-size:inherit;color:inherit;width:auto;vertical-align:baseline;padding:0 .25em;margin:0 .25em} | |
1407 | input.raw_input:focus{box-shadow:none} |
|
1407 | input.raw_input:focus{box-shadow:none} | |
1408 | p.p-space{margin-bottom:10px} |
|
1408 | p.p-space{margin-bottom:10px} | |
1409 | .rendered_html{color:#000;}.rendered_html em{font-style:italic} |
|
1409 | .rendered_html{color:#000;}.rendered_html em{font-style:italic} | |
1410 | .rendered_html strong{font-weight:bold} |
|
1410 | .rendered_html strong{font-weight:bold} | |
1411 | .rendered_html u{text-decoration:underline} |
|
1411 | .rendered_html u{text-decoration:underline} | |
1412 | .rendered_html :link{text-decoration:underline} |
|
1412 | .rendered_html :link{text-decoration:underline} | |
1413 | .rendered_html :visited{text-decoration:underline} |
|
1413 | .rendered_html :visited{text-decoration:underline} | |
1414 | .rendered_html h1{font-size:185.7%;margin:1.08em 0 0 0;font-weight:bold;line-height:1} |
|
1414 | .rendered_html h1{font-size:185.7%;margin:1.08em 0 0 0;font-weight:bold;line-height:1} | |
1415 | .rendered_html h2{font-size:157.1%;margin:1.27em 0 0 0;font-weight:bold;line-height:1} |
|
1415 | .rendered_html h2{font-size:157.1%;margin:1.27em 0 0 0;font-weight:bold;line-height:1} | |
1416 | .rendered_html h3{font-size:128.6%;margin:1.55em 0 0 0;font-weight:bold;line-height:1} |
|
1416 | .rendered_html h3{font-size:128.6%;margin:1.55em 0 0 0;font-weight:bold;line-height:1} | |
1417 | .rendered_html h4{font-size:100%;margin:2em 0 0 0;font-weight:bold;line-height:1} |
|
1417 | .rendered_html h4{font-size:100%;margin:2em 0 0 0;font-weight:bold;line-height:1} | |
1418 | .rendered_html h5{font-size:100%;margin:2em 0 0 0;font-weight:bold;line-height:1;font-style:italic} |
|
1418 | .rendered_html h5{font-size:100%;margin:2em 0 0 0;font-weight:bold;line-height:1;font-style:italic} | |
1419 | .rendered_html h6{font-size:100%;margin:2em 0 0 0;font-weight:bold;line-height:1;font-style:italic} |
|
1419 | .rendered_html h6{font-size:100%;margin:2em 0 0 0;font-weight:bold;line-height:1;font-style:italic} | |
1420 | .rendered_html h1:first-child{margin-top:.538em} |
|
1420 | .rendered_html h1:first-child{margin-top:.538em} | |
1421 | .rendered_html h2:first-child{margin-top:.636em} |
|
1421 | .rendered_html h2:first-child{margin-top:.636em} | |
1422 | .rendered_html h3:first-child{margin-top:.777em} |
|
1422 | .rendered_html h3:first-child{margin-top:.777em} | |
1423 | .rendered_html h4:first-child{margin-top:1em} |
|
1423 | .rendered_html h4:first-child{margin-top:1em} | |
1424 | .rendered_html h5:first-child{margin-top:1em} |
|
1424 | .rendered_html h5:first-child{margin-top:1em} | |
1425 | .rendered_html h6:first-child{margin-top:1em} |
|
1425 | .rendered_html h6:first-child{margin-top:1em} | |
1426 | .rendered_html ul{list-style:disc;margin:0 2em} |
|
1426 | .rendered_html ul{list-style:disc;margin:0 2em} | |
1427 | .rendered_html ul ul{list-style:square;margin:0 2em} |
|
1427 | .rendered_html ul ul{list-style:square;margin:0 2em} | |
1428 | .rendered_html ul ul ul{list-style:circle;margin:0 2em} |
|
1428 | .rendered_html ul ul ul{list-style:circle;margin:0 2em} | |
1429 | .rendered_html ol{list-style:decimal;margin:0 2em} |
|
1429 | .rendered_html ol{list-style:decimal;margin:0 2em} | |
1430 | .rendered_html ol ol{list-style:upper-alpha;margin:0 2em} |
|
1430 | .rendered_html ol ol{list-style:upper-alpha;margin:0 2em} | |
1431 | .rendered_html ol ol ol{list-style:lower-alpha;margin:0 2em} |
|
1431 | .rendered_html ol ol ol{list-style:lower-alpha;margin:0 2em} | |
1432 | .rendered_html ol ol ol ol{list-style:lower-roman;margin:0 2em} |
|
1432 | .rendered_html ol ol ol ol{list-style:lower-roman;margin:0 2em} | |
1433 | .rendered_html ol ol ol ol ol{list-style:decimal;margin:0 2em} |
|
1433 | .rendered_html ol ol ol ol ol{list-style:decimal;margin:0 2em} | |
1434 | .rendered_html *+ul{margin-top:1em} |
|
1434 | .rendered_html *+ul{margin-top:1em} | |
1435 | .rendered_html *+ol{margin-top:1em} |
|
1435 | .rendered_html *+ol{margin-top:1em} | |
1436 | .rendered_html hr{color:#000;background-color:#000} |
|
1436 | .rendered_html hr{color:#000;background-color:#000} | |
1437 | .rendered_html pre{margin:1em 2em} |
|
1437 | .rendered_html pre{margin:1em 2em} | |
1438 | .rendered_html pre,.rendered_html code{border:0;background-color:#fff;color:#000;font-size:100%;padding:0} |
|
1438 | .rendered_html pre,.rendered_html code{border:0;background-color:#fff;color:#000;font-size:100%;padding:0} | |
1439 | .rendered_html blockquote{margin:1em 2em} |
|
1439 | .rendered_html blockquote{margin:1em 2em} | |
1440 | .rendered_html table{margin-left:auto;margin-right:auto;border:1px solid #000;border-collapse:collapse} |
|
1440 | .rendered_html table{margin-left:auto;margin-right:auto;border:1px solid #000;border-collapse:collapse} | |
1441 | .rendered_html tr,.rendered_html th,.rendered_html td{border:1px solid #000;border-collapse:collapse;margin:1em 2em} |
|
1441 | .rendered_html tr,.rendered_html th,.rendered_html td{border:1px solid #000;border-collapse:collapse;margin:1em 2em} | |
1442 | .rendered_html td,.rendered_html th{text-align:left;vertical-align:middle;padding:4px} |
|
1442 | .rendered_html td,.rendered_html th{text-align:left;vertical-align:middle;padding:4px} | |
1443 | .rendered_html th{font-weight:bold} |
|
1443 | .rendered_html th{font-weight:bold} | |
1444 | .rendered_html *+table{margin-top:1em} |
|
1444 | .rendered_html *+table{margin-top:1em} | |
1445 | .rendered_html p{text-align:justify} |
|
1445 | .rendered_html p{text-align:justify} | |
1446 | .rendered_html *+p{margin-top:1em} |
|
1446 | .rendered_html *+p{margin-top:1em} | |
1447 | .rendered_html img{display:block;margin-left:auto;margin-right:auto} |
|
1447 | .rendered_html img{display:block;margin-left:auto;margin-right:auto} | |
1448 | .rendered_html *+img{margin-top:1em} |
|
1448 | .rendered_html *+img{margin-top:1em} | |
1449 | div.text_cell{padding:5px 5px 5px 0;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch} |
|
1449 | div.text_cell{padding:5px 5px 5px 0;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch} | |
1450 | div.text_cell_render{outline:none;resize:none;width:inherit;border-style:none;padding:.5em .5em .5em .4em;color:#000} |
|
1450 | div.text_cell_render{outline:none;resize:none;width:inherit;border-style:none;padding:.5em .5em .5em .4em;color:#000} | |
1451 | a.anchor-link:link{text-decoration:none;padding:0 20px;visibility:hidden} |
|
1451 | a.anchor-link:link{text-decoration:none;padding:0 20px;visibility:hidden} | |
1452 | h1:hover .anchor-link,h2:hover .anchor-link,h3:hover .anchor-link,h4:hover .anchor-link,h5:hover .anchor-link,h6:hover .anchor-link{visibility:visible} |
|
1452 | h1:hover .anchor-link,h2:hover .anchor-link,h3:hover .anchor-link,h4:hover .anchor-link,h5:hover .anchor-link,h6:hover .anchor-link{visibility:visible} | |
1453 | div.cell.text_cell.rendered{padding:0} |
|
1453 | div.cell.text_cell.rendered{padding:0} | |
1454 | .widget-area{page-break-inside:avoid;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch}.widget-area .widget-subarea{padding:.44em .4em .4em 1px;margin-left:6px;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch;-webkit-box-flex:2;-moz-box-flex:2;box-flex:2;flex:2;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start} |
|
1454 | .widget-area{page-break-inside:avoid;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch}.widget-area .widget-subarea{padding:.44em .4em .4em 1px;margin-left:6px;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch;-webkit-box-flex:2;-moz-box-flex:2;box-flex:2;flex:2;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start} | |
1455 | .widget-hlabel{min-width:10ex;padding-right:8px;padding-top:3px;text-align:right;vertical-align:text-top} |
|
1455 | .widget-hlabel{min-width:10ex;padding-right:8px;padding-top:3px;text-align:right;vertical-align:text-top} | |
1456 | .widget-vlabel{padding-bottom:5px;text-align:center;vertical-align:text-bottom} |
|
1456 | .widget-vlabel{padding-bottom:5px;text-align:center;vertical-align:text-bottom} | |
1457 | .widget-hreadout{padding-left:8px;padding-top:3px;text-align:left;vertical-align:text-top} |
|
1457 | .widget-hreadout{padding-left:8px;padding-top:3px;text-align:left;vertical-align:text-top} | |
1458 | .widget-vreadout{padding-top:5px;text-align:center;vertical-align:text-top} |
|
1458 | .widget-vreadout{padding-top:5px;text-align:center;vertical-align:text-top} | |
1459 | .slide-track{border:1px solid #ccc;background:#fff;border-radius:4px;} |
|
1459 | .slide-track{border:1px solid #ccc;background:#fff;border-radius:4px;} | |
1460 | .widget-hslider{padding-left:8px;padding-right:5px;overflow:visible;width:348px;height:5px;max-height:5px;margin-top:11px;margin-bottom:10px;border:1px solid #ccc;background:#fff;border-radius:4px;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch}.widget-hslider .ui-slider{border:0 !important;background:none !important;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1}.widget-hslider .ui-slider .ui-slider-handle{width:14px !important;height:28px !important;margin-top:-8px !important} |
|
1460 | .widget-hslider{padding-left:8px;padding-right:5px;overflow:visible;width:348px;height:5px;max-height:5px;margin-top:11px;margin-bottom:10px;border:1px solid #ccc;background:#fff;border-radius:4px;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch}.widget-hslider .ui-slider{border:0 !important;background:none !important;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1}.widget-hslider .ui-slider .ui-slider-handle{width:14px !important;height:28px !important;margin-top:-8px !important} | |
1461 | .widget-vslider{padding-bottom:8px;overflow:visible;width:5px;max-width:5px;height:250px;margin-left:12px;border:1px solid #ccc;background:#fff;border-radius:4px;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch}.widget-vslider .ui-slider{border:0 !important;background:none !important;margin-left:-4px;margin-top:5px;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1}.widget-vslider .ui-slider .ui-slider-handle{width:28px !important;height:14px !important;margin-left:-9px} |
|
1461 | .widget-vslider{padding-bottom:8px;overflow:visible;width:5px;max-width:5px;height:250px;margin-left:12px;border:1px solid #ccc;background:#fff;border-radius:4px;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch}.widget-vslider .ui-slider{border:0 !important;background:none !important;margin-left:-4px;margin-top:5px;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1}.widget-vslider .ui-slider .ui-slider-handle{width:28px !important;height:14px !important;margin-left:-9px} | |
1462 | .widget-text{width:350px;margin:0 !important} |
|
1462 | .widget-text{width:350px;margin:0 !important} | |
1463 | .widget-listbox{width:364px;margin-bottom:0} |
|
1463 | .widget-listbox{width:364px;margin-bottom:0} | |
1464 | .widget-numeric-text{width:150px;margin:0 !important} |
|
1464 | .widget-numeric-text{width:150px;margin:0 !important} | |
1465 | .widget-progress{width:363px}.widget-progress .bar{-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none} |
|
1465 | .widget-progress{width:363px}.widget-progress .bar{-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none} | |
1466 | .widget-combo-btn{min-width:138px;} |
|
1466 | .widget-combo-btn{min-width:138px;} | |
1467 | .widget-box{margin:5px;-webkit-box-pack:start;-moz-box-pack:start;box-pack:start;justify-content:flex-start;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start} |
|
1467 | .widget-box{margin:5px;-webkit-box-pack:start;-moz-box-pack:start;box-pack:start;justify-content:flex-start;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start} | |
1468 | .widget-hbox{margin:5px;-webkit-box-pack:start;-moz-box-pack:start;box-pack:start;justify-content:flex-start;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch} |
|
1468 | .widget-hbox{margin:5px;-webkit-box-pack:start;-moz-box-pack:start;box-pack:start;justify-content:flex-start;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch} | |
1469 | .widget-hbox-single{margin:5px;-webkit-box-pack:start;-moz-box-pack:start;box-pack:start;justify-content:flex-start;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch;height:30px} |
|
1469 | .widget-hbox-single{margin:5px;-webkit-box-pack:start;-moz-box-pack:start;box-pack:start;justify-content:flex-start;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch;height:30px} | |
1470 | .widget-vbox{margin:5px;-webkit-box-pack:start;-moz-box-pack:start;box-pack:start;justify-content:flex-start;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch} |
|
1470 | .widget-vbox{margin:5px;-webkit-box-pack:start;-moz-box-pack:start;box-pack:start;justify-content:flex-start;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch} | |
1471 | .widget-vbox-single{margin:5px;-webkit-box-pack:start;-moz-box-pack:start;box-pack:start;justify-content:flex-start;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch;width:30px} |
|
1471 | .widget-vbox-single{margin:5px;-webkit-box-pack:start;-moz-box-pack:start;box-pack:start;justify-content:flex-start;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start;display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch;width:30px} | |
1472 | .widget-modal{overflow:hidden;position:absolute !important;top:0;left:0;margin-left:0 !important} |
|
1472 | .widget-modal{overflow:hidden;position:absolute !important;top:0;left:0;margin-left:0 !important} | |
1473 | .widget-modal-body{max-height:none !important} |
|
1473 | .widget-modal-body{max-height:none !important} | |
1474 | .widget-container{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start} |
|
1474 | .widget-container{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-box-align:start;-moz-box-align:start;box-align:start;align-items:flex-start} | |
1475 | .widget-radio-box{display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding-top:4px} |
|
1475 | .widget-radio-box{display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:vertical;-moz-box-align:stretch;display:box;box-orient:vertical;box-align:stretch;width:100%;display:flex;flex-direction:column;align-items:stretch;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding-top:4px} | |
1476 | .docked-widget-modal{overflow:hidden;position:relative !important;top:0 !important;left:0 !important;margin-left:0 !important} |
|
1476 | .docked-widget-modal{overflow:hidden;position:relative !important;top:0 !important;left:0 !important;margin-left:0 !important} | |
1477 | body{background-color:#fff} |
|
1477 | body{background-color:#fff} | |
1478 | body.notebook_app{overflow:hidden} |
|
1478 | body.notebook_app{overflow:hidden} | |
1479 | span#notebook_name{height:1em;line-height:1em;padding:3px;border:none;font-size:146.5%} |
|
1479 | span#notebook_name{height:1em;line-height:1em;padding:3px;border:none;font-size:146.5%} | |
1480 | div#notebook_panel{margin:0 0 0 0;padding:0;-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)} |
|
1480 | div#notebook_panel{margin:0 0 0 0;padding:0;-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)} | |
1481 | div#notebook{font-size:14px;line-height:20px;overflow-y:scroll;overflow-x:auto;width:100%;padding:1em 0 1em 0;margin:0;border-top:1px solid #ababab;outline:none;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box} |
|
1481 | div#notebook{font-size:14px;line-height:20px;overflow-y:scroll;overflow-x:auto;width:100%;padding:1em 0 1em 0;margin:0;border-top:1px solid #ababab;outline:none;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box} | |
1482 | div.ui-widget-content{border:1px solid #ababab;outline:none} |
|
1482 | div.ui-widget-content{border:1px solid #ababab;outline:none} | |
1483 | pre.dialog{background-color:#f7f7f7;border:1px solid #ddd;border-radius:4px;padding:.4em;padding-left:2em} |
|
1483 | pre.dialog{background-color:#f7f7f7;border:1px solid #ddd;border-radius:4px;padding:.4em;padding-left:2em} | |
1484 | p.dialog{padding:.2em} |
|
1484 | p.dialog{padding:.2em} | |
1485 | pre,code,kbd,samp{white-space:pre-wrap} |
|
1485 | pre,code,kbd,samp{white-space:pre-wrap} | |
1486 | #fonttest{font-family:monospace} |
|
1486 | #fonttest{font-family:monospace} | |
1487 | p{margin-bottom:0} |
|
1487 | p{margin-bottom:0} | |
1488 | .end_space{height:200px} |
|
1488 | .end_space{height:200px} | |
1489 | .celltoolbar{border:thin solid #cfcfcf;border-bottom:none;background:#eee;border-radius:3px 3px 0 0;width:100%;-webkit-box-pack:end;height:22px;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch;-webkit-box-direction:reverse;-moz-box-direction:reverse;box-direction:reverse;flex-direction:row-reverse} |
|
1489 | .celltoolbar{border:thin solid #cfcfcf;border-bottom:none;background:#eee;border-radius:3px 3px 0 0;width:100%;-webkit-box-pack:end;height:22px;display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch;-webkit-box-direction:reverse;-moz-box-direction:reverse;box-direction:reverse;flex-direction:row-reverse} | |
1490 | .ctb_hideshow{display:none;vertical-align:bottom;padding-right:2px} |
|
1490 | .ctb_hideshow{display:none;vertical-align:bottom;padding-right:2px} | |
1491 | .celltoolbar>div{padding-top:0} |
|
1491 | .celltoolbar>div{padding-top:0} | |
1492 | .ctb_global_show .ctb_show.ctb_hideshow{display:block} |
|
1492 | .ctb_global_show .ctb_show.ctb_hideshow{display:block} | |
1493 | .ctb_global_show .ctb_show+.input_area,.ctb_global_show .ctb_show+div.text_cell_input{border-top-right-radius:0;border-top-left-radius:0} |
|
1493 | .ctb_global_show .ctb_show+.input_area,.ctb_global_show .ctb_show+div.text_cell_input{border-top-right-radius:0;border-top-left-radius:0} | |
1494 | .celltoolbar .button_container select{margin:10px;margin-top:1px;margin-bottom:0;padding:0;font-size:87%;width:auto;display:inline-block;height:18px;line-height:18px;vertical-align:top} |
|
1494 | .celltoolbar .button_container select{margin:10px;margin-top:1px;margin-bottom:0;padding:0;font-size:87%;width:auto;display:inline-block;height:18px;line-height:18px;vertical-align:top} | |
1495 | .celltoolbar label{display:inline-block;height:15px;line-height:15px;vertical-align:top} |
|
1495 | .celltoolbar label{display:inline-block;height:15px;line-height:15px;vertical-align:top} | |
1496 | .celltoolbar label span{font-size:85%} |
|
1496 | .celltoolbar label span{font-size:85%} | |
1497 | .celltoolbar input[type=checkbox]{margin:0;margin-left:4px;margin-right:4px} |
|
1497 | .celltoolbar input[type=checkbox]{margin:0;margin-left:4px;margin-right:4px} | |
1498 | .celltoolbar .ui-button{border:none;vertical-align:top;height:20px;min-width:30px} |
|
1498 | .celltoolbar .ui-button{border:none;vertical-align:top;height:20px;min-width:30px} | |
1499 | .completions{position:absolute;z-index:10;overflow:hidden;border:1px solid #ababab;border-radius:4px;-webkit-box-shadow:0 6px 10px -1px #adadad;-moz-box-shadow:0 6px 10px -1px #adadad;box-shadow:0 6px 10px -1px #adadad} |
|
1499 | .completions{position:absolute;z-index:10;overflow:hidden;border:1px solid #ababab;border-radius:4px;-webkit-box-shadow:0 6px 10px -1px #adadad;-moz-box-shadow:0 6px 10px -1px #adadad;box-shadow:0 6px 10px -1px #adadad} | |
1500 | .completions select{background:#fff;outline:none;border:none;padding:0;margin:0;overflow:auto;font-family:monospace;font-size:110%;color:#000} |
|
1500 | .completions select{background:#fff;outline:none;border:none;padding:0;margin:0;overflow:auto;font-family:monospace;font-size:110%;color:#000;width:auto} | |
1501 | .completions select option.context{color:#0064cd} |
|
1501 | .completions select option.context{color:#0064cd} | |
1502 | #menubar .navbar-inner{min-height:28px;border-top:1px;border-radius:0 0 4px 4px} |
|
1502 | #menubar .navbar-inner{min-height:28px;border-top:1px;border-radius:0 0 4px 4px} | |
1503 | #menubar .navbar{margin-bottom:8px} |
|
1503 | #menubar .navbar{margin-bottom:8px} | |
1504 | .nav-wrapper{border-bottom:1px solid #d4d4d4} |
|
1504 | .nav-wrapper{border-bottom:1px solid #d4d4d4} | |
1505 | #menubar li.dropdown{line-height:12px} |
|
1505 | #menubar li.dropdown{line-height:12px} | |
1506 | i.menu-icon{padding-top:4px} |
|
1506 | i.menu-icon{padding-top:4px} | |
1507 | ul#help_menu li a{overflow:hidden;padding-right:2.2em}ul#help_menu li a i{margin-right:-1.2em} |
|
1507 | ul#help_menu li a{overflow:hidden;padding-right:2.2em}ul#help_menu li a i{margin-right:-1.2em} | |
1508 | #notification_area{z-index:10} |
|
1508 | #notification_area{z-index:10} | |
1509 | .indicator_area{color:#777;padding:4px 3px;margin:0;width:11px;z-index:10;text-align:center} |
|
1509 | .indicator_area{color:#777;padding:4px 3px;margin:0;width:11px;z-index:10;text-align:center} | |
1510 | #kernel_indicator{margin-right:-16px} |
|
1510 | #kernel_indicator{margin-right:-16px} | |
1511 | .edit_mode_icon:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f040"} |
|
1511 | .edit_mode_icon:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f040"} | |
1512 | .command_mode_icon:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:' '} |
|
1512 | .command_mode_icon:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:' '} | |
1513 | .kernel_idle_icon:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f10c"} |
|
1513 | .kernel_idle_icon:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f10c"} | |
1514 | .kernel_busy_icon:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f111"} |
|
1514 | .kernel_busy_icon:before{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;content:"\f111"} | |
1515 | .notification_widget{color:#777;padding:1px 12px;margin:2px 4px;z-index:10;border:1px solid #ccc;border-radius:4px;background:rgba(240,240,240,0.5)}.notification_widget.span{padding-right:2px} |
|
1515 | .notification_widget{color:#777;padding:1px 12px;margin:2px 4px;z-index:10;border:1px solid #ccc;border-radius:4px;background:rgba(240,240,240,0.5)}.notification_widget.span{padding-right:2px} | |
1516 | div#pager_splitter{height:8px} |
|
1516 | div#pager_splitter{height:8px} | |
1517 | #pager-container{position:relative;padding:15px 0} |
|
1517 | #pager-container{position:relative;padding:15px 0} | |
1518 | div#pager{font-size:14px;line-height:20px;overflow:auto;display:none}div#pager pre{font-size:13px;line-height:1.21429em;color:#000;background-color:#f7f7f7;padding:.4em} |
|
1518 | div#pager{font-size:14px;line-height:20px;overflow:auto;display:none}div#pager pre{font-size:13px;line-height:1.21429em;color:#000;background-color:#f7f7f7;padding:.4em} | |
1519 | .quickhelp{display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch} |
|
1519 | .quickhelp{display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-align:stretch;display:-moz-box;-moz-box-orient:horizontal;-moz-box-align:stretch;display:box;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch} | |
1520 | .shortcut_key{display:inline-block;width:20ex;text-align:right;font-family:monospace} |
|
1520 | .shortcut_key{display:inline-block;width:20ex;text-align:right;font-family:monospace} | |
1521 | .shortcut_descr{display:inline-block;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1} |
|
1521 | .shortcut_descr{display:inline-block;-webkit-box-flex:1;-moz-box-flex:1;box-flex:1;flex:1} | |
1522 | span#save_widget{padding:0 5px;margin-top:12px} |
|
1522 | span#save_widget{padding:0 5px;margin-top:12px} | |
1523 | span#checkpoint_status,span#autosave_status{font-size:small} |
|
1523 | span#checkpoint_status,span#autosave_status{font-size:small} | |
1524 | @media (max-width:767px){span#save_widget{font-size:small} span#checkpoint_status,span#autosave_status{font-size:x-small}}@media (max-width:767px){span#checkpoint_status,span#autosave_status{display:none}}@media (min-width:768px) and (max-width:979px){span#checkpoint_status{display:none} span#autosave_status{font-size:x-small}}.toolbar{padding:0 10px;margin-top:-5px}.toolbar select,.toolbar label{width:auto;height:26px;vertical-align:middle;margin-right:2px;margin-bottom:0;display:inline;font-size:92%;margin-left:.3em;margin-right:.3em;padding:0;padding-top:3px} |
|
1524 | @media (max-width:767px){span#save_widget{font-size:small} span#checkpoint_status,span#autosave_status{font-size:x-small}}@media (max-width:767px){span#checkpoint_status,span#autosave_status{display:none}}@media (min-width:768px) and (max-width:979px){span#checkpoint_status{display:none} span#autosave_status{font-size:x-small}}.toolbar{padding:0 10px;margin-top:-5px}.toolbar select,.toolbar label{width:auto;height:26px;vertical-align:middle;margin-right:2px;margin-bottom:0;display:inline;font-size:92%;margin-left:.3em;margin-right:.3em;padding:0;padding-top:3px} | |
1525 | .toolbar .btn{padding:2px 8px} |
|
1525 | .toolbar .btn{padding:2px 8px} | |
1526 | .toolbar .btn-group{margin-top:0} |
|
1526 | .toolbar .btn-group{margin-top:0} | |
1527 | .toolbar-inner{border:none !important;-webkit-box-shadow:none !important;-moz-box-shadow:none !important;box-shadow:none !important} |
|
1527 | .toolbar-inner{border:none !important;-webkit-box-shadow:none !important;-moz-box-shadow:none !important;box-shadow:none !important} | |
1528 | #maintoolbar{margin-bottom:0} |
|
1528 | #maintoolbar{margin-bottom:0} | |
1529 | @-moz-keyframes fadeOut{from{opacity:1} to{opacity:0}}@-webkit-keyframes fadeOut{from{opacity:1} to{opacity:0}}@-moz-keyframes fadeIn{from{opacity:0} to{opacity:1}}@-webkit-keyframes fadeIn{from{opacity:0} to{opacity:1}}.bigtooltip{overflow:auto;height:200px;-webkit-transition-property:height;-webkit-transition-duration:500ms;-moz-transition-property:height;-moz-transition-duration:500ms;transition-property:height;transition-duration:500ms} |
|
1529 | @-moz-keyframes fadeOut{from{opacity:1} to{opacity:0}}@-webkit-keyframes fadeOut{from{opacity:1} to{opacity:0}}@-moz-keyframes fadeIn{from{opacity:0} to{opacity:1}}@-webkit-keyframes fadeIn{from{opacity:0} to{opacity:1}}.bigtooltip{overflow:auto;height:200px;-webkit-transition-property:height;-webkit-transition-duration:500ms;-moz-transition-property:height;-moz-transition-duration:500ms;transition-property:height;transition-duration:500ms} | |
1530 | .smalltooltip{-webkit-transition-property:height;-webkit-transition-duration:500ms;-moz-transition-property:height;-moz-transition-duration:500ms;transition-property:height;transition-duration:500ms;text-overflow:ellipsis;overflow:hidden;height:80px} |
|
1530 | .smalltooltip{-webkit-transition-property:height;-webkit-transition-duration:500ms;-moz-transition-property:height;-moz-transition-duration:500ms;transition-property:height;transition-duration:500ms;text-overflow:ellipsis;overflow:hidden;height:80px} | |
1531 | .tooltipbuttons{position:absolute;padding-right:15px;top:0;right:0} |
|
1531 | .tooltipbuttons{position:absolute;padding-right:15px;top:0;right:0} | |
1532 | .tooltiptext{padding-right:30px} |
|
1532 | .tooltiptext{padding-right:30px} | |
1533 | .ipython_tooltip{max-width:700px;-webkit-animation:fadeOut 400ms;-moz-animation:fadeOut 400ms;animation:fadeOut 400ms;-webkit-animation:fadeIn 400ms;-moz-animation:fadeIn 400ms;animation:fadeIn 400ms;vertical-align:middle;background-color:#f7f7f7;overflow:visible;border:#ababab 1px solid;outline:none;padding:3px;margin:0;padding-left:7px;font-family:monospace;min-height:50px;-moz-box-shadow:0 6px 10px -1px #adadad;-webkit-box-shadow:0 6px 10px -1px #adadad;box-shadow:0 6px 10px -1px #adadad;border-radius:4px;position:absolute;z-index:2}.ipython_tooltip a{float:right} |
|
1533 | .ipython_tooltip{max-width:700px;-webkit-animation:fadeOut 400ms;-moz-animation:fadeOut 400ms;animation:fadeOut 400ms;-webkit-animation:fadeIn 400ms;-moz-animation:fadeIn 400ms;animation:fadeIn 400ms;vertical-align:middle;background-color:#f7f7f7;overflow:visible;border:#ababab 1px solid;outline:none;padding:3px;margin:0;padding-left:7px;font-family:monospace;min-height:50px;-moz-box-shadow:0 6px 10px -1px #adadad;-webkit-box-shadow:0 6px 10px -1px #adadad;box-shadow:0 6px 10px -1px #adadad;border-radius:4px;position:absolute;z-index:2}.ipython_tooltip a{float:right} | |
1534 | .ipython_tooltip .tooltiptext pre{border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;font-size:100%;background-color:#f7f7f7} |
|
1534 | .ipython_tooltip .tooltiptext pre{border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;font-size:100%;background-color:#f7f7f7} | |
1535 | .pretooltiparrow{left:0;margin:0;top:-16px;width:40px;height:16px;overflow:hidden;position:absolute} |
|
1535 | .pretooltiparrow{left:0;margin:0;top:-16px;width:40px;height:16px;overflow:hidden;position:absolute} | |
1536 | .pretooltiparrow:before{background-color:#f7f7f7;border:1px #ababab solid;z-index:11;content:"";position:absolute;left:15px;top:10px;width:25px;height:25px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg)} |
|
1536 | .pretooltiparrow:before{background-color:#f7f7f7;border:1px #ababab solid;z-index:11;content:"";position:absolute;left:15px;top:10px;width:25px;height:25px;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg)} |
@@ -1,450 +1,451 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2013 The IPython Development Team |
|
2 | // Copyright (C) 2013 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // Base Widget Model and View classes |
|
9 | // Base Widget Model and View classes | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | /** |
|
12 | /** | |
13 | * @module IPython |
|
13 | * @module IPython | |
14 | * @namespace IPython |
|
14 | * @namespace IPython | |
15 | **/ |
|
15 | **/ | |
16 |
|
16 | |||
17 | define(["widgets/js/manager", |
|
17 | define(["widgets/js/manager", | |
18 | "underscore", |
|
18 | "underscore", | |
19 | "backbone"], |
|
19 | "backbone"], | |
20 | function(WidgetManager, _, Backbone){ |
|
20 | function(WidgetManager, _, Backbone){ | |
21 |
|
21 | |||
22 | var WidgetModel = Backbone.Model.extend({ |
|
22 | var WidgetModel = Backbone.Model.extend({ | |
23 | constructor: function (widget_manager, model_id, comm) { |
|
23 | constructor: function (widget_manager, model_id, comm) { | |
24 | // Constructor |
|
24 | // Constructor | |
25 | // |
|
25 | // | |
26 | // Creates a WidgetModel instance. |
|
26 | // Creates a WidgetModel instance. | |
27 | // |
|
27 | // | |
28 | // Parameters |
|
28 | // Parameters | |
29 | // ---------- |
|
29 | // ---------- | |
30 | // widget_manager : WidgetManager instance |
|
30 | // widget_manager : WidgetManager instance | |
31 | // model_id : string |
|
31 | // model_id : string | |
32 | // An ID unique to this model. |
|
32 | // An ID unique to this model. | |
33 | // comm : Comm instance (optional) |
|
33 | // comm : Comm instance (optional) | |
34 | this.widget_manager = widget_manager; |
|
34 | this.widget_manager = widget_manager; | |
35 | this._buffered_state_diff = {}; |
|
35 | this._buffered_state_diff = {}; | |
36 | this.pending_msgs = 0; |
|
36 | this.pending_msgs = 0; | |
37 | this.msg_buffer = null; |
|
37 | this.msg_buffer = null; | |
38 | this.key_value_lock = null; |
|
38 | this.key_value_lock = null; | |
39 | this.id = model_id; |
|
39 | this.id = model_id; | |
40 | this.views = []; |
|
40 | this.views = []; | |
41 |
|
41 | |||
42 | if (comm !== undefined) { |
|
42 | if (comm !== undefined) { | |
43 | // Remember comm associated with the model. |
|
43 | // Remember comm associated with the model. | |
44 | this.comm = comm; |
|
44 | this.comm = comm; | |
45 | comm.model = this; |
|
45 | comm.model = this; | |
46 |
|
46 | |||
47 | // Hook comm messages up to model. |
|
47 | // Hook comm messages up to model. | |
48 | comm.on_close($.proxy(this._handle_comm_closed, this)); |
|
48 | comm.on_close($.proxy(this._handle_comm_closed, this)); | |
49 | comm.on_msg($.proxy(this._handle_comm_msg, this)); |
|
49 | comm.on_msg($.proxy(this._handle_comm_msg, this)); | |
50 | } |
|
50 | } | |
51 | return Backbone.Model.apply(this); |
|
51 | return Backbone.Model.apply(this); | |
52 | }, |
|
52 | }, | |
53 |
|
53 | |||
54 | send: function (content, callbacks) { |
|
54 | send: function (content, callbacks) { | |
55 | // Send a custom msg over the comm. |
|
55 | // Send a custom msg over the comm. | |
56 | if (this.comm !== undefined) { |
|
56 | if (this.comm !== undefined) { | |
57 | var data = {method: 'custom', content: content}; |
|
57 | var data = {method: 'custom', content: content}; | |
58 | this.comm.send(data, callbacks); |
|
58 | this.comm.send(data, callbacks); | |
59 | this.pending_msgs++; |
|
59 | this.pending_msgs++; | |
60 | } |
|
60 | } | |
61 | }, |
|
61 | }, | |
62 |
|
62 | |||
63 | _handle_comm_closed: function (msg) { |
|
63 | _handle_comm_closed: function (msg) { | |
64 | // Handle when a widget is closed. |
|
64 | // Handle when a widget is closed. | |
65 | this.trigger('comm:close'); |
|
65 | this.trigger('comm:close'); | |
66 | delete this.comm.model; // Delete ref so GC will collect widget model. |
|
66 | delete this.comm.model; // Delete ref so GC will collect widget model. | |
67 | delete this.comm; |
|
67 | delete this.comm; | |
68 | delete this.model_id; // Delete id from model so widget manager cleans up. |
|
68 | delete this.model_id; // Delete id from model so widget manager cleans up. | |
69 | _.each(this.views, function(view, i) { |
|
69 | _.each(this.views, function(view, i) { | |
70 | view.remove(); |
|
70 | view.remove(); | |
71 | }); |
|
71 | }); | |
72 | }, |
|
72 | }, | |
73 |
|
73 | |||
74 | _handle_comm_msg: function (msg) { |
|
74 | _handle_comm_msg: function (msg) { | |
75 | // Handle incoming comm msg. |
|
75 | // Handle incoming comm msg. | |
76 | var method = msg.content.data.method; |
|
76 | var method = msg.content.data.method; | |
77 | switch (method) { |
|
77 | switch (method) { | |
78 | case 'update': |
|
78 | case 'update': | |
79 | this.apply_update(msg.content.data.state); |
|
79 | this.apply_update(msg.content.data.state); | |
80 | break; |
|
80 | break; | |
81 | case 'custom': |
|
81 | case 'custom': | |
82 | this.trigger('msg:custom', msg.content.data.content); |
|
82 | this.trigger('msg:custom', msg.content.data.content); | |
83 | break; |
|
83 | break; | |
84 | case 'display': |
|
84 | case 'display': | |
85 | this.widget_manager.display_view(msg, this); |
|
85 | this.widget_manager.display_view(msg, this); | |
|
86 | this.trigger('displayed'); | |||
86 | break; |
|
87 | break; | |
87 | } |
|
88 | } | |
88 | }, |
|
89 | }, | |
89 |
|
90 | |||
90 | apply_update: function (state) { |
|
91 | apply_update: function (state) { | |
91 | // Handle when a widget is updated via the python side. |
|
92 | // Handle when a widget is updated via the python side. | |
92 | var that = this; |
|
93 | var that = this; | |
93 | _.each(state, function(value, key) { |
|
94 | _.each(state, function(value, key) { | |
94 | that.key_value_lock = [key, value]; |
|
95 | that.key_value_lock = [key, value]; | |
95 | try { |
|
96 | try { | |
96 | WidgetModel.__super__.set.apply(that, [key, that._unpack_models(value)]); |
|
97 | WidgetModel.__super__.set.apply(that, [key, that._unpack_models(value)]); | |
97 | } finally { |
|
98 | } finally { | |
98 | that.key_value_lock = null; |
|
99 | that.key_value_lock = null; | |
99 | } |
|
100 | } | |
100 | }); |
|
101 | }); | |
101 | }, |
|
102 | }, | |
102 |
|
103 | |||
103 | _handle_status: function (msg, callbacks) { |
|
104 | _handle_status: function (msg, callbacks) { | |
104 | // Handle status msgs. |
|
105 | // Handle status msgs. | |
105 |
|
106 | |||
106 | // execution_state : ('busy', 'idle', 'starting') |
|
107 | // execution_state : ('busy', 'idle', 'starting') | |
107 | if (this.comm !== undefined) { |
|
108 | if (this.comm !== undefined) { | |
108 | if (msg.content.execution_state ==='idle') { |
|
109 | if (msg.content.execution_state ==='idle') { | |
109 | // Send buffer if this message caused another message to be |
|
110 | // Send buffer if this message caused another message to be | |
110 | // throttled. |
|
111 | // throttled. | |
111 | if (this.msg_buffer !== null && |
|
112 | if (this.msg_buffer !== null && | |
112 | (this.get('msg_throttle') || 3) === this.pending_msgs) { |
|
113 | (this.get('msg_throttle') || 3) === this.pending_msgs) { | |
113 | var data = {method: 'backbone', sync_method: 'update', sync_data: this.msg_buffer}; |
|
114 | var data = {method: 'backbone', sync_method: 'update', sync_data: this.msg_buffer}; | |
114 | this.comm.send(data, callbacks); |
|
115 | this.comm.send(data, callbacks); | |
115 | this.msg_buffer = null; |
|
116 | this.msg_buffer = null; | |
116 | } else { |
|
117 | } else { | |
117 | --this.pending_msgs; |
|
118 | --this.pending_msgs; | |
118 | } |
|
119 | } | |
119 | } |
|
120 | } | |
120 | } |
|
121 | } | |
121 | }, |
|
122 | }, | |
122 |
|
123 | |||
123 | callbacks: function(view) { |
|
124 | callbacks: function(view) { | |
124 | // Create msg callbacks for a comm msg. |
|
125 | // Create msg callbacks for a comm msg. | |
125 | var callbacks = this.widget_manager.callbacks(view); |
|
126 | var callbacks = this.widget_manager.callbacks(view); | |
126 |
|
127 | |||
127 | if (callbacks.iopub === undefined) { |
|
128 | if (callbacks.iopub === undefined) { | |
128 | callbacks.iopub = {}; |
|
129 | callbacks.iopub = {}; | |
129 | } |
|
130 | } | |
130 |
|
131 | |||
131 | var that = this; |
|
132 | var that = this; | |
132 | callbacks.iopub.status = function (msg) { |
|
133 | callbacks.iopub.status = function (msg) { | |
133 | that._handle_status(msg, callbacks); |
|
134 | that._handle_status(msg, callbacks); | |
134 | }; |
|
135 | }; | |
135 | return callbacks; |
|
136 | return callbacks; | |
136 | }, |
|
137 | }, | |
137 |
|
138 | |||
138 | set: function(key, val, options) { |
|
139 | set: function(key, val, options) { | |
139 | // Set a value. |
|
140 | // Set a value. | |
140 | var return_value = WidgetModel.__super__.set.apply(this, arguments); |
|
141 | var return_value = WidgetModel.__super__.set.apply(this, arguments); | |
141 |
|
142 | |||
142 | // Backbone only remembers the diff of the most recent set() |
|
143 | // Backbone only remembers the diff of the most recent set() | |
143 | // operation. Calling set multiple times in a row results in a |
|
144 | // operation. Calling set multiple times in a row results in a | |
144 | // loss of diff information. Here we keep our own running diff. |
|
145 | // loss of diff information. Here we keep our own running diff. | |
145 | this._buffered_state_diff = $.extend(this._buffered_state_diff, this.changedAttributes() || {}); |
|
146 | this._buffered_state_diff = $.extend(this._buffered_state_diff, this.changedAttributes() || {}); | |
146 | return return_value; |
|
147 | return return_value; | |
147 | }, |
|
148 | }, | |
148 |
|
149 | |||
149 | sync: function (method, model, options) { |
|
150 | sync: function (method, model, options) { | |
150 | // Handle sync to the back-end. Called when a model.save() is called. |
|
151 | // Handle sync to the back-end. Called when a model.save() is called. | |
151 |
|
152 | |||
152 | // Make sure a comm exists. |
|
153 | // Make sure a comm exists. | |
153 | var error = options.error || function() { |
|
154 | var error = options.error || function() { | |
154 | console.error('Backbone sync error:', arguments); |
|
155 | console.error('Backbone sync error:', arguments); | |
155 | }; |
|
156 | }; | |
156 | if (this.comm === undefined) { |
|
157 | if (this.comm === undefined) { | |
157 | error(); |
|
158 | error(); | |
158 | return false; |
|
159 | return false; | |
159 | } |
|
160 | } | |
160 |
|
161 | |||
161 | // Delete any key value pairs that the back-end already knows about. |
|
162 | // Delete any key value pairs that the back-end already knows about. | |
162 | var attrs = (method === 'patch') ? options.attrs : model.toJSON(options); |
|
163 | var attrs = (method === 'patch') ? options.attrs : model.toJSON(options); | |
163 | if (this.key_value_lock !== null) { |
|
164 | if (this.key_value_lock !== null) { | |
164 | var key = this.key_value_lock[0]; |
|
165 | var key = this.key_value_lock[0]; | |
165 | var value = this.key_value_lock[1]; |
|
166 | var value = this.key_value_lock[1]; | |
166 | if (attrs[key] === value) { |
|
167 | if (attrs[key] === value) { | |
167 | delete attrs[key]; |
|
168 | delete attrs[key]; | |
168 | } |
|
169 | } | |
169 | } |
|
170 | } | |
170 |
|
171 | |||
171 | // Only sync if there are attributes to send to the back-end. |
|
172 | // Only sync if there are attributes to send to the back-end. | |
172 | attrs = this._pack_models(attrs); |
|
173 | attrs = this._pack_models(attrs); | |
173 | if (_.size(attrs) > 0) { |
|
174 | if (_.size(attrs) > 0) { | |
174 |
|
175 | |||
175 | // If this message was sent via backbone itself, it will not |
|
176 | // If this message was sent via backbone itself, it will not | |
176 | // have any callbacks. It's important that we create callbacks |
|
177 | // have any callbacks. It's important that we create callbacks | |
177 | // so we can listen for status messages, etc... |
|
178 | // so we can listen for status messages, etc... | |
178 | var callbacks = options.callbacks || this.callbacks(); |
|
179 | var callbacks = options.callbacks || this.callbacks(); | |
179 |
|
180 | |||
180 | // Check throttle. |
|
181 | // Check throttle. | |
181 | if (this.pending_msgs >= (this.get('msg_throttle') || 3)) { |
|
182 | if (this.pending_msgs >= (this.get('msg_throttle') || 3)) { | |
182 | // The throttle has been exceeded, buffer the current msg so |
|
183 | // The throttle has been exceeded, buffer the current msg so | |
183 | // it can be sent once the kernel has finished processing |
|
184 | // it can be sent once the kernel has finished processing | |
184 | // some of the existing messages. |
|
185 | // some of the existing messages. | |
185 |
|
186 | |||
186 | // Combine updates if it is a 'patch' sync, otherwise replace updates |
|
187 | // Combine updates if it is a 'patch' sync, otherwise replace updates | |
187 | switch (method) { |
|
188 | switch (method) { | |
188 | case 'patch': |
|
189 | case 'patch': | |
189 | this.msg_buffer = $.extend(this.msg_buffer || {}, attrs); |
|
190 | this.msg_buffer = $.extend(this.msg_buffer || {}, attrs); | |
190 | break; |
|
191 | break; | |
191 | case 'update': |
|
192 | case 'update': | |
192 | case 'create': |
|
193 | case 'create': | |
193 | this.msg_buffer = attrs; |
|
194 | this.msg_buffer = attrs; | |
194 | break; |
|
195 | break; | |
195 | default: |
|
196 | default: | |
196 | error(); |
|
197 | error(); | |
197 | return false; |
|
198 | return false; | |
198 | } |
|
199 | } | |
199 | this.msg_buffer_callbacks = callbacks; |
|
200 | this.msg_buffer_callbacks = callbacks; | |
200 |
|
201 | |||
201 | } else { |
|
202 | } else { | |
202 | // We haven't exceeded the throttle, send the message like |
|
203 | // We haven't exceeded the throttle, send the message like | |
203 | // normal. |
|
204 | // normal. | |
204 | var data = {method: 'backbone', sync_data: attrs}; |
|
205 | var data = {method: 'backbone', sync_data: attrs}; | |
205 | this.comm.send(data, callbacks); |
|
206 | this.comm.send(data, callbacks); | |
206 | this.pending_msgs++; |
|
207 | this.pending_msgs++; | |
207 | } |
|
208 | } | |
208 | } |
|
209 | } | |
209 | // Since the comm is a one-way communication, assume the message |
|
210 | // Since the comm is a one-way communication, assume the message | |
210 | // arrived. Don't call success since we don't have a model back from the server |
|
211 | // arrived. Don't call success since we don't have a model back from the server | |
211 | // this means we miss out on the 'sync' event. |
|
212 | // this means we miss out on the 'sync' event. | |
212 | this._buffered_state_diff = {}; |
|
213 | this._buffered_state_diff = {}; | |
213 | }, |
|
214 | }, | |
214 |
|
215 | |||
215 | save_changes: function(callbacks) { |
|
216 | save_changes: function(callbacks) { | |
216 | // Push this model's state to the back-end |
|
217 | // Push this model's state to the back-end | |
217 | // |
|
218 | // | |
218 | // This invokes a Backbone.Sync. |
|
219 | // This invokes a Backbone.Sync. | |
219 | this.save(this._buffered_state_diff, {patch: true, callbacks: callbacks}); |
|
220 | this.save(this._buffered_state_diff, {patch: true, callbacks: callbacks}); | |
220 | }, |
|
221 | }, | |
221 |
|
222 | |||
222 | _pack_models: function(value) { |
|
223 | _pack_models: function(value) { | |
223 | // Replace models with model ids recursively. |
|
224 | // Replace models with model ids recursively. | |
224 | if (value instanceof Backbone.Model) { |
|
225 | if (value instanceof Backbone.Model) { | |
225 | return value.id; |
|
226 | return value.id; | |
226 |
|
227 | |||
227 | } else if ($.isArray(value)) { |
|
228 | } else if ($.isArray(value)) { | |
228 | var packed = []; |
|
229 | var packed = []; | |
229 | var that = this; |
|
230 | var that = this; | |
230 | _.each(value, function(sub_value, key) { |
|
231 | _.each(value, function(sub_value, key) { | |
231 | packed.push(that._pack_models(sub_value)); |
|
232 | packed.push(that._pack_models(sub_value)); | |
232 | }); |
|
233 | }); | |
233 | return packed; |
|
234 | return packed; | |
234 |
|
235 | |||
235 | } else if (value instanceof Object) { |
|
236 | } else if (value instanceof Object) { | |
236 | var packed = {}; |
|
237 | var packed = {}; | |
237 | var that = this; |
|
238 | var that = this; | |
238 | _.each(value, function(sub_value, key) { |
|
239 | _.each(value, function(sub_value, key) { | |
239 | packed[key] = that._pack_models(sub_value); |
|
240 | packed[key] = that._pack_models(sub_value); | |
240 | }); |
|
241 | }); | |
241 | return packed; |
|
242 | return packed; | |
242 |
|
243 | |||
243 | } else { |
|
244 | } else { | |
244 | return value; |
|
245 | return value; | |
245 | } |
|
246 | } | |
246 | }, |
|
247 | }, | |
247 |
|
248 | |||
248 | _unpack_models: function(value) { |
|
249 | _unpack_models: function(value) { | |
249 | // Replace model ids with models recursively. |
|
250 | // Replace model ids with models recursively. | |
250 | if ($.isArray(value)) { |
|
251 | if ($.isArray(value)) { | |
251 | var unpacked = []; |
|
252 | var unpacked = []; | |
252 | var that = this; |
|
253 | var that = this; | |
253 | _.each(value, function(sub_value, key) { |
|
254 | _.each(value, function(sub_value, key) { | |
254 | unpacked.push(that._unpack_models(sub_value)); |
|
255 | unpacked.push(that._unpack_models(sub_value)); | |
255 | }); |
|
256 | }); | |
256 | return unpacked; |
|
257 | return unpacked; | |
257 |
|
258 | |||
258 | } else if (value instanceof Object) { |
|
259 | } else if (value instanceof Object) { | |
259 | var unpacked = {}; |
|
260 | var unpacked = {}; | |
260 | var that = this; |
|
261 | var that = this; | |
261 | _.each(value, function(sub_value, key) { |
|
262 | _.each(value, function(sub_value, key) { | |
262 | unpacked[key] = that._unpack_models(sub_value); |
|
263 | unpacked[key] = that._unpack_models(sub_value); | |
263 | }); |
|
264 | }); | |
264 | return unpacked; |
|
265 | return unpacked; | |
265 |
|
266 | |||
266 | } else { |
|
267 | } else { | |
267 | var model = this.widget_manager.get_model(value); |
|
268 | var model = this.widget_manager.get_model(value); | |
268 | if (model) { |
|
269 | if (model) { | |
269 | return model; |
|
270 | return model; | |
270 | } else { |
|
271 | } else { | |
271 | return value; |
|
272 | return value; | |
272 | } |
|
273 | } | |
273 | } |
|
274 | } | |
274 | }, |
|
275 | }, | |
275 |
|
276 | |||
276 | }); |
|
277 | }); | |
277 | WidgetManager.register_widget_model('WidgetModel', WidgetModel); |
|
278 | WidgetManager.register_widget_model('WidgetModel', WidgetModel); | |
278 |
|
279 | |||
279 |
|
280 | |||
280 | var WidgetView = Backbone.View.extend({ |
|
281 | var WidgetView = Backbone.View.extend({ | |
281 | initialize: function(parameters) { |
|
282 | initialize: function(parameters) { | |
282 | // Public constructor. |
|
283 | // Public constructor. | |
283 | this.model.on('change',this.update,this); |
|
284 | this.model.on('change',this.update,this); | |
284 | this.options = parameters.options; |
|
285 | this.options = parameters.options; | |
285 | this.child_views = []; |
|
286 | this.child_views = []; | |
286 | this.model.views.push(this); |
|
287 | this.model.views.push(this); | |
287 | }, |
|
288 | }, | |
288 |
|
289 | |||
289 | update: function(){ |
|
290 | update: function(){ | |
290 | // Triggered on model change. |
|
291 | // Triggered on model change. | |
291 | // |
|
292 | // | |
292 | // Update view to be consistent with this.model |
|
293 | // Update view to be consistent with this.model | |
293 | }, |
|
294 | }, | |
294 |
|
295 | |||
295 | create_child_view: function(child_model, options) { |
|
296 | create_child_view: function(child_model, options) { | |
296 | // Create and return a child view. |
|
297 | // Create and return a child view. | |
297 | // |
|
298 | // | |
298 | // -given a model and (optionally) a view name if the view name is |
|
299 | // -given a model and (optionally) a view name if the view name is | |
299 | // not given, it defaults to the model's default view attribute. |
|
300 | // not given, it defaults to the model's default view attribute. | |
300 |
|
301 | |||
301 | // TODO: this is hacky, and makes the view depend on this cell attribute and widget manager behavior |
|
302 | // TODO: this is hacky, and makes the view depend on this cell attribute and widget manager behavior | |
302 | // it would be great to have the widget manager add the cell metadata |
|
303 | // it would be great to have the widget manager add the cell metadata | |
303 | // to the subview without having to add it here. |
|
304 | // to the subview without having to add it here. | |
304 | var child_view = this.model.widget_manager.create_view(child_model, options || {}, this); |
|
305 | var child_view = this.model.widget_manager.create_view(child_model, options || {}, this); | |
305 | this.child_views[child_model.id] = child_view; |
|
306 | this.child_views[child_model.id] = child_view; | |
306 | return child_view; |
|
307 | return child_view; | |
307 | }, |
|
308 | }, | |
308 |
|
309 | |||
309 | delete_child_view: function(child_model, options) { |
|
310 | delete_child_view: function(child_model, options) { | |
310 | // Delete a child view that was previously created using create_child_view. |
|
311 | // Delete a child view that was previously created using create_child_view. | |
311 | var view = this.child_views[child_model.id]; |
|
312 | var view = this.child_views[child_model.id]; | |
312 | if (view !== undefined) { |
|
313 | if (view !== undefined) { | |
313 | delete this.child_views[child_model.id]; |
|
314 | delete this.child_views[child_model.id]; | |
314 | view.remove(); |
|
315 | view.remove(); | |
315 | } |
|
316 | } | |
316 | }, |
|
317 | }, | |
317 |
|
318 | |||
318 | do_diff: function(old_list, new_list, removed_callback, added_callback) { |
|
319 | do_diff: function(old_list, new_list, removed_callback, added_callback) { | |
319 | // Difference a changed list and call remove and add callbacks for |
|
320 | // Difference a changed list and call remove and add callbacks for | |
320 | // each removed and added item in the new list. |
|
321 | // each removed and added item in the new list. | |
321 | // |
|
322 | // | |
322 | // Parameters |
|
323 | // Parameters | |
323 | // ---------- |
|
324 | // ---------- | |
324 | // old_list : array |
|
325 | // old_list : array | |
325 | // new_list : array |
|
326 | // new_list : array | |
326 | // removed_callback : Callback(item) |
|
327 | // removed_callback : Callback(item) | |
327 | // Callback that is called for each item removed. |
|
328 | // Callback that is called for each item removed. | |
328 | // added_callback : Callback(item) |
|
329 | // added_callback : Callback(item) | |
329 | // Callback that is called for each item added. |
|
330 | // Callback that is called for each item added. | |
330 |
|
331 | |||
331 |
|
332 | |||
332 | // removed items |
|
333 | // removed items | |
333 | _.each(_.difference(old_list, new_list), function(item, index, list) { |
|
334 | _.each(_.difference(old_list, new_list), function(item, index, list) { | |
334 | removed_callback(item); |
|
335 | removed_callback(item); | |
335 | }, this); |
|
336 | }, this); | |
336 |
|
337 | |||
337 | // added items |
|
338 | // added items | |
338 | _.each(_.difference(new_list, old_list), function(item, index, list) { |
|
339 | _.each(_.difference(new_list, old_list), function(item, index, list) { | |
339 | added_callback(item); |
|
340 | added_callback(item); | |
340 | }, this); |
|
341 | }, this); | |
341 | }, |
|
342 | }, | |
342 |
|
343 | |||
343 | callbacks: function(){ |
|
344 | callbacks: function(){ | |
344 | // Create msg callbacks for a comm msg. |
|
345 | // Create msg callbacks for a comm msg. | |
345 | return this.model.callbacks(this); |
|
346 | return this.model.callbacks(this); | |
346 | }, |
|
347 | }, | |
347 |
|
348 | |||
348 | render: function(){ |
|
349 | render: function(){ | |
349 | // Render the view. |
|
350 | // Render the view. | |
350 | // |
|
351 | // | |
351 | // By default, this is only called the first time the view is created |
|
352 | // By default, this is only called the first time the view is created | |
352 | }, |
|
353 | }, | |
353 |
|
354 | |||
354 | send: function (content) { |
|
355 | send: function (content) { | |
355 | // Send a custom msg associated with this view. |
|
356 | // Send a custom msg associated with this view. | |
356 | this.model.send(content, this.callbacks()); |
|
357 | this.model.send(content, this.callbacks()); | |
357 | }, |
|
358 | }, | |
358 |
|
359 | |||
359 | touch: function () { |
|
360 | touch: function () { | |
360 | this.model.save_changes(this.callbacks()); |
|
361 | this.model.save_changes(this.callbacks()); | |
361 | }, |
|
362 | }, | |
362 | }); |
|
363 | }); | |
363 |
|
364 | |||
364 |
|
365 | |||
365 | var DOMWidgetView = WidgetView.extend({ |
|
366 | var DOMWidgetView = WidgetView.extend({ | |
366 | initialize: function (options) { |
|
367 | initialize: function (options) { | |
367 | // Public constructor |
|
368 | // Public constructor | |
368 |
|
369 | |||
369 | // In the future we may want to make changes more granular |
|
370 | // In the future we may want to make changes more granular | |
370 | // (e.g., trigger on visible:change). |
|
371 | // (e.g., trigger on visible:change). | |
371 | this.model.on('change', this.update, this); |
|
372 | this.model.on('change', this.update, this); | |
372 | this.model.on('msg:custom', this.on_msg, this); |
|
373 | this.model.on('msg:custom', this.on_msg, this); | |
373 | DOMWidgetView.__super__.initialize.apply(this, arguments); |
|
374 | DOMWidgetView.__super__.initialize.apply(this, arguments); | |
374 | }, |
|
375 | }, | |
375 |
|
376 | |||
376 | on_msg: function(msg) { |
|
377 | on_msg: function(msg) { | |
377 | // Handle DOM specific msgs. |
|
378 | // Handle DOM specific msgs. | |
378 | switch(msg.msg_type) { |
|
379 | switch(msg.msg_type) { | |
379 | case 'add_class': |
|
380 | case 'add_class': | |
380 | this.add_class(msg.selector, msg.class_list); |
|
381 | this.add_class(msg.selector, msg.class_list); | |
381 | break; |
|
382 | break; | |
382 | case 'remove_class': |
|
383 | case 'remove_class': | |
383 | this.remove_class(msg.selector, msg.class_list); |
|
384 | this.remove_class(msg.selector, msg.class_list); | |
384 | break; |
|
385 | break; | |
385 | } |
|
386 | } | |
386 | }, |
|
387 | }, | |
387 |
|
388 | |||
388 | add_class: function (selector, class_list) { |
|
389 | add_class: function (selector, class_list) { | |
389 | // Add a DOM class to an element. |
|
390 | // Add a DOM class to an element. | |
390 | this._get_selector_element(selector).addClass(class_list); |
|
391 | this._get_selector_element(selector).addClass(class_list); | |
391 | }, |
|
392 | }, | |
392 |
|
393 | |||
393 | remove_class: function (selector, class_list) { |
|
394 | remove_class: function (selector, class_list) { | |
394 | // Remove a DOM class from an element. |
|
395 | // Remove a DOM class from an element. | |
395 | this._get_selector_element(selector).removeClass(class_list); |
|
396 | this._get_selector_element(selector).removeClass(class_list); | |
396 | }, |
|
397 | }, | |
397 |
|
398 | |||
398 | update: function () { |
|
399 | update: function () { | |
399 | // Update the contents of this view |
|
400 | // Update the contents of this view | |
400 | // |
|
401 | // | |
401 | // Called when the model is changed. The model may have been |
|
402 | // Called when the model is changed. The model may have been | |
402 | // changed by another view or by a state update from the back-end. |
|
403 | // changed by another view or by a state update from the back-end. | |
403 | // The very first update seems to happen before the element is |
|
404 | // The very first update seems to happen before the element is | |
404 | // finished rendering so we use setTimeout to give the element time |
|
405 | // finished rendering so we use setTimeout to give the element time | |
405 | // to render |
|
406 | // to render | |
406 | var e = this.$el; |
|
407 | var e = this.$el; | |
407 | var visible = this.model.get('visible'); |
|
408 | var visible = this.model.get('visible'); | |
408 | setTimeout(function() {e.toggle(visible);},0); |
|
409 | setTimeout(function() {e.toggle(visible);},0); | |
409 |
|
410 | |||
410 | var css = this.model.get('_css'); |
|
411 | var css = this.model.get('_css'); | |
411 | if (css === undefined) {return;} |
|
412 | if (css === undefined) {return;} | |
412 | var that = this; |
|
413 | var that = this; | |
413 | _.each(css, function(css_traits, selector){ |
|
414 | _.each(css, function(css_traits, selector){ | |
414 | // Apply the css traits to all elements that match the selector. |
|
415 | // Apply the css traits to all elements that match the selector. | |
415 | var elements = that._get_selector_element(selector); |
|
416 | var elements = that._get_selector_element(selector); | |
416 | if (elements.length > 0) { |
|
417 | if (elements.length > 0) { | |
417 | _.each(css_traits, function(css_value, css_key){ |
|
418 | _.each(css_traits, function(css_value, css_key){ | |
418 | elements.css(css_key, css_value); |
|
419 | elements.css(css_key, css_value); | |
419 | }); |
|
420 | }); | |
420 | } |
|
421 | } | |
421 | }); |
|
422 | }); | |
422 | }, |
|
423 | }, | |
423 |
|
424 | |||
424 | _get_selector_element: function (selector) { |
|
425 | _get_selector_element: function (selector) { | |
425 | // Get the elements via the css selector. |
|
426 | // Get the elements via the css selector. | |
426 |
|
427 | |||
427 | // If the selector is blank, apply the style to the $el_to_style |
|
428 | // If the selector is blank, apply the style to the $el_to_style | |
428 | // element. If the $el_to_style element is not defined, use apply |
|
429 | // element. If the $el_to_style element is not defined, use apply | |
429 | // the style to the view's element. |
|
430 | // the style to the view's element. | |
430 | var elements; |
|
431 | var elements; | |
431 | if (!selector) { |
|
432 | if (!selector) { | |
432 | if (this.$el_to_style === undefined) { |
|
433 | if (this.$el_to_style === undefined) { | |
433 | elements = this.$el; |
|
434 | elements = this.$el; | |
434 | } else { |
|
435 | } else { | |
435 | elements = this.$el_to_style; |
|
436 | elements = this.$el_to_style; | |
436 | } |
|
437 | } | |
437 | } else { |
|
438 | } else { | |
438 | elements = this.$el.find(selector); |
|
439 | elements = this.$el.find(selector); | |
439 | } |
|
440 | } | |
440 | return elements; |
|
441 | return elements; | |
441 | }, |
|
442 | }, | |
442 | }); |
|
443 | }); | |
443 |
|
444 | |||
444 | IPython.WidgetModel = WidgetModel; |
|
445 | IPython.WidgetModel = WidgetModel; | |
445 | IPython.WidgetView = WidgetView; |
|
446 | IPython.WidgetView = WidgetView; | |
446 | IPython.DOMWidgetView = DOMWidgetView; |
|
447 | IPython.DOMWidgetView = DOMWidgetView; | |
447 |
|
448 | |||
448 | // Pass through WidgetManager namespace. |
|
449 | // Pass through WidgetManager namespace. | |
449 | return WidgetManager; |
|
450 | return WidgetManager; | |
450 | }); |
|
451 | }); |
@@ -1,244 +1,243 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2013 The IPython Development Team |
|
2 | // Copyright (C) 2013 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // SelectionContainerWidget |
|
9 | // SelectionContainerWidget | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 |
|
11 | |||
12 | /** |
|
12 | /** | |
13 | * @module IPython |
|
13 | * @module IPython | |
14 | * @namespace IPython |
|
14 | * @namespace IPython | |
15 | **/ |
|
15 | **/ | |
16 |
|
16 | |||
17 | define(["widgets/js/widget"], function(WidgetManager){ |
|
17 | define(["widgets/js/widget"], function(WidgetManager){ | |
18 |
|
18 | |||
19 | var AccordionView = IPython.DOMWidgetView.extend({ |
|
19 | var AccordionView = IPython.DOMWidgetView.extend({ | |
20 | render: function(){ |
|
20 | render: function(){ | |
21 | // Called when view is rendered. |
|
21 | // Called when view is rendered. | |
22 | var guid = 'accordion' + IPython.utils.uuid(); |
|
22 | var guid = 'accordion' + IPython.utils.uuid(); | |
23 | this.$el |
|
23 | this.$el | |
24 | .attr('id', guid) |
|
24 | .attr('id', guid) | |
25 | .addClass('accordion'); |
|
25 | .addClass('accordion'); | |
26 | this.containers = []; |
|
26 | this.containers = []; | |
27 | this.model_containers = {}; |
|
27 | this.model_containers = {}; | |
28 | this.update_children([], this.model.get('_children')); |
|
28 | this.update_children([], this.model.get('_children')); | |
29 | this.model.on('change:_children', function(model, value, options) { |
|
29 | this.model.on('change:_children', function(model, value, options) { | |
30 | this.update_children(model.previous('_children'), value); |
|
30 | this.update_children(model.previous('_children'), value); | |
31 | }, this); |
|
31 | }, this); | |
|
32 | this.model.on('change:selected_index', function(model, value, options) { | |||
|
33 | this.update_selected_index(model.previous('selected_index'), value, options); | |||
|
34 | }, this); | |||
|
35 | this.model.on('change:_titles', function(model, value, options) { | |||
|
36 | this.update_titles(value); | |||
|
37 | }, this); | |||
|
38 | this.model.on('displayed', function() { | |||
|
39 | this.update_titles(); | |||
|
40 | }, this); | |||
32 | }, |
|
41 | }, | |
33 |
|
||||
34 | update: function(options) { |
|
|||
35 | // Update the contents of this view |
|
|||
36 | // |
|
|||
37 | // Called when the model is changed. The model may have been |
|
|||
38 | // changed by another view or by a state update from the back-end. |
|
|||
39 | if (options === undefined || options.updated_view != this) { |
|
|||
40 | // Set tab titles |
|
|||
41 | var titles = this.model.get('_titles'); |
|
|||
42 | var that = this; |
|
|||
43 | _.each(titles, function(title, page_index) { |
|
|||
44 | var accordian = that.containers[page_index]; |
|
|||
45 | if (accordian !== undefined) { |
|
|||
46 | accordian |
|
|||
47 | .find('.accordion-heading') |
|
|||
48 | .find('.accordion-toggle') |
|
|||
49 | .text(title); |
|
|||
50 | } |
|
|||
51 | }); |
|
|||
52 |
|
42 | |||
53 | // Set selected page |
|
43 | update_titles: function(titles) { | |
54 | var selected_index = this.model.get("selected_index"); |
|
44 | // Set tab titles | |
55 | if (0 <= selected_index && selected_index < this.containers.length) { |
|
45 | if (!titles) { | |
56 | _.each(this.containers, function(container, index) { |
|
46 | titles = this.model.get('_titles'); | |
57 | if (index==selected_index) { |
|
47 | } | |
58 | container.find('.accordion-body').collapse('show'); |
|
48 | ||
59 | } else { |
|
49 | var that = this; | |
60 | container.find('.accordion-body').collapse('hide'); |
|
50 | _.each(titles, function(title, page_index) { | |
61 | } |
|
51 | var accordian = that.containers[page_index]; | |
62 | }); |
|
52 | if (accordian !== undefined) { | |
|
53 | accordian | |||
|
54 | .find('.accordion-heading') | |||
|
55 | .find('.accordion-toggle') | |||
|
56 | .text(title); | |||
|
57 | } | |||
|
58 | }); | |||
|
59 | }, | |||
|
60 | ||||
|
61 | update_selected_index: function(old_index, new_index, options) { | |||
|
62 | // Only update the selection if the selection wasn't triggered | |||
|
63 | // by the front-end. It must be triggered by the back-end. | |||
|
64 | if (options === undefined || options.updated_view != this) { | |||
|
65 | this.containers[old_index].find('.accordion-body').collapse('hide'); | |||
|
66 | if (0 <= new_index && new_index < this.containers.length) { | |||
|
67 | this.containers[new_index].find('.accordion-body').collapse('show'); | |||
63 | } |
|
68 | } | |
64 | } |
|
69 | } | |
65 | return AccordionView.__super__.update.apply(this); |
|
|||
66 | }, |
|
70 | }, | |
67 |
|
71 | |||
68 | update_children: function(old_list, new_list) { |
|
72 | update_children: function(old_list, new_list) { | |
69 | // Called when the children list is modified. |
|
73 | // Called when the children list is modified. | |
70 | this.do_diff(old_list, |
|
74 | this.do_diff(old_list, | |
71 | new_list, |
|
75 | new_list, | |
72 | $.proxy(this.remove_child_model, this), |
|
76 | $.proxy(this.remove_child_model, this), | |
73 | $.proxy(this.add_child_model, this)); |
|
77 | $.proxy(this.add_child_model, this)); | |
74 | }, |
|
78 | }, | |
75 |
|
79 | |||
76 | remove_child_model: function(model) { |
|
80 | remove_child_model: function(model) { | |
77 | // Called when a child is removed from children list. |
|
81 | // Called when a child is removed from children list. | |
78 | var accordion_group = this.model_containers[model.id]; |
|
82 | var accordion_group = this.model_containers[model.id]; | |
79 | this.containers.splice(accordion_group.container_index, 1); |
|
83 | this.containers.splice(accordion_group.container_index, 1); | |
80 | delete this.model_containers[model.id]; |
|
84 | delete this.model_containers[model.id]; | |
81 | accordion_group.remove(); |
|
85 | accordion_group.remove(); | |
82 | this.delete_child_view(model); |
|
86 | this.delete_child_view(model); | |
83 | }, |
|
87 | }, | |
84 |
|
88 | |||
85 | add_child_model: function(model) { |
|
89 | add_child_model: function(model) { | |
86 | // Called when a child is added to children list. |
|
90 | // Called when a child is added to children list. | |
87 | var view = this.create_child_view(model); |
|
91 | var view = this.create_child_view(model); | |
88 | var index = this.containers.length; |
|
92 | var index = this.containers.length; | |
89 | var uuid = IPython.utils.uuid(); |
|
93 | var uuid = IPython.utils.uuid(); | |
90 | var accordion_group = $('<div />') |
|
94 | var accordion_group = $('<div />') | |
91 | .addClass('accordion-group') |
|
95 | .addClass('accordion-group') | |
92 | .appendTo(this.$el); |
|
96 | .appendTo(this.$el); | |
93 | var accordion_heading = $('<div />') |
|
97 | var accordion_heading = $('<div />') | |
94 | .addClass('accordion-heading') |
|
98 | .addClass('accordion-heading') | |
95 | .appendTo(accordion_group); |
|
99 | .appendTo(accordion_group); | |
96 | var that = this; |
|
100 | var that = this; | |
97 | var accordion_toggle = $('<a />') |
|
101 | var accordion_toggle = $('<a />') | |
98 | .addClass('accordion-toggle') |
|
102 | .addClass('accordion-toggle') | |
99 | .attr('data-toggle', 'collapse') |
|
103 | .attr('data-toggle', 'collapse') | |
100 | .attr('data-parent', '#' + this.$el.attr('id')) |
|
104 | .attr('data-parent', '#' + this.$el.attr('id')) | |
101 | .attr('href', '#' + uuid) |
|
105 | .attr('href', '#' + uuid) | |
102 | .click(function(evt){ |
|
106 | .click(function(evt){ | |
103 |
|
107 | |||
104 | // Calling model.set will trigger all of the other views of the |
|
108 | // Calling model.set will trigger all of the other views of the | |
105 | // model to update. |
|
109 | // model to update. | |
106 |
that.model.set("selected_index", index, {updated_view: th |
|
110 | that.model.set("selected_index", index, {updated_view: that}); | |
107 | that.touch(); |
|
111 | that.touch(); | |
108 | }) |
|
112 | }) | |
109 | .text('Page ' + index) |
|
113 | .text('Page ' + index) | |
110 | .appendTo(accordion_heading); |
|
114 | .appendTo(accordion_heading); | |
111 | var accordion_body = $('<div />', {id: uuid}) |
|
115 | var accordion_body = $('<div />', {id: uuid}) | |
112 | .addClass('accordion-body collapse') |
|
116 | .addClass('accordion-body collapse') | |
113 | .appendTo(accordion_group); |
|
117 | .appendTo(accordion_group); | |
114 | var accordion_inner = $('<div />') |
|
118 | var accordion_inner = $('<div />') | |
115 | .addClass('accordion-inner') |
|
119 | .addClass('accordion-inner') | |
116 | .appendTo(accordion_body); |
|
120 | .appendTo(accordion_body); | |
117 | var container_index = this.containers.push(accordion_group) - 1; |
|
121 | var container_index = this.containers.push(accordion_group) - 1; | |
118 | accordion_group.container_index = container_index; |
|
122 | accordion_group.container_index = container_index; | |
119 | this.model_containers[model.id] = accordion_group; |
|
123 | this.model_containers[model.id] = accordion_group; | |
120 | accordion_inner.append(view.$el); |
|
124 | accordion_inner.append(view.$el); | |
121 |
|
125 | |||
122 | this.update(); |
|
126 | this.update(); | |
123 |
|
127 | this.update_titles(); | ||
124 | // Stupid workaround to close the bootstrap accordion tabs which |
|
|||
125 | // open by default even though they don't have the `in` class |
|
|||
126 | // attached to them. For some reason a delay is required. |
|
|||
127 | // TODO: Better fix. |
|
|||
128 | setTimeout(function(){ that.update(); }, 500); |
|
|||
129 | }, |
|
128 | }, | |
130 | }); |
|
129 | }); | |
131 | WidgetManager.register_widget_view('AccordionView', AccordionView); |
|
130 | WidgetManager.register_widget_view('AccordionView', AccordionView); | |
132 |
|
131 | |||
133 |
|
132 | |||
134 | var TabView = IPython.DOMWidgetView.extend({ |
|
133 | var TabView = IPython.DOMWidgetView.extend({ | |
135 | initialize: function() { |
|
134 | initialize: function() { | |
136 | // Public constructor. |
|
135 | // Public constructor. | |
137 | this.containers = []; |
|
136 | this.containers = []; | |
138 | TabView.__super__.initialize.apply(this, arguments); |
|
137 | TabView.__super__.initialize.apply(this, arguments); | |
139 | }, |
|
138 | }, | |
140 |
|
139 | |||
141 | render: function(){ |
|
140 | render: function(){ | |
142 | // Called when view is rendered. |
|
141 | // Called when view is rendered. | |
143 | var uuid = 'tabs'+IPython.utils.uuid(); |
|
142 | var uuid = 'tabs'+IPython.utils.uuid(); | |
144 | var that = this; |
|
143 | var that = this; | |
145 | this.$tabs = $('<div />', {id: uuid}) |
|
144 | this.$tabs = $('<div />', {id: uuid}) | |
146 | .addClass('nav') |
|
145 | .addClass('nav') | |
147 | .addClass('nav-tabs') |
|
146 | .addClass('nav-tabs') | |
148 | .appendTo(this.$el); |
|
147 | .appendTo(this.$el); | |
149 | this.$tab_contents = $('<div />', {id: uuid + 'Content'}) |
|
148 | this.$tab_contents = $('<div />', {id: uuid + 'Content'}) | |
150 | .addClass('tab-content') |
|
149 | .addClass('tab-content') | |
151 | .appendTo(this.$el); |
|
150 | .appendTo(this.$el); | |
152 | this.containers = []; |
|
151 | this.containers = []; | |
153 | this.update_children([], this.model.get('_children')); |
|
152 | this.update_children([], this.model.get('_children')); | |
154 | this.model.on('change:_children', function(model, value, options) { |
|
153 | this.model.on('change:_children', function(model, value, options) { | |
155 | this.update_children(model.previous('_children'), value); |
|
154 | this.update_children(model.previous('_children'), value); | |
156 | }, this); |
|
155 | }, this); | |
157 | }, |
|
156 | }, | |
158 |
|
157 | |||
159 | update_children: function(old_list, new_list) { |
|
158 | update_children: function(old_list, new_list) { | |
160 | // Called when the children list is modified. |
|
159 | // Called when the children list is modified. | |
161 | this.do_diff(old_list, |
|
160 | this.do_diff(old_list, | |
162 | new_list, |
|
161 | new_list, | |
163 | $.proxy(this.remove_child_model, this), |
|
162 | $.proxy(this.remove_child_model, this), | |
164 | $.proxy(this.add_child_model, this)); |
|
163 | $.proxy(this.add_child_model, this)); | |
165 | }, |
|
164 | }, | |
166 |
|
165 | |||
167 | remove_child_model: function(model) { |
|
166 | remove_child_model: function(model) { | |
168 | // Called when a child is removed from children list. |
|
167 | // Called when a child is removed from children list. | |
169 | var view = this.child_views[model.id]; |
|
168 | var view = this.child_views[model.id]; | |
170 | this.containers.splice(view.parent_tab.tab_text_index, 1); |
|
169 | this.containers.splice(view.parent_tab.tab_text_index, 1); | |
171 | view.parent_tab.remove(); |
|
170 | view.parent_tab.remove(); | |
172 | view.parent_container.remove(); |
|
171 | view.parent_container.remove(); | |
173 | view.remove(); |
|
172 | view.remove(); | |
174 | this.delete_child_view(model); |
|
173 | this.delete_child_view(model); | |
175 | }, |
|
174 | }, | |
176 |
|
175 | |||
177 | add_child_model: function(model) { |
|
176 | add_child_model: function(model) { | |
178 | // Called when a child is added to children list. |
|
177 | // Called when a child is added to children list. | |
179 | var view = this.create_child_view(model); |
|
178 | var view = this.create_child_view(model); | |
180 | var index = this.containers.length; |
|
179 | var index = this.containers.length; | |
181 | var uuid = IPython.utils.uuid(); |
|
180 | var uuid = IPython.utils.uuid(); | |
182 |
|
181 | |||
183 | var that = this; |
|
182 | var that = this; | |
184 | var tab = $('<li />') |
|
183 | var tab = $('<li />') | |
185 | .css('list-style-type', 'none') |
|
184 | .css('list-style-type', 'none') | |
186 | .appendTo(this.$tabs); |
|
185 | .appendTo(this.$tabs); | |
187 | view.parent_tab = tab; |
|
186 | view.parent_tab = tab; | |
188 |
|
187 | |||
189 | var tab_text = $('<a />') |
|
188 | var tab_text = $('<a />') | |
190 | .attr('href', '#' + uuid) |
|
189 | .attr('href', '#' + uuid) | |
191 | .attr('data-toggle', 'tab') |
|
190 | .attr('data-toggle', 'tab') | |
192 | .text('Page ' + index) |
|
191 | .text('Page ' + index) | |
193 | .appendTo(tab) |
|
192 | .appendTo(tab) | |
194 | .click(function (e) { |
|
193 | .click(function (e) { | |
195 |
|
194 | |||
196 | // Calling model.set will trigger all of the other views of the |
|
195 | // Calling model.set will trigger all of the other views of the | |
197 | // model to update. |
|
196 | // model to update. | |
198 | that.model.set("selected_index", index, {updated_view: this}); |
|
197 | that.model.set("selected_index", index, {updated_view: this}); | |
199 | that.touch(); |
|
198 | that.touch(); | |
200 | that.select_page(index); |
|
199 | that.select_page(index); | |
201 | }); |
|
200 | }); | |
202 | tab.tab_text_index = this.containers.push(tab_text) - 1; |
|
201 | tab.tab_text_index = this.containers.push(tab_text) - 1; | |
203 |
|
202 | |||
204 | var contents_div = $('<div />', {id: uuid}) |
|
203 | var contents_div = $('<div />', {id: uuid}) | |
205 | .addClass('tab-pane') |
|
204 | .addClass('tab-pane') | |
206 | .addClass('fade') |
|
205 | .addClass('fade') | |
207 | .append(view.$el) |
|
206 | .append(view.$el) | |
208 | .appendTo(this.$tab_contents); |
|
207 | .appendTo(this.$tab_contents); | |
209 | view.parent_container = contents_div; |
|
208 | view.parent_container = contents_div; | |
210 | }, |
|
209 | }, | |
211 |
|
210 | |||
212 | update: function(options) { |
|
211 | update: function(options) { | |
213 | // Update the contents of this view |
|
212 | // Update the contents of this view | |
214 | // |
|
213 | // | |
215 | // Called when the model is changed. The model may have been |
|
214 | // Called when the model is changed. The model may have been | |
216 | // changed by another view or by a state update from the back-end. |
|
215 | // changed by another view or by a state update from the back-end. | |
217 | if (options === undefined || options.updated_view != this) { |
|
216 | if (options === undefined || options.updated_view != this) { | |
218 | // Set tab titles |
|
217 | // Set tab titles | |
219 | var titles = this.model.get('_titles'); |
|
218 | var titles = this.model.get('_titles'); | |
220 | var that = this; |
|
219 | var that = this; | |
221 | _.each(titles, function(title, page_index) { |
|
220 | _.each(titles, function(title, page_index) { | |
222 | var tab_text = that.containers[page_index]; |
|
221 | var tab_text = that.containers[page_index]; | |
223 | if (tab_text !== undefined) { |
|
222 | if (tab_text !== undefined) { | |
224 | tab_text.text(title); |
|
223 | tab_text.text(title); | |
225 | } |
|
224 | } | |
226 | }); |
|
225 | }); | |
227 |
|
226 | |||
228 | var selected_index = this.model.get('selected_index'); |
|
227 | var selected_index = this.model.get('selected_index'); | |
229 | if (0 <= selected_index && selected_index < this.containers.length) { |
|
228 | if (0 <= selected_index && selected_index < this.containers.length) { | |
230 | this.select_page(selected_index); |
|
229 | this.select_page(selected_index); | |
231 | } |
|
230 | } | |
232 | } |
|
231 | } | |
233 | return TabView.__super__.update.apply(this); |
|
232 | return TabView.__super__.update.apply(this); | |
234 | }, |
|
233 | }, | |
235 |
|
234 | |||
236 | select_page: function(index) { |
|
235 | select_page: function(index) { | |
237 | // Select a page. |
|
236 | // Select a page. | |
238 | this.$tabs.find('li') |
|
237 | this.$tabs.find('li') | |
239 | .removeClass('active'); |
|
238 | .removeClass('active'); | |
240 | this.containers[index].tab('show'); |
|
239 | this.containers[index].tab('show'); | |
241 | }, |
|
240 | }, | |
242 | }); |
|
241 | }); | |
243 | WidgetManager.register_widget_view('TabView', TabView); |
|
242 | WidgetManager.register_widget_view('TabView', TabView); | |
244 | }); |
|
243 | }); |
@@ -1,108 +1,113 b'' | |||||
1 | // Test multicontainer class |
|
1 | // Test multicontainer class | |
2 | casper.notebook_test(function () { |
|
2 | casper.notebook_test(function () { | |
3 | index = this.append_cell( |
|
3 | index = this.append_cell( | |
4 | 'from IPython.html import widgets\n' + |
|
4 | 'from IPython.html import widgets\n' + | |
5 | 'from IPython.display import display, clear_output\n' + |
|
5 | 'from IPython.display import display, clear_output\n' + | |
6 | 'print("Success")'); |
|
6 | 'print("Success")'); | |
7 | this.execute_cell_then(index); |
|
7 | this.execute_cell_then(index); | |
8 |
|
8 | |||
9 | // Test tab view |
|
9 | // Test tab view | |
10 | var multicontainer1_query = '.widget-area .widget-subarea div div.nav-tabs'; |
|
10 | var multicontainer1_query = '.widget-area .widget-subarea div div.nav-tabs'; | |
11 | var multicontainer1_index = this.append_cell( |
|
11 | var multicontainer1_index = this.append_cell( | |
12 | 'multicontainer = widgets.TabWidget()\n' + |
|
12 | 'multicontainer = widgets.TabWidget()\n' + | |
13 | 'page1 = widgets.TextWidget()\n' + |
|
13 | 'page1 = widgets.TextWidget()\n' + | |
14 | 'page2 = widgets.TextWidget()\n' + |
|
14 | 'page2 = widgets.TextWidget()\n' + | |
15 | 'page3 = widgets.TextWidget()\n' + |
|
15 | 'page3 = widgets.TextWidget()\n' + | |
16 | 'multicontainer.children = [page1, page2, page3]\n' + |
|
16 | 'multicontainer.children = [page1, page2, page3]\n' + | |
17 | 'display(multicontainer)\n' + |
|
17 | 'display(multicontainer)\n' + | |
18 | 'multicontainer.selected_index = 0\n' + |
|
18 | 'multicontainer.selected_index = 0\n' + | |
19 | 'print("Success")\n'); |
|
19 | 'print("Success")\n'); | |
20 | this.execute_cell_then(multicontainer1_index, function(index){ |
|
20 | this.execute_cell_then(multicontainer1_index, function(index){ | |
21 |
|
21 | |||
22 | this.test.assertEquals(this.get_output_cell(index).text, 'Success\n', |
|
22 | this.test.assertEquals(this.get_output_cell(index).text, 'Success\n', | |
23 | 'Create multicontainer cell executed with correct output. (1)'); |
|
23 | 'Create multicontainer cell executed with correct output. (1)'); | |
24 |
|
24 | |||
25 | this.test.assert(this.cell_element_exists(index, |
|
25 | this.test.assert(this.cell_element_exists(index, | |
26 | '.widget-area .widget-subarea'), |
|
26 | '.widget-area .widget-subarea'), | |
27 | 'Widget subarea exists.'); |
|
27 | 'Widget subarea exists.'); | |
28 |
|
28 | |||
29 | this.test.assert(this.cell_element_exists(index, multicontainer1_query), |
|
29 | this.test.assert(this.cell_element_exists(index, multicontainer1_query), | |
30 | 'Widget tab list exists.'); |
|
30 | 'Widget tab list exists.'); | |
31 |
|
31 | |||
32 | this.test.assert(this.cell_element_exists(index, multicontainer1_query), |
|
32 | this.test.assert(this.cell_element_exists(index, multicontainer1_query), | |
33 | 'First widget tab list exists.'); |
|
33 | 'First widget tab list exists.'); | |
34 |
|
34 | |||
35 | // JQuery selector is 1 based |
|
35 | // JQuery selector is 1 based | |
36 | this.click(multicontainer1_query + ' li:nth-child(2) a'); |
|
36 | this.click(multicontainer1_query + ' li:nth-child(2) a'); | |
37 | }); |
|
37 | }); | |
38 |
|
38 | |||
39 | this.wait_for_idle(); |
|
39 | this.wait_for_idle(); | |
40 |
|
40 | |||
41 | index = this.append_cell( |
|
41 | index = this.append_cell( | |
42 | 'print(multicontainer.selected_index)\n' + |
|
42 | 'print(multicontainer.selected_index)\n' + | |
43 | 'multicontainer.selected_index = 2'); // 0 based |
|
43 | 'multicontainer.selected_index = 2'); // 0 based | |
44 | this.execute_cell_then(index, function(index){ |
|
44 | this.execute_cell_then(index, function(index){ | |
45 | this.test.assertEquals(this.get_output_cell(index).text, '1\n', // 0 based |
|
45 | this.test.assertEquals(this.get_output_cell(index).text, '1\n', // 0 based | |
46 | 'selected_index property updated with tab change.'); |
|
46 | 'selected_index property updated with tab change.'); | |
47 |
|
47 | |||
48 | // JQuery selector is 1 based |
|
48 | // JQuery selector is 1 based | |
49 | this.test.assert(!this.cell_element_function(multicontainer1_index, multicontainer1_query + ' li:nth-child(1)', 'hasClass', ['active']), |
|
49 | this.test.assert(!this.cell_element_function(multicontainer1_index, multicontainer1_query + ' li:nth-child(1)', 'hasClass', ['active']), | |
50 | "Tab 1 is not selected."); |
|
50 | "Tab 1 is not selected."); | |
51 | this.test.assert(!this.cell_element_function(multicontainer1_index, multicontainer1_query + ' li:nth-child(2)', 'hasClass', ['active']), |
|
51 | this.test.assert(!this.cell_element_function(multicontainer1_index, multicontainer1_query + ' li:nth-child(2)', 'hasClass', ['active']), | |
52 | "Tab 2 is not selected."); |
|
52 | "Tab 2 is not selected."); | |
53 | this.test.assert(this.cell_element_function(multicontainer1_index, multicontainer1_query + ' li:nth-child(3)', 'hasClass', ['active']), |
|
53 | this.test.assert(this.cell_element_function(multicontainer1_index, multicontainer1_query + ' li:nth-child(3)', 'hasClass', ['active']), | |
54 | "Tab 3 is selected."); |
|
54 | "Tab 3 is selected."); | |
55 | }); |
|
55 | }); | |
56 |
|
56 | |||
57 | index = this.append_cell('multicontainer.set_title(1, "hello")\nprint("Success")'); // 0 based |
|
57 | index = this.append_cell('multicontainer.set_title(1, "hello")\nprint("Success")'); // 0 based | |
58 | this.execute_cell_then(index, function(index){ |
|
58 | this.execute_cell_then(index, function(index){ | |
59 | this.test.assert(this.cell_element_function(multicontainer1_index, multicontainer1_query + |
|
59 | this.test.assert(this.cell_element_function(multicontainer1_index, multicontainer1_query + | |
60 | ' li:nth-child(2) a', 'html') == 'hello', |
|
60 | ' li:nth-child(2) a', 'html') == 'hello', | |
61 | 'Tab page title set (after display).'); |
|
61 | 'Tab page title set (after display).'); | |
62 | }); |
|
62 | }); | |
63 |
|
63 | |||
64 | // Test accordion view |
|
64 | // Test accordion view | |
65 | var multicontainer2_query = '.widget-area .widget-subarea .accordion'; |
|
65 | var multicontainer2_query = '.widget-area .widget-subarea .accordion'; | |
66 | var multicontainer2_index = this.append_cell( |
|
66 | var multicontainer2_index = this.append_cell( | |
67 | 'multicontainer = widgets.AccordionWidget()\n' + |
|
67 | 'multicontainer = widgets.AccordionWidget()\n' + | |
68 | 'page1 = widgets.TextWidget()\n' + |
|
68 | 'page1 = widgets.TextWidget()\n' + | |
69 | 'page2 = widgets.TextWidget()\n' + |
|
69 | 'page2 = widgets.TextWidget()\n' + | |
70 | 'page3 = widgets.TextWidget()\n' + |
|
70 | 'page3 = widgets.TextWidget()\n' + | |
71 | 'multicontainer.children = [page1, page2, page3]\n' + |
|
71 | 'multicontainer.children = [page1, page2, page3]\n' + | |
72 | 'multicontainer.set_title(2, "good")\n' + |
|
72 | 'multicontainer.set_title(2, "good")\n' + | |
73 | 'display(multicontainer)\n' + |
|
73 | 'display(multicontainer)\n' + | |
74 | 'multicontainer.selected_index = 0\n' + |
|
74 | 'multicontainer.selected_index = 0\n' + | |
75 | 'print("Success")\n'); |
|
75 | 'print("Success")\n'); | |
76 | this.execute_cell_then(multicontainer2_index, function(index){ |
|
76 | this.execute_cell_then(multicontainer2_index, function(index){ | |
77 |
|
77 | |||
78 | this.test.assertEquals(this.get_output_cell(index).text, 'Success\n', |
|
78 | this.test.assertEquals(this.get_output_cell(index).text, 'Success\n', | |
79 | 'Create multicontainer cell executed with correct output. (2)'); |
|
79 | 'Create multicontainer cell executed with correct output. (2)'); | |
80 |
|
80 | |||
81 | this.test.assert(this.cell_element_exists(index, |
|
81 | this.test.assert(this.cell_element_exists(index, | |
82 | '.widget-area .widget-subarea'), |
|
82 | '.widget-area .widget-subarea'), | |
83 | 'Widget subarea exists.'); |
|
83 | 'Widget subarea exists.'); | |
84 |
|
84 | |||
85 | this.test.assert(this.cell_element_exists(index, multicontainer2_query), |
|
85 | this.test.assert(this.cell_element_exists(index, multicontainer2_query), | |
86 | 'Widget accordion exists.'); |
|
86 | 'Widget accordion exists.'); | |
87 |
|
87 | |||
88 | this.test.assert(this.cell_element_exists(index, multicontainer2_query + |
|
88 | this.test.assert(this.cell_element_exists(index, multicontainer2_query + | |
89 | ' .accordion-group:nth-child(1) .accordion-body'), |
|
89 | ' .accordion-group:nth-child(1) .accordion-body'), | |
90 | 'First accordion page exists.'); |
|
90 | 'First accordion page exists.'); | |
91 |
|
91 | |||
92 | // JQuery selector is 1 based |
|
92 | // JQuery selector is 1 based | |
93 | this.test.assert(this.cell_element_function(index, multicontainer2_query + |
|
93 | this.test.assert(this.cell_element_function(index, multicontainer2_query + | |
94 | ' .accordion-group:nth-child(3) .accordion-heading .accordion-toggle', |
|
94 | ' .accordion-group:nth-child(3) .accordion-heading .accordion-toggle', | |
95 | 'html')=='good', 'Accordion page title set (before display).'); |
|
95 | 'html')=='good', 'Accordion page title set (before display).'); | |
96 |
|
96 | |||
97 | // JQuery selector is 1 based |
|
97 | // JQuery selector is 1 based | |
98 | this.click(multicontainer2_query + ' .accordion-group:nth-child(2) .accordion-heading .accordion-toggle'); |
|
98 | this.click(multicontainer2_query + ' .accordion-group:nth-child(2) .accordion-heading .accordion-toggle'); | |
99 | }); |
|
99 | }); | |
100 |
|
100 | |||
101 | this.wait_for_idle(); |
|
101 | this.wait_for_idle(); | |
102 |
|
102 | |||
103 | index = this.append_cell('print(multicontainer.selected_index)'); // 0 based |
|
103 | index = this.append_cell('print(multicontainer.selected_index)'); // 0 based | |
104 | this.execute_cell_then(index, function(index){ |
|
104 | this.execute_cell_then(index, function(index){ | |
105 | this.test.assertEquals(this.get_output_cell(index).text, '1\n', // 0 based |
|
105 | this.test.assertEquals(this.get_output_cell(index).text, '1\n', // 0 based | |
106 | 'selected_index property updated with tab change.'); |
|
106 | 'selected_index property updated with tab change.'); | |
|
107 | ||||
|
108 | var is_collapsed = this.evaluate(function(s){ | |||
|
109 | return $(s + ' div.accordion-group:nth-child(2) a').hasClass('collapsed'); // 1 based | |||
|
110 | }, {s: multicontainer2_query}); | |||
|
111 | this.test.assertEquals(is_collapsed, false, 'Was tab actually opened?'); | |||
107 | }); |
|
112 | }); | |
108 | }); No newline at end of file |
|
113 | }); |
@@ -1,583 +1,583 b'' | |||||
1 | """Module for interactive demos using IPython. |
|
1 | """Module for interactive demos using IPython. | |
2 |
|
2 | |||
3 | This module implements a few classes for running Python scripts interactively |
|
3 | This module implements a few classes for running Python scripts interactively | |
4 | in IPython for demonstrations. With very simple markup (a few tags in |
|
4 | in IPython for demonstrations. With very simple markup (a few tags in | |
5 | comments), you can control points where the script stops executing and returns |
|
5 | comments), you can control points where the script stops executing and returns | |
6 | control to IPython. |
|
6 | control to IPython. | |
7 |
|
7 | |||
8 |
|
8 | |||
9 | Provided classes |
|
9 | Provided classes | |
10 | ---------------- |
|
10 | ---------------- | |
11 |
|
11 | |||
12 | The classes are (see their docstrings for further details): |
|
12 | The classes are (see their docstrings for further details): | |
13 |
|
13 | |||
14 | - Demo: pure python demos |
|
14 | - Demo: pure python demos | |
15 |
|
15 | |||
16 | - IPythonDemo: demos with input to be processed by IPython as if it had been |
|
16 | - IPythonDemo: demos with input to be processed by IPython as if it had been | |
17 | typed interactively (so magics work, as well as any other special syntax you |
|
17 | typed interactively (so magics work, as well as any other special syntax you | |
18 | may have added via input prefilters). |
|
18 | may have added via input prefilters). | |
19 |
|
19 | |||
20 | - LineDemo: single-line version of the Demo class. These demos are executed |
|
20 | - LineDemo: single-line version of the Demo class. These demos are executed | |
21 | one line at a time, and require no markup. |
|
21 | one line at a time, and require no markup. | |
22 |
|
22 | |||
23 | - IPythonLineDemo: IPython version of the LineDemo class (the demo is |
|
23 | - IPythonLineDemo: IPython version of the LineDemo class (the demo is | |
24 | executed a line at a time, but processed via IPython). |
|
24 | executed a line at a time, but processed via IPython). | |
25 |
|
25 | |||
26 | - ClearMixin: mixin to make Demo classes with less visual clutter. It |
|
26 | - ClearMixin: mixin to make Demo classes with less visual clutter. It | |
27 | declares an empty marquee and a pre_cmd that clears the screen before each |
|
27 | declares an empty marquee and a pre_cmd that clears the screen before each | |
28 | block (see Subclassing below). |
|
28 | block (see Subclassing below). | |
29 |
|
29 | |||
30 | - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo |
|
30 | - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo | |
31 | classes. |
|
31 | classes. | |
32 |
|
32 | |||
33 | Inheritance diagram: |
|
33 | Inheritance diagram: | |
34 |
|
34 | |||
35 | .. inheritance-diagram:: IPython.lib.demo |
|
35 | .. inheritance-diagram:: IPython.lib.demo | |
36 | :parts: 3 |
|
36 | :parts: 3 | |
37 |
|
37 | |||
38 | Subclassing |
|
38 | Subclassing | |
39 | ----------- |
|
39 | ----------- | |
40 |
|
40 | |||
41 | The classes here all include a few methods meant to make customization by |
|
41 | The classes here all include a few methods meant to make customization by | |
42 | subclassing more convenient. Their docstrings below have some more details: |
|
42 | subclassing more convenient. Their docstrings below have some more details: | |
43 |
|
43 | |||
44 | - marquee(): generates a marquee to provide visible on-screen markers at each |
|
44 | - marquee(): generates a marquee to provide visible on-screen markers at each | |
45 | block start and end. |
|
45 | block start and end. | |
46 |
|
46 | |||
47 | - pre_cmd(): run right before the execution of each block. |
|
47 | - pre_cmd(): run right before the execution of each block. | |
48 |
|
48 | |||
49 | - post_cmd(): run right after the execution of each block. If the block |
|
49 | - post_cmd(): run right after the execution of each block. If the block | |
50 | raises an exception, this is NOT called. |
|
50 | raises an exception, this is NOT called. | |
51 |
|
51 | |||
52 |
|
52 | |||
53 | Operation |
|
53 | Operation | |
54 | --------- |
|
54 | --------- | |
55 |
|
55 | |||
56 | The file is run in its own empty namespace (though you can pass it a string of |
|
56 | The file is run in its own empty namespace (though you can pass it a string of | |
57 | arguments as if in a command line environment, and it will see those as |
|
57 | arguments as if in a command line environment, and it will see those as | |
58 | sys.argv). But at each stop, the global IPython namespace is updated with the |
|
58 | sys.argv). But at each stop, the global IPython namespace is updated with the | |
59 | current internal demo namespace, so you can work interactively with the data |
|
59 | current internal demo namespace, so you can work interactively with the data | |
60 | accumulated so far. |
|
60 | accumulated so far. | |
61 |
|
61 | |||
62 | By default, each block of code is printed (with syntax highlighting) before |
|
62 | By default, each block of code is printed (with syntax highlighting) before | |
63 | executing it and you have to confirm execution. This is intended to show the |
|
63 | executing it and you have to confirm execution. This is intended to show the | |
64 | code to an audience first so you can discuss it, and only proceed with |
|
64 | code to an audience first so you can discuss it, and only proceed with | |
65 | execution once you agree. There are a few tags which allow you to modify this |
|
65 | execution once you agree. There are a few tags which allow you to modify this | |
66 | behavior. |
|
66 | behavior. | |
67 |
|
67 | |||
68 | The supported tags are: |
|
68 | The supported tags are: | |
69 |
|
69 | |||
70 | # <demo> stop |
|
70 | # <demo> stop | |
71 |
|
71 | |||
72 | Defines block boundaries, the points where IPython stops execution of the |
|
72 | Defines block boundaries, the points where IPython stops execution of the | |
73 | file and returns to the interactive prompt. |
|
73 | file and returns to the interactive prompt. | |
74 |
|
74 | |||
75 | You can optionally mark the stop tag with extra dashes before and after the |
|
75 | You can optionally mark the stop tag with extra dashes before and after the | |
76 | word 'stop', to help visually distinguish the blocks in a text editor: |
|
76 | word 'stop', to help visually distinguish the blocks in a text editor: | |
77 |
|
77 | |||
78 | # <demo> --- stop --- |
|
78 | # <demo> --- stop --- | |
79 |
|
79 | |||
80 |
|
80 | |||
81 | # <demo> silent |
|
81 | # <demo> silent | |
82 |
|
82 | |||
83 | Make a block execute silently (and hence automatically). Typically used in |
|
83 | Make a block execute silently (and hence automatically). Typically used in | |
84 | cases where you have some boilerplate or initialization code which you need |
|
84 | cases where you have some boilerplate or initialization code which you need | |
85 | executed but do not want to be seen in the demo. |
|
85 | executed but do not want to be seen in the demo. | |
86 |
|
86 | |||
87 | # <demo> auto |
|
87 | # <demo> auto | |
88 |
|
88 | |||
89 | Make a block execute automatically, but still being printed. Useful for |
|
89 | Make a block execute automatically, but still being printed. Useful for | |
90 | simple code which does not warrant discussion, since it avoids the extra |
|
90 | simple code which does not warrant discussion, since it avoids the extra | |
91 | manual confirmation. |
|
91 | manual confirmation. | |
92 |
|
92 | |||
93 | # <demo> auto_all |
|
93 | # <demo> auto_all | |
94 |
|
94 | |||
95 | This tag can _only_ be in the first block, and if given it overrides the |
|
95 | This tag can _only_ be in the first block, and if given it overrides the | |
96 | individual auto tags to make the whole demo fully automatic (no block asks |
|
96 | individual auto tags to make the whole demo fully automatic (no block asks | |
97 | for confirmation). It can also be given at creation time (or the attribute |
|
97 | for confirmation). It can also be given at creation time (or the attribute | |
98 | set later) to override what's in the file. |
|
98 | set later) to override what's in the file. | |
99 |
|
99 | |||
100 | While _any_ python file can be run as a Demo instance, if there are no stop |
|
100 | While _any_ python file can be run as a Demo instance, if there are no stop | |
101 | tags the whole file will run in a single block (no different that calling |
|
101 | tags the whole file will run in a single block (no different that calling | |
102 | first %pycat and then %run). The minimal markup to make this useful is to |
|
102 | first %pycat and then %run). The minimal markup to make this useful is to | |
103 | place a set of stop tags; the other tags are only there to let you fine-tune |
|
103 | place a set of stop tags; the other tags are only there to let you fine-tune | |
104 | the execution. |
|
104 | the execution. | |
105 |
|
105 | |||
106 | This is probably best explained with the simple example file below. You can |
|
106 | This is probably best explained with the simple example file below. You can | |
107 | copy this into a file named ex_demo.py, and try running it via:: |
|
107 | copy this into a file named ex_demo.py, and try running it via:: | |
108 |
|
108 | |||
109 | from IPython.demo import Demo |
|
109 | from IPython.demo import Demo | |
110 | d = Demo('ex_demo.py') |
|
110 | d = Demo('ex_demo.py') | |
111 | d() |
|
111 | d() | |
112 |
|
112 | |||
113 | Each time you call the demo object, it runs the next block. The demo object |
|
113 | Each time you call the demo object, it runs the next block. The demo object | |
114 | has a few useful methods for navigation, like again(), edit(), jump(), seek() |
|
114 | has a few useful methods for navigation, like again(), edit(), jump(), seek() | |
115 | and back(). It can be reset for a new run via reset() or reloaded from disk |
|
115 | and back(). It can be reset for a new run via reset() or reloaded from disk | |
116 | (in case you've edited the source) via reload(). See their docstrings below. |
|
116 | (in case you've edited the source) via reload(). See their docstrings below. | |
117 |
|
117 | |||
118 | Note: To make this simpler to explore, a file called "demo-exercizer.py" has |
|
118 | Note: To make this simpler to explore, a file called "demo-exercizer.py" has | |
119 | been added to the "docs/examples/core" directory. Just cd to this directory in |
|
119 | been added to the "docs/examples/core" directory. Just cd to this directory in | |
120 | an IPython session, and type:: |
|
120 | an IPython session, and type:: | |
121 |
|
121 | |||
122 | %run demo-exercizer.py |
|
122 | %run demo-exercizer.py | |
123 |
|
123 | |||
124 | and then follow the directions. |
|
124 | and then follow the directions. | |
125 |
|
125 | |||
126 | Example |
|
126 | Example | |
127 | ------- |
|
127 | ------- | |
128 |
|
128 | |||
129 | The following is a very simple example of a valid demo file. |
|
129 | The following is a very simple example of a valid demo file. | |
130 |
|
130 | |||
131 | :: |
|
131 | :: | |
132 |
|
132 | |||
133 | #################### EXAMPLE DEMO <ex_demo.py> ############################### |
|
133 | #################### EXAMPLE DEMO <ex_demo.py> ############################### | |
134 | '''A simple interactive demo to illustrate the use of IPython's Demo class.''' |
|
134 | '''A simple interactive demo to illustrate the use of IPython's Demo class.''' | |
135 |
|
135 | |||
136 | print 'Hello, welcome to an interactive IPython demo.' |
|
136 | print 'Hello, welcome to an interactive IPython demo.' | |
137 |
|
137 | |||
138 | # The mark below defines a block boundary, which is a point where IPython will |
|
138 | # The mark below defines a block boundary, which is a point where IPython will | |
139 | # stop execution and return to the interactive prompt. The dashes are actually |
|
139 | # stop execution and return to the interactive prompt. The dashes are actually | |
140 | # optional and used only as a visual aid to clearly separate blocks while |
|
140 | # optional and used only as a visual aid to clearly separate blocks while | |
141 | # editing the demo code. |
|
141 | # editing the demo code. | |
142 | # <demo> stop |
|
142 | # <demo> stop | |
143 |
|
143 | |||
144 | x = 1 |
|
144 | x = 1 | |
145 | y = 2 |
|
145 | y = 2 | |
146 |
|
146 | |||
147 | # <demo> stop |
|
147 | # <demo> stop | |
148 |
|
148 | |||
149 | # the mark below makes this block as silent |
|
149 | # the mark below makes this block as silent | |
150 | # <demo> silent |
|
150 | # <demo> silent | |
151 |
|
151 | |||
152 | print 'This is a silent block, which gets executed but not printed.' |
|
152 | print 'This is a silent block, which gets executed but not printed.' | |
153 |
|
153 | |||
154 | # <demo> stop |
|
154 | # <demo> stop | |
155 | # <demo> auto |
|
155 | # <demo> auto | |
156 | print 'This is an automatic block.' |
|
156 | print 'This is an automatic block.' | |
157 | print 'It is executed without asking for confirmation, but printed.' |
|
157 | print 'It is executed without asking for confirmation, but printed.' | |
158 | z = x+y |
|
158 | z = x+y | |
159 |
|
159 | |||
160 | print 'z=',x |
|
160 | print 'z=',x | |
161 |
|
161 | |||
162 | # <demo> stop |
|
162 | # <demo> stop | |
163 | # This is just another normal block. |
|
163 | # This is just another normal block. | |
164 | print 'z is now:', z |
|
164 | print 'z is now:', z | |
165 |
|
165 | |||
166 | print 'bye!' |
|
166 | print 'bye!' | |
167 | ################### END EXAMPLE DEMO <ex_demo.py> ############################ |
|
167 | ################### END EXAMPLE DEMO <ex_demo.py> ############################ | |
168 | """ |
|
168 | """ | |
169 |
|
169 | |||
170 | from __future__ import unicode_literals |
|
170 | from __future__ import unicode_literals | |
171 |
|
171 | |||
172 | #***************************************************************************** |
|
172 | #***************************************************************************** | |
173 | # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu> |
|
173 | # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu> | |
174 | # |
|
174 | # | |
175 | # Distributed under the terms of the BSD License. The full license is in |
|
175 | # Distributed under the terms of the BSD License. The full license is in | |
176 | # the file COPYING, distributed as part of this software. |
|
176 | # the file COPYING, distributed as part of this software. | |
177 | # |
|
177 | # | |
178 | #***************************************************************************** |
|
178 | #***************************************************************************** | |
179 | from __future__ import print_function |
|
179 | from __future__ import print_function | |
180 |
|
180 | |||
181 | import os |
|
181 | import os | |
182 | import re |
|
182 | import re | |
183 | import shlex |
|
183 | import shlex | |
184 | import sys |
|
184 | import sys | |
185 |
|
185 | |||
186 | from IPython.utils import io |
|
186 | from IPython.utils import io | |
187 | from IPython.utils.text import marquee |
|
187 | from IPython.utils.text import marquee | |
188 | from IPython.utils import openpy |
|
188 | from IPython.utils import openpy | |
189 | from IPython.utils import py3compat |
|
189 | from IPython.utils import py3compat | |
190 | __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError'] |
|
190 | __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError'] | |
191 |
|
191 | |||
192 | class DemoError(Exception): pass |
|
192 | class DemoError(Exception): pass | |
193 |
|
193 | |||
194 | def re_mark(mark): |
|
194 | def re_mark(mark): | |
195 | return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE) |
|
195 | return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE) | |
196 |
|
196 | |||
197 | class Demo(object): |
|
197 | class Demo(object): | |
198 |
|
198 | |||
199 | re_stop = re_mark('-*\s?stop\s?-*') |
|
199 | re_stop = re_mark('-*\s?stop\s?-*') | |
200 | re_silent = re_mark('silent') |
|
200 | re_silent = re_mark('silent') | |
201 | re_auto = re_mark('auto') |
|
201 | re_auto = re_mark('auto') | |
202 | re_auto_all = re_mark('auto_all') |
|
202 | re_auto_all = re_mark('auto_all') | |
203 |
|
203 | |||
204 | def __init__(self,src,title='',arg_str='',auto_all=None): |
|
204 | def __init__(self,src,title='',arg_str='',auto_all=None): | |
205 | """Make a new demo object. To run the demo, simply call the object. |
|
205 | """Make a new demo object. To run the demo, simply call the object. | |
206 |
|
206 | |||
207 | See the module docstring for full details and an example (you can use |
|
207 | See the module docstring for full details and an example (you can use | |
208 | IPython.Demo? in IPython to see it). |
|
208 | IPython.Demo? in IPython to see it). | |
209 |
|
209 | |||
210 | Inputs: |
|
210 | Inputs: | |
211 |
|
211 | |||
212 | - src is either a file, or file-like object, or a |
|
212 | - src is either a file, or file-like object, or a | |
213 | string that can be resolved to a filename. |
|
213 | string that can be resolved to a filename. | |
214 |
|
214 | |||
215 | Optional inputs: |
|
215 | Optional inputs: | |
216 |
|
216 | |||
217 | - title: a string to use as the demo name. Of most use when the demo |
|
217 | - title: a string to use as the demo name. Of most use when the demo | |
218 | you are making comes from an object that has no filename, or if you |
|
218 | you are making comes from an object that has no filename, or if you | |
219 | want an alternate denotation distinct from the filename. |
|
219 | want an alternate denotation distinct from the filename. | |
220 |
|
220 | |||
221 | - arg_str(''): a string of arguments, internally converted to a list |
|
221 | - arg_str(''): a string of arguments, internally converted to a list | |
222 | just like sys.argv, so the demo script can see a similar |
|
222 | just like sys.argv, so the demo script can see a similar | |
223 | environment. |
|
223 | environment. | |
224 |
|
224 | |||
225 | - auto_all(None): global flag to run all blocks automatically without |
|
225 | - auto_all(None): global flag to run all blocks automatically without | |
226 | confirmation. This attribute overrides the block-level tags and |
|
226 | confirmation. This attribute overrides the block-level tags and | |
227 | applies to the whole demo. It is an attribute of the object, and |
|
227 | applies to the whole demo. It is an attribute of the object, and | |
228 | can be changed at runtime simply by reassigning it to a boolean |
|
228 | can be changed at runtime simply by reassigning it to a boolean | |
229 | value. |
|
229 | value. | |
230 | """ |
|
230 | """ | |
231 | if hasattr(src, "read"): |
|
231 | if hasattr(src, "read"): | |
232 | # It seems to be a file or a file-like object |
|
232 | # It seems to be a file or a file-like object | |
233 | self.fname = "from a file-like object" |
|
233 | self.fname = "from a file-like object" | |
234 | if title == '': |
|
234 | if title == '': | |
235 | self.title = "from a file-like object" |
|
235 | self.title = "from a file-like object" | |
236 | else: |
|
236 | else: | |
237 | self.title = title |
|
237 | self.title = title | |
238 | else: |
|
238 | else: | |
239 | # Assume it's a string or something that can be converted to one |
|
239 | # Assume it's a string or something that can be converted to one | |
240 | self.fname = src |
|
240 | self.fname = src | |
241 | if title == '': |
|
241 | if title == '': | |
242 | (filepath, filename) = os.path.split(src) |
|
242 | (filepath, filename) = os.path.split(src) | |
243 | self.title = filename |
|
243 | self.title = filename | |
244 | else: |
|
244 | else: | |
245 | self.title = title |
|
245 | self.title = title | |
246 | self.sys_argv = [src] + shlex.split(arg_str) |
|
246 | self.sys_argv = [src] + shlex.split(arg_str) | |
247 | self.auto_all = auto_all |
|
247 | self.auto_all = auto_all | |
248 | self.src = src |
|
248 | self.src = src | |
249 |
|
249 | |||
250 | # get a few things from ipython. While it's a bit ugly design-wise, |
|
250 | # get a few things from ipython. While it's a bit ugly design-wise, | |
251 | # it ensures that things like color scheme and the like are always in |
|
251 | # it ensures that things like color scheme and the like are always in | |
252 | # sync with the ipython mode being used. This class is only meant to |
|
252 | # sync with the ipython mode being used. This class is only meant to | |
253 | # be used inside ipython anyways, so it's OK. |
|
253 | # be used inside ipython anyways, so it's OK. | |
254 | ip = get_ipython() # this is in builtins whenever IPython is running |
|
254 | ip = get_ipython() # this is in builtins whenever IPython is running | |
255 | self.ip_ns = ip.user_ns |
|
255 | self.ip_ns = ip.user_ns | |
256 | self.ip_colorize = ip.pycolorize |
|
256 | self.ip_colorize = ip.pycolorize | |
257 | self.ip_showtb = ip.showtraceback |
|
257 | self.ip_showtb = ip.showtraceback | |
258 | self.ip_run_cell = ip.run_cell |
|
258 | self.ip_run_cell = ip.run_cell | |
259 | self.shell = ip |
|
259 | self.shell = ip | |
260 |
|
260 | |||
261 | # load user data and initialize data structures |
|
261 | # load user data and initialize data structures | |
262 | self.reload() |
|
262 | self.reload() | |
263 |
|
263 | |||
264 | def fload(self): |
|
264 | def fload(self): | |
265 | """Load file object.""" |
|
265 | """Load file object.""" | |
266 | # read data and parse into blocks |
|
266 | # read data and parse into blocks | |
267 | if hasattr(self, 'fobj') and self.fobj is not None: |
|
267 | if hasattr(self, 'fobj') and self.fobj is not None: | |
268 | self.fobj.close() |
|
268 | self.fobj.close() | |
269 | if hasattr(self.src, "read"): |
|
269 | if hasattr(self.src, "read"): | |
270 | # It seems to be a file or a file-like object |
|
270 | # It seems to be a file or a file-like object | |
271 | self.fobj = self.src |
|
271 | self.fobj = self.src | |
272 | else: |
|
272 | else: | |
273 | # Assume it's a string or something that can be converted to one |
|
273 | # Assume it's a string or something that can be converted to one | |
274 | self.fobj = openpy.open(self.fname) |
|
274 | self.fobj = openpy.open(self.fname) | |
275 |
|
275 | |||
276 | def reload(self): |
|
276 | def reload(self): | |
277 | """Reload source from disk and initialize state.""" |
|
277 | """Reload source from disk and initialize state.""" | |
278 | self.fload() |
|
278 | self.fload() | |
279 |
|
279 | |||
280 | self.src = "".join(openpy.strip_encoding_cookie(self.fobj)) |
|
280 | self.src = "".join(openpy.strip_encoding_cookie(self.fobj)) | |
281 | src_b = [b.strip() for b in self.re_stop.split(self.src) if b] |
|
281 | src_b = [b.strip() for b in self.re_stop.split(self.src) if b] | |
282 | self._silent = [bool(self.re_silent.findall(b)) for b in src_b] |
|
282 | self._silent = [bool(self.re_silent.findall(b)) for b in src_b] | |
283 | self._auto = [bool(self.re_auto.findall(b)) for b in src_b] |
|
283 | self._auto = [bool(self.re_auto.findall(b)) for b in src_b] | |
284 |
|
284 | |||
285 | # if auto_all is not given (def. None), we read it from the file |
|
285 | # if auto_all is not given (def. None), we read it from the file | |
286 | if self.auto_all is None: |
|
286 | if self.auto_all is None: | |
287 | self.auto_all = bool(self.re_auto_all.findall(src_b[0])) |
|
287 | self.auto_all = bool(self.re_auto_all.findall(src_b[0])) | |
288 | else: |
|
288 | else: | |
289 | self.auto_all = bool(self.auto_all) |
|
289 | self.auto_all = bool(self.auto_all) | |
290 |
|
290 | |||
291 | # Clean the sources from all markup so it doesn't get displayed when |
|
291 | # Clean the sources from all markup so it doesn't get displayed when | |
292 | # running the demo |
|
292 | # running the demo | |
293 | src_blocks = [] |
|
293 | src_blocks = [] | |
294 | auto_strip = lambda s: self.re_auto.sub('',s) |
|
294 | auto_strip = lambda s: self.re_auto.sub('',s) | |
295 | for i,b in enumerate(src_b): |
|
295 | for i,b in enumerate(src_b): | |
296 | if self._auto[i]: |
|
296 | if self._auto[i]: | |
297 | src_blocks.append(auto_strip(b)) |
|
297 | src_blocks.append(auto_strip(b)) | |
298 | else: |
|
298 | else: | |
299 | src_blocks.append(b) |
|
299 | src_blocks.append(b) | |
300 | # remove the auto_all marker |
|
300 | # remove the auto_all marker | |
301 | src_blocks[0] = self.re_auto_all.sub('',src_blocks[0]) |
|
301 | src_blocks[0] = self.re_auto_all.sub('',src_blocks[0]) | |
302 |
|
302 | |||
303 | self.nblocks = len(src_blocks) |
|
303 | self.nblocks = len(src_blocks) | |
304 | self.src_blocks = src_blocks |
|
304 | self.src_blocks = src_blocks | |
305 |
|
305 | |||
306 | # also build syntax-highlighted source |
|
306 | # also build syntax-highlighted source | |
307 | self.src_blocks_colored = map(self.ip_colorize,self.src_blocks) |
|
307 | self.src_blocks_colored = list(map(self.ip_colorize,self.src_blocks)) | |
308 |
|
308 | |||
309 | # ensure clean namespace and seek offset |
|
309 | # ensure clean namespace and seek offset | |
310 | self.reset() |
|
310 | self.reset() | |
311 |
|
311 | |||
312 | def reset(self): |
|
312 | def reset(self): | |
313 | """Reset the namespace and seek pointer to restart the demo""" |
|
313 | """Reset the namespace and seek pointer to restart the demo""" | |
314 | self.user_ns = {} |
|
314 | self.user_ns = {} | |
315 | self.finished = False |
|
315 | self.finished = False | |
316 | self.block_index = 0 |
|
316 | self.block_index = 0 | |
317 |
|
317 | |||
318 | def _validate_index(self,index): |
|
318 | def _validate_index(self,index): | |
319 | if index<0 or index>=self.nblocks: |
|
319 | if index<0 or index>=self.nblocks: | |
320 | raise ValueError('invalid block index %s' % index) |
|
320 | raise ValueError('invalid block index %s' % index) | |
321 |
|
321 | |||
322 | def _get_index(self,index): |
|
322 | def _get_index(self,index): | |
323 | """Get the current block index, validating and checking status. |
|
323 | """Get the current block index, validating and checking status. | |
324 |
|
324 | |||
325 | Returns None if the demo is finished""" |
|
325 | Returns None if the demo is finished""" | |
326 |
|
326 | |||
327 | if index is None: |
|
327 | if index is None: | |
328 | if self.finished: |
|
328 | if self.finished: | |
329 | print('Demo finished. Use <demo_name>.reset() if you want to rerun it.', file=io.stdout) |
|
329 | print('Demo finished. Use <demo_name>.reset() if you want to rerun it.', file=io.stdout) | |
330 | return None |
|
330 | return None | |
331 | index = self.block_index |
|
331 | index = self.block_index | |
332 | else: |
|
332 | else: | |
333 | self._validate_index(index) |
|
333 | self._validate_index(index) | |
334 | return index |
|
334 | return index | |
335 |
|
335 | |||
336 | def seek(self,index): |
|
336 | def seek(self,index): | |
337 | """Move the current seek pointer to the given block. |
|
337 | """Move the current seek pointer to the given block. | |
338 |
|
338 | |||
339 | You can use negative indices to seek from the end, with identical |
|
339 | You can use negative indices to seek from the end, with identical | |
340 | semantics to those of Python lists.""" |
|
340 | semantics to those of Python lists.""" | |
341 | if index<0: |
|
341 | if index<0: | |
342 | index = self.nblocks + index |
|
342 | index = self.nblocks + index | |
343 | self._validate_index(index) |
|
343 | self._validate_index(index) | |
344 | self.block_index = index |
|
344 | self.block_index = index | |
345 | self.finished = False |
|
345 | self.finished = False | |
346 |
|
346 | |||
347 | def back(self,num=1): |
|
347 | def back(self,num=1): | |
348 | """Move the seek pointer back num blocks (default is 1).""" |
|
348 | """Move the seek pointer back num blocks (default is 1).""" | |
349 | self.seek(self.block_index-num) |
|
349 | self.seek(self.block_index-num) | |
350 |
|
350 | |||
351 | def jump(self,num=1): |
|
351 | def jump(self,num=1): | |
352 | """Jump a given number of blocks relative to the current one. |
|
352 | """Jump a given number of blocks relative to the current one. | |
353 |
|
353 | |||
354 | The offset can be positive or negative, defaults to 1.""" |
|
354 | The offset can be positive or negative, defaults to 1.""" | |
355 | self.seek(self.block_index+num) |
|
355 | self.seek(self.block_index+num) | |
356 |
|
356 | |||
357 | def again(self): |
|
357 | def again(self): | |
358 | """Move the seek pointer back one block and re-execute.""" |
|
358 | """Move the seek pointer back one block and re-execute.""" | |
359 | self.back(1) |
|
359 | self.back(1) | |
360 | self() |
|
360 | self() | |
361 |
|
361 | |||
362 | def edit(self,index=None): |
|
362 | def edit(self,index=None): | |
363 | """Edit a block. |
|
363 | """Edit a block. | |
364 |
|
364 | |||
365 | If no number is given, use the last block executed. |
|
365 | If no number is given, use the last block executed. | |
366 |
|
366 | |||
367 | This edits the in-memory copy of the demo, it does NOT modify the |
|
367 | This edits the in-memory copy of the demo, it does NOT modify the | |
368 | original source file. If you want to do that, simply open the file in |
|
368 | original source file. If you want to do that, simply open the file in | |
369 | an editor and use reload() when you make changes to the file. This |
|
369 | an editor and use reload() when you make changes to the file. This | |
370 | method is meant to let you change a block during a demonstration for |
|
370 | method is meant to let you change a block during a demonstration for | |
371 | explanatory purposes, without damaging your original script.""" |
|
371 | explanatory purposes, without damaging your original script.""" | |
372 |
|
372 | |||
373 | index = self._get_index(index) |
|
373 | index = self._get_index(index) | |
374 | if index is None: |
|
374 | if index is None: | |
375 | return |
|
375 | return | |
376 | # decrease the index by one (unless we're at the very beginning), so |
|
376 | # decrease the index by one (unless we're at the very beginning), so | |
377 | # that the default demo.edit() call opens up the sblock we've last run |
|
377 | # that the default demo.edit() call opens up the sblock we've last run | |
378 | if index>0: |
|
378 | if index>0: | |
379 | index -= 1 |
|
379 | index -= 1 | |
380 |
|
380 | |||
381 | filename = self.shell.mktempfile(self.src_blocks[index]) |
|
381 | filename = self.shell.mktempfile(self.src_blocks[index]) | |
382 | self.shell.hooks.editor(filename,1) |
|
382 | self.shell.hooks.editor(filename,1) | |
383 | with open(filename, 'r') as f: |
|
383 | with open(filename, 'r') as f: | |
384 | new_block = f.read() |
|
384 | new_block = f.read() | |
385 | # update the source and colored block |
|
385 | # update the source and colored block | |
386 | self.src_blocks[index] = new_block |
|
386 | self.src_blocks[index] = new_block | |
387 | self.src_blocks_colored[index] = self.ip_colorize(new_block) |
|
387 | self.src_blocks_colored[index] = self.ip_colorize(new_block) | |
388 | self.block_index = index |
|
388 | self.block_index = index | |
389 | # call to run with the newly edited index |
|
389 | # call to run with the newly edited index | |
390 | self() |
|
390 | self() | |
391 |
|
391 | |||
392 | def show(self,index=None): |
|
392 | def show(self,index=None): | |
393 | """Show a single block on screen""" |
|
393 | """Show a single block on screen""" | |
394 |
|
394 | |||
395 | index = self._get_index(index) |
|
395 | index = self._get_index(index) | |
396 | if index is None: |
|
396 | if index is None: | |
397 | return |
|
397 | return | |
398 |
|
398 | |||
399 | print(self.marquee('<%s> block # %s (%s remaining)' % |
|
399 | print(self.marquee('<%s> block # %s (%s remaining)' % | |
400 | (self.title,index,self.nblocks-index-1)), file=io.stdout) |
|
400 | (self.title,index,self.nblocks-index-1)), file=io.stdout) | |
401 | print(self.src_blocks_colored[index], file=io.stdout) |
|
401 | print(self.src_blocks_colored[index], file=io.stdout) | |
402 | sys.stdout.flush() |
|
402 | sys.stdout.flush() | |
403 |
|
403 | |||
404 | def show_all(self): |
|
404 | def show_all(self): | |
405 | """Show entire demo on screen, block by block""" |
|
405 | """Show entire demo on screen, block by block""" | |
406 |
|
406 | |||
407 | fname = self.title |
|
407 | fname = self.title | |
408 | title = self.title |
|
408 | title = self.title | |
409 | nblocks = self.nblocks |
|
409 | nblocks = self.nblocks | |
410 | silent = self._silent |
|
410 | silent = self._silent | |
411 | marquee = self.marquee |
|
411 | marquee = self.marquee | |
412 | for index,block in enumerate(self.src_blocks_colored): |
|
412 | for index,block in enumerate(self.src_blocks_colored): | |
413 | if silent[index]: |
|
413 | if silent[index]: | |
414 | print(marquee('<%s> SILENT block # %s (%s remaining)' % |
|
414 | print(marquee('<%s> SILENT block # %s (%s remaining)' % | |
415 | (title,index,nblocks-index-1)), file=io.stdout) |
|
415 | (title,index,nblocks-index-1)), file=io.stdout) | |
416 | else: |
|
416 | else: | |
417 | print(marquee('<%s> block # %s (%s remaining)' % |
|
417 | print(marquee('<%s> block # %s (%s remaining)' % | |
418 | (title,index,nblocks-index-1)), file=io.stdout) |
|
418 | (title,index,nblocks-index-1)), file=io.stdout) | |
419 | print(block, end=' ', file=io.stdout) |
|
419 | print(block, end=' ', file=io.stdout) | |
420 | sys.stdout.flush() |
|
420 | sys.stdout.flush() | |
421 |
|
421 | |||
422 | def run_cell(self,source): |
|
422 | def run_cell(self,source): | |
423 | """Execute a string with one or more lines of code""" |
|
423 | """Execute a string with one or more lines of code""" | |
424 |
|
424 | |||
425 | exec(source, self.user_ns) |
|
425 | exec(source, self.user_ns) | |
426 |
|
426 | |||
427 | def __call__(self,index=None): |
|
427 | def __call__(self,index=None): | |
428 | """run a block of the demo. |
|
428 | """run a block of the demo. | |
429 |
|
429 | |||
430 | If index is given, it should be an integer >=1 and <= nblocks. This |
|
430 | If index is given, it should be an integer >=1 and <= nblocks. This | |
431 | means that the calling convention is one off from typical Python |
|
431 | means that the calling convention is one off from typical Python | |
432 | lists. The reason for the inconsistency is that the demo always |
|
432 | lists. The reason for the inconsistency is that the demo always | |
433 | prints 'Block n/N, and N is the total, so it would be very odd to use |
|
433 | prints 'Block n/N, and N is the total, so it would be very odd to use | |
434 | zero-indexing here.""" |
|
434 | zero-indexing here.""" | |
435 |
|
435 | |||
436 | index = self._get_index(index) |
|
436 | index = self._get_index(index) | |
437 | if index is None: |
|
437 | if index is None: | |
438 | return |
|
438 | return | |
439 | try: |
|
439 | try: | |
440 | marquee = self.marquee |
|
440 | marquee = self.marquee | |
441 | next_block = self.src_blocks[index] |
|
441 | next_block = self.src_blocks[index] | |
442 | self.block_index += 1 |
|
442 | self.block_index += 1 | |
443 | if self._silent[index]: |
|
443 | if self._silent[index]: | |
444 | print(marquee('Executing silent block # %s (%s remaining)' % |
|
444 | print(marquee('Executing silent block # %s (%s remaining)' % | |
445 | (index,self.nblocks-index-1)), file=io.stdout) |
|
445 | (index,self.nblocks-index-1)), file=io.stdout) | |
446 | else: |
|
446 | else: | |
447 | self.pre_cmd() |
|
447 | self.pre_cmd() | |
448 | self.show(index) |
|
448 | self.show(index) | |
449 | if self.auto_all or self._auto[index]: |
|
449 | if self.auto_all or self._auto[index]: | |
450 | print(marquee('output:'), file=io.stdout) |
|
450 | print(marquee('output:'), file=io.stdout) | |
451 | else: |
|
451 | else: | |
452 | print(marquee('Press <q> to quit, <Enter> to execute...'), end=' ', file=io.stdout) |
|
452 | print(marquee('Press <q> to quit, <Enter> to execute...'), end=' ', file=io.stdout) | |
453 | ans = py3compat.input().strip() |
|
453 | ans = py3compat.input().strip() | |
454 | if ans: |
|
454 | if ans: | |
455 | print(marquee('Block NOT executed'), file=io.stdout) |
|
455 | print(marquee('Block NOT executed'), file=io.stdout) | |
456 | return |
|
456 | return | |
457 | try: |
|
457 | try: | |
458 | save_argv = sys.argv |
|
458 | save_argv = sys.argv | |
459 | sys.argv = self.sys_argv |
|
459 | sys.argv = self.sys_argv | |
460 | self.run_cell(next_block) |
|
460 | self.run_cell(next_block) | |
461 | self.post_cmd() |
|
461 | self.post_cmd() | |
462 | finally: |
|
462 | finally: | |
463 | sys.argv = save_argv |
|
463 | sys.argv = save_argv | |
464 |
|
464 | |||
465 | except: |
|
465 | except: | |
466 | self.ip_showtb(filename=self.fname) |
|
466 | self.ip_showtb(filename=self.fname) | |
467 | else: |
|
467 | else: | |
468 | self.ip_ns.update(self.user_ns) |
|
468 | self.ip_ns.update(self.user_ns) | |
469 |
|
469 | |||
470 | if self.block_index == self.nblocks: |
|
470 | if self.block_index == self.nblocks: | |
471 | mq1 = self.marquee('END OF DEMO') |
|
471 | mq1 = self.marquee('END OF DEMO') | |
472 | if mq1: |
|
472 | if mq1: | |
473 | # avoid spurious print >>io.stdout,s if empty marquees are used |
|
473 | # avoid spurious print >>io.stdout,s if empty marquees are used | |
474 | print(file=io.stdout) |
|
474 | print(file=io.stdout) | |
475 | print(mq1, file=io.stdout) |
|
475 | print(mq1, file=io.stdout) | |
476 | print(self.marquee('Use <demo_name>.reset() if you want to rerun it.'), file=io.stdout) |
|
476 | print(self.marquee('Use <demo_name>.reset() if you want to rerun it.'), file=io.stdout) | |
477 | self.finished = True |
|
477 | self.finished = True | |
478 |
|
478 | |||
479 | # These methods are meant to be overridden by subclasses who may wish to |
|
479 | # These methods are meant to be overridden by subclasses who may wish to | |
480 | # customize the behavior of of their demos. |
|
480 | # customize the behavior of of their demos. | |
481 | def marquee(self,txt='',width=78,mark='*'): |
|
481 | def marquee(self,txt='',width=78,mark='*'): | |
482 | """Return the input string centered in a 'marquee'.""" |
|
482 | """Return the input string centered in a 'marquee'.""" | |
483 | return marquee(txt,width,mark) |
|
483 | return marquee(txt,width,mark) | |
484 |
|
484 | |||
485 | def pre_cmd(self): |
|
485 | def pre_cmd(self): | |
486 | """Method called before executing each block.""" |
|
486 | """Method called before executing each block.""" | |
487 | pass |
|
487 | pass | |
488 |
|
488 | |||
489 | def post_cmd(self): |
|
489 | def post_cmd(self): | |
490 | """Method called after executing each block.""" |
|
490 | """Method called after executing each block.""" | |
491 | pass |
|
491 | pass | |
492 |
|
492 | |||
493 |
|
493 | |||
494 | class IPythonDemo(Demo): |
|
494 | class IPythonDemo(Demo): | |
495 | """Class for interactive demos with IPython's input processing applied. |
|
495 | """Class for interactive demos with IPython's input processing applied. | |
496 |
|
496 | |||
497 | This subclasses Demo, but instead of executing each block by the Python |
|
497 | This subclasses Demo, but instead of executing each block by the Python | |
498 | interpreter (via exec), it actually calls IPython on it, so that any input |
|
498 | interpreter (via exec), it actually calls IPython on it, so that any input | |
499 | filters which may be in place are applied to the input block. |
|
499 | filters which may be in place are applied to the input block. | |
500 |
|
500 | |||
501 | If you have an interactive environment which exposes special input |
|
501 | If you have an interactive environment which exposes special input | |
502 | processing, you can use this class instead to write demo scripts which |
|
502 | processing, you can use this class instead to write demo scripts which | |
503 | operate exactly as if you had typed them interactively. The default Demo |
|
503 | operate exactly as if you had typed them interactively. The default Demo | |
504 | class requires the input to be valid, pure Python code. |
|
504 | class requires the input to be valid, pure Python code. | |
505 | """ |
|
505 | """ | |
506 |
|
506 | |||
507 | def run_cell(self,source): |
|
507 | def run_cell(self,source): | |
508 | """Execute a string with one or more lines of code""" |
|
508 | """Execute a string with one or more lines of code""" | |
509 |
|
509 | |||
510 | self.shell.run_cell(source) |
|
510 | self.shell.run_cell(source) | |
511 |
|
511 | |||
512 | class LineDemo(Demo): |
|
512 | class LineDemo(Demo): | |
513 | """Demo where each line is executed as a separate block. |
|
513 | """Demo where each line is executed as a separate block. | |
514 |
|
514 | |||
515 | The input script should be valid Python code. |
|
515 | The input script should be valid Python code. | |
516 |
|
516 | |||
517 | This class doesn't require any markup at all, and it's meant for simple |
|
517 | This class doesn't require any markup at all, and it's meant for simple | |
518 | scripts (with no nesting or any kind of indentation) which consist of |
|
518 | scripts (with no nesting or any kind of indentation) which consist of | |
519 | multiple lines of input to be executed, one at a time, as if they had been |
|
519 | multiple lines of input to be executed, one at a time, as if they had been | |
520 | typed in the interactive prompt. |
|
520 | typed in the interactive prompt. | |
521 |
|
521 | |||
522 | Note: the input can not have *any* indentation, which means that only |
|
522 | Note: the input can not have *any* indentation, which means that only | |
523 | single-lines of input are accepted, not even function definitions are |
|
523 | single-lines of input are accepted, not even function definitions are | |
524 | valid.""" |
|
524 | valid.""" | |
525 |
|
525 | |||
526 | def reload(self): |
|
526 | def reload(self): | |
527 | """Reload source from disk and initialize state.""" |
|
527 | """Reload source from disk and initialize state.""" | |
528 | # read data and parse into blocks |
|
528 | # read data and parse into blocks | |
529 | self.fload() |
|
529 | self.fload() | |
530 | lines = self.fobj.readlines() |
|
530 | lines = self.fobj.readlines() | |
531 | src_b = [l for l in lines if l.strip()] |
|
531 | src_b = [l for l in lines if l.strip()] | |
532 | nblocks = len(src_b) |
|
532 | nblocks = len(src_b) | |
533 | self.src = ''.join(lines) |
|
533 | self.src = ''.join(lines) | |
534 | self._silent = [False]*nblocks |
|
534 | self._silent = [False]*nblocks | |
535 | self._auto = [True]*nblocks |
|
535 | self._auto = [True]*nblocks | |
536 | self.auto_all = True |
|
536 | self.auto_all = True | |
537 | self.nblocks = nblocks |
|
537 | self.nblocks = nblocks | |
538 | self.src_blocks = src_b |
|
538 | self.src_blocks = src_b | |
539 |
|
539 | |||
540 | # also build syntax-highlighted source |
|
540 | # also build syntax-highlighted source | |
541 | self.src_blocks_colored = map(self.ip_colorize,self.src_blocks) |
|
541 | self.src_blocks_colored = map(self.ip_colorize,self.src_blocks) | |
542 |
|
542 | |||
543 | # ensure clean namespace and seek offset |
|
543 | # ensure clean namespace and seek offset | |
544 | self.reset() |
|
544 | self.reset() | |
545 |
|
545 | |||
546 |
|
546 | |||
547 | class IPythonLineDemo(IPythonDemo,LineDemo): |
|
547 | class IPythonLineDemo(IPythonDemo,LineDemo): | |
548 | """Variant of the LineDemo class whose input is processed by IPython.""" |
|
548 | """Variant of the LineDemo class whose input is processed by IPython.""" | |
549 | pass |
|
549 | pass | |
550 |
|
550 | |||
551 |
|
551 | |||
552 | class ClearMixin(object): |
|
552 | class ClearMixin(object): | |
553 | """Use this mixin to make Demo classes with less visual clutter. |
|
553 | """Use this mixin to make Demo classes with less visual clutter. | |
554 |
|
554 | |||
555 | Demos using this mixin will clear the screen before every block and use |
|
555 | Demos using this mixin will clear the screen before every block and use | |
556 | blank marquees. |
|
556 | blank marquees. | |
557 |
|
557 | |||
558 | Note that in order for the methods defined here to actually override those |
|
558 | Note that in order for the methods defined here to actually override those | |
559 | of the classes it's mixed with, it must go /first/ in the inheritance |
|
559 | of the classes it's mixed with, it must go /first/ in the inheritance | |
560 | tree. For example: |
|
560 | tree. For example: | |
561 |
|
561 | |||
562 | class ClearIPDemo(ClearMixin,IPythonDemo): pass |
|
562 | class ClearIPDemo(ClearMixin,IPythonDemo): pass | |
563 |
|
563 | |||
564 | will provide an IPythonDemo class with the mixin's features. |
|
564 | will provide an IPythonDemo class with the mixin's features. | |
565 | """ |
|
565 | """ | |
566 |
|
566 | |||
567 | def marquee(self,txt='',width=78,mark='*'): |
|
567 | def marquee(self,txt='',width=78,mark='*'): | |
568 | """Blank marquee that returns '' no matter what the input.""" |
|
568 | """Blank marquee that returns '' no matter what the input.""" | |
569 | return '' |
|
569 | return '' | |
570 |
|
570 | |||
571 | def pre_cmd(self): |
|
571 | def pre_cmd(self): | |
572 | """Method called before executing each block. |
|
572 | """Method called before executing each block. | |
573 |
|
573 | |||
574 | This one simply clears the screen.""" |
|
574 | This one simply clears the screen.""" | |
575 | from IPython.utils.terminal import term_clear |
|
575 | from IPython.utils.terminal import term_clear | |
576 | term_clear() |
|
576 | term_clear() | |
577 |
|
577 | |||
578 | class ClearDemo(ClearMixin,Demo): |
|
578 | class ClearDemo(ClearMixin,Demo): | |
579 | pass |
|
579 | pass | |
580 |
|
580 | |||
581 |
|
581 | |||
582 | class ClearIPDemo(ClearMixin,IPythonDemo): |
|
582 | class ClearIPDemo(ClearMixin,IPythonDemo): | |
583 | pass |
|
583 | pass |
@@ -1,1463 +1,1463 b'' | |||||
1 | # encoding: utf-8 |
|
1 | # encoding: utf-8 | |
2 | """ |
|
2 | """ | |
3 | Facilities for launching IPython processes asynchronously. |
|
3 | Facilities for launching IPython processes asynchronously. | |
4 |
|
4 | |||
5 | Authors: |
|
5 | Authors: | |
6 |
|
6 | |||
7 | * Brian Granger |
|
7 | * Brian Granger | |
8 | * MinRK |
|
8 | * MinRK | |
9 | """ |
|
9 | """ | |
10 |
|
10 | |||
11 | #----------------------------------------------------------------------------- |
|
11 | #----------------------------------------------------------------------------- | |
12 | # Copyright (C) 2008-2011 The IPython Development Team |
|
12 | # Copyright (C) 2008-2011 The IPython Development Team | |
13 | # |
|
13 | # | |
14 | # Distributed under the terms of the BSD License. The full license is in |
|
14 | # Distributed under the terms of the BSD License. The full license is in | |
15 | # the file COPYING, distributed as part of this software. |
|
15 | # the file COPYING, distributed as part of this software. | |
16 | #----------------------------------------------------------------------------- |
|
16 | #----------------------------------------------------------------------------- | |
17 |
|
17 | |||
18 | #----------------------------------------------------------------------------- |
|
18 | #----------------------------------------------------------------------------- | |
19 | # Imports |
|
19 | # Imports | |
20 | #----------------------------------------------------------------------------- |
|
20 | #----------------------------------------------------------------------------- | |
21 |
|
21 | |||
22 | import copy |
|
22 | import copy | |
23 | import logging |
|
23 | import logging | |
24 | import os |
|
24 | import os | |
25 | import pipes |
|
25 | import pipes | |
26 | import stat |
|
26 | import stat | |
27 | import sys |
|
27 | import sys | |
28 | import time |
|
28 | import time | |
29 |
|
29 | |||
30 | # signal imports, handling various platforms, versions |
|
30 | # signal imports, handling various platforms, versions | |
31 |
|
31 | |||
32 | from signal import SIGINT, SIGTERM |
|
32 | from signal import SIGINT, SIGTERM | |
33 | try: |
|
33 | try: | |
34 | from signal import SIGKILL |
|
34 | from signal import SIGKILL | |
35 | except ImportError: |
|
35 | except ImportError: | |
36 | # Windows |
|
36 | # Windows | |
37 | SIGKILL=SIGTERM |
|
37 | SIGKILL=SIGTERM | |
38 |
|
38 | |||
39 | try: |
|
39 | try: | |
40 | # Windows >= 2.7, 3.2 |
|
40 | # Windows >= 2.7, 3.2 | |
41 | from signal import CTRL_C_EVENT as SIGINT |
|
41 | from signal import CTRL_C_EVENT as SIGINT | |
42 | except ImportError: |
|
42 | except ImportError: | |
43 | pass |
|
43 | pass | |
44 |
|
44 | |||
45 | from subprocess import Popen, PIPE, STDOUT |
|
45 | from subprocess import Popen, PIPE, STDOUT | |
46 | try: |
|
46 | try: | |
47 | from subprocess import check_output |
|
47 | from subprocess import check_output | |
48 | except ImportError: |
|
48 | except ImportError: | |
49 | # pre-2.7, define check_output with Popen |
|
49 | # pre-2.7, define check_output with Popen | |
50 | def check_output(*args, **kwargs): |
|
50 | def check_output(*args, **kwargs): | |
51 | kwargs.update(dict(stdout=PIPE)) |
|
51 | kwargs.update(dict(stdout=PIPE)) | |
52 | p = Popen(*args, **kwargs) |
|
52 | p = Popen(*args, **kwargs) | |
53 | out,err = p.communicate() |
|
53 | out,err = p.communicate() | |
54 | return out |
|
54 | return out | |
55 |
|
55 | |||
56 | from zmq.eventloop import ioloop |
|
56 | from zmq.eventloop import ioloop | |
57 |
|
57 | |||
58 | from IPython.config.application import Application |
|
58 | from IPython.config.application import Application | |
59 | from IPython.config.configurable import LoggingConfigurable |
|
59 | from IPython.config.configurable import LoggingConfigurable | |
60 | from IPython.utils.text import EvalFormatter |
|
60 | from IPython.utils.text import EvalFormatter | |
61 | from IPython.utils.traitlets import ( |
|
61 | from IPython.utils.traitlets import ( | |
62 | Any, Integer, CFloat, List, Unicode, Dict, Instance, HasTraits, CRegExp |
|
62 | Any, Integer, CFloat, List, Unicode, Dict, Instance, HasTraits, CRegExp | |
63 | ) |
|
63 | ) | |
64 | from IPython.utils.encoding import DEFAULT_ENCODING |
|
64 | from IPython.utils.encoding import DEFAULT_ENCODING | |
65 | from IPython.utils.path import get_home_dir |
|
65 | from IPython.utils.path import get_home_dir | |
66 | from IPython.utils.process import find_cmd, FindCmdError |
|
66 | from IPython.utils.process import find_cmd, FindCmdError | |
67 | from IPython.utils.py3compat import iteritems, itervalues |
|
67 | from IPython.utils.py3compat import iteritems, itervalues | |
68 |
|
68 | |||
69 | from .win32support import forward_read_events |
|
69 | from .win32support import forward_read_events | |
70 |
|
70 | |||
71 | from .winhpcjob import IPControllerTask, IPEngineTask, IPControllerJob, IPEngineSetJob |
|
71 | from .winhpcjob import IPControllerTask, IPEngineTask, IPControllerJob, IPEngineSetJob | |
72 |
|
72 | |||
73 | WINDOWS = os.name == 'nt' |
|
73 | WINDOWS = os.name == 'nt' | |
74 |
|
74 | |||
75 | #----------------------------------------------------------------------------- |
|
75 | #----------------------------------------------------------------------------- | |
76 | # Paths to the kernel apps |
|
76 | # Paths to the kernel apps | |
77 | #----------------------------------------------------------------------------- |
|
77 | #----------------------------------------------------------------------------- | |
78 |
|
78 | |||
79 | ipcluster_cmd_argv = [sys.executable, "-m", "IPython.parallel.cluster"] |
|
79 | ipcluster_cmd_argv = [sys.executable, "-m", "IPython.parallel.cluster"] | |
80 |
|
80 | |||
81 | ipengine_cmd_argv = [sys.executable, "-m", "IPython.parallel.engine"] |
|
81 | ipengine_cmd_argv = [sys.executable, "-m", "IPython.parallel.engine"] | |
82 |
|
82 | |||
83 | ipcontroller_cmd_argv = [sys.executable, "-m", "IPython.parallel.controller"] |
|
83 | ipcontroller_cmd_argv = [sys.executable, "-m", "IPython.parallel.controller"] | |
84 |
|
84 | |||
85 | if WINDOWS and sys.version_info < (3,): |
|
85 | if WINDOWS and sys.version_info < (3,): | |
86 | # `python -m package` doesn't work on Windows Python 2, |
|
86 | # `python -m package` doesn't work on Windows Python 2, | |
87 | # but `python -m module` does. |
|
87 | # but `python -m module` does. | |
88 | ipengine_cmd_argv = [sys.executable, "-m", "IPython.parallel.apps.ipengineapp"] |
|
88 | ipengine_cmd_argv = [sys.executable, "-m", "IPython.parallel.apps.ipengineapp"] | |
89 | ipcontroller_cmd_argv = [sys.executable, "-m", "IPython.parallel.apps.ipcontrollerapp"] |
|
89 | ipcontroller_cmd_argv = [sys.executable, "-m", "IPython.parallel.apps.ipcontrollerapp"] | |
90 |
|
90 | |||
91 | #----------------------------------------------------------------------------- |
|
91 | #----------------------------------------------------------------------------- | |
92 | # Base launchers and errors |
|
92 | # Base launchers and errors | |
93 | #----------------------------------------------------------------------------- |
|
93 | #----------------------------------------------------------------------------- | |
94 |
|
94 | |||
95 | class LauncherError(Exception): |
|
95 | class LauncherError(Exception): | |
96 | pass |
|
96 | pass | |
97 |
|
97 | |||
98 |
|
98 | |||
99 | class ProcessStateError(LauncherError): |
|
99 | class ProcessStateError(LauncherError): | |
100 | pass |
|
100 | pass | |
101 |
|
101 | |||
102 |
|
102 | |||
103 | class UnknownStatus(LauncherError): |
|
103 | class UnknownStatus(LauncherError): | |
104 | pass |
|
104 | pass | |
105 |
|
105 | |||
106 |
|
106 | |||
107 | class BaseLauncher(LoggingConfigurable): |
|
107 | class BaseLauncher(LoggingConfigurable): | |
108 | """An asbtraction for starting, stopping and signaling a process.""" |
|
108 | """An asbtraction for starting, stopping and signaling a process.""" | |
109 |
|
109 | |||
110 | # In all of the launchers, the work_dir is where child processes will be |
|
110 | # In all of the launchers, the work_dir is where child processes will be | |
111 | # run. This will usually be the profile_dir, but may not be. any work_dir |
|
111 | # run. This will usually be the profile_dir, but may not be. any work_dir | |
112 | # passed into the __init__ method will override the config value. |
|
112 | # passed into the __init__ method will override the config value. | |
113 | # This should not be used to set the work_dir for the actual engine |
|
113 | # This should not be used to set the work_dir for the actual engine | |
114 | # and controller. Instead, use their own config files or the |
|
114 | # and controller. Instead, use their own config files or the | |
115 | # controller_args, engine_args attributes of the launchers to add |
|
115 | # controller_args, engine_args attributes of the launchers to add | |
116 | # the work_dir option. |
|
116 | # the work_dir option. | |
117 | work_dir = Unicode(u'.') |
|
117 | work_dir = Unicode(u'.') | |
118 | loop = Instance('zmq.eventloop.ioloop.IOLoop') |
|
118 | loop = Instance('zmq.eventloop.ioloop.IOLoop') | |
119 |
|
119 | |||
120 | start_data = Any() |
|
120 | start_data = Any() | |
121 | stop_data = Any() |
|
121 | stop_data = Any() | |
122 |
|
122 | |||
123 | def _loop_default(self): |
|
123 | def _loop_default(self): | |
124 | return ioloop.IOLoop.instance() |
|
124 | return ioloop.IOLoop.instance() | |
125 |
|
125 | |||
126 | def __init__(self, work_dir=u'.', config=None, **kwargs): |
|
126 | def __init__(self, work_dir=u'.', config=None, **kwargs): | |
127 | super(BaseLauncher, self).__init__(work_dir=work_dir, config=config, **kwargs) |
|
127 | super(BaseLauncher, self).__init__(work_dir=work_dir, config=config, **kwargs) | |
128 | self.state = 'before' # can be before, running, after |
|
128 | self.state = 'before' # can be before, running, after | |
129 | self.stop_callbacks = [] |
|
129 | self.stop_callbacks = [] | |
130 | self.start_data = None |
|
130 | self.start_data = None | |
131 | self.stop_data = None |
|
131 | self.stop_data = None | |
132 |
|
132 | |||
133 | @property |
|
133 | @property | |
134 | def args(self): |
|
134 | def args(self): | |
135 | """A list of cmd and args that will be used to start the process. |
|
135 | """A list of cmd and args that will be used to start the process. | |
136 |
|
136 | |||
137 | This is what is passed to :func:`spawnProcess` and the first element |
|
137 | This is what is passed to :func:`spawnProcess` and the first element | |
138 | will be the process name. |
|
138 | will be the process name. | |
139 | """ |
|
139 | """ | |
140 | return self.find_args() |
|
140 | return self.find_args() | |
141 |
|
141 | |||
142 | def find_args(self): |
|
142 | def find_args(self): | |
143 | """The ``.args`` property calls this to find the args list. |
|
143 | """The ``.args`` property calls this to find the args list. | |
144 |
|
144 | |||
145 | Subcommand should implement this to construct the cmd and args. |
|
145 | Subcommand should implement this to construct the cmd and args. | |
146 | """ |
|
146 | """ | |
147 | raise NotImplementedError('find_args must be implemented in a subclass') |
|
147 | raise NotImplementedError('find_args must be implemented in a subclass') | |
148 |
|
148 | |||
149 | @property |
|
149 | @property | |
150 | def arg_str(self): |
|
150 | def arg_str(self): | |
151 | """The string form of the program arguments.""" |
|
151 | """The string form of the program arguments.""" | |
152 | return ' '.join(self.args) |
|
152 | return ' '.join(self.args) | |
153 |
|
153 | |||
154 | @property |
|
154 | @property | |
155 | def running(self): |
|
155 | def running(self): | |
156 | """Am I running.""" |
|
156 | """Am I running.""" | |
157 | if self.state == 'running': |
|
157 | if self.state == 'running': | |
158 | return True |
|
158 | return True | |
159 | else: |
|
159 | else: | |
160 | return False |
|
160 | return False | |
161 |
|
161 | |||
162 | def start(self): |
|
162 | def start(self): | |
163 | """Start the process.""" |
|
163 | """Start the process.""" | |
164 | raise NotImplementedError('start must be implemented in a subclass') |
|
164 | raise NotImplementedError('start must be implemented in a subclass') | |
165 |
|
165 | |||
166 | def stop(self): |
|
166 | def stop(self): | |
167 | """Stop the process and notify observers of stopping. |
|
167 | """Stop the process and notify observers of stopping. | |
168 |
|
168 | |||
169 | This method will return None immediately. |
|
169 | This method will return None immediately. | |
170 | To observe the actual process stopping, see :meth:`on_stop`. |
|
170 | To observe the actual process stopping, see :meth:`on_stop`. | |
171 | """ |
|
171 | """ | |
172 | raise NotImplementedError('stop must be implemented in a subclass') |
|
172 | raise NotImplementedError('stop must be implemented in a subclass') | |
173 |
|
173 | |||
174 | def on_stop(self, f): |
|
174 | def on_stop(self, f): | |
175 | """Register a callback to be called with this Launcher's stop_data |
|
175 | """Register a callback to be called with this Launcher's stop_data | |
176 | when the process actually finishes. |
|
176 | when the process actually finishes. | |
177 | """ |
|
177 | """ | |
178 | if self.state=='after': |
|
178 | if self.state=='after': | |
179 | return f(self.stop_data) |
|
179 | return f(self.stop_data) | |
180 | else: |
|
180 | else: | |
181 | self.stop_callbacks.append(f) |
|
181 | self.stop_callbacks.append(f) | |
182 |
|
182 | |||
183 | def notify_start(self, data): |
|
183 | def notify_start(self, data): | |
184 | """Call this to trigger startup actions. |
|
184 | """Call this to trigger startup actions. | |
185 |
|
185 | |||
186 | This logs the process startup and sets the state to 'running'. It is |
|
186 | This logs the process startup and sets the state to 'running'. It is | |
187 | a pass-through so it can be used as a callback. |
|
187 | a pass-through so it can be used as a callback. | |
188 | """ |
|
188 | """ | |
189 |
|
189 | |||
190 | self.log.debug('Process %r started: %r', self.args[0], data) |
|
190 | self.log.debug('Process %r started: %r', self.args[0], data) | |
191 | self.start_data = data |
|
191 | self.start_data = data | |
192 | self.state = 'running' |
|
192 | self.state = 'running' | |
193 | return data |
|
193 | return data | |
194 |
|
194 | |||
195 | def notify_stop(self, data): |
|
195 | def notify_stop(self, data): | |
196 | """Call this to trigger process stop actions. |
|
196 | """Call this to trigger process stop actions. | |
197 |
|
197 | |||
198 | This logs the process stopping and sets the state to 'after'. Call |
|
198 | This logs the process stopping and sets the state to 'after'. Call | |
199 | this to trigger callbacks registered via :meth:`on_stop`.""" |
|
199 | this to trigger callbacks registered via :meth:`on_stop`.""" | |
200 |
|
200 | |||
201 | self.log.debug('Process %r stopped: %r', self.args[0], data) |
|
201 | self.log.debug('Process %r stopped: %r', self.args[0], data) | |
202 | self.stop_data = data |
|
202 | self.stop_data = data | |
203 | self.state = 'after' |
|
203 | self.state = 'after' | |
204 | for i in range(len(self.stop_callbacks)): |
|
204 | for i in range(len(self.stop_callbacks)): | |
205 | d = self.stop_callbacks.pop() |
|
205 | d = self.stop_callbacks.pop() | |
206 | d(data) |
|
206 | d(data) | |
207 | return data |
|
207 | return data | |
208 |
|
208 | |||
209 | def signal(self, sig): |
|
209 | def signal(self, sig): | |
210 | """Signal the process. |
|
210 | """Signal the process. | |
211 |
|
211 | |||
212 | Parameters |
|
212 | Parameters | |
213 | ---------- |
|
213 | ---------- | |
214 | sig : str or int |
|
214 | sig : str or int | |
215 | 'KILL', 'INT', etc., or any signal number |
|
215 | 'KILL', 'INT', etc., or any signal number | |
216 | """ |
|
216 | """ | |
217 | raise NotImplementedError('signal must be implemented in a subclass') |
|
217 | raise NotImplementedError('signal must be implemented in a subclass') | |
218 |
|
218 | |||
219 | class ClusterAppMixin(HasTraits): |
|
219 | class ClusterAppMixin(HasTraits): | |
220 | """MixIn for cluster args as traits""" |
|
220 | """MixIn for cluster args as traits""" | |
221 | profile_dir=Unicode('') |
|
221 | profile_dir=Unicode('') | |
222 | cluster_id=Unicode('') |
|
222 | cluster_id=Unicode('') | |
223 |
|
223 | |||
224 | @property |
|
224 | @property | |
225 | def cluster_args(self): |
|
225 | def cluster_args(self): | |
226 | return ['--profile-dir', self.profile_dir, '--cluster-id', self.cluster_id] |
|
226 | return ['--profile-dir', self.profile_dir, '--cluster-id', self.cluster_id] | |
227 |
|
227 | |||
228 | class ControllerMixin(ClusterAppMixin): |
|
228 | class ControllerMixin(ClusterAppMixin): | |
229 | controller_cmd = List(ipcontroller_cmd_argv, config=True, |
|
229 | controller_cmd = List(ipcontroller_cmd_argv, config=True, | |
230 | help="""Popen command to launch ipcontroller.""") |
|
230 | help="""Popen command to launch ipcontroller.""") | |
231 | # Command line arguments to ipcontroller. |
|
231 | # Command line arguments to ipcontroller. | |
232 | controller_args = List(['--log-to-file','--log-level=%i' % logging.INFO], config=True, |
|
232 | controller_args = List(['--log-to-file','--log-level=%i' % logging.INFO], config=True, | |
233 | help="""command-line args to pass to ipcontroller""") |
|
233 | help="""command-line args to pass to ipcontroller""") | |
234 |
|
234 | |||
235 | class EngineMixin(ClusterAppMixin): |
|
235 | class EngineMixin(ClusterAppMixin): | |
236 | engine_cmd = List(ipengine_cmd_argv, config=True, |
|
236 | engine_cmd = List(ipengine_cmd_argv, config=True, | |
237 | help="""command to launch the Engine.""") |
|
237 | help="""command to launch the Engine.""") | |
238 | # Command line arguments for ipengine. |
|
238 | # Command line arguments for ipengine. | |
239 | engine_args = List(['--log-to-file','--log-level=%i' % logging.INFO], config=True, |
|
239 | engine_args = List(['--log-to-file','--log-level=%i' % logging.INFO], config=True, | |
240 | help="command-line arguments to pass to ipengine" |
|
240 | help="command-line arguments to pass to ipengine" | |
241 | ) |
|
241 | ) | |
242 |
|
242 | |||
243 |
|
243 | |||
244 | #----------------------------------------------------------------------------- |
|
244 | #----------------------------------------------------------------------------- | |
245 | # Local process launchers |
|
245 | # Local process launchers | |
246 | #----------------------------------------------------------------------------- |
|
246 | #----------------------------------------------------------------------------- | |
247 |
|
247 | |||
248 |
|
248 | |||
249 | class LocalProcessLauncher(BaseLauncher): |
|
249 | class LocalProcessLauncher(BaseLauncher): | |
250 | """Start and stop an external process in an asynchronous manner. |
|
250 | """Start and stop an external process in an asynchronous manner. | |
251 |
|
251 | |||
252 | This will launch the external process with a working directory of |
|
252 | This will launch the external process with a working directory of | |
253 | ``self.work_dir``. |
|
253 | ``self.work_dir``. | |
254 | """ |
|
254 | """ | |
255 |
|
255 | |||
256 | # This is used to to construct self.args, which is passed to |
|
256 | # This is used to to construct self.args, which is passed to | |
257 | # spawnProcess. |
|
257 | # spawnProcess. | |
258 | cmd_and_args = List([]) |
|
258 | cmd_and_args = List([]) | |
259 | poll_frequency = Integer(100) # in ms |
|
259 | poll_frequency = Integer(100) # in ms | |
260 |
|
260 | |||
261 | def __init__(self, work_dir=u'.', config=None, **kwargs): |
|
261 | def __init__(self, work_dir=u'.', config=None, **kwargs): | |
262 | super(LocalProcessLauncher, self).__init__( |
|
262 | super(LocalProcessLauncher, self).__init__( | |
263 | work_dir=work_dir, config=config, **kwargs |
|
263 | work_dir=work_dir, config=config, **kwargs | |
264 | ) |
|
264 | ) | |
265 | self.process = None |
|
265 | self.process = None | |
266 | self.poller = None |
|
266 | self.poller = None | |
267 |
|
267 | |||
268 | def find_args(self): |
|
268 | def find_args(self): | |
269 | return self.cmd_and_args |
|
269 | return self.cmd_and_args | |
270 |
|
270 | |||
271 | def start(self): |
|
271 | def start(self): | |
272 | self.log.debug("Starting %s: %r", self.__class__.__name__, self.args) |
|
272 | self.log.debug("Starting %s: %r", self.__class__.__name__, self.args) | |
273 | if self.state == 'before': |
|
273 | if self.state == 'before': | |
274 | self.process = Popen(self.args, |
|
274 | self.process = Popen(self.args, | |
275 | stdout=PIPE,stderr=PIPE,stdin=PIPE, |
|
275 | stdout=PIPE,stderr=PIPE,stdin=PIPE, | |
276 | env=os.environ, |
|
276 | env=os.environ, | |
277 | cwd=self.work_dir |
|
277 | cwd=self.work_dir | |
278 | ) |
|
278 | ) | |
279 | if WINDOWS: |
|
279 | if WINDOWS: | |
280 | self.stdout = forward_read_events(self.process.stdout) |
|
280 | self.stdout = forward_read_events(self.process.stdout) | |
281 | self.stderr = forward_read_events(self.process.stderr) |
|
281 | self.stderr = forward_read_events(self.process.stderr) | |
282 | else: |
|
282 | else: | |
283 | self.stdout = self.process.stdout.fileno() |
|
283 | self.stdout = self.process.stdout.fileno() | |
284 | self.stderr = self.process.stderr.fileno() |
|
284 | self.stderr = self.process.stderr.fileno() | |
285 | self.loop.add_handler(self.stdout, self.handle_stdout, self.loop.READ) |
|
285 | self.loop.add_handler(self.stdout, self.handle_stdout, self.loop.READ) | |
286 | self.loop.add_handler(self.stderr, self.handle_stderr, self.loop.READ) |
|
286 | self.loop.add_handler(self.stderr, self.handle_stderr, self.loop.READ) | |
287 | self.poller = ioloop.PeriodicCallback(self.poll, self.poll_frequency, self.loop) |
|
287 | self.poller = ioloop.PeriodicCallback(self.poll, self.poll_frequency, self.loop) | |
288 | self.poller.start() |
|
288 | self.poller.start() | |
289 | self.notify_start(self.process.pid) |
|
289 | self.notify_start(self.process.pid) | |
290 | else: |
|
290 | else: | |
291 | s = 'The process was already started and has state: %r' % self.state |
|
291 | s = 'The process was already started and has state: %r' % self.state | |
292 | raise ProcessStateError(s) |
|
292 | raise ProcessStateError(s) | |
293 |
|
293 | |||
294 | def stop(self): |
|
294 | def stop(self): | |
295 | return self.interrupt_then_kill() |
|
295 | return self.interrupt_then_kill() | |
296 |
|
296 | |||
297 | def signal(self, sig): |
|
297 | def signal(self, sig): | |
298 | if self.state == 'running': |
|
298 | if self.state == 'running': | |
299 | if WINDOWS and sig != SIGINT: |
|
299 | if WINDOWS and sig != SIGINT: | |
300 | # use Windows tree-kill for better child cleanup |
|
300 | # use Windows tree-kill for better child cleanup | |
301 | check_output(['taskkill', '-pid', str(self.process.pid), '-t', '-f']) |
|
301 | check_output(['taskkill', '-pid', str(self.process.pid), '-t', '-f']) | |
302 | else: |
|
302 | else: | |
303 | self.process.send_signal(sig) |
|
303 | self.process.send_signal(sig) | |
304 |
|
304 | |||
305 | def interrupt_then_kill(self, delay=2.0): |
|
305 | def interrupt_then_kill(self, delay=2.0): | |
306 | """Send INT, wait a delay and then send KILL.""" |
|
306 | """Send INT, wait a delay and then send KILL.""" | |
307 | try: |
|
307 | try: | |
308 | self.signal(SIGINT) |
|
308 | self.signal(SIGINT) | |
309 | except Exception: |
|
309 | except Exception: | |
310 | self.log.debug("interrupt failed") |
|
310 | self.log.debug("interrupt failed") | |
311 | pass |
|
311 | pass | |
312 | self.killer = ioloop.DelayedCallback(lambda : self.signal(SIGKILL), delay*1000, self.loop) |
|
312 | self.killer = ioloop.DelayedCallback(lambda : self.signal(SIGKILL), delay*1000, self.loop) | |
313 | self.killer.start() |
|
313 | self.killer.start() | |
314 |
|
314 | |||
315 | # callbacks, etc: |
|
315 | # callbacks, etc: | |
316 |
|
316 | |||
317 | def handle_stdout(self, fd, events): |
|
317 | def handle_stdout(self, fd, events): | |
318 | if WINDOWS: |
|
318 | if WINDOWS: | |
319 | line = self.stdout.recv() |
|
319 | line = self.stdout.recv() | |
320 | else: |
|
320 | else: | |
321 | line = self.process.stdout.readline() |
|
321 | line = self.process.stdout.readline() | |
322 | # a stopped process will be readable but return empty strings |
|
322 | # a stopped process will be readable but return empty strings | |
323 | if line: |
|
323 | if line: | |
324 | self.log.debug(line[:-1]) |
|
324 | self.log.debug(line[:-1]) | |
325 | else: |
|
325 | else: | |
326 | self.poll() |
|
326 | self.poll() | |
327 |
|
327 | |||
328 | def handle_stderr(self, fd, events): |
|
328 | def handle_stderr(self, fd, events): | |
329 | if WINDOWS: |
|
329 | if WINDOWS: | |
330 | line = self.stderr.recv() |
|
330 | line = self.stderr.recv() | |
331 | else: |
|
331 | else: | |
332 | line = self.process.stderr.readline() |
|
332 | line = self.process.stderr.readline() | |
333 | # a stopped process will be readable but return empty strings |
|
333 | # a stopped process will be readable but return empty strings | |
334 | if line: |
|
334 | if line: | |
335 | self.log.debug(line[:-1]) |
|
335 | self.log.debug(line[:-1]) | |
336 | else: |
|
336 | else: | |
337 | self.poll() |
|
337 | self.poll() | |
338 |
|
338 | |||
339 | def poll(self): |
|
339 | def poll(self): | |
340 | status = self.process.poll() |
|
340 | status = self.process.poll() | |
341 | if status is not None: |
|
341 | if status is not None: | |
342 | self.poller.stop() |
|
342 | self.poller.stop() | |
343 | self.loop.remove_handler(self.stdout) |
|
343 | self.loop.remove_handler(self.stdout) | |
344 | self.loop.remove_handler(self.stderr) |
|
344 | self.loop.remove_handler(self.stderr) | |
345 | self.notify_stop(dict(exit_code=status, pid=self.process.pid)) |
|
345 | self.notify_stop(dict(exit_code=status, pid=self.process.pid)) | |
346 | return status |
|
346 | return status | |
347 |
|
347 | |||
348 | class LocalControllerLauncher(LocalProcessLauncher, ControllerMixin): |
|
348 | class LocalControllerLauncher(LocalProcessLauncher, ControllerMixin): | |
349 | """Launch a controller as a regular external process.""" |
|
349 | """Launch a controller as a regular external process.""" | |
350 |
|
350 | |||
351 | def find_args(self): |
|
351 | def find_args(self): | |
352 | return self.controller_cmd + self.cluster_args + self.controller_args |
|
352 | return self.controller_cmd + self.cluster_args + self.controller_args | |
353 |
|
353 | |||
354 | def start(self): |
|
354 | def start(self): | |
355 | """Start the controller by profile_dir.""" |
|
355 | """Start the controller by profile_dir.""" | |
356 | return super(LocalControllerLauncher, self).start() |
|
356 | return super(LocalControllerLauncher, self).start() | |
357 |
|
357 | |||
358 |
|
358 | |||
359 | class LocalEngineLauncher(LocalProcessLauncher, EngineMixin): |
|
359 | class LocalEngineLauncher(LocalProcessLauncher, EngineMixin): | |
360 | """Launch a single engine as a regular externall process.""" |
|
360 | """Launch a single engine as a regular externall process.""" | |
361 |
|
361 | |||
362 | def find_args(self): |
|
362 | def find_args(self): | |
363 | return self.engine_cmd + self.cluster_args + self.engine_args |
|
363 | return self.engine_cmd + self.cluster_args + self.engine_args | |
364 |
|
364 | |||
365 |
|
365 | |||
366 | class LocalEngineSetLauncher(LocalEngineLauncher): |
|
366 | class LocalEngineSetLauncher(LocalEngineLauncher): | |
367 | """Launch a set of engines as regular external processes.""" |
|
367 | """Launch a set of engines as regular external processes.""" | |
368 |
|
368 | |||
369 | delay = CFloat(0.1, config=True, |
|
369 | delay = CFloat(0.1, config=True, | |
370 | help="""delay (in seconds) between starting each engine after the first. |
|
370 | help="""delay (in seconds) between starting each engine after the first. | |
371 | This can help force the engines to get their ids in order, or limit |
|
371 | This can help force the engines to get their ids in order, or limit | |
372 | process flood when starting many engines.""" |
|
372 | process flood when starting many engines.""" | |
373 | ) |
|
373 | ) | |
374 |
|
374 | |||
375 | # launcher class |
|
375 | # launcher class | |
376 | launcher_class = LocalEngineLauncher |
|
376 | launcher_class = LocalEngineLauncher | |
377 |
|
377 | |||
378 | launchers = Dict() |
|
378 | launchers = Dict() | |
379 | stop_data = Dict() |
|
379 | stop_data = Dict() | |
380 |
|
380 | |||
381 | def __init__(self, work_dir=u'.', config=None, **kwargs): |
|
381 | def __init__(self, work_dir=u'.', config=None, **kwargs): | |
382 | super(LocalEngineSetLauncher, self).__init__( |
|
382 | super(LocalEngineSetLauncher, self).__init__( | |
383 | work_dir=work_dir, config=config, **kwargs |
|
383 | work_dir=work_dir, config=config, **kwargs | |
384 | ) |
|
384 | ) | |
385 | self.stop_data = {} |
|
385 | self.stop_data = {} | |
386 |
|
386 | |||
387 | def start(self, n): |
|
387 | def start(self, n): | |
388 | """Start n engines by profile or profile_dir.""" |
|
388 | """Start n engines by profile or profile_dir.""" | |
389 | dlist = [] |
|
389 | dlist = [] | |
390 | for i in range(n): |
|
390 | for i in range(n): | |
391 | if i > 0: |
|
391 | if i > 0: | |
392 | time.sleep(self.delay) |
|
392 | time.sleep(self.delay) | |
393 | el = self.launcher_class(work_dir=self.work_dir, parent=self, log=self.log, |
|
393 | el = self.launcher_class(work_dir=self.work_dir, parent=self, log=self.log, | |
394 | profile_dir=self.profile_dir, cluster_id=self.cluster_id, |
|
394 | profile_dir=self.profile_dir, cluster_id=self.cluster_id, | |
395 | ) |
|
395 | ) | |
396 |
|
396 | |||
397 | # Copy the engine args over to each engine launcher. |
|
397 | # Copy the engine args over to each engine launcher. | |
398 | el.engine_cmd = copy.deepcopy(self.engine_cmd) |
|
398 | el.engine_cmd = copy.deepcopy(self.engine_cmd) | |
399 | el.engine_args = copy.deepcopy(self.engine_args) |
|
399 | el.engine_args = copy.deepcopy(self.engine_args) | |
400 | el.on_stop(self._notice_engine_stopped) |
|
400 | el.on_stop(self._notice_engine_stopped) | |
401 | d = el.start() |
|
401 | d = el.start() | |
402 | self.launchers[i] = el |
|
402 | self.launchers[i] = el | |
403 | dlist.append(d) |
|
403 | dlist.append(d) | |
404 | self.notify_start(dlist) |
|
404 | self.notify_start(dlist) | |
405 | return dlist |
|
405 | return dlist | |
406 |
|
406 | |||
407 | def find_args(self): |
|
407 | def find_args(self): | |
408 | return ['engine set'] |
|
408 | return ['engine set'] | |
409 |
|
409 | |||
410 | def signal(self, sig): |
|
410 | def signal(self, sig): | |
411 | dlist = [] |
|
411 | dlist = [] | |
412 | for el in itervalues(self.launchers): |
|
412 | for el in itervalues(self.launchers): | |
413 | d = el.signal(sig) |
|
413 | d = el.signal(sig) | |
414 | dlist.append(d) |
|
414 | dlist.append(d) | |
415 | return dlist |
|
415 | return dlist | |
416 |
|
416 | |||
417 | def interrupt_then_kill(self, delay=1.0): |
|
417 | def interrupt_then_kill(self, delay=1.0): | |
418 | dlist = [] |
|
418 | dlist = [] | |
419 | for el in itervalues(self.launchers): |
|
419 | for el in itervalues(self.launchers): | |
420 | d = el.interrupt_then_kill(delay) |
|
420 | d = el.interrupt_then_kill(delay) | |
421 | dlist.append(d) |
|
421 | dlist.append(d) | |
422 | return dlist |
|
422 | return dlist | |
423 |
|
423 | |||
424 | def stop(self): |
|
424 | def stop(self): | |
425 | return self.interrupt_then_kill() |
|
425 | return self.interrupt_then_kill() | |
426 |
|
426 | |||
427 | def _notice_engine_stopped(self, data): |
|
427 | def _notice_engine_stopped(self, data): | |
428 | pid = data['pid'] |
|
428 | pid = data['pid'] | |
429 | for idx,el in iteritems(self.launchers): |
|
429 | for idx,el in iteritems(self.launchers): | |
430 | if el.process.pid == pid: |
|
430 | if el.process.pid == pid: | |
431 | break |
|
431 | break | |
432 | self.launchers.pop(idx) |
|
432 | self.launchers.pop(idx) | |
433 | self.stop_data[idx] = data |
|
433 | self.stop_data[idx] = data | |
434 | if not self.launchers: |
|
434 | if not self.launchers: | |
435 | self.notify_stop(self.stop_data) |
|
435 | self.notify_stop(self.stop_data) | |
436 |
|
436 | |||
437 |
|
437 | |||
438 | #----------------------------------------------------------------------------- |
|
438 | #----------------------------------------------------------------------------- | |
439 | # MPI launchers |
|
439 | # MPI launchers | |
440 | #----------------------------------------------------------------------------- |
|
440 | #----------------------------------------------------------------------------- | |
441 |
|
441 | |||
442 |
|
442 | |||
443 | class MPILauncher(LocalProcessLauncher): |
|
443 | class MPILauncher(LocalProcessLauncher): | |
444 | """Launch an external process using mpiexec.""" |
|
444 | """Launch an external process using mpiexec.""" | |
445 |
|
445 | |||
446 | mpi_cmd = List(['mpiexec'], config=True, |
|
446 | mpi_cmd = List(['mpiexec'], config=True, | |
447 | help="The mpiexec command to use in starting the process." |
|
447 | help="The mpiexec command to use in starting the process." | |
448 | ) |
|
448 | ) | |
449 | mpi_args = List([], config=True, |
|
449 | mpi_args = List([], config=True, | |
450 | help="The command line arguments to pass to mpiexec." |
|
450 | help="The command line arguments to pass to mpiexec." | |
451 | ) |
|
451 | ) | |
452 | program = List(['date'], |
|
452 | program = List(['date'], | |
453 | help="The program to start via mpiexec.") |
|
453 | help="The program to start via mpiexec.") | |
454 | program_args = List([], |
|
454 | program_args = List([], | |
455 | help="The command line argument to the program." |
|
455 | help="The command line argument to the program." | |
456 | ) |
|
456 | ) | |
457 | n = Integer(1) |
|
457 | n = Integer(1) | |
458 |
|
458 | |||
459 | def __init__(self, *args, **kwargs): |
|
459 | def __init__(self, *args, **kwargs): | |
460 | # deprecation for old MPIExec names: |
|
460 | # deprecation for old MPIExec names: | |
461 | config = kwargs.get('config', {}) |
|
461 | config = kwargs.get('config', {}) | |
462 | for oldname in ('MPIExecLauncher', 'MPIExecControllerLauncher', 'MPIExecEngineSetLauncher'): |
|
462 | for oldname in ('MPIExecLauncher', 'MPIExecControllerLauncher', 'MPIExecEngineSetLauncher'): | |
463 | deprecated = config.get(oldname) |
|
463 | deprecated = config.get(oldname) | |
464 | if deprecated: |
|
464 | if deprecated: | |
465 | newname = oldname.replace('MPIExec', 'MPI') |
|
465 | newname = oldname.replace('MPIExec', 'MPI') | |
466 | config[newname].update(deprecated) |
|
466 | config[newname].update(deprecated) | |
467 | self.log.warn("WARNING: %s name has been deprecated, use %s", oldname, newname) |
|
467 | self.log.warn("WARNING: %s name has been deprecated, use %s", oldname, newname) | |
468 |
|
468 | |||
469 | super(MPILauncher, self).__init__(*args, **kwargs) |
|
469 | super(MPILauncher, self).__init__(*args, **kwargs) | |
470 |
|
470 | |||
471 | def find_args(self): |
|
471 | def find_args(self): | |
472 | """Build self.args using all the fields.""" |
|
472 | """Build self.args using all the fields.""" | |
473 | return self.mpi_cmd + ['-n', str(self.n)] + self.mpi_args + \ |
|
473 | return self.mpi_cmd + ['-n', str(self.n)] + self.mpi_args + \ | |
474 | self.program + self.program_args |
|
474 | self.program + self.program_args | |
475 |
|
475 | |||
476 | def start(self, n): |
|
476 | def start(self, n): | |
477 | """Start n instances of the program using mpiexec.""" |
|
477 | """Start n instances of the program using mpiexec.""" | |
478 | self.n = n |
|
478 | self.n = n | |
479 | return super(MPILauncher, self).start() |
|
479 | return super(MPILauncher, self).start() | |
480 |
|
480 | |||
481 |
|
481 | |||
482 | class MPIControllerLauncher(MPILauncher, ControllerMixin): |
|
482 | class MPIControllerLauncher(MPILauncher, ControllerMixin): | |
483 | """Launch a controller using mpiexec.""" |
|
483 | """Launch a controller using mpiexec.""" | |
484 |
|
484 | |||
485 | # alias back to *non-configurable* program[_args] for use in find_args() |
|
485 | # alias back to *non-configurable* program[_args] for use in find_args() | |
486 | # this way all Controller/EngineSetLaunchers have the same form, rather |
|
486 | # this way all Controller/EngineSetLaunchers have the same form, rather | |
487 | # than *some* having `program_args` and others `controller_args` |
|
487 | # than *some* having `program_args` and others `controller_args` | |
488 | @property |
|
488 | @property | |
489 | def program(self): |
|
489 | def program(self): | |
490 | return self.controller_cmd |
|
490 | return self.controller_cmd | |
491 |
|
491 | |||
492 | @property |
|
492 | @property | |
493 | def program_args(self): |
|
493 | def program_args(self): | |
494 | return self.cluster_args + self.controller_args |
|
494 | return self.cluster_args + self.controller_args | |
495 |
|
495 | |||
496 | def start(self): |
|
496 | def start(self): | |
497 | """Start the controller by profile_dir.""" |
|
497 | """Start the controller by profile_dir.""" | |
498 | return super(MPIControllerLauncher, self).start(1) |
|
498 | return super(MPIControllerLauncher, self).start(1) | |
499 |
|
499 | |||
500 |
|
500 | |||
501 | class MPIEngineSetLauncher(MPILauncher, EngineMixin): |
|
501 | class MPIEngineSetLauncher(MPILauncher, EngineMixin): | |
502 | """Launch engines using mpiexec""" |
|
502 | """Launch engines using mpiexec""" | |
503 |
|
503 | |||
504 | # alias back to *non-configurable* program[_args] for use in find_args() |
|
504 | # alias back to *non-configurable* program[_args] for use in find_args() | |
505 | # this way all Controller/EngineSetLaunchers have the same form, rather |
|
505 | # this way all Controller/EngineSetLaunchers have the same form, rather | |
506 | # than *some* having `program_args` and others `controller_args` |
|
506 | # than *some* having `program_args` and others `controller_args` | |
507 | @property |
|
507 | @property | |
508 | def program(self): |
|
508 | def program(self): | |
509 | return self.engine_cmd |
|
509 | return self.engine_cmd | |
510 |
|
510 | |||
511 | @property |
|
511 | @property | |
512 | def program_args(self): |
|
512 | def program_args(self): | |
513 | return self.cluster_args + self.engine_args |
|
513 | return self.cluster_args + self.engine_args | |
514 |
|
514 | |||
515 | def start(self, n): |
|
515 | def start(self, n): | |
516 | """Start n engines by profile or profile_dir.""" |
|
516 | """Start n engines by profile or profile_dir.""" | |
517 | self.n = n |
|
517 | self.n = n | |
518 | return super(MPIEngineSetLauncher, self).start(n) |
|
518 | return super(MPIEngineSetLauncher, self).start(n) | |
519 |
|
519 | |||
520 | # deprecated MPIExec names |
|
520 | # deprecated MPIExec names | |
521 | class DeprecatedMPILauncher(object): |
|
521 | class DeprecatedMPILauncher(object): | |
522 | def warn(self): |
|
522 | def warn(self): | |
523 | oldname = self.__class__.__name__ |
|
523 | oldname = self.__class__.__name__ | |
524 | newname = oldname.replace('MPIExec', 'MPI') |
|
524 | newname = oldname.replace('MPIExec', 'MPI') | |
525 | self.log.warn("WARNING: %s name is deprecated, use %s", oldname, newname) |
|
525 | self.log.warn("WARNING: %s name is deprecated, use %s", oldname, newname) | |
526 |
|
526 | |||
527 | class MPIExecLauncher(MPILauncher, DeprecatedMPILauncher): |
|
527 | class MPIExecLauncher(MPILauncher, DeprecatedMPILauncher): | |
528 | """Deprecated, use MPILauncher""" |
|
528 | """Deprecated, use MPILauncher""" | |
529 | def __init__(self, *args, **kwargs): |
|
529 | def __init__(self, *args, **kwargs): | |
530 | super(MPIExecLauncher, self).__init__(*args, **kwargs) |
|
530 | super(MPIExecLauncher, self).__init__(*args, **kwargs) | |
531 | self.warn() |
|
531 | self.warn() | |
532 |
|
532 | |||
533 | class MPIExecControllerLauncher(MPIControllerLauncher, DeprecatedMPILauncher): |
|
533 | class MPIExecControllerLauncher(MPIControllerLauncher, DeprecatedMPILauncher): | |
534 | """Deprecated, use MPIControllerLauncher""" |
|
534 | """Deprecated, use MPIControllerLauncher""" | |
535 | def __init__(self, *args, **kwargs): |
|
535 | def __init__(self, *args, **kwargs): | |
536 | super(MPIExecControllerLauncher, self).__init__(*args, **kwargs) |
|
536 | super(MPIExecControllerLauncher, self).__init__(*args, **kwargs) | |
537 | self.warn() |
|
537 | self.warn() | |
538 |
|
538 | |||
539 | class MPIExecEngineSetLauncher(MPIEngineSetLauncher, DeprecatedMPILauncher): |
|
539 | class MPIExecEngineSetLauncher(MPIEngineSetLauncher, DeprecatedMPILauncher): | |
540 | """Deprecated, use MPIEngineSetLauncher""" |
|
540 | """Deprecated, use MPIEngineSetLauncher""" | |
541 | def __init__(self, *args, **kwargs): |
|
541 | def __init__(self, *args, **kwargs): | |
542 | super(MPIExecEngineSetLauncher, self).__init__(*args, **kwargs) |
|
542 | super(MPIExecEngineSetLauncher, self).__init__(*args, **kwargs) | |
543 | self.warn() |
|
543 | self.warn() | |
544 |
|
544 | |||
545 |
|
545 | |||
546 | #----------------------------------------------------------------------------- |
|
546 | #----------------------------------------------------------------------------- | |
547 | # SSH launchers |
|
547 | # SSH launchers | |
548 | #----------------------------------------------------------------------------- |
|
548 | #----------------------------------------------------------------------------- | |
549 |
|
549 | |||
550 | # TODO: Get SSH Launcher back to level of sshx in 0.10.2 |
|
550 | # TODO: Get SSH Launcher back to level of sshx in 0.10.2 | |
551 |
|
551 | |||
552 | class SSHLauncher(LocalProcessLauncher): |
|
552 | class SSHLauncher(LocalProcessLauncher): | |
553 | """A minimal launcher for ssh. |
|
553 | """A minimal launcher for ssh. | |
554 |
|
554 | |||
555 | To be useful this will probably have to be extended to use the ``sshx`` |
|
555 | To be useful this will probably have to be extended to use the ``sshx`` | |
556 | idea for environment variables. There could be other things this needs |
|
556 | idea for environment variables. There could be other things this needs | |
557 | as well. |
|
557 | as well. | |
558 | """ |
|
558 | """ | |
559 |
|
559 | |||
560 | ssh_cmd = List(['ssh'], config=True, |
|
560 | ssh_cmd = List(['ssh'], config=True, | |
561 | help="command for starting ssh") |
|
561 | help="command for starting ssh") | |
562 | ssh_args = List(['-tt'], config=True, |
|
562 | ssh_args = List(['-tt'], config=True, | |
563 | help="args to pass to ssh") |
|
563 | help="args to pass to ssh") | |
564 | scp_cmd = List(['scp'], config=True, |
|
564 | scp_cmd = List(['scp'], config=True, | |
565 | help="command for sending files") |
|
565 | help="command for sending files") | |
566 | program = List(['date'], |
|
566 | program = List(['date'], | |
567 | help="Program to launch via ssh") |
|
567 | help="Program to launch via ssh") | |
568 | program_args = List([], |
|
568 | program_args = List([], | |
569 | help="args to pass to remote program") |
|
569 | help="args to pass to remote program") | |
570 | hostname = Unicode('', config=True, |
|
570 | hostname = Unicode('', config=True, | |
571 | help="hostname on which to launch the program") |
|
571 | help="hostname on which to launch the program") | |
572 | user = Unicode('', config=True, |
|
572 | user = Unicode('', config=True, | |
573 | help="username for ssh") |
|
573 | help="username for ssh") | |
574 | location = Unicode('', config=True, |
|
574 | location = Unicode('', config=True, | |
575 | help="user@hostname location for ssh in one setting") |
|
575 | help="user@hostname location for ssh in one setting") | |
576 | to_fetch = List([], config=True, |
|
576 | to_fetch = List([], config=True, | |
577 | help="List of (remote, local) files to fetch after starting") |
|
577 | help="List of (remote, local) files to fetch after starting") | |
578 | to_send = List([], config=True, |
|
578 | to_send = List([], config=True, | |
579 | help="List of (local, remote) files to send before starting") |
|
579 | help="List of (local, remote) files to send before starting") | |
580 |
|
580 | |||
581 | def _hostname_changed(self, name, old, new): |
|
581 | def _hostname_changed(self, name, old, new): | |
582 | if self.user: |
|
582 | if self.user: | |
583 | self.location = u'%s@%s' % (self.user, new) |
|
583 | self.location = u'%s@%s' % (self.user, new) | |
584 | else: |
|
584 | else: | |
585 | self.location = new |
|
585 | self.location = new | |
586 |
|
586 | |||
587 | def _user_changed(self, name, old, new): |
|
587 | def _user_changed(self, name, old, new): | |
588 | self.location = u'%s@%s' % (new, self.hostname) |
|
588 | self.location = u'%s@%s' % (new, self.hostname) | |
589 |
|
589 | |||
590 | def find_args(self): |
|
590 | def find_args(self): | |
591 | return self.ssh_cmd + self.ssh_args + [self.location] + \ |
|
591 | return self.ssh_cmd + self.ssh_args + [self.location] + \ | |
592 | list(map(pipes.quote, self.program + self.program_args)) |
|
592 | list(map(pipes.quote, self.program + self.program_args)) | |
593 |
|
593 | |||
594 | def _send_file(self, local, remote): |
|
594 | def _send_file(self, local, remote): | |
595 | """send a single file""" |
|
595 | """send a single file""" | |
596 | remote = "%s:%s" % (self.location, remote) |
|
596 | full_remote = "%s:%s" % (self.location, remote) | |
597 | for i in range(10): |
|
597 | for i in range(10): | |
598 | if not os.path.exists(local): |
|
598 | if not os.path.exists(local): | |
599 | self.log.debug("waiting for %s" % local) |
|
599 | self.log.debug("waiting for %s" % local) | |
600 | time.sleep(1) |
|
600 | time.sleep(1) | |
601 | else: |
|
601 | else: | |
602 | break |
|
602 | break | |
603 | remote_dir = os.path.dirname(remote) |
|
603 | remote_dir = os.path.dirname(remote) | |
604 | self.log.info("ensuring remote %s:%s/ exists", self.location, remote_dir) |
|
604 | self.log.info("ensuring remote %s:%s/ exists", self.location, remote_dir) | |
605 | check_output(self.ssh_cmd + self.ssh_args + \ |
|
605 | check_output(self.ssh_cmd + self.ssh_args + \ | |
606 | [self.location, 'mkdir', '-p', '--', remote_dir] |
|
606 | [self.location, 'mkdir', '-p', '--', remote_dir] | |
607 | ) |
|
607 | ) | |
608 | self.log.info("sending %s to %s", local, remote) |
|
608 | self.log.info("sending %s to %s", local, full_remote) | |
609 | check_output(self.scp_cmd + [local, remote]) |
|
609 | check_output(self.scp_cmd + [local, full_remote]) | |
610 |
|
610 | |||
611 | def send_files(self): |
|
611 | def send_files(self): | |
612 | """send our files (called before start)""" |
|
612 | """send our files (called before start)""" | |
613 | if not self.to_send: |
|
613 | if not self.to_send: | |
614 | return |
|
614 | return | |
615 | for local_file, remote_file in self.to_send: |
|
615 | for local_file, remote_file in self.to_send: | |
616 | self._send_file(local_file, remote_file) |
|
616 | self._send_file(local_file, remote_file) | |
617 |
|
617 | |||
618 | def _fetch_file(self, remote, local): |
|
618 | def _fetch_file(self, remote, local): | |
619 | """fetch a single file""" |
|
619 | """fetch a single file""" | |
620 | full_remote = "%s:%s" % (self.location, remote) |
|
620 | full_remote = "%s:%s" % (self.location, remote) | |
621 | self.log.info("fetching %s from %s", local, full_remote) |
|
621 | self.log.info("fetching %s from %s", local, full_remote) | |
622 | for i in range(10): |
|
622 | for i in range(10): | |
623 | # wait up to 10s for remote file to exist |
|
623 | # wait up to 10s for remote file to exist | |
624 | check = check_output(self.ssh_cmd + self.ssh_args + \ |
|
624 | check = check_output(self.ssh_cmd + self.ssh_args + \ | |
625 | [self.location, 'test -e', remote, "&& echo 'yes' || echo 'no'"]) |
|
625 | [self.location, 'test -e', remote, "&& echo 'yes' || echo 'no'"]) | |
626 | check = check.decode(DEFAULT_ENCODING, 'replace').strip() |
|
626 | check = check.decode(DEFAULT_ENCODING, 'replace').strip() | |
627 | if check == u'no': |
|
627 | if check == u'no': | |
628 | time.sleep(1) |
|
628 | time.sleep(1) | |
629 | elif check == u'yes': |
|
629 | elif check == u'yes': | |
630 | break |
|
630 | break | |
631 | local_dir = os.path.dirname(local) |
|
631 | local_dir = os.path.dirname(local) | |
632 | if not os.path.exists(local_dir): |
|
632 | if not os.path.exists(local_dir): | |
633 | os.makedirs(local_dir, 775) |
|
633 | os.makedirs(local_dir, 775) | |
634 | check_output(self.scp_cmd + [full_remote, local]) |
|
634 | check_output(self.scp_cmd + [full_remote, local]) | |
635 |
|
635 | |||
636 | def fetch_files(self): |
|
636 | def fetch_files(self): | |
637 | """fetch remote files (called after start)""" |
|
637 | """fetch remote files (called after start)""" | |
638 | if not self.to_fetch: |
|
638 | if not self.to_fetch: | |
639 | return |
|
639 | return | |
640 | for remote_file, local_file in self.to_fetch: |
|
640 | for remote_file, local_file in self.to_fetch: | |
641 | self._fetch_file(remote_file, local_file) |
|
641 | self._fetch_file(remote_file, local_file) | |
642 |
|
642 | |||
643 | def start(self, hostname=None, user=None): |
|
643 | def start(self, hostname=None, user=None): | |
644 | if hostname is not None: |
|
644 | if hostname is not None: | |
645 | self.hostname = hostname |
|
645 | self.hostname = hostname | |
646 | if user is not None: |
|
646 | if user is not None: | |
647 | self.user = user |
|
647 | self.user = user | |
648 |
|
648 | |||
649 | self.send_files() |
|
649 | self.send_files() | |
650 | super(SSHLauncher, self).start() |
|
650 | super(SSHLauncher, self).start() | |
651 | self.fetch_files() |
|
651 | self.fetch_files() | |
652 |
|
652 | |||
653 | def signal(self, sig): |
|
653 | def signal(self, sig): | |
654 | if self.state == 'running': |
|
654 | if self.state == 'running': | |
655 | # send escaped ssh connection-closer |
|
655 | # send escaped ssh connection-closer | |
656 | self.process.stdin.write('~.') |
|
656 | self.process.stdin.write('~.') | |
657 | self.process.stdin.flush() |
|
657 | self.process.stdin.flush() | |
658 |
|
658 | |||
659 | class SSHClusterLauncher(SSHLauncher, ClusterAppMixin): |
|
659 | class SSHClusterLauncher(SSHLauncher, ClusterAppMixin): | |
660 |
|
660 | |||
661 | remote_profile_dir = Unicode('', config=True, |
|
661 | remote_profile_dir = Unicode('', config=True, | |
662 | help="""The remote profile_dir to use. |
|
662 | help="""The remote profile_dir to use. | |
663 |
|
663 | |||
664 | If not specified, use calling profile, stripping out possible leading homedir. |
|
664 | If not specified, use calling profile, stripping out possible leading homedir. | |
665 | """) |
|
665 | """) | |
666 |
|
666 | |||
667 | def _profile_dir_changed(self, name, old, new): |
|
667 | def _profile_dir_changed(self, name, old, new): | |
668 | if not self.remote_profile_dir: |
|
668 | if not self.remote_profile_dir: | |
669 | # trigger remote_profile_dir_default logic again, |
|
669 | # trigger remote_profile_dir_default logic again, | |
670 | # in case it was already triggered before profile_dir was set |
|
670 | # in case it was already triggered before profile_dir was set | |
671 | self.remote_profile_dir = self._strip_home(new) |
|
671 | self.remote_profile_dir = self._strip_home(new) | |
672 |
|
672 | |||
673 | @staticmethod |
|
673 | @staticmethod | |
674 | def _strip_home(path): |
|
674 | def _strip_home(path): | |
675 | """turns /home/you/.ipython/profile_foo into .ipython/profile_foo""" |
|
675 | """turns /home/you/.ipython/profile_foo into .ipython/profile_foo""" | |
676 | home = get_home_dir() |
|
676 | home = get_home_dir() | |
677 | if not home.endswith('/'): |
|
677 | if not home.endswith('/'): | |
678 | home = home+'/' |
|
678 | home = home+'/' | |
679 |
|
679 | |||
680 | if path.startswith(home): |
|
680 | if path.startswith(home): | |
681 | return path[len(home):] |
|
681 | return path[len(home):] | |
682 | else: |
|
682 | else: | |
683 | return path |
|
683 | return path | |
684 |
|
684 | |||
685 | def _remote_profile_dir_default(self): |
|
685 | def _remote_profile_dir_default(self): | |
686 | return self._strip_home(self.profile_dir) |
|
686 | return self._strip_home(self.profile_dir) | |
687 |
|
687 | |||
688 | def _cluster_id_changed(self, name, old, new): |
|
688 | def _cluster_id_changed(self, name, old, new): | |
689 | if new: |
|
689 | if new: | |
690 | raise ValueError("cluster id not supported by SSH launchers") |
|
690 | raise ValueError("cluster id not supported by SSH launchers") | |
691 |
|
691 | |||
692 | @property |
|
692 | @property | |
693 | def cluster_args(self): |
|
693 | def cluster_args(self): | |
694 | return ['--profile-dir', self.remote_profile_dir] |
|
694 | return ['--profile-dir', self.remote_profile_dir] | |
695 |
|
695 | |||
696 | class SSHControllerLauncher(SSHClusterLauncher, ControllerMixin): |
|
696 | class SSHControllerLauncher(SSHClusterLauncher, ControllerMixin): | |
697 |
|
697 | |||
698 | # alias back to *non-configurable* program[_args] for use in find_args() |
|
698 | # alias back to *non-configurable* program[_args] for use in find_args() | |
699 | # this way all Controller/EngineSetLaunchers have the same form, rather |
|
699 | # this way all Controller/EngineSetLaunchers have the same form, rather | |
700 | # than *some* having `program_args` and others `controller_args` |
|
700 | # than *some* having `program_args` and others `controller_args` | |
701 |
|
701 | |||
702 | def _controller_cmd_default(self): |
|
702 | def _controller_cmd_default(self): | |
703 | return ['ipcontroller'] |
|
703 | return ['ipcontroller'] | |
704 |
|
704 | |||
705 | @property |
|
705 | @property | |
706 | def program(self): |
|
706 | def program(self): | |
707 | return self.controller_cmd |
|
707 | return self.controller_cmd | |
708 |
|
708 | |||
709 | @property |
|
709 | @property | |
710 | def program_args(self): |
|
710 | def program_args(self): | |
711 | return self.cluster_args + self.controller_args |
|
711 | return self.cluster_args + self.controller_args | |
712 |
|
712 | |||
713 | def _to_fetch_default(self): |
|
713 | def _to_fetch_default(self): | |
714 | return [ |
|
714 | return [ | |
715 | (os.path.join(self.remote_profile_dir, 'security', cf), |
|
715 | (os.path.join(self.remote_profile_dir, 'security', cf), | |
716 | os.path.join(self.profile_dir, 'security', cf),) |
|
716 | os.path.join(self.profile_dir, 'security', cf),) | |
717 | for cf in ('ipcontroller-client.json', 'ipcontroller-engine.json') |
|
717 | for cf in ('ipcontroller-client.json', 'ipcontroller-engine.json') | |
718 | ] |
|
718 | ] | |
719 |
|
719 | |||
720 | class SSHEngineLauncher(SSHClusterLauncher, EngineMixin): |
|
720 | class SSHEngineLauncher(SSHClusterLauncher, EngineMixin): | |
721 |
|
721 | |||
722 | # alias back to *non-configurable* program[_args] for use in find_args() |
|
722 | # alias back to *non-configurable* program[_args] for use in find_args() | |
723 | # this way all Controller/EngineSetLaunchers have the same form, rather |
|
723 | # this way all Controller/EngineSetLaunchers have the same form, rather | |
724 | # than *some* having `program_args` and others `controller_args` |
|
724 | # than *some* having `program_args` and others `controller_args` | |
725 |
|
725 | |||
726 | def _engine_cmd_default(self): |
|
726 | def _engine_cmd_default(self): | |
727 | return ['ipengine'] |
|
727 | return ['ipengine'] | |
728 |
|
728 | |||
729 | @property |
|
729 | @property | |
730 | def program(self): |
|
730 | def program(self): | |
731 | return self.engine_cmd |
|
731 | return self.engine_cmd | |
732 |
|
732 | |||
733 | @property |
|
733 | @property | |
734 | def program_args(self): |
|
734 | def program_args(self): | |
735 | return self.cluster_args + self.engine_args |
|
735 | return self.cluster_args + self.engine_args | |
736 |
|
736 | |||
737 | def _to_send_default(self): |
|
737 | def _to_send_default(self): | |
738 | return [ |
|
738 | return [ | |
739 | (os.path.join(self.profile_dir, 'security', cf), |
|
739 | (os.path.join(self.profile_dir, 'security', cf), | |
740 | os.path.join(self.remote_profile_dir, 'security', cf)) |
|
740 | os.path.join(self.remote_profile_dir, 'security', cf)) | |
741 | for cf in ('ipcontroller-client.json', 'ipcontroller-engine.json') |
|
741 | for cf in ('ipcontroller-client.json', 'ipcontroller-engine.json') | |
742 | ] |
|
742 | ] | |
743 |
|
743 | |||
744 |
|
744 | |||
745 | class SSHEngineSetLauncher(LocalEngineSetLauncher): |
|
745 | class SSHEngineSetLauncher(LocalEngineSetLauncher): | |
746 | launcher_class = SSHEngineLauncher |
|
746 | launcher_class = SSHEngineLauncher | |
747 | engines = Dict(config=True, |
|
747 | engines = Dict(config=True, | |
748 | help="""dict of engines to launch. This is a dict by hostname of ints, |
|
748 | help="""dict of engines to launch. This is a dict by hostname of ints, | |
749 | corresponding to the number of engines to start on that host.""") |
|
749 | corresponding to the number of engines to start on that host.""") | |
750 |
|
750 | |||
751 | def _engine_cmd_default(self): |
|
751 | def _engine_cmd_default(self): | |
752 | return ['ipengine'] |
|
752 | return ['ipengine'] | |
753 |
|
753 | |||
754 | @property |
|
754 | @property | |
755 | def engine_count(self): |
|
755 | def engine_count(self): | |
756 | """determine engine count from `engines` dict""" |
|
756 | """determine engine count from `engines` dict""" | |
757 | count = 0 |
|
757 | count = 0 | |
758 | for n in itervalues(self.engines): |
|
758 | for n in itervalues(self.engines): | |
759 | if isinstance(n, (tuple,list)): |
|
759 | if isinstance(n, (tuple,list)): | |
760 | n,args = n |
|
760 | n,args = n | |
761 | count += n |
|
761 | count += n | |
762 | return count |
|
762 | return count | |
763 |
|
763 | |||
764 | def start(self, n): |
|
764 | def start(self, n): | |
765 | """Start engines by profile or profile_dir. |
|
765 | """Start engines by profile or profile_dir. | |
766 | `n` is ignored, and the `engines` config property is used instead. |
|
766 | `n` is ignored, and the `engines` config property is used instead. | |
767 | """ |
|
767 | """ | |
768 |
|
768 | |||
769 | dlist = [] |
|
769 | dlist = [] | |
770 | for host, n in iteritems(self.engines): |
|
770 | for host, n in iteritems(self.engines): | |
771 | if isinstance(n, (tuple, list)): |
|
771 | if isinstance(n, (tuple, list)): | |
772 | n, args = n |
|
772 | n, args = n | |
773 | else: |
|
773 | else: | |
774 | args = copy.deepcopy(self.engine_args) |
|
774 | args = copy.deepcopy(self.engine_args) | |
775 |
|
775 | |||
776 | if '@' in host: |
|
776 | if '@' in host: | |
777 | user,host = host.split('@',1) |
|
777 | user,host = host.split('@',1) | |
778 | else: |
|
778 | else: | |
779 | user=None |
|
779 | user=None | |
780 | for i in range(n): |
|
780 | for i in range(n): | |
781 | if i > 0: |
|
781 | if i > 0: | |
782 | time.sleep(self.delay) |
|
782 | time.sleep(self.delay) | |
783 | el = self.launcher_class(work_dir=self.work_dir, parent=self, log=self.log, |
|
783 | el = self.launcher_class(work_dir=self.work_dir, parent=self, log=self.log, | |
784 | profile_dir=self.profile_dir, cluster_id=self.cluster_id, |
|
784 | profile_dir=self.profile_dir, cluster_id=self.cluster_id, | |
785 | ) |
|
785 | ) | |
786 | if i > 0: |
|
786 | if i > 0: | |
787 | # only send files for the first engine on each host |
|
787 | # only send files for the first engine on each host | |
788 | el.to_send = [] |
|
788 | el.to_send = [] | |
789 |
|
789 | |||
790 | # Copy the engine args over to each engine launcher. |
|
790 | # Copy the engine args over to each engine launcher. | |
791 | el.engine_cmd = self.engine_cmd |
|
791 | el.engine_cmd = self.engine_cmd | |
792 | el.engine_args = args |
|
792 | el.engine_args = args | |
793 | el.on_stop(self._notice_engine_stopped) |
|
793 | el.on_stop(self._notice_engine_stopped) | |
794 | d = el.start(user=user, hostname=host) |
|
794 | d = el.start(user=user, hostname=host) | |
795 | self.launchers[ "%s/%i" % (host,i) ] = el |
|
795 | self.launchers[ "%s/%i" % (host,i) ] = el | |
796 | dlist.append(d) |
|
796 | dlist.append(d) | |
797 | self.notify_start(dlist) |
|
797 | self.notify_start(dlist) | |
798 | return dlist |
|
798 | return dlist | |
799 |
|
799 | |||
800 |
|
800 | |||
801 | class SSHProxyEngineSetLauncher(SSHClusterLauncher): |
|
801 | class SSHProxyEngineSetLauncher(SSHClusterLauncher): | |
802 | """Launcher for calling |
|
802 | """Launcher for calling | |
803 | `ipcluster engines` on a remote machine. |
|
803 | `ipcluster engines` on a remote machine. | |
804 |
|
804 | |||
805 | Requires that remote profile is already configured. |
|
805 | Requires that remote profile is already configured. | |
806 | """ |
|
806 | """ | |
807 |
|
807 | |||
808 | n = Integer() |
|
808 | n = Integer() | |
809 | ipcluster_cmd = List(['ipcluster'], config=True) |
|
809 | ipcluster_cmd = List(['ipcluster'], config=True) | |
810 |
|
810 | |||
811 | @property |
|
811 | @property | |
812 | def program(self): |
|
812 | def program(self): | |
813 | return self.ipcluster_cmd + ['engines'] |
|
813 | return self.ipcluster_cmd + ['engines'] | |
814 |
|
814 | |||
815 | @property |
|
815 | @property | |
816 | def program_args(self): |
|
816 | def program_args(self): | |
817 | return ['-n', str(self.n), '--profile-dir', self.remote_profile_dir] |
|
817 | return ['-n', str(self.n), '--profile-dir', self.remote_profile_dir] | |
818 |
|
818 | |||
819 | def _to_send_default(self): |
|
819 | def _to_send_default(self): | |
820 | return [ |
|
820 | return [ | |
821 | (os.path.join(self.profile_dir, 'security', cf), |
|
821 | (os.path.join(self.profile_dir, 'security', cf), | |
822 | os.path.join(self.remote_profile_dir, 'security', cf)) |
|
822 | os.path.join(self.remote_profile_dir, 'security', cf)) | |
823 | for cf in ('ipcontroller-client.json', 'ipcontroller-engine.json') |
|
823 | for cf in ('ipcontroller-client.json', 'ipcontroller-engine.json') | |
824 | ] |
|
824 | ] | |
825 |
|
825 | |||
826 | def start(self, n): |
|
826 | def start(self, n): | |
827 | self.n = n |
|
827 | self.n = n | |
828 | super(SSHProxyEngineSetLauncher, self).start() |
|
828 | super(SSHProxyEngineSetLauncher, self).start() | |
829 |
|
829 | |||
830 |
|
830 | |||
831 | #----------------------------------------------------------------------------- |
|
831 | #----------------------------------------------------------------------------- | |
832 | # Windows HPC Server 2008 scheduler launchers |
|
832 | # Windows HPC Server 2008 scheduler launchers | |
833 | #----------------------------------------------------------------------------- |
|
833 | #----------------------------------------------------------------------------- | |
834 |
|
834 | |||
835 |
|
835 | |||
836 | # This is only used on Windows. |
|
836 | # This is only used on Windows. | |
837 | def find_job_cmd(): |
|
837 | def find_job_cmd(): | |
838 | if WINDOWS: |
|
838 | if WINDOWS: | |
839 | try: |
|
839 | try: | |
840 | return find_cmd('job') |
|
840 | return find_cmd('job') | |
841 | except (FindCmdError, ImportError): |
|
841 | except (FindCmdError, ImportError): | |
842 | # ImportError will be raised if win32api is not installed |
|
842 | # ImportError will be raised if win32api is not installed | |
843 | return 'job' |
|
843 | return 'job' | |
844 | else: |
|
844 | else: | |
845 | return 'job' |
|
845 | return 'job' | |
846 |
|
846 | |||
847 |
|
847 | |||
848 | class WindowsHPCLauncher(BaseLauncher): |
|
848 | class WindowsHPCLauncher(BaseLauncher): | |
849 |
|
849 | |||
850 | job_id_regexp = CRegExp(r'\d+', config=True, |
|
850 | job_id_regexp = CRegExp(r'\d+', config=True, | |
851 | help="""A regular expression used to get the job id from the output of the |
|
851 | help="""A regular expression used to get the job id from the output of the | |
852 | submit_command. """ |
|
852 | submit_command. """ | |
853 | ) |
|
853 | ) | |
854 | job_file_name = Unicode(u'ipython_job.xml', config=True, |
|
854 | job_file_name = Unicode(u'ipython_job.xml', config=True, | |
855 | help="The filename of the instantiated job script.") |
|
855 | help="The filename of the instantiated job script.") | |
856 | # The full path to the instantiated job script. This gets made dynamically |
|
856 | # The full path to the instantiated job script. This gets made dynamically | |
857 | # by combining the work_dir with the job_file_name. |
|
857 | # by combining the work_dir with the job_file_name. | |
858 | job_file = Unicode(u'') |
|
858 | job_file = Unicode(u'') | |
859 | scheduler = Unicode('', config=True, |
|
859 | scheduler = Unicode('', config=True, | |
860 | help="The hostname of the scheduler to submit the job to.") |
|
860 | help="The hostname of the scheduler to submit the job to.") | |
861 | job_cmd = Unicode(find_job_cmd(), config=True, |
|
861 | job_cmd = Unicode(find_job_cmd(), config=True, | |
862 | help="The command for submitting jobs.") |
|
862 | help="The command for submitting jobs.") | |
863 |
|
863 | |||
864 | def __init__(self, work_dir=u'.', config=None, **kwargs): |
|
864 | def __init__(self, work_dir=u'.', config=None, **kwargs): | |
865 | super(WindowsHPCLauncher, self).__init__( |
|
865 | super(WindowsHPCLauncher, self).__init__( | |
866 | work_dir=work_dir, config=config, **kwargs |
|
866 | work_dir=work_dir, config=config, **kwargs | |
867 | ) |
|
867 | ) | |
868 |
|
868 | |||
869 | @property |
|
869 | @property | |
870 | def job_file(self): |
|
870 | def job_file(self): | |
871 | return os.path.join(self.work_dir, self.job_file_name) |
|
871 | return os.path.join(self.work_dir, self.job_file_name) | |
872 |
|
872 | |||
873 | def write_job_file(self, n): |
|
873 | def write_job_file(self, n): | |
874 | raise NotImplementedError("Implement write_job_file in a subclass.") |
|
874 | raise NotImplementedError("Implement write_job_file in a subclass.") | |
875 |
|
875 | |||
876 | def find_args(self): |
|
876 | def find_args(self): | |
877 | return [u'job.exe'] |
|
877 | return [u'job.exe'] | |
878 |
|
878 | |||
879 | def parse_job_id(self, output): |
|
879 | def parse_job_id(self, output): | |
880 | """Take the output of the submit command and return the job id.""" |
|
880 | """Take the output of the submit command and return the job id.""" | |
881 | m = self.job_id_regexp.search(output) |
|
881 | m = self.job_id_regexp.search(output) | |
882 | if m is not None: |
|
882 | if m is not None: | |
883 | job_id = m.group() |
|
883 | job_id = m.group() | |
884 | else: |
|
884 | else: | |
885 | raise LauncherError("Job id couldn't be determined: %s" % output) |
|
885 | raise LauncherError("Job id couldn't be determined: %s" % output) | |
886 | self.job_id = job_id |
|
886 | self.job_id = job_id | |
887 | self.log.info('Job started with id: %r', job_id) |
|
887 | self.log.info('Job started with id: %r', job_id) | |
888 | return job_id |
|
888 | return job_id | |
889 |
|
889 | |||
890 | def start(self, n): |
|
890 | def start(self, n): | |
891 | """Start n copies of the process using the Win HPC job scheduler.""" |
|
891 | """Start n copies of the process using the Win HPC job scheduler.""" | |
892 | self.write_job_file(n) |
|
892 | self.write_job_file(n) | |
893 | args = [ |
|
893 | args = [ | |
894 | 'submit', |
|
894 | 'submit', | |
895 | '/jobfile:%s' % self.job_file, |
|
895 | '/jobfile:%s' % self.job_file, | |
896 | '/scheduler:%s' % self.scheduler |
|
896 | '/scheduler:%s' % self.scheduler | |
897 | ] |
|
897 | ] | |
898 | self.log.debug("Starting Win HPC Job: %s" % (self.job_cmd + ' ' + ' '.join(args),)) |
|
898 | self.log.debug("Starting Win HPC Job: %s" % (self.job_cmd + ' ' + ' '.join(args),)) | |
899 |
|
899 | |||
900 | output = check_output([self.job_cmd]+args, |
|
900 | output = check_output([self.job_cmd]+args, | |
901 | env=os.environ, |
|
901 | env=os.environ, | |
902 | cwd=self.work_dir, |
|
902 | cwd=self.work_dir, | |
903 | stderr=STDOUT |
|
903 | stderr=STDOUT | |
904 | ) |
|
904 | ) | |
905 | output = output.decode(DEFAULT_ENCODING, 'replace') |
|
905 | output = output.decode(DEFAULT_ENCODING, 'replace') | |
906 | job_id = self.parse_job_id(output) |
|
906 | job_id = self.parse_job_id(output) | |
907 | self.notify_start(job_id) |
|
907 | self.notify_start(job_id) | |
908 | return job_id |
|
908 | return job_id | |
909 |
|
909 | |||
910 | def stop(self): |
|
910 | def stop(self): | |
911 | args = [ |
|
911 | args = [ | |
912 | 'cancel', |
|
912 | 'cancel', | |
913 | self.job_id, |
|
913 | self.job_id, | |
914 | '/scheduler:%s' % self.scheduler |
|
914 | '/scheduler:%s' % self.scheduler | |
915 | ] |
|
915 | ] | |
916 | self.log.info("Stopping Win HPC Job: %s" % (self.job_cmd + ' ' + ' '.join(args),)) |
|
916 | self.log.info("Stopping Win HPC Job: %s" % (self.job_cmd + ' ' + ' '.join(args),)) | |
917 | try: |
|
917 | try: | |
918 | output = check_output([self.job_cmd]+args, |
|
918 | output = check_output([self.job_cmd]+args, | |
919 | env=os.environ, |
|
919 | env=os.environ, | |
920 | cwd=self.work_dir, |
|
920 | cwd=self.work_dir, | |
921 | stderr=STDOUT |
|
921 | stderr=STDOUT | |
922 | ) |
|
922 | ) | |
923 | output = output.decode(DEFAULT_ENCODING, 'replace') |
|
923 | output = output.decode(DEFAULT_ENCODING, 'replace') | |
924 | except: |
|
924 | except: | |
925 | output = u'The job already appears to be stopped: %r' % self.job_id |
|
925 | output = u'The job already appears to be stopped: %r' % self.job_id | |
926 | self.notify_stop(dict(job_id=self.job_id, output=output)) # Pass the output of the kill cmd |
|
926 | self.notify_stop(dict(job_id=self.job_id, output=output)) # Pass the output of the kill cmd | |
927 | return output |
|
927 | return output | |
928 |
|
928 | |||
929 |
|
929 | |||
930 | class WindowsHPCControllerLauncher(WindowsHPCLauncher, ClusterAppMixin): |
|
930 | class WindowsHPCControllerLauncher(WindowsHPCLauncher, ClusterAppMixin): | |
931 |
|
931 | |||
932 | job_file_name = Unicode(u'ipcontroller_job.xml', config=True, |
|
932 | job_file_name = Unicode(u'ipcontroller_job.xml', config=True, | |
933 | help="WinHPC xml job file.") |
|
933 | help="WinHPC xml job file.") | |
934 | controller_args = List([], config=False, |
|
934 | controller_args = List([], config=False, | |
935 | help="extra args to pass to ipcontroller") |
|
935 | help="extra args to pass to ipcontroller") | |
936 |
|
936 | |||
937 | def write_job_file(self, n): |
|
937 | def write_job_file(self, n): | |
938 | job = IPControllerJob(parent=self) |
|
938 | job = IPControllerJob(parent=self) | |
939 |
|
939 | |||
940 | t = IPControllerTask(parent=self) |
|
940 | t = IPControllerTask(parent=self) | |
941 | # The tasks work directory is *not* the actual work directory of |
|
941 | # The tasks work directory is *not* the actual work directory of | |
942 | # the controller. It is used as the base path for the stdout/stderr |
|
942 | # the controller. It is used as the base path for the stdout/stderr | |
943 | # files that the scheduler redirects to. |
|
943 | # files that the scheduler redirects to. | |
944 | t.work_directory = self.profile_dir |
|
944 | t.work_directory = self.profile_dir | |
945 | # Add the profile_dir and from self.start(). |
|
945 | # Add the profile_dir and from self.start(). | |
946 | t.controller_args.extend(self.cluster_args) |
|
946 | t.controller_args.extend(self.cluster_args) | |
947 | t.controller_args.extend(self.controller_args) |
|
947 | t.controller_args.extend(self.controller_args) | |
948 | job.add_task(t) |
|
948 | job.add_task(t) | |
949 |
|
949 | |||
950 | self.log.debug("Writing job description file: %s", self.job_file) |
|
950 | self.log.debug("Writing job description file: %s", self.job_file) | |
951 | job.write(self.job_file) |
|
951 | job.write(self.job_file) | |
952 |
|
952 | |||
953 | @property |
|
953 | @property | |
954 | def job_file(self): |
|
954 | def job_file(self): | |
955 | return os.path.join(self.profile_dir, self.job_file_name) |
|
955 | return os.path.join(self.profile_dir, self.job_file_name) | |
956 |
|
956 | |||
957 | def start(self): |
|
957 | def start(self): | |
958 | """Start the controller by profile_dir.""" |
|
958 | """Start the controller by profile_dir.""" | |
959 | return super(WindowsHPCControllerLauncher, self).start(1) |
|
959 | return super(WindowsHPCControllerLauncher, self).start(1) | |
960 |
|
960 | |||
961 |
|
961 | |||
962 | class WindowsHPCEngineSetLauncher(WindowsHPCLauncher, ClusterAppMixin): |
|
962 | class WindowsHPCEngineSetLauncher(WindowsHPCLauncher, ClusterAppMixin): | |
963 |
|
963 | |||
964 | job_file_name = Unicode(u'ipengineset_job.xml', config=True, |
|
964 | job_file_name = Unicode(u'ipengineset_job.xml', config=True, | |
965 | help="jobfile for ipengines job") |
|
965 | help="jobfile for ipengines job") | |
966 | engine_args = List([], config=False, |
|
966 | engine_args = List([], config=False, | |
967 | help="extra args to pas to ipengine") |
|
967 | help="extra args to pas to ipengine") | |
968 |
|
968 | |||
969 | def write_job_file(self, n): |
|
969 | def write_job_file(self, n): | |
970 | job = IPEngineSetJob(parent=self) |
|
970 | job = IPEngineSetJob(parent=self) | |
971 |
|
971 | |||
972 | for i in range(n): |
|
972 | for i in range(n): | |
973 | t = IPEngineTask(parent=self) |
|
973 | t = IPEngineTask(parent=self) | |
974 | # The tasks work directory is *not* the actual work directory of |
|
974 | # The tasks work directory is *not* the actual work directory of | |
975 | # the engine. It is used as the base path for the stdout/stderr |
|
975 | # the engine. It is used as the base path for the stdout/stderr | |
976 | # files that the scheduler redirects to. |
|
976 | # files that the scheduler redirects to. | |
977 | t.work_directory = self.profile_dir |
|
977 | t.work_directory = self.profile_dir | |
978 | # Add the profile_dir and from self.start(). |
|
978 | # Add the profile_dir and from self.start(). | |
979 | t.engine_args.extend(self.cluster_args) |
|
979 | t.engine_args.extend(self.cluster_args) | |
980 | t.engine_args.extend(self.engine_args) |
|
980 | t.engine_args.extend(self.engine_args) | |
981 | job.add_task(t) |
|
981 | job.add_task(t) | |
982 |
|
982 | |||
983 | self.log.debug("Writing job description file: %s", self.job_file) |
|
983 | self.log.debug("Writing job description file: %s", self.job_file) | |
984 | job.write(self.job_file) |
|
984 | job.write(self.job_file) | |
985 |
|
985 | |||
986 | @property |
|
986 | @property | |
987 | def job_file(self): |
|
987 | def job_file(self): | |
988 | return os.path.join(self.profile_dir, self.job_file_name) |
|
988 | return os.path.join(self.profile_dir, self.job_file_name) | |
989 |
|
989 | |||
990 | def start(self, n): |
|
990 | def start(self, n): | |
991 | """Start the controller by profile_dir.""" |
|
991 | """Start the controller by profile_dir.""" | |
992 | return super(WindowsHPCEngineSetLauncher, self).start(n) |
|
992 | return super(WindowsHPCEngineSetLauncher, self).start(n) | |
993 |
|
993 | |||
994 |
|
994 | |||
995 | #----------------------------------------------------------------------------- |
|
995 | #----------------------------------------------------------------------------- | |
996 | # Batch (PBS) system launchers |
|
996 | # Batch (PBS) system launchers | |
997 | #----------------------------------------------------------------------------- |
|
997 | #----------------------------------------------------------------------------- | |
998 |
|
998 | |||
999 | class BatchClusterAppMixin(ClusterAppMixin): |
|
999 | class BatchClusterAppMixin(ClusterAppMixin): | |
1000 | """ClusterApp mixin that updates the self.context dict, rather than cl-args.""" |
|
1000 | """ClusterApp mixin that updates the self.context dict, rather than cl-args.""" | |
1001 | def _profile_dir_changed(self, name, old, new): |
|
1001 | def _profile_dir_changed(self, name, old, new): | |
1002 | self.context[name] = new |
|
1002 | self.context[name] = new | |
1003 | _cluster_id_changed = _profile_dir_changed |
|
1003 | _cluster_id_changed = _profile_dir_changed | |
1004 |
|
1004 | |||
1005 | def _profile_dir_default(self): |
|
1005 | def _profile_dir_default(self): | |
1006 | self.context['profile_dir'] = '' |
|
1006 | self.context['profile_dir'] = '' | |
1007 | return '' |
|
1007 | return '' | |
1008 | def _cluster_id_default(self): |
|
1008 | def _cluster_id_default(self): | |
1009 | self.context['cluster_id'] = '' |
|
1009 | self.context['cluster_id'] = '' | |
1010 | return '' |
|
1010 | return '' | |
1011 |
|
1011 | |||
1012 |
|
1012 | |||
1013 | class BatchSystemLauncher(BaseLauncher): |
|
1013 | class BatchSystemLauncher(BaseLauncher): | |
1014 | """Launch an external process using a batch system. |
|
1014 | """Launch an external process using a batch system. | |
1015 |
|
1015 | |||
1016 | This class is designed to work with UNIX batch systems like PBS, LSF, |
|
1016 | This class is designed to work with UNIX batch systems like PBS, LSF, | |
1017 | GridEngine, etc. The overall model is that there are different commands |
|
1017 | GridEngine, etc. The overall model is that there are different commands | |
1018 | like qsub, qdel, etc. that handle the starting and stopping of the process. |
|
1018 | like qsub, qdel, etc. that handle the starting and stopping of the process. | |
1019 |
|
1019 | |||
1020 | This class also has the notion of a batch script. The ``batch_template`` |
|
1020 | This class also has the notion of a batch script. The ``batch_template`` | |
1021 | attribute can be set to a string that is a template for the batch script. |
|
1021 | attribute can be set to a string that is a template for the batch script. | |
1022 | This template is instantiated using string formatting. Thus the template can |
|
1022 | This template is instantiated using string formatting. Thus the template can | |
1023 | use {n} fot the number of instances. Subclasses can add additional variables |
|
1023 | use {n} fot the number of instances. Subclasses can add additional variables | |
1024 | to the template dict. |
|
1024 | to the template dict. | |
1025 | """ |
|
1025 | """ | |
1026 |
|
1026 | |||
1027 | # Subclasses must fill these in. See PBSEngineSet |
|
1027 | # Subclasses must fill these in. See PBSEngineSet | |
1028 | submit_command = List([''], config=True, |
|
1028 | submit_command = List([''], config=True, | |
1029 | help="The name of the command line program used to submit jobs.") |
|
1029 | help="The name of the command line program used to submit jobs.") | |
1030 | delete_command = List([''], config=True, |
|
1030 | delete_command = List([''], config=True, | |
1031 | help="The name of the command line program used to delete jobs.") |
|
1031 | help="The name of the command line program used to delete jobs.") | |
1032 | job_id_regexp = CRegExp('', config=True, |
|
1032 | job_id_regexp = CRegExp('', config=True, | |
1033 | help="""A regular expression used to get the job id from the output of the |
|
1033 | help="""A regular expression used to get the job id from the output of the | |
1034 | submit_command.""") |
|
1034 | submit_command.""") | |
1035 | job_id_regexp_group = Integer(0, config=True, |
|
1035 | job_id_regexp_group = Integer(0, config=True, | |
1036 | help="""The group we wish to match in job_id_regexp (0 to match all)""") |
|
1036 | help="""The group we wish to match in job_id_regexp (0 to match all)""") | |
1037 | batch_template = Unicode('', config=True, |
|
1037 | batch_template = Unicode('', config=True, | |
1038 | help="The string that is the batch script template itself.") |
|
1038 | help="The string that is the batch script template itself.") | |
1039 | batch_template_file = Unicode(u'', config=True, |
|
1039 | batch_template_file = Unicode(u'', config=True, | |
1040 | help="The file that contains the batch template.") |
|
1040 | help="The file that contains the batch template.") | |
1041 | batch_file_name = Unicode(u'batch_script', config=True, |
|
1041 | batch_file_name = Unicode(u'batch_script', config=True, | |
1042 | help="The filename of the instantiated batch script.") |
|
1042 | help="The filename of the instantiated batch script.") | |
1043 | queue = Unicode(u'', config=True, |
|
1043 | queue = Unicode(u'', config=True, | |
1044 | help="The PBS Queue.") |
|
1044 | help="The PBS Queue.") | |
1045 |
|
1045 | |||
1046 | def _queue_changed(self, name, old, new): |
|
1046 | def _queue_changed(self, name, old, new): | |
1047 | self.context[name] = new |
|
1047 | self.context[name] = new | |
1048 |
|
1048 | |||
1049 | n = Integer(1) |
|
1049 | n = Integer(1) | |
1050 | _n_changed = _queue_changed |
|
1050 | _n_changed = _queue_changed | |
1051 |
|
1051 | |||
1052 | # not configurable, override in subclasses |
|
1052 | # not configurable, override in subclasses | |
1053 | # PBS Job Array regex |
|
1053 | # PBS Job Array regex | |
1054 | job_array_regexp = CRegExp('') |
|
1054 | job_array_regexp = CRegExp('') | |
1055 | job_array_template = Unicode('') |
|
1055 | job_array_template = Unicode('') | |
1056 | # PBS Queue regex |
|
1056 | # PBS Queue regex | |
1057 | queue_regexp = CRegExp('') |
|
1057 | queue_regexp = CRegExp('') | |
1058 | queue_template = Unicode('') |
|
1058 | queue_template = Unicode('') | |
1059 | # The default batch template, override in subclasses |
|
1059 | # The default batch template, override in subclasses | |
1060 | default_template = Unicode('') |
|
1060 | default_template = Unicode('') | |
1061 | # The full path to the instantiated batch script. |
|
1061 | # The full path to the instantiated batch script. | |
1062 | batch_file = Unicode(u'') |
|
1062 | batch_file = Unicode(u'') | |
1063 | # the format dict used with batch_template: |
|
1063 | # the format dict used with batch_template: | |
1064 | context = Dict() |
|
1064 | context = Dict() | |
1065 |
|
1065 | |||
1066 | def _context_default(self): |
|
1066 | def _context_default(self): | |
1067 | """load the default context with the default values for the basic keys |
|
1067 | """load the default context with the default values for the basic keys | |
1068 |
|
1068 | |||
1069 | because the _trait_changed methods only load the context if they |
|
1069 | because the _trait_changed methods only load the context if they | |
1070 | are set to something other than the default value. |
|
1070 | are set to something other than the default value. | |
1071 | """ |
|
1071 | """ | |
1072 | return dict(n=1, queue=u'', profile_dir=u'', cluster_id=u'') |
|
1072 | return dict(n=1, queue=u'', profile_dir=u'', cluster_id=u'') | |
1073 |
|
1073 | |||
1074 | # the Formatter instance for rendering the templates: |
|
1074 | # the Formatter instance for rendering the templates: | |
1075 | formatter = Instance(EvalFormatter, (), {}) |
|
1075 | formatter = Instance(EvalFormatter, (), {}) | |
1076 |
|
1076 | |||
1077 | def find_args(self): |
|
1077 | def find_args(self): | |
1078 | return self.submit_command + [self.batch_file] |
|
1078 | return self.submit_command + [self.batch_file] | |
1079 |
|
1079 | |||
1080 | def __init__(self, work_dir=u'.', config=None, **kwargs): |
|
1080 | def __init__(self, work_dir=u'.', config=None, **kwargs): | |
1081 | super(BatchSystemLauncher, self).__init__( |
|
1081 | super(BatchSystemLauncher, self).__init__( | |
1082 | work_dir=work_dir, config=config, **kwargs |
|
1082 | work_dir=work_dir, config=config, **kwargs | |
1083 | ) |
|
1083 | ) | |
1084 | self.batch_file = os.path.join(self.work_dir, self.batch_file_name) |
|
1084 | self.batch_file = os.path.join(self.work_dir, self.batch_file_name) | |
1085 |
|
1085 | |||
1086 | def parse_job_id(self, output): |
|
1086 | def parse_job_id(self, output): | |
1087 | """Take the output of the submit command and return the job id.""" |
|
1087 | """Take the output of the submit command and return the job id.""" | |
1088 | m = self.job_id_regexp.search(output) |
|
1088 | m = self.job_id_regexp.search(output) | |
1089 | if m is not None: |
|
1089 | if m is not None: | |
1090 | job_id = m.group(self.job_id_regexp_group) |
|
1090 | job_id = m.group(self.job_id_regexp_group) | |
1091 | else: |
|
1091 | else: | |
1092 | raise LauncherError("Job id couldn't be determined: %s" % output) |
|
1092 | raise LauncherError("Job id couldn't be determined: %s" % output) | |
1093 | self.job_id = job_id |
|
1093 | self.job_id = job_id | |
1094 | self.log.info('Job submitted with job id: %r', job_id) |
|
1094 | self.log.info('Job submitted with job id: %r', job_id) | |
1095 | return job_id |
|
1095 | return job_id | |
1096 |
|
1096 | |||
1097 | def write_batch_script(self, n): |
|
1097 | def write_batch_script(self, n): | |
1098 | """Instantiate and write the batch script to the work_dir.""" |
|
1098 | """Instantiate and write the batch script to the work_dir.""" | |
1099 | self.n = n |
|
1099 | self.n = n | |
1100 | # first priority is batch_template if set |
|
1100 | # first priority is batch_template if set | |
1101 | if self.batch_template_file and not self.batch_template: |
|
1101 | if self.batch_template_file and not self.batch_template: | |
1102 | # second priority is batch_template_file |
|
1102 | # second priority is batch_template_file | |
1103 | with open(self.batch_template_file) as f: |
|
1103 | with open(self.batch_template_file) as f: | |
1104 | self.batch_template = f.read() |
|
1104 | self.batch_template = f.read() | |
1105 | if not self.batch_template: |
|
1105 | if not self.batch_template: | |
1106 | # third (last) priority is default_template |
|
1106 | # third (last) priority is default_template | |
1107 | self.batch_template = self.default_template |
|
1107 | self.batch_template = self.default_template | |
1108 | # add jobarray or queue lines to user-specified template |
|
1108 | # add jobarray or queue lines to user-specified template | |
1109 | # note that this is *only* when user did not specify a template. |
|
1109 | # note that this is *only* when user did not specify a template. | |
1110 | self._insert_queue_in_script() |
|
1110 | self._insert_queue_in_script() | |
1111 | self._insert_job_array_in_script() |
|
1111 | self._insert_job_array_in_script() | |
1112 | script_as_string = self.formatter.format(self.batch_template, **self.context) |
|
1112 | script_as_string = self.formatter.format(self.batch_template, **self.context) | |
1113 | self.log.debug('Writing batch script: %s', self.batch_file) |
|
1113 | self.log.debug('Writing batch script: %s', self.batch_file) | |
1114 | with open(self.batch_file, 'w') as f: |
|
1114 | with open(self.batch_file, 'w') as f: | |
1115 | f.write(script_as_string) |
|
1115 | f.write(script_as_string) | |
1116 | os.chmod(self.batch_file, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) |
|
1116 | os.chmod(self.batch_file, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR) | |
1117 |
|
1117 | |||
1118 | def _insert_queue_in_script(self): |
|
1118 | def _insert_queue_in_script(self): | |
1119 | """Inserts a queue if required into the batch script. |
|
1119 | """Inserts a queue if required into the batch script. | |
1120 | """ |
|
1120 | """ | |
1121 | if self.queue and not self.queue_regexp.search(self.batch_template): |
|
1121 | if self.queue and not self.queue_regexp.search(self.batch_template): | |
1122 | self.log.debug("adding PBS queue settings to batch script") |
|
1122 | self.log.debug("adding PBS queue settings to batch script") | |
1123 | firstline, rest = self.batch_template.split('\n',1) |
|
1123 | firstline, rest = self.batch_template.split('\n',1) | |
1124 | self.batch_template = u'\n'.join([firstline, self.queue_template, rest]) |
|
1124 | self.batch_template = u'\n'.join([firstline, self.queue_template, rest]) | |
1125 |
|
1125 | |||
1126 | def _insert_job_array_in_script(self): |
|
1126 | def _insert_job_array_in_script(self): | |
1127 | """Inserts a job array if required into the batch script. |
|
1127 | """Inserts a job array if required into the batch script. | |
1128 | """ |
|
1128 | """ | |
1129 | if not self.job_array_regexp.search(self.batch_template): |
|
1129 | if not self.job_array_regexp.search(self.batch_template): | |
1130 | self.log.debug("adding job array settings to batch script") |
|
1130 | self.log.debug("adding job array settings to batch script") | |
1131 | firstline, rest = self.batch_template.split('\n',1) |
|
1131 | firstline, rest = self.batch_template.split('\n',1) | |
1132 | self.batch_template = u'\n'.join([firstline, self.job_array_template, rest]) |
|
1132 | self.batch_template = u'\n'.join([firstline, self.job_array_template, rest]) | |
1133 |
|
1133 | |||
1134 | def start(self, n): |
|
1134 | def start(self, n): | |
1135 | """Start n copies of the process using a batch system.""" |
|
1135 | """Start n copies of the process using a batch system.""" | |
1136 | self.log.debug("Starting %s: %r", self.__class__.__name__, self.args) |
|
1136 | self.log.debug("Starting %s: %r", self.__class__.__name__, self.args) | |
1137 | # Here we save profile_dir in the context so they |
|
1137 | # Here we save profile_dir in the context so they | |
1138 | # can be used in the batch script template as {profile_dir} |
|
1138 | # can be used in the batch script template as {profile_dir} | |
1139 | self.write_batch_script(n) |
|
1139 | self.write_batch_script(n) | |
1140 | output = check_output(self.args, env=os.environ) |
|
1140 | output = check_output(self.args, env=os.environ) | |
1141 | output = output.decode(DEFAULT_ENCODING, 'replace') |
|
1141 | output = output.decode(DEFAULT_ENCODING, 'replace') | |
1142 |
|
1142 | |||
1143 | job_id = self.parse_job_id(output) |
|
1143 | job_id = self.parse_job_id(output) | |
1144 | self.notify_start(job_id) |
|
1144 | self.notify_start(job_id) | |
1145 | return job_id |
|
1145 | return job_id | |
1146 |
|
1146 | |||
1147 | def stop(self): |
|
1147 | def stop(self): | |
1148 | try: |
|
1148 | try: | |
1149 | p = Popen(self.delete_command+[self.job_id], env=os.environ, |
|
1149 | p = Popen(self.delete_command+[self.job_id], env=os.environ, | |
1150 | stdout=PIPE, stderr=PIPE) |
|
1150 | stdout=PIPE, stderr=PIPE) | |
1151 | out, err = p.communicate() |
|
1151 | out, err = p.communicate() | |
1152 | output = out + err |
|
1152 | output = out + err | |
1153 | except: |
|
1153 | except: | |
1154 | self.log.exception("Problem stopping cluster with command: %s" % |
|
1154 | self.log.exception("Problem stopping cluster with command: %s" % | |
1155 | (self.delete_command + [self.job_id])) |
|
1155 | (self.delete_command + [self.job_id])) | |
1156 | output = "" |
|
1156 | output = "" | |
1157 | output = output.decode(DEFAULT_ENCODING, 'replace') |
|
1157 | output = output.decode(DEFAULT_ENCODING, 'replace') | |
1158 | self.notify_stop(dict(job_id=self.job_id, output=output)) # Pass the output of the kill cmd |
|
1158 | self.notify_stop(dict(job_id=self.job_id, output=output)) # Pass the output of the kill cmd | |
1159 | return output |
|
1159 | return output | |
1160 |
|
1160 | |||
1161 |
|
1161 | |||
1162 | class PBSLauncher(BatchSystemLauncher): |
|
1162 | class PBSLauncher(BatchSystemLauncher): | |
1163 | """A BatchSystemLauncher subclass for PBS.""" |
|
1163 | """A BatchSystemLauncher subclass for PBS.""" | |
1164 |
|
1164 | |||
1165 | submit_command = List(['qsub'], config=True, |
|
1165 | submit_command = List(['qsub'], config=True, | |
1166 | help="The PBS submit command ['qsub']") |
|
1166 | help="The PBS submit command ['qsub']") | |
1167 | delete_command = List(['qdel'], config=True, |
|
1167 | delete_command = List(['qdel'], config=True, | |
1168 | help="The PBS delete command ['qsub']") |
|
1168 | help="The PBS delete command ['qsub']") | |
1169 | job_id_regexp = CRegExp(r'\d+', config=True, |
|
1169 | job_id_regexp = CRegExp(r'\d+', config=True, | |
1170 | help="Regular expresion for identifying the job ID [r'\d+']") |
|
1170 | help="Regular expresion for identifying the job ID [r'\d+']") | |
1171 |
|
1171 | |||
1172 | batch_file = Unicode(u'') |
|
1172 | batch_file = Unicode(u'') | |
1173 | job_array_regexp = CRegExp('#PBS\W+-t\W+[\w\d\-\$]+') |
|
1173 | job_array_regexp = CRegExp('#PBS\W+-t\W+[\w\d\-\$]+') | |
1174 | job_array_template = Unicode('#PBS -t 1-{n}') |
|
1174 | job_array_template = Unicode('#PBS -t 1-{n}') | |
1175 | queue_regexp = CRegExp('#PBS\W+-q\W+\$?\w+') |
|
1175 | queue_regexp = CRegExp('#PBS\W+-q\W+\$?\w+') | |
1176 | queue_template = Unicode('#PBS -q {queue}') |
|
1176 | queue_template = Unicode('#PBS -q {queue}') | |
1177 |
|
1177 | |||
1178 |
|
1178 | |||
1179 | class PBSControllerLauncher(PBSLauncher, BatchClusterAppMixin): |
|
1179 | class PBSControllerLauncher(PBSLauncher, BatchClusterAppMixin): | |
1180 | """Launch a controller using PBS.""" |
|
1180 | """Launch a controller using PBS.""" | |
1181 |
|
1181 | |||
1182 | batch_file_name = Unicode(u'pbs_controller', config=True, |
|
1182 | batch_file_name = Unicode(u'pbs_controller', config=True, | |
1183 | help="batch file name for the controller job.") |
|
1183 | help="batch file name for the controller job.") | |
1184 | default_template= Unicode("""#!/bin/sh |
|
1184 | default_template= Unicode("""#!/bin/sh | |
1185 | #PBS -V |
|
1185 | #PBS -V | |
1186 | #PBS -N ipcontroller |
|
1186 | #PBS -N ipcontroller | |
1187 | %s --log-to-file --profile-dir="{profile_dir}" --cluster-id="{cluster_id}" |
|
1187 | %s --log-to-file --profile-dir="{profile_dir}" --cluster-id="{cluster_id}" | |
1188 | """%(' '.join(map(pipes.quote, ipcontroller_cmd_argv)))) |
|
1188 | """%(' '.join(map(pipes.quote, ipcontroller_cmd_argv)))) | |
1189 |
|
1189 | |||
1190 | def start(self): |
|
1190 | def start(self): | |
1191 | """Start the controller by profile or profile_dir.""" |
|
1191 | """Start the controller by profile or profile_dir.""" | |
1192 | return super(PBSControllerLauncher, self).start(1) |
|
1192 | return super(PBSControllerLauncher, self).start(1) | |
1193 |
|
1193 | |||
1194 |
|
1194 | |||
1195 | class PBSEngineSetLauncher(PBSLauncher, BatchClusterAppMixin): |
|
1195 | class PBSEngineSetLauncher(PBSLauncher, BatchClusterAppMixin): | |
1196 | """Launch Engines using PBS""" |
|
1196 | """Launch Engines using PBS""" | |
1197 | batch_file_name = Unicode(u'pbs_engines', config=True, |
|
1197 | batch_file_name = Unicode(u'pbs_engines', config=True, | |
1198 | help="batch file name for the engine(s) job.") |
|
1198 | help="batch file name for the engine(s) job.") | |
1199 | default_template= Unicode(u"""#!/bin/sh |
|
1199 | default_template= Unicode(u"""#!/bin/sh | |
1200 | #PBS -V |
|
1200 | #PBS -V | |
1201 | #PBS -N ipengine |
|
1201 | #PBS -N ipengine | |
1202 | %s --profile-dir="{profile_dir}" --cluster-id="{cluster_id}" |
|
1202 | %s --profile-dir="{profile_dir}" --cluster-id="{cluster_id}" | |
1203 | """%(' '.join(map(pipes.quote,ipengine_cmd_argv)))) |
|
1203 | """%(' '.join(map(pipes.quote,ipengine_cmd_argv)))) | |
1204 |
|
1204 | |||
1205 |
|
1205 | |||
1206 | #SGE is very similar to PBS |
|
1206 | #SGE is very similar to PBS | |
1207 |
|
1207 | |||
1208 | class SGELauncher(PBSLauncher): |
|
1208 | class SGELauncher(PBSLauncher): | |
1209 | """Sun GridEngine is a PBS clone with slightly different syntax""" |
|
1209 | """Sun GridEngine is a PBS clone with slightly different syntax""" | |
1210 | job_array_regexp = CRegExp('#\$\W+\-t') |
|
1210 | job_array_regexp = CRegExp('#\$\W+\-t') | |
1211 | job_array_template = Unicode('#$ -t 1-{n}') |
|
1211 | job_array_template = Unicode('#$ -t 1-{n}') | |
1212 | queue_regexp = CRegExp('#\$\W+-q\W+\$?\w+') |
|
1212 | queue_regexp = CRegExp('#\$\W+-q\W+\$?\w+') | |
1213 | queue_template = Unicode('#$ -q {queue}') |
|
1213 | queue_template = Unicode('#$ -q {queue}') | |
1214 |
|
1214 | |||
1215 |
|
1215 | |||
1216 | class SGEControllerLauncher(SGELauncher, BatchClusterAppMixin): |
|
1216 | class SGEControllerLauncher(SGELauncher, BatchClusterAppMixin): | |
1217 | """Launch a controller using SGE.""" |
|
1217 | """Launch a controller using SGE.""" | |
1218 |
|
1218 | |||
1219 | batch_file_name = Unicode(u'sge_controller', config=True, |
|
1219 | batch_file_name = Unicode(u'sge_controller', config=True, | |
1220 | help="batch file name for the ipontroller job.") |
|
1220 | help="batch file name for the ipontroller job.") | |
1221 | default_template= Unicode(u"""#$ -V |
|
1221 | default_template= Unicode(u"""#$ -V | |
1222 | #$ -S /bin/sh |
|
1222 | #$ -S /bin/sh | |
1223 | #$ -N ipcontroller |
|
1223 | #$ -N ipcontroller | |
1224 | %s --log-to-file --profile-dir="{profile_dir}" --cluster-id="{cluster_id}" |
|
1224 | %s --log-to-file --profile-dir="{profile_dir}" --cluster-id="{cluster_id}" | |
1225 | """%(' '.join(map(pipes.quote, ipcontroller_cmd_argv)))) |
|
1225 | """%(' '.join(map(pipes.quote, ipcontroller_cmd_argv)))) | |
1226 |
|
1226 | |||
1227 | def start(self): |
|
1227 | def start(self): | |
1228 | """Start the controller by profile or profile_dir.""" |
|
1228 | """Start the controller by profile or profile_dir.""" | |
1229 | return super(SGEControllerLauncher, self).start(1) |
|
1229 | return super(SGEControllerLauncher, self).start(1) | |
1230 |
|
1230 | |||
1231 |
|
1231 | |||
1232 | class SGEEngineSetLauncher(SGELauncher, BatchClusterAppMixin): |
|
1232 | class SGEEngineSetLauncher(SGELauncher, BatchClusterAppMixin): | |
1233 | """Launch Engines with SGE""" |
|
1233 | """Launch Engines with SGE""" | |
1234 | batch_file_name = Unicode(u'sge_engines', config=True, |
|
1234 | batch_file_name = Unicode(u'sge_engines', config=True, | |
1235 | help="batch file name for the engine(s) job.") |
|
1235 | help="batch file name for the engine(s) job.") | |
1236 | default_template = Unicode("""#$ -V |
|
1236 | default_template = Unicode("""#$ -V | |
1237 | #$ -S /bin/sh |
|
1237 | #$ -S /bin/sh | |
1238 | #$ -N ipengine |
|
1238 | #$ -N ipengine | |
1239 | %s --profile-dir="{profile_dir}" --cluster-id="{cluster_id}" |
|
1239 | %s --profile-dir="{profile_dir}" --cluster-id="{cluster_id}" | |
1240 | """%(' '.join(map(pipes.quote, ipengine_cmd_argv)))) |
|
1240 | """%(' '.join(map(pipes.quote, ipengine_cmd_argv)))) | |
1241 |
|
1241 | |||
1242 |
|
1242 | |||
1243 | # LSF launchers |
|
1243 | # LSF launchers | |
1244 |
|
1244 | |||
1245 | class LSFLauncher(BatchSystemLauncher): |
|
1245 | class LSFLauncher(BatchSystemLauncher): | |
1246 | """A BatchSystemLauncher subclass for LSF.""" |
|
1246 | """A BatchSystemLauncher subclass for LSF.""" | |
1247 |
|
1247 | |||
1248 | submit_command = List(['bsub'], config=True, |
|
1248 | submit_command = List(['bsub'], config=True, | |
1249 | help="The PBS submit command ['bsub']") |
|
1249 | help="The PBS submit command ['bsub']") | |
1250 | delete_command = List(['bkill'], config=True, |
|
1250 | delete_command = List(['bkill'], config=True, | |
1251 | help="The PBS delete command ['bkill']") |
|
1251 | help="The PBS delete command ['bkill']") | |
1252 | job_id_regexp = CRegExp(r'\d+', config=True, |
|
1252 | job_id_regexp = CRegExp(r'\d+', config=True, | |
1253 | help="Regular expresion for identifying the job ID [r'\d+']") |
|
1253 | help="Regular expresion for identifying the job ID [r'\d+']") | |
1254 |
|
1254 | |||
1255 | batch_file = Unicode(u'') |
|
1255 | batch_file = Unicode(u'') | |
1256 | job_array_regexp = CRegExp('#BSUB[ \t]-J+\w+\[\d+-\d+\]') |
|
1256 | job_array_regexp = CRegExp('#BSUB[ \t]-J+\w+\[\d+-\d+\]') | |
1257 | job_array_template = Unicode('#BSUB -J ipengine[1-{n}]') |
|
1257 | job_array_template = Unicode('#BSUB -J ipengine[1-{n}]') | |
1258 | queue_regexp = CRegExp('#BSUB[ \t]+-q[ \t]+\w+') |
|
1258 | queue_regexp = CRegExp('#BSUB[ \t]+-q[ \t]+\w+') | |
1259 | queue_template = Unicode('#BSUB -q {queue}') |
|
1259 | queue_template = Unicode('#BSUB -q {queue}') | |
1260 |
|
1260 | |||
1261 | def start(self, n): |
|
1261 | def start(self, n): | |
1262 | """Start n copies of the process using LSF batch system. |
|
1262 | """Start n copies of the process using LSF batch system. | |
1263 | This cant inherit from the base class because bsub expects |
|
1263 | This cant inherit from the base class because bsub expects | |
1264 | to be piped a shell script in order to honor the #BSUB directives : |
|
1264 | to be piped a shell script in order to honor the #BSUB directives : | |
1265 | bsub < script |
|
1265 | bsub < script | |
1266 | """ |
|
1266 | """ | |
1267 | # Here we save profile_dir in the context so they |
|
1267 | # Here we save profile_dir in the context so they | |
1268 | # can be used in the batch script template as {profile_dir} |
|
1268 | # can be used in the batch script template as {profile_dir} | |
1269 | self.write_batch_script(n) |
|
1269 | self.write_batch_script(n) | |
1270 | piped_cmd = self.args[0]+'<\"'+self.args[1]+'\"' |
|
1270 | piped_cmd = self.args[0]+'<\"'+self.args[1]+'\"' | |
1271 | self.log.debug("Starting %s: %s", self.__class__.__name__, piped_cmd) |
|
1271 | self.log.debug("Starting %s: %s", self.__class__.__name__, piped_cmd) | |
1272 | p = Popen(piped_cmd, shell=True,env=os.environ,stdout=PIPE) |
|
1272 | p = Popen(piped_cmd, shell=True,env=os.environ,stdout=PIPE) | |
1273 | output,err = p.communicate() |
|
1273 | output,err = p.communicate() | |
1274 | output = output.decode(DEFAULT_ENCODING, 'replace') |
|
1274 | output = output.decode(DEFAULT_ENCODING, 'replace') | |
1275 | job_id = self.parse_job_id(output) |
|
1275 | job_id = self.parse_job_id(output) | |
1276 | self.notify_start(job_id) |
|
1276 | self.notify_start(job_id) | |
1277 | return job_id |
|
1277 | return job_id | |
1278 |
|
1278 | |||
1279 |
|
1279 | |||
1280 | class LSFControllerLauncher(LSFLauncher, BatchClusterAppMixin): |
|
1280 | class LSFControllerLauncher(LSFLauncher, BatchClusterAppMixin): | |
1281 | """Launch a controller using LSF.""" |
|
1281 | """Launch a controller using LSF.""" | |
1282 |
|
1282 | |||
1283 | batch_file_name = Unicode(u'lsf_controller', config=True, |
|
1283 | batch_file_name = Unicode(u'lsf_controller', config=True, | |
1284 | help="batch file name for the controller job.") |
|
1284 | help="batch file name for the controller job.") | |
1285 | default_template= Unicode("""#!/bin/sh |
|
1285 | default_template= Unicode("""#!/bin/sh | |
1286 | #BSUB -J ipcontroller |
|
1286 | #BSUB -J ipcontroller | |
1287 | #BSUB -oo ipcontroller.o.%%J |
|
1287 | #BSUB -oo ipcontroller.o.%%J | |
1288 | #BSUB -eo ipcontroller.e.%%J |
|
1288 | #BSUB -eo ipcontroller.e.%%J | |
1289 | %s --log-to-file --profile-dir="{profile_dir}" --cluster-id="{cluster_id}" |
|
1289 | %s --log-to-file --profile-dir="{profile_dir}" --cluster-id="{cluster_id}" | |
1290 | """%(' '.join(map(pipes.quote,ipcontroller_cmd_argv)))) |
|
1290 | """%(' '.join(map(pipes.quote,ipcontroller_cmd_argv)))) | |
1291 |
|
1291 | |||
1292 | def start(self): |
|
1292 | def start(self): | |
1293 | """Start the controller by profile or profile_dir.""" |
|
1293 | """Start the controller by profile or profile_dir.""" | |
1294 | return super(LSFControllerLauncher, self).start(1) |
|
1294 | return super(LSFControllerLauncher, self).start(1) | |
1295 |
|
1295 | |||
1296 |
|
1296 | |||
1297 | class LSFEngineSetLauncher(LSFLauncher, BatchClusterAppMixin): |
|
1297 | class LSFEngineSetLauncher(LSFLauncher, BatchClusterAppMixin): | |
1298 | """Launch Engines using LSF""" |
|
1298 | """Launch Engines using LSF""" | |
1299 | batch_file_name = Unicode(u'lsf_engines', config=True, |
|
1299 | batch_file_name = Unicode(u'lsf_engines', config=True, | |
1300 | help="batch file name for the engine(s) job.") |
|
1300 | help="batch file name for the engine(s) job.") | |
1301 | default_template= Unicode(u"""#!/bin/sh |
|
1301 | default_template= Unicode(u"""#!/bin/sh | |
1302 | #BSUB -oo ipengine.o.%%J |
|
1302 | #BSUB -oo ipengine.o.%%J | |
1303 | #BSUB -eo ipengine.e.%%J |
|
1303 | #BSUB -eo ipengine.e.%%J | |
1304 | %s --profile-dir="{profile_dir}" --cluster-id="{cluster_id}" |
|
1304 | %s --profile-dir="{profile_dir}" --cluster-id="{cluster_id}" | |
1305 | """%(' '.join(map(pipes.quote, ipengine_cmd_argv)))) |
|
1305 | """%(' '.join(map(pipes.quote, ipengine_cmd_argv)))) | |
1306 |
|
1306 | |||
1307 |
|
1307 | |||
1308 |
|
1308 | |||
1309 | class HTCondorLauncher(BatchSystemLauncher): |
|
1309 | class HTCondorLauncher(BatchSystemLauncher): | |
1310 | """A BatchSystemLauncher subclass for HTCondor. |
|
1310 | """A BatchSystemLauncher subclass for HTCondor. | |
1311 |
|
1311 | |||
1312 | HTCondor requires that we launch the ipengine/ipcontroller scripts rather |
|
1312 | HTCondor requires that we launch the ipengine/ipcontroller scripts rather | |
1313 | that the python instance but otherwise is very similar to PBS. This is because |
|
1313 | that the python instance but otherwise is very similar to PBS. This is because | |
1314 | HTCondor destroys sys.executable when launching remote processes - a launched |
|
1314 | HTCondor destroys sys.executable when launching remote processes - a launched | |
1315 | python process depends on sys.executable to effectively evaluate its |
|
1315 | python process depends on sys.executable to effectively evaluate its | |
1316 | module search paths. Without it, regardless of which python interpreter you launch |
|
1316 | module search paths. Without it, regardless of which python interpreter you launch | |
1317 | you will get the to built in module search paths. |
|
1317 | you will get the to built in module search paths. | |
1318 |
|
1318 | |||
1319 | We use the ip{cluster, engine, controller} scripts as our executable to circumvent |
|
1319 | We use the ip{cluster, engine, controller} scripts as our executable to circumvent | |
1320 | this - the mechanism of shebanged scripts means that the python binary will be |
|
1320 | this - the mechanism of shebanged scripts means that the python binary will be | |
1321 | launched with argv[0] set to the *location of the ip{cluster, engine, controller} |
|
1321 | launched with argv[0] set to the *location of the ip{cluster, engine, controller} | |
1322 | scripts on the remote node*. This means you need to take care that: |
|
1322 | scripts on the remote node*. This means you need to take care that: | |
1323 |
|
1323 | |||
1324 | a. Your remote nodes have their paths configured correctly, with the ipengine and ipcontroller |
|
1324 | a. Your remote nodes have their paths configured correctly, with the ipengine and ipcontroller | |
1325 | of the python environment you wish to execute code in having top precedence. |
|
1325 | of the python environment you wish to execute code in having top precedence. | |
1326 | b. This functionality is untested on Windows. |
|
1326 | b. This functionality is untested on Windows. | |
1327 |
|
1327 | |||
1328 | If you need different behavior, consider making you own template. |
|
1328 | If you need different behavior, consider making you own template. | |
1329 | """ |
|
1329 | """ | |
1330 |
|
1330 | |||
1331 | submit_command = List(['condor_submit'], config=True, |
|
1331 | submit_command = List(['condor_submit'], config=True, | |
1332 | help="The HTCondor submit command ['condor_submit']") |
|
1332 | help="The HTCondor submit command ['condor_submit']") | |
1333 | delete_command = List(['condor_rm'], config=True, |
|
1333 | delete_command = List(['condor_rm'], config=True, | |
1334 | help="The HTCondor delete command ['condor_rm']") |
|
1334 | help="The HTCondor delete command ['condor_rm']") | |
1335 | job_id_regexp = CRegExp(r'(\d+)\.$', config=True, |
|
1335 | job_id_regexp = CRegExp(r'(\d+)\.$', config=True, | |
1336 | help="Regular expression for identifying the job ID [r'(\d+)\.$']") |
|
1336 | help="Regular expression for identifying the job ID [r'(\d+)\.$']") | |
1337 | job_id_regexp_group = Integer(1, config=True, |
|
1337 | job_id_regexp_group = Integer(1, config=True, | |
1338 | help="""The group we wish to match in job_id_regexp [1]""") |
|
1338 | help="""The group we wish to match in job_id_regexp [1]""") | |
1339 |
|
1339 | |||
1340 | job_array_regexp = CRegExp('queue\W+\$') |
|
1340 | job_array_regexp = CRegExp('queue\W+\$') | |
1341 | job_array_template = Unicode('queue {n}') |
|
1341 | job_array_template = Unicode('queue {n}') | |
1342 |
|
1342 | |||
1343 |
|
1343 | |||
1344 | def _insert_job_array_in_script(self): |
|
1344 | def _insert_job_array_in_script(self): | |
1345 | """Inserts a job array if required into the batch script. |
|
1345 | """Inserts a job array if required into the batch script. | |
1346 | """ |
|
1346 | """ | |
1347 | if not self.job_array_regexp.search(self.batch_template): |
|
1347 | if not self.job_array_regexp.search(self.batch_template): | |
1348 | self.log.debug("adding job array settings to batch script") |
|
1348 | self.log.debug("adding job array settings to batch script") | |
1349 | #HTCondor requires that the job array goes at the bottom of the script |
|
1349 | #HTCondor requires that the job array goes at the bottom of the script | |
1350 | self.batch_template = '\n'.join([self.batch_template, |
|
1350 | self.batch_template = '\n'.join([self.batch_template, | |
1351 | self.job_array_template]) |
|
1351 | self.job_array_template]) | |
1352 |
|
1352 | |||
1353 | def _insert_queue_in_script(self): |
|
1353 | def _insert_queue_in_script(self): | |
1354 | """AFAIK, HTCondor doesn't have a concept of multiple queues that can be |
|
1354 | """AFAIK, HTCondor doesn't have a concept of multiple queues that can be | |
1355 | specified in the script. |
|
1355 | specified in the script. | |
1356 | """ |
|
1356 | """ | |
1357 | pass |
|
1357 | pass | |
1358 |
|
1358 | |||
1359 |
|
1359 | |||
1360 | class HTCondorControllerLauncher(HTCondorLauncher, BatchClusterAppMixin): |
|
1360 | class HTCondorControllerLauncher(HTCondorLauncher, BatchClusterAppMixin): | |
1361 | """Launch a controller using HTCondor.""" |
|
1361 | """Launch a controller using HTCondor.""" | |
1362 |
|
1362 | |||
1363 | batch_file_name = Unicode(u'htcondor_controller', config=True, |
|
1363 | batch_file_name = Unicode(u'htcondor_controller', config=True, | |
1364 | help="batch file name for the controller job.") |
|
1364 | help="batch file name for the controller job.") | |
1365 | default_template = Unicode(r""" |
|
1365 | default_template = Unicode(r""" | |
1366 | universe = vanilla |
|
1366 | universe = vanilla | |
1367 | executable = ipcontroller |
|
1367 | executable = ipcontroller | |
1368 | # by default we expect a shared file system |
|
1368 | # by default we expect a shared file system | |
1369 | transfer_executable = False |
|
1369 | transfer_executable = False | |
1370 | arguments = --log-to-file '--profile-dir={profile_dir}' --cluster-id='{cluster_id}' |
|
1370 | arguments = --log-to-file '--profile-dir={profile_dir}' --cluster-id='{cluster_id}' | |
1371 | """) |
|
1371 | """) | |
1372 |
|
1372 | |||
1373 | def start(self): |
|
1373 | def start(self): | |
1374 | """Start the controller by profile or profile_dir.""" |
|
1374 | """Start the controller by profile or profile_dir.""" | |
1375 | return super(HTCondorControllerLauncher, self).start(1) |
|
1375 | return super(HTCondorControllerLauncher, self).start(1) | |
1376 |
|
1376 | |||
1377 |
|
1377 | |||
1378 | class HTCondorEngineSetLauncher(HTCondorLauncher, BatchClusterAppMixin): |
|
1378 | class HTCondorEngineSetLauncher(HTCondorLauncher, BatchClusterAppMixin): | |
1379 | """Launch Engines using HTCondor""" |
|
1379 | """Launch Engines using HTCondor""" | |
1380 | batch_file_name = Unicode(u'htcondor_engines', config=True, |
|
1380 | batch_file_name = Unicode(u'htcondor_engines', config=True, | |
1381 | help="batch file name for the engine(s) job.") |
|
1381 | help="batch file name for the engine(s) job.") | |
1382 | default_template = Unicode(""" |
|
1382 | default_template = Unicode(""" | |
1383 | universe = vanilla |
|
1383 | universe = vanilla | |
1384 | executable = ipengine |
|
1384 | executable = ipengine | |
1385 | # by default we expect a shared file system |
|
1385 | # by default we expect a shared file system | |
1386 | transfer_executable = False |
|
1386 | transfer_executable = False | |
1387 | arguments = "--log-to-file '--profile-dir={profile_dir}' '--cluster-id={cluster_id}'" |
|
1387 | arguments = "--log-to-file '--profile-dir={profile_dir}' '--cluster-id={cluster_id}'" | |
1388 | """) |
|
1388 | """) | |
1389 |
|
1389 | |||
1390 |
|
1390 | |||
1391 | #----------------------------------------------------------------------------- |
|
1391 | #----------------------------------------------------------------------------- | |
1392 | # A launcher for ipcluster itself! |
|
1392 | # A launcher for ipcluster itself! | |
1393 | #----------------------------------------------------------------------------- |
|
1393 | #----------------------------------------------------------------------------- | |
1394 |
|
1394 | |||
1395 |
|
1395 | |||
1396 | class IPClusterLauncher(LocalProcessLauncher): |
|
1396 | class IPClusterLauncher(LocalProcessLauncher): | |
1397 | """Launch the ipcluster program in an external process.""" |
|
1397 | """Launch the ipcluster program in an external process.""" | |
1398 |
|
1398 | |||
1399 | ipcluster_cmd = List(ipcluster_cmd_argv, config=True, |
|
1399 | ipcluster_cmd = List(ipcluster_cmd_argv, config=True, | |
1400 | help="Popen command for ipcluster") |
|
1400 | help="Popen command for ipcluster") | |
1401 | ipcluster_args = List( |
|
1401 | ipcluster_args = List( | |
1402 | ['--clean-logs=True', '--log-to-file', '--log-level=%i'%logging.INFO], config=True, |
|
1402 | ['--clean-logs=True', '--log-to-file', '--log-level=%i'%logging.INFO], config=True, | |
1403 | help="Command line arguments to pass to ipcluster.") |
|
1403 | help="Command line arguments to pass to ipcluster.") | |
1404 | ipcluster_subcommand = Unicode('start') |
|
1404 | ipcluster_subcommand = Unicode('start') | |
1405 | profile = Unicode('default') |
|
1405 | profile = Unicode('default') | |
1406 | n = Integer(2) |
|
1406 | n = Integer(2) | |
1407 |
|
1407 | |||
1408 | def find_args(self): |
|
1408 | def find_args(self): | |
1409 | return self.ipcluster_cmd + [self.ipcluster_subcommand] + \ |
|
1409 | return self.ipcluster_cmd + [self.ipcluster_subcommand] + \ | |
1410 | ['--n=%i'%self.n, '--profile=%s'%self.profile] + \ |
|
1410 | ['--n=%i'%self.n, '--profile=%s'%self.profile] + \ | |
1411 | self.ipcluster_args |
|
1411 | self.ipcluster_args | |
1412 |
|
1412 | |||
1413 | def start(self): |
|
1413 | def start(self): | |
1414 | return super(IPClusterLauncher, self).start() |
|
1414 | return super(IPClusterLauncher, self).start() | |
1415 |
|
1415 | |||
1416 | #----------------------------------------------------------------------------- |
|
1416 | #----------------------------------------------------------------------------- | |
1417 | # Collections of launchers |
|
1417 | # Collections of launchers | |
1418 | #----------------------------------------------------------------------------- |
|
1418 | #----------------------------------------------------------------------------- | |
1419 |
|
1419 | |||
1420 | local_launchers = [ |
|
1420 | local_launchers = [ | |
1421 | LocalControllerLauncher, |
|
1421 | LocalControllerLauncher, | |
1422 | LocalEngineLauncher, |
|
1422 | LocalEngineLauncher, | |
1423 | LocalEngineSetLauncher, |
|
1423 | LocalEngineSetLauncher, | |
1424 | ] |
|
1424 | ] | |
1425 | mpi_launchers = [ |
|
1425 | mpi_launchers = [ | |
1426 | MPILauncher, |
|
1426 | MPILauncher, | |
1427 | MPIControllerLauncher, |
|
1427 | MPIControllerLauncher, | |
1428 | MPIEngineSetLauncher, |
|
1428 | MPIEngineSetLauncher, | |
1429 | ] |
|
1429 | ] | |
1430 | ssh_launchers = [ |
|
1430 | ssh_launchers = [ | |
1431 | SSHLauncher, |
|
1431 | SSHLauncher, | |
1432 | SSHControllerLauncher, |
|
1432 | SSHControllerLauncher, | |
1433 | SSHEngineLauncher, |
|
1433 | SSHEngineLauncher, | |
1434 | SSHEngineSetLauncher, |
|
1434 | SSHEngineSetLauncher, | |
1435 | SSHProxyEngineSetLauncher, |
|
1435 | SSHProxyEngineSetLauncher, | |
1436 | ] |
|
1436 | ] | |
1437 | winhpc_launchers = [ |
|
1437 | winhpc_launchers = [ | |
1438 | WindowsHPCLauncher, |
|
1438 | WindowsHPCLauncher, | |
1439 | WindowsHPCControllerLauncher, |
|
1439 | WindowsHPCControllerLauncher, | |
1440 | WindowsHPCEngineSetLauncher, |
|
1440 | WindowsHPCEngineSetLauncher, | |
1441 | ] |
|
1441 | ] | |
1442 | pbs_launchers = [ |
|
1442 | pbs_launchers = [ | |
1443 | PBSLauncher, |
|
1443 | PBSLauncher, | |
1444 | PBSControllerLauncher, |
|
1444 | PBSControllerLauncher, | |
1445 | PBSEngineSetLauncher, |
|
1445 | PBSEngineSetLauncher, | |
1446 | ] |
|
1446 | ] | |
1447 | sge_launchers = [ |
|
1447 | sge_launchers = [ | |
1448 | SGELauncher, |
|
1448 | SGELauncher, | |
1449 | SGEControllerLauncher, |
|
1449 | SGEControllerLauncher, | |
1450 | SGEEngineSetLauncher, |
|
1450 | SGEEngineSetLauncher, | |
1451 | ] |
|
1451 | ] | |
1452 | lsf_launchers = [ |
|
1452 | lsf_launchers = [ | |
1453 | LSFLauncher, |
|
1453 | LSFLauncher, | |
1454 | LSFControllerLauncher, |
|
1454 | LSFControllerLauncher, | |
1455 | LSFEngineSetLauncher, |
|
1455 | LSFEngineSetLauncher, | |
1456 | ] |
|
1456 | ] | |
1457 | htcondor_launchers = [ |
|
1457 | htcondor_launchers = [ | |
1458 | HTCondorLauncher, |
|
1458 | HTCondorLauncher, | |
1459 | HTCondorControllerLauncher, |
|
1459 | HTCondorControllerLauncher, | |
1460 | HTCondorEngineSetLauncher, |
|
1460 | HTCondorEngineSetLauncher, | |
1461 | ] |
|
1461 | ] | |
1462 | all_launchers = local_launchers + mpi_launchers + ssh_launchers + winhpc_launchers\ |
|
1462 | all_launchers = local_launchers + mpi_launchers + ssh_launchers + winhpc_launchers\ | |
1463 | + pbs_launchers + sge_launchers + lsf_launchers + htcondor_launchers |
|
1463 | + pbs_launchers + sge_launchers + lsf_launchers + htcondor_launchers |
@@ -1,524 +1,524 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 | """IPython Test Suite Runner. |
|
2 | """IPython Test Suite Runner. | |
3 |
|
3 | |||
4 | This module provides a main entry point to a user script to test IPython |
|
4 | This module provides a main entry point to a user script to test IPython | |
5 | itself from the command line. There are two ways of running this script: |
|
5 | itself from the command line. There are two ways of running this script: | |
6 |
|
6 | |||
7 | 1. With the syntax `iptest all`. This runs our entire test suite by |
|
7 | 1. With the syntax `iptest all`. This runs our entire test suite by | |
8 | calling this script (with different arguments) recursively. This |
|
8 | calling this script (with different arguments) recursively. This | |
9 | causes modules and package to be tested in different processes, using nose |
|
9 | causes modules and package to be tested in different processes, using nose | |
10 | or trial where appropriate. |
|
10 | or trial where appropriate. | |
11 | 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form |
|
11 | 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form | |
12 | the script simply calls nose, but with special command line flags and |
|
12 | the script simply calls nose, but with special command line flags and | |
13 | plugins loaded. |
|
13 | plugins loaded. | |
14 |
|
14 | |||
15 | """ |
|
15 | """ | |
16 |
|
16 | |||
17 | #----------------------------------------------------------------------------- |
|
17 | #----------------------------------------------------------------------------- | |
18 | # Copyright (C) 2009-2011 The IPython Development Team |
|
18 | # Copyright (C) 2009-2011 The IPython Development Team | |
19 | # |
|
19 | # | |
20 | # Distributed under the terms of the BSD License. The full license is in |
|
20 | # Distributed under the terms of the BSD License. The full license is in | |
21 | # the file COPYING, distributed as part of this software. |
|
21 | # the file COPYING, distributed as part of this software. | |
22 | #----------------------------------------------------------------------------- |
|
22 | #----------------------------------------------------------------------------- | |
23 |
|
23 | |||
24 | #----------------------------------------------------------------------------- |
|
24 | #----------------------------------------------------------------------------- | |
25 | # Imports |
|
25 | # Imports | |
26 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
27 | from __future__ import print_function |
|
27 | from __future__ import print_function | |
28 |
|
28 | |||
29 | # Stdlib |
|
29 | # Stdlib | |
30 | import glob |
|
30 | import glob | |
31 | from io import BytesIO |
|
31 | from io import BytesIO | |
32 | import os |
|
32 | import os | |
33 | import os.path as path |
|
33 | import os.path as path | |
34 | import sys |
|
34 | import sys | |
35 | from threading import Thread, Lock, Event |
|
35 | from threading import Thread, Lock, Event | |
36 | import warnings |
|
36 | import warnings | |
37 |
|
37 | |||
38 | # Now, proceed to import nose itself |
|
38 | # Now, proceed to import nose itself | |
39 | import nose.plugins.builtin |
|
39 | import nose.plugins.builtin | |
40 | from nose.plugins.xunit import Xunit |
|
40 | from nose.plugins.xunit import Xunit | |
41 | from nose import SkipTest |
|
41 | from nose import SkipTest | |
42 | from nose.core import TestProgram |
|
42 | from nose.core import TestProgram | |
43 | from nose.plugins import Plugin |
|
43 | from nose.plugins import Plugin | |
44 | from nose.util import safe_str |
|
44 | from nose.util import safe_str | |
45 |
|
45 | |||
46 | # Our own imports |
|
46 | # Our own imports | |
47 | from IPython.utils.process import is_cmd_found |
|
47 | from IPython.utils.process import is_cmd_found | |
48 | from IPython.utils.importstring import import_item |
|
48 | from IPython.utils.importstring import import_item | |
49 | from IPython.testing.plugin.ipdoctest import IPythonDoctest |
|
49 | from IPython.testing.plugin.ipdoctest import IPythonDoctest | |
50 | from IPython.external.decorators import KnownFailure, knownfailureif |
|
50 | from IPython.external.decorators import KnownFailure, knownfailureif | |
51 |
|
51 | |||
52 | pjoin = path.join |
|
52 | pjoin = path.join | |
53 |
|
53 | |||
54 |
|
54 | |||
55 | #----------------------------------------------------------------------------- |
|
55 | #----------------------------------------------------------------------------- | |
56 | # Globals |
|
56 | # Globals | |
57 | #----------------------------------------------------------------------------- |
|
57 | #----------------------------------------------------------------------------- | |
58 |
|
58 | |||
59 |
|
59 | |||
60 | #----------------------------------------------------------------------------- |
|
60 | #----------------------------------------------------------------------------- | |
61 | # Warnings control |
|
61 | # Warnings control | |
62 | #----------------------------------------------------------------------------- |
|
62 | #----------------------------------------------------------------------------- | |
63 |
|
63 | |||
64 | # Twisted generates annoying warnings with Python 2.6, as will do other code |
|
64 | # Twisted generates annoying warnings with Python 2.6, as will do other code | |
65 | # that imports 'sets' as of today |
|
65 | # that imports 'sets' as of today | |
66 | warnings.filterwarnings('ignore', 'the sets module is deprecated', |
|
66 | warnings.filterwarnings('ignore', 'the sets module is deprecated', | |
67 | DeprecationWarning ) |
|
67 | DeprecationWarning ) | |
68 |
|
68 | |||
69 | # This one also comes from Twisted |
|
69 | # This one also comes from Twisted | |
70 | warnings.filterwarnings('ignore', 'the sha module is deprecated', |
|
70 | warnings.filterwarnings('ignore', 'the sha module is deprecated', | |
71 | DeprecationWarning) |
|
71 | DeprecationWarning) | |
72 |
|
72 | |||
73 | # Wx on Fedora11 spits these out |
|
73 | # Wx on Fedora11 spits these out | |
74 | warnings.filterwarnings('ignore', 'wxPython/wxWidgets release number mismatch', |
|
74 | warnings.filterwarnings('ignore', 'wxPython/wxWidgets release number mismatch', | |
75 | UserWarning) |
|
75 | UserWarning) | |
76 |
|
76 | |||
77 | # ------------------------------------------------------------------------------ |
|
77 | # ------------------------------------------------------------------------------ | |
78 | # Monkeypatch Xunit to count known failures as skipped. |
|
78 | # Monkeypatch Xunit to count known failures as skipped. | |
79 | # ------------------------------------------------------------------------------ |
|
79 | # ------------------------------------------------------------------------------ | |
80 | def monkeypatch_xunit(): |
|
80 | def monkeypatch_xunit(): | |
81 | try: |
|
81 | try: | |
82 | knownfailureif(True)(lambda: None)() |
|
82 | knownfailureif(True)(lambda: None)() | |
83 | except Exception as e: |
|
83 | except Exception as e: | |
84 | KnownFailureTest = type(e) |
|
84 | KnownFailureTest = type(e) | |
85 |
|
85 | |||
86 | def addError(self, test, err, capt=None): |
|
86 | def addError(self, test, err, capt=None): | |
87 | if issubclass(err[0], KnownFailureTest): |
|
87 | if issubclass(err[0], KnownFailureTest): | |
88 | err = (SkipTest,) + err[1:] |
|
88 | err = (SkipTest,) + err[1:] | |
89 | return self.orig_addError(test, err, capt) |
|
89 | return self.orig_addError(test, err, capt) | |
90 |
|
90 | |||
91 | Xunit.orig_addError = Xunit.addError |
|
91 | Xunit.orig_addError = Xunit.addError | |
92 | Xunit.addError = addError |
|
92 | Xunit.addError = addError | |
93 |
|
93 | |||
94 | #----------------------------------------------------------------------------- |
|
94 | #----------------------------------------------------------------------------- | |
95 | # Check which dependencies are installed and greater than minimum version. |
|
95 | # Check which dependencies are installed and greater than minimum version. | |
96 | #----------------------------------------------------------------------------- |
|
96 | #----------------------------------------------------------------------------- | |
97 | def extract_version(mod): |
|
97 | def extract_version(mod): | |
98 | return mod.__version__ |
|
98 | return mod.__version__ | |
99 |
|
99 | |||
100 | def test_for(item, min_version=None, callback=extract_version): |
|
100 | def test_for(item, min_version=None, callback=extract_version): | |
101 | """Test to see if item is importable, and optionally check against a minimum |
|
101 | """Test to see if item is importable, and optionally check against a minimum | |
102 | version. |
|
102 | version. | |
103 |
|
103 | |||
104 | If min_version is given, the default behavior is to check against the |
|
104 | If min_version is given, the default behavior is to check against the | |
105 | `__version__` attribute of the item, but specifying `callback` allows you to |
|
105 | `__version__` attribute of the item, but specifying `callback` allows you to | |
106 | extract the value you are interested in. e.g:: |
|
106 | extract the value you are interested in. e.g:: | |
107 |
|
107 | |||
108 | In [1]: import sys |
|
108 | In [1]: import sys | |
109 |
|
109 | |||
110 | In [2]: from IPython.testing.iptest import test_for |
|
110 | In [2]: from IPython.testing.iptest import test_for | |
111 |
|
111 | |||
112 | In [3]: test_for('sys', (2,6), callback=lambda sys: sys.version_info) |
|
112 | In [3]: test_for('sys', (2,6), callback=lambda sys: sys.version_info) | |
113 | Out[3]: True |
|
113 | Out[3]: True | |
114 |
|
114 | |||
115 | """ |
|
115 | """ | |
116 | try: |
|
116 | try: | |
117 | check = import_item(item) |
|
117 | check = import_item(item) | |
118 | except (ImportError, RuntimeError): |
|
118 | except (ImportError, RuntimeError): | |
119 | # GTK reports Runtime error if it can't be initialized even if it's |
|
119 | # GTK reports Runtime error if it can't be initialized even if it's | |
120 | # importable. |
|
120 | # importable. | |
121 | return False |
|
121 | return False | |
122 | else: |
|
122 | else: | |
123 | if min_version: |
|
123 | if min_version: | |
124 | if callback: |
|
124 | if callback: | |
125 | # extra processing step to get version to compare |
|
125 | # extra processing step to get version to compare | |
126 | check = callback(check) |
|
126 | check = callback(check) | |
127 |
|
127 | |||
128 | return check >= min_version |
|
128 | return check >= min_version | |
129 | else: |
|
129 | else: | |
130 | return True |
|
130 | return True | |
131 |
|
131 | |||
132 | # Global dict where we can store information on what we have and what we don't |
|
132 | # Global dict where we can store information on what we have and what we don't | |
133 | # have available at test run time |
|
133 | # have available at test run time | |
134 | have = {} |
|
134 | have = {} | |
135 |
|
135 | |||
136 | have['curses'] = test_for('_curses') |
|
136 | have['curses'] = test_for('_curses') | |
137 | have['matplotlib'] = test_for('matplotlib') |
|
137 | have['matplotlib'] = test_for('matplotlib') | |
138 | have['numpy'] = test_for('numpy') |
|
138 | have['numpy'] = test_for('numpy') | |
139 | have['pexpect'] = test_for('IPython.external.pexpect') |
|
139 | have['pexpect'] = test_for('IPython.external.pexpect') | |
140 | have['pymongo'] = test_for('pymongo') |
|
140 | have['pymongo'] = test_for('pymongo') | |
141 | have['pygments'] = test_for('pygments') |
|
141 | have['pygments'] = test_for('pygments') | |
142 | have['qt'] = test_for('IPython.external.qt') |
|
142 | have['qt'] = test_for('IPython.external.qt') | |
143 | have['rpy2'] = test_for('rpy2') |
|
143 | have['rpy2'] = test_for('rpy2') | |
144 | have['sqlite3'] = test_for('sqlite3') |
|
144 | have['sqlite3'] = test_for('sqlite3') | |
145 | have['cython'] = test_for('Cython') |
|
145 | have['cython'] = test_for('Cython') | |
146 | have['oct2py'] = test_for('oct2py') |
|
146 | have['oct2py'] = test_for('oct2py') | |
147 | have['tornado'] = test_for('tornado.version_info', (3,1,0), callback=None) |
|
147 | have['tornado'] = test_for('tornado.version_info', (3,1,0), callback=None) | |
148 | have['jinja2'] = test_for('jinja2') |
|
148 | have['jinja2'] = test_for('jinja2') | |
149 | have['requests'] = test_for('requests') |
|
149 | have['requests'] = test_for('requests') | |
150 | have['sphinx'] = test_for('sphinx') |
|
150 | have['sphinx'] = test_for('sphinx') | |
151 | have['casperjs'] = is_cmd_found('casperjs') |
|
151 | have['casperjs'] = is_cmd_found('casperjs') | |
152 |
|
152 | |||
153 | min_zmq = (2,1,11) |
|
153 | min_zmq = (2,1,11) | |
154 |
|
154 | |||
155 | have['zmq'] = test_for('zmq.pyzmq_version_info', min_zmq, callback=lambda x: x()) |
|
155 | have['zmq'] = test_for('zmq.pyzmq_version_info', min_zmq, callback=lambda x: x()) | |
156 |
|
156 | |||
157 | #----------------------------------------------------------------------------- |
|
157 | #----------------------------------------------------------------------------- | |
158 | # Test suite definitions |
|
158 | # Test suite definitions | |
159 | #----------------------------------------------------------------------------- |
|
159 | #----------------------------------------------------------------------------- | |
160 |
|
160 | |||
161 | test_group_names = ['parallel', 'kernel', 'kernel.inprocess', 'config', 'core', |
|
161 | test_group_names = ['parallel', 'kernel', 'kernel.inprocess', 'config', 'core', | |
162 | 'extensions', 'lib', 'terminal', 'testing', 'utils', |
|
162 | 'extensions', 'lib', 'terminal', 'testing', 'utils', | |
163 | 'nbformat', 'qt', 'html', 'nbconvert' |
|
163 | 'nbformat', 'qt', 'html', 'nbconvert' | |
164 | ] |
|
164 | ] | |
165 |
|
165 | |||
166 | class TestSection(object): |
|
166 | class TestSection(object): | |
167 | def __init__(self, name, includes): |
|
167 | def __init__(self, name, includes): | |
168 | self.name = name |
|
168 | self.name = name | |
169 | self.includes = includes |
|
169 | self.includes = includes | |
170 | self.excludes = [] |
|
170 | self.excludes = [] | |
171 | self.dependencies = [] |
|
171 | self.dependencies = [] | |
172 | self.enabled = True |
|
172 | self.enabled = True | |
173 |
|
173 | |||
174 | def exclude(self, module): |
|
174 | def exclude(self, module): | |
175 | if not module.startswith('IPython'): |
|
175 | if not module.startswith('IPython'): | |
176 | module = self.includes[0] + "." + module |
|
176 | module = self.includes[0] + "." + module | |
177 | self.excludes.append(module.replace('.', os.sep)) |
|
177 | self.excludes.append(module.replace('.', os.sep)) | |
178 |
|
178 | |||
179 | def requires(self, *packages): |
|
179 | def requires(self, *packages): | |
180 | self.dependencies.extend(packages) |
|
180 | self.dependencies.extend(packages) | |
181 |
|
181 | |||
182 | @property |
|
182 | @property | |
183 | def will_run(self): |
|
183 | def will_run(self): | |
184 | return self.enabled and all(have[p] for p in self.dependencies) |
|
184 | return self.enabled and all(have[p] for p in self.dependencies) | |
185 |
|
185 | |||
186 | # Name -> (include, exclude, dependencies_met) |
|
186 | # Name -> (include, exclude, dependencies_met) | |
187 | test_sections = {n:TestSection(n, ['IPython.%s' % n]) for n in test_group_names} |
|
187 | test_sections = {n:TestSection(n, ['IPython.%s' % n]) for n in test_group_names} | |
188 |
|
188 | |||
189 | # Exclusions and dependencies |
|
189 | # Exclusions and dependencies | |
190 | # --------------------------- |
|
190 | # --------------------------- | |
191 |
|
191 | |||
192 | # core: |
|
192 | # core: | |
193 | sec = test_sections['core'] |
|
193 | sec = test_sections['core'] | |
194 | if not have['sqlite3']: |
|
194 | if not have['sqlite3']: | |
195 | sec.exclude('tests.test_history') |
|
195 | sec.exclude('tests.test_history') | |
196 | sec.exclude('history') |
|
196 | sec.exclude('history') | |
197 | if not have['matplotlib']: |
|
197 | if not have['matplotlib']: | |
198 | sec.exclude('pylabtools'), |
|
198 | sec.exclude('pylabtools'), | |
199 | sec.exclude('tests.test_pylabtools') |
|
199 | sec.exclude('tests.test_pylabtools') | |
200 |
|
200 | |||
201 | # lib: |
|
201 | # lib: | |
202 | sec = test_sections['lib'] |
|
202 | sec = test_sections['lib'] | |
203 | if not have['zmq']: |
|
203 | if not have['zmq']: | |
204 | sec.exclude('kernel') |
|
204 | sec.exclude('kernel') | |
205 | # We do this unconditionally, so that the test suite doesn't import |
|
205 | # We do this unconditionally, so that the test suite doesn't import | |
206 | # gtk, changing the default encoding and masking some unicode bugs. |
|
206 | # gtk, changing the default encoding and masking some unicode bugs. | |
207 | sec.exclude('inputhookgtk') |
|
207 | sec.exclude('inputhookgtk') | |
208 | # We also do this unconditionally, because wx can interfere with Unix signals. |
|
208 | # We also do this unconditionally, because wx can interfere with Unix signals. | |
209 | # There are currently no tests for it anyway. |
|
209 | # There are currently no tests for it anyway. | |
210 | sec.exclude('inputhookwx') |
|
210 | sec.exclude('inputhookwx') | |
211 | # Testing inputhook will need a lot of thought, to figure out |
|
211 | # Testing inputhook will need a lot of thought, to figure out | |
212 | # how to have tests that don't lock up with the gui event |
|
212 | # how to have tests that don't lock up with the gui event | |
213 | # loops in the picture |
|
213 | # loops in the picture | |
214 | sec.exclude('inputhook') |
|
214 | sec.exclude('inputhook') | |
215 |
|
215 | |||
216 | # testing: |
|
216 | # testing: | |
217 | sec = test_sections['testing'] |
|
217 | sec = test_sections['testing'] | |
218 | # These have to be skipped on win32 because they use echo, rm, cd, etc. |
|
218 | # These have to be skipped on win32 because they use echo, rm, cd, etc. | |
219 | # See ticket https://github.com/ipython/ipython/issues/87 |
|
219 | # See ticket https://github.com/ipython/ipython/issues/87 | |
220 | if sys.platform == 'win32': |
|
220 | if sys.platform == 'win32': | |
221 | sec.exclude('plugin.test_exampleip') |
|
221 | sec.exclude('plugin.test_exampleip') | |
222 | sec.exclude('plugin.dtexample') |
|
222 | sec.exclude('plugin.dtexample') | |
223 |
|
223 | |||
224 | # terminal: |
|
224 | # terminal: | |
225 | if (not have['pexpect']) or (not have['zmq']): |
|
225 | if (not have['pexpect']) or (not have['zmq']): | |
226 | test_sections['terminal'].exclude('console') |
|
226 | test_sections['terminal'].exclude('console') | |
227 |
|
227 | |||
228 | # parallel |
|
228 | # parallel | |
229 | sec = test_sections['parallel'] |
|
229 | sec = test_sections['parallel'] | |
230 | sec.requires('zmq') |
|
230 | sec.requires('zmq') | |
231 | if not have['pymongo']: |
|
231 | if not have['pymongo']: | |
232 | sec.exclude('controller.mongodb') |
|
232 | sec.exclude('controller.mongodb') | |
233 | sec.exclude('tests.test_mongodb') |
|
233 | sec.exclude('tests.test_mongodb') | |
234 |
|
234 | |||
235 | # kernel: |
|
235 | # kernel: | |
236 | sec = test_sections['kernel'] |
|
236 | sec = test_sections['kernel'] | |
237 | sec.requires('zmq') |
|
237 | sec.requires('zmq') | |
238 | # The in-process kernel tests are done in a separate section |
|
238 | # The in-process kernel tests are done in a separate section | |
239 | sec.exclude('inprocess') |
|
239 | sec.exclude('inprocess') | |
240 | # importing gtk sets the default encoding, which we want to avoid |
|
240 | # importing gtk sets the default encoding, which we want to avoid | |
241 | sec.exclude('zmq.gui.gtkembed') |
|
241 | sec.exclude('zmq.gui.gtkembed') | |
242 | if not have['matplotlib']: |
|
242 | if not have['matplotlib']: | |
243 | sec.exclude('zmq.pylab') |
|
243 | sec.exclude('zmq.pylab') | |
244 |
|
244 | |||
245 | # kernel.inprocess: |
|
245 | # kernel.inprocess: | |
246 | test_sections['kernel.inprocess'].requires('zmq') |
|
246 | test_sections['kernel.inprocess'].requires('zmq') | |
247 |
|
247 | |||
248 | # extensions: |
|
248 | # extensions: | |
249 | sec = test_sections['extensions'] |
|
249 | sec = test_sections['extensions'] | |
250 | if not have['cython']: |
|
250 | if not have['cython']: | |
251 | sec.exclude('cythonmagic') |
|
251 | sec.exclude('cythonmagic') | |
252 | sec.exclude('tests.test_cythonmagic') |
|
252 | sec.exclude('tests.test_cythonmagic') | |
253 | if not have['oct2py']: |
|
253 | if not have['oct2py']: | |
254 | sec.exclude('octavemagic') |
|
254 | sec.exclude('octavemagic') | |
255 | sec.exclude('tests.test_octavemagic') |
|
255 | sec.exclude('tests.test_octavemagic') | |
256 | if not have['rpy2'] or not have['numpy']: |
|
256 | if not have['rpy2'] or not have['numpy']: | |
257 | sec.exclude('rmagic') |
|
257 | sec.exclude('rmagic') | |
258 | sec.exclude('tests.test_rmagic') |
|
258 | sec.exclude('tests.test_rmagic') | |
259 | # autoreload does some strange stuff, so move it to its own test section |
|
259 | # autoreload does some strange stuff, so move it to its own test section | |
260 | sec.exclude('autoreload') |
|
260 | sec.exclude('autoreload') | |
261 | sec.exclude('tests.test_autoreload') |
|
261 | sec.exclude('tests.test_autoreload') | |
262 | test_sections['autoreload'] = TestSection('autoreload', |
|
262 | test_sections['autoreload'] = TestSection('autoreload', | |
263 | ['IPython.extensions.autoreload', 'IPython.extensions.tests.test_autoreload']) |
|
263 | ['IPython.extensions.autoreload', 'IPython.extensions.tests.test_autoreload']) | |
264 | test_group_names.append('autoreload') |
|
264 | test_group_names.append('autoreload') | |
265 |
|
265 | |||
266 | # qt: |
|
266 | # qt: | |
267 | test_sections['qt'].requires('zmq', 'qt', 'pygments') |
|
267 | test_sections['qt'].requires('zmq', 'qt', 'pygments') | |
268 |
|
268 | |||
269 | # html: |
|
269 | # html: | |
270 | sec = test_sections['html'] |
|
270 | sec = test_sections['html'] | |
271 | sec.requires('zmq', 'tornado', 'requests') |
|
271 | sec.requires('zmq', 'tornado', 'requests', 'sqlite3') | |
272 | # The notebook 'static' directory contains JS, css and other |
|
272 | # The notebook 'static' directory contains JS, css and other | |
273 | # files for web serving. Occasionally projects may put a .py |
|
273 | # files for web serving. Occasionally projects may put a .py | |
274 | # file in there (MathJax ships a conf.py), so we might as |
|
274 | # file in there (MathJax ships a conf.py), so we might as | |
275 | # well play it safe and skip the whole thing. |
|
275 | # well play it safe and skip the whole thing. | |
276 | sec.exclude('static') |
|
276 | sec.exclude('static') | |
277 | sec.exclude('fabfile') |
|
277 | sec.exclude('fabfile') | |
278 | if not have['jinja2']: |
|
278 | if not have['jinja2']: | |
279 | sec.exclude('notebookapp') |
|
279 | sec.exclude('notebookapp') | |
280 | if not have['pygments'] or not have['jinja2']: |
|
280 | if not have['pygments'] or not have['jinja2']: | |
281 | sec.exclude('nbconvert') |
|
281 | sec.exclude('nbconvert') | |
282 |
|
282 | |||
283 | # config: |
|
283 | # config: | |
284 | # Config files aren't really importable stand-alone |
|
284 | # Config files aren't really importable stand-alone | |
285 | test_sections['config'].exclude('profile') |
|
285 | test_sections['config'].exclude('profile') | |
286 |
|
286 | |||
287 | # nbconvert: |
|
287 | # nbconvert: | |
288 | sec = test_sections['nbconvert'] |
|
288 | sec = test_sections['nbconvert'] | |
289 | sec.requires('pygments', 'jinja2') |
|
289 | sec.requires('pygments', 'jinja2') | |
290 | # Exclude nbconvert directories containing config files used to test. |
|
290 | # Exclude nbconvert directories containing config files used to test. | |
291 | # Executing the config files with iptest would cause an exception. |
|
291 | # Executing the config files with iptest would cause an exception. | |
292 | sec.exclude('tests.files') |
|
292 | sec.exclude('tests.files') | |
293 | sec.exclude('exporters.tests.files') |
|
293 | sec.exclude('exporters.tests.files') | |
294 | if not have['tornado']: |
|
294 | if not have['tornado']: | |
295 | sec.exclude('nbconvert.post_processors.serve') |
|
295 | sec.exclude('nbconvert.post_processors.serve') | |
296 | sec.exclude('nbconvert.post_processors.tests.test_serve') |
|
296 | sec.exclude('nbconvert.post_processors.tests.test_serve') | |
297 |
|
297 | |||
298 | #----------------------------------------------------------------------------- |
|
298 | #----------------------------------------------------------------------------- | |
299 | # Functions and classes |
|
299 | # Functions and classes | |
300 | #----------------------------------------------------------------------------- |
|
300 | #----------------------------------------------------------------------------- | |
301 |
|
301 | |||
302 | def check_exclusions_exist(): |
|
302 | def check_exclusions_exist(): | |
303 | from IPython.utils.path import get_ipython_package_dir |
|
303 | from IPython.utils.path import get_ipython_package_dir | |
304 | from IPython.utils.warn import warn |
|
304 | from IPython.utils.warn import warn | |
305 | parent = os.path.dirname(get_ipython_package_dir()) |
|
305 | parent = os.path.dirname(get_ipython_package_dir()) | |
306 | for sec in test_sections: |
|
306 | for sec in test_sections: | |
307 | for pattern in sec.exclusions: |
|
307 | for pattern in sec.exclusions: | |
308 | fullpath = pjoin(parent, pattern) |
|
308 | fullpath = pjoin(parent, pattern) | |
309 | if not os.path.exists(fullpath) and not glob.glob(fullpath + '.*'): |
|
309 | if not os.path.exists(fullpath) and not glob.glob(fullpath + '.*'): | |
310 | warn("Excluding nonexistent file: %r" % pattern) |
|
310 | warn("Excluding nonexistent file: %r" % pattern) | |
311 |
|
311 | |||
312 |
|
312 | |||
313 | class ExclusionPlugin(Plugin): |
|
313 | class ExclusionPlugin(Plugin): | |
314 | """A nose plugin to effect our exclusions of files and directories. |
|
314 | """A nose plugin to effect our exclusions of files and directories. | |
315 | """ |
|
315 | """ | |
316 | name = 'exclusions' |
|
316 | name = 'exclusions' | |
317 | score = 3000 # Should come before any other plugins |
|
317 | score = 3000 # Should come before any other plugins | |
318 |
|
318 | |||
319 | def __init__(self, exclude_patterns=None): |
|
319 | def __init__(self, exclude_patterns=None): | |
320 | """ |
|
320 | """ | |
321 | Parameters |
|
321 | Parameters | |
322 | ---------- |
|
322 | ---------- | |
323 |
|
323 | |||
324 | exclude_patterns : sequence of strings, optional |
|
324 | exclude_patterns : sequence of strings, optional | |
325 | Filenames containing these patterns (as raw strings, not as regular |
|
325 | Filenames containing these patterns (as raw strings, not as regular | |
326 | expressions) are excluded from the tests. |
|
326 | expressions) are excluded from the tests. | |
327 | """ |
|
327 | """ | |
328 | self.exclude_patterns = exclude_patterns or [] |
|
328 | self.exclude_patterns = exclude_patterns or [] | |
329 | super(ExclusionPlugin, self).__init__() |
|
329 | super(ExclusionPlugin, self).__init__() | |
330 |
|
330 | |||
331 | def options(self, parser, env=os.environ): |
|
331 | def options(self, parser, env=os.environ): | |
332 | Plugin.options(self, parser, env) |
|
332 | Plugin.options(self, parser, env) | |
333 |
|
333 | |||
334 | def configure(self, options, config): |
|
334 | def configure(self, options, config): | |
335 | Plugin.configure(self, options, config) |
|
335 | Plugin.configure(self, options, config) | |
336 | # Override nose trying to disable plugin. |
|
336 | # Override nose trying to disable plugin. | |
337 | self.enabled = True |
|
337 | self.enabled = True | |
338 |
|
338 | |||
339 | def wantFile(self, filename): |
|
339 | def wantFile(self, filename): | |
340 | """Return whether the given filename should be scanned for tests. |
|
340 | """Return whether the given filename should be scanned for tests. | |
341 | """ |
|
341 | """ | |
342 | if any(pat in filename for pat in self.exclude_patterns): |
|
342 | if any(pat in filename for pat in self.exclude_patterns): | |
343 | return False |
|
343 | return False | |
344 | return None |
|
344 | return None | |
345 |
|
345 | |||
346 | def wantDirectory(self, directory): |
|
346 | def wantDirectory(self, directory): | |
347 | """Return whether the given directory should be scanned for tests. |
|
347 | """Return whether the given directory should be scanned for tests. | |
348 | """ |
|
348 | """ | |
349 | if any(pat in directory for pat in self.exclude_patterns): |
|
349 | if any(pat in directory for pat in self.exclude_patterns): | |
350 | return False |
|
350 | return False | |
351 | return None |
|
351 | return None | |
352 |
|
352 | |||
353 |
|
353 | |||
354 | class StreamCapturer(Thread): |
|
354 | class StreamCapturer(Thread): | |
355 | daemon = True # Don't hang if main thread crashes |
|
355 | daemon = True # Don't hang if main thread crashes | |
356 | started = False |
|
356 | started = False | |
357 | def __init__(self): |
|
357 | def __init__(self): | |
358 | super(StreamCapturer, self).__init__() |
|
358 | super(StreamCapturer, self).__init__() | |
359 | self.streams = [] |
|
359 | self.streams = [] | |
360 | self.buffer = BytesIO() |
|
360 | self.buffer = BytesIO() | |
361 | self.readfd, self.writefd = os.pipe() |
|
361 | self.readfd, self.writefd = os.pipe() | |
362 | self.buffer_lock = Lock() |
|
362 | self.buffer_lock = Lock() | |
363 | self.stop = Event() |
|
363 | self.stop = Event() | |
364 |
|
364 | |||
365 | def run(self): |
|
365 | def run(self): | |
366 | self.started = True |
|
366 | self.started = True | |
367 |
|
367 | |||
368 | while not self.stop.is_set(): |
|
368 | while not self.stop.is_set(): | |
369 | chunk = os.read(self.readfd, 1024) |
|
369 | chunk = os.read(self.readfd, 1024) | |
370 |
|
370 | |||
371 | with self.buffer_lock: |
|
371 | with self.buffer_lock: | |
372 | self.buffer.write(chunk) |
|
372 | self.buffer.write(chunk) | |
373 |
|
373 | |||
374 | os.close(self.readfd) |
|
374 | os.close(self.readfd) | |
375 | os.close(self.writefd) |
|
375 | os.close(self.writefd) | |
376 |
|
376 | |||
377 | def reset_buffer(self): |
|
377 | def reset_buffer(self): | |
378 | with self.buffer_lock: |
|
378 | with self.buffer_lock: | |
379 | self.buffer.truncate(0) |
|
379 | self.buffer.truncate(0) | |
380 | self.buffer.seek(0) |
|
380 | self.buffer.seek(0) | |
381 |
|
381 | |||
382 | def get_buffer(self): |
|
382 | def get_buffer(self): | |
383 | with self.buffer_lock: |
|
383 | with self.buffer_lock: | |
384 | return self.buffer.getvalue() |
|
384 | return self.buffer.getvalue() | |
385 |
|
385 | |||
386 | def ensure_started(self): |
|
386 | def ensure_started(self): | |
387 | if not self.started: |
|
387 | if not self.started: | |
388 | self.start() |
|
388 | self.start() | |
389 |
|
389 | |||
390 | def halt(self): |
|
390 | def halt(self): | |
391 | """Safely stop the thread.""" |
|
391 | """Safely stop the thread.""" | |
392 | if not self.started: |
|
392 | if not self.started: | |
393 | return |
|
393 | return | |
394 |
|
394 | |||
395 | self.stop.set() |
|
395 | self.stop.set() | |
396 | os.write(self.writefd, b'wake up') # Ensure we're not locked in a read() |
|
396 | os.write(self.writefd, b'wake up') # Ensure we're not locked in a read() | |
397 | self.join() |
|
397 | self.join() | |
398 |
|
398 | |||
399 | class SubprocessStreamCapturePlugin(Plugin): |
|
399 | class SubprocessStreamCapturePlugin(Plugin): | |
400 | name='subprocstreams' |
|
400 | name='subprocstreams' | |
401 | def __init__(self): |
|
401 | def __init__(self): | |
402 | Plugin.__init__(self) |
|
402 | Plugin.__init__(self) | |
403 | self.stream_capturer = StreamCapturer() |
|
403 | self.stream_capturer = StreamCapturer() | |
404 | self.destination = os.environ.get('IPTEST_SUBPROC_STREAMS', 'capture') |
|
404 | self.destination = os.environ.get('IPTEST_SUBPROC_STREAMS', 'capture') | |
405 | # This is ugly, but distant parts of the test machinery need to be able |
|
405 | # This is ugly, but distant parts of the test machinery need to be able | |
406 | # to redirect streams, so we make the object globally accessible. |
|
406 | # to redirect streams, so we make the object globally accessible. | |
407 | nose.iptest_stdstreams_fileno = self.get_write_fileno |
|
407 | nose.iptest_stdstreams_fileno = self.get_write_fileno | |
408 |
|
408 | |||
409 | def get_write_fileno(self): |
|
409 | def get_write_fileno(self): | |
410 | if self.destination == 'capture': |
|
410 | if self.destination == 'capture': | |
411 | self.stream_capturer.ensure_started() |
|
411 | self.stream_capturer.ensure_started() | |
412 | return self.stream_capturer.writefd |
|
412 | return self.stream_capturer.writefd | |
413 | elif self.destination == 'discard': |
|
413 | elif self.destination == 'discard': | |
414 | return os.open(os.devnull, os.O_WRONLY) |
|
414 | return os.open(os.devnull, os.O_WRONLY) | |
415 | else: |
|
415 | else: | |
416 | return sys.__stdout__.fileno() |
|
416 | return sys.__stdout__.fileno() | |
417 |
|
417 | |||
418 | def configure(self, options, config): |
|
418 | def configure(self, options, config): | |
419 | Plugin.configure(self, options, config) |
|
419 | Plugin.configure(self, options, config) | |
420 | # Override nose trying to disable plugin. |
|
420 | # Override nose trying to disable plugin. | |
421 | if self.destination == 'capture': |
|
421 | if self.destination == 'capture': | |
422 | self.enabled = True |
|
422 | self.enabled = True | |
423 |
|
423 | |||
424 | def startTest(self, test): |
|
424 | def startTest(self, test): | |
425 | # Reset log capture |
|
425 | # Reset log capture | |
426 | self.stream_capturer.reset_buffer() |
|
426 | self.stream_capturer.reset_buffer() | |
427 |
|
427 | |||
428 | def formatFailure(self, test, err): |
|
428 | def formatFailure(self, test, err): | |
429 | # Show output |
|
429 | # Show output | |
430 | ec, ev, tb = err |
|
430 | ec, ev, tb = err | |
431 | captured = self.stream_capturer.get_buffer().decode('utf-8', 'replace') |
|
431 | captured = self.stream_capturer.get_buffer().decode('utf-8', 'replace') | |
432 | if captured.strip(): |
|
432 | if captured.strip(): | |
433 | ev = safe_str(ev) |
|
433 | ev = safe_str(ev) | |
434 | out = [ev, '>> begin captured subprocess output <<', |
|
434 | out = [ev, '>> begin captured subprocess output <<', | |
435 | captured, |
|
435 | captured, | |
436 | '>> end captured subprocess output <<'] |
|
436 | '>> end captured subprocess output <<'] | |
437 | return ec, '\n'.join(out), tb |
|
437 | return ec, '\n'.join(out), tb | |
438 |
|
438 | |||
439 | return err |
|
439 | return err | |
440 |
|
440 | |||
441 | formatError = formatFailure |
|
441 | formatError = formatFailure | |
442 |
|
442 | |||
443 | def finalize(self, result): |
|
443 | def finalize(self, result): | |
444 | self.stream_capturer.halt() |
|
444 | self.stream_capturer.halt() | |
445 |
|
445 | |||
446 |
|
446 | |||
447 | def run_iptest(): |
|
447 | def run_iptest(): | |
448 | """Run the IPython test suite using nose. |
|
448 | """Run the IPython test suite using nose. | |
449 |
|
449 | |||
450 | This function is called when this script is **not** called with the form |
|
450 | This function is called when this script is **not** called with the form | |
451 | `iptest all`. It simply calls nose with appropriate command line flags |
|
451 | `iptest all`. It simply calls nose with appropriate command line flags | |
452 | and accepts all of the standard nose arguments. |
|
452 | and accepts all of the standard nose arguments. | |
453 | """ |
|
453 | """ | |
454 | # Apply our monkeypatch to Xunit |
|
454 | # Apply our monkeypatch to Xunit | |
455 | if '--with-xunit' in sys.argv and not hasattr(Xunit, 'orig_addError'): |
|
455 | if '--with-xunit' in sys.argv and not hasattr(Xunit, 'orig_addError'): | |
456 | monkeypatch_xunit() |
|
456 | monkeypatch_xunit() | |
457 |
|
457 | |||
458 | warnings.filterwarnings('ignore', |
|
458 | warnings.filterwarnings('ignore', | |
459 | 'This will be removed soon. Use IPython.testing.util instead') |
|
459 | 'This will be removed soon. Use IPython.testing.util instead') | |
460 |
|
460 | |||
461 | arg1 = sys.argv[1] |
|
461 | arg1 = sys.argv[1] | |
462 | if arg1 in test_sections: |
|
462 | if arg1 in test_sections: | |
463 | section = test_sections[arg1] |
|
463 | section = test_sections[arg1] | |
464 | sys.argv[1:2] = section.includes |
|
464 | sys.argv[1:2] = section.includes | |
465 | elif arg1.startswith('IPython.') and arg1[8:] in test_sections: |
|
465 | elif arg1.startswith('IPython.') and arg1[8:] in test_sections: | |
466 | section = test_sections[arg1[8:]] |
|
466 | section = test_sections[arg1[8:]] | |
467 | sys.argv[1:2] = section.includes |
|
467 | sys.argv[1:2] = section.includes | |
468 | else: |
|
468 | else: | |
469 | section = TestSection(arg1, includes=[arg1]) |
|
469 | section = TestSection(arg1, includes=[arg1]) | |
470 |
|
470 | |||
471 |
|
471 | |||
472 | argv = sys.argv + [ '--detailed-errors', # extra info in tracebacks |
|
472 | argv = sys.argv + [ '--detailed-errors', # extra info in tracebacks | |
473 |
|
473 | |||
474 | '--with-ipdoctest', |
|
474 | '--with-ipdoctest', | |
475 | '--ipdoctest-tests','--ipdoctest-extension=txt', |
|
475 | '--ipdoctest-tests','--ipdoctest-extension=txt', | |
476 |
|
476 | |||
477 | # We add --exe because of setuptools' imbecility (it |
|
477 | # We add --exe because of setuptools' imbecility (it | |
478 | # blindly does chmod +x on ALL files). Nose does the |
|
478 | # blindly does chmod +x on ALL files). Nose does the | |
479 | # right thing and it tries to avoid executables, |
|
479 | # right thing and it tries to avoid executables, | |
480 | # setuptools unfortunately forces our hand here. This |
|
480 | # setuptools unfortunately forces our hand here. This | |
481 | # has been discussed on the distutils list and the |
|
481 | # has been discussed on the distutils list and the | |
482 | # setuptools devs refuse to fix this problem! |
|
482 | # setuptools devs refuse to fix this problem! | |
483 | '--exe', |
|
483 | '--exe', | |
484 | ] |
|
484 | ] | |
485 | if '-a' not in argv and '-A' not in argv: |
|
485 | if '-a' not in argv and '-A' not in argv: | |
486 | argv = argv + ['-a', '!crash'] |
|
486 | argv = argv + ['-a', '!crash'] | |
487 |
|
487 | |||
488 | if nose.__version__ >= '0.11': |
|
488 | if nose.__version__ >= '0.11': | |
489 | # I don't fully understand why we need this one, but depending on what |
|
489 | # I don't fully understand why we need this one, but depending on what | |
490 | # directory the test suite is run from, if we don't give it, 0 tests |
|
490 | # directory the test suite is run from, if we don't give it, 0 tests | |
491 | # get run. Specifically, if the test suite is run from the source dir |
|
491 | # get run. Specifically, if the test suite is run from the source dir | |
492 | # with an argument (like 'iptest.py IPython.core', 0 tests are run, |
|
492 | # with an argument (like 'iptest.py IPython.core', 0 tests are run, | |
493 | # even if the same call done in this directory works fine). It appears |
|
493 | # even if the same call done in this directory works fine). It appears | |
494 | # that if the requested package is in the current dir, nose bails early |
|
494 | # that if the requested package is in the current dir, nose bails early | |
495 | # by default. Since it's otherwise harmless, leave it in by default |
|
495 | # by default. Since it's otherwise harmless, leave it in by default | |
496 | # for nose >= 0.11, though unfortunately nose 0.10 doesn't support it. |
|
496 | # for nose >= 0.11, though unfortunately nose 0.10 doesn't support it. | |
497 | argv.append('--traverse-namespace') |
|
497 | argv.append('--traverse-namespace') | |
498 |
|
498 | |||
499 | # use our plugin for doctesting. It will remove the standard doctest plugin |
|
499 | # use our plugin for doctesting. It will remove the standard doctest plugin | |
500 | # if it finds it enabled |
|
500 | # if it finds it enabled | |
501 | plugins = [ExclusionPlugin(section.excludes), IPythonDoctest(), KnownFailure(), |
|
501 | plugins = [ExclusionPlugin(section.excludes), IPythonDoctest(), KnownFailure(), | |
502 | SubprocessStreamCapturePlugin() ] |
|
502 | SubprocessStreamCapturePlugin() ] | |
503 |
|
503 | |||
504 | # Use working directory set by parent process (see iptestcontroller) |
|
504 | # Use working directory set by parent process (see iptestcontroller) | |
505 | if 'IPTEST_WORKING_DIR' in os.environ: |
|
505 | if 'IPTEST_WORKING_DIR' in os.environ: | |
506 | os.chdir(os.environ['IPTEST_WORKING_DIR']) |
|
506 | os.chdir(os.environ['IPTEST_WORKING_DIR']) | |
507 |
|
507 | |||
508 | # We need a global ipython running in this process, but the special |
|
508 | # We need a global ipython running in this process, but the special | |
509 | # in-process group spawns its own IPython kernels, so for *that* group we |
|
509 | # in-process group spawns its own IPython kernels, so for *that* group we | |
510 | # must avoid also opening the global one (otherwise there's a conflict of |
|
510 | # must avoid also opening the global one (otherwise there's a conflict of | |
511 | # singletons). Ultimately the solution to this problem is to refactor our |
|
511 | # singletons). Ultimately the solution to this problem is to refactor our | |
512 | # assumptions about what needs to be a singleton and what doesn't (app |
|
512 | # assumptions about what needs to be a singleton and what doesn't (app | |
513 | # objects should, individual shells shouldn't). But for now, this |
|
513 | # objects should, individual shells shouldn't). But for now, this | |
514 | # workaround allows the test suite for the inprocess module to complete. |
|
514 | # workaround allows the test suite for the inprocess module to complete. | |
515 | if 'kernel.inprocess' not in section.name: |
|
515 | if 'kernel.inprocess' not in section.name: | |
516 | from IPython.testing import globalipapp |
|
516 | from IPython.testing import globalipapp | |
517 | globalipapp.start_ipython() |
|
517 | globalipapp.start_ipython() | |
518 |
|
518 | |||
519 | # Now nose can run |
|
519 | # Now nose can run | |
520 | TestProgram(argv=argv, addplugins=plugins) |
|
520 | TestProgram(argv=argv, addplugins=plugins) | |
521 |
|
521 | |||
522 | if __name__ == '__main__': |
|
522 | if __name__ == '__main__': | |
523 | run_iptest() |
|
523 | run_iptest() | |
524 |
|
524 |
@@ -1,569 +1,592 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 | """IPython Test Process Controller |
|
2 | """IPython Test Process Controller | |
3 |
|
3 | |||
4 | This module runs one or more subprocesses which will actually run the IPython |
|
4 | This module runs one or more subprocesses which will actually run the IPython | |
5 | test suite. |
|
5 | test suite. | |
6 |
|
6 | |||
7 | """ |
|
7 | """ | |
8 |
|
8 | |||
9 | #----------------------------------------------------------------------------- |
|
9 | #----------------------------------------------------------------------------- | |
10 | # Copyright (C) 2009-2011 The IPython Development Team |
|
10 | # Copyright (C) 2009-2011 The IPython Development Team | |
11 | # |
|
11 | # | |
12 | # Distributed under the terms of the BSD License. The full license is in |
|
12 | # Distributed under the terms of the BSD License. The full license is in | |
13 | # the file COPYING, distributed as part of this software. |
|
13 | # the file COPYING, distributed as part of this software. | |
14 | #----------------------------------------------------------------------------- |
|
14 | #----------------------------------------------------------------------------- | |
15 |
|
15 | |||
16 | #----------------------------------------------------------------------------- |
|
16 | #----------------------------------------------------------------------------- | |
17 | # Imports |
|
17 | # Imports | |
18 | #----------------------------------------------------------------------------- |
|
18 | #----------------------------------------------------------------------------- | |
19 | from __future__ import print_function |
|
19 | from __future__ import print_function | |
20 |
|
20 | |||
21 | import argparse |
|
21 | import argparse | |
|
22 | import json | |||
22 | import multiprocessing.pool |
|
23 | import multiprocessing.pool | |
23 | from multiprocessing import Process, Queue |
|
|||
24 | import os |
|
24 | import os | |
25 | import shutil |
|
25 | import shutil | |
26 | import signal |
|
26 | import signal | |
27 | import sys |
|
27 | import sys | |
28 | import subprocess |
|
28 | import subprocess | |
29 | import time |
|
29 | import time | |
30 |
|
30 | |||
31 | from .iptest import have, test_group_names as py_test_group_names, test_sections |
|
31 | from .iptest import have, test_group_names as py_test_group_names, test_sections, StreamCapturer | |
32 | from IPython.utils.path import compress_user |
|
32 | from IPython.utils.path import compress_user | |
33 | from IPython.utils.py3compat import bytes_to_str |
|
33 | from IPython.utils.py3compat import bytes_to_str | |
34 | from IPython.utils.sysinfo import get_sys_info |
|
34 | from IPython.utils.sysinfo import get_sys_info | |
35 | from IPython.utils.tempdir import TemporaryDirectory |
|
35 | from IPython.utils.tempdir import TemporaryDirectory | |
36 |
|
36 | |||
37 |
|
37 | |||
38 | class TestController(object): |
|
38 | class TestController(object): | |
39 | """Run tests in a subprocess |
|
39 | """Run tests in a subprocess | |
40 | """ |
|
40 | """ | |
41 | #: str, IPython test suite to be executed. |
|
41 | #: str, IPython test suite to be executed. | |
42 | section = None |
|
42 | section = None | |
43 | #: list, command line arguments to be executed |
|
43 | #: list, command line arguments to be executed | |
44 | cmd = None |
|
44 | cmd = None | |
45 | #: dict, extra environment variables to set for the subprocess |
|
45 | #: dict, extra environment variables to set for the subprocess | |
46 | env = None |
|
46 | env = None | |
47 | #: list, TemporaryDirectory instances to clear up when the process finishes |
|
47 | #: list, TemporaryDirectory instances to clear up when the process finishes | |
48 | dirs = None |
|
48 | dirs = None | |
49 | #: subprocess.Popen instance |
|
49 | #: subprocess.Popen instance | |
50 | process = None |
|
50 | process = None | |
51 | #: str, process stdout+stderr |
|
51 | #: str, process stdout+stderr | |
52 | stdout = None |
|
52 | stdout = None | |
53 |
|
53 | |||
54 | def __init__(self): |
|
54 | def __init__(self): | |
55 | self.cmd = [] |
|
55 | self.cmd = [] | |
56 | self.env = {} |
|
56 | self.env = {} | |
57 | self.dirs = [] |
|
57 | self.dirs = [] | |
58 |
|
58 | |||
59 | def setup(self): |
|
59 | def setup(self): | |
60 | """Create temporary directories etc. |
|
60 | """Create temporary directories etc. | |
61 |
|
61 | |||
62 | This is only called when we know the test group will be run. Things |
|
62 | This is only called when we know the test group will be run. Things | |
63 | created here may be cleaned up by self.cleanup(). |
|
63 | created here may be cleaned up by self.cleanup(). | |
64 | """ |
|
64 | """ | |
65 | pass |
|
65 | pass | |
66 |
|
66 | |||
67 | def launch(self, buffer_output=False): |
|
67 | def launch(self, buffer_output=False): | |
68 | # print('*** ENV:', self.env) # dbg |
|
68 | # print('*** ENV:', self.env) # dbg | |
69 | # print('*** CMD:', self.cmd) # dbg |
|
69 | # print('*** CMD:', self.cmd) # dbg | |
70 | env = os.environ.copy() |
|
70 | env = os.environ.copy() | |
71 | env.update(self.env) |
|
71 | env.update(self.env) | |
72 | output = subprocess.PIPE if buffer_output else None |
|
72 | output = subprocess.PIPE if buffer_output else None | |
73 | stdout = subprocess.STDOUT if buffer_output else None |
|
73 | stdout = subprocess.STDOUT if buffer_output else None | |
74 | self.process = subprocess.Popen(self.cmd, stdout=output, |
|
74 | self.process = subprocess.Popen(self.cmd, stdout=output, | |
75 | stderr=stdout, env=env) |
|
75 | stderr=stdout, env=env) | |
76 |
|
76 | |||
77 | def wait(self): |
|
77 | def wait(self): | |
78 | self.stdout, _ = self.process.communicate() |
|
78 | self.stdout, _ = self.process.communicate() | |
79 | return self.process.returncode |
|
79 | return self.process.returncode | |
80 |
|
80 | |||
81 | def print_extra_info(self): |
|
81 | def print_extra_info(self): | |
82 | """Print extra information about this test run. |
|
82 | """Print extra information about this test run. | |
83 |
|
83 | |||
84 | If we're running in parallel and showing the concise view, this is only |
|
84 | If we're running in parallel and showing the concise view, this is only | |
85 | called if the test group fails. Otherwise, it's called before the test |
|
85 | called if the test group fails. Otherwise, it's called before the test | |
86 | group is started. |
|
86 | group is started. | |
87 |
|
87 | |||
88 | The base implementation does nothing, but it can be overridden by |
|
88 | The base implementation does nothing, but it can be overridden by | |
89 | subclasses. |
|
89 | subclasses. | |
90 | """ |
|
90 | """ | |
91 | return |
|
91 | return | |
92 |
|
92 | |||
93 | def cleanup_process(self): |
|
93 | def cleanup_process(self): | |
94 | """Cleanup on exit by killing any leftover processes.""" |
|
94 | """Cleanup on exit by killing any leftover processes.""" | |
95 | subp = self.process |
|
95 | subp = self.process | |
96 | if subp is None or (subp.poll() is not None): |
|
96 | if subp is None or (subp.poll() is not None): | |
97 | return # Process doesn't exist, or is already dead. |
|
97 | return # Process doesn't exist, or is already dead. | |
98 |
|
98 | |||
99 | try: |
|
99 | try: | |
100 | print('Cleaning up stale PID: %d' % subp.pid) |
|
100 | print('Cleaning up stale PID: %d' % subp.pid) | |
101 | subp.kill() |
|
101 | subp.kill() | |
102 | except: # (OSError, WindowsError) ? |
|
102 | except: # (OSError, WindowsError) ? | |
103 | # This is just a best effort, if we fail or the process was |
|
103 | # This is just a best effort, if we fail or the process was | |
104 | # really gone, ignore it. |
|
104 | # really gone, ignore it. | |
105 | pass |
|
105 | pass | |
106 | else: |
|
106 | else: | |
107 | for i in range(10): |
|
107 | for i in range(10): | |
108 | if subp.poll() is None: |
|
108 | if subp.poll() is None: | |
109 | time.sleep(0.1) |
|
109 | time.sleep(0.1) | |
110 | else: |
|
110 | else: | |
111 | break |
|
111 | break | |
112 |
|
112 | |||
113 | if subp.poll() is None: |
|
113 | if subp.poll() is None: | |
114 | # The process did not die... |
|
114 | # The process did not die... | |
115 | print('... failed. Manual cleanup may be required.') |
|
115 | print('... failed. Manual cleanup may be required.') | |
116 |
|
116 | |||
117 | def cleanup(self): |
|
117 | def cleanup(self): | |
118 | "Kill process if it's still alive, and clean up temporary directories" |
|
118 | "Kill process if it's still alive, and clean up temporary directories" | |
119 | self.cleanup_process() |
|
119 | self.cleanup_process() | |
120 | for td in self.dirs: |
|
120 | for td in self.dirs: | |
121 | td.cleanup() |
|
121 | td.cleanup() | |
122 |
|
122 | |||
123 | __del__ = cleanup |
|
123 | __del__ = cleanup | |
124 |
|
124 | |||
125 | class PyTestController(TestController): |
|
125 | class PyTestController(TestController): | |
126 | """Run Python tests using IPython.testing.iptest""" |
|
126 | """Run Python tests using IPython.testing.iptest""" | |
127 | #: str, Python command to execute in subprocess |
|
127 | #: str, Python command to execute in subprocess | |
128 | pycmd = None |
|
128 | pycmd = None | |
129 |
|
129 | |||
130 | def __init__(self, section): |
|
130 | def __init__(self, section, options): | |
131 | """Create new test runner.""" |
|
131 | """Create new test runner.""" | |
132 | TestController.__init__(self) |
|
132 | TestController.__init__(self) | |
133 | self.section = section |
|
133 | self.section = section | |
134 | # pycmd is put into cmd[2] in PyTestController.launch() |
|
134 | # pycmd is put into cmd[2] in PyTestController.launch() | |
135 | self.cmd = [sys.executable, '-c', None, section] |
|
135 | self.cmd = [sys.executable, '-c', None, section] | |
136 | self.pycmd = "from IPython.testing.iptest import run_iptest; run_iptest()" |
|
136 | self.pycmd = "from IPython.testing.iptest import run_iptest; run_iptest()" | |
|
137 | self.options = options | |||
137 |
|
138 | |||
138 | def setup(self): |
|
139 | def setup(self): | |
139 | ipydir = TemporaryDirectory() |
|
140 | ipydir = TemporaryDirectory() | |
140 | self.dirs.append(ipydir) |
|
141 | self.dirs.append(ipydir) | |
141 | self.env['IPYTHONDIR'] = ipydir.name |
|
142 | self.env['IPYTHONDIR'] = ipydir.name | |
142 | self.workingdir = workingdir = TemporaryDirectory() |
|
143 | self.workingdir = workingdir = TemporaryDirectory() | |
143 | self.dirs.append(workingdir) |
|
144 | self.dirs.append(workingdir) | |
144 | self.env['IPTEST_WORKING_DIR'] = workingdir.name |
|
145 | self.env['IPTEST_WORKING_DIR'] = workingdir.name | |
145 | # This means we won't get odd effects from our own matplotlib config |
|
146 | # This means we won't get odd effects from our own matplotlib config | |
146 | self.env['MPLCONFIGDIR'] = workingdir.name |
|
147 | self.env['MPLCONFIGDIR'] = workingdir.name | |
147 |
|
148 | |||
|
149 | # From options: | |||
|
150 | if self.options.xunit: | |||
|
151 | self.add_xunit() | |||
|
152 | if self.options.coverage: | |||
|
153 | self.add_coverage() | |||
|
154 | self.env['IPTEST_SUBPROC_STREAMS'] = self.options.subproc_streams | |||
|
155 | self.cmd.extend(self.options.extra_args) | |||
|
156 | ||||
148 | @property |
|
157 | @property | |
149 | def will_run(self): |
|
158 | def will_run(self): | |
150 | try: |
|
159 | try: | |
151 | return test_sections[self.section].will_run |
|
160 | return test_sections[self.section].will_run | |
152 | except KeyError: |
|
161 | except KeyError: | |
153 | return True |
|
162 | return True | |
154 |
|
163 | |||
155 | def add_xunit(self): |
|
164 | def add_xunit(self): | |
156 | xunit_file = os.path.abspath(self.section + '.xunit.xml') |
|
165 | xunit_file = os.path.abspath(self.section + '.xunit.xml') | |
157 | self.cmd.extend(['--with-xunit', '--xunit-file', xunit_file]) |
|
166 | self.cmd.extend(['--with-xunit', '--xunit-file', xunit_file]) | |
158 |
|
167 | |||
159 | def add_coverage(self): |
|
168 | def add_coverage(self): | |
160 | try: |
|
169 | try: | |
161 | sources = test_sections[self.section].includes |
|
170 | sources = test_sections[self.section].includes | |
162 | except KeyError: |
|
171 | except KeyError: | |
163 | sources = ['IPython'] |
|
172 | sources = ['IPython'] | |
164 |
|
173 | |||
165 | coverage_rc = ("[run]\n" |
|
174 | coverage_rc = ("[run]\n" | |
166 | "data_file = {data_file}\n" |
|
175 | "data_file = {data_file}\n" | |
167 | "source =\n" |
|
176 | "source =\n" | |
168 | " {source}\n" |
|
177 | " {source}\n" | |
169 | ).format(data_file=os.path.abspath('.coverage.'+self.section), |
|
178 | ).format(data_file=os.path.abspath('.coverage.'+self.section), | |
170 | source="\n ".join(sources)) |
|
179 | source="\n ".join(sources)) | |
171 | config_file = os.path.join(self.workingdir.name, '.coveragerc') |
|
180 | config_file = os.path.join(self.workingdir.name, '.coveragerc') | |
172 | with open(config_file, 'w') as f: |
|
181 | with open(config_file, 'w') as f: | |
173 | f.write(coverage_rc) |
|
182 | f.write(coverage_rc) | |
174 |
|
183 | |||
175 | self.env['COVERAGE_PROCESS_START'] = config_file |
|
184 | self.env['COVERAGE_PROCESS_START'] = config_file | |
176 | self.pycmd = "import coverage; coverage.process_startup(); " + self.pycmd |
|
185 | self.pycmd = "import coverage; coverage.process_startup(); " + self.pycmd | |
177 |
|
186 | |||
178 | def launch(self, buffer_output=False): |
|
187 | def launch(self, buffer_output=False): | |
179 | self.cmd[2] = self.pycmd |
|
188 | self.cmd[2] = self.pycmd | |
180 | super(PyTestController, self).launch(buffer_output=buffer_output) |
|
189 | super(PyTestController, self).launch(buffer_output=buffer_output) | |
181 |
|
190 | |||
182 | js_prefix = 'js/' |
|
191 | js_prefix = 'js/' | |
183 |
|
192 | |||
184 | def get_js_test_dir(): |
|
193 | def get_js_test_dir(): | |
185 | import IPython.html.tests as t |
|
194 | import IPython.html.tests as t | |
186 | return os.path.join(os.path.dirname(t.__file__), '') |
|
195 | return os.path.join(os.path.dirname(t.__file__), '') | |
187 |
|
196 | |||
188 | def all_js_groups(): |
|
197 | def all_js_groups(): | |
189 | import glob |
|
198 | import glob | |
190 | test_dir = get_js_test_dir() |
|
199 | test_dir = get_js_test_dir() | |
191 | all_subdirs = glob.glob(test_dir + '*/') |
|
200 | all_subdirs = glob.glob(test_dir + '*/') | |
192 | return [js_prefix+os.path.relpath(x, test_dir) for x in all_subdirs if os.path.relpath(x, test_dir) != '__pycache__'] |
|
201 | return [js_prefix+os.path.relpath(x, test_dir) for x in all_subdirs if os.path.relpath(x, test_dir) != '__pycache__'] | |
193 |
|
202 | |||
194 | class JSController(TestController): |
|
203 | class JSController(TestController): | |
195 | """Run CasperJS tests """ |
|
204 | """Run CasperJS tests """ | |
196 | def __init__(self, section): |
|
205 | def __init__(self, section): | |
197 | """Create new test runner.""" |
|
206 | """Create new test runner.""" | |
198 | TestController.__init__(self) |
|
207 | TestController.__init__(self) | |
199 | self.section = section |
|
208 | self.section = section | |
200 | js_test_dir = get_js_test_dir() |
|
209 | js_test_dir = get_js_test_dir() | |
201 | includes = '--includes=' + os.path.join(js_test_dir,'util.js') |
|
210 | includes = '--includes=' + os.path.join(js_test_dir,'util.js') | |
202 | test_cases = os.path.join(js_test_dir, self.section[len(js_prefix):]) |
|
211 | test_cases = os.path.join(js_test_dir, self.section[len(js_prefix):]) | |
203 | self.cmd = ['casperjs', 'test', includes, test_cases] |
|
212 | self.cmd = ['casperjs', 'test', includes, test_cases] | |
204 |
|
213 | |||
205 | def setup(self): |
|
214 | def setup(self): | |
206 | self.ipydir = TemporaryDirectory() |
|
215 | self.ipydir = TemporaryDirectory() | |
207 | self.nbdir = TemporaryDirectory() |
|
216 | self.nbdir = TemporaryDirectory() | |
208 | self.dirs.append(self.ipydir) |
|
217 | self.dirs.append(self.ipydir) | |
209 | self.dirs.append(self.nbdir) |
|
218 | self.dirs.append(self.nbdir) | |
210 | os.makedirs(os.path.join(self.nbdir.name, os.path.join(u'sub βir1', u'sub βir 1a'))) |
|
219 | os.makedirs(os.path.join(self.nbdir.name, os.path.join(u'sub βir1', u'sub βir 1a'))) | |
211 | os.makedirs(os.path.join(self.nbdir.name, os.path.join(u'sub βir2', u'sub βir 1b'))) |
|
220 | os.makedirs(os.path.join(self.nbdir.name, os.path.join(u'sub βir2', u'sub βir 1b'))) | |
212 |
|
221 | |||
213 | # start the ipython notebook, so we get the port number |
|
222 | # start the ipython notebook, so we get the port number | |
|
223 | self.server_port = 0 | |||
214 | self._init_server() |
|
224 | self._init_server() | |
215 |
|
|
225 | if self.server_port: | |
216 |
|
226 | self.cmd.append("--port=%i" % self.server_port) | ||
|
227 | else: | |||
|
228 | # don't launch tests if the server didn't start | |||
|
229 | self.cmd = [sys.executable, '-c', 'raise SystemExit(1)'] | |||
|
230 | ||||
217 | def print_extra_info(self): |
|
231 | def print_extra_info(self): | |
218 | print("Running tests with notebook directory %r" % self.nbdir.name) |
|
232 | print("Running tests with notebook directory %r" % self.nbdir.name) | |
219 |
|
233 | |||
220 | @property |
|
234 | @property | |
221 | def will_run(self): |
|
235 | def will_run(self): | |
222 | return all(have[a] for a in ['zmq', 'tornado', 'jinja2', 'casperjs']) |
|
236 | return all(have[a] for a in ['zmq', 'tornado', 'jinja2', 'casperjs', 'sqlite3']) | |
223 |
|
237 | |||
224 | def _init_server(self): |
|
238 | def _init_server(self): | |
225 | "Start the notebook server in a separate process" |
|
239 | "Start the notebook server in a separate process" | |
226 | self.queue = q = Queue() |
|
240 | self.server_command = command = [sys.executable, | |
227 | self.server = Process(target=run_webapp, args=(q, self.ipydir.name, self.nbdir.name)) |
|
241 | '-m', 'IPython.html', | |
228 | self.server.start() |
|
242 | '--no-browser', | |
229 | self.server_port = q.get() |
|
243 | '--ipython-dir', self.ipydir.name, | |
|
244 | '--notebook-dir', self.nbdir.name, | |||
|
245 | ] | |||
|
246 | # ipc doesn't work on Windows, and darwin has crazy-long temp paths, | |||
|
247 | # which run afoul of ipc's maximum path length. | |||
|
248 | if sys.platform.startswith('linux'): | |||
|
249 | command.append('--KernelManager.transport=ipc') | |||
|
250 | self.stream_capturer = c = StreamCapturer() | |||
|
251 | c.start() | |||
|
252 | self.server = subprocess.Popen(command, stdout=c.writefd, stderr=subprocess.STDOUT) | |||
|
253 | self.server_info_file = os.path.join(self.ipydir.name, | |||
|
254 | 'profile_default', 'security', 'nbserver-%i.json' % self.server.pid | |||
|
255 | ) | |||
|
256 | self._wait_for_server() | |||
|
257 | ||||
|
258 | def _wait_for_server(self): | |||
|
259 | """Wait 30 seconds for the notebook server to start""" | |||
|
260 | for i in range(300): | |||
|
261 | if self.server.poll() is not None: | |||
|
262 | return self._failed_to_start() | |||
|
263 | if os.path.exists(self.server_info_file): | |||
|
264 | self._load_server_info() | |||
|
265 | return | |||
|
266 | time.sleep(0.1) | |||
|
267 | print("Notebook server-info file never arrived: %s" % self.server_info_file, | |||
|
268 | file=sys.stderr | |||
|
269 | ) | |||
|
270 | ||||
|
271 | def _failed_to_start(self): | |||
|
272 | """Notebook server exited prematurely""" | |||
|
273 | captured = self.stream_capturer.get_buffer().decode('utf-8', 'replace') | |||
|
274 | print("Notebook failed to start: ", file=sys.stderr) | |||
|
275 | print(self.server_command) | |||
|
276 | print(captured, file=sys.stderr) | |||
|
277 | ||||
|
278 | def _load_server_info(self): | |||
|
279 | """Notebook server started, load connection info from JSON""" | |||
|
280 | with open(self.server_info_file) as f: | |||
|
281 | info = json.load(f) | |||
|
282 | self.server_port = info['port'] | |||
230 |
|
283 | |||
231 | def cleanup(self): |
|
284 | def cleanup(self): | |
232 | self.server.terminate() |
|
285 | try: | |
233 |
self.server. |
|
286 | self.server.terminate() | |
|
287 | except OSError: | |||
|
288 | # already dead | |||
|
289 | pass | |||
|
290 | self.server.wait() | |||
|
291 | self.stream_capturer.halt() | |||
234 | TestController.cleanup(self) |
|
292 | TestController.cleanup(self) | |
235 |
|
293 | |||
236 | def run_webapp(q, ipydir, nbdir, loglevel=0): |
|
|||
237 | """start the IPython Notebook, and pass port back to the queue""" |
|
|||
238 | import os |
|
|||
239 | import IPython.html.notebookapp as nbapp |
|
|||
240 | import sys |
|
|||
241 | sys.stderr = open(os.devnull, 'w') |
|
|||
242 | server = nbapp.NotebookApp() |
|
|||
243 | args = ['--no-browser'] |
|
|||
244 | args.extend(['--ipython-dir', ipydir, |
|
|||
245 | '--notebook-dir', nbdir, |
|
|||
246 | '--log-level', str(loglevel), |
|
|||
247 | ]) |
|
|||
248 | # ipc doesn't work on Windows, and darwin has crazy-long temp paths, |
|
|||
249 | # which run afoul of ipc's maximum path length. |
|
|||
250 | if sys.platform.startswith('linux'): |
|
|||
251 | args.append('--KernelManager.transport=ipc') |
|
|||
252 | server.initialize(args) |
|
|||
253 | # communicate the port number to the parent process |
|
|||
254 | q.put(server.port) |
|
|||
255 | server.start() |
|
|||
256 |
|
294 | |||
257 | def prepare_controllers(options): |
|
295 | def prepare_controllers(options): | |
258 | """Returns two lists of TestController instances, those to run, and those |
|
296 | """Returns two lists of TestController instances, those to run, and those | |
259 | not to run.""" |
|
297 | not to run.""" | |
260 | testgroups = options.testgroups |
|
298 | testgroups = options.testgroups | |
261 |
|
299 | |||
262 | if testgroups: |
|
300 | if testgroups: | |
263 | py_testgroups = [g for g in testgroups if (g in py_test_group_names) \ |
|
301 | py_testgroups = [g for g in testgroups if (g in py_test_group_names) \ | |
264 | or g.startswith('IPython.')] |
|
302 | or g.startswith('IPython.')] | |
265 | if 'js' in testgroups: |
|
303 | if 'js' in testgroups: | |
266 | js_testgroups = all_js_groups() |
|
304 | js_testgroups = all_js_groups() | |
267 | else: |
|
305 | else: | |
268 | js_testgroups = [g for g in testgroups if g not in py_testgroups] |
|
306 | js_testgroups = [g for g in testgroups if g not in py_testgroups] | |
269 | else: |
|
307 | else: | |
270 | py_testgroups = py_test_group_names |
|
308 | py_testgroups = py_test_group_names | |
271 | js_testgroups = all_js_groups() |
|
309 | js_testgroups = all_js_groups() | |
272 | if not options.all: |
|
310 | if not options.all: | |
273 | test_sections['parallel'].enabled = False |
|
311 | test_sections['parallel'].enabled = False | |
274 |
|
312 | |||
275 | c_js = [JSController(name) for name in js_testgroups] |
|
313 | c_js = [JSController(name) for name in js_testgroups] | |
276 | c_py = [PyTestController(name) for name in py_testgroups] |
|
314 | c_py = [PyTestController(name, options) for name in py_testgroups] | |
277 |
|
||||
278 | configure_py_controllers(c_py, xunit=options.xunit, |
|
|||
279 | coverage=options.coverage, subproc_streams=options.subproc_streams, |
|
|||
280 | extra_args=options.extra_args) |
|
|||
281 |
|
315 | |||
282 | controllers = c_py + c_js |
|
316 | controllers = c_py + c_js | |
283 | to_run = [c for c in controllers if c.will_run] |
|
317 | to_run = [c for c in controllers if c.will_run] | |
284 | not_run = [c for c in controllers if not c.will_run] |
|
318 | not_run = [c for c in controllers if not c.will_run] | |
285 | return to_run, not_run |
|
319 | return to_run, not_run | |
286 |
|
320 | |||
287 | def configure_py_controllers(controllers, xunit=False, coverage=False, |
|
|||
288 | subproc_streams='capture', extra_args=()): |
|
|||
289 | """Apply options for a collection of TestController objects.""" |
|
|||
290 | for controller in controllers: |
|
|||
291 | if xunit: |
|
|||
292 | controller.add_xunit() |
|
|||
293 | if coverage: |
|
|||
294 | controller.add_coverage() |
|
|||
295 | controller.env['IPTEST_SUBPROC_STREAMS'] = subproc_streams |
|
|||
296 | controller.cmd.extend(extra_args) |
|
|||
297 |
|
||||
298 | def do_run(controller, buffer_output=True): |
|
321 | def do_run(controller, buffer_output=True): | |
299 | """Setup and run a test controller. |
|
322 | """Setup and run a test controller. | |
300 |
|
323 | |||
301 | If buffer_output is True, no output is displayed, to avoid it appearing |
|
324 | If buffer_output is True, no output is displayed, to avoid it appearing | |
302 | interleaved. In this case, the caller is responsible for displaying test |
|
325 | interleaved. In this case, the caller is responsible for displaying test | |
303 | output on failure. |
|
326 | output on failure. | |
304 |
|
327 | |||
305 | Returns |
|
328 | Returns | |
306 | ------- |
|
329 | ------- | |
307 | controller : TestController |
|
330 | controller : TestController | |
308 | The same controller as passed in, as a convenience for using map() type |
|
331 | The same controller as passed in, as a convenience for using map() type | |
309 | APIs. |
|
332 | APIs. | |
310 | exitcode : int |
|
333 | exitcode : int | |
311 | The exit code of the test subprocess. Non-zero indicates failure. |
|
334 | The exit code of the test subprocess. Non-zero indicates failure. | |
312 | """ |
|
335 | """ | |
313 | try: |
|
336 | try: | |
314 | try: |
|
337 | try: | |
315 | controller.setup() |
|
338 | controller.setup() | |
316 | if not buffer_output: |
|
339 | if not buffer_output: | |
317 | controller.print_extra_info() |
|
340 | controller.print_extra_info() | |
318 | controller.launch(buffer_output=buffer_output) |
|
341 | controller.launch(buffer_output=buffer_output) | |
319 | except Exception: |
|
342 | except Exception: | |
320 | import traceback |
|
343 | import traceback | |
321 | traceback.print_exc() |
|
344 | traceback.print_exc() | |
322 | return controller, 1 # signal failure |
|
345 | return controller, 1 # signal failure | |
323 |
|
346 | |||
324 | exitcode = controller.wait() |
|
347 | exitcode = controller.wait() | |
325 | return controller, exitcode |
|
348 | return controller, exitcode | |
326 |
|
349 | |||
327 | except KeyboardInterrupt: |
|
350 | except KeyboardInterrupt: | |
328 | return controller, -signal.SIGINT |
|
351 | return controller, -signal.SIGINT | |
329 | finally: |
|
352 | finally: | |
330 | controller.cleanup() |
|
353 | controller.cleanup() | |
331 |
|
354 | |||
332 | def report(): |
|
355 | def report(): | |
333 | """Return a string with a summary report of test-related variables.""" |
|
356 | """Return a string with a summary report of test-related variables.""" | |
334 | inf = get_sys_info() |
|
357 | inf = get_sys_info() | |
335 | out = [] |
|
358 | out = [] | |
336 | def _add(name, value): |
|
359 | def _add(name, value): | |
337 | out.append((name, value)) |
|
360 | out.append((name, value)) | |
338 |
|
361 | |||
339 | _add('IPython version', inf['ipython_version']) |
|
362 | _add('IPython version', inf['ipython_version']) | |
340 | _add('IPython commit', "{} ({})".format(inf['commit_hash'], inf['commit_source'])) |
|
363 | _add('IPython commit', "{} ({})".format(inf['commit_hash'], inf['commit_source'])) | |
341 | _add('IPython package', compress_user(inf['ipython_path'])) |
|
364 | _add('IPython package', compress_user(inf['ipython_path'])) | |
342 | _add('Python version', inf['sys_version'].replace('\n','')) |
|
365 | _add('Python version', inf['sys_version'].replace('\n','')) | |
343 | _add('sys.executable', compress_user(inf['sys_executable'])) |
|
366 | _add('sys.executable', compress_user(inf['sys_executable'])) | |
344 | _add('Platform', inf['platform']) |
|
367 | _add('Platform', inf['platform']) | |
345 |
|
368 | |||
346 | width = max(len(n) for (n,v) in out) |
|
369 | width = max(len(n) for (n,v) in out) | |
347 | out = ["{:<{width}}: {}\n".format(n, v, width=width) for (n,v) in out] |
|
370 | out = ["{:<{width}}: {}\n".format(n, v, width=width) for (n,v) in out] | |
348 |
|
371 | |||
349 | avail = [] |
|
372 | avail = [] | |
350 | not_avail = [] |
|
373 | not_avail = [] | |
351 |
|
374 | |||
352 | for k, is_avail in have.items(): |
|
375 | for k, is_avail in have.items(): | |
353 | if is_avail: |
|
376 | if is_avail: | |
354 | avail.append(k) |
|
377 | avail.append(k) | |
355 | else: |
|
378 | else: | |
356 | not_avail.append(k) |
|
379 | not_avail.append(k) | |
357 |
|
380 | |||
358 | if avail: |
|
381 | if avail: | |
359 | out.append('\nTools and libraries available at test time:\n') |
|
382 | out.append('\nTools and libraries available at test time:\n') | |
360 | avail.sort() |
|
383 | avail.sort() | |
361 | out.append(' ' + ' '.join(avail)+'\n') |
|
384 | out.append(' ' + ' '.join(avail)+'\n') | |
362 |
|
385 | |||
363 | if not_avail: |
|
386 | if not_avail: | |
364 | out.append('\nTools and libraries NOT available at test time:\n') |
|
387 | out.append('\nTools and libraries NOT available at test time:\n') | |
365 | not_avail.sort() |
|
388 | not_avail.sort() | |
366 | out.append(' ' + ' '.join(not_avail)+'\n') |
|
389 | out.append(' ' + ' '.join(not_avail)+'\n') | |
367 |
|
390 | |||
368 | return ''.join(out) |
|
391 | return ''.join(out) | |
369 |
|
392 | |||
370 | def run_iptestall(options): |
|
393 | def run_iptestall(options): | |
371 | """Run the entire IPython test suite by calling nose and trial. |
|
394 | """Run the entire IPython test suite by calling nose and trial. | |
372 |
|
395 | |||
373 | This function constructs :class:`IPTester` instances for all IPython |
|
396 | This function constructs :class:`IPTester` instances for all IPython | |
374 | modules and package and then runs each of them. This causes the modules |
|
397 | modules and package and then runs each of them. This causes the modules | |
375 | and packages of IPython to be tested each in their own subprocess using |
|
398 | and packages of IPython to be tested each in their own subprocess using | |
376 | nose. |
|
399 | nose. | |
377 |
|
400 | |||
378 | Parameters |
|
401 | Parameters | |
379 | ---------- |
|
402 | ---------- | |
380 |
|
403 | |||
381 | All parameters are passed as attributes of the options object. |
|
404 | All parameters are passed as attributes of the options object. | |
382 |
|
405 | |||
383 | testgroups : list of str |
|
406 | testgroups : list of str | |
384 | Run only these sections of the test suite. If empty, run all the available |
|
407 | Run only these sections of the test suite. If empty, run all the available | |
385 | sections. |
|
408 | sections. | |
386 |
|
409 | |||
387 | fast : int or None |
|
410 | fast : int or None | |
388 | Run the test suite in parallel, using n simultaneous processes. If None |
|
411 | Run the test suite in parallel, using n simultaneous processes. If None | |
389 | is passed, one process is used per CPU core. Default 1 (i.e. sequential) |
|
412 | is passed, one process is used per CPU core. Default 1 (i.e. sequential) | |
390 |
|
413 | |||
391 | inc_slow : bool |
|
414 | inc_slow : bool | |
392 | Include slow tests, like IPython.parallel. By default, these tests aren't |
|
415 | Include slow tests, like IPython.parallel. By default, these tests aren't | |
393 | run. |
|
416 | run. | |
394 |
|
417 | |||
395 | xunit : bool |
|
418 | xunit : bool | |
396 | Produce Xunit XML output. This is written to multiple foo.xunit.xml files. |
|
419 | Produce Xunit XML output. This is written to multiple foo.xunit.xml files. | |
397 |
|
420 | |||
398 | coverage : bool or str |
|
421 | coverage : bool or str | |
399 | Measure code coverage from tests. True will store the raw coverage data, |
|
422 | Measure code coverage from tests. True will store the raw coverage data, | |
400 | or pass 'html' or 'xml' to get reports. |
|
423 | or pass 'html' or 'xml' to get reports. | |
401 |
|
424 | |||
402 | extra_args : list |
|
425 | extra_args : list | |
403 | Extra arguments to pass to the test subprocesses, e.g. '-v' |
|
426 | Extra arguments to pass to the test subprocesses, e.g. '-v' | |
404 | """ |
|
427 | """ | |
405 | to_run, not_run = prepare_controllers(options) |
|
428 | to_run, not_run = prepare_controllers(options) | |
406 |
|
429 | |||
407 | def justify(ltext, rtext, width=70, fill='-'): |
|
430 | def justify(ltext, rtext, width=70, fill='-'): | |
408 | ltext += ' ' |
|
431 | ltext += ' ' | |
409 | rtext = (' ' + rtext).rjust(width - len(ltext), fill) |
|
432 | rtext = (' ' + rtext).rjust(width - len(ltext), fill) | |
410 | return ltext + rtext |
|
433 | return ltext + rtext | |
411 |
|
434 | |||
412 | # Run all test runners, tracking execution time |
|
435 | # Run all test runners, tracking execution time | |
413 | failed = [] |
|
436 | failed = [] | |
414 | t_start = time.time() |
|
437 | t_start = time.time() | |
415 |
|
438 | |||
416 | print() |
|
439 | print() | |
417 | if options.fast == 1: |
|
440 | if options.fast == 1: | |
418 | # This actually means sequential, i.e. with 1 job |
|
441 | # This actually means sequential, i.e. with 1 job | |
419 | for controller in to_run: |
|
442 | for controller in to_run: | |
420 | print('Test group:', controller.section) |
|
443 | print('Test group:', controller.section) | |
421 | sys.stdout.flush() # Show in correct order when output is piped |
|
444 | sys.stdout.flush() # Show in correct order when output is piped | |
422 | controller, res = do_run(controller, buffer_output=False) |
|
445 | controller, res = do_run(controller, buffer_output=False) | |
423 | if res: |
|
446 | if res: | |
424 | failed.append(controller) |
|
447 | failed.append(controller) | |
425 | if res == -signal.SIGINT: |
|
448 | if res == -signal.SIGINT: | |
426 | print("Interrupted") |
|
449 | print("Interrupted") | |
427 | break |
|
450 | break | |
428 | print() |
|
451 | print() | |
429 |
|
452 | |||
430 | else: |
|
453 | else: | |
431 | # Run tests concurrently |
|
454 | # Run tests concurrently | |
432 | try: |
|
455 | try: | |
433 | pool = multiprocessing.pool.ThreadPool(options.fast) |
|
456 | pool = multiprocessing.pool.ThreadPool(options.fast) | |
434 | for (controller, res) in pool.imap_unordered(do_run, to_run): |
|
457 | for (controller, res) in pool.imap_unordered(do_run, to_run): | |
435 | res_string = 'OK' if res == 0 else 'FAILED' |
|
458 | res_string = 'OK' if res == 0 else 'FAILED' | |
436 | print(justify('Test group: ' + controller.section, res_string)) |
|
459 | print(justify('Test group: ' + controller.section, res_string)) | |
437 | if res: |
|
460 | if res: | |
438 | controller.print_extra_info() |
|
461 | controller.print_extra_info() | |
439 | print(bytes_to_str(controller.stdout)) |
|
462 | print(bytes_to_str(controller.stdout)) | |
440 | failed.append(controller) |
|
463 | failed.append(controller) | |
441 | if res == -signal.SIGINT: |
|
464 | if res == -signal.SIGINT: | |
442 | print("Interrupted") |
|
465 | print("Interrupted") | |
443 | break |
|
466 | break | |
444 | except KeyboardInterrupt: |
|
467 | except KeyboardInterrupt: | |
445 | return |
|
468 | return | |
446 |
|
469 | |||
447 | for controller in not_run: |
|
470 | for controller in not_run: | |
448 | print(justify('Test group: ' + controller.section, 'NOT RUN')) |
|
471 | print(justify('Test group: ' + controller.section, 'NOT RUN')) | |
449 |
|
472 | |||
450 | t_end = time.time() |
|
473 | t_end = time.time() | |
451 | t_tests = t_end - t_start |
|
474 | t_tests = t_end - t_start | |
452 | nrunners = len(to_run) |
|
475 | nrunners = len(to_run) | |
453 | nfail = len(failed) |
|
476 | nfail = len(failed) | |
454 | # summarize results |
|
477 | # summarize results | |
455 | print('_'*70) |
|
478 | print('_'*70) | |
456 | print('Test suite completed for system with the following information:') |
|
479 | print('Test suite completed for system with the following information:') | |
457 | print(report()) |
|
480 | print(report()) | |
458 | took = "Took %.3fs." % t_tests |
|
481 | took = "Took %.3fs." % t_tests | |
459 | print('Status: ', end='') |
|
482 | print('Status: ', end='') | |
460 | if not failed: |
|
483 | if not failed: | |
461 | print('OK (%d test groups).' % nrunners, took) |
|
484 | print('OK (%d test groups).' % nrunners, took) | |
462 | else: |
|
485 | else: | |
463 | # If anything went wrong, point out what command to rerun manually to |
|
486 | # If anything went wrong, point out what command to rerun manually to | |
464 | # see the actual errors and individual summary |
|
487 | # see the actual errors and individual summary | |
465 | failed_sections = [c.section for c in failed] |
|
488 | failed_sections = [c.section for c in failed] | |
466 | print('ERROR - {} out of {} test groups failed ({}).'.format(nfail, |
|
489 | print('ERROR - {} out of {} test groups failed ({}).'.format(nfail, | |
467 | nrunners, ', '.join(failed_sections)), took) |
|
490 | nrunners, ', '.join(failed_sections)), took) | |
468 | print() |
|
491 | print() | |
469 | print('You may wish to rerun these, with:') |
|
492 | print('You may wish to rerun these, with:') | |
470 | print(' iptest', *failed_sections) |
|
493 | print(' iptest', *failed_sections) | |
471 | print() |
|
494 | print() | |
472 |
|
495 | |||
473 | if options.coverage: |
|
496 | if options.coverage: | |
474 | from coverage import coverage |
|
497 | from coverage import coverage | |
475 | cov = coverage(data_file='.coverage') |
|
498 | cov = coverage(data_file='.coverage') | |
476 | cov.combine() |
|
499 | cov.combine() | |
477 | cov.save() |
|
500 | cov.save() | |
478 |
|
501 | |||
479 | # Coverage HTML report |
|
502 | # Coverage HTML report | |
480 | if options.coverage == 'html': |
|
503 | if options.coverage == 'html': | |
481 | html_dir = 'ipy_htmlcov' |
|
504 | html_dir = 'ipy_htmlcov' | |
482 | shutil.rmtree(html_dir, ignore_errors=True) |
|
505 | shutil.rmtree(html_dir, ignore_errors=True) | |
483 | print("Writing HTML coverage report to %s/ ... " % html_dir, end="") |
|
506 | print("Writing HTML coverage report to %s/ ... " % html_dir, end="") | |
484 | sys.stdout.flush() |
|
507 | sys.stdout.flush() | |
485 |
|
508 | |||
486 | # Custom HTML reporter to clean up module names. |
|
509 | # Custom HTML reporter to clean up module names. | |
487 | from coverage.html import HtmlReporter |
|
510 | from coverage.html import HtmlReporter | |
488 | class CustomHtmlReporter(HtmlReporter): |
|
511 | class CustomHtmlReporter(HtmlReporter): | |
489 | def find_code_units(self, morfs): |
|
512 | def find_code_units(self, morfs): | |
490 | super(CustomHtmlReporter, self).find_code_units(morfs) |
|
513 | super(CustomHtmlReporter, self).find_code_units(morfs) | |
491 | for cu in self.code_units: |
|
514 | for cu in self.code_units: | |
492 | nameparts = cu.name.split(os.sep) |
|
515 | nameparts = cu.name.split(os.sep) | |
493 | if 'IPython' not in nameparts: |
|
516 | if 'IPython' not in nameparts: | |
494 | continue |
|
517 | continue | |
495 | ix = nameparts.index('IPython') |
|
518 | ix = nameparts.index('IPython') | |
496 | cu.name = '.'.join(nameparts[ix:]) |
|
519 | cu.name = '.'.join(nameparts[ix:]) | |
497 |
|
520 | |||
498 | # Reimplement the html_report method with our custom reporter |
|
521 | # Reimplement the html_report method with our custom reporter | |
499 | cov._harvest_data() |
|
522 | cov._harvest_data() | |
500 | cov.config.from_args(omit='*{0}tests{0}*'.format(os.sep), html_dir=html_dir, |
|
523 | cov.config.from_args(omit='*{0}tests{0}*'.format(os.sep), html_dir=html_dir, | |
501 | html_title='IPython test coverage', |
|
524 | html_title='IPython test coverage', | |
502 | ) |
|
525 | ) | |
503 | reporter = CustomHtmlReporter(cov, cov.config) |
|
526 | reporter = CustomHtmlReporter(cov, cov.config) | |
504 | reporter.report(None) |
|
527 | reporter.report(None) | |
505 | print('done.') |
|
528 | print('done.') | |
506 |
|
529 | |||
507 | # Coverage XML report |
|
530 | # Coverage XML report | |
508 | elif options.coverage == 'xml': |
|
531 | elif options.coverage == 'xml': | |
509 | cov.xml_report(outfile='ipy_coverage.xml') |
|
532 | cov.xml_report(outfile='ipy_coverage.xml') | |
510 |
|
533 | |||
511 | if failed: |
|
534 | if failed: | |
512 | # Ensure that our exit code indicates failure |
|
535 | # Ensure that our exit code indicates failure | |
513 | sys.exit(1) |
|
536 | sys.exit(1) | |
514 |
|
537 | |||
515 | argparser = argparse.ArgumentParser(description='Run IPython test suite') |
|
538 | argparser = argparse.ArgumentParser(description='Run IPython test suite') | |
516 | argparser.add_argument('testgroups', nargs='*', |
|
539 | argparser.add_argument('testgroups', nargs='*', | |
517 | help='Run specified groups of tests. If omitted, run ' |
|
540 | help='Run specified groups of tests. If omitted, run ' | |
518 | 'all tests.') |
|
541 | 'all tests.') | |
519 | argparser.add_argument('--all', action='store_true', |
|
542 | argparser.add_argument('--all', action='store_true', | |
520 | help='Include slow tests not run by default.') |
|
543 | help='Include slow tests not run by default.') | |
521 | argparser.add_argument('-j', '--fast', nargs='?', const=None, default=1, type=int, |
|
544 | argparser.add_argument('-j', '--fast', nargs='?', const=None, default=1, type=int, | |
522 | help='Run test sections in parallel. This starts as many ' |
|
545 | help='Run test sections in parallel. This starts as many ' | |
523 | 'processes as you have cores, or you can specify a number.') |
|
546 | 'processes as you have cores, or you can specify a number.') | |
524 | argparser.add_argument('--xunit', action='store_true', |
|
547 | argparser.add_argument('--xunit', action='store_true', | |
525 | help='Produce Xunit XML results') |
|
548 | help='Produce Xunit XML results') | |
526 | argparser.add_argument('--coverage', nargs='?', const=True, default=False, |
|
549 | argparser.add_argument('--coverage', nargs='?', const=True, default=False, | |
527 | help="Measure test coverage. Specify 'html' or " |
|
550 | help="Measure test coverage. Specify 'html' or " | |
528 | "'xml' to get reports.") |
|
551 | "'xml' to get reports.") | |
529 | argparser.add_argument('--subproc-streams', default='capture', |
|
552 | argparser.add_argument('--subproc-streams', default='capture', | |
530 | help="What to do with stdout/stderr from subprocesses. " |
|
553 | help="What to do with stdout/stderr from subprocesses. " | |
531 | "'capture' (default), 'show' and 'discard' are the options.") |
|
554 | "'capture' (default), 'show' and 'discard' are the options.") | |
532 |
|
555 | |||
533 | def default_options(): |
|
556 | def default_options(): | |
534 | """Get an argparse Namespace object with the default arguments, to pass to |
|
557 | """Get an argparse Namespace object with the default arguments, to pass to | |
535 | :func:`run_iptestall`. |
|
558 | :func:`run_iptestall`. | |
536 | """ |
|
559 | """ | |
537 | options = argparser.parse_args([]) |
|
560 | options = argparser.parse_args([]) | |
538 | options.extra_args = [] |
|
561 | options.extra_args = [] | |
539 | return options |
|
562 | return options | |
540 |
|
563 | |||
541 | def main(): |
|
564 | def main(): | |
542 | # iptest doesn't work correctly if the working directory is the |
|
565 | # iptest doesn't work correctly if the working directory is the | |
543 | # root of the IPython source tree. Tell the user to avoid |
|
566 | # root of the IPython source tree. Tell the user to avoid | |
544 | # frustration. |
|
567 | # frustration. | |
545 | if os.path.exists(os.path.join(os.getcwd(), |
|
568 | if os.path.exists(os.path.join(os.getcwd(), | |
546 | 'IPython', 'testing', '__main__.py')): |
|
569 | 'IPython', 'testing', '__main__.py')): | |
547 | print("Don't run iptest from the IPython source directory", |
|
570 | print("Don't run iptest from the IPython source directory", | |
548 | file=sys.stderr) |
|
571 | file=sys.stderr) | |
549 | sys.exit(1) |
|
572 | sys.exit(1) | |
550 | # Arguments after -- should be passed through to nose. Argparse treats |
|
573 | # Arguments after -- should be passed through to nose. Argparse treats | |
551 | # everything after -- as regular positional arguments, so we separate them |
|
574 | # everything after -- as regular positional arguments, so we separate them | |
552 | # first. |
|
575 | # first. | |
553 | try: |
|
576 | try: | |
554 | ix = sys.argv.index('--') |
|
577 | ix = sys.argv.index('--') | |
555 | except ValueError: |
|
578 | except ValueError: | |
556 | to_parse = sys.argv[1:] |
|
579 | to_parse = sys.argv[1:] | |
557 | extra_args = [] |
|
580 | extra_args = [] | |
558 | else: |
|
581 | else: | |
559 | to_parse = sys.argv[1:ix] |
|
582 | to_parse = sys.argv[1:ix] | |
560 | extra_args = sys.argv[ix+1:] |
|
583 | extra_args = sys.argv[ix+1:] | |
561 |
|
584 | |||
562 | options = argparser.parse_args(to_parse) |
|
585 | options = argparser.parse_args(to_parse) | |
563 | options.extra_args = extra_args |
|
586 | options.extra_args = extra_args | |
564 |
|
587 | |||
565 | run_iptestall(options) |
|
588 | run_iptestall(options) | |
566 |
|
589 | |||
567 |
|
590 | |||
568 | if __name__ == '__main__': |
|
591 | if __name__ == '__main__': | |
569 | main() |
|
592 | main() |
@@ -1,1163 +1,1093 b'' | |||||
1 | ================= |
|
1 | ================= | |
2 | IPython reference |
|
2 | IPython reference | |
3 | ================= |
|
3 | ================= | |
4 |
|
4 | |||
5 | .. _command_line_options: |
|
5 | .. _command_line_options: | |
6 |
|
6 | |||
7 | Command-line usage |
|
7 | Command-line usage | |
8 | ================== |
|
8 | ================== | |
9 |
|
9 | |||
10 | You start IPython with the command:: |
|
10 | You start IPython with the command:: | |
11 |
|
11 | |||
12 | $ ipython [options] files |
|
12 | $ ipython [options] files | |
13 |
|
13 | |||
14 | If invoked with no options, it executes all the files listed in sequence |
|
14 | If invoked with no options, it executes all the files listed in sequence | |
15 | and drops you into the interpreter while still acknowledging any options |
|
15 | and drops you into the interpreter while still acknowledging any options | |
16 | you may have set in your ipython_config.py. This behavior is different from |
|
16 | you may have set in your ipython_config.py. This behavior is different from | |
17 | standard Python, which when called as python -i will only execute one |
|
17 | standard Python, which when called as python -i will only execute one | |
18 | file and ignore your configuration setup. |
|
18 | file and ignore your configuration setup. | |
19 |
|
19 | |||
20 | Please note that some of the configuration options are not available at |
|
20 | Please note that some of the configuration options are not available at | |
21 | the command line, simply because they are not practical here. Look into |
|
21 | the command line, simply because they are not practical here. Look into | |
22 | your configuration files for details on those. There are separate configuration |
|
22 | your configuration files for details on those. There are separate configuration | |
23 | files for each profile, and the files look like :file:`ipython_config.py` or |
|
23 | files for each profile, and the files look like :file:`ipython_config.py` or | |
24 | :file:`ipython_config_{frontendname}.py`. Profile directories look like |
|
24 | :file:`ipython_config_{frontendname}.py`. Profile directories look like | |
25 | :file:`profile_{profilename}` and are typically installed in the :envvar:`IPYTHONDIR` directory, |
|
25 | :file:`profile_{profilename}` and are typically installed in the :envvar:`IPYTHONDIR` directory, | |
26 | which defaults to :file:`$HOME/.ipython`. For Windows users, :envvar:`HOME` |
|
26 | which defaults to :file:`$HOME/.ipython`. For Windows users, :envvar:`HOME` | |
27 | resolves to :file:`C:\\Users\\{YourUserName}` in most instances. |
|
27 | resolves to :file:`C:\\Users\\{YourUserName}` in most instances. | |
28 |
|
28 | |||
29 |
|
||||
30 | Eventloop integration |
|
|||
31 | --------------------- |
|
|||
32 |
|
||||
33 | Previously IPython had command line options for controlling GUI event loop |
|
|||
34 | integration (-gthread, -qthread, -q4thread, -wthread, -pylab). As of IPython |
|
|||
35 | version 0.11, these have been removed. Please see the new ``%gui`` |
|
|||
36 | magic command or :ref:`this section <gui_support>` for details on the new |
|
|||
37 | interface, or specify the gui at the commandline:: |
|
|||
38 |
|
||||
39 | $ ipython --gui=qt |
|
|||
40 |
|
||||
41 |
|
||||
42 | Command-line Options |
|
29 | Command-line Options | |
43 | -------------------- |
|
30 | -------------------- | |
44 |
|
31 | |||
45 | To see the options IPython accepts, use ``ipython --help`` (and you probably |
|
32 | To see the options IPython accepts, use ``ipython --help`` (and you probably | |
46 | should run the output through a pager such as ``ipython --help | less`` for |
|
33 | should run the output through a pager such as ``ipython --help | less`` for | |
47 | more convenient reading). This shows all the options that have a single-word |
|
34 | more convenient reading). This shows all the options that have a single-word | |
48 | alias to control them, but IPython lets you configure all of its objects from |
|
35 | alias to control them, but IPython lets you configure all of its objects from | |
49 | the command-line by passing the full class name and a corresponding value; type |
|
36 | the command-line by passing the full class name and a corresponding value; type | |
50 | ``ipython --help-all`` to see this full list. For example:: |
|
37 | ``ipython --help-all`` to see this full list. For example:: | |
51 |
|
38 | |||
52 | ipython --matplotlib qt |
|
39 | ipython --matplotlib qt | |
53 |
|
40 | |||
54 | is equivalent to:: |
|
41 | is equivalent to:: | |
55 |
|
42 | |||
56 | ipython --TerminalIPythonApp.matplotlib='qt' |
|
43 | ipython --TerminalIPythonApp.matplotlib='qt' | |
57 |
|
44 | |||
58 | Note that in the second form, you *must* use the equal sign, as the expression |
|
45 | Note that in the second form, you *must* use the equal sign, as the expression | |
59 | is evaluated as an actual Python assignment. While in the above example the |
|
46 | is evaluated as an actual Python assignment. While in the above example the | |
60 | short form is more convenient, only the most common options have a short form, |
|
47 | short form is more convenient, only the most common options have a short form, | |
61 | while any configurable variable in IPython can be set at the command-line by |
|
48 | while any configurable variable in IPython can be set at the command-line by | |
62 | using the long form. This long form is the same syntax used in the |
|
49 | using the long form. This long form is the same syntax used in the | |
63 | configuration files, if you want to set these options permanently. |
|
50 | configuration files, if you want to set these options permanently. | |
64 |
|
51 | |||
65 |
|
52 | |||
66 | Interactive use |
|
53 | Interactive use | |
67 | =============== |
|
54 | =============== | |
68 |
|
55 | |||
69 | IPython is meant to work as a drop-in replacement for the standard interactive |
|
56 | IPython is meant to work as a drop-in replacement for the standard interactive | |
70 | interpreter. As such, any code which is valid python should execute normally |
|
57 | interpreter. As such, any code which is valid python should execute normally | |
71 | under IPython (cases where this is not true should be reported as bugs). It |
|
58 | under IPython (cases where this is not true should be reported as bugs). It | |
72 | does, however, offer many features which are not available at a standard python |
|
59 | does, however, offer many features which are not available at a standard python | |
73 | prompt. What follows is a list of these. |
|
60 | prompt. What follows is a list of these. | |
74 |
|
61 | |||
75 |
|
62 | |||
76 | Caution for Windows users |
|
63 | Caution for Windows users | |
77 | ------------------------- |
|
64 | ------------------------- | |
78 |
|
65 | |||
79 | Windows, unfortunately, uses the '\\' character as a path separator. This is a |
|
66 | Windows, unfortunately, uses the '\\' character as a path separator. This is a | |
80 | terrible choice, because '\\' also represents the escape character in most |
|
67 | terrible choice, because '\\' also represents the escape character in most | |
81 | modern programming languages, including Python. For this reason, using '/' |
|
68 | modern programming languages, including Python. For this reason, using '/' | |
82 | character is recommended if you have problems with ``\``. However, in Windows |
|
69 | character is recommended if you have problems with ``\``. However, in Windows | |
83 | commands '/' flags options, so you can not use it for the root directory. This |
|
70 | commands '/' flags options, so you can not use it for the root directory. This | |
84 | means that paths beginning at the root must be typed in a contrived manner |
|
71 | means that paths beginning at the root must be typed in a contrived manner | |
85 | like: ``%copy \opt/foo/bar.txt \tmp`` |
|
72 | like: ``%copy \opt/foo/bar.txt \tmp`` | |
86 |
|
73 | |||
87 | .. _magic: |
|
74 | .. _magic: | |
88 |
|
75 | |||
89 | Magic command system |
|
76 | Magic command system | |
90 | -------------------- |
|
77 | -------------------- | |
91 |
|
78 | |||
92 | IPython will treat any line whose first character is a % as a special |
|
79 | IPython will treat any line whose first character is a % as a special | |
93 | call to a 'magic' function. These allow you to control the behavior of |
|
80 | call to a 'magic' function. These allow you to control the behavior of | |
94 | IPython itself, plus a lot of system-type features. They are all |
|
81 | IPython itself, plus a lot of system-type features. They are all | |
95 | prefixed with a % character, but parameters are given without |
|
82 | prefixed with a % character, but parameters are given without | |
96 | parentheses or quotes. |
|
83 | parentheses or quotes. | |
97 |
|
84 | |||
98 | Lines that begin with ``%%`` signal a *cell magic*: they take as arguments not |
|
85 | Lines that begin with ``%%`` signal a *cell magic*: they take as arguments not | |
99 | only the rest of the current line, but all lines below them as well, in the |
|
86 | only the rest of the current line, but all lines below them as well, in the | |
100 | current execution block. Cell magics can in fact make arbitrary modifications |
|
87 | current execution block. Cell magics can in fact make arbitrary modifications | |
101 | to the input they receive, which need not even be valid Python code at all. |
|
88 | to the input they receive, which need not even be valid Python code at all. | |
102 | They receive the whole block as a single string. |
|
89 | They receive the whole block as a single string. | |
103 |
|
90 | |||
104 | As a line magic example, the ``%cd`` magic works just like the OS command of |
|
91 | As a line magic example, the ``%cd`` magic works just like the OS command of | |
105 | the same name:: |
|
92 | the same name:: | |
106 |
|
93 | |||
107 | In [8]: %cd |
|
94 | In [8]: %cd | |
108 | /home/fperez |
|
95 | /home/fperez | |
109 |
|
96 | |||
110 | The following uses the builtin ``timeit`` in cell mode:: |
|
97 | The following uses the builtin ``timeit`` in cell mode:: | |
111 |
|
98 | |||
112 | In [10]: %%timeit x = range(10000) |
|
99 | In [10]: %%timeit x = range(10000) | |
113 | ...: min(x) |
|
100 | ...: min(x) | |
114 | ...: max(x) |
|
101 | ...: max(x) | |
115 | ...: |
|
102 | ...: | |
116 | 1000 loops, best of 3: 438 us per loop |
|
103 | 1000 loops, best of 3: 438 us per loop | |
117 |
|
104 | |||
118 | In this case, ``x = range(10000)`` is called as the line argument, and the |
|
105 | In this case, ``x = range(10000)`` is called as the line argument, and the | |
119 | block with ``min(x)`` and ``max(x)`` is called as the cell body. The |
|
106 | block with ``min(x)`` and ``max(x)`` is called as the cell body. The | |
120 | ``timeit`` magic receives both. |
|
107 | ``timeit`` magic receives both. | |
121 |
|
108 | |||
122 | If you have 'automagic' enabled (as it by default), you don't need to type in |
|
109 | If you have 'automagic' enabled (as it by default), you don't need to type in | |
123 | the single ``%`` explicitly for line magics; IPython will scan its internal |
|
110 | the single ``%`` explicitly for line magics; IPython will scan its internal | |
124 | list of magic functions and call one if it exists. With automagic on you can |
|
111 | list of magic functions and call one if it exists. With automagic on you can | |
125 | then just type ``cd mydir`` to go to directory 'mydir':: |
|
112 | then just type ``cd mydir`` to go to directory 'mydir':: | |
126 |
|
113 | |||
127 | In [9]: cd mydir |
|
114 | In [9]: cd mydir | |
128 | /home/fperez/mydir |
|
115 | /home/fperez/mydir | |
129 |
|
116 | |||
130 | Note that cell magics *always* require an explicit ``%%`` prefix, automagic |
|
117 | Note that cell magics *always* require an explicit ``%%`` prefix, automagic | |
131 | calling only works for line magics. |
|
118 | calling only works for line magics. | |
132 |
|
119 | |||
133 | The automagic system has the lowest possible precedence in name searches, so |
|
120 | The automagic system has the lowest possible precedence in name searches, so | |
134 | defining an identifier with the same name as an existing magic function will |
|
121 | you can freely use variables with the same names as magic commands. If a magic | |
135 | shadow it for automagic use. You can still access the shadowed magic function |
|
122 | command is 'shadowed' by a variable, you will need the explicit ``%`` prefix to | |
136 | by explicitly using the ``%`` character at the beginning of the line. |
|
123 | use it: | |
137 |
|
||||
138 | An example (with automagic on) should clarify all this: |
|
|||
139 |
|
124 | |||
140 | .. sourcecode:: ipython |
|
125 | .. sourcecode:: ipython | |
141 |
|
126 | |||
142 | In [1]: cd ipython # %cd is called by automagic |
|
127 | In [1]: cd ipython # %cd is called by automagic | |
143 | /home/fperez/ipython |
|
128 | /home/fperez/ipython | |
144 |
|
129 | |||
145 | In [2]: cd=1 # now cd is just a variable |
|
130 | In [2]: cd=1 # now cd is just a variable | |
146 |
|
131 | |||
147 | In [3]: cd .. # and doesn't work as a function anymore |
|
132 | In [3]: cd .. # and doesn't work as a function anymore | |
148 | File "<ipython-input-3-9fedb3aff56c>", line 1 |
|
133 | File "<ipython-input-3-9fedb3aff56c>", line 1 | |
149 | cd .. |
|
134 | cd .. | |
150 | ^ |
|
135 | ^ | |
151 | SyntaxError: invalid syntax |
|
136 | SyntaxError: invalid syntax | |
152 |
|
137 | |||
153 |
|
138 | |||
154 | In [4]: %cd .. # but %cd always works |
|
139 | In [4]: %cd .. # but %cd always works | |
155 | /home/fperez |
|
140 | /home/fperez | |
156 |
|
141 | |||
157 | In [5]: del cd # if you remove the cd variable, automagic works again |
|
142 | In [5]: del cd # if you remove the cd variable, automagic works again | |
158 |
|
143 | |||
159 | In [6]: cd ipython |
|
144 | In [6]: cd ipython | |
160 |
|
145 | |||
161 | /home/fperez/ipython |
|
146 | /home/fperez/ipython | |
162 |
|
147 | |||
163 | .. _defining_magics: |
|
148 | .. _defining_magics: | |
164 |
|
149 | |||
165 | Defining your own magics |
|
150 | Defining your own magics | |
166 | ++++++++++++++++++++++++ |
|
151 | ++++++++++++++++++++++++ | |
167 |
|
152 | |||
168 | There are two main ways to define your own magic functions: from standalone |
|
153 | There are two main ways to define your own magic functions: from standalone | |
169 | functions and by inheriting from a base class provided by IPython: |
|
154 | functions and by inheriting from a base class provided by IPython: | |
170 | :class:`IPython.core.magic.Magics`. Below we show code you can place in a file |
|
155 | :class:`IPython.core.magic.Magics`. Below we show code you can place in a file | |
171 | that you load from your configuration, such as any file in the ``startup`` |
|
156 | that you load from your configuration, such as any file in the ``startup`` | |
172 | subdirectory of your default IPython profile. |
|
157 | subdirectory of your default IPython profile. | |
173 |
|
158 | |||
174 | First, let us see the simplest case. The following shows how to create a line |
|
159 | First, let us see the simplest case. The following shows how to create a line | |
175 | magic, a cell one and one that works in both modes, using just plain functions: |
|
160 | magic, a cell one and one that works in both modes, using just plain functions: | |
176 |
|
161 | |||
177 | .. sourcecode:: python |
|
162 | .. sourcecode:: python | |
178 |
|
163 | |||
179 | from IPython.core.magic import (register_line_magic, register_cell_magic, |
|
164 | from IPython.core.magic import (register_line_magic, register_cell_magic, | |
180 | register_line_cell_magic) |
|
165 | register_line_cell_magic) | |
181 |
|
166 | |||
182 | @register_line_magic |
|
167 | @register_line_magic | |
183 | def lmagic(line): |
|
168 | def lmagic(line): | |
184 | "my line magic" |
|
169 | "my line magic" | |
185 | return line |
|
170 | return line | |
186 |
|
171 | |||
187 | @register_cell_magic |
|
172 | @register_cell_magic | |
188 | def cmagic(line, cell): |
|
173 | def cmagic(line, cell): | |
189 | "my cell magic" |
|
174 | "my cell magic" | |
190 | return line, cell |
|
175 | return line, cell | |
191 |
|
176 | |||
192 | @register_line_cell_magic |
|
177 | @register_line_cell_magic | |
193 | def lcmagic(line, cell=None): |
|
178 | def lcmagic(line, cell=None): | |
194 | "Magic that works both as %lcmagic and as %%lcmagic" |
|
179 | "Magic that works both as %lcmagic and as %%lcmagic" | |
195 | if cell is None: |
|
180 | if cell is None: | |
196 | print("Called as line magic") |
|
181 | print("Called as line magic") | |
197 | return line |
|
182 | return line | |
198 | else: |
|
183 | else: | |
199 | print("Called as cell magic") |
|
184 | print("Called as cell magic") | |
200 | return line, cell |
|
185 | return line, cell | |
201 |
|
186 | |||
202 | # We delete these to avoid name conflicts for automagic to work |
|
187 | # We delete these to avoid name conflicts for automagic to work | |
203 | del lmagic, lcmagic |
|
188 | del lmagic, lcmagic | |
204 |
|
189 | |||
205 |
|
190 | |||
206 | You can also create magics of all three kinds by inheriting from the |
|
191 | You can also create magics of all three kinds by inheriting from the | |
207 | :class:`IPython.core.magic.Magics` class. This lets you create magics that can |
|
192 | :class:`IPython.core.magic.Magics` class. This lets you create magics that can | |
208 | potentially hold state in between calls, and that have full access to the main |
|
193 | potentially hold state in between calls, and that have full access to the main | |
209 | IPython object: |
|
194 | IPython object: | |
210 |
|
195 | |||
211 | .. sourcecode:: python |
|
196 | .. sourcecode:: python | |
212 |
|
197 | |||
213 | # This code can be put in any Python module, it does not require IPython |
|
198 | # This code can be put in any Python module, it does not require IPython | |
214 | # itself to be running already. It only creates the magics subclass but |
|
199 | # itself to be running already. It only creates the magics subclass but | |
215 | # doesn't instantiate it yet. |
|
200 | # doesn't instantiate it yet. | |
216 | from __future__ import print_function |
|
201 | from __future__ import print_function | |
217 | from IPython.core.magic import (Magics, magics_class, line_magic, |
|
202 | from IPython.core.magic import (Magics, magics_class, line_magic, | |
218 | cell_magic, line_cell_magic) |
|
203 | cell_magic, line_cell_magic) | |
219 |
|
204 | |||
220 | # The class MUST call this class decorator at creation time |
|
205 | # The class MUST call this class decorator at creation time | |
221 | @magics_class |
|
206 | @magics_class | |
222 | class MyMagics(Magics): |
|
207 | class MyMagics(Magics): | |
223 |
|
208 | |||
224 | @line_magic |
|
209 | @line_magic | |
225 | def lmagic(self, line): |
|
210 | def lmagic(self, line): | |
226 | "my line magic" |
|
211 | "my line magic" | |
227 | print("Full access to the main IPython object:", self.shell) |
|
212 | print("Full access to the main IPython object:", self.shell) | |
228 | print("Variables in the user namespace:", list(self.shell.user_ns.keys())) |
|
213 | print("Variables in the user namespace:", list(self.shell.user_ns.keys())) | |
229 | return line |
|
214 | return line | |
230 |
|
215 | |||
231 | @cell_magic |
|
216 | @cell_magic | |
232 | def cmagic(self, line, cell): |
|
217 | def cmagic(self, line, cell): | |
233 | "my cell magic" |
|
218 | "my cell magic" | |
234 | return line, cell |
|
219 | return line, cell | |
235 |
|
220 | |||
236 | @line_cell_magic |
|
221 | @line_cell_magic | |
237 | def lcmagic(self, line, cell=None): |
|
222 | def lcmagic(self, line, cell=None): | |
238 | "Magic that works both as %lcmagic and as %%lcmagic" |
|
223 | "Magic that works both as %lcmagic and as %%lcmagic" | |
239 | if cell is None: |
|
224 | if cell is None: | |
240 | print("Called as line magic") |
|
225 | print("Called as line magic") | |
241 | return line |
|
226 | return line | |
242 | else: |
|
227 | else: | |
243 | print("Called as cell magic") |
|
228 | print("Called as cell magic") | |
244 | return line, cell |
|
229 | return line, cell | |
245 |
|
230 | |||
246 |
|
231 | |||
247 | # In order to actually use these magics, you must register them with a |
|
232 | # In order to actually use these magics, you must register them with a | |
248 | # running IPython. This code must be placed in a file that is loaded once |
|
233 | # running IPython. This code must be placed in a file that is loaded once | |
249 | # IPython is up and running: |
|
234 | # IPython is up and running: | |
250 | ip = get_ipython() |
|
235 | ip = get_ipython() | |
251 | # You can register the class itself without instantiating it. IPython will |
|
236 | # You can register the class itself without instantiating it. IPython will | |
252 | # call the default constructor on it. |
|
237 | # call the default constructor on it. | |
253 | ip.register_magics(MyMagics) |
|
238 | ip.register_magics(MyMagics) | |
254 |
|
239 | |||
255 | If you want to create a class with a different constructor that holds |
|
240 | If you want to create a class with a different constructor that holds | |
256 | additional state, then you should always call the parent constructor and |
|
241 | additional state, then you should always call the parent constructor and | |
257 | instantiate the class yourself before registration: |
|
242 | instantiate the class yourself before registration: | |
258 |
|
243 | |||
259 | .. sourcecode:: python |
|
244 | .. sourcecode:: python | |
260 |
|
245 | |||
261 | @magics_class |
|
246 | @magics_class | |
262 | class StatefulMagics(Magics): |
|
247 | class StatefulMagics(Magics): | |
263 | "Magics that hold additional state" |
|
248 | "Magics that hold additional state" | |
264 |
|
249 | |||
265 | def __init__(self, shell, data): |
|
250 | def __init__(self, shell, data): | |
266 | # You must call the parent constructor |
|
251 | # You must call the parent constructor | |
267 | super(StatefulMagics, self).__init__(shell) |
|
252 | super(StatefulMagics, self).__init__(shell) | |
268 | self.data = data |
|
253 | self.data = data | |
269 |
|
254 | |||
270 | # etc... |
|
255 | # etc... | |
271 |
|
256 | |||
272 | # This class must then be registered with a manually created instance, |
|
257 | # This class must then be registered with a manually created instance, | |
273 | # since its constructor has different arguments from the default: |
|
258 | # since its constructor has different arguments from the default: | |
274 | ip = get_ipython() |
|
259 | ip = get_ipython() | |
275 | magics = StatefulMagics(ip, some_data) |
|
260 | magics = StatefulMagics(ip, some_data) | |
276 | ip.register_magics(magics) |
|
261 | ip.register_magics(magics) | |
277 |
|
262 | |||
278 |
|
263 | |||
279 | In earlier versions, IPython had an API for the creation of line magics (cell |
|
264 | In earlier versions, IPython had an API for the creation of line magics (cell | |
280 | magics did not exist at the time) that required you to create functions with a |
|
265 | magics did not exist at the time) that required you to create functions with a | |
281 | method-looking signature and to manually pass both the function and the name. |
|
266 | method-looking signature and to manually pass both the function and the name. | |
282 | While this API is no longer recommended, it remains indefinitely supported for |
|
267 | While this API is no longer recommended, it remains indefinitely supported for | |
283 | backwards compatibility purposes. With the old API, you'd create a magic as |
|
268 | backwards compatibility purposes. With the old API, you'd create a magic as | |
284 | follows: |
|
269 | follows: | |
285 |
|
270 | |||
286 | .. sourcecode:: python |
|
271 | .. sourcecode:: python | |
287 |
|
272 | |||
288 | def func(self, line): |
|
273 | def func(self, line): | |
289 | print("Line magic called with line:", line) |
|
274 | print("Line magic called with line:", line) | |
290 | print("IPython object:", self.shell) |
|
275 | print("IPython object:", self.shell) | |
291 |
|
276 | |||
292 | ip = get_ipython() |
|
277 | ip = get_ipython() | |
293 | # Declare this function as the magic %mycommand |
|
278 | # Declare this function as the magic %mycommand | |
294 | ip.define_magic('mycommand', func) |
|
279 | ip.define_magic('mycommand', func) | |
295 |
|
280 | |||
296 | Type ``%magic`` for more information, including a list of all available magic |
|
281 | Type ``%magic`` for more information, including a list of all available magic | |
297 | functions at any time and their docstrings. You can also type |
|
282 | functions at any time and their docstrings. You can also type | |
298 | ``%magic_function_name?`` (see :ref:`below <dynamic_object_info>` for |
|
283 | ``%magic_function_name?`` (see :ref:`below <dynamic_object_info>` for | |
299 | information on the '?' system) to get information about any particular magic |
|
284 | information on the '?' system) to get information about any particular magic | |
300 | function you are interested in. |
|
285 | function you are interested in. | |
301 |
|
286 | |||
302 | The API documentation for the :mod:`IPython.core.magic` module contains the full |
|
287 | The API documentation for the :mod:`IPython.core.magic` module contains the full | |
303 | docstrings of all currently available magic commands. |
|
288 | docstrings of all currently available magic commands. | |
304 |
|
289 | |||
305 |
|
290 | |||
306 | Access to the standard Python help |
|
291 | Access to the standard Python help | |
307 | ---------------------------------- |
|
292 | ---------------------------------- | |
308 |
|
293 | |||
309 | Simply type ``help()`` to access Python's standard help system. You can |
|
294 | Simply type ``help()`` to access Python's standard help system. You can | |
310 | also type ``help(object)`` for information about a given object, or |
|
295 | also type ``help(object)`` for information about a given object, or | |
311 | ``help('keyword')`` for information on a keyword. You may need to configure your |
|
296 | ``help('keyword')`` for information on a keyword. You may need to configure your | |
312 | PYTHONDOCS environment variable for this feature to work correctly. |
|
297 | PYTHONDOCS environment variable for this feature to work correctly. | |
313 |
|
298 | |||
314 | .. _dynamic_object_info: |
|
299 | .. _dynamic_object_info: | |
315 |
|
300 | |||
316 | Dynamic object information |
|
301 | Dynamic object information | |
317 | -------------------------- |
|
302 | -------------------------- | |
318 |
|
303 | |||
319 | Typing ``?word`` or ``word?`` prints detailed information about an object. If |
|
304 | Typing ``?word`` or ``word?`` prints detailed information about an object. If | |
320 | certain strings in the object are too long (e.g. function signatures) they get |
|
305 | certain strings in the object are too long (e.g. function signatures) they get | |
321 | snipped in the center for brevity. This system gives access variable types and |
|
306 | snipped in the center for brevity. This system gives access variable types and | |
322 | values, docstrings, function prototypes and other useful information. |
|
307 | values, docstrings, function prototypes and other useful information. | |
323 |
|
308 | |||
324 | If the information will not fit in the terminal, it is displayed in a pager |
|
309 | If the information will not fit in the terminal, it is displayed in a pager | |
325 | (``less`` if available, otherwise a basic internal pager). |
|
310 | (``less`` if available, otherwise a basic internal pager). | |
326 |
|
311 | |||
327 | Typing ``??word`` or ``word??`` gives access to the full information, including |
|
312 | Typing ``??word`` or ``word??`` gives access to the full information, including | |
328 | the source code where possible. Long strings are not snipped. |
|
313 | the source code where possible. Long strings are not snipped. | |
329 |
|
314 | |||
330 | The following magic functions are particularly useful for gathering |
|
315 | The following magic functions are particularly useful for gathering | |
331 | information about your working environment. You can get more details by |
|
316 | information about your working environment. You can get more details by | |
332 | typing ``%magic`` or querying them individually (``%function_name?``); |
|
317 | typing ``%magic`` or querying them individually (``%function_name?``); | |
333 | this is just a summary: |
|
318 | this is just a summary: | |
334 |
|
319 | |||
335 | * **%pdoc <object>**: Print (or run through a pager if too long) the |
|
320 | * **%pdoc <object>**: Print (or run through a pager if too long) the | |
336 | docstring for an object. If the given object is a class, it will |
|
321 | docstring for an object. If the given object is a class, it will | |
337 | print both the class and the constructor docstrings. |
|
322 | print both the class and the constructor docstrings. | |
338 | * **%pdef <object>**: Print the call signature for any callable |
|
323 | * **%pdef <object>**: Print the call signature for any callable | |
339 | object. If the object is a class, print the constructor information. |
|
324 | object. If the object is a class, print the constructor information. | |
340 | * **%psource <object>**: Print (or run through a pager if too long) |
|
325 | * **%psource <object>**: Print (or run through a pager if too long) | |
341 | the source code for an object. |
|
326 | the source code for an object. | |
342 | * **%pfile <object>**: Show the entire source file where an object was |
|
327 | * **%pfile <object>**: Show the entire source file where an object was | |
343 | defined via a pager, opening it at the line where the object |
|
328 | defined via a pager, opening it at the line where the object | |
344 | definition begins. |
|
329 | definition begins. | |
345 | * **%who/%whos**: These functions give information about identifiers |
|
330 | * **%who/%whos**: These functions give information about identifiers | |
346 | you have defined interactively (not things you loaded or defined |
|
331 | you have defined interactively (not things you loaded or defined | |
347 | in your configuration files). %who just prints a list of |
|
332 | in your configuration files). %who just prints a list of | |
348 | identifiers and %whos prints a table with some basic details about |
|
333 | identifiers and %whos prints a table with some basic details about | |
349 | each identifier. |
|
334 | each identifier. | |
350 |
|
335 | |||
351 | Note that the dynamic object information functions (?/??, ``%pdoc``, |
|
336 | Note that the dynamic object information functions (?/??, ``%pdoc``, | |
352 | ``%pfile``, ``%pdef``, ``%psource``) work on object attributes, as well as |
|
337 | ``%pfile``, ``%pdef``, ``%psource``) work on object attributes, as well as | |
353 | directly on variables. For example, after doing ``import os``, you can use |
|
338 | directly on variables. For example, after doing ``import os``, you can use | |
354 | ``os.path.abspath??``. |
|
339 | ``os.path.abspath??``. | |
355 |
|
340 | |||
356 | .. _readline: |
|
341 | .. _readline: | |
357 |
|
342 | |||
358 | Readline-based features |
|
343 | Readline-based features | |
359 | ----------------------- |
|
344 | ----------------------- | |
360 |
|
345 | |||
361 | These features require the GNU readline library, so they won't work if your |
|
346 | These features require the GNU readline library, so they won't work if your | |
362 | Python installation lacks readline support. We will first describe the default |
|
347 | Python installation lacks readline support. We will first describe the default | |
363 | behavior IPython uses, and then how to change it to suit your preferences. |
|
348 | behavior IPython uses, and then how to change it to suit your preferences. | |
364 |
|
349 | |||
365 |
|
350 | |||
366 | Command line completion |
|
351 | Command line completion | |
367 | +++++++++++++++++++++++ |
|
352 | +++++++++++++++++++++++ | |
368 |
|
353 | |||
369 | At any time, hitting TAB will complete any available python commands or |
|
354 | At any time, hitting TAB will complete any available python commands or | |
370 | variable names, and show you a list of the possible completions if |
|
355 | variable names, and show you a list of the possible completions if | |
371 | there's no unambiguous one. It will also complete filenames in the |
|
356 | there's no unambiguous one. It will also complete filenames in the | |
372 | current directory if no python names match what you've typed so far. |
|
357 | current directory if no python names match what you've typed so far. | |
373 |
|
358 | |||
374 |
|
359 | |||
375 | Search command history |
|
360 | Search command history | |
376 | ++++++++++++++++++++++ |
|
361 | ++++++++++++++++++++++ | |
377 |
|
362 | |||
378 | IPython provides two ways for searching through previous input and thus |
|
363 | IPython provides two ways for searching through previous input and thus | |
379 | reduce the need for repetitive typing: |
|
364 | reduce the need for repetitive typing: | |
380 |
|
365 | |||
381 | 1. Start typing, and then use Ctrl-p (previous,up) and Ctrl-n |
|
366 | 1. Start typing, and then use the up and down arrow keys (or :kbd:`Ctrl-p` | |
382 |
|
|
367 | and :kbd:`Ctrl-n`) to search through only the history items that match | |
383 |
what you've typed so far. |
|
368 | what you've typed so far. | |
384 | prompt, they just behave like normal arrow keys. |
|
369 | 2. Hit :kbd:`Ctrl-r`: to open a search prompt. Begin typing and the system | |
385 | 2. Hit Ctrl-r: opens a search prompt. Begin typing and the system |
|
|||
386 | searches your history for lines that contain what you've typed so |
|
370 | searches your history for lines that contain what you've typed so | |
387 | far, completing as much as it can. |
|
371 | far, completing as much as it can. | |
388 |
|
372 | |||
389 |
|
||||
390 | Persistent command history across sessions |
|
|||
391 | ++++++++++++++++++++++++++++++++++++++++++ |
|
|||
392 |
|
||||
393 | IPython will save your input history when it leaves and reload it next |
|
373 | IPython will save your input history when it leaves and reload it next | |
394 | time you restart it. By default, the history file is named |
|
374 | time you restart it. By default, the history file is named | |
395 | $IPYTHONDIR/profile_<name>/history.sqlite. This allows you to keep |
|
375 | :file:`.ipython/profile_{name}/history.sqlite`. | |
396 | separate histories related to various tasks: commands related to |
|
|||
397 | numerical work will not be clobbered by a system shell history, for |
|
|||
398 | example. |
|
|||
399 |
|
||||
400 |
|
376 | |||
401 | Autoindent |
|
377 | Autoindent | |
402 | ++++++++++ |
|
378 | ++++++++++ | |
403 |
|
379 | |||
404 | IPython can recognize lines ending in ':' and indent the next line, |
|
380 | IPython can recognize lines ending in ':' and indent the next line, | |
405 | while also un-indenting automatically after 'raise' or 'return'. |
|
381 | while also un-indenting automatically after 'raise' or 'return'. | |
406 |
|
382 | |||
407 | This feature uses the readline library, so it will honor your |
|
383 | This feature uses the readline library, so it will honor your | |
408 | :file:`~/.inputrc` configuration (or whatever file your INPUTRC variable points |
|
384 | :file:`~/.inputrc` configuration (or whatever file your :envvar:`INPUTRC` environment variable points | |
409 | to). Adding the following lines to your :file:`.inputrc` file can make |
|
385 | to). Adding the following lines to your :file:`.inputrc` file can make | |
410 | indenting/unindenting more convenient (M-i indents, M-u unindents):: |
|
386 | indenting/unindenting more convenient (M-i indents, M-u unindents):: | |
411 |
|
387 | |||
412 | # if you don't already have a ~/.inputrc file, you need this include: |
|
388 | # if you don't already have a ~/.inputrc file, you need this include: | |
413 | $include /etc/inputrc |
|
389 | $include /etc/inputrc | |
414 |
|
390 | |||
415 | $if Python |
|
391 | $if Python | |
416 | "\M-i": " " |
|
392 | "\M-i": " " | |
417 | "\M-u": "\d\d\d\d" |
|
393 | "\M-u": "\d\d\d\d" | |
418 | $endif |
|
394 | $endif | |
419 |
|
395 | |||
420 | Note that there are 4 spaces between the quote marks after "M-i" above. |
|
396 | Note that there are 4 spaces between the quote marks after "M-i" above. | |
421 |
|
397 | |||
422 | .. warning:: |
|
398 | .. warning:: | |
423 |
|
399 | |||
424 | Setting the above indents will cause problems with unicode text entry in |
|
400 | Setting the above indents will cause problems with unicode text entry in | |
425 | the terminal. |
|
401 | the terminal. | |
426 |
|
402 | |||
427 | .. warning:: |
|
403 | .. warning:: | |
428 |
|
404 | |||
429 | Autoindent is ON by default, but it can cause problems with the pasting of |
|
405 | Autoindent is ON by default, but it can cause problems with the pasting of | |
430 | multi-line indented code (the pasted code gets re-indented on each line). A |
|
406 | multi-line indented code (the pasted code gets re-indented on each line). A | |
431 | magic function %autoindent allows you to toggle it on/off at runtime. You |
|
407 | magic function %autoindent allows you to toggle it on/off at runtime. You | |
432 | can also disable it permanently on in your :file:`ipython_config.py` file |
|
408 | can also disable it permanently on in your :file:`ipython_config.py` file | |
433 | (set TerminalInteractiveShell.autoindent=False). |
|
409 | (set TerminalInteractiveShell.autoindent=False). | |
434 |
|
410 | |||
435 | If you want to paste multiple lines in the terminal, it is recommended that |
|
411 | If you want to paste multiple lines in the terminal, it is recommended that | |
436 | you use ``%paste``. |
|
412 | you use ``%paste``. | |
437 |
|
413 | |||
438 |
|
414 | |||
439 | Customizing readline behavior |
|
415 | Customizing readline behavior | |
440 | +++++++++++++++++++++++++++++ |
|
416 | +++++++++++++++++++++++++++++ | |
441 |
|
417 | |||
442 | All these features are based on the GNU readline library, which has an |
|
418 | All these features are based on the GNU readline library, which has an | |
443 | extremely customizable interface. Normally, readline is configured via a |
|
419 | extremely customizable interface. Normally, readline is configured via a | |
444 | file which defines the behavior of the library; the details of the |
|
420 | :file:`.inputrc` file. IPython respects this, and you can also customise readline | |
445 | syntax for this can be found in the readline documentation available |
|
421 | by setting the following :doc:`configuration </config/intro>` options: | |
446 | with your system or on the Internet. IPython doesn't read this file (if |
|
422 | ||
447 | it exists) directly, but it does support passing to readline valid |
|
423 | * ``InteractiveShell.readline_parse_and_bind``: this holds a list of strings to be executed | |
448 | options via a simple interface. In brief, you can customize readline by |
|
|||
449 | setting the following options in your configuration file (note |
|
|||
450 | that these options can not be specified at the command line): |
|
|||
451 |
|
||||
452 | * **readline_parse_and_bind**: this holds a list of strings to be executed |
|
|||
453 | via a readline.parse_and_bind() command. The syntax for valid commands |
|
424 | via a readline.parse_and_bind() command. The syntax for valid commands | |
454 | of this kind can be found by reading the documentation for the GNU |
|
425 | of this kind can be found by reading the documentation for the GNU | |
455 | readline library, as these commands are of the kind which readline |
|
426 | readline library, as these commands are of the kind which readline | |
456 | accepts in its configuration file. |
|
427 | accepts in its configuration file. | |
457 |
* |
|
428 | * ``InteractiveShell.readline_remove_delims``: a string of characters to be removed | |
458 | from the default word-delimiters list used by readline, so that |
|
429 | from the default word-delimiters list used by readline, so that | |
459 | completions may be performed on strings which contain them. Do not |
|
430 | completions may be performed on strings which contain them. Do not | |
460 | change the default value unless you know what you're doing. |
|
431 | change the default value unless you know what you're doing. | |
461 |
|
432 | |||
462 | You will find the default values in your configuration file. |
|
433 | You will find the default values in your configuration file. | |
463 |
|
434 | |||
464 |
|
435 | |||
465 | Session logging and restoring |
|
436 | Session logging and restoring | |
466 | ----------------------------- |
|
437 | ----------------------------- | |
467 |
|
438 | |||
468 | You can log all input from a session either by starting IPython with the |
|
439 | You can log all input from a session either by starting IPython with the | |
469 | command line switch ``--logfile=foo.py`` (see :ref:`here <command_line_options>`) |
|
440 | command line switch ``--logfile=foo.py`` (see :ref:`here <command_line_options>`) | |
470 | or by activating the logging at any moment with the magic function %logstart. |
|
441 | or by activating the logging at any moment with the magic function %logstart. | |
471 |
|
442 | |||
472 | Log files can later be reloaded by running them as scripts and IPython |
|
443 | Log files can later be reloaded by running them as scripts and IPython | |
473 | will attempt to 'replay' the log by executing all the lines in it, thus |
|
444 | will attempt to 'replay' the log by executing all the lines in it, thus | |
474 | restoring the state of a previous session. This feature is not quite |
|
445 | restoring the state of a previous session. This feature is not quite | |
475 | perfect, but can still be useful in many cases. |
|
446 | perfect, but can still be useful in many cases. | |
476 |
|
447 | |||
477 | The log files can also be used as a way to have a permanent record of |
|
448 | The log files can also be used as a way to have a permanent record of | |
478 | any code you wrote while experimenting. Log files are regular text files |
|
449 | any code you wrote while experimenting. Log files are regular text files | |
479 | which you can later open in your favorite text editor to extract code or |
|
450 | which you can later open in your favorite text editor to extract code or | |
480 | to 'clean them up' before using them to replay a session. |
|
451 | to 'clean them up' before using them to replay a session. | |
481 |
|
452 | |||
482 | The `%logstart` function for activating logging in mid-session is used as |
|
453 | The `%logstart` function for activating logging in mid-session is used as | |
483 | follows:: |
|
454 | follows:: | |
484 |
|
455 | |||
485 | %logstart [log_name [log_mode]] |
|
456 | %logstart [log_name [log_mode]] | |
486 |
|
457 | |||
487 | If no name is given, it defaults to a file named 'ipython_log.py' in your |
|
458 | If no name is given, it defaults to a file named 'ipython_log.py' in your | |
488 | current working directory, in 'rotate' mode (see below). |
|
459 | current working directory, in 'rotate' mode (see below). | |
489 |
|
460 | |||
490 | '%logstart name' saves to file 'name' in 'backup' mode. It saves your |
|
461 | '%logstart name' saves to file 'name' in 'backup' mode. It saves your | |
491 | history up to that point and then continues logging. |
|
462 | history up to that point and then continues logging. | |
492 |
|
463 | |||
493 | %logstart takes a second optional parameter: logging mode. This can be |
|
464 | %logstart takes a second optional parameter: logging mode. This can be | |
494 | one of (note that the modes are given unquoted): |
|
465 | one of (note that the modes are given unquoted): | |
495 |
|
466 | |||
496 | * [over:] overwrite existing log_name. |
|
467 | * [over:] overwrite existing log_name. | |
497 | * [backup:] rename (if exists) to log_name~ and start log_name. |
|
468 | * [backup:] rename (if exists) to log_name~ and start log_name. | |
498 | * [append:] well, that says it. |
|
469 | * [append:] well, that says it. | |
499 | * [rotate:] create rotating logs log_name.1~, log_name.2~, etc. |
|
470 | * [rotate:] create rotating logs log_name.1~, log_name.2~, etc. | |
500 |
|
471 | |||
501 | The %logoff and %logon functions allow you to temporarily stop and |
|
472 | The %logoff and %logon functions allow you to temporarily stop and | |
502 | resume logging to a file which had previously been started with |
|
473 | resume logging to a file which had previously been started with | |
503 | %logstart. They will fail (with an explanation) if you try to use them |
|
474 | %logstart. They will fail (with an explanation) if you try to use them | |
504 | before logging has been started. |
|
475 | before logging has been started. | |
505 |
|
476 | |||
506 | .. _system_shell_access: |
|
477 | .. _system_shell_access: | |
507 |
|
478 | |||
508 | System shell access |
|
479 | System shell access | |
509 | ------------------- |
|
480 | ------------------- | |
510 |
|
481 | |||
511 | Any input line beginning with a ! character is passed verbatim (minus |
|
482 | Any input line beginning with a ! character is passed verbatim (minus | |
512 | the !, of course) to the underlying operating system. For example, |
|
483 | the !, of course) to the underlying operating system. For example, | |
513 | typing ``!ls`` will run 'ls' in the current directory. |
|
484 | typing ``!ls`` will run 'ls' in the current directory. | |
514 |
|
485 | |||
515 | Manual capture of command output |
|
486 | Manual capture of command output | |
516 | -------------------------------- |
|
487 | -------------------------------- | |
517 |
|
488 | |||
518 | You can assign the result of a system command to a Python variable with the |
|
489 | You can assign the result of a system command to a Python variable with the | |
519 | syntax ``myfiles = !ls``. This gets machine readable output from stdout |
|
490 | syntax ``myfiles = !ls``. This gets machine readable output from stdout | |
520 | (e.g. without colours), and splits on newlines. To explicitly get this sort of |
|
491 | (e.g. without colours), and splits on newlines. To explicitly get this sort of | |
521 | output without assigning to a variable, use two exclamation marks (``!!ls``) or |
|
492 | output without assigning to a variable, use two exclamation marks (``!!ls``) or | |
522 | the ``%sx`` magic command. |
|
493 | the ``%sx`` magic command. | |
523 |
|
494 | |||
524 | The captured list has some convenience features. ``myfiles.n`` or ``myfiles.s`` |
|
495 | The captured list has some convenience features. ``myfiles.n`` or ``myfiles.s`` | |
525 | returns a string delimited by newlines or spaces, respectively. ``myfiles.p`` |
|
496 | returns a string delimited by newlines or spaces, respectively. ``myfiles.p`` | |
526 | produces `path objects <http://pypi.python.org/pypi/path.py>`_ from the list items. |
|
497 | produces `path objects <http://pypi.python.org/pypi/path.py>`_ from the list items. | |
527 | See :ref:`string_lists` for details. |
|
498 | See :ref:`string_lists` for details. | |
528 |
|
499 | |||
529 | IPython also allows you to expand the value of python variables when |
|
500 | IPython also allows you to expand the value of python variables when | |
530 | making system calls. Wrap variables or expressions in {braces}:: |
|
501 | making system calls. Wrap variables or expressions in {braces}:: | |
531 |
|
502 | |||
532 | In [1]: pyvar = 'Hello world' |
|
503 | In [1]: pyvar = 'Hello world' | |
533 | In [2]: !echo "A python variable: {pyvar}" |
|
504 | In [2]: !echo "A python variable: {pyvar}" | |
534 | A python variable: Hello world |
|
505 | A python variable: Hello world | |
535 | In [3]: import math |
|
506 | In [3]: import math | |
536 | In [4]: x = 8 |
|
507 | In [4]: x = 8 | |
537 | In [5]: !echo {math.factorial(x)} |
|
508 | In [5]: !echo {math.factorial(x)} | |
538 | 40320 |
|
509 | 40320 | |
539 |
|
510 | |||
540 | For simple cases, you can alternatively prepend $ to a variable name:: |
|
511 | For simple cases, you can alternatively prepend $ to a variable name:: | |
541 |
|
512 | |||
542 | In [6]: !echo $sys.argv |
|
513 | In [6]: !echo $sys.argv | |
543 | [/home/fperez/usr/bin/ipython] |
|
514 | [/home/fperez/usr/bin/ipython] | |
544 | In [7]: !echo "A system variable: $$HOME" # Use $$ for literal $ |
|
515 | In [7]: !echo "A system variable: $$HOME" # Use $$ for literal $ | |
545 | A system variable: /home/fperez |
|
516 | A system variable: /home/fperez | |
546 |
|
517 | |||
547 | System command aliases |
|
518 | System command aliases | |
548 | ---------------------- |
|
519 | ---------------------- | |
549 |
|
520 | |||
550 | The %alias magic function allows you to define magic functions which are in fact |
|
521 | The %alias magic function allows you to define magic functions which are in fact | |
551 | system shell commands. These aliases can have parameters. |
|
522 | system shell commands. These aliases can have parameters. | |
552 |
|
523 | |||
553 | ``%alias alias_name cmd`` defines 'alias_name' as an alias for 'cmd' |
|
524 | ``%alias alias_name cmd`` defines 'alias_name' as an alias for 'cmd' | |
554 |
|
525 | |||
555 | Then, typing ``alias_name params`` will execute the system command 'cmd |
|
526 | Then, typing ``alias_name params`` will execute the system command 'cmd | |
556 | params' (from your underlying operating system). |
|
527 | params' (from your underlying operating system). | |
557 |
|
528 | |||
558 | You can also define aliases with parameters using %s specifiers (one per |
|
529 | You can also define aliases with parameters using %s specifiers (one per | |
559 | parameter). The following example defines the parts function as an |
|
530 | parameter). The following example defines the parts function as an | |
560 | alias to the command 'echo first %s second %s' where each %s will be |
|
531 | alias to the command 'echo first %s second %s' where each %s will be | |
561 | replaced by a positional parameter to the call to %parts:: |
|
532 | replaced by a positional parameter to the call to %parts:: | |
562 |
|
533 | |||
563 | In [1]: %alias parts echo first %s second %s |
|
534 | In [1]: %alias parts echo first %s second %s | |
564 | In [2]: parts A B |
|
535 | In [2]: parts A B | |
565 | first A second B |
|
536 | first A second B | |
566 | In [3]: parts A |
|
537 | In [3]: parts A | |
567 | ERROR: Alias <parts> requires 2 arguments, 1 given. |
|
538 | ERROR: Alias <parts> requires 2 arguments, 1 given. | |
568 |
|
539 | |||
569 | If called with no parameters, %alias prints the table of currently |
|
540 | If called with no parameters, %alias prints the table of currently | |
570 | defined aliases. |
|
541 | defined aliases. | |
571 |
|
542 | |||
572 | The %rehashx magic allows you to load your entire $PATH as |
|
543 | The %rehashx magic allows you to load your entire $PATH as | |
573 | ipython aliases. See its docstring for further details. |
|
544 | ipython aliases. See its docstring for further details. | |
574 |
|
545 | |||
575 |
|
546 | |||
576 | .. _dreload: |
|
547 | .. _dreload: | |
577 |
|
548 | |||
578 | Recursive reload |
|
549 | Recursive reload | |
579 | ---------------- |
|
550 | ---------------- | |
580 |
|
551 | |||
581 | The :mod:`IPython.lib.deepreload` module allows you to recursively reload a |
|
552 | The :mod:`IPython.lib.deepreload` module allows you to recursively reload a | |
582 | module: changes made to any of its dependencies will be reloaded without |
|
553 | module: changes made to any of its dependencies will be reloaded without | |
583 | having to exit. To start using it, do:: |
|
554 | having to exit. To start using it, do:: | |
584 |
|
555 | |||
585 | from IPython.lib.deepreload import reload as dreload |
|
556 | from IPython.lib.deepreload import reload as dreload | |
586 |
|
557 | |||
587 |
|
558 | |||
588 | Verbose and colored exception traceback printouts |
|
559 | Verbose and colored exception traceback printouts | |
589 | ------------------------------------------------- |
|
560 | ------------------------------------------------- | |
590 |
|
561 | |||
591 | IPython provides the option to see very detailed exception tracebacks, |
|
562 | IPython provides the option to see very detailed exception tracebacks, | |
592 | which can be especially useful when debugging large programs. You can |
|
563 | which can be especially useful when debugging large programs. You can | |
593 | run any Python file with the %run function to benefit from these |
|
564 | run any Python file with the %run function to benefit from these | |
594 | detailed tracebacks. Furthermore, both normal and verbose tracebacks can |
|
565 | detailed tracebacks. Furthermore, both normal and verbose tracebacks can | |
595 | be colored (if your terminal supports it) which makes them much easier |
|
566 | be colored (if your terminal supports it) which makes them much easier | |
596 | to parse visually. |
|
567 | to parse visually. | |
597 |
|
568 | |||
598 |
See the magic xmode and colors functions for details |
|
569 | See the magic xmode and colors functions for details. | |
599 |
|
570 | |||
600 | These features are basically a terminal version of Ka-Ping Yee's cgitb |
|
571 | These features are basically a terminal version of Ka-Ping Yee's cgitb | |
601 | module, now part of the standard Python library. |
|
572 | module, now part of the standard Python library. | |
602 |
|
573 | |||
603 |
|
574 | |||
604 | .. _input_caching: |
|
575 | .. _input_caching: | |
605 |
|
576 | |||
606 | Input caching system |
|
577 | Input caching system | |
607 | -------------------- |
|
578 | -------------------- | |
608 |
|
579 | |||
609 | IPython offers numbered prompts (In/Out) with input and output caching |
|
580 | IPython offers numbered prompts (In/Out) with input and output caching | |
610 | (also referred to as 'input history'). All input is saved and can be |
|
581 | (also referred to as 'input history'). All input is saved and can be | |
611 | retrieved as variables (besides the usual arrow key recall), in |
|
582 | retrieved as variables (besides the usual arrow key recall), in | |
612 | addition to the %rep magic command that brings a history entry |
|
583 | addition to the %rep magic command that brings a history entry | |
613 | up for editing on the next command line. |
|
584 | up for editing on the next command line. | |
614 |
|
585 | |||
615 |
The following |
|
586 | The following variables always exist: | |
616 |
|
587 | |||
617 | * _i, _ii, _iii: store previous, next previous and next-next previous inputs. |
|
588 | * _i, _ii, _iii: store previous, next previous and next-next previous inputs. | |
618 | * In, _ih : a list of all inputs; _ih[n] is the input from line n. If you |
|
589 | * In, _ih : a list of all inputs; _ih[n] is the input from line n. If you | |
619 | overwrite In with a variable of your own, you can remake the assignment to the |
|
590 | overwrite In with a variable of your own, you can remake the assignment to the | |
620 | internal list with a simple ``In=_ih``. |
|
591 | internal list with a simple ``In=_ih``. | |
621 |
|
592 | |||
622 | Additionally, global variables named _i<n> are dynamically created (<n> |
|
593 | Additionally, global variables named _i<n> are dynamically created (<n> | |
623 | being the prompt counter), so ``_i<n> == _ih[<n>] == In[<n>]``. |
|
594 | being the prompt counter), so ``_i<n> == _ih[<n>] == In[<n>]``. | |
624 |
|
595 | |||
625 | For example, what you typed at prompt 14 is available as _i14, _ih[14] |
|
596 | For example, what you typed at prompt 14 is available as ``_i14``, ``_ih[14]`` | |
626 | and In[14]. |
|
597 | and ``In[14]``. | |
627 |
|
598 | |||
628 | This allows you to easily cut and paste multi line interactive prompts |
|
599 | This allows you to easily cut and paste multi line interactive prompts | |
629 | by printing them out: they print like a clean string, without prompt |
|
600 | by printing them out: they print like a clean string, without prompt | |
630 | characters. You can also manipulate them like regular variables (they |
|
601 | characters. You can also manipulate them like regular variables (they | |
631 |
are strings), modify or exec them |
|
602 | are strings), modify or exec them. | |
632 | contents of input prompt 9. |
|
|||
633 |
|
603 | |||
634 | You can also re-execute multiple lines of input easily by using the |
|
604 | You can also re-execute multiple lines of input easily by using the | |
635 | magic %rerun or %macro functions. The macro system also allows you to re-execute |
|
605 | magic %rerun or %macro functions. The macro system also allows you to re-execute | |
636 | previous lines which include magic function calls (which require special |
|
606 | previous lines which include magic function calls (which require special | |
637 | processing). Type %macro? for more details on the macro system. |
|
607 | processing). Type %macro? for more details on the macro system. | |
638 |
|
608 | |||
639 | A history function %hist allows you to see any part of your input |
|
609 | A history function %hist allows you to see any part of your input | |
640 | history by printing a range of the _i variables. |
|
610 | history by printing a range of the _i variables. | |
641 |
|
611 | |||
642 | You can also search ('grep') through your history by typing |
|
612 | You can also search ('grep') through your history by typing | |
643 | ``%hist -g somestring``. This is handy for searching for URLs, IP addresses, |
|
613 | ``%hist -g somestring``. This is handy for searching for URLs, IP addresses, | |
644 | etc. You can bring history entries listed by '%hist -g' up for editing |
|
614 | etc. You can bring history entries listed by '%hist -g' up for editing | |
645 | with the %recall command, or run them immediately with %rerun. |
|
615 | with the %recall command, or run them immediately with %rerun. | |
646 |
|
616 | |||
647 | .. _output_caching: |
|
617 | .. _output_caching: | |
648 |
|
618 | |||
649 | Output caching system |
|
619 | Output caching system | |
650 | --------------------- |
|
620 | --------------------- | |
651 |
|
621 | |||
652 | For output that is returned from actions, a system similar to the input |
|
622 | For output that is returned from actions, a system similar to the input | |
653 | cache exists but using _ instead of _i. Only actions that produce a |
|
623 | cache exists but using _ instead of _i. Only actions that produce a | |
654 | result (NOT assignments, for example) are cached. If you are familiar |
|
624 | result (NOT assignments, for example) are cached. If you are familiar | |
655 | with Mathematica, IPython's _ variables behave exactly like |
|
625 | with Mathematica, IPython's _ variables behave exactly like | |
656 | Mathematica's % variables. |
|
626 | Mathematica's % variables. | |
657 |
|
627 | |||
658 |
The following |
|
628 | The following variables always exist: | |
659 |
|
629 | |||
660 |
* [_] (a single underscore) |
|
630 | * [_] (a single underscore): stores previous output, like Python's | |
661 | default interpreter. |
|
631 | default interpreter. | |
662 | * [__] (two underscores): next previous. |
|
632 | * [__] (two underscores): next previous. | |
663 | * [___] (three underscores): next-next previous. |
|
633 | * [___] (three underscores): next-next previous. | |
664 |
|
634 | |||
665 | Additionally, global variables named _<n> are dynamically created (<n> |
|
635 | Additionally, global variables named _<n> are dynamically created (<n> | |
666 | being the prompt counter), such that the result of output <n> is always |
|
636 | being the prompt counter), such that the result of output <n> is always | |
667 | available as _<n> (don't use the angle brackets, just the number, e.g. |
|
637 | available as _<n> (don't use the angle brackets, just the number, e.g. | |
668 | _21). |
|
638 | ``_21``). | |
669 |
|
639 | |||
670 | These variables are also stored in a global dictionary (not a |
|
640 | These variables are also stored in a global dictionary (not a | |
671 | list, since it only has entries for lines which returned a result) |
|
641 | list, since it only has entries for lines which returned a result) | |
672 | available under the names _oh and Out (similar to _ih and In). So the |
|
642 | available under the names _oh and Out (similar to _ih and In). So the | |
673 | output from line 12 can be obtained as _12, Out[12] or _oh[12]. If you |
|
643 | output from line 12 can be obtained as ``_12``, ``Out[12]`` or ``_oh[12]``. If you | |
674 | accidentally overwrite the Out variable you can recover it by typing |
|
644 | accidentally overwrite the Out variable you can recover it by typing | |
675 |
|
|
645 | ``Out=_oh`` at the prompt. | |
676 |
|
646 | |||
677 | This system obviously can potentially put heavy memory demands on your |
|
647 | This system obviously can potentially put heavy memory demands on your | |
678 | system, since it prevents Python's garbage collector from removing any |
|
648 | system, since it prevents Python's garbage collector from removing any | |
679 | previously computed results. You can control how many results are kept |
|
649 | previously computed results. You can control how many results are kept | |
680 | in memory with the option (at the command line or in your configuration |
|
650 | in memory with the configuration option ``InteractiveShell.cache_size``. | |
681 | file) cache_size. If you set it to 0, the whole system is completely |
|
651 | If you set it to 0, output caching is disabled. You can also use the ``%reset`` | |
682 | disabled and the prompts revert to the classic '>>>' of normal Python. |
|
652 | and ``%xdel`` magics to clear large items from memory. | |
683 |
|
||||
684 |
|
653 | |||
685 | Directory history |
|
654 | Directory history | |
686 | ----------------- |
|
655 | ----------------- | |
687 |
|
656 | |||
688 | Your history of visited directories is kept in the global list _dh, and |
|
657 | Your history of visited directories is kept in the global list _dh, and | |
689 | the magic %cd command can be used to go to any entry in that list. The |
|
658 | the magic %cd command can be used to go to any entry in that list. The | |
690 | %dhist command allows you to view this history. Do ``cd -<TAB>`` to |
|
659 | %dhist command allows you to view this history. Do ``cd -<TAB>`` to | |
691 | conveniently view the directory history. |
|
660 | conveniently view the directory history. | |
692 |
|
661 | |||
693 |
|
662 | |||
694 | Automatic parentheses and quotes |
|
663 | Automatic parentheses and quotes | |
695 | -------------------------------- |
|
664 | -------------------------------- | |
696 |
|
665 | |||
697 | These features were adapted from Nathan Gray's LazyPython. They are |
|
666 | These features were adapted from Nathan Gray's LazyPython. They are | |
698 | meant to allow less typing for common situations. |
|
667 | meant to allow less typing for common situations. | |
699 |
|
668 | |||
700 |
|
||||
701 | Automatic parentheses |
|
|||
702 | +++++++++++++++++++++ |
|
|||
703 |
|
||||
704 | Callable objects (i.e. functions, methods, etc) can be invoked like this |
|
669 | Callable objects (i.e. functions, methods, etc) can be invoked like this | |
705 | (notice the commas between the arguments):: |
|
670 | (notice the commas between the arguments):: | |
706 |
|
671 | |||
707 | In [1]: callable_ob arg1, arg2, arg3 |
|
672 | In [1]: callable_ob arg1, arg2, arg3 | |
708 | ------> callable_ob(arg1, arg2, arg3) |
|
673 | ------> callable_ob(arg1, arg2, arg3) | |
709 |
|
674 | |||
|
675 | .. note:: | |||
|
676 | This feature is disabled by default. To enable it, use the ``%autocall`` | |||
|
677 | magic command. The commands below with special prefixes will always work, | |||
|
678 | however. | |||
|
679 | ||||
710 | You can force automatic parentheses by using '/' as the first character |
|
680 | You can force automatic parentheses by using '/' as the first character | |
711 | of a line. For example:: |
|
681 | of a line. For example:: | |
712 |
|
682 | |||
713 | In [2]: /globals # becomes 'globals()' |
|
683 | In [2]: /globals # becomes 'globals()' | |
714 |
|
684 | |||
715 | Note that the '/' MUST be the first character on the line! This won't work:: |
|
685 | Note that the '/' MUST be the first character on the line! This won't work:: | |
716 |
|
686 | |||
717 | In [3]: print /globals # syntax error |
|
687 | In [3]: print /globals # syntax error | |
718 |
|
688 | |||
719 | In most cases the automatic algorithm should work, so you should rarely |
|
689 | In most cases the automatic algorithm should work, so you should rarely | |
720 | need to explicitly invoke /. One notable exception is if you are trying |
|
690 | need to explicitly invoke /. One notable exception is if you are trying | |
721 | to call a function with a list of tuples as arguments (the parenthesis |
|
691 | to call a function with a list of tuples as arguments (the parenthesis | |
722 | will confuse IPython):: |
|
692 | will confuse IPython):: | |
723 |
|
693 | |||
724 | In [4]: zip (1,2,3),(4,5,6) # won't work |
|
694 | In [4]: zip (1,2,3),(4,5,6) # won't work | |
725 |
|
695 | |||
726 | but this will work:: |
|
696 | but this will work:: | |
727 |
|
697 | |||
728 | In [5]: /zip (1,2,3),(4,5,6) |
|
698 | In [5]: /zip (1,2,3),(4,5,6) | |
729 | ------> zip ((1,2,3),(4,5,6)) |
|
699 | ------> zip ((1,2,3),(4,5,6)) | |
730 | Out[5]: [(1, 4), (2, 5), (3, 6)] |
|
700 | Out[5]: [(1, 4), (2, 5), (3, 6)] | |
731 |
|
701 | |||
732 | IPython tells you that it has altered your command line by displaying |
|
702 | IPython tells you that it has altered your command line by displaying | |
733 |
the new command line preceded by ->. |
|
703 | the new command line preceded by ``--->``. | |
734 |
|
||||
735 | In [6]: callable list |
|
|||
736 | ------> callable(list) |
|
|||
737 |
|
704 | |||
738 |
|
705 | You can force automatic quoting of a function's arguments by using ``,`` | ||
739 | Automatic quoting |
|
706 | or ``;`` as the first character of a line. For example:: | |
740 | +++++++++++++++++ |
|
|||
741 |
|
||||
742 | You can force automatic quoting of a function's arguments by using ',' |
|
|||
743 | or ';' as the first character of a line. For example:: |
|
|||
744 |
|
707 | |||
745 | In [1]: ,my_function /home/me # becomes my_function("/home/me") |
|
708 | In [1]: ,my_function /home/me # becomes my_function("/home/me") | |
746 |
|
709 | |||
747 | If you use ';' the whole argument is quoted as a single string, while ',' splits |
|
710 | If you use ';' the whole argument is quoted as a single string, while ',' splits | |
748 | on whitespace:: |
|
711 | on whitespace:: | |
749 |
|
712 | |||
750 | In [2]: ,my_function a b c # becomes my_function("a","b","c") |
|
713 | In [2]: ,my_function a b c # becomes my_function("a","b","c") | |
751 |
|
714 | |||
752 | In [3]: ;my_function a b c # becomes my_function("a b c") |
|
715 | In [3]: ;my_function a b c # becomes my_function("a b c") | |
753 |
|
716 | |||
754 | Note that the ',' or ';' MUST be the first character on the line! This |
|
717 | Note that the ',' or ';' MUST be the first character on the line! This | |
755 | won't work:: |
|
718 | won't work:: | |
756 |
|
719 | |||
757 | In [4]: x = ,my_function /home/me # syntax error |
|
720 | In [4]: x = ,my_function /home/me # syntax error | |
758 |
|
721 | |||
759 | IPython as your default Python environment |
|
722 | IPython as your default Python environment | |
760 | ========================================== |
|
723 | ========================================== | |
761 |
|
724 | |||
762 | Python honors the environment variable :envvar:`PYTHONSTARTUP` and will |
|
725 | Python honors the environment variable :envvar:`PYTHONSTARTUP` and will | |
763 | execute at startup the file referenced by this variable. If you put the |
|
726 | execute at startup the file referenced by this variable. If you put the | |
764 | following code at the end of that file, then IPython will be your working |
|
727 | following code at the end of that file, then IPython will be your working | |
765 | environment anytime you start Python:: |
|
728 | environment anytime you start Python:: | |
766 |
|
729 | |||
767 | import os, IPython |
|
730 | import os, IPython | |
768 | os.environ['PYTHONSTARTUP'] = '' # Prevent running this again |
|
731 | os.environ['PYTHONSTARTUP'] = '' # Prevent running this again | |
769 | IPython.start_ipython() |
|
732 | IPython.start_ipython() | |
770 | raise SystemExit |
|
733 | raise SystemExit | |
771 |
|
734 | |||
772 | The ``raise SystemExit`` is needed to exit Python when |
|
735 | The ``raise SystemExit`` is needed to exit Python when | |
773 |
it finishes, otherwise you'll be back at the normal Python |
|
736 | it finishes, otherwise you'll be back at the normal Python ``>>>`` | |
774 | prompt. |
|
737 | prompt. | |
775 |
|
738 | |||
776 | This is probably useful to developers who manage multiple Python |
|
739 | This is probably useful to developers who manage multiple Python | |
777 | versions and don't want to have correspondingly multiple IPython |
|
740 | versions and don't want to have correspondingly multiple IPython | |
778 | versions. Note that in this mode, there is no way to pass IPython any |
|
741 | versions. Note that in this mode, there is no way to pass IPython any | |
779 | command-line options, as those are trapped first by Python itself. |
|
742 | command-line options, as those are trapped first by Python itself. | |
780 |
|
743 | |||
781 | .. _Embedding: |
|
744 | .. _Embedding: | |
782 |
|
745 | |||
783 | Embedding IPython |
|
746 | Embedding IPython | |
784 | ================= |
|
747 | ================= | |
785 |
|
748 | |||
786 | You can start a regular IPython session with |
|
749 | You can start a regular IPython session with | |
787 |
|
750 | |||
788 | .. sourcecode:: python |
|
751 | .. sourcecode:: python | |
789 |
|
752 | |||
790 | import IPython |
|
753 | import IPython | |
791 | IPython.start_ipython() |
|
754 | IPython.start_ipython(argv=[]) | |
792 |
|
755 | |||
793 | at any point in your program. This will load IPython configuration, |
|
756 | at any point in your program. This will load IPython configuration, | |
794 | startup files, and everything, just as if it were a normal IPython session. |
|
757 | startup files, and everything, just as if it were a normal IPython session. | |
795 | In addition to this, |
|
758 | ||
796 |
|
|
759 | It is also possible to embed an IPython shell in a namespace in your Python code. | |
797 | This allows you to evaluate dynamically the state of your code, |
|
760 | This allows you to evaluate dynamically the state of your code, | |
798 | operate with your variables, analyze them, etc. Note however that |
|
761 | operate with your variables, analyze them, etc. Note however that | |
799 | any changes you make to values while in the shell do not propagate back |
|
762 | any changes you make to values while in the shell do not propagate back | |
800 | to the running code, so it is safe to modify your values because you |
|
763 | to the running code, so it is safe to modify your values because you | |
801 | won't break your code in bizarre ways by doing so. |
|
764 | won't break your code in bizarre ways by doing so. | |
802 |
|
765 | |||
803 | .. note:: |
|
766 | .. note:: | |
804 |
|
767 | |||
805 | At present, embedding IPython cannot be done from inside IPython. |
|
768 | At present, embedding IPython cannot be done from inside IPython. | |
806 | Run the code samples below outside IPython. |
|
769 | Run the code samples below outside IPython. | |
807 |
|
770 | |||
808 | This feature allows you to easily have a fully functional python |
|
771 | This feature allows you to easily have a fully functional python | |
809 | environment for doing object introspection anywhere in your code with a |
|
772 | environment for doing object introspection anywhere in your code with a | |
810 | simple function call. In some cases a simple print statement is enough, |
|
773 | simple function call. In some cases a simple print statement is enough, | |
811 | but if you need to do more detailed analysis of a code fragment this |
|
774 | but if you need to do more detailed analysis of a code fragment this | |
812 | feature can be very valuable. |
|
775 | feature can be very valuable. | |
813 |
|
776 | |||
814 | It can also be useful in scientific computing situations where it is |
|
777 | It can also be useful in scientific computing situations where it is | |
815 | common to need to do some automatic, computationally intensive part and |
|
778 | common to need to do some automatic, computationally intensive part and | |
816 | then stop to look at data, plots, etc. |
|
779 | then stop to look at data, plots, etc. | |
817 | Opening an IPython instance will give you full access to your data and |
|
780 | Opening an IPython instance will give you full access to your data and | |
818 | functions, and you can resume program execution once you are done with |
|
781 | functions, and you can resume program execution once you are done with | |
819 | the interactive part (perhaps to stop again later, as many times as |
|
782 | the interactive part (perhaps to stop again later, as many times as | |
820 | needed). |
|
783 | needed). | |
821 |
|
784 | |||
822 | The following code snippet is the bare minimum you need to include in |
|
785 | The following code snippet is the bare minimum you need to include in | |
823 | your Python programs for this to work (detailed examples follow later):: |
|
786 | your Python programs for this to work (detailed examples follow later):: | |
824 |
|
787 | |||
825 | from IPython import embed |
|
788 | from IPython import embed | |
826 |
|
789 | |||
827 | embed() # this call anywhere in your program will start IPython |
|
790 | embed() # this call anywhere in your program will start IPython | |
828 |
|
791 | |||
829 | .. note:: |
|
792 | You can also embed an IPython *kernel*, for use with qtconsole, etc. via | |
830 |
|
793 | ``IPython.embed_kernel()``. This should function work the same way, but you can | ||
831 | As of 0.13, you can embed an IPython *kernel*, for use with qtconsole, |
|
794 | connect an external frontend (``ipython qtconsole`` or ``ipython console``), | |
832 | etc. via ``IPython.embed_kernel()`` instead of ``IPython.embed()``. |
|
795 | rather than interacting with it in the terminal. | |
833 | It should function just the same as regular embed, but you connect |
|
|||
834 | an external frontend rather than IPython starting up in the local |
|
|||
835 | terminal. |
|
|||
836 |
|
796 | |||
837 | You can run embedded instances even in code which is itself being run at |
|
797 | You can run embedded instances even in code which is itself being run at | |
838 | the IPython interactive prompt with '%run <filename>'. Since it's easy |
|
798 | the IPython interactive prompt with '%run <filename>'. Since it's easy | |
839 | to get lost as to where you are (in your top-level IPython or in your |
|
799 | to get lost as to where you are (in your top-level IPython or in your | |
840 | embedded one), it's a good idea in such cases to set the in/out prompts |
|
800 | embedded one), it's a good idea in such cases to set the in/out prompts | |
841 | to something different for the embedded instances. The code examples |
|
801 | to something different for the embedded instances. The code examples | |
842 | below illustrate this. |
|
802 | below illustrate this. | |
843 |
|
803 | |||
844 | You can also have multiple IPython instances in your program and open |
|
804 | You can also have multiple IPython instances in your program and open | |
845 | them separately, for example with different options for data |
|
805 | them separately, for example with different options for data | |
846 | presentation. If you close and open the same instance multiple times, |
|
806 | presentation. If you close and open the same instance multiple times, | |
847 | its prompt counters simply continue from each execution to the next. |
|
807 | its prompt counters simply continue from each execution to the next. | |
848 |
|
808 | |||
849 | Please look at the docstrings in the :mod:`~IPython.frontend.terminal.embed` |
|
809 | Please look at the docstrings in the :mod:`~IPython.frontend.terminal.embed` | |
850 | module for more details on the use of this system. |
|
810 | module for more details on the use of this system. | |
851 |
|
811 | |||
852 | The following sample file illustrating how to use the embedding |
|
812 | The following sample file illustrating how to use the embedding | |
853 | functionality is provided in the examples directory as example-embed.py. |
|
813 | functionality is provided in the examples directory as example-embed.py. | |
854 | It should be fairly self-explanatory: |
|
814 | It should be fairly self-explanatory: | |
855 |
|
815 | |||
856 | .. literalinclude:: ../../../examples/core/example-embed.py |
|
816 | .. literalinclude:: ../../../examples/core/example-embed.py | |
857 | :language: python |
|
817 | :language: python | |
858 |
|
818 | |||
859 | Once you understand how the system functions, you can use the following |
|
819 | Once you understand how the system functions, you can use the following | |
860 | code fragments in your programs which are ready for cut and paste: |
|
820 | code fragments in your programs which are ready for cut and paste: | |
861 |
|
821 | |||
862 | .. literalinclude:: ../../../examples/core/example-embed-short.py |
|
822 | .. literalinclude:: ../../../examples/core/example-embed-short.py | |
863 | :language: python |
|
823 | :language: python | |
864 |
|
824 | |||
865 | Using the Python debugger (pdb) |
|
825 | Using the Python debugger (pdb) | |
866 | =============================== |
|
826 | =============================== | |
867 |
|
827 | |||
868 | Running entire programs via pdb |
|
828 | Running entire programs via pdb | |
869 | ------------------------------- |
|
829 | ------------------------------- | |
870 |
|
830 | |||
871 | pdb, the Python debugger, is a powerful interactive debugger which |
|
831 | pdb, the Python debugger, is a powerful interactive debugger which | |
872 | allows you to step through code, set breakpoints, watch variables, |
|
832 | allows you to step through code, set breakpoints, watch variables, | |
873 | etc. IPython makes it very easy to start any script under the control |
|
833 | etc. IPython makes it very easy to start any script under the control | |
874 | of pdb, regardless of whether you have wrapped it into a 'main()' |
|
834 | of pdb, regardless of whether you have wrapped it into a 'main()' | |
875 |
function or not. For this, simply type |
|
835 | function or not. For this, simply type ``%run -d myscript`` at an | |
876 |
IPython prompt. See the %run command's documentation |
|
836 | IPython prompt. See the %run command's documentation for more details, including | |
877 | in Sec. magic_ for more details, including how to control where pdb |
|
837 | how to control where pdb will stop execution first. | |
878 | will stop execution first. |
|
|||
879 |
|
||||
880 | For more information on the use of the pdb debugger, read the included |
|
|||
881 | pdb.doc file (part of the standard Python distribution). On a stock |
|
|||
882 | Linux system it is located at /usr/lib/python2.3/pdb.doc, but the |
|
|||
883 | easiest way to read it is by using the help() function of the pdb module |
|
|||
884 | as follows (in an IPython prompt):: |
|
|||
885 |
|
838 | |||
886 | In [1]: import pdb |
|
839 | For more information on the use of the pdb debugger, see :ref:`debugger-commands` | |
887 | In [2]: pdb.help() |
|
840 | in the Python documentation. | |
888 |
|
841 | |||
889 | This will load the pdb.doc document in a file viewer for you automatically. |
|
|||
890 |
|
842 | |||
|
843 | Post-mortem debugging | |||
|
844 | --------------------- | |||
891 |
|
845 | |||
892 | Automatic invocation of pdb on exceptions |
|
846 | Going into a debugger when an exception occurs can be | |
893 | ----------------------------------------- |
|
|||
894 |
|
||||
895 | IPython, if started with the ``--pdb`` option (or if the option is set in |
|
|||
896 | your config file) can call the Python pdb debugger every time your code |
|
|||
897 | triggers an uncaught exception. This feature |
|
|||
898 | can also be toggled at any time with the %pdb magic command. This can be |
|
|||
899 | extremely useful in order to find the origin of subtle bugs, because pdb |
|
847 | extremely useful in order to find the origin of subtle bugs, because pdb | |
900 | opens up at the point in your code which triggered the exception, and |
|
848 | opens up at the point in your code which triggered the exception, and | |
901 | while your program is at this point 'dead', all the data is still |
|
849 | while your program is at this point 'dead', all the data is still | |
902 | available and you can walk up and down the stack frame and understand |
|
850 | available and you can walk up and down the stack frame and understand | |
903 | the origin of the problem. |
|
851 | the origin of the problem. | |
904 |
|
852 | |||
905 | Furthermore, you can use these debugging facilities both with the |
|
853 | You can use the ``%debug`` magic after an exception has occurred to start | |
906 | embedded IPython mode and without IPython at all. For an embedded shell |
|
854 | post-mortem debugging. IPython can also call debugger every time your code | |
907 | (see sec. Embedding_), simply call the constructor with |
|
855 | triggers an uncaught exception. This feature can be toggled with the %pdb magic | |
908 | ``--pdb`` in the argument string and pdb will automatically be called if an |
|
856 | command, or you can start IPython with the ``--pdb`` option. | |
909 | uncaught exception is triggered by your code. |
|
|||
910 |
|
857 | |||
911 | For stand-alone use of the feature in your programs which do not use |
|
858 | For a post-mortem debugger in your programs outside IPython, | |
912 |
|
|
859 | put the following lines toward the top of your 'main' routine:: | |
913 | routine:: |
|
|||
914 |
|
860 | |||
915 | import sys |
|
861 | import sys | |
916 | from IPython.core import ultratb |
|
862 | from IPython.core import ultratb | |
917 | sys.excepthook = ultratb.FormattedTB(mode='Verbose', |
|
863 | sys.excepthook = ultratb.FormattedTB(mode='Verbose', | |
918 | color_scheme='Linux', call_pdb=1) |
|
864 | color_scheme='Linux', call_pdb=1) | |
919 |
|
865 | |||
920 | The mode keyword can be either 'Verbose' or 'Plain', giving either very |
|
866 | The mode keyword can be either 'Verbose' or 'Plain', giving either very | |
921 | detailed or normal tracebacks respectively. The color_scheme keyword can |
|
867 | detailed or normal tracebacks respectively. The color_scheme keyword can | |
922 | be one of 'NoColor', 'Linux' (default) or 'LightBG'. These are the same |
|
868 | be one of 'NoColor', 'Linux' (default) or 'LightBG'. These are the same | |
923 | options which can be set in IPython with ``--colors`` and ``--xmode``. |
|
869 | options which can be set in IPython with ``--colors`` and ``--xmode``. | |
924 |
|
870 | |||
925 | This will give any of your programs detailed, colored tracebacks with |
|
871 | This will give any of your programs detailed, colored tracebacks with | |
926 | automatic invocation of pdb. |
|
872 | automatic invocation of pdb. | |
927 |
|
873 | |||
928 |
|
||||
929 | Extensions for syntax processing |
|
|||
930 | ================================ |
|
|||
931 |
|
||||
932 | This isn't for the faint of heart, because the potential for breaking |
|
|||
933 | things is quite high. But it can be a very powerful and useful feature. |
|
|||
934 | In a nutshell, you can redefine the way IPython processes the user input |
|
|||
935 | line to accept new, special extensions to the syntax without needing to |
|
|||
936 | change any of IPython's own code. |
|
|||
937 |
|
||||
938 | In the IPython/extensions directory you will find some examples |
|
|||
939 | supplied, which we will briefly describe now. These can be used 'as is' |
|
|||
940 | (and both provide very useful functionality), or you can use them as a |
|
|||
941 | starting point for writing your own extensions. |
|
|||
942 |
|
||||
943 | .. _pasting_with_prompts: |
|
874 | .. _pasting_with_prompts: | |
944 |
|
875 | |||
945 | Pasting of code starting with Python or IPython prompts |
|
876 | Pasting of code starting with Python or IPython prompts | |
946 | ------------------------------------------------------- |
|
877 | ======================================================= | |
947 |
|
878 | |||
948 | IPython is smart enough to filter out input prompts, be they plain Python ones |
|
879 | IPython is smart enough to filter out input prompts, be they plain Python ones | |
949 | (``>>>`` and ``...``) or IPython ones (``In [N]:`` and ``...:``). You can |
|
880 | (``>>>`` and ``...``) or IPython ones (``In [N]:`` and ``...:``). You can | |
950 | therefore copy and paste from existing interactive sessions without worry. |
|
881 | therefore copy and paste from existing interactive sessions without worry. | |
951 |
|
882 | |||
952 | The following is a 'screenshot' of how things work, copying an example from the |
|
883 | The following is a 'screenshot' of how things work, copying an example from the | |
953 | standard Python tutorial:: |
|
884 | standard Python tutorial:: | |
954 |
|
885 | |||
955 | In [1]: >>> # Fibonacci series: |
|
886 | In [1]: >>> # Fibonacci series: | |
956 |
|
887 | |||
957 | In [2]: ... # the sum of two elements defines the next |
|
888 | In [2]: ... # the sum of two elements defines the next | |
958 |
|
889 | |||
959 | In [3]: ... a, b = 0, 1 |
|
890 | In [3]: ... a, b = 0, 1 | |
960 |
|
891 | |||
961 | In [4]: >>> while b < 10: |
|
892 | In [4]: >>> while b < 10: | |
962 | ...: ... print(b) |
|
893 | ...: ... print(b) | |
963 | ...: ... a, b = b, a+b |
|
894 | ...: ... a, b = b, a+b | |
964 | ...: |
|
895 | ...: | |
965 | 1 |
|
896 | 1 | |
966 | 1 |
|
897 | 1 | |
967 | 2 |
|
898 | 2 | |
968 | 3 |
|
899 | 3 | |
969 | 5 |
|
900 | 5 | |
970 | 8 |
|
901 | 8 | |
971 |
|
902 | |||
972 | And pasting from IPython sessions works equally well:: |
|
903 | And pasting from IPython sessions works equally well:: | |
973 |
|
904 | |||
974 | In [1]: In [5]: def f(x): |
|
905 | In [1]: In [5]: def f(x): | |
975 | ...: ...: "A simple function" |
|
906 | ...: ...: "A simple function" | |
976 | ...: ...: return x**2 |
|
907 | ...: ...: return x**2 | |
977 | ...: ...: |
|
908 | ...: ...: | |
978 |
|
909 | |||
979 | In [2]: f(3) |
|
910 | In [2]: f(3) | |
980 | Out[2]: 9 |
|
911 | Out[2]: 9 | |
981 |
|
912 | |||
982 | .. _gui_support: |
|
913 | .. _gui_support: | |
983 |
|
914 | |||
984 | GUI event loop support |
|
915 | GUI event loop support | |
985 | ====================== |
|
916 | ====================== | |
986 |
|
917 | |||
987 | .. versionadded:: 0.11 |
|
918 | .. versionadded:: 0.11 | |
988 | The ``%gui`` magic and :mod:`IPython.lib.inputhook`. |
|
919 | The ``%gui`` magic and :mod:`IPython.lib.inputhook`. | |
989 |
|
920 | |||
990 | IPython has excellent support for working interactively with Graphical User |
|
921 | IPython has excellent support for working interactively with Graphical User | |
991 | Interface (GUI) toolkits, such as wxPython, PyQt4/PySide, PyGTK and Tk. This is |
|
922 | Interface (GUI) toolkits, such as wxPython, PyQt4/PySide, PyGTK and Tk. This is | |
992 | implemented using Python's builtin ``PyOSInputHook`` hook. This implementation |
|
923 | implemented using Python's builtin ``PyOSInputHook`` hook. This implementation | |
993 | is extremely robust compared to our previous thread-based version. The |
|
924 | is extremely robust compared to our previous thread-based version. The | |
994 | advantages of this are: |
|
925 | advantages of this are: | |
995 |
|
926 | |||
996 | * GUIs can be enabled and disabled dynamically at runtime. |
|
927 | * GUIs can be enabled and disabled dynamically at runtime. | |
997 | * The active GUI can be switched dynamically at runtime. |
|
928 | * The active GUI can be switched dynamically at runtime. | |
998 | * In some cases, multiple GUIs can run simultaneously with no problems. |
|
929 | * In some cases, multiple GUIs can run simultaneously with no problems. | |
999 | * There is a developer API in :mod:`IPython.lib.inputhook` for customizing |
|
930 | * There is a developer API in :mod:`IPython.lib.inputhook` for customizing | |
1000 | all of these things. |
|
931 | all of these things. | |
1001 |
|
932 | |||
1002 | For users, enabling GUI event loop integration is simple. You simple use the |
|
933 | For users, enabling GUI event loop integration is simple. You simple use the | |
1003 | ``%gui`` magic as follows:: |
|
934 | ``%gui`` magic as follows:: | |
1004 |
|
935 | |||
1005 | %gui [GUINAME] |
|
936 | %gui [GUINAME] | |
1006 |
|
937 | |||
1007 | With no arguments, ``%gui`` removes all GUI support. Valid ``GUINAME`` |
|
938 | With no arguments, ``%gui`` removes all GUI support. Valid ``GUINAME`` | |
1008 | arguments are ``wx``, ``qt``, ``gtk`` and ``tk``. |
|
939 | arguments are ``wx``, ``qt``, ``gtk`` and ``tk``. | |
1009 |
|
940 | |||
1010 | Thus, to use wxPython interactively and create a running :class:`wx.App` |
|
941 | Thus, to use wxPython interactively and create a running :class:`wx.App` | |
1011 | object, do:: |
|
942 | object, do:: | |
1012 |
|
943 | |||
1013 | %gui wx |
|
944 | %gui wx | |
1014 |
|
945 | |||
|
946 | You can also start IPython with an event loop set up using the :option:`--gui` | |||
|
947 | flag:: | |||
|
948 | ||||
|
949 | $ ipython --gui=qt | |||
|
950 | ||||
1015 | For information on IPython's matplotlib_ integration (and the ``matplotlib`` |
|
951 | For information on IPython's matplotlib_ integration (and the ``matplotlib`` | |
1016 | mode) see :ref:`this section <matplotlib_support>`. |
|
952 | mode) see :ref:`this section <matplotlib_support>`. | |
1017 |
|
953 | |||
1018 | For developers that want to use IPython's GUI event loop integration in the |
|
954 | For developers that want to use IPython's GUI event loop integration in the | |
1019 | form of a library, these capabilities are exposed in library form in the |
|
955 | form of a library, these capabilities are exposed in library form in the | |
1020 | :mod:`IPython.lib.inputhook` and :mod:`IPython.lib.guisupport` modules. |
|
956 | :mod:`IPython.lib.inputhook` and :mod:`IPython.lib.guisupport` modules. | |
1021 | Interested developers should see the module docstrings for more information, |
|
957 | Interested developers should see the module docstrings for more information, | |
1022 | but there are a few points that should be mentioned here. |
|
958 | but there are a few points that should be mentioned here. | |
1023 |
|
959 | |||
1024 | First, the ``PyOSInputHook`` approach only works in command line settings |
|
960 | First, the ``PyOSInputHook`` approach only works in command line settings | |
1025 | where readline is activated. The integration with various eventloops |
|
961 | where readline is activated. The integration with various eventloops | |
1026 | is handled somewhat differently (and more simply) when using the standalone |
|
962 | is handled somewhat differently (and more simply) when using the standalone | |
1027 | kernel, as in the qtconsole and notebook. |
|
963 | kernel, as in the qtconsole and notebook. | |
1028 |
|
964 | |||
1029 | Second, when using the ``PyOSInputHook`` approach, a GUI application should |
|
965 | Second, when using the ``PyOSInputHook`` approach, a GUI application should | |
1030 | *not* start its event loop. Instead all of this is handled by the |
|
966 | *not* start its event loop. Instead all of this is handled by the | |
1031 | ``PyOSInputHook``. This means that applications that are meant to be used both |
|
967 | ``PyOSInputHook``. This means that applications that are meant to be used both | |
1032 | in IPython and as standalone apps need to have special code to detects how the |
|
968 | in IPython and as standalone apps need to have special code to detects how the | |
1033 | application is being run. We highly recommend using IPython's support for this. |
|
969 | application is being run. We highly recommend using IPython's support for this. | |
1034 | Since the details vary slightly between toolkits, we point you to the various |
|
970 | Since the details vary slightly between toolkits, we point you to the various | |
1035 | examples in our source directory :file:`examples/lib` that demonstrate |
|
971 | examples in our source directory :file:`examples/lib` that demonstrate | |
1036 | these capabilities. |
|
972 | these capabilities. | |
1037 |
|
973 | |||
1038 | Third, unlike previous versions of IPython, we no longer "hijack" (replace |
|
974 | Third, unlike previous versions of IPython, we no longer "hijack" (replace | |
1039 | them with no-ops) the event loops. This is done to allow applications that |
|
975 | them with no-ops) the event loops. This is done to allow applications that | |
1040 | actually need to run the real event loops to do so. This is often needed to |
|
976 | actually need to run the real event loops to do so. This is often needed to | |
1041 | process pending events at critical points. |
|
977 | process pending events at critical points. | |
1042 |
|
978 | |||
1043 | Finally, we also have a number of examples in our source directory |
|
979 | Finally, we also have a number of examples in our source directory | |
1044 | :file:`examples/lib` that demonstrate these capabilities. |
|
980 | :file:`examples/lib` that demonstrate these capabilities. | |
1045 |
|
981 | |||
1046 | PyQt and PySide |
|
982 | PyQt and PySide | |
1047 | --------------- |
|
983 | --------------- | |
1048 |
|
984 | |||
1049 | .. attempt at explanation of the complete mess that is Qt support |
|
985 | .. attempt at explanation of the complete mess that is Qt support | |
1050 |
|
986 | |||
1051 | When you use ``--gui=qt`` or ``--matplotlib=qt``, IPython can work with either |
|
987 | When you use ``--gui=qt`` or ``--matplotlib=qt``, IPython can work with either | |
1052 | PyQt4 or PySide. There are three options for configuration here, because |
|
988 | PyQt4 or PySide. There are three options for configuration here, because | |
1053 | PyQt4 has two APIs for QString and QVariant - v1, which is the default on |
|
989 | PyQt4 has two APIs for QString and QVariant - v1, which is the default on | |
1054 | Python 2, and the more natural v2, which is the only API supported by PySide. |
|
990 | Python 2, and the more natural v2, which is the only API supported by PySide. | |
1055 | v2 is also the default for PyQt4 on Python 3. IPython's code for the QtConsole |
|
991 | v2 is also the default for PyQt4 on Python 3. IPython's code for the QtConsole | |
1056 | uses v2, but you can still use any interface in your code, since the |
|
992 | uses v2, but you can still use any interface in your code, since the | |
1057 | Qt frontend is in a different process. |
|
993 | Qt frontend is in a different process. | |
1058 |
|
994 | |||
1059 | The default will be to import PyQt4 without configuration of the APIs, thus |
|
995 | The default will be to import PyQt4 without configuration of the APIs, thus | |
1060 | matching what most applications would expect. It will fall back of PySide if |
|
996 | matching what most applications would expect. It will fall back of PySide if | |
1061 | PyQt4 is unavailable. |
|
997 | PyQt4 is unavailable. | |
1062 |
|
998 | |||
1063 | If specified, IPython will respect the environment variable ``QT_API`` used |
|
999 | If specified, IPython will respect the environment variable ``QT_API`` used | |
1064 | by ETS. ETS 4.0 also works with both PyQt4 and PySide, but it requires |
|
1000 | by ETS. ETS 4.0 also works with both PyQt4 and PySide, but it requires | |
1065 | PyQt4 to use its v2 API. So if ``QT_API=pyside`` PySide will be used, |
|
1001 | PyQt4 to use its v2 API. So if ``QT_API=pyside`` PySide will be used, | |
1066 | and if ``QT_API=pyqt`` then PyQt4 will be used *with the v2 API* for |
|
1002 | and if ``QT_API=pyqt`` then PyQt4 will be used *with the v2 API* for | |
1067 | QString and QVariant, so ETS codes like MayaVi will also work with IPython. |
|
1003 | QString and QVariant, so ETS codes like MayaVi will also work with IPython. | |
1068 |
|
1004 | |||
1069 | If you launch IPython in matplotlib mode with ``ipython --matplotlib=qt``, |
|
1005 | If you launch IPython in matplotlib mode with ``ipython --matplotlib=qt``, | |
1070 | then IPython will ask matplotlib which Qt library to use (only if QT_API is |
|
1006 | then IPython will ask matplotlib which Qt library to use (only if QT_API is | |
1071 | *not set*), via the 'backend.qt4' rcParam. If matplotlib is version 1.0.1 or |
|
1007 | *not set*), via the 'backend.qt4' rcParam. If matplotlib is version 1.0.1 or | |
1072 | older, then IPython will always use PyQt4 without setting the v2 APIs, since |
|
1008 | older, then IPython will always use PyQt4 without setting the v2 APIs, since | |
1073 | neither v2 PyQt nor PySide work. |
|
1009 | neither v2 PyQt nor PySide work. | |
1074 |
|
1010 | |||
1075 | .. warning:: |
|
1011 | .. warning:: | |
1076 |
|
1012 | |||
1077 | Note that this means for ETS 4 to work with PyQt4, ``QT_API`` *must* be set |
|
1013 | Note that this means for ETS 4 to work with PyQt4, ``QT_API`` *must* be set | |
1078 | to work with IPython's qt integration, because otherwise PyQt4 will be |
|
1014 | to work with IPython's qt integration, because otherwise PyQt4 will be | |
1079 | loaded in an incompatible mode. |
|
1015 | loaded in an incompatible mode. | |
1080 |
|
1016 | |||
1081 | It also means that you must *not* have ``QT_API`` set if you want to |
|
1017 | It also means that you must *not* have ``QT_API`` set if you want to | |
1082 | use ``--gui=qt`` with code that requires PyQt4 API v1. |
|
1018 | use ``--gui=qt`` with code that requires PyQt4 API v1. | |
1083 |
|
1019 | |||
1084 |
|
1020 | |||
1085 | .. _matplotlib_support: |
|
1021 | .. _matplotlib_support: | |
1086 |
|
1022 | |||
1087 | Plotting with matplotlib |
|
1023 | Plotting with matplotlib | |
1088 | ======================== |
|
1024 | ======================== | |
1089 |
|
1025 | |||
1090 | matplotlib_ provides high quality 2D and 3D plotting for Python. matplotlib_ |
|
1026 | matplotlib_ provides high quality 2D and 3D plotting for Python. matplotlib_ | |
1091 | can produce plots on screen using a variety of GUI toolkits, including Tk, |
|
1027 | can produce plots on screen using a variety of GUI toolkits, including Tk, | |
1092 | PyGTK, PyQt4 and wxPython. It also provides a number of commands useful for |
|
1028 | PyGTK, PyQt4 and wxPython. It also provides a number of commands useful for | |
1093 | scientific computing, all with a syntax compatible with that of the popular |
|
1029 | scientific computing, all with a syntax compatible with that of the popular | |
1094 | Matlab program. |
|
1030 | Matlab program. | |
1095 |
|
1031 | |||
1096 | To start IPython with matplotlib support, use the ``--matplotlib`` switch. If |
|
1032 | To start IPython with matplotlib support, use the ``--matplotlib`` switch. If | |
1097 | IPython is already running, you can run the ``%matplotlib`` magic. If no |
|
1033 | IPython is already running, you can run the ``%matplotlib`` magic. If no | |
1098 | arguments are given, IPython will automatically detect your choice of |
|
1034 | arguments are given, IPython will automatically detect your choice of | |
1099 | matplotlib backend. You can also request a specific backend with |
|
1035 | matplotlib backend. You can also request a specific backend with | |
1100 | ``%matplotlib backend``, where ``backend`` must be one of: 'tk', 'qt', 'wx', |
|
1036 | ``%matplotlib backend``, where ``backend`` must be one of: 'tk', 'qt', 'wx', | |
1101 | 'gtk', 'osx'. In the web notebook and Qt console, 'inline' is also a valid |
|
1037 | 'gtk', 'osx'. In the web notebook and Qt console, 'inline' is also a valid | |
1102 | backend value, which produces static figures inlined inside the application |
|
1038 | backend value, which produces static figures inlined inside the application | |
1103 | window instead of matplotlib's interactive figures that live in separate |
|
1039 | window instead of matplotlib's interactive figures that live in separate | |
1104 | windows. |
|
1040 | windows. | |
1105 |
|
1041 | |||
1106 | .. _interactive_demos: |
|
1042 | .. _interactive_demos: | |
1107 |
|
1043 | |||
1108 | Interactive demos with IPython |
|
1044 | Interactive demos with IPython | |
1109 | ============================== |
|
1045 | ============================== | |
1110 |
|
1046 | |||
1111 | IPython ships with a basic system for running scripts interactively in |
|
1047 | IPython ships with a basic system for running scripts interactively in | |
1112 | sections, useful when presenting code to audiences. A few tags embedded |
|
1048 | sections, useful when presenting code to audiences. A few tags embedded | |
1113 | in comments (so that the script remains valid Python code) divide a file |
|
1049 | in comments (so that the script remains valid Python code) divide a file | |
1114 | into separate blocks, and the demo can be run one block at a time, with |
|
1050 | into separate blocks, and the demo can be run one block at a time, with | |
1115 | IPython printing (with syntax highlighting) the block before executing |
|
1051 | IPython printing (with syntax highlighting) the block before executing | |
1116 | it, and returning to the interactive prompt after each block. The |
|
1052 | it, and returning to the interactive prompt after each block. The | |
1117 | interactive namespace is updated after each block is run with the |
|
1053 | interactive namespace is updated after each block is run with the | |
1118 | contents of the demo's namespace. |
|
1054 | contents of the demo's namespace. | |
1119 |
|
1055 | |||
1120 | This allows you to show a piece of code, run it and then execute |
|
1056 | This allows you to show a piece of code, run it and then execute | |
1121 | interactively commands based on the variables just created. Once you |
|
1057 | interactively commands based on the variables just created. Once you | |
1122 | want to continue, you simply execute the next block of the demo. The |
|
1058 | want to continue, you simply execute the next block of the demo. The | |
1123 | following listing shows the markup necessary for dividing a script into |
|
1059 | following listing shows the markup necessary for dividing a script into | |
1124 | sections for execution as a demo: |
|
1060 | sections for execution as a demo: | |
1125 |
|
1061 | |||
1126 | .. literalinclude:: ../../../examples/lib/example-demo.py |
|
1062 | .. literalinclude:: ../../../examples/lib/example-demo.py | |
1127 | :language: python |
|
1063 | :language: python | |
1128 |
|
1064 | |||
1129 | In order to run a file as a demo, you must first make a Demo object out |
|
1065 | In order to run a file as a demo, you must first make a Demo object out | |
1130 | of it. If the file is named myscript.py, the following code will make a |
|
1066 | of it. If the file is named myscript.py, the following code will make a | |
1131 | demo:: |
|
1067 | demo:: | |
1132 |
|
1068 | |||
1133 | from IPython.lib.demo import Demo |
|
1069 | from IPython.lib.demo import Demo | |
1134 |
|
1070 | |||
1135 | mydemo = Demo('myscript.py') |
|
1071 | mydemo = Demo('myscript.py') | |
1136 |
|
1072 | |||
1137 | This creates the mydemo object, whose blocks you run one at a time by |
|
1073 | This creates the mydemo object, whose blocks you run one at a time by | |
1138 |
simply calling the object with no arguments. |
|
1074 | simply calling the object with no arguments. Then call it to run each step | |
1139 | in IPython (the default), all you need to do is type:: |
|
1075 | of the demo:: | |
1140 |
|
1076 | |||
1141 |
mydemo |
|
1077 | mydemo() | |
1142 |
|
1078 | |||
1143 | and IPython will call it, executing each block. Demo objects can be |
|
1079 | Demo objects can be | |
1144 | restarted, you can move forward or back skipping blocks, re-execute the |
|
1080 | restarted, you can move forward or back skipping blocks, re-execute the | |
1145 | last block, etc. Simply use the Tab key on a demo object to see its |
|
1081 | last block, etc. See the :mod:`IPython.lib.demo` module and the | |
1146 | methods, and call '?' on them to see their docstrings for more usage |
|
1082 | :class:`~IPython.lib.demo.Demo` class for details. | |
1147 | details. In addition, the demo module itself contains a comprehensive |
|
|||
1148 | docstring, which you can access via:: |
|
|||
1149 |
|
||||
1150 | from IPython.lib import demo |
|
|||
1151 |
|
||||
1152 | demo? |
|
|||
1153 |
|
1083 | |||
1154 |
Limitations: |
|
1084 | Limitations: These demos are limited to | |
1155 | fairly simple uses. In particular, you cannot break up sections within |
|
1085 | fairly simple uses. In particular, you cannot break up sections within | |
1156 | indented code (loops, if statements, function definitions, etc.) |
|
1086 | indented code (loops, if statements, function definitions, etc.) | |
1157 | Supporting something like this would basically require tracking the |
|
1087 | Supporting something like this would basically require tracking the | |
1158 | internal execution state of the Python interpreter, so only top-level |
|
1088 | internal execution state of the Python interpreter, so only top-level | |
1159 | divisions are allowed. If you want to be able to open an IPython |
|
1089 | divisions are allowed. If you want to be able to open an IPython | |
1160 | instance at an arbitrary point in a program, you can use IPython's |
|
1090 | instance at an arbitrary point in a program, you can use IPython's | |
1161 | embedding facilities, see :func:`IPython.embed` for details. |
|
1091 | :ref:`embedding facilities <Embedding>`. | |
1162 |
|
1092 | |||
1163 | .. include:: ../links.txt |
|
1093 | .. include:: ../links.txt |
@@ -1,138 +1,137 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 |
|
||||
3 | """An example of how to embed an IPython shell into a running program. |
|
2 | """An example of how to embed an IPython shell into a running program. | |
4 |
|
3 | |||
5 | Please see the documentation in the IPython.Shell module for more details. |
|
4 | Please see the documentation in the IPython.Shell module for more details. | |
6 |
|
5 | |||
7 | The accompanying file example-embed-short.py has quick code fragments for |
|
6 | The accompanying file example-embed-short.py has quick code fragments for | |
8 | embedding which you can cut and paste in your code once you understand how |
|
7 | embedding which you can cut and paste in your code once you understand how | |
9 | things work. |
|
8 | things work. | |
10 |
|
9 | |||
11 | The code in this file is deliberately extra-verbose, meant for learning.""" |
|
10 | The code in this file is deliberately extra-verbose, meant for learning.""" | |
12 | from __future__ import print_function |
|
11 | from __future__ import print_function | |
13 |
|
12 | |||
14 | # The basics to get you going: |
|
13 | # The basics to get you going: | |
15 |
|
14 | |||
16 |
# IPython |
|
15 | # IPython injects get_ipython into builtins, so you can know if you have nested | |
17 | # copies running. |
|
16 | # copies running. | |
18 |
|
17 | |||
19 | # Try running this code both at the command line and from inside IPython (with |
|
18 | # Try running this code both at the command line and from inside IPython (with | |
20 | # %run example-embed.py) |
|
19 | # %run example-embed.py) | |
21 | from IPython.config.loader import Config |
|
20 | from IPython.config.loader import Config | |
22 | try: |
|
21 | try: | |
23 | get_ipython |
|
22 | get_ipython | |
24 | except NameError: |
|
23 | except NameError: | |
25 | nested = 0 |
|
24 | nested = 0 | |
26 | cfg = Config() |
|
25 | cfg = Config() | |
27 | prompt_config = cfg.PromptManager |
|
26 | prompt_config = cfg.PromptManager | |
28 | prompt_config.in_template = 'In <\\#>: ' |
|
27 | prompt_config.in_template = 'In <\\#>: ' | |
29 | prompt_config.in2_template = ' .\\D.: ' |
|
28 | prompt_config.in2_template = ' .\\D.: ' | |
30 | prompt_config.out_template = 'Out<\\#>: ' |
|
29 | prompt_config.out_template = 'Out<\\#>: ' | |
31 | else: |
|
30 | else: | |
32 | print("Running nested copies of IPython.") |
|
31 | print("Running nested copies of IPython.") | |
33 | print("The prompts for the nested copy have been modified") |
|
32 | print("The prompts for the nested copy have been modified") | |
34 | cfg = Config() |
|
33 | cfg = Config() | |
35 | nested = 1 |
|
34 | nested = 1 | |
36 |
|
35 | |||
37 | # First import the embeddable shell class |
|
36 | # First import the embeddable shell class | |
38 | from IPython.terminal.embed import InteractiveShellEmbed |
|
37 | from IPython.terminal.embed import InteractiveShellEmbed | |
39 |
|
38 | |||
40 | # Now create an instance of the embeddable shell. The first argument is a |
|
39 | # Now create an instance of the embeddable shell. The first argument is a | |
41 | # string with options exactly as you would type them if you were starting |
|
40 | # string with options exactly as you would type them if you were starting | |
42 | # IPython at the system command line. Any parameters you want to define for |
|
41 | # IPython at the system command line. Any parameters you want to define for | |
43 | # configuration can thus be specified here. |
|
42 | # configuration can thus be specified here. | |
44 | ipshell = InteractiveShellEmbed(config=cfg, |
|
43 | ipshell = InteractiveShellEmbed(config=cfg, | |
45 | banner1 = 'Dropping into IPython', |
|
44 | banner1 = 'Dropping into IPython', | |
46 | exit_msg = 'Leaving Interpreter, back to program.') |
|
45 | exit_msg = 'Leaving Interpreter, back to program.') | |
47 |
|
46 | |||
48 | # Make a second instance, you can have as many as you want. |
|
47 | # Make a second instance, you can have as many as you want. | |
49 | cfg2 = cfg.copy() |
|
48 | cfg2 = cfg.copy() | |
50 | prompt_config = cfg2.PromptManager |
|
49 | prompt_config = cfg2.PromptManager | |
51 | prompt_config.in_template = 'In2<\\#>: ' |
|
50 | prompt_config.in_template = 'In2<\\#>: ' | |
52 | if not nested: |
|
51 | if not nested: | |
53 | prompt_config.in_template = 'In2<\\#>: ' |
|
52 | prompt_config.in_template = 'In2<\\#>: ' | |
54 | prompt_config.in2_template = ' .\\D.: ' |
|
53 | prompt_config.in2_template = ' .\\D.: ' | |
55 | prompt_config.out_template = 'Out<\\#>: ' |
|
54 | prompt_config.out_template = 'Out<\\#>: ' | |
56 | ipshell2 = InteractiveShellEmbed(config=cfg, |
|
55 | ipshell2 = InteractiveShellEmbed(config=cfg, | |
57 | banner1 = 'Second IPython instance.') |
|
56 | banner1 = 'Second IPython instance.') | |
58 |
|
57 | |||
59 | print('\nHello. This is printed from the main controller program.\n') |
|
58 | print('\nHello. This is printed from the main controller program.\n') | |
60 |
|
59 | |||
61 | # You can then call ipshell() anywhere you need it (with an optional |
|
60 | # You can then call ipshell() anywhere you need it (with an optional | |
62 | # message): |
|
61 | # message): | |
63 | ipshell('***Called from top level. ' |
|
62 | ipshell('***Called from top level. ' | |
64 | 'Hit Ctrl-D to exit interpreter and continue program.\n' |
|
63 | 'Hit Ctrl-D to exit interpreter and continue program.\n' | |
65 | 'Note that if you use %kill_embedded, you can fully deactivate\n' |
|
64 | 'Note that if you use %kill_embedded, you can fully deactivate\n' | |
66 | 'This embedded instance so it will never turn on again') |
|
65 | 'This embedded instance so it will never turn on again') | |
67 |
|
66 | |||
68 | print('\nBack in caller program, moving along...\n') |
|
67 | print('\nBack in caller program, moving along...\n') | |
69 |
|
68 | |||
70 | #--------------------------------------------------------------------------- |
|
69 | #--------------------------------------------------------------------------- | |
71 | # More details: |
|
70 | # More details: | |
72 |
|
71 | |||
73 | # InteractiveShellEmbed instances don't print the standard system banner and |
|
72 | # InteractiveShellEmbed instances don't print the standard system banner and | |
74 | # messages. The IPython banner (which actually may contain initialization |
|
73 | # messages. The IPython banner (which actually may contain initialization | |
75 | # messages) is available as get_ipython().banner in case you want it. |
|
74 | # messages) is available as get_ipython().banner in case you want it. | |
76 |
|
75 | |||
77 | # InteractiveShellEmbed instances print the following information everytime they |
|
76 | # InteractiveShellEmbed instances print the following information everytime they | |
78 | # start: |
|
77 | # start: | |
79 |
|
78 | |||
80 | # - A global startup banner. |
|
79 | # - A global startup banner. | |
81 |
|
80 | |||
82 | # - A call-specific header string, which you can use to indicate where in the |
|
81 | # - A call-specific header string, which you can use to indicate where in the | |
83 | # execution flow the shell is starting. |
|
82 | # execution flow the shell is starting. | |
84 |
|
83 | |||
85 | # They also print an exit message every time they exit. |
|
84 | # They also print an exit message every time they exit. | |
86 |
|
85 | |||
87 | # Both the startup banner and the exit message default to None, and can be set |
|
86 | # Both the startup banner and the exit message default to None, and can be set | |
88 | # either at the instance constructor or at any other time with the |
|
87 | # either at the instance constructor or at any other time with the | |
89 | # by setting the banner and exit_msg attributes. |
|
88 | # by setting the banner and exit_msg attributes. | |
90 |
|
89 | |||
91 | # The shell instance can be also put in 'dummy' mode globally or on a per-call |
|
90 | # The shell instance can be also put in 'dummy' mode globally or on a per-call | |
92 | # basis. This gives you fine control for debugging without having to change |
|
91 | # basis. This gives you fine control for debugging without having to change | |
93 | # code all over the place. |
|
92 | # code all over the place. | |
94 |
|
93 | |||
95 | # The code below illustrates all this. |
|
94 | # The code below illustrates all this. | |
96 |
|
95 | |||
97 |
|
96 | |||
98 | # This is how the global banner and exit_msg can be reset at any point |
|
97 | # This is how the global banner and exit_msg can be reset at any point | |
99 | ipshell.banner = 'Entering interpreter - New Banner' |
|
98 | ipshell.banner = 'Entering interpreter - New Banner' | |
100 | ipshell.exit_msg = 'Leaving interpreter - New exit_msg' |
|
99 | ipshell.exit_msg = 'Leaving interpreter - New exit_msg' | |
101 |
|
100 | |||
102 | def foo(m): |
|
101 | def foo(m): | |
103 | s = 'spam' |
|
102 | s = 'spam' | |
104 | ipshell('***In foo(). Try %whos, or print s or m:') |
|
103 | ipshell('***In foo(). Try %whos, or print s or m:') | |
105 | print('foo says m = ',m) |
|
104 | print('foo says m = ',m) | |
106 |
|
105 | |||
107 | def bar(n): |
|
106 | def bar(n): | |
108 | s = 'eggs' |
|
107 | s = 'eggs' | |
109 | ipshell('***In bar(). Try %whos, or print s or n:') |
|
108 | ipshell('***In bar(). Try %whos, or print s or n:') | |
110 | print('bar says n = ',n) |
|
109 | print('bar says n = ',n) | |
111 |
|
110 | |||
112 | # Some calls to the above functions which will trigger IPython: |
|
111 | # Some calls to the above functions which will trigger IPython: | |
113 | print('Main program calling foo("eggs")\n') |
|
112 | print('Main program calling foo("eggs")\n') | |
114 | foo('eggs') |
|
113 | foo('eggs') | |
115 |
|
114 | |||
116 | # The shell can be put in 'dummy' mode where calls to it silently return. This |
|
115 | # The shell can be put in 'dummy' mode where calls to it silently return. This | |
117 | # allows you, for example, to globally turn off debugging for a program with a |
|
116 | # allows you, for example, to globally turn off debugging for a program with a | |
118 | # single call. |
|
117 | # single call. | |
119 | ipshell.dummy_mode = True |
|
118 | ipshell.dummy_mode = True | |
120 | print('\nTrying to call IPython which is now "dummy":') |
|
119 | print('\nTrying to call IPython which is now "dummy":') | |
121 | ipshell() |
|
120 | ipshell() | |
122 | print('Nothing happened...') |
|
121 | print('Nothing happened...') | |
123 | # The global 'dummy' mode can still be overridden for a single call |
|
122 | # The global 'dummy' mode can still be overridden for a single call | |
124 | print('\nOverriding dummy mode manually:') |
|
123 | print('\nOverriding dummy mode manually:') | |
125 | ipshell(dummy=False) |
|
124 | ipshell(dummy=False) | |
126 |
|
125 | |||
127 | # Reactivate the IPython shell |
|
126 | # Reactivate the IPython shell | |
128 | ipshell.dummy_mode = False |
|
127 | ipshell.dummy_mode = False | |
129 |
|
128 | |||
130 | print('You can even have multiple embedded instances:') |
|
129 | print('You can even have multiple embedded instances:') | |
131 | ipshell2() |
|
130 | ipshell2() | |
132 |
|
131 | |||
133 | print('\nMain program calling bar("spam")\n') |
|
132 | print('\nMain program calling bar("spam")\n') | |
134 | bar('spam') |
|
133 | bar('spam') | |
135 |
|
134 | |||
136 | print('Main program finished. Bye!') |
|
135 | print('Main program finished. Bye!') | |
137 |
|
136 | |||
138 | #********************** End of file <example-embed.py> *********************** |
|
137 | #********************** End of file <example-embed.py> *********************** |
@@ -1,44 +1,43 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 | """A simple interactive demo to illustrate the use of IPython's Demo class. |
|
2 | """A simple interactive demo to illustrate the use of IPython's Demo class. | |
3 |
|
3 | |||
4 | Any python script can be run as a demo, but that does little more than showing |
|
4 | Any python script can be run as a demo, but that does little more than showing | |
5 | it on-screen, syntax-highlighted in one shot. If you add a little simple |
|
5 | it on-screen, syntax-highlighted in one shot. If you add a little simple | |
6 | markup, you can stop at specified intervals and return to the ipython prompt, |
|
6 | markup, you can stop at specified intervals and return to the ipython prompt, | |
7 | resuming execution later. |
|
7 | resuming execution later. | |
8 |
|
8 | |||
9 | This is a unicode test, Γ₯Àâ |
|
9 | This is a unicode test, Γ₯Àâ | |
10 | """ |
|
10 | """ | |
11 | from __future__ import print_function |
|
11 | from __future__ import print_function | |
12 |
|
12 | |||
13 | print('Hello, welcome to an interactive IPython demo.') |
|
13 | print('Hello, welcome to an interactive IPython demo.') | |
14 | print('Executing this block should require confirmation before proceeding,') |
|
14 | print('Executing this block should require confirmation before proceeding,') | |
15 | print('unless auto_all has been set to true in the demo object') |
|
15 | print('unless auto_all has been set to true in the demo object') | |
16 |
|
16 | |||
17 | # The mark below defines a block boundary, which is a point where IPython will |
|
17 | # The mark below defines a block boundary, which is a point where IPython will | |
18 | # stop execution and return to the interactive prompt. |
|
18 | # stop execution and return to the interactive prompt. | |
19 | # Note that in actual interactive execution, |
|
|||
20 | # <demo> --- stop --- |
|
19 | # <demo> --- stop --- | |
21 |
|
20 | |||
22 | x = 1 |
|
21 | x = 1 | |
23 | y = 2 |
|
22 | y = 2 | |
24 |
|
23 | |||
25 | # <demo> --- stop --- |
|
24 | # <demo> --- stop --- | |
26 |
|
25 | |||
27 | # the mark below makes this block as silent |
|
26 | # the mark below makes this block as silent | |
28 | # <demo> silent |
|
27 | # <demo> silent | |
29 |
|
28 | |||
30 | print('This is a silent block, which gets executed but not printed.') |
|
29 | print('This is a silent block, which gets executed but not printed.') | |
31 |
|
30 | |||
32 | # <demo> --- stop --- |
|
31 | # <demo> --- stop --- | |
33 | # <demo> auto |
|
32 | # <demo> auto | |
34 | print('This is an automatic block.') |
|
33 | print('This is an automatic block.') | |
35 | print('It is executed without asking for confirmation, but printed.') |
|
34 | print('It is executed without asking for confirmation, but printed.') | |
36 | z = x+y |
|
35 | z = x+y | |
37 |
|
36 | |||
38 | print('z=',x) |
|
37 | print('z=',x) | |
39 |
|
38 | |||
40 | # <demo> --- stop --- |
|
39 | # <demo> --- stop --- | |
41 | # This is just another normal block. |
|
40 | # This is just another normal block. | |
42 | print('z is now:', z) |
|
41 | print('z is now:', z) | |
43 |
|
42 | |||
44 | print('bye!') |
|
43 | print('bye!') |
General Comments 0
You need to be logged in to leave comments.
Login now