'+a.addText+" "),h=d.find("tr:last a")):(c.filter(":last").after('"),h=c.filter(":last").next().find("a"));h.click(function(d){d.preventDefault();var f=b("#id_"+a.prefix+"-TOTAL_FORMS"),d=b("#"+a.prefix+
3 | "-empty"),c=d.clone(true);c.removeClass(a.emptyCssClass).addClass(a.formCssClass).attr("id",a.prefix+"-"+g);c.is("tr")?c.children(":last").append('"):c.is("ul")||c.is("ol")?c.append(''+a.deleteText+" "):c.children(":first").append(''+a.deleteText+" ");c.find("*").each(function(){i(this,
4 | a.prefix,f.val())});c.insertBefore(b(d));b(f).val(parseInt(f.val(),10)+1);g=g+1;e.val()!==""&&e.val()-f.val()<=0&&h.parent().hide();c.find("a."+a.deleteCssClass).click(function(d){d.preventDefault();d=b(this).parents("."+a.formCssClass);d.remove();g=g-1;a.removed&&a.removed(d);d=b("."+a.formCssClass);b("#id_"+a.prefix+"-TOTAL_FORMS").val(d.length);(e.val()===""||e.val()-d.length>0)&&h.parent().show();for(var c=0,f=d.length;c b) return 1;
97 | if (a < b) return -1;
98 | }
99 | catch (e) {
100 | // silently fail on IE 'unknown' exception
101 | }
102 | return 0;
103 | } );
104 | },
105 | select_all: function(id) {
106 | var box = document.getElementById(id);
107 | for (var i = 0; i < box.options.length; i++) {
108 | box.options[i].selected = 'selected';
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/static/admin/css/rtl.css:
--------------------------------------------------------------------------------
1 | body {
2 | direction: rtl;
3 | }
4 |
5 | /* LOGIN */
6 |
7 | .login .form-row {
8 | float: right;
9 | }
10 |
11 | .login .form-row label {
12 | float: right;
13 | padding-left: 0.5em;
14 | padding-right: 0;
15 | text-align: left;
16 | }
17 |
18 | .login .submit-row {
19 | clear: both;
20 | padding: 1em 9.4em 0 0;
21 | }
22 |
23 | /* GLOBAL */
24 |
25 | th {
26 | text-align: right;
27 | }
28 |
29 | .module h2, .module caption {
30 | text-align: right;
31 | }
32 |
33 | .addlink, .changelink {
34 | padding-left: 0px;
35 | padding-right: 12px;
36 | background-position: 100% 0.2em;
37 | }
38 |
39 | .deletelink {
40 | padding-left: 0px;
41 | padding-right: 12px;
42 | background-position: 100% 0.25em;
43 | }
44 |
45 | .object-tools {
46 | float: left;
47 | }
48 |
49 | thead th:first-child,
50 | tfoot td:first-child {
51 | border-left: 1px solid #ddd !important;
52 | }
53 |
54 | /* LAYOUT */
55 |
56 | #user-tools {
57 | right: auto;
58 | left: 0;
59 | text-align: left;
60 | }
61 |
62 | div.breadcrumbs {
63 | text-align: right;
64 | }
65 |
66 | #content-main {
67 | float: right;
68 | }
69 |
70 | #content-related {
71 | float: left;
72 | margin-left: -19em;
73 | margin-right: auto;
74 | }
75 |
76 | .colMS {
77 | margin-left: 20em !important;
78 | margin-right: 10px !important;
79 | }
80 |
81 | /* SORTABLE TABLES */
82 |
83 | table thead th.sorted .sortoptions {
84 | float: left;
85 | }
86 |
87 | thead th.sorted .text {
88 | padding-right: 0;
89 | padding-left: 42px;
90 | }
91 |
92 | /* dashboard styles */
93 |
94 | .dashboard .module table td a {
95 | padding-left: .6em;
96 | padding-right: 12px;
97 | }
98 |
99 | /* changelists styles */
100 |
101 | .change-list .filtered {
102 | background: white url(../img/changelist-bg_rtl.gif) top left repeat-y !important;
103 | }
104 |
105 | .change-list .filtered table {
106 | border-left: 1px solid #ddd;
107 | border-right: 0px none;
108 | }
109 |
110 | #changelist-filter {
111 | right: auto;
112 | left: 0;
113 | border-left: 0px none;
114 | border-right: 1px solid #ddd;
115 | }
116 |
117 | .change-list .filtered .results, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull {
118 | margin-right: 0px !important;
119 | margin-left: 160px !important;
120 | }
121 |
122 | #changelist-filter li.selected {
123 | border-left: 0px none;
124 | padding-left: 0px;
125 | margin-left: 0;
126 | border-right: 5px solid #ccc;
127 | padding-right: 5px;
128 | margin-right: -10px;
129 | }
130 |
131 | .filtered .actions {
132 | border-left:1px solid #DDDDDD;
133 | margin-left:160px !important;
134 | border-right: 0 none;
135 | margin-right:0 !important;
136 | }
137 |
138 | #changelist table tbody td:first-child, #changelist table tbody th:first-child {
139 | border-right: 0;
140 | border-left: 1px solid #ddd;
141 | }
142 |
143 | /* FORMS */
144 |
145 | .aligned label {
146 | padding: 0 0 3px 1em;
147 | float: right;
148 | }
149 |
150 | .submit-row {
151 | text-align: left
152 | }
153 |
154 | .submit-row p.deletelink-box {
155 | float: right;
156 | }
157 |
158 | .submit-row .deletelink {
159 | background: url(../img/icon_deletelink.gif) 0 50% no-repeat;
160 | padding-right: 14px;
161 | }
162 |
163 | .vDateField, .vTimeField {
164 | margin-left: 2px;
165 | }
166 |
167 | form ul.inline li {
168 | float: right;
169 | padding-right: 0;
170 | padding-left: 7px;
171 | }
172 |
173 | input[type=submit].default, .submit-row input.default {
174 | float: left;
175 | }
176 |
177 | fieldset .field-box {
178 | float: right;
179 | margin-left: 20px;
180 | margin-right: 0;
181 | }
182 |
183 | .errorlist li {
184 | background-position: 100% .3em;
185 | padding: 4px 25px 4px 5px;
186 | }
187 |
188 | .errornote {
189 | background-position: 100% .3em;
190 | padding: 4px 25px 4px 5px;
191 | }
192 |
193 | /* WIDGETS */
194 |
195 | .calendarnav-previous {
196 | top: 0;
197 | left: auto;
198 | right: 0;
199 | }
200 |
201 | .calendarnav-next {
202 | top: 0;
203 | right: auto;
204 | left: 0;
205 | }
206 |
207 | .calendar caption, .calendarbox h2 {
208 | text-align: center;
209 | }
210 |
211 | .selector {
212 | float: right;
213 | }
214 |
215 | .selector .selector-filter {
216 | text-align: right;
217 | }
218 |
219 | .inline-deletelink {
220 | float: left;
221 | }
222 |
223 | /* MISC */
224 |
225 | .inline-related h2, .inline-group h2 {
226 | text-align: right
227 | }
228 |
229 | .inline-related h3 span.delete {
230 | padding-right: 20px;
231 | padding-left: inherit;
232 | left: 10px;
233 | right: inherit;
234 | float:left;
235 | }
236 |
237 | .inline-related h3 span.delete label {
238 | margin-left: inherit;
239 | margin-right: 2px;
240 | }
241 |
242 | /* IE7 specific bug fixes */
243 |
244 | div.colM {
245 | position: relative;
246 | }
247 |
248 | .submit-row input {
249 | float: left;
250 | }
--------------------------------------------------------------------------------
/static/admin/js/actions.js:
--------------------------------------------------------------------------------
1 | (function($) {
2 | $.fn.actions = function(opts) {
3 | var options = $.extend({}, $.fn.actions.defaults, opts);
4 | var actionCheckboxes = $(this);
5 | var list_editable_changed = false;
6 | var checker = function(checked) {
7 | if (checked) {
8 | showQuestion();
9 | } else {
10 | reset();
11 | }
12 | $(actionCheckboxes).prop("checked", checked)
13 | .parent().parent().toggleClass(options.selectedClass, checked);
14 | },
15 | updateCounter = function() {
16 | var sel = $(actionCheckboxes).filter(":checked").length;
17 | $(options.counterContainer).html(interpolate(
18 | ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), {
19 | sel: sel,
20 | cnt: _actions_icnt
21 | }, true));
22 | $(options.allToggle).prop("checked", function() {
23 | if (sel == actionCheckboxes.length) {
24 | value = true;
25 | showQuestion();
26 | } else {
27 | value = false;
28 | clearAcross();
29 | }
30 | return value;
31 | });
32 | },
33 | showQuestion = function() {
34 | $(options.acrossClears).hide();
35 | $(options.acrossQuestions).show();
36 | $(options.allContainer).hide();
37 | },
38 | showClear = function() {
39 | $(options.acrossClears).show();
40 | $(options.acrossQuestions).hide();
41 | $(options.actionContainer).toggleClass(options.selectedClass);
42 | $(options.allContainer).show();
43 | $(options.counterContainer).hide();
44 | },
45 | reset = function() {
46 | $(options.acrossClears).hide();
47 | $(options.acrossQuestions).hide();
48 | $(options.allContainer).hide();
49 | $(options.counterContainer).show();
50 | },
51 | clearAcross = function() {
52 | reset();
53 | $(options.acrossInput).val(0);
54 | $(options.actionContainer).removeClass(options.selectedClass);
55 | };
56 | // Show counter by default
57 | $(options.counterContainer).show();
58 | // Check state of checkboxes and reinit state if needed
59 | $(this).filter(":checked").each(function(i) {
60 | $(this).parent().parent().toggleClass(options.selectedClass);
61 | updateCounter();
62 | if ($(options.acrossInput).val() == 1) {
63 | showClear();
64 | }
65 | });
66 | $(options.allToggle).show().click(function() {
67 | checker($(this).prop("checked"));
68 | updateCounter();
69 | });
70 | $("div.actions span.question a").click(function(event) {
71 | event.preventDefault();
72 | $(options.acrossInput).val(1);
73 | showClear();
74 | });
75 | $("div.actions span.clear a").click(function(event) {
76 | event.preventDefault();
77 | $(options.allToggle).prop("checked", false);
78 | clearAcross();
79 | checker(0);
80 | updateCounter();
81 | });
82 | lastChecked = null;
83 | $(actionCheckboxes).click(function(event) {
84 | if (!event) { event = window.event; }
85 | var target = event.target ? event.target : event.srcElement;
86 | if (lastChecked && $.data(lastChecked) != $.data(target) && event.shiftKey === true) {
87 | var inrange = false;
88 | $(lastChecked).prop("checked", target.checked)
89 | .parent().parent().toggleClass(options.selectedClass, target.checked);
90 | $(actionCheckboxes).each(function() {
91 | if ($.data(this) == $.data(lastChecked) || $.data(this) == $.data(target)) {
92 | inrange = (inrange) ? false : true;
93 | }
94 | if (inrange) {
95 | $(this).prop("checked", target.checked)
96 | .parent().parent().toggleClass(options.selectedClass, target.checked);
97 | }
98 | });
99 | }
100 | $(target).parent().parent().toggleClass(options.selectedClass, target.checked);
101 | lastChecked = target;
102 | updateCounter();
103 | });
104 | $('form#changelist-form table#result_list tr').find('td:gt(0) :input').change(function() {
105 | list_editable_changed = true;
106 | });
107 | $('form#changelist-form button[name="index"]').click(function(event) {
108 | if (list_editable_changed) {
109 | return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."));
110 | }
111 | });
112 | $('form#changelist-form input[name="_save"]').click(function(event) {
113 | var action_changed = false;
114 | $('div.actions select option:selected').each(function() {
115 | if ($(this).val()) {
116 | action_changed = true;
117 | }
118 | });
119 | if (action_changed) {
120 | if (list_editable_changed) {
121 | return confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action."));
122 | } else {
123 | return confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button."));
124 | }
125 | }
126 | });
127 | };
128 | /* Setup plugin defaults */
129 | $.fn.actions.defaults = {
130 | actionContainer: "div.actions",
131 | counterContainer: "span.action-counter",
132 | allContainer: "div.actions span.all",
133 | acrossInput: "div.actions input.select-across",
134 | acrossQuestions: "div.actions span.question",
135 | acrossClears: "div.actions span.clear",
136 | allToggle: "#action-toggle",
137 | selectedClass: "selected"
138 | };
139 | })(django.jQuery);
140 |
--------------------------------------------------------------------------------
/static/admin/js/calendar.js:
--------------------------------------------------------------------------------
1 | /*
2 | calendar.js - Calendar functions by Adrian Holovaty
3 | depends on core.js for utility functions like removeChildren or quickElement
4 | */
5 |
6 | // CalendarNamespace -- Provides a collection of HTML calendar-related helper functions
7 | var CalendarNamespace = {
8 | monthsOfYear: gettext('January February March April May June July August September October November December').split(' '),
9 | daysOfWeek: gettext('S M T W T F S').split(' '),
10 | firstDayOfWeek: parseInt(get_format('FIRST_DAY_OF_WEEK')),
11 | isLeapYear: function(year) {
12 | return (((year % 4)==0) && ((year % 100)!=0) || ((year % 400)==0));
13 | },
14 | getDaysInMonth: function(month,year) {
15 | var days;
16 | if (month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12) {
17 | days = 31;
18 | }
19 | else if (month==4 || month==6 || month==9 || month==11) {
20 | days = 30;
21 | }
22 | else if (month==2 && CalendarNamespace.isLeapYear(year)) {
23 | days = 29;
24 | }
25 | else {
26 | days = 28;
27 | }
28 | return days;
29 | },
30 | draw: function(month, year, div_id, callback) { // month = 1-12, year = 1-9999
31 | var today = new Date();
32 | var todayDay = today.getDate();
33 | var todayMonth = today.getMonth()+1;
34 | var todayYear = today.getFullYear();
35 | var todayClass = '';
36 |
37 | month = parseInt(month);
38 | year = parseInt(year);
39 | var calDiv = document.getElementById(div_id);
40 | removeChildren(calDiv);
41 | var calTable = document.createElement('table');
42 | quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month-1] + ' ' + year);
43 | var tableBody = quickElement('tbody', calTable);
44 |
45 | // Draw days-of-week header
46 | var tableRow = quickElement('tr', tableBody);
47 | for (var i = 0; i < 7; i++) {
48 | quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]);
49 | }
50 |
51 | var startingPos = new Date(year, month-1, 1 - CalendarNamespace.firstDayOfWeek).getDay();
52 | var days = CalendarNamespace.getDaysInMonth(month, year);
53 |
54 | // Draw blanks before first of month
55 | tableRow = quickElement('tr', tableBody);
56 | for (var i = 0; i < startingPos; i++) {
57 | var _cell = quickElement('td', tableRow, ' ');
58 | _cell.style.backgroundColor = '#f3f3f3';
59 | }
60 |
61 | // Draw days of month
62 | var currentDay = 1;
63 | for (var i = startingPos; currentDay <= days; i++) {
64 | if (i%7 == 0 && currentDay != 1) {
65 | tableRow = quickElement('tr', tableBody);
66 | }
67 | if ((currentDay==todayDay) && (month==todayMonth) && (year==todayYear)) {
68 | todayClass='today';
69 | } else {
70 | todayClass='';
71 | }
72 | var cell = quickElement('td', tableRow, '', 'class', todayClass);
73 |
74 | quickElement('a', cell, currentDay, 'href', 'javascript:void(' + callback + '('+year+','+month+','+currentDay+'));');
75 | currentDay++;
76 | }
77 |
78 | // Draw blanks after end of month (optional, but makes for valid code)
79 | while (tableRow.childNodes.length < 7) {
80 | var _cell = quickElement('td', tableRow, ' ');
81 | _cell.style.backgroundColor = '#f3f3f3';
82 | }
83 |
84 | calDiv.appendChild(calTable);
85 | }
86 | }
87 |
88 | // Calendar -- A calendar instance
89 | function Calendar(div_id, callback) {
90 | // div_id (string) is the ID of the element in which the calendar will
91 | // be displayed
92 | // callback (string) is the name of a JavaScript function that will be
93 | // called with the parameters (year, month, day) when a day in the
94 | // calendar is clicked
95 | this.div_id = div_id;
96 | this.callback = callback;
97 | this.today = new Date();
98 | this.currentMonth = this.today.getMonth() + 1;
99 | this.currentYear = this.today.getFullYear();
100 | }
101 | Calendar.prototype = {
102 | drawCurrent: function() {
103 | CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback);
104 | },
105 | drawDate: function(month, year) {
106 | this.currentMonth = month;
107 | this.currentYear = year;
108 | this.drawCurrent();
109 | },
110 | drawPreviousMonth: function() {
111 | if (this.currentMonth == 1) {
112 | this.currentMonth = 12;
113 | this.currentYear--;
114 | }
115 | else {
116 | this.currentMonth--;
117 | }
118 | this.drawCurrent();
119 | },
120 | drawNextMonth: function() {
121 | if (this.currentMonth == 12) {
122 | this.currentMonth = 1;
123 | this.currentYear++;
124 | }
125 | else {
126 | this.currentMonth++;
127 | }
128 | this.drawCurrent();
129 | },
130 | drawPreviousYear: function() {
131 | this.currentYear--;
132 | this.drawCurrent();
133 | },
134 | drawNextYear: function() {
135 | this.currentYear++;
136 | this.drawCurrent();
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/static/admin/js/urlify.js:
--------------------------------------------------------------------------------
1 | var LATIN_MAP = {
2 | 'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 'Ç':
3 | 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 'Î': 'I',
4 | 'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 'Õ': 'O', 'Ö':
5 | 'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ű': 'U',
6 | 'Ý': 'Y', 'Þ': 'TH', 'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã': 'a', 'ä':
7 | 'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e',
8 | 'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó':
9 | 'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u',
10 | 'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
11 | }
12 | var LATIN_SYMBOLS_MAP = {
13 | '©':'(c)'
14 | }
15 | var GREEK_MAP = {
16 | 'α':'a', 'β':'b', 'γ':'g', 'δ':'d', 'ε':'e', 'ζ':'z', 'η':'h', 'θ':'8',
17 | 'ι':'i', 'κ':'k', 'λ':'l', 'μ':'m', 'ν':'n', 'ξ':'3', 'ο':'o', 'π':'p',
18 | 'ρ':'r', 'σ':'s', 'τ':'t', 'υ':'y', 'φ':'f', 'χ':'x', 'ψ':'ps', 'ω':'w',
19 | 'ά':'a', 'έ':'e', 'ί':'i', 'ό':'o', 'ύ':'y', 'ή':'h', 'ώ':'w', 'ς':'s',
20 | 'ϊ':'i', 'ΰ':'y', 'ϋ':'y', 'ΐ':'i',
21 | 'Α':'A', 'Β':'B', 'Γ':'G', 'Δ':'D', 'Ε':'E', 'Ζ':'Z', 'Η':'H', 'Θ':'8',
22 | 'Ι':'I', 'Κ':'K', 'Λ':'L', 'Μ':'M', 'Ν':'N', 'Ξ':'3', 'Ο':'O', 'Π':'P',
23 | 'Ρ':'R', 'Σ':'S', 'Τ':'T', 'Υ':'Y', 'Φ':'F', 'Χ':'X', 'Ψ':'PS', 'Ω':'W',
24 | 'Ά':'A', 'Έ':'E', 'Ί':'I', 'Ό':'O', 'Ύ':'Y', 'Ή':'H', 'Ώ':'W', 'Ϊ':'I',
25 | 'Ϋ':'Y'
26 | }
27 | var TURKISH_MAP = {
28 | 'ş':'s', 'Ş':'S', 'ı':'i', 'İ':'I', 'ç':'c', 'Ç':'C', 'ü':'u', 'Ü':'U',
29 | 'ö':'o', 'Ö':'O', 'ğ':'g', 'Ğ':'G'
30 | }
31 | var RUSSIAN_MAP = {
32 | 'а':'a', 'б':'b', 'в':'v', 'г':'g', 'д':'d', 'е':'e', 'ё':'yo', 'ж':'zh',
33 | 'з':'z', 'и':'i', 'й':'j', 'к':'k', 'л':'l', 'м':'m', 'н':'n', 'о':'o',
34 | 'п':'p', 'р':'r', 'с':'s', 'т':'t', 'у':'u', 'ф':'f', 'х':'h', 'ц':'c',
35 | 'ч':'ch', 'ш':'sh', 'щ':'sh', 'ъ':'', 'ы':'y', 'ь':'', 'э':'e', 'ю':'yu',
36 | 'я':'ya',
37 | 'А':'A', 'Б':'B', 'В':'V', 'Г':'G', 'Д':'D', 'Е':'E', 'Ё':'Yo', 'Ж':'Zh',
38 | 'З':'Z', 'И':'I', 'Й':'J', 'К':'K', 'Л':'L', 'М':'M', 'Н':'N', 'О':'O',
39 | 'П':'P', 'Р':'R', 'С':'S', 'Т':'T', 'У':'U', 'Ф':'F', 'Х':'H', 'Ц':'C',
40 | 'Ч':'Ch', 'Ш':'Sh', 'Щ':'Sh', 'Ъ':'', 'Ы':'Y', 'Ь':'', 'Э':'E', 'Ю':'Yu',
41 | 'Я':'Ya'
42 | }
43 | var UKRAINIAN_MAP = {
44 | 'Є':'Ye', 'І':'I', 'Ї':'Yi', 'Ґ':'G', 'є':'ye', 'і':'i', 'ї':'yi', 'ґ':'g'
45 | }
46 | var CZECH_MAP = {
47 | 'č':'c', 'ď':'d', 'ě':'e', 'ň': 'n', 'ř':'r', 'š':'s', 'ť':'t', 'ů':'u',
48 | 'ž':'z', 'Č':'C', 'Ď':'D', 'Ě':'E', 'Ň': 'N', 'Ř':'R', 'Š':'S', 'Ť':'T',
49 | 'Ů':'U', 'Ž':'Z'
50 | }
51 |
52 | var POLISH_MAP = {
53 | 'ą':'a', 'ć':'c', 'ę':'e', 'ł':'l', 'ń':'n', 'ó':'o', 'ś':'s', 'ź':'z',
54 | 'ż':'z', 'Ą':'A', 'Ć':'C', 'Ę':'e', 'Ł':'L', 'Ń':'N', 'Ó':'o', 'Ś':'S',
55 | 'Ź':'Z', 'Ż':'Z'
56 | }
57 |
58 | var LATVIAN_MAP = {
59 | 'ā':'a', 'č':'c', 'ē':'e', 'ģ':'g', 'ī':'i', 'ķ':'k', 'ļ':'l', 'ņ':'n',
60 | 'š':'s', 'ū':'u', 'ž':'z', 'Ā':'A', 'Č':'C', 'Ē':'E', 'Ģ':'G', 'Ī':'i',
61 | 'Ķ':'k', 'Ļ':'L', 'Ņ':'N', 'Š':'S', 'Ū':'u', 'Ž':'Z'
62 | }
63 |
64 | var ALL_DOWNCODE_MAPS=new Array()
65 | ALL_DOWNCODE_MAPS[0]=LATIN_MAP
66 | ALL_DOWNCODE_MAPS[1]=LATIN_SYMBOLS_MAP
67 | ALL_DOWNCODE_MAPS[2]=GREEK_MAP
68 | ALL_DOWNCODE_MAPS[3]=TURKISH_MAP
69 | ALL_DOWNCODE_MAPS[4]=RUSSIAN_MAP
70 | ALL_DOWNCODE_MAPS[5]=UKRAINIAN_MAP
71 | ALL_DOWNCODE_MAPS[6]=CZECH_MAP
72 | ALL_DOWNCODE_MAPS[7]=POLISH_MAP
73 | ALL_DOWNCODE_MAPS[8]=LATVIAN_MAP
74 |
75 | var Downcoder = new Object();
76 | Downcoder.Initialize = function()
77 | {
78 | if (Downcoder.map) // already made
79 | return ;
80 | Downcoder.map ={}
81 | Downcoder.chars = '' ;
82 | for(var i in ALL_DOWNCODE_MAPS)
83 | {
84 | var lookup = ALL_DOWNCODE_MAPS[i]
85 | for (var c in lookup)
86 | {
87 | Downcoder.map[c] = lookup[c] ;
88 | Downcoder.chars += c ;
89 | }
90 | }
91 | Downcoder.regex = new RegExp('[' + Downcoder.chars + ']|[^' + Downcoder.chars + ']+','g') ;
92 | }
93 |
94 | downcode= function( slug )
95 | {
96 | Downcoder.Initialize() ;
97 | var downcoded =""
98 | var pieces = slug.match(Downcoder.regex);
99 | if(pieces)
100 | {
101 | for (var i = 0 ; i < pieces.length ; i++)
102 | {
103 | if (pieces[i].length == 1)
104 | {
105 | var mapped = Downcoder.map[pieces[i]] ;
106 | if (mapped != null)
107 | {
108 | downcoded+=mapped;
109 | continue ;
110 | }
111 | }
112 | downcoded+=pieces[i];
113 | }
114 | }
115 | else
116 | {
117 | downcoded = slug;
118 | }
119 | return downcoded;
120 | }
121 |
122 |
123 | function URLify(s, num_chars) {
124 | // changes, e.g., "Petty theft" to "petty_theft"
125 | // remove all these words from the string before urlifying
126 | s = downcode(s);
127 | removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from",
128 | "is", "in", "into", "like", "of", "off", "on", "onto", "per",
129 | "since", "than", "the", "this", "that", "to", "up", "via",
130 | "with"];
131 | r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
132 | s = s.replace(r, '');
133 | // if downcode doesn't hit, the char will be stripped here
134 | s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars
135 | s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
136 | s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens
137 | s = s.toLowerCase(); // convert to lowercase
138 | return s.substring(0, num_chars);// trim to first num_chars chars
139 | }
140 |
141 |
--------------------------------------------------------------------------------
/static/admin/css/changelists.css:
--------------------------------------------------------------------------------
1 | /* CHANGELISTS */
2 |
3 | #changelist {
4 | position: relative;
5 | width: 100%;
6 | }
7 |
8 | #changelist table {
9 | width: 100%;
10 | }
11 |
12 | .change-list .hiddenfields { display:none; }
13 |
14 | .change-list .filtered table {
15 | border-right: 1px solid #ddd;
16 | }
17 |
18 | .change-list .filtered {
19 | min-height: 400px;
20 | }
21 |
22 | .change-list .filtered {
23 | background: white url(../img/changelist-bg.gif) top right repeat-y !important;
24 | }
25 |
26 | .change-list .filtered .results, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull {
27 | margin-right: 160px !important;
28 | width: auto !important;
29 | }
30 |
31 | .change-list .filtered table tbody th {
32 | padding-right: 1em;
33 | }
34 |
35 | #changelist-form .results {
36 | overflow-x: auto;
37 | }
38 |
39 | #changelist .toplinks {
40 | border-bottom: 1px solid #ccc !important;
41 | }
42 |
43 | #changelist .paginator {
44 | color: #666;
45 | border-top: 1px solid #eee;
46 | border-bottom: 1px solid #eee;
47 | background: white url(../img/nav-bg.gif) 0 180% repeat-x;
48 | overflow: hidden;
49 | }
50 |
51 | .change-list .filtered .paginator {
52 | border-right: 1px solid #ddd;
53 | }
54 |
55 | /* CHANGELIST TABLES */
56 |
57 | #changelist table thead th {
58 | padding: 0;
59 | white-space: nowrap;
60 | vertical-align: middle;
61 | }
62 |
63 | #changelist table thead th.action-checkbox-column {
64 | width: 1.5em;
65 | text-align: center;
66 | }
67 |
68 | #changelist table tbody td, #changelist table tbody th {
69 | border-left: 1px solid #ddd;
70 | }
71 |
72 | #changelist table tbody td:first-child, #changelist table tbody th:first-child {
73 | border-left: 0;
74 | border-right: 1px solid #ddd;
75 | }
76 |
77 | #changelist table tbody td.action-checkbox {
78 | text-align:center;
79 | }
80 |
81 | #changelist table tfoot {
82 | color: #666;
83 | }
84 |
85 | /* TOOLBAR */
86 |
87 | #changelist #toolbar {
88 | padding: 3px;
89 | border-bottom: 1px solid #ddd;
90 | background: #e1e1e1 url(../img/nav-bg.gif) top left repeat-x;
91 | color: #666;
92 | }
93 |
94 | #changelist #toolbar form input {
95 | font-size: 11px;
96 | padding: 1px 2px;
97 | }
98 |
99 | #changelist #toolbar form #searchbar {
100 | padding: 2px;
101 | }
102 |
103 | #changelist #changelist-search img {
104 | vertical-align: middle;
105 | }
106 |
107 | /* FILTER COLUMN */
108 |
109 | #changelist-filter {
110 | position: absolute;
111 | top: 0;
112 | right: 0;
113 | z-index: 1000;
114 | width: 160px;
115 | border-left: 1px solid #ddd;
116 | background: #efefef;
117 | margin: 0;
118 | }
119 |
120 | #changelist-filter h2 {
121 | font-size: 11px;
122 | padding: 2px 5px;
123 | border-bottom: 1px solid #ddd;
124 | }
125 |
126 | #changelist-filter h3 {
127 | font-size: 12px;
128 | margin-bottom: 0;
129 | }
130 |
131 | #changelist-filter ul {
132 | padding-left: 0;
133 | margin-left: 10px;
134 | }
135 |
136 | #changelist-filter li {
137 | list-style-type: none;
138 | margin-left: 0;
139 | padding-left: 0;
140 | }
141 |
142 | #changelist-filter a {
143 | color: #999;
144 | }
145 |
146 | #changelist-filter a:hover {
147 | color: #036;
148 | }
149 |
150 | #changelist-filter li.selected {
151 | border-left: 5px solid #ccc;
152 | padding-left: 5px;
153 | margin-left: -10px;
154 | }
155 |
156 | #changelist-filter li.selected a {
157 | color: #5b80b2 !important;
158 | }
159 |
160 | /* DATE DRILLDOWN */
161 |
162 | .change-list ul.toplinks {
163 | display: block;
164 | background: white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x;
165 | border-top: 1px solid white;
166 | float: left;
167 | padding: 0 !important;
168 | margin: 0 !important;
169 | width: 100%;
170 | }
171 |
172 | .change-list ul.toplinks li {
173 | padding: 3px 6px;
174 | font-weight: bold;
175 | list-style-type: none;
176 | display: inline-block;
177 | }
178 |
179 | .change-list ul.toplinks .date-back a {
180 | color: #999;
181 | }
182 |
183 | .change-list ul.toplinks .date-back a:hover {
184 | color: #036;
185 | }
186 |
187 | /* PAGINATOR */
188 |
189 | .paginator {
190 | font-size: 11px;
191 | padding-top: 10px;
192 | padding-bottom: 10px;
193 | line-height: 22px;
194 | margin: 0;
195 | border-top: 1px solid #ddd;
196 | }
197 |
198 | .paginator a:link, .paginator a:visited {
199 | padding: 2px 6px;
200 | border: solid 1px #ccc;
201 | background: white;
202 | text-decoration: none;
203 | }
204 |
205 | .paginator a.showall {
206 | padding: 0 !important;
207 | border: none !important;
208 | }
209 |
210 | .paginator a.showall:hover {
211 | color: #036 !important;
212 | background: transparent !important;
213 | }
214 |
215 | .paginator .end {
216 | border-width: 2px !important;
217 | margin-right: 6px;
218 | }
219 |
220 | .paginator .this-page {
221 | padding: 2px 6px;
222 | font-weight: bold;
223 | font-size: 13px;
224 | vertical-align: top;
225 | }
226 |
227 | .paginator a:hover {
228 | color: white;
229 | background: #5b80b2;
230 | border-color: #036;
231 | }
232 |
233 | /* ACTIONS */
234 |
235 | .filtered .actions {
236 | margin-right: 160px !important;
237 | border-right: 1px solid #ddd;
238 | }
239 |
240 | #changelist table input {
241 | margin: 0;
242 | }
243 |
244 | #changelist table tbody tr.selected {
245 | background-color: #FFFFCC;
246 | }
247 |
248 | #changelist .actions {
249 | color: #999;
250 | padding: 3px;
251 | border-top: 1px solid #fff;
252 | border-bottom: 1px solid #ddd;
253 | background: white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x;
254 | }
255 |
256 | #changelist .actions.selected {
257 | background: #fffccf;
258 | border-top: 1px solid #fffee8;
259 | border-bottom: 1px solid #edecd6;
260 | }
261 |
262 | #changelist .actions span.all,
263 | #changelist .actions span.action-counter,
264 | #changelist .actions span.clear,
265 | #changelist .actions span.question {
266 | font-size: 11px;
267 | margin: 0 0.5em;
268 | display: none;
269 | }
270 |
271 | #changelist .actions:last-child {
272 | border-bottom: none;
273 | }
274 |
275 | #changelist .actions select {
276 | border: 1px solid #aaa;
277 | margin-left: 0.5em;
278 | padding: 1px 2px;
279 | }
280 |
281 | #changelist .actions label {
282 | font-size: 11px;
283 | margin-left: 0.5em;
284 | }
285 |
286 | #changelist #action-toggle {
287 | display: none;
288 | }
289 |
290 | #changelist .actions .button {
291 | font-size: 11px;
292 | padding: 1px 2px;
293 | }
294 |
--------------------------------------------------------------------------------
/static/admin/css/forms.css:
--------------------------------------------------------------------------------
1 | @import url('widgets.css');
2 |
3 | /* FORM ROWS */
4 |
5 | .form-row {
6 | overflow: hidden;
7 | padding: 8px 12px;
8 | font-size: 11px;
9 | border-bottom: 1px solid #eee;
10 | }
11 |
12 | .form-row img, .form-row input {
13 | vertical-align: middle;
14 | }
15 |
16 | form .form-row p {
17 | padding-left: 0;
18 | font-size: 11px;
19 | }
20 |
21 | /* FORM LABELS */
22 |
23 | form h4 {
24 | margin: 0 !important;
25 | padding: 0 !important;
26 | border: none !important;
27 | }
28 |
29 | label {
30 | font-weight: normal !important;
31 | color: #666;
32 | font-size: 12px;
33 | }
34 |
35 | .required label, label.required {
36 | font-weight: bold !important;
37 | color: #333 !important;
38 | }
39 |
40 | /* RADIO BUTTONS */
41 |
42 | form ul.radiolist li {
43 | list-style-type: none;
44 | }
45 |
46 | form ul.radiolist label {
47 | float: none;
48 | display: inline;
49 | }
50 |
51 | form ul.inline {
52 | margin-left: 0;
53 | padding: 0;
54 | }
55 |
56 | form ul.inline li {
57 | float: left;
58 | padding-right: 7px;
59 | }
60 |
61 | /* ALIGNED FIELDSETS */
62 |
63 | .aligned label {
64 | display: block;
65 | padding: 3px 10px 0 0;
66 | float: left;
67 | width: 8em;
68 | word-wrap: break-word;
69 | }
70 |
71 | .aligned ul label {
72 | display: inline;
73 | float: none;
74 | width: auto;
75 | }
76 |
77 | .colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField {
78 | width: 350px;
79 | }
80 |
81 | form .aligned p, form .aligned ul {
82 | margin-left: 7em;
83 | padding-left: 30px;
84 | }
85 |
86 | form .aligned table p {
87 | margin-left: 0;
88 | padding-left: 0;
89 | }
90 |
91 | form .aligned p.help {
92 | padding-left: 38px;
93 | }
94 |
95 | .aligned .vCheckboxLabel {
96 | float: none !important;
97 | display: inline;
98 | padding-left: 4px;
99 | }
100 |
101 | .colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField {
102 | width: 610px;
103 | }
104 |
105 | .checkbox-row p.help {
106 | margin-left: 0;
107 | padding-left: 0 !important;
108 | }
109 |
110 | fieldset .field-box {
111 | float: left;
112 | margin-right: 20px;
113 | }
114 |
115 | /* WIDE FIELDSETS */
116 |
117 | .wide label {
118 | width: 15em !important;
119 | }
120 |
121 | form .wide p {
122 | margin-left: 15em;
123 | }
124 |
125 | form .wide p.help {
126 | padding-left: 38px;
127 | }
128 |
129 | .colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField {
130 | width: 450px;
131 | }
132 |
133 | /* COLLAPSED FIELDSETS */
134 |
135 | fieldset.collapsed * {
136 | display: none;
137 | }
138 |
139 | fieldset.collapsed h2, fieldset.collapsed {
140 | display: block !important;
141 | }
142 |
143 | fieldset.collapsed h2 {
144 | background-image: url(../img/nav-bg.gif);
145 | background-position: bottom left;
146 | color: #999;
147 | }
148 |
149 | fieldset.collapsed .collapse-toggle {
150 | background: transparent;
151 | display: inline !important;
152 | }
153 |
154 | /* MONOSPACE TEXTAREAS */
155 |
156 | fieldset.monospace textarea {
157 | font-family: "Bitstream Vera Sans Mono",Monaco,"Courier New",Courier,monospace;
158 | }
159 |
160 | /* SUBMIT ROW */
161 |
162 | .submit-row {
163 | padding: 5px 7px;
164 | text-align: right;
165 | background: white url(../img/nav-bg.gif) 0 100% repeat-x;
166 | border: 1px solid #ccc;
167 | margin: 5px 0;
168 | overflow: hidden;
169 | }
170 |
171 | body.popup .submit-row {
172 | overflow: auto;
173 | }
174 |
175 | .submit-row input {
176 | margin: 0 0 0 5px;
177 | }
178 |
179 | .submit-row p {
180 | margin: 0.3em;
181 | }
182 |
183 | .submit-row p.deletelink-box {
184 | float: left;
185 | }
186 |
187 | .submit-row .deletelink {
188 | background: url(../img/icon_deletelink.gif) 0 50% no-repeat;
189 | padding-left: 14px;
190 | }
191 |
192 | /* CUSTOM FORM FIELDS */
193 |
194 | .vSelectMultipleField {
195 | vertical-align: top !important;
196 | }
197 |
198 | .vCheckboxField {
199 | border: none;
200 | }
201 |
202 | .vDateField, .vTimeField {
203 | margin-right: 2px;
204 | }
205 |
206 | .vURLField {
207 | width: 30em;
208 | }
209 |
210 | .vLargeTextField, .vXMLLargeTextField {
211 | width: 48em;
212 | }
213 |
214 | .flatpages-flatpage #id_content {
215 | height: 40.2em;
216 | }
217 |
218 | .module table .vPositiveSmallIntegerField {
219 | width: 2.2em;
220 | }
221 |
222 | .vTextField {
223 | width: 20em;
224 | }
225 |
226 | .vIntegerField {
227 | width: 5em;
228 | }
229 |
230 | .vBigIntegerField {
231 | width: 10em;
232 | }
233 |
234 | .vForeignKeyRawIdAdminField {
235 | width: 5em;
236 | }
237 |
238 | /* INLINES */
239 |
240 | .inline-group {
241 | padding: 0;
242 | border: 1px solid #ccc;
243 | margin: 10px 0;
244 | }
245 |
246 | .inline-group .aligned label {
247 | width: 8em;
248 | }
249 |
250 | .inline-related {
251 | position: relative;
252 | }
253 |
254 | .inline-related h3 {
255 | margin: 0;
256 | color: #666;
257 | padding: 3px 5px;
258 | font-size: 11px;
259 | background: #e1e1e1 url(../img/nav-bg.gif) top left repeat-x;
260 | border-bottom: 1px solid #ddd;
261 | }
262 |
263 | .inline-related h3 span.delete {
264 | float: right;
265 | }
266 |
267 | .inline-related h3 span.delete label {
268 | margin-left: 2px;
269 | font-size: 11px;
270 | }
271 |
272 | .inline-related fieldset {
273 | margin: 0;
274 | background: #fff;
275 | border: none;
276 | width: 100%;
277 | }
278 |
279 | .inline-related fieldset.module h3 {
280 | margin: 0;
281 | padding: 2px 5px 3px 5px;
282 | font-size: 11px;
283 | text-align: left;
284 | font-weight: bold;
285 | background: #bcd;
286 | color: #fff;
287 | }
288 |
289 | .inline-group .tabular fieldset.module {
290 | border: none;
291 | border-bottom: 1px solid #ddd;
292 | }
293 |
294 | .inline-related.tabular fieldset.module table {
295 | width: 100%;
296 | }
297 |
298 | .last-related fieldset {
299 | border: none;
300 | }
301 |
302 | .inline-group .tabular tr.has_original td {
303 | padding-top: 2em;
304 | }
305 |
306 | .inline-group .tabular tr td.original {
307 | padding: 2px 0 0 0;
308 | width: 0;
309 | _position: relative;
310 | }
311 |
312 | .inline-group .tabular th.original {
313 | width: 0px;
314 | padding: 0;
315 | }
316 |
317 | .inline-group .tabular td.original p {
318 | position: absolute;
319 | left: 0;
320 | height: 1.1em;
321 | padding: 2px 7px;
322 | overflow: hidden;
323 | font-size: 9px;
324 | font-weight: bold;
325 | color: #666;
326 | _width: 700px;
327 | }
328 |
329 | .inline-group ul.tools {
330 | padding: 0;
331 | margin: 0;
332 | list-style: none;
333 | }
334 |
335 | .inline-group ul.tools li {
336 | display: inline;
337 | padding: 0 5px;
338 | }
339 |
340 | .inline-group div.add-row,
341 | .inline-group .tabular tr.add-row td {
342 | color: #666;
343 | padding: 3px 5px;
344 | border-bottom: 1px solid #ddd;
345 | background: #e1e1e1 url(../img/nav-bg.gif) top left repeat-x;
346 | }
347 |
348 | .inline-group .tabular tr.add-row td {
349 | padding: 4px 5px 3px;
350 | border-bottom: none;
351 | }
352 |
353 | .inline-group ul.tools a.add,
354 | .inline-group div.add-row a,
355 | .inline-group .tabular tr.add-row td a {
356 | background: url(../img/icon_addlink.gif) 0 50% no-repeat;
357 | padding-left: 14px;
358 | font-size: 11px;
359 | outline: 0; /* Remove dotted border around link */
360 | }
361 |
362 | .empty-form {
363 | display: none;
364 | }
365 |
--------------------------------------------------------------------------------
/static/admin/js/core.js:
--------------------------------------------------------------------------------
1 | // Core javascript helper functions
2 |
3 | // basic browser identification & version
4 | var isOpera = (navigator.userAgent.indexOf("Opera")>=0) && parseFloat(navigator.appVersion);
5 | var isIE = ((document.all) && (!isOpera)) && parseFloat(navigator.appVersion.split("MSIE ")[1].split(";")[0]);
6 |
7 | // Cross-browser event handlers.
8 | function addEvent(obj, evType, fn) {
9 | if (obj.addEventListener) {
10 | obj.addEventListener(evType, fn, false);
11 | return true;
12 | } else if (obj.attachEvent) {
13 | var r = obj.attachEvent("on" + evType, fn);
14 | return r;
15 | } else {
16 | return false;
17 | }
18 | }
19 |
20 | function removeEvent(obj, evType, fn) {
21 | if (obj.removeEventListener) {
22 | obj.removeEventListener(evType, fn, false);
23 | return true;
24 | } else if (obj.detachEvent) {
25 | obj.detachEvent("on" + evType, fn);
26 | return true;
27 | } else {
28 | return false;
29 | }
30 | }
31 |
32 | function cancelEventPropagation(e) {
33 | if (!e) e = window.event;
34 | e.cancelBubble = true;
35 | if (e.stopPropagation) e.stopPropagation();
36 | }
37 |
38 | // quickElement(tagType, parentReference, textInChildNode, [, attribute, attributeValue ...]);
39 | function quickElement() {
40 | var obj = document.createElement(arguments[0]);
41 | if (arguments[2] != '' && arguments[2] != null) {
42 | var textNode = document.createTextNode(arguments[2]);
43 | obj.appendChild(textNode);
44 | }
45 | var len = arguments.length;
46 | for (var i = 3; i < len; i += 2) {
47 | obj.setAttribute(arguments[i], arguments[i+1]);
48 | }
49 | arguments[1].appendChild(obj);
50 | return obj;
51 | }
52 |
53 | // "a" is reference to an object
54 | function removeChildren(a) {
55 | while (a.hasChildNodes()) a.removeChild(a.lastChild);
56 | }
57 |
58 | // ----------------------------------------------------------------------------
59 | // Cross-browser xmlhttp object
60 | // from http://jibbering.com/2002/4/httprequest.html
61 | // ----------------------------------------------------------------------------
62 | var xmlhttp;
63 | /*@cc_on @*/
64 | /*@if (@_jscript_version >= 5)
65 | try {
66 | xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
67 | } catch (e) {
68 | try {
69 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
70 | } catch (E) {
71 | xmlhttp = false;
72 | }
73 | }
74 | @else
75 | xmlhttp = false;
76 | @end @*/
77 | if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
78 | xmlhttp = new XMLHttpRequest();
79 | }
80 |
81 | // ----------------------------------------------------------------------------
82 | // Find-position functions by PPK
83 | // See http://www.quirksmode.org/js/findpos.html
84 | // ----------------------------------------------------------------------------
85 | function findPosX(obj) {
86 | var curleft = 0;
87 | if (obj.offsetParent) {
88 | while (obj.offsetParent) {
89 | curleft += obj.offsetLeft - ((isOpera) ? 0 : obj.scrollLeft);
90 | obj = obj.offsetParent;
91 | }
92 | // IE offsetParent does not include the top-level
93 | if (isIE && obj.parentElement){
94 | curleft += obj.offsetLeft - obj.scrollLeft;
95 | }
96 | } else if (obj.x) {
97 | curleft += obj.x;
98 | }
99 | return curleft;
100 | }
101 |
102 | function findPosY(obj) {
103 | var curtop = 0;
104 | if (obj.offsetParent) {
105 | while (obj.offsetParent) {
106 | curtop += obj.offsetTop - ((isOpera) ? 0 : obj.scrollTop);
107 | obj = obj.offsetParent;
108 | }
109 | // IE offsetParent does not include the top-level
110 | if (isIE && obj.parentElement){
111 | curtop += obj.offsetTop - obj.scrollTop;
112 | }
113 | } else if (obj.y) {
114 | curtop += obj.y;
115 | }
116 | return curtop;
117 | }
118 |
119 | //-----------------------------------------------------------------------------
120 | // Date object extensions
121 | // ----------------------------------------------------------------------------
122 |
123 | Date.prototype.getTwelveHours = function() {
124 | hours = this.getHours();
125 | if (hours == 0) {
126 | return 12;
127 | }
128 | else {
129 | return hours <= 12 ? hours : hours-12
130 | }
131 | }
132 |
133 | Date.prototype.getTwoDigitMonth = function() {
134 | return (this.getMonth() < 9) ? '0' + (this.getMonth()+1) : (this.getMonth()+1);
135 | }
136 |
137 | Date.prototype.getTwoDigitDate = function() {
138 | return (this.getDate() < 10) ? '0' + this.getDate() : this.getDate();
139 | }
140 |
141 | Date.prototype.getTwoDigitTwelveHour = function() {
142 | return (this.getTwelveHours() < 10) ? '0' + this.getTwelveHours() : this.getTwelveHours();
143 | }
144 |
145 | Date.prototype.getTwoDigitHour = function() {
146 | return (this.getHours() < 10) ? '0' + this.getHours() : this.getHours();
147 | }
148 |
149 | Date.prototype.getTwoDigitMinute = function() {
150 | return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes();
151 | }
152 |
153 | Date.prototype.getTwoDigitSecond = function() {
154 | return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds();
155 | }
156 |
157 | Date.prototype.getHourMinute = function() {
158 | return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute();
159 | }
160 |
161 | Date.prototype.getHourMinuteSecond = function() {
162 | return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute() + ':' + this.getTwoDigitSecond();
163 | }
164 |
165 | Date.prototype.strftime = function(format) {
166 | var fields = {
167 | c: this.toString(),
168 | d: this.getTwoDigitDate(),
169 | H: this.getTwoDigitHour(),
170 | I: this.getTwoDigitTwelveHour(),
171 | m: this.getTwoDigitMonth(),
172 | M: this.getTwoDigitMinute(),
173 | p: (this.getHours() >= 12) ? 'PM' : 'AM',
174 | S: this.getTwoDigitSecond(),
175 | w: '0' + this.getDay(),
176 | x: this.toLocaleDateString(),
177 | X: this.toLocaleTimeString(),
178 | y: ('' + this.getFullYear()).substr(2, 4),
179 | Y: '' + this.getFullYear(),
180 | '%' : '%'
181 | };
182 | var result = '', i = 0;
183 | while (i < format.length) {
184 | if (format.charAt(i) === '%') {
185 | result = result + fields[format.charAt(i + 1)];
186 | ++i;
187 | }
188 | else {
189 | result = result + format.charAt(i);
190 | }
191 | ++i;
192 | }
193 | return result;
194 | }
195 |
196 | // ----------------------------------------------------------------------------
197 | // String object extensions
198 | // ----------------------------------------------------------------------------
199 | String.prototype.pad_left = function(pad_length, pad_string) {
200 | var new_string = this;
201 | for (var i = 0; new_string.length < pad_length; i++) {
202 | new_string = pad_string + new_string;
203 | }
204 | return new_string;
205 | }
206 |
207 | // ----------------------------------------------------------------------------
208 | // Get the computed style for and element
209 | // ----------------------------------------------------------------------------
210 | function getStyle(oElm, strCssRule){
211 | var strValue = "";
212 | if(document.defaultView && document.defaultView.getComputedStyle){
213 | strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
214 | }
215 | else if(oElm.currentStyle){
216 | strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
217 | return p1.toUpperCase();
218 | });
219 | strValue = oElm.currentStyle[strCssRule];
220 | }
221 | return strValue;
222 | }
223 |
--------------------------------------------------------------------------------
/static/admin/js/SelectFilter2.js:
--------------------------------------------------------------------------------
1 | /*
2 | SelectFilter2 - Turns a multiple-select box into a filter interface.
3 |
4 | Requires core.js, SelectBox.js and addevent.js.
5 | */
6 | (function($) {
7 | function findForm(node) {
8 | // returns the node of the form containing the given node
9 | if (node.tagName.toLowerCase() != 'form') {
10 | return findForm(node.parentNode);
11 | }
12 | return node;
13 | }
14 |
15 | window.SelectFilter = {
16 | init: function(field_id, field_name, is_stacked, admin_static_prefix) {
17 | if (field_id.match(/__prefix__/)){
18 | // Don't intialize on empty forms.
19 | return;
20 | }
21 | var from_box = document.getElementById(field_id);
22 | from_box.id += '_from'; // change its ID
23 | from_box.className = 'filtered';
24 |
25 | var ps = from_box.parentNode.getElementsByTagName('p');
26 | for (var i=0; i, because it just gets in the way.
29 | from_box.parentNode.removeChild(ps[i]);
30 | } else if (ps[i].className.indexOf("help") != -1) {
31 | // Move help text up to the top so it isn't below the select
32 | // boxes or wrapped off on the side to the right of the add
33 | // button:
34 | from_box.parentNode.insertBefore(ps[i], from_box.parentNode.firstChild);
35 | }
36 | }
37 |
38 | // or
39 | var selector_div = quickElement('div', from_box.parentNode);
40 | selector_div.className = is_stacked ? 'selector stacked' : 'selector';
41 |
42 | //
43 | var selector_available = quickElement('div', selector_div, '');
44 | selector_available.className = 'selector-available';
45 | var title_available = quickElement('h2', selector_available, interpolate(gettext('Available %s') + ' ', [field_name]));
46 | quickElement('img', title_available, '', 'src', admin_static_prefix + 'img/icon-unknown.gif', 'width', '10', 'height', '10', 'class', 'help help-tooltip', 'title', interpolate(gettext('This is the list of available %s. You may choose some by selecting them in the box below and then clicking the "Choose" arrow between the two boxes.'), [field_name]));
47 |
48 | var filter_p = quickElement('p', selector_available, '', 'id', field_id + '_filter');
49 | filter_p.className = 'selector-filter';
50 |
51 | var search_filter_label = quickElement('label', filter_p, '', 'for', field_id + "_input");
52 |
53 | var search_selector_img = quickElement('img', search_filter_label, '', 'src', admin_static_prefix + 'img/selector-search.gif', 'class', 'help-tooltip', 'alt', '', 'title', interpolate(gettext("Type into this box to filter down the list of available %s."), [field_name]));
54 |
55 | filter_p.appendChild(document.createTextNode(' '));
56 |
57 | var filter_input = quickElement('input', filter_p, '', 'type', 'text', 'placeholder', gettext("Filter"));
58 | filter_input.id = field_id + '_input';
59 |
60 | selector_available.appendChild(from_box);
61 | var choose_all = quickElement('a', selector_available, gettext('Choose all'), 'title', interpolate(gettext('Click to choose all %s at once.'), [field_name]), 'href', 'javascript: (function(){ SelectBox.move_all("' + field_id + '_from", "' + field_id + '_to"); SelectFilter.refresh_icons("' + field_id + '");})()', 'id', field_id + '_add_all_link');
62 | choose_all.className = 'selector-chooseall';
63 |
64 | //
65 | var selector_chooser = quickElement('ul', selector_div, '');
66 | selector_chooser.className = 'selector-chooser';
67 | var add_link = quickElement('a', quickElement('li', selector_chooser, ''), gettext('Choose'), 'title', gettext('Choose'), 'href', 'javascript: (function(){ SelectBox.move("' + field_id + '_from","' + field_id + '_to"); SelectFilter.refresh_icons("' + field_id + '");})()', 'id', field_id + '_add_link');
68 | add_link.className = 'selector-add';
69 | var remove_link = quickElement('a', quickElement('li', selector_chooser, ''), gettext('Remove'), 'title', gettext('Remove'), 'href', 'javascript: (function(){ SelectBox.move("' + field_id + '_to","' + field_id + '_from"); SelectFilter.refresh_icons("' + field_id + '");})()', 'id', field_id + '_remove_link');
70 | remove_link.className = 'selector-remove';
71 |
72 | //
73 | var selector_chosen = quickElement('div', selector_div, '');
74 | selector_chosen.className = 'selector-chosen';
75 | var title_chosen = quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s') + ' ', [field_name]));
76 | quickElement('img', title_chosen, '', 'src', admin_static_prefix + 'img/icon-unknown.gif', 'width', '10', 'height', '10', 'class', 'help help-tooltip', 'title', interpolate(gettext('This is the list of chosen %s. You may remove some by selecting them in the box below and then clicking the "Remove" arrow between the two boxes.'), [field_name]));
77 |
78 | var to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', 'multiple', 'size', from_box.size, 'name', from_box.getAttribute('name'));
79 | to_box.className = 'filtered';
80 | var clear_all = quickElement('a', selector_chosen, gettext('Remove all'), 'title', interpolate(gettext('Click to remove all chosen %s at once.'), [field_name]), 'href', 'javascript: (function() { SelectBox.move_all("' + field_id + '_to", "' + field_id + '_from"); SelectFilter.refresh_icons("' + field_id + '");})()', 'id', field_id + '_remove_all_link');
81 | clear_all.className = 'selector-clearall';
82 |
83 | from_box.setAttribute('name', from_box.getAttribute('name') + '_old');
84 |
85 | // Set up the JavaScript event handlers for the select box filter interface
86 | addEvent(filter_input, 'keyup', function(e) { SelectFilter.filter_key_up(e, field_id); });
87 | addEvent(filter_input, 'keydown', function(e) { SelectFilter.filter_key_down(e, field_id); });
88 | addEvent(from_box, 'change', function(e) { SelectFilter.refresh_icons(field_id) });
89 | addEvent(to_box, 'change', function(e) { SelectFilter.refresh_icons(field_id) });
90 | addEvent(from_box, 'dblclick', function() { SelectBox.move(field_id + '_from', field_id + '_to'); SelectFilter.refresh_icons(field_id); });
91 | addEvent(to_box, 'dblclick', function() { SelectBox.move(field_id + '_to', field_id + '_from'); SelectFilter.refresh_icons(field_id); });
92 | addEvent(findForm(from_box), 'submit', function() { SelectBox.select_all(field_id + '_to'); });
93 | SelectBox.init(field_id + '_from');
94 | SelectBox.init(field_id + '_to');
95 | // Move selected from_box options to to_box
96 | SelectBox.move(field_id + '_from', field_id + '_to');
97 |
98 | if (!is_stacked) {
99 | // In horizontal mode, give the same height to the two boxes.
100 | var j_from_box = $(from_box);
101 | var j_to_box = $(to_box);
102 | var resize_filters = function() { j_to_box.height($(filter_p).outerHeight() + j_from_box.outerHeight()); }
103 | if (j_from_box.outerHeight() > 0) {
104 | resize_filters(); // This fieldset is already open. Resize now.
105 | } else {
106 | // This fieldset is probably collapsed. Wait for its 'show' event.
107 | j_to_box.closest('fieldset').one('show.fieldset', resize_filters);
108 | }
109 | }
110 |
111 | // Initial icon refresh
112 | SelectFilter.refresh_icons(field_id);
113 | },
114 | refresh_icons: function(field_id) {
115 | var from = $('#' + field_id + '_from');
116 | var to = $('#' + field_id + '_to');
117 | var is_from_selected = from.find('option:selected').length > 0;
118 | var is_to_selected = to.find('option:selected').length > 0;
119 | // Active if at least one item is selected
120 | $('#' + field_id + '_add_link').toggleClass('active', is_from_selected);
121 | $('#' + field_id + '_remove_link').toggleClass('active', is_to_selected);
122 | // Active if the corresponding box isn't empty
123 | $('#' + field_id + '_add_all_link').toggleClass('active', from.find('option').length > 0);
124 | $('#' + field_id + '_remove_all_link').toggleClass('active', to.find('option').length > 0);
125 | },
126 | filter_key_up: function(event, field_id) {
127 | var from = document.getElementById(field_id + '_from');
128 | // don't submit form if user pressed Enter
129 | if ((event.which && event.which == 13) || (event.keyCode && event.keyCode == 13)) {
130 | from.selectedIndex = 0;
131 | SelectBox.move(field_id + '_from', field_id + '_to');
132 | from.selectedIndex = 0;
133 | return false;
134 | }
135 | var temp = from.selectedIndex;
136 | SelectBox.filter(field_id + '_from', document.getElementById(field_id + '_input').value);
137 | from.selectedIndex = temp;
138 | return true;
139 | },
140 | filter_key_down: function(event, field_id) {
141 | var from = document.getElementById(field_id + '_from');
142 | // right arrow -- move across
143 | if ((event.which && event.which == 39) || (event.keyCode && event.keyCode == 39)) {
144 | var old_index = from.selectedIndex;
145 | SelectBox.move(field_id + '_from', field_id + '_to');
146 | from.selectedIndex = (old_index == from.length) ? from.length - 1 : old_index;
147 | return false;
148 | }
149 | // down arrow -- wrap around
150 | if ((event.which && event.which == 40) || (event.keyCode && event.keyCode == 40)) {
151 | from.selectedIndex = (from.length == from.selectedIndex + 1) ? 0 : from.selectedIndex + 1;
152 | }
153 | // up arrow -- wrap around
154 | if ((event.which && event.which == 38) || (event.keyCode && event.keyCode == 38)) {
155 | from.selectedIndex = (from.selectedIndex == 0) ? from.length - 1 : from.selectedIndex - 1;
156 | }
157 | return true;
158 | }
159 | }
160 |
161 | })(django.jQuery);
162 |
--------------------------------------------------------------------------------
/static/admin/js/inlines.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Django admin inlines
3 | *
4 | * Based on jQuery Formset 1.1
5 | * @author Stanislaus Madueke (stan DOT madueke AT gmail DOT com)
6 | * @requires jQuery 1.2.6 or later
7 | *
8 | * Copyright (c) 2009, Stanislaus Madueke
9 | * All rights reserved.
10 | *
11 | * Spiced up with Code from Zain Memon's GSoC project 2009
12 | * and modified for Django by Jannis Leidel, Travis Swicegood and Julien Phalip.
13 | *
14 | * Licensed under the New BSD License
15 | * See: http://www.opensource.org/licenses/bsd-license.php
16 | */
17 | (function($) {
18 | $.fn.formset = function(opts) {
19 | var options = $.extend({}, $.fn.formset.defaults, opts);
20 | var $this = $(this);
21 | var $parent = $this.parent();
22 | var updateElementIndex = function(el, prefix, ndx) {
23 | var id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))");
24 | var replacement = prefix + "-" + ndx;
25 | if ($(el).prop("for")) {
26 | $(el).prop("for", $(el).prop("for").replace(id_regex, replacement));
27 | }
28 | if (el.id) {
29 | el.id = el.id.replace(id_regex, replacement);
30 | }
31 | if (el.name) {
32 | el.name = el.name.replace(id_regex, replacement);
33 | }
34 | };
35 | var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").prop("autocomplete", "off");
36 | var nextIndex = parseInt(totalForms.val(), 10);
37 | var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").prop("autocomplete", "off");
38 | // only show the add button if we are allowed to add more items,
39 | // note that max_num = None translates to a blank string.
40 | var showAddButton = maxForms.val() === '' || (maxForms.val()-totalForms.val()) > 0;
41 | $this.each(function(i) {
42 | $(this).not("." + options.emptyCssClass).addClass(options.formCssClass);
43 | });
44 | if ($this.length && showAddButton) {
45 | var addButton;
46 | if ($this.prop("tagName") == "TR") {
47 | // If forms are laid out as table rows, insert the
48 | // "add" button in a new table row:
49 | var numCols = this.eq(-1).children().length;
50 | $parent.append('
' + options.addText + " ");
51 | addButton = $parent.find("tr:last a");
52 | } else {
53 | // Otherwise, insert it immediately after the last form:
54 | $this.filter(":last").after('
");
55 | addButton = $this.filter(":last").next().find("a");
56 | }
57 | addButton.click(function(e) {
58 | e.preventDefault();
59 | var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS");
60 | var template = $("#" + options.prefix + "-empty");
61 | var row = template.clone(true);
62 | row.removeClass(options.emptyCssClass)
63 | .addClass(options.formCssClass)
64 | .attr("id", options.prefix + "-" + nextIndex);
65 | if (row.is("tr")) {
66 | // If the forms are laid out in table rows, insert
67 | // the remove button into the last table cell:
68 | row.children(":last").append('
");
69 | } else if (row.is("ul") || row.is("ol")) {
70 | // If they're laid out as an ordered/unordered list,
71 | // insert an
after the last list item:
72 | row.append(' ' + options.deleteText + " ");
73 | } else {
74 | // Otherwise, just insert the remove button as the
75 | // last child element of the form's container:
76 | row.children(":first").append('
' + options.deleteText + " ");
77 | }
78 | row.find("*").each(function() {
79 | updateElementIndex(this, options.prefix, totalForms.val());
80 | });
81 | // Insert the new form when it has been fully edited
82 | row.insertBefore($(template));
83 | // Update number of total forms
84 | $(totalForms).val(parseInt(totalForms.val(), 10) + 1);
85 | nextIndex += 1;
86 | // Hide add button in case we've hit the max, except we want to add infinitely
87 | if ((maxForms.val() !== '') && (maxForms.val()-totalForms.val()) <= 0) {
88 | addButton.parent().hide();
89 | }
90 | // The delete button of each row triggers a bunch of other things
91 | row.find("a." + options.deleteCssClass).click(function(e) {
92 | e.preventDefault();
93 | // Remove the parent form containing this button:
94 | var row = $(this).parents("." + options.formCssClass);
95 | row.remove();
96 | nextIndex -= 1;
97 | // If a post-delete callback was provided, call it with the deleted form:
98 | if (options.removed) {
99 | options.removed(row);
100 | }
101 | // Update the TOTAL_FORMS form count.
102 | var forms = $("." + options.formCssClass);
103 | $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length);
104 | // Show add button again once we drop below max
105 | if ((maxForms.val() === '') || (maxForms.val()-forms.length) > 0) {
106 | addButton.parent().show();
107 | }
108 | // Also, update names and ids for all remaining form controls
109 | // so they remain in sequence:
110 | for (var i=0, formCount=forms.length; i
3 | //
4 |
5 | var DateTimeShortcuts = {
6 | calendars: [],
7 | calendarInputs: [],
8 | clockInputs: [],
9 | dismissClockFunc: [],
10 | dismissCalendarFunc: [],
11 | calendarDivName1: 'calendarbox', // name of calendar that gets toggled
12 | calendarDivName2: 'calendarin', // name of
that contains calendar
13 | calendarLinkName: 'calendarlink',// name of the link that is used to toggle
14 | clockDivName: 'clockbox', // name of clock
that gets toggled
15 | clockLinkName: 'clocklink', // name of the link that is used to toggle
16 | shortCutsClass: 'datetimeshortcuts', // class of the clock and cal shortcuts
17 | admin_media_prefix: '',
18 | init: function() {
19 | // Get admin_media_prefix by grabbing it off the window object. It's
20 | // set in the admin/base.html template, so if it's not there, someone's
21 | // overridden the template. In that case, we'll set a clearly-invalid
22 | // value in the hopes that someone will examine HTTP requests and see it.
23 | if (window.__admin_media_prefix__ != undefined) {
24 | DateTimeShortcuts.admin_media_prefix = window.__admin_media_prefix__;
25 | } else {
26 | DateTimeShortcuts.admin_media_prefix = '/missing-admin-media-prefix/';
27 | }
28 |
29 | var inputs = document.getElementsByTagName('input');
30 | for (i=0; i
66 | // Choose a time
67 | //
73 | // Cancel
74 | //
75 |
76 | var clock_box = document.createElement('div');
77 | clock_box.style.display = 'none';
78 | clock_box.style.position = 'absolute';
79 | clock_box.className = 'clockbox module';
80 | clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
81 | document.body.appendChild(clock_box);
82 | addEvent(clock_box, 'click', cancelEventPropagation);
83 |
84 | quickElement('h2', clock_box, gettext('Choose a time'));
85 | var time_list = quickElement('ul', clock_box, '');
86 | time_list.className = 'timelist';
87 | var time_format = get_format('TIME_INPUT_FORMATS')[0];
88 | quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().strftime('" + time_format + "'));");
89 | quickElement("a", quickElement("li", time_list, ""), gettext("Midnight"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,0,0,0,0).strftime('" + time_format + "'));");
90 | quickElement("a", quickElement("li", time_list, ""), gettext("6 a.m."), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,6,0,0,0).strftime('" + time_format + "'));");
91 | quickElement("a", quickElement("li", time_list, ""), gettext("Noon"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date(1970,1,1,12,0,0,0).strftime('" + time_format + "'));");
92 |
93 | var cancel_p = quickElement('p', clock_box, '');
94 | cancel_p.className = 'calendar-cancel';
95 | quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
96 | django.jQuery(document).bind('keyup', function(event) {
97 | if (event.which == 27) {
98 | // ESC key closes popup
99 | DateTimeShortcuts.dismissClock(num);
100 | event.preventDefault();
101 | }
102 | });
103 | },
104 | openClock: function(num) {
105 | var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num)
106 | var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num)
107 |
108 | // Recalculate the clockbox position
109 | // is it left-to-right or right-to-left layout ?
110 | if (getStyle(document.body,'direction')!='rtl') {
111 | clock_box.style.left = findPosX(clock_link) + 17 + 'px';
112 | }
113 | else {
114 | // since style's width is in em, it'd be tough to calculate
115 | // px value of it. let's use an estimated px for now
116 | // TODO: IE returns wrong value for findPosX when in rtl mode
117 | // (it returns as it was left aligned), needs to be fixed.
118 | clock_box.style.left = findPosX(clock_link) - 110 + 'px';
119 | }
120 | clock_box.style.top = Math.max(0, findPosY(clock_link) - 30) + 'px';
121 |
122 | // Show the clock box
123 | clock_box.style.display = 'block';
124 | addEvent(document, 'click', DateTimeShortcuts.dismissClockFunc[num]);
125 | },
126 | dismissClock: function(num) {
127 | document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none';
128 | removeEvent(document, 'click', DateTimeShortcuts.dismissClockFunc[num]);
129 | },
130 | handleClockQuicklink: function(num, val) {
131 | DateTimeShortcuts.clockInputs[num].value = val;
132 | DateTimeShortcuts.clockInputs[num].focus();
133 | DateTimeShortcuts.dismissClock(num);
134 | },
135 | // Add calendar widget to a given field.
136 | addCalendar: function(inp) {
137 | var num = DateTimeShortcuts.calendars.length;
138 |
139 | DateTimeShortcuts.calendarInputs[num] = inp;
140 | DateTimeShortcuts.dismissCalendarFunc[num] = function() { DateTimeShortcuts.dismissCalendar(num); return true; };
141 |
142 | // Shortcut links (calendar icon and "Today" link)
143 | var shortcuts_span = document.createElement('span');
144 | shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
145 | inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
146 | var today_link = document.createElement('a');
147 | today_link.setAttribute('href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
148 | today_link.appendChild(document.createTextNode(gettext('Today')));
149 | var cal_link = document.createElement('a');
150 | cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
151 | cal_link.id = DateTimeShortcuts.calendarLinkName + num;
152 | quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/icon_calendar.gif', 'alt', gettext('Calendar'));
153 | shortcuts_span.appendChild(document.createTextNode('\240'));
154 | shortcuts_span.appendChild(today_link);
155 | shortcuts_span.appendChild(document.createTextNode('\240|\240'));
156 | shortcuts_span.appendChild(cal_link);
157 |
158 | // Create calendarbox div.
159 | //
160 | // Markup looks like:
161 | //
162 | //
163 | //
164 | // ‹
165 | // › February 2003
166 | //
167 | //
168 | //
169 | //
170 | //
173 | //
Cancel
174 | //
175 | var cal_box = document.createElement('div');
176 | cal_box.style.display = 'none';
177 | cal_box.style.position = 'absolute';
178 | cal_box.className = 'calendarbox module';
179 | cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
180 | document.body.appendChild(cal_box);
181 | addEvent(cal_box, 'click', cancelEventPropagation);
182 |
183 | // next-prev links
184 | var cal_nav = quickElement('div', cal_box, '');
185 | var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', 'javascript:DateTimeShortcuts.drawPrev('+num+');');
186 | cal_nav_prev.className = 'calendarnav-previous';
187 | var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');');
188 | cal_nav_next.className = 'calendarnav-next';
189 |
190 | // main box
191 | var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);
192 | cal_main.className = 'calendar';
193 | DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num));
194 | DateTimeShortcuts.calendars[num].drawCurrent();
195 |
196 | // calendar shortcuts
197 | var shortcuts = quickElement('div', cal_box, '');
198 | shortcuts.className = 'calendar-shortcuts';
199 | quickElement('a', shortcuts, gettext('Yesterday'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', -1);');
200 | shortcuts.appendChild(document.createTextNode('\240|\240'));
201 | quickElement('a', shortcuts, gettext('Today'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
202 | shortcuts.appendChild(document.createTextNode('\240|\240'));
203 | quickElement('a', shortcuts, gettext('Tomorrow'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', +1);');
204 |
205 | // cancel bar
206 | var cancel_p = quickElement('p', cal_box, '');
207 | cancel_p.className = 'calendar-cancel';
208 | quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
209 | django.jQuery(document).bind('keyup', function(event) {
210 | if (event.which == 27) {
211 | // ESC key closes popup
212 | DateTimeShortcuts.dismissCalendar(num);
213 | event.preventDefault();
214 | }
215 | });
216 | },
217 | openCalendar: function(num) {
218 | var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
219 | var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
220 | var inp = DateTimeShortcuts.calendarInputs[num];
221 |
222 | // Determine if the current value in the input has a valid date.
223 | // If so, draw the calendar with that date's year and month.
224 | if (inp.value) {
225 | var date_parts = inp.value.split('-');
226 | var year = date_parts[0];
227 | var month = parseFloat(date_parts[1]);
228 | if (year.match(/\d\d\d\d/) && month >= 1 && month <= 12) {
229 | DateTimeShortcuts.calendars[num].drawDate(month, year);
230 | }
231 | }
232 |
233 | // Recalculate the clockbox position
234 | // is it left-to-right or right-to-left layout ?
235 | if (getStyle(document.body,'direction')!='rtl') {
236 | cal_box.style.left = findPosX(cal_link) + 17 + 'px';
237 | }
238 | else {
239 | // since style's width is in em, it'd be tough to calculate
240 | // px value of it. let's use an estimated px for now
241 | // TODO: IE returns wrong value for findPosX when in rtl mode
242 | // (it returns as it was left aligned), needs to be fixed.
243 | cal_box.style.left = findPosX(cal_link) - 180 + 'px';
244 | }
245 | cal_box.style.top = Math.max(0, findPosY(cal_link) - 75) + 'px';
246 |
247 | cal_box.style.display = 'block';
248 | addEvent(document, 'click', DateTimeShortcuts.dismissCalendarFunc[num]);
249 | },
250 | dismissCalendar: function(num) {
251 | document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'none';
252 | removeEvent(document, 'click', DateTimeShortcuts.dismissCalendarFunc[num]);
253 | },
254 | drawPrev: function(num) {
255 | DateTimeShortcuts.calendars[num].drawPreviousMonth();
256 | },
257 | drawNext: function(num) {
258 | DateTimeShortcuts.calendars[num].drawNextMonth();
259 | },
260 | handleCalendarCallback: function(num) {
261 | format = get_format('DATE_INPUT_FORMATS')[0];
262 | // the format needs to be escaped a little
263 | format = format.replace('\\', '\\\\');
264 | format = format.replace('\r', '\\r');
265 | format = format.replace('\n', '\\n');
266 | format = format.replace('\t', '\\t');
267 | format = format.replace("'", "\\'");
268 | return ["function(y, m, d) { DateTimeShortcuts.calendarInputs[",
269 | num,
270 | "].value = new Date(y, m-1, d).strftime('",
271 | format,
272 | "');DateTimeShortcuts.calendarInputs[",
273 | num,
274 | "].focus();document.getElementById(DateTimeShortcuts.calendarDivName1+",
275 | num,
276 | ").style.display='none';}"].join('');
277 | },
278 | handleCalendarQuickLink: function(num, offset) {
279 | var d = new Date();
280 | d.setDate(d.getDate() + offset)
281 | DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]);
282 | DateTimeShortcuts.calendarInputs[num].focus();
283 | DateTimeShortcuts.dismissCalendar(num);
284 | }
285 | }
286 |
287 | addEvent(window, 'load', DateTimeShortcuts.init);
288 |
--------------------------------------------------------------------------------
/static/css/nv.d3.css:
--------------------------------------------------------------------------------
1 |
2 | /********************
3 | * HTML CSS
4 | */
5 |
6 |
7 | .chartWrap {
8 | margin: 0;
9 | padding: 0;
10 | overflow: hidden;
11 | }
12 |
13 | /********************
14 | Box shadow and border radius styling
15 | */
16 | .nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip {
17 | -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
18 | -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
19 | box-shadow: 0 5px 10px rgba(0,0,0,.2);
20 |
21 | -webkit-border-radius: 6px;
22 | -moz-border-radius: 6px;
23 | border-radius: 6px;
24 | }
25 |
26 | /********************
27 | * TOOLTIP CSS
28 | */
29 |
30 | .nvtooltip {
31 | position: absolute;
32 | background-color: rgba(255,255,255,1.0);
33 | padding: 1px;
34 | border: 1px solid rgba(0,0,0,.2);
35 | z-index: 10000;
36 |
37 | font-family: Arial;
38 | font-size: 13px;
39 | text-align: left;
40 | pointer-events: none;
41 |
42 | white-space: nowrap;
43 |
44 | -webkit-touch-callout: none;
45 | -webkit-user-select: none;
46 | -khtml-user-select: none;
47 | -moz-user-select: none;
48 | -ms-user-select: none;
49 | user-select: none;
50 | }
51 |
52 | /*Give tooltips that old fade in transition by
53 | putting a "with-transitions" class on the container div.
54 | */
55 | .nvtooltip.with-transitions, .with-transitions .nvtooltip {
56 | transition: opacity 250ms linear;
57 | -moz-transition: opacity 250ms linear;
58 | -webkit-transition: opacity 250ms linear;
59 |
60 | transition-delay: 250ms;
61 | -moz-transition-delay: 250ms;
62 | -webkit-transition-delay: 250ms;
63 | }
64 |
65 | .nvtooltip.x-nvtooltip,
66 | .nvtooltip.y-nvtooltip {
67 | padding: 8px;
68 | }
69 |
70 | .nvtooltip h3 {
71 | margin: 0;
72 | padding: 4px 14px;
73 | line-height: 18px;
74 | font-weight: normal;
75 | background-color: rgba(247,247,247,0.75);
76 | text-align: center;
77 |
78 | border-bottom: 1px solid #ebebeb;
79 |
80 | -webkit-border-radius: 5px 5px 0 0;
81 | -moz-border-radius: 5px 5px 0 0;
82 | border-radius: 5px 5px 0 0;
83 | }
84 |
85 | .nvtooltip p {
86 | margin: 0;
87 | padding: 5px 14px;
88 | text-align: center;
89 | }
90 |
91 | .nvtooltip span {
92 | display: inline-block;
93 | margin: 2px 0;
94 | }
95 |
96 | .nvtooltip table {
97 | margin: 6px;
98 | border-spacing:0;
99 | }
100 |
101 |
102 | .nvtooltip table td {
103 | padding: 2px 9px 2px 0;
104 | vertical-align: middle;
105 | }
106 |
107 | .nvtooltip table td.key {
108 | font-weight:normal;
109 | }
110 | .nvtooltip table td.value {
111 | text-align: right;
112 | font-weight: bold;
113 | }
114 |
115 | .nvtooltip table tr.highlight td {
116 | padding: 1px 9px 1px 0;
117 | border-bottom-style: solid;
118 | border-bottom-width: 1px;
119 | border-top-style: solid;
120 | border-top-width: 1px;
121 | }
122 |
123 | .nvtooltip table td.legend-color-guide div {
124 | width: 8px;
125 | height: 8px;
126 | vertical-align: middle;
127 | }
128 |
129 | .nvtooltip .footer {
130 | padding: 3px;
131 | text-align: center;
132 | }
133 |
134 |
135 | .nvtooltip-pending-removal {
136 | position: absolute;
137 | pointer-events: none;
138 | }
139 |
140 |
141 | /********************
142 | * SVG CSS
143 | */
144 |
145 |
146 | svg {
147 | -webkit-touch-callout: none;
148 | -webkit-user-select: none;
149 | -khtml-user-select: none;
150 | -moz-user-select: none;
151 | -ms-user-select: none;
152 | user-select: none;
153 | /* Trying to get SVG to act like a greedy block in all browsers */
154 | display: block;
155 | width:100%;
156 | height:100%;
157 | }
158 |
159 |
160 | svg text {
161 | font: normal 12px Arial;
162 | }
163 |
164 | svg .title {
165 | font: bold 14px Arial;
166 | }
167 |
168 | .nvd3 .nv-background {
169 | fill: white;
170 | fill-opacity: 0;
171 | /*
172 | pointer-events: none;
173 | */
174 | }
175 |
176 | .nvd3.nv-noData {
177 | font-size: 18px;
178 | font-weight: bold;
179 | }
180 |
181 |
182 | /**********
183 | * Brush
184 | */
185 |
186 | .nv-brush .extent {
187 | fill-opacity: .125;
188 | shape-rendering: crispEdges;
189 | }
190 |
191 |
192 |
193 | /**********
194 | * Legend
195 | */
196 |
197 | .nvd3 .nv-legend .nv-series {
198 | cursor: pointer;
199 | }
200 |
201 | .nvd3 .nv-legend .disabled circle {
202 | fill-opacity: 0;
203 | }
204 |
205 |
206 |
207 | /**********
208 | * Axes
209 | */
210 | .nvd3 .nv-axis {
211 | pointer-events:none;
212 | }
213 |
214 | .nvd3 .nv-axis path {
215 | fill: none;
216 | stroke: #000;
217 | stroke-opacity: .75;
218 | shape-rendering: crispEdges;
219 | }
220 |
221 | .nvd3 .nv-axis path.domain {
222 | stroke-opacity: .75;
223 | }
224 |
225 | .nvd3 .nv-axis.nv-x path.domain {
226 | stroke-opacity: 0;
227 | }
228 |
229 | .nvd3 .nv-axis line {
230 | fill: none;
231 | stroke: #e5e5e5;
232 | shape-rendering: crispEdges;
233 | }
234 |
235 | .nvd3 .nv-axis .zero line,
236 | /*this selector may not be necessary*/ .nvd3 .nv-axis line.zero {
237 | stroke-opacity: .75;
238 | }
239 |
240 | .nvd3 .nv-axis .nv-axisMaxMin text {
241 | font-weight: bold;
242 | }
243 |
244 | .nvd3 .x .nv-axis .nv-axisMaxMin text,
245 | .nvd3 .x2 .nv-axis .nv-axisMaxMin text,
246 | .nvd3 .x3 .nv-axis .nv-axisMaxMin text {
247 | text-anchor: middle
248 | }
249 |
250 |
251 |
252 | /**********
253 | * Brush
254 | */
255 |
256 | .nv-brush .resize path {
257 | fill: #eee;
258 | stroke: #666;
259 | }
260 |
261 |
262 |
263 | /**********
264 | * Bars
265 | */
266 |
267 | .nvd3 .nv-bars .negative rect {
268 | zfill: brown;
269 | }
270 |
271 | .nvd3 .nv-bars rect {
272 | zfill: steelblue;
273 | fill-opacity: .75;
274 |
275 | transition: fill-opacity 250ms linear;
276 | -moz-transition: fill-opacity 250ms linear;
277 | -webkit-transition: fill-opacity 250ms linear;
278 | }
279 |
280 | .nvd3 .nv-bars rect.hover {
281 | fill-opacity: 1;
282 | }
283 |
284 | .nvd3 .nv-bars .hover rect {
285 | fill: lightblue;
286 | }
287 |
288 | .nvd3 .nv-bars text {
289 | fill: rgba(0,0,0,0);
290 | }
291 |
292 | .nvd3 .nv-bars .hover text {
293 | fill: rgba(0,0,0,1);
294 | }
295 |
296 |
297 | /**********
298 | * Bars
299 | */
300 |
301 | .nvd3 .nv-multibar .nv-groups rect,
302 | .nvd3 .nv-multibarHorizontal .nv-groups rect,
303 | .nvd3 .nv-discretebar .nv-groups rect {
304 | stroke-opacity: 0;
305 |
306 | transition: fill-opacity 250ms linear;
307 | -moz-transition: fill-opacity 250ms linear;
308 | -webkit-transition: fill-opacity 250ms linear;
309 | }
310 |
311 | .nvd3 .nv-multibar .nv-groups rect:hover,
312 | .nvd3 .nv-multibarHorizontal .nv-groups rect:hover,
313 | .nvd3 .nv-discretebar .nv-groups rect:hover {
314 | fill-opacity: 1;
315 | }
316 |
317 | .nvd3 .nv-discretebar .nv-groups text,
318 | .nvd3 .nv-multibarHorizontal .nv-groups text {
319 | font-weight: bold;
320 | fill: rgba(0,0,0,1);
321 | stroke: rgba(0,0,0,0);
322 | }
323 |
324 | /***********
325 | * Pie Chart
326 | */
327 |
328 | .nvd3.nv-pie path {
329 | stroke-opacity: 0;
330 | transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
331 | -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
332 | -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
333 |
334 | }
335 |
336 | .nvd3.nv-pie .nv-slice text {
337 | stroke: #000;
338 | stroke-width: 0;
339 | }
340 |
341 | .nvd3.nv-pie path {
342 | stroke: #fff;
343 | stroke-width: 1px;
344 | stroke-opacity: 1;
345 | }
346 |
347 | .nvd3.nv-pie .hover path {
348 | fill-opacity: .7;
349 | }
350 | .nvd3.nv-pie .nv-label {
351 | pointer-events: none;
352 | }
353 | .nvd3.nv-pie .nv-label rect {
354 | fill-opacity: 0;
355 | stroke-opacity: 0;
356 | }
357 |
358 | /**********
359 | * Lines
360 | */
361 |
362 | .nvd3 .nv-groups path.nv-line {
363 | fill: none;
364 | stroke-width: 1.5px;
365 | /*
366 | stroke-linecap: round;
367 | shape-rendering: geometricPrecision;
368 |
369 | transition: stroke-width 250ms linear;
370 | -moz-transition: stroke-width 250ms linear;
371 | -webkit-transition: stroke-width 250ms linear;
372 |
373 | transition-delay: 250ms
374 | -moz-transition-delay: 250ms;
375 | -webkit-transition-delay: 250ms;
376 | */
377 | }
378 |
379 | .nvd3 .nv-groups path.nv-line.nv-thin-line {
380 | stroke-width: 1px;
381 | }
382 |
383 |
384 | .nvd3 .nv-groups path.nv-area {
385 | stroke: none;
386 | /*
387 | stroke-linecap: round;
388 | shape-rendering: geometricPrecision;
389 |
390 | stroke-width: 2.5px;
391 | transition: stroke-width 250ms linear;
392 | -moz-transition: stroke-width 250ms linear;
393 | -webkit-transition: stroke-width 250ms linear;
394 |
395 | transition-delay: 250ms
396 | -moz-transition-delay: 250ms;
397 | -webkit-transition-delay: 250ms;
398 | */
399 | }
400 |
401 | .nvd3 .nv-line.hover path {
402 | stroke-width: 6px;
403 | }
404 |
405 | /*
406 | .nvd3.scatter .groups .point {
407 | fill-opacity: 0.1;
408 | stroke-opacity: 0.1;
409 | }
410 | */
411 |
412 | .nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point {
413 | fill-opacity: 0;
414 | stroke-opacity: 0;
415 | }
416 |
417 | .nvd3.nv-scatter.nv-single-point .nv-groups .nv-point {
418 | fill-opacity: .5 !important;
419 | stroke-opacity: .5 !important;
420 | }
421 |
422 |
423 | .with-transitions .nvd3 .nv-groups .nv-point {
424 | transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
425 | -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
426 | -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
427 |
428 | }
429 |
430 | .nvd3.nv-scatter .nv-groups .nv-point.hover,
431 | .nvd3 .nv-groups .nv-point.hover {
432 | stroke-width: 7px;
433 | fill-opacity: .95 !important;
434 | stroke-opacity: .95 !important;
435 | }
436 |
437 |
438 | .nvd3 .nv-point-paths path {
439 | stroke: #aaa;
440 | stroke-opacity: 0;
441 | fill: #eee;
442 | fill-opacity: 0;
443 | }
444 |
445 |
446 |
447 | .nvd3 .nv-indexLine {
448 | cursor: ew-resize;
449 | }
450 |
451 |
452 | /**********
453 | * Distribution
454 | */
455 |
456 | .nvd3 .nv-distribution {
457 | pointer-events: none;
458 | }
459 |
460 |
461 |
462 | /**********
463 | * Scatter
464 | */
465 |
466 | /* **Attempting to remove this for useVoronoi(false), need to see if it's required anywhere
467 | .nvd3 .nv-groups .nv-point {
468 | pointer-events: none;
469 | }
470 | */
471 |
472 | .nvd3 .nv-groups .nv-point.hover {
473 | stroke-width: 20px;
474 | stroke-opacity: .5;
475 | }
476 |
477 | .nvd3 .nv-scatter .nv-point.hover {
478 | fill-opacity: 1;
479 | }
480 |
481 | /*
482 | .nv-group.hover .nv-point {
483 | fill-opacity: 1;
484 | }
485 | */
486 |
487 |
488 | /**********
489 | * Stacked Area
490 | */
491 |
492 | .nvd3.nv-stackedarea path.nv-area {
493 | fill-opacity: .7;
494 | /*
495 | stroke-opacity: .65;
496 | fill-opacity: 1;
497 | */
498 | stroke-opacity: 0;
499 |
500 | transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
501 | -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
502 | -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
503 |
504 | /*
505 | transition-delay: 500ms;
506 | -moz-transition-delay: 500ms;
507 | -webkit-transition-delay: 500ms;
508 | */
509 |
510 | }
511 |
512 | .nvd3.nv-stackedarea path.nv-area.hover {
513 | fill-opacity: .9;
514 | /*
515 | stroke-opacity: .85;
516 | */
517 | }
518 | /*
519 | .d3stackedarea .groups path {
520 | stroke-opacity: 0;
521 | }
522 | */
523 |
524 |
525 |
526 | .nvd3.nv-stackedarea .nv-groups .nv-point {
527 | stroke-opacity: 0;
528 | fill-opacity: 0;
529 | }
530 |
531 | /*
532 | .nvd3.nv-stackedarea .nv-groups .nv-point.hover {
533 | stroke-width: 20px;
534 | stroke-opacity: .75;
535 | fill-opacity: 1;
536 | }*/
537 |
538 |
539 |
540 | /**********
541 | * Line Plus Bar
542 | */
543 |
544 | .nvd3.nv-linePlusBar .nv-bar rect {
545 | fill-opacity: .75;
546 | }
547 |
548 | .nvd3.nv-linePlusBar .nv-bar rect:hover {
549 | fill-opacity: 1;
550 | }
551 |
552 |
553 | /**********
554 | * Bullet
555 | */
556 |
557 | .nvd3.nv-bullet { font: 10px sans-serif; }
558 | .nvd3.nv-bullet .nv-measure { fill-opacity: .8; }
559 | .nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; }
560 | .nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; }
561 | .nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; }
562 | .nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; }
563 | .nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; }
564 | .nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; }
565 | .nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; }
566 | .nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; }
567 | .nvd3.nv-bullet .nv-subtitle { fill: #999; }
568 |
569 |
570 | .nvd3.nv-bullet .nv-range {
571 | fill: #bababa;
572 | fill-opacity: .4;
573 | }
574 | .nvd3.nv-bullet .nv-range:hover {
575 | fill-opacity: .7;
576 | }
577 |
578 |
579 |
580 | /**********
581 | * Sparkline
582 | */
583 |
584 | .nvd3.nv-sparkline path {
585 | fill: none;
586 | }
587 |
588 | .nvd3.nv-sparklineplus g.nv-hoverValue {
589 | pointer-events: none;
590 | }
591 |
592 | .nvd3.nv-sparklineplus .nv-hoverValue line {
593 | stroke: #333;
594 | stroke-width: 1.5px;
595 | }
596 |
597 | .nvd3.nv-sparklineplus,
598 | .nvd3.nv-sparklineplus g {
599 | pointer-events: all;
600 | }
601 |
602 | .nvd3 .nv-hoverArea {
603 | fill-opacity: 0;
604 | stroke-opacity: 0;
605 | }
606 |
607 | .nvd3.nv-sparklineplus .nv-xValue,
608 | .nvd3.nv-sparklineplus .nv-yValue {
609 | /*
610 | stroke: #666;
611 | */
612 | stroke-width: 0;
613 | font-size: .9em;
614 | font-weight: normal;
615 | }
616 |
617 | .nvd3.nv-sparklineplus .nv-yValue {
618 | stroke: #f66;
619 | }
620 |
621 | .nvd3.nv-sparklineplus .nv-maxValue {
622 | stroke: #2ca02c;
623 | fill: #2ca02c;
624 | }
625 |
626 | .nvd3.nv-sparklineplus .nv-minValue {
627 | stroke: #d62728;
628 | fill: #d62728;
629 | }
630 |
631 | .nvd3.nv-sparklineplus .nv-currentValue {
632 | /*
633 | stroke: #444;
634 | fill: #000;
635 | */
636 | font-weight: bold;
637 | font-size: 1.1em;
638 | }
639 |
640 | /**********
641 | * historical stock
642 | */
643 |
644 | .nvd3.nv-ohlcBar .nv-ticks .nv-tick {
645 | stroke-width: 2px;
646 | }
647 |
648 | .nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover {
649 | stroke-width: 4px;
650 | }
651 |
652 | .nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive {
653 | stroke: #2ca02c;
654 | }
655 |
656 | .nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative {
657 | stroke: #d62728;
658 | }
659 |
660 | .nvd3.nv-historicalStockChart .nv-axis .nv-axislabel {
661 | font-weight: bold;
662 | }
663 |
664 | .nvd3.nv-historicalStockChart .nv-dragTarget {
665 | fill-opacity: 0;
666 | stroke: none;
667 | cursor: move;
668 | }
669 |
670 | .nvd3 .nv-brush .extent {
671 | /*
672 | cursor: ew-resize !important;
673 | */
674 | fill-opacity: 0 !important;
675 | }
676 |
677 | .nvd3 .nv-brushBackground rect {
678 | stroke: #000;
679 | stroke-width: .4;
680 | fill: #fff;
681 | fill-opacity: .7;
682 | }
683 |
684 |
685 |
686 | /**********
687 | * Indented Tree
688 | */
689 |
690 |
691 | /**
692 | * TODO: the following 3 selectors are based on classes used in the example. I should either make them standard and leave them here, or move to a CSS file not included in the library
693 | */
694 | .nvd3.nv-indentedtree .name {
695 | margin-left: 5px;
696 | }
697 |
698 | .nvd3.nv-indentedtree .clickable {
699 | color: #08C;
700 | cursor: pointer;
701 | }
702 |
703 | .nvd3.nv-indentedtree span.clickable:hover {
704 | color: #005580;
705 | text-decoration: underline;
706 | }
707 |
708 |
709 | .nvd3.nv-indentedtree .nv-childrenCount {
710 | display: inline-block;
711 | margin-left: 5px;
712 | }
713 |
714 | .nvd3.nv-indentedtree .nv-treeicon {
715 | cursor: pointer;
716 | /*
717 | cursor: n-resize;
718 | */
719 | }
720 |
721 | .nvd3.nv-indentedtree .nv-treeicon.nv-folded {
722 | cursor: pointer;
723 | /*
724 | cursor: s-resize;
725 | */
726 | }
727 |
728 | /**********
729 | * Parallel Coordinates
730 | */
731 |
732 | .nvd3 .background path {
733 | fill: none;
734 | stroke: #ccc;
735 | stroke-opacity: .4;
736 | shape-rendering: crispEdges;
737 | }
738 |
739 | .nvd3 .foreground path {
740 | fill: none;
741 | stroke: steelblue;
742 | stroke-opacity: .7;
743 | }
744 |
745 | .nvd3 .brush .extent {
746 | fill-opacity: .3;
747 | stroke: #fff;
748 | shape-rendering: crispEdges;
749 | }
750 |
751 | .nvd3 .axis line, .axis path {
752 | fill: none;
753 | stroke: #000;
754 | shape-rendering: crispEdges;
755 | }
756 |
757 | .nvd3 .axis text {
758 | text-shadow: 0 1px 0 #fff;
759 | }
760 |
761 | /****
762 | Interactive Layer
763 | */
764 | .nvd3 .nv-interactiveGuideLine {
765 | pointer-events:none;
766 | }
767 | .nvd3 line.nv-guideline {
768 | stroke: #ccc;
769 | }
--------------------------------------------------------------------------------
/acra/static/css/nv.d3.css:
--------------------------------------------------------------------------------
1 |
2 | /********************
3 | * HTML CSS
4 | */
5 |
6 |
7 | .chartWrap {
8 | margin: 0;
9 | padding: 0;
10 | overflow: hidden;
11 | }
12 |
13 | /********************
14 | Box shadow and border radius styling
15 | */
16 | .nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip {
17 | -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
18 | -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
19 | box-shadow: 0 5px 10px rgba(0,0,0,.2);
20 |
21 | -webkit-border-radius: 6px;
22 | -moz-border-radius: 6px;
23 | border-radius: 6px;
24 | }
25 |
26 | /********************
27 | * TOOLTIP CSS
28 | */
29 |
30 | .nvtooltip {
31 | position: absolute;
32 | background-color: rgba(255,255,255,1.0);
33 | padding: 1px;
34 | border: 1px solid rgba(0,0,0,.2);
35 | z-index: 10000;
36 |
37 | font-family: Arial;
38 | font-size: 13px;
39 | text-align: left;
40 | pointer-events: none;
41 |
42 | white-space: nowrap;
43 |
44 | -webkit-touch-callout: none;
45 | -webkit-user-select: none;
46 | -khtml-user-select: none;
47 | -moz-user-select: none;
48 | -ms-user-select: none;
49 | user-select: none;
50 | }
51 |
52 | /*Give tooltips that old fade in transition by
53 | putting a "with-transitions" class on the container div.
54 | */
55 | .nvtooltip.with-transitions, .with-transitions .nvtooltip {
56 | transition: opacity 250ms linear;
57 | -moz-transition: opacity 250ms linear;
58 | -webkit-transition: opacity 250ms linear;
59 |
60 | transition-delay: 250ms;
61 | -moz-transition-delay: 250ms;
62 | -webkit-transition-delay: 250ms;
63 | }
64 |
65 | .nvtooltip.x-nvtooltip,
66 | .nvtooltip.y-nvtooltip {
67 | padding: 8px;
68 | }
69 |
70 | .nvtooltip h3 {
71 | margin: 0;
72 | padding: 4px 14px;
73 | line-height: 18px;
74 | font-weight: normal;
75 | background-color: rgba(247,247,247,0.75);
76 | text-align: center;
77 |
78 | border-bottom: 1px solid #ebebeb;
79 |
80 | -webkit-border-radius: 5px 5px 0 0;
81 | -moz-border-radius: 5px 5px 0 0;
82 | border-radius: 5px 5px 0 0;
83 | }
84 |
85 | .nvtooltip p {
86 | margin: 0;
87 | padding: 5px 14px;
88 | text-align: center;
89 | }
90 |
91 | .nvtooltip span {
92 | display: inline-block;
93 | margin: 2px 0;
94 | }
95 |
96 | .nvtooltip table {
97 | margin: 6px;
98 | border-spacing:0;
99 | }
100 |
101 |
102 | .nvtooltip table td {
103 | padding: 2px 9px 2px 0;
104 | vertical-align: middle;
105 | }
106 |
107 | .nvtooltip table td.key {
108 | font-weight:normal;
109 | }
110 | .nvtooltip table td.value {
111 | text-align: right;
112 | font-weight: bold;
113 | }
114 |
115 | .nvtooltip table tr.highlight td {
116 | padding: 1px 9px 1px 0;
117 | border-bottom-style: solid;
118 | border-bottom-width: 1px;
119 | border-top-style: solid;
120 | border-top-width: 1px;
121 | }
122 |
123 | .nvtooltip table td.legend-color-guide div {
124 | width: 8px;
125 | height: 8px;
126 | vertical-align: middle;
127 | }
128 |
129 | .nvtooltip .footer {
130 | padding: 3px;
131 | text-align: center;
132 | }
133 |
134 |
135 | .nvtooltip-pending-removal {
136 | position: absolute;
137 | pointer-events: none;
138 | }
139 |
140 |
141 | /********************
142 | * SVG CSS
143 | */
144 |
145 |
146 | svg {
147 | -webkit-touch-callout: none;
148 | -webkit-user-select: none;
149 | -khtml-user-select: none;
150 | -moz-user-select: none;
151 | -ms-user-select: none;
152 | user-select: none;
153 | /* Trying to get SVG to act like a greedy block in all browsers */
154 | display: block;
155 | width:100%;
156 | height:100%;
157 | }
158 |
159 |
160 | svg text {
161 | font: normal 12px Arial;
162 | }
163 |
164 | svg .title {
165 | font: bold 14px Arial;
166 | }
167 |
168 | .nvd3 .nv-background {
169 | fill: white;
170 | fill-opacity: 0;
171 | /*
172 | pointer-events: none;
173 | */
174 | }
175 |
176 | .nvd3.nv-noData {
177 | font-size: 18px;
178 | font-weight: bold;
179 | }
180 |
181 |
182 | /**********
183 | * Brush
184 | */
185 |
186 | .nv-brush .extent {
187 | fill-opacity: .125;
188 | shape-rendering: crispEdges;
189 | }
190 |
191 |
192 |
193 | /**********
194 | * Legend
195 | */
196 |
197 | .nvd3 .nv-legend .nv-series {
198 | cursor: pointer;
199 | }
200 |
201 | .nvd3 .nv-legend .disabled circle {
202 | fill-opacity: 0;
203 | }
204 |
205 |
206 |
207 | /**********
208 | * Axes
209 | */
210 | .nvd3 .nv-axis {
211 | pointer-events:none;
212 | }
213 |
214 | .nvd3 .nv-axis path {
215 | fill: none;
216 | stroke: #000;
217 | stroke-opacity: .75;
218 | shape-rendering: crispEdges;
219 | }
220 |
221 | .nvd3 .nv-axis path.domain {
222 | stroke-opacity: .75;
223 | }
224 |
225 | .nvd3 .nv-axis.nv-x path.domain {
226 | stroke-opacity: 0;
227 | }
228 |
229 | .nvd3 .nv-axis line {
230 | fill: none;
231 | stroke: #e5e5e5;
232 | shape-rendering: crispEdges;
233 | }
234 |
235 | .nvd3 .nv-axis .zero line,
236 | /*this selector may not be necessary*/ .nvd3 .nv-axis line.zero {
237 | stroke-opacity: .75;
238 | }
239 |
240 | .nvd3 .nv-axis .nv-axisMaxMin text {
241 | font-weight: bold;
242 | }
243 |
244 | .nvd3 .x .nv-axis .nv-axisMaxMin text,
245 | .nvd3 .x2 .nv-axis .nv-axisMaxMin text,
246 | .nvd3 .x3 .nv-axis .nv-axisMaxMin text {
247 | text-anchor: middle
248 | }
249 |
250 |
251 |
252 | /**********
253 | * Brush
254 | */
255 |
256 | .nv-brush .resize path {
257 | fill: #eee;
258 | stroke: #666;
259 | }
260 |
261 |
262 |
263 | /**********
264 | * Bars
265 | */
266 |
267 | .nvd3 .nv-bars .negative rect {
268 | zfill: brown;
269 | }
270 |
271 | .nvd3 .nv-bars rect {
272 | zfill: steelblue;
273 | fill-opacity: .75;
274 |
275 | transition: fill-opacity 250ms linear;
276 | -moz-transition: fill-opacity 250ms linear;
277 | -webkit-transition: fill-opacity 250ms linear;
278 | }
279 |
280 | .nvd3 .nv-bars rect.hover {
281 | fill-opacity: 1;
282 | }
283 |
284 | .nvd3 .nv-bars .hover rect {
285 | fill: lightblue;
286 | }
287 |
288 | .nvd3 .nv-bars text {
289 | fill: rgba(0,0,0,0);
290 | }
291 |
292 | .nvd3 .nv-bars .hover text {
293 | fill: rgba(0,0,0,1);
294 | }
295 |
296 |
297 | /**********
298 | * Bars
299 | */
300 |
301 | .nvd3 .nv-multibar .nv-groups rect,
302 | .nvd3 .nv-multibarHorizontal .nv-groups rect,
303 | .nvd3 .nv-discretebar .nv-groups rect {
304 | stroke-opacity: 0;
305 |
306 | transition: fill-opacity 250ms linear;
307 | -moz-transition: fill-opacity 250ms linear;
308 | -webkit-transition: fill-opacity 250ms linear;
309 | }
310 |
311 | .nvd3 .nv-multibar .nv-groups rect:hover,
312 | .nvd3 .nv-multibarHorizontal .nv-groups rect:hover,
313 | .nvd3 .nv-discretebar .nv-groups rect:hover {
314 | fill-opacity: 1;
315 | }
316 |
317 | .nvd3 .nv-discretebar .nv-groups text,
318 | .nvd3 .nv-multibarHorizontal .nv-groups text {
319 | font-weight: bold;
320 | fill: rgba(0,0,0,1);
321 | stroke: rgba(0,0,0,0);
322 | }
323 |
324 | /***********
325 | * Pie Chart
326 | */
327 |
328 | .nvd3.nv-pie path {
329 | stroke-opacity: 0;
330 | transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
331 | -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
332 | -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear;
333 |
334 | }
335 |
336 | .nvd3.nv-pie .nv-slice text {
337 | stroke: #000;
338 | stroke-width: 0;
339 | }
340 |
341 | .nvd3.nv-pie path {
342 | stroke: #fff;
343 | stroke-width: 1px;
344 | stroke-opacity: 1;
345 | }
346 |
347 | .nvd3.nv-pie .hover path {
348 | fill-opacity: .7;
349 | }
350 | .nvd3.nv-pie .nv-label {
351 | pointer-events: none;
352 | }
353 | .nvd3.nv-pie .nv-label rect {
354 | fill-opacity: 0;
355 | stroke-opacity: 0;
356 | }
357 |
358 | /**********
359 | * Lines
360 | */
361 |
362 | .nvd3 .nv-groups path.nv-line {
363 | fill: none;
364 | stroke-width: 1.5px;
365 | /*
366 | stroke-linecap: round;
367 | shape-rendering: geometricPrecision;
368 |
369 | transition: stroke-width 250ms linear;
370 | -moz-transition: stroke-width 250ms linear;
371 | -webkit-transition: stroke-width 250ms linear;
372 |
373 | transition-delay: 250ms
374 | -moz-transition-delay: 250ms;
375 | -webkit-transition-delay: 250ms;
376 | */
377 | }
378 |
379 | .nvd3 .nv-groups path.nv-line.nv-thin-line {
380 | stroke-width: 1px;
381 | }
382 |
383 |
384 | .nvd3 .nv-groups path.nv-area {
385 | stroke: none;
386 | /*
387 | stroke-linecap: round;
388 | shape-rendering: geometricPrecision;
389 |
390 | stroke-width: 2.5px;
391 | transition: stroke-width 250ms linear;
392 | -moz-transition: stroke-width 250ms linear;
393 | -webkit-transition: stroke-width 250ms linear;
394 |
395 | transition-delay: 250ms
396 | -moz-transition-delay: 250ms;
397 | -webkit-transition-delay: 250ms;
398 | */
399 | }
400 |
401 | .nvd3 .nv-line.hover path {
402 | stroke-width: 6px;
403 | }
404 |
405 | /*
406 | .nvd3.scatter .groups .point {
407 | fill-opacity: 0.1;
408 | stroke-opacity: 0.1;
409 | }
410 | */
411 |
412 | .nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point {
413 | fill-opacity: 0;
414 | stroke-opacity: 0;
415 | }
416 |
417 | .nvd3.nv-scatter.nv-single-point .nv-groups .nv-point {
418 | fill-opacity: .5 !important;
419 | stroke-opacity: .5 !important;
420 | }
421 |
422 |
423 | .with-transitions .nvd3 .nv-groups .nv-point {
424 | transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
425 | -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
426 | -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear;
427 |
428 | }
429 |
430 | .nvd3.nv-scatter .nv-groups .nv-point.hover,
431 | .nvd3 .nv-groups .nv-point.hover {
432 | stroke-width: 7px;
433 | fill-opacity: .95 !important;
434 | stroke-opacity: .95 !important;
435 | }
436 |
437 |
438 | .nvd3 .nv-point-paths path {
439 | stroke: #aaa;
440 | stroke-opacity: 0;
441 | fill: #eee;
442 | fill-opacity: 0;
443 | }
444 |
445 |
446 |
447 | .nvd3 .nv-indexLine {
448 | cursor: ew-resize;
449 | }
450 |
451 |
452 | /**********
453 | * Distribution
454 | */
455 |
456 | .nvd3 .nv-distribution {
457 | pointer-events: none;
458 | }
459 |
460 |
461 |
462 | /**********
463 | * Scatter
464 | */
465 |
466 | /* **Attempting to remove this for useVoronoi(false), need to see if it's required anywhere
467 | .nvd3 .nv-groups .nv-point {
468 | pointer-events: none;
469 | }
470 | */
471 |
472 | .nvd3 .nv-groups .nv-point.hover {
473 | stroke-width: 20px;
474 | stroke-opacity: .5;
475 | }
476 |
477 | .nvd3 .nv-scatter .nv-point.hover {
478 | fill-opacity: 1;
479 | }
480 |
481 | /*
482 | .nv-group.hover .nv-point {
483 | fill-opacity: 1;
484 | }
485 | */
486 |
487 |
488 | /**********
489 | * Stacked Area
490 | */
491 |
492 | .nvd3.nv-stackedarea path.nv-area {
493 | fill-opacity: .7;
494 | /*
495 | stroke-opacity: .65;
496 | fill-opacity: 1;
497 | */
498 | stroke-opacity: 0;
499 |
500 | transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
501 | -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
502 | -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear;
503 |
504 | /*
505 | transition-delay: 500ms;
506 | -moz-transition-delay: 500ms;
507 | -webkit-transition-delay: 500ms;
508 | */
509 |
510 | }
511 |
512 | .nvd3.nv-stackedarea path.nv-area.hover {
513 | fill-opacity: .9;
514 | /*
515 | stroke-opacity: .85;
516 | */
517 | }
518 | /*
519 | .d3stackedarea .groups path {
520 | stroke-opacity: 0;
521 | }
522 | */
523 |
524 |
525 |
526 | .nvd3.nv-stackedarea .nv-groups .nv-point {
527 | stroke-opacity: 0;
528 | fill-opacity: 0;
529 | }
530 |
531 | /*
532 | .nvd3.nv-stackedarea .nv-groups .nv-point.hover {
533 | stroke-width: 20px;
534 | stroke-opacity: .75;
535 | fill-opacity: 1;
536 | }*/
537 |
538 |
539 |
540 | /**********
541 | * Line Plus Bar
542 | */
543 |
544 | .nvd3.nv-linePlusBar .nv-bar rect {
545 | fill-opacity: .75;
546 | }
547 |
548 | .nvd3.nv-linePlusBar .nv-bar rect:hover {
549 | fill-opacity: 1;
550 | }
551 |
552 |
553 | /**********
554 | * Bullet
555 | */
556 |
557 | .nvd3.nv-bullet { font: 10px sans-serif; }
558 | .nvd3.nv-bullet .nv-measure { fill-opacity: .8; }
559 | .nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; }
560 | .nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; }
561 | .nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; }
562 | .nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; }
563 | .nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; }
564 | .nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; }
565 | .nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; }
566 | .nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; }
567 | .nvd3.nv-bullet .nv-subtitle { fill: #999; }
568 |
569 |
570 | .nvd3.nv-bullet .nv-range {
571 | fill: #bababa;
572 | fill-opacity: .4;
573 | }
574 | .nvd3.nv-bullet .nv-range:hover {
575 | fill-opacity: .7;
576 | }
577 |
578 |
579 |
580 | /**********
581 | * Sparkline
582 | */
583 |
584 | .nvd3.nv-sparkline path {
585 | fill: none;
586 | }
587 |
588 | .nvd3.nv-sparklineplus g.nv-hoverValue {
589 | pointer-events: none;
590 | }
591 |
592 | .nvd3.nv-sparklineplus .nv-hoverValue line {
593 | stroke: #333;
594 | stroke-width: 1.5px;
595 | }
596 |
597 | .nvd3.nv-sparklineplus,
598 | .nvd3.nv-sparklineplus g {
599 | pointer-events: all;
600 | }
601 |
602 | .nvd3 .nv-hoverArea {
603 | fill-opacity: 0;
604 | stroke-opacity: 0;
605 | }
606 |
607 | .nvd3.nv-sparklineplus .nv-xValue,
608 | .nvd3.nv-sparklineplus .nv-yValue {
609 | /*
610 | stroke: #666;
611 | */
612 | stroke-width: 0;
613 | font-size: .9em;
614 | font-weight: normal;
615 | }
616 |
617 | .nvd3.nv-sparklineplus .nv-yValue {
618 | stroke: #f66;
619 | }
620 |
621 | .nvd3.nv-sparklineplus .nv-maxValue {
622 | stroke: #2ca02c;
623 | fill: #2ca02c;
624 | }
625 |
626 | .nvd3.nv-sparklineplus .nv-minValue {
627 | stroke: #d62728;
628 | fill: #d62728;
629 | }
630 |
631 | .nvd3.nv-sparklineplus .nv-currentValue {
632 | /*
633 | stroke: #444;
634 | fill: #000;
635 | */
636 | font-weight: bold;
637 | font-size: 1.1em;
638 | }
639 |
640 | /**********
641 | * historical stock
642 | */
643 |
644 | .nvd3.nv-ohlcBar .nv-ticks .nv-tick {
645 | stroke-width: 2px;
646 | }
647 |
648 | .nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover {
649 | stroke-width: 4px;
650 | }
651 |
652 | .nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive {
653 | stroke: #2ca02c;
654 | }
655 |
656 | .nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative {
657 | stroke: #d62728;
658 | }
659 |
660 | .nvd3.nv-historicalStockChart .nv-axis .nv-axislabel {
661 | font-weight: bold;
662 | }
663 |
664 | .nvd3.nv-historicalStockChart .nv-dragTarget {
665 | fill-opacity: 0;
666 | stroke: none;
667 | cursor: move;
668 | }
669 |
670 | .nvd3 .nv-brush .extent {
671 | /*
672 | cursor: ew-resize !important;
673 | */
674 | fill-opacity: 0 !important;
675 | }
676 |
677 | .nvd3 .nv-brushBackground rect {
678 | stroke: #000;
679 | stroke-width: .4;
680 | fill: #fff;
681 | fill-opacity: .7;
682 | }
683 |
684 |
685 |
686 | /**********
687 | * Indented Tree
688 | */
689 |
690 |
691 | /**
692 | * TODO: the following 3 selectors are based on classes used in the example. I should either make them standard and leave them here, or move to a CSS file not included in the library
693 | */
694 | .nvd3.nv-indentedtree .name {
695 | margin-left: 5px;
696 | }
697 |
698 | .nvd3.nv-indentedtree .clickable {
699 | color: #08C;
700 | cursor: pointer;
701 | }
702 |
703 | .nvd3.nv-indentedtree span.clickable:hover {
704 | color: #005580;
705 | text-decoration: underline;
706 | }
707 |
708 |
709 | .nvd3.nv-indentedtree .nv-childrenCount {
710 | display: inline-block;
711 | margin-left: 5px;
712 | }
713 |
714 | .nvd3.nv-indentedtree .nv-treeicon {
715 | cursor: pointer;
716 | /*
717 | cursor: n-resize;
718 | */
719 | }
720 |
721 | .nvd3.nv-indentedtree .nv-treeicon.nv-folded {
722 | cursor: pointer;
723 | /*
724 | cursor: s-resize;
725 | */
726 | }
727 |
728 | /**********
729 | * Parallel Coordinates
730 | */
731 |
732 | .nvd3 .background path {
733 | fill: none;
734 | stroke: #ccc;
735 | stroke-opacity: .4;
736 | shape-rendering: crispEdges;
737 | }
738 |
739 | .nvd3 .foreground path {
740 | fill: none;
741 | stroke: steelblue;
742 | stroke-opacity: .7;
743 | }
744 |
745 | .nvd3 .brush .extent {
746 | fill-opacity: .3;
747 | stroke: #fff;
748 | shape-rendering: crispEdges;
749 | }
750 |
751 | .nvd3 .axis line, .axis path {
752 | fill: none;
753 | stroke: #000;
754 | shape-rendering: crispEdges;
755 | }
756 |
757 | .nvd3 .axis text {
758 | text-shadow: 0 1px 0 #fff;
759 | }
760 |
761 | /****
762 | Interactive Layer
763 | */
764 | .nvd3 .nv-interactiveGuideLine {
765 | pointer-events:none;
766 | }
767 | .nvd3 line.nv-guideline {
768 | stroke: #ccc;
769 | }
--------------------------------------------------------------------------------
/static/admin/css/base.css:
--------------------------------------------------------------------------------
1 | /*
2 | DJANGO Admin styles
3 | */
4 |
5 | body {
6 | margin: 0;
7 | padding: 0;
8 | font-size: 12px;
9 | font-family: "Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif;
10 | color: #333;
11 | background: #fff;
12 | }
13 |
14 | /* LINKS */
15 |
16 | a:link, a:visited {
17 | color: #5b80b2;
18 | text-decoration: none;
19 | }
20 |
21 | a:hover {
22 | color: #036;
23 | }
24 |
25 | a img {
26 | border: none;
27 | }
28 |
29 | a.section:link, a.section:visited {
30 | color: white;
31 | text-decoration: none;
32 | }
33 |
34 | /* GLOBAL DEFAULTS */
35 |
36 | p, ol, ul, dl {
37 | margin: .2em 0 .8em 0;
38 | }
39 |
40 | p {
41 | padding: 0;
42 | line-height: 140%;
43 | }
44 |
45 | h1,h2,h3,h4,h5 {
46 | font-weight: bold;
47 | }
48 |
49 | h1 {
50 | font-size: 18px;
51 | color: #666;
52 | padding: 0 6px 0 0;
53 | margin: 0 0 .2em 0;
54 | }
55 |
56 | h2 {
57 | font-size: 16px;
58 | margin: 1em 0 .5em 0;
59 | }
60 |
61 | h2.subhead {
62 | font-weight: normal;
63 | margin-top: 0;
64 | }
65 |
66 | h3 {
67 | font-size: 14px;
68 | margin: .8em 0 .3em 0;
69 | color: #666;
70 | font-weight: bold;
71 | }
72 |
73 | h4 {
74 | font-size: 12px;
75 | margin: 1em 0 .8em 0;
76 | padding-bottom: 3px;
77 | }
78 |
79 | h5 {
80 | font-size: 10px;
81 | margin: 1.5em 0 .5em 0;
82 | color: #666;
83 | text-transform: uppercase;
84 | letter-spacing: 1px;
85 | }
86 |
87 | ul li {
88 | list-style-type: square;
89 | padding: 1px 0;
90 | }
91 |
92 | ul.plainlist {
93 | margin-left: 0 !important;
94 | }
95 |
96 | ul.plainlist li {
97 | list-style-type: none;
98 | }
99 |
100 | li ul {
101 | margin-bottom: 0;
102 | }
103 |
104 | li, dt, dd {
105 | font-size: 11px;
106 | line-height: 14px;
107 | }
108 |
109 | dt {
110 | font-weight: bold;
111 | margin-top: 4px;
112 | }
113 |
114 | dd {
115 | margin-left: 0;
116 | }
117 |
118 | form {
119 | margin: 0;
120 | padding: 0;
121 | }
122 |
123 | fieldset {
124 | margin: 0;
125 | padding: 0;
126 | }
127 |
128 | blockquote {
129 | font-size: 11px;
130 | color: #777;
131 | margin-left: 2px;
132 | padding-left: 10px;
133 | border-left: 5px solid #ddd;
134 | }
135 |
136 | code, pre {
137 | font-family: "Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace;
138 | background: inherit;
139 | color: #666;
140 | font-size: 11px;
141 | }
142 |
143 | pre.literal-block {
144 | margin: 10px;
145 | background: #eee;
146 | padding: 6px 8px;
147 | }
148 |
149 | code strong {
150 | color: #930;
151 | }
152 |
153 | hr {
154 | clear: both;
155 | color: #eee;
156 | background-color: #eee;
157 | height: 1px;
158 | border: none;
159 | margin: 0;
160 | padding: 0;
161 | font-size: 1px;
162 | line-height: 1px;
163 | }
164 |
165 | /* TEXT STYLES & MODIFIERS */
166 |
167 | .small {
168 | font-size: 11px;
169 | }
170 |
171 | .tiny {
172 | font-size: 10px;
173 | }
174 |
175 | p.tiny {
176 | margin-top: -2px;
177 | }
178 |
179 | .mini {
180 | font-size: 9px;
181 | }
182 |
183 | p.mini {
184 | margin-top: -3px;
185 | }
186 |
187 | .help, p.help {
188 | font-size: 10px !important;
189 | color: #999;
190 | }
191 |
192 | img.help-tooltip {
193 | cursor: help;
194 | }
195 |
196 | p img, h1 img, h2 img, h3 img, h4 img, td img {
197 | vertical-align: middle;
198 | }
199 |
200 | .quiet, a.quiet:link, a.quiet:visited {
201 | color: #999 !important;
202 | font-weight: normal !important;
203 | }
204 |
205 | .quiet strong {
206 | font-weight: bold !important;
207 | }
208 |
209 | .float-right {
210 | float: right;
211 | }
212 |
213 | .float-left {
214 | float: left;
215 | }
216 |
217 | .clear {
218 | clear: both;
219 | }
220 |
221 | .align-left {
222 | text-align: left;
223 | }
224 |
225 | .align-right {
226 | text-align: right;
227 | }
228 |
229 | .example {
230 | margin: 10px 0;
231 | padding: 5px 10px;
232 | background: #efefef;
233 | }
234 |
235 | .nowrap {
236 | white-space: nowrap;
237 | }
238 |
239 | /* TABLES */
240 |
241 | table {
242 | border-collapse: collapse;
243 | border-color: #ccc;
244 | }
245 |
246 | td, th {
247 | font-size: 11px;
248 | line-height: 13px;
249 | border-bottom: 1px solid #eee;
250 | vertical-align: top;
251 | padding: 5px;
252 | font-family: "Lucida Grande", Verdana, Arial, sans-serif;
253 | }
254 |
255 | th {
256 | text-align: left;
257 | font-size: 12px;
258 | font-weight: bold;
259 | }
260 |
261 | thead th,
262 | tfoot td {
263 | color: #666;
264 | padding: 2px 5px;
265 | font-size: 11px;
266 | background: #e1e1e1 url(../img/nav-bg.gif) top left repeat-x;
267 | border-left: 1px solid #ddd;
268 | border-bottom: 1px solid #ddd;
269 | }
270 |
271 | tfoot td {
272 | border-bottom: none;
273 | border-top: 1px solid #ddd;
274 | }
275 |
276 | thead th:first-child,
277 | tfoot td:first-child {
278 | border-left: none !important;
279 | }
280 |
281 | thead th.optional {
282 | font-weight: normal !important;
283 | }
284 |
285 | fieldset table {
286 | border-right: 1px solid #eee;
287 | }
288 |
289 | tr.row-label td {
290 | font-size: 9px;
291 | padding-top: 2px;
292 | padding-bottom: 0;
293 | border-bottom: none;
294 | color: #666;
295 | margin-top: -1px;
296 | }
297 |
298 | tr.alt {
299 | background: #f6f6f6;
300 | }
301 |
302 | .row1 {
303 | background: #EDF3FE;
304 | }
305 |
306 | .row2 {
307 | background: white;
308 | }
309 |
310 | /* SORTABLE TABLES */
311 |
312 | thead th {
313 | padding: 2px 5px;
314 | line-height: normal;
315 | }
316 |
317 | thead th a:link, thead th a:visited {
318 | color: #666;
319 | }
320 |
321 | thead th.sorted {
322 | background: #c5c5c5 url(../img/nav-bg-selected.gif) top left repeat-x;
323 | }
324 |
325 | thead th.sorted .text {
326 | padding-right: 42px;
327 | }
328 |
329 | table thead th .text span {
330 | padding: 2px 5px;
331 | display:block;
332 | }
333 |
334 | table thead th .text a {
335 | display: block;
336 | cursor: pointer;
337 | padding: 2px 5px;
338 | }
339 |
340 | table thead th.sortable:hover {
341 | background: white url(../img/nav-bg-reverse.gif) 0 -5px repeat-x;
342 | }
343 |
344 | thead th.sorted a.sortremove {
345 | visibility: hidden;
346 | }
347 |
348 | table thead th.sorted:hover a.sortremove {
349 | visibility: visible;
350 | }
351 |
352 | table thead th.sorted .sortoptions {
353 | display: block;
354 | padding: 4px 5px 0 5px;
355 | float: right;
356 | text-align: right;
357 | }
358 |
359 | table thead th.sorted .sortpriority {
360 | font-size: .8em;
361 | min-width: 12px;
362 | text-align: center;
363 | vertical-align: top;
364 | }
365 |
366 | table thead th.sorted .sortoptions a {
367 | width: 14px;
368 | height: 12px;
369 | display: inline-block;
370 | }
371 |
372 | table thead th.sorted .sortoptions a.sortremove {
373 | background: url(../img/sorting-icons.gif) -4px -5px no-repeat;
374 | }
375 |
376 | table thead th.sorted .sortoptions a.sortremove:hover {
377 | background: url(../img/sorting-icons.gif) -4px -27px no-repeat;
378 | }
379 |
380 | table thead th.sorted .sortoptions a.ascending {
381 | background: url(../img/sorting-icons.gif) -5px -50px no-repeat;
382 | }
383 |
384 | table thead th.sorted .sortoptions a.ascending:hover {
385 | background: url(../img/sorting-icons.gif) -5px -72px no-repeat;
386 | }
387 |
388 | table thead th.sorted .sortoptions a.descending {
389 | background: url(../img/sorting-icons.gif) -5px -94px no-repeat;
390 | }
391 |
392 | table thead th.sorted .sortoptions a.descending:hover {
393 | background: url(../img/sorting-icons.gif) -5px -115px no-repeat;
394 | }
395 |
396 | /* ORDERABLE TABLES */
397 |
398 | table.orderable tbody tr td:hover {
399 | cursor: move;
400 | }
401 |
402 | table.orderable tbody tr td:first-child {
403 | padding-left: 14px;
404 | background-image: url(../img/nav-bg-grabber.gif);
405 | background-repeat: repeat-y;
406 | }
407 |
408 | table.orderable-initalized .order-cell, body>tr>td.order-cell {
409 | display: none;
410 | }
411 |
412 | /* FORM DEFAULTS */
413 |
414 | input, textarea, select, .form-row p {
415 | margin: 2px 0;
416 | padding: 2px 3px;
417 | vertical-align: middle;
418 | font-family: "Lucida Grande", Verdana, Arial, sans-serif;
419 | font-weight: normal;
420 | font-size: 11px;
421 | }
422 |
423 | textarea {
424 | vertical-align: top !important;
425 | }
426 |
427 | input[type=text], input[type=password], input[type=email], input[type=url], input[type=number],
428 | textarea, select, .vTextField {
429 | border: 1px solid #ccc;
430 | }
431 |
432 | /* FORM BUTTONS */
433 |
434 | .button, input[type=submit], input[type=button], .submit-row input {
435 | background: white url(../img/nav-bg.gif) bottom repeat-x;
436 | padding: 3px 5px;
437 | color: black;
438 | border: 1px solid #bbb;
439 | border-color: #ddd #aaa #aaa #ddd;
440 | }
441 |
442 | .button:active, input[type=submit]:active, input[type=button]:active {
443 | background-image: url(../img/nav-bg-reverse.gif);
444 | background-position: top;
445 | }
446 |
447 | .button[disabled], input[type=submit][disabled], input[type=button][disabled] {
448 | background-image: url(../img/nav-bg.gif);
449 | background-position: bottom;
450 | opacity: 0.4;
451 | }
452 |
453 | .button.default, input[type=submit].default, .submit-row input.default {
454 | border: 2px solid #5b80b2;
455 | background: #7CA0C7 url(../img/default-bg.gif) bottom repeat-x;
456 | font-weight: bold;
457 | color: white;
458 | float: right;
459 | }
460 |
461 | .button.default:active, input[type=submit].default:active {
462 | background-image: url(../img/default-bg-reverse.gif);
463 | background-position: top;
464 | }
465 |
466 | .button[disabled].default, input[type=submit][disabled].default, input[type=button][disabled].default {
467 | background-image: url(../img/default-bg.gif);
468 | background-position: bottom;
469 | opacity: 0.4;
470 | }
471 |
472 |
473 | /* MODULES */
474 |
475 | .module {
476 | border: 1px solid #ccc;
477 | margin-bottom: 5px;
478 | background: white;
479 | }
480 |
481 | .module p, .module ul, .module h3, .module h4, .module dl, .module pre {
482 | padding-left: 10px;
483 | padding-right: 10px;
484 | }
485 |
486 | .module blockquote {
487 | margin-left: 12px;
488 | }
489 |
490 | .module ul, .module ol {
491 | margin-left: 1.5em;
492 | }
493 |
494 | .module h3 {
495 | margin-top: .6em;
496 | }
497 |
498 | .module h2, .module caption, .inline-group h2 {
499 | margin: 0;
500 | padding: 2px 5px 3px 5px;
501 | font-size: 11px;
502 | text-align: left;
503 | font-weight: bold;
504 | background: #7CA0C7 url(../img/default-bg.gif) top left repeat-x;
505 | color: white;
506 | }
507 |
508 | .module table {
509 | border-collapse: collapse;
510 | }
511 |
512 | /* MESSAGES & ERRORS */
513 |
514 | ul.messagelist {
515 | padding: 0 0 5px 0;
516 | margin: 0;
517 | }
518 |
519 | ul.messagelist li {
520 | font-size: 12px;
521 | display: block;
522 | padding: 4px 5px 4px 25px;
523 | margin: 0 0 3px 0;
524 | border-bottom: 1px solid #ddd;
525 | color: #666;
526 | background: #ffc url(../img/icon_success.gif) 5px .3em no-repeat;
527 | }
528 |
529 | ul.messagelist li.warning{
530 | background-image: url(../img/icon_alert.gif);
531 | }
532 |
533 | ul.messagelist li.error{
534 | background-image: url(../img/icon_error.gif);
535 | }
536 |
537 | .errornote {
538 | font-size: 12px !important;
539 | display: block;
540 | padding: 4px 5px 4px 25px;
541 | margin: 0 0 3px 0;
542 | border: 1px solid red;
543 | color: red;
544 | background: #ffc url(../img/icon_error.gif) 5px .3em no-repeat;
545 | }
546 |
547 | ul.errorlist {
548 | margin: 0 !important;
549 | padding: 0 !important;
550 | }
551 |
552 | .errorlist li {
553 | font-size: 12px !important;
554 | display: block;
555 | padding: 4px 5px 4px 25px;
556 | margin: 0 0 3px 0;
557 | border: 1px solid red;
558 | color: white;
559 | background: red url(../img/icon_alert.gif) 5px .3em no-repeat;
560 | }
561 |
562 | .errorlist li a {
563 | color: white;
564 | text-decoration: underline;
565 | }
566 |
567 | td ul.errorlist {
568 | margin: 0 !important;
569 | padding: 0 !important;
570 | }
571 |
572 | td ul.errorlist li {
573 | margin: 0 !important;
574 | }
575 |
576 | .errors {
577 | background: #ffc;
578 | }
579 |
580 | .errors input, .errors select, .errors textarea {
581 | border: 1px solid red;
582 | }
583 |
584 | div.system-message {
585 | background: #ffc;
586 | margin: 10px;
587 | padding: 6px 8px;
588 | font-size: .8em;
589 | }
590 |
591 | div.system-message p.system-message-title {
592 | padding: 4px 5px 4px 25px;
593 | margin: 0;
594 | color: red;
595 | background: #ffc url(../img/icon_error.gif) 5px .3em no-repeat;
596 | }
597 |
598 | .description {
599 | font-size: 12px;
600 | padding: 5px 0 0 12px;
601 | }
602 |
603 | /* BREADCRUMBS */
604 |
605 | div.breadcrumbs {
606 | background: white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x;
607 | padding: 2px 8px 3px 8px;
608 | font-size: 11px;
609 | color: #999;
610 | border-top: 1px solid white;
611 | border-bottom: 1px solid #ccc;
612 | text-align: left;
613 | }
614 |
615 | /* ACTION ICONS */
616 |
617 | .addlink {
618 | padding-left: 12px;
619 | background: url(../img/icon_addlink.gif) 0 .2em no-repeat;
620 | }
621 |
622 | .changelink {
623 | padding-left: 12px;
624 | background: url(../img/icon_changelink.gif) 0 .2em no-repeat;
625 | }
626 |
627 | .deletelink {
628 | padding-left: 12px;
629 | background: url(../img/icon_deletelink.gif) 0 .25em no-repeat;
630 | }
631 |
632 | a.deletelink:link, a.deletelink:visited {
633 | color: #CC3434;
634 | }
635 |
636 | a.deletelink:hover {
637 | color: #993333;
638 | }
639 |
640 | /* OBJECT TOOLS */
641 |
642 | .object-tools {
643 | font-size: 10px;
644 | font-weight: bold;
645 | font-family: Arial,Helvetica,sans-serif;
646 | padding-left: 0;
647 | float: right;
648 | position: relative;
649 | margin-top: -2.4em;
650 | margin-bottom: -2em;
651 | }
652 |
653 | .form-row .object-tools {
654 | margin-top: 5px;
655 | margin-bottom: 5px;
656 | float: none;
657 | height: 2em;
658 | padding-left: 3.5em;
659 | }
660 |
661 | .object-tools li {
662 | display: block;
663 | float: left;
664 | background: url(../img/tool-left.gif) 0 0 no-repeat;
665 | padding: 0 0 0 8px;
666 | margin-left: 2px;
667 | height: 16px;
668 | }
669 |
670 | .object-tools li:hover {
671 | background: url(../img/tool-left_over.gif) 0 0 no-repeat;
672 | }
673 |
674 | .object-tools a:link, .object-tools a:visited {
675 | display: block;
676 | float: left;
677 | color: white;
678 | padding: .1em 14px .1em 8px;
679 | height: 14px;
680 | background: #999 url(../img/tool-right.gif) 100% 0 no-repeat;
681 | }
682 |
683 | .object-tools a:hover, .object-tools li:hover a {
684 | background: #5b80b2 url(../img/tool-right_over.gif) 100% 0 no-repeat;
685 | }
686 |
687 | .object-tools a.viewsitelink, .object-tools a.golink {
688 | background: #999 url(../img/tooltag-arrowright.gif) top right no-repeat;
689 | padding-right: 28px;
690 | }
691 |
692 | .object-tools a.viewsitelink:hover, .object-tools a.golink:hover {
693 | background: #5b80b2 url(../img/tooltag-arrowright_over.gif) top right no-repeat;
694 | }
695 |
696 | .object-tools a.addlink {
697 | background: #999 url(../img/tooltag-add.gif) top right no-repeat;
698 | padding-right: 28px;
699 | }
700 |
701 | .object-tools a.addlink:hover {
702 | background: #5b80b2 url(../img/tooltag-add_over.gif) top right no-repeat;
703 | }
704 |
705 | /* OBJECT HISTORY */
706 |
707 | table#change-history {
708 | width: 100%;
709 | }
710 |
711 | table#change-history tbody th {
712 | width: 16em;
713 | }
714 |
715 | /* PAGE STRUCTURE */
716 |
717 | #container {
718 | position: relative;
719 | width: 100%;
720 | min-width: 760px;
721 | padding: 0;
722 | }
723 |
724 | #content {
725 | margin: 10px 15px;
726 | }
727 |
728 | #header {
729 | width: 100%;
730 | }
731 |
732 | #content-main {
733 | float: left;
734 | width: 100%;
735 | }
736 |
737 | #content-related {
738 | float: right;
739 | width: 18em;
740 | position: relative;
741 | margin-right: -19em;
742 | }
743 |
744 | #footer {
745 | clear: both;
746 | padding: 10px;
747 | }
748 |
749 | /* COLUMN TYPES */
750 |
751 | .colMS {
752 | margin-right: 20em !important;
753 | }
754 |
755 | .colSM {
756 | margin-left: 20em !important;
757 | }
758 |
759 | .colSM #content-related {
760 | float: left;
761 | margin-right: 0;
762 | margin-left: -19em;
763 | }
764 |
765 | .colSM #content-main {
766 | float: right;
767 | }
768 |
769 | .popup .colM {
770 | width: 95%;
771 | }
772 |
773 | .subcol {
774 | float: left;
775 | width: 46%;
776 | margin-right: 15px;
777 | }
778 |
779 | .dashboard #content {
780 | width: 500px;
781 | }
782 |
783 | /* HEADER */
784 |
785 | #header {
786 | background: #417690;
787 | color: #ffc;
788 | overflow: hidden;
789 | }
790 |
791 | #header a:link, #header a:visited {
792 | color: white;
793 | }
794 |
795 | #header a:hover {
796 | text-decoration: underline;
797 | }
798 |
799 | #branding h1 {
800 | padding: 0 10px;
801 | font-size: 18px;
802 | margin: 8px 0;
803 | font-weight: normal;
804 | color: #f4f379;
805 | }
806 |
807 | #branding h2 {
808 | padding: 0 10px;
809 | font-size: 14px;
810 | margin: -8px 0 8px 0;
811 | font-weight: normal;
812 | color: #ffc;
813 | }
814 |
815 | #user-tools {
816 | position: absolute;
817 | top: 0;
818 | right: 0;
819 | padding: 1.2em 10px;
820 | font-size: 11px;
821 | text-align: right;
822 | }
823 |
824 | /* SIDEBAR */
825 |
826 | #content-related h3 {
827 | font-size: 12px;
828 | color: #666;
829 | margin-bottom: 3px;
830 | }
831 |
832 | #content-related h4 {
833 | font-size: 11px;
834 | }
835 |
836 | #content-related .module h2 {
837 | background: #eee url(../img/nav-bg.gif) bottom left repeat-x;
838 | color: #666;
839 | }
840 |
841 |
--------------------------------------------------------------------------------
/static/js/lineWithFocusChart.js:
--------------------------------------------------------------------------------
1 | nv.models.lineWithFocusChart = function() {
2 | "use strict";
3 | //============================================================
4 | // Public Variables with Default Settings
5 | //------------------------------------------------------------
6 |
7 | var lines = nv.models.line()
8 | , lines2 = nv.models.line()
9 | , xAxis = nv.models.axis()
10 | , yAxis = nv.models.axis()
11 | , x2Axis = nv.models.axis()
12 | , y2Axis = nv.models.axis()
13 | , legend = nv.models.legend()
14 | , brush = d3.svg.brush()
15 | ;
16 |
17 | var margin = {top: 30, right: 30, bottom: 30, left: 60}
18 | , margin2 = {top: 0, right: 30, bottom: 20, left: 60}
19 | , color = nv.utils.defaultColor()
20 | , width = null
21 | , height = null
22 | , height2 = 100
23 | , x
24 | , y
25 | , x2
26 | , y2
27 | , showLegend = true
28 | , brushExtent = null
29 | , tooltips = true
30 | , tooltip = function(key, x, y, e, graph) {
31 | return '
' + key + ' ' +
32 | '
' + y + ' at ' + x + '
'
33 | }
34 | , noData = "No Data Available."
35 | , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush')
36 | , transitionDuration = 250
37 | ;
38 |
39 | lines
40 | .clipEdge(true)
41 | ;
42 | lines2
43 | .interactive(false)
44 | ;
45 | xAxis
46 | .orient('bottom')
47 | .tickPadding(5)
48 | ;
49 | yAxis
50 | .orient('left')
51 | ;
52 | x2Axis
53 | .orient('bottom')
54 | .tickPadding(5)
55 | ;
56 | y2Axis
57 | .orient('left')
58 | ;
59 | //============================================================
60 |
61 |
62 | //============================================================
63 | // Private Variables
64 | //------------------------------------------------------------
65 |
66 | var showTooltip = function(e, offsetElement) {
67 | var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
68 | top = e.pos[1] + ( offsetElement.offsetTop || 0),
69 | x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),
70 | y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)),
71 | content = tooltip(e.series.key, x, y, e, chart);
72 |
73 | nv.tooltip.show([left, top], content, null, null, offsetElement);
74 | };
75 |
76 | //============================================================
77 |
78 |
79 | function chart(selection) {
80 | selection.each(function(data) {
81 | var container = d3.select(this),
82 | that = this;
83 |
84 | var availableWidth = (width || parseInt(container.style('width')) || 960)
85 | - margin.left - margin.right,
86 | availableHeight1 = (height || parseInt(container.style('height')) || 400)
87 | - margin.top - margin.bottom - height2,
88 | availableHeight2 = height2 - margin2.top - margin2.bottom;
89 |
90 | chart.update = function() { container.transition().duration(transitionDuration).call(chart) };
91 | chart.container = this;
92 |
93 |
94 | //------------------------------------------------------------
95 | // Display No Data message if there's nothing to show.
96 |
97 | if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
98 | var noDataText = container.selectAll('.nv-noData').data([noData]);
99 |
100 | noDataText.enter().append('text')
101 | .attr('class', 'nvd3 nv-noData')
102 | .attr('dy', '-.7em')
103 | .style('text-anchor', 'middle');
104 |
105 | noDataText
106 | .attr('x', margin.left + availableWidth / 2)
107 | .attr('y', margin.top + availableHeight1 / 2)
108 | .text(function(d) { return d });
109 |
110 | return chart;
111 | } else {
112 | container.selectAll('.nv-noData').remove();
113 | }
114 |
115 | //------------------------------------------------------------
116 |
117 |
118 | //------------------------------------------------------------
119 | // Setup Scales
120 |
121 | x = lines.xScale();
122 | y = lines.yScale();
123 | x2 = lines2.xScale();
124 | y2 = lines2.yScale();
125 |
126 | //------------------------------------------------------------
127 |
128 |
129 | //------------------------------------------------------------
130 | // Setup containers and skeleton of chart
131 |
132 | var wrap = container.selectAll('g.nv-wrap.nv-lineWithFocusChart').data([data]);
133 | var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineWithFocusChart').append('g');
134 | var g = wrap.select('g');
135 |
136 | gEnter.append('g').attr('class', 'nv-legendWrap');
137 |
138 | var focusEnter = gEnter.append('g').attr('class', 'nv-focus');
139 | focusEnter.append('g').attr('class', 'nv-x nv-axis');
140 | focusEnter.append('g').attr('class', 'nv-y nv-axis');
141 | focusEnter.append('g').attr('class', 'nv-linesWrap');
142 |
143 | var contextEnter = gEnter.append('g').attr('class', 'nv-context');
144 | contextEnter.append('g').attr('class', 'nv-x nv-axis');
145 | contextEnter.append('g').attr('class', 'nv-y nv-axis');
146 | contextEnter.append('g').attr('class', 'nv-linesWrap');
147 | contextEnter.append('g').attr('class', 'nv-brushBackground');
148 | contextEnter.append('g').attr('class', 'nv-x nv-brush');
149 |
150 | //------------------------------------------------------------
151 |
152 |
153 | //------------------------------------------------------------
154 | // Legend
155 |
156 | if (showLegend) {
157 | legend.width(availableWidth);
158 |
159 | g.select('.nv-legendWrap')
160 | .datum(data)
161 | .call(legend);
162 |
163 | if ( margin.top != legend.height()) {
164 | margin.top = legend.height();
165 | availableHeight1 = (height || parseInt(container.style('height')) || 400)
166 | - margin.top - margin.bottom - height2;
167 | }
168 |
169 | g.select('.nv-legendWrap')
170 | .attr('transform', 'translate(0,' + (-margin.top) +')')
171 | }
172 |
173 | //------------------------------------------------------------
174 |
175 |
176 | wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
177 |
178 |
179 | //------------------------------------------------------------
180 | // Main Chart Component(s)
181 |
182 | lines
183 | .width(availableWidth)
184 | .height(availableHeight1)
185 | .color(
186 | data
187 | .map(function(d,i) {
188 | return d.color || color(d, i);
189 | })
190 | .filter(function(d,i) {
191 | return !data[i].disabled;
192 | })
193 | );
194 |
195 | lines2
196 | .defined(lines.defined())
197 | .width(availableWidth)
198 | .height(availableHeight2)
199 | .color(
200 | data
201 | .map(function(d,i) {
202 | return d.color || color(d, i);
203 | })
204 | .filter(function(d,i) {
205 | return !data[i].disabled;
206 | })
207 | );
208 |
209 | g.select('.nv-context')
210 | .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')')
211 |
212 | var contextLinesWrap = g.select('.nv-context .nv-linesWrap')
213 | .datum(data.filter(function(d) { return !d.disabled }))
214 |
215 | d3.transition(contextLinesWrap).call(lines2);
216 |
217 | //------------------------------------------------------------
218 |
219 |
220 | /*
221 | var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
222 | .datum(data.filter(function(d) { return !d.disabled }))
223 |
224 | d3.transition(focusLinesWrap).call(lines);
225 | */
226 |
227 |
228 | //------------------------------------------------------------
229 | // Setup Main (Focus) Axes
230 |
231 | xAxis
232 | .scale(x)
233 | .ticks( availableWidth / 100 )
234 | .tickSize(-availableHeight1, 0);
235 |
236 | yAxis
237 | .scale(y)
238 | .ticks( availableHeight1 / 36 )
239 | .tickSize( -availableWidth, 0);
240 |
241 | g.select('.nv-focus .nv-x.nv-axis')
242 | .attr('transform', 'translate(0,' + availableHeight1 + ')');
243 |
244 | //------------------------------------------------------------
245 |
246 |
247 | //------------------------------------------------------------
248 | // Setup Brush
249 |
250 | brush
251 | .x(x2)
252 | .on('brush', function() {
253 | //When brushing, turn off transitions because chart needs to change immediately.
254 | var oldTransition = chart.transitionDuration();
255 | chart.transitionDuration(0);
256 | onBrush();
257 | chart.transitionDuration(oldTransition);
258 | });
259 |
260 | if (brushExtent) brush.extent(brushExtent);
261 |
262 | var brushBG = g.select('.nv-brushBackground').selectAll('g')
263 | .data([brushExtent || brush.extent()])
264 |
265 | var brushBGenter = brushBG.enter()
266 | .append('g');
267 |
268 | brushBGenter.append('rect')
269 | .attr('class', 'left')
270 | .attr('x', 0)
271 | .attr('y', 0)
272 | .attr('height', availableHeight2);
273 |
274 | brushBGenter.append('rect')
275 | .attr('class', 'right')
276 | .attr('x', 0)
277 | .attr('y', 0)
278 | .attr('height', availableHeight2);
279 |
280 | var gBrush = g.select('.nv-x.nv-brush')
281 | .call(brush);
282 | gBrush.selectAll('rect')
283 | //.attr('y', -5)
284 | .attr('height', availableHeight2);
285 | gBrush.selectAll('.resize').append('path').attr('d', resizePath);
286 |
287 | onBrush();
288 |
289 | //------------------------------------------------------------
290 |
291 |
292 | //------------------------------------------------------------
293 | // Setup Secondary (Context) Axes
294 |
295 | x2Axis
296 | .scale(x2)
297 | .ticks( availableWidth / 100 )
298 | .tickSize(-availableHeight2, 0);
299 |
300 | g.select('.nv-context .nv-x.nv-axis')
301 | .attr('transform', 'translate(0,' + y2.range()[0] + ')');
302 | d3.transition(g.select('.nv-context .nv-x.nv-axis'))
303 | .call(x2Axis);
304 |
305 |
306 | y2Axis
307 | .scale(y2)
308 | .ticks( availableHeight2 / 36 )
309 | .tickSize( -availableWidth, 0);
310 |
311 | d3.transition(g.select('.nv-context .nv-y.nv-axis'))
312 | .call(y2Axis);
313 |
314 | g.select('.nv-context .nv-x.nv-axis')
315 | .attr('transform', 'translate(0,' + y2.range()[0] + ')');
316 |
317 | //------------------------------------------------------------
318 |
319 |
320 | //============================================================
321 | // Event Handling/Dispatching (in chart's scope)
322 | //------------------------------------------------------------
323 |
324 | legend.dispatch.on('stateChange', function(newState) {
325 | chart.update();
326 | });
327 |
328 | dispatch.on('tooltipShow', function(e) {
329 | if (tooltips) showTooltip(e, that.parentNode);
330 | });
331 |
332 | //============================================================
333 |
334 |
335 | //============================================================
336 | // Functions
337 | //------------------------------------------------------------
338 |
339 | // Taken from crossfilter (http://square.github.com/crossfilter/)
340 | function resizePath(d) {
341 | var e = +(d == 'e'),
342 | x = e ? 1 : -1,
343 | y = availableHeight2 / 3;
344 | return 'M' + (.5 * x) + ',' + y
345 | + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)
346 | + 'V' + (2 * y - 6)
347 | + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y)
348 | + 'Z'
349 | + 'M' + (2.5 * x) + ',' + (y + 8)
350 | + 'V' + (2 * y - 8)
351 | + 'M' + (4.5 * x) + ',' + (y + 8)
352 | + 'V' + (2 * y - 8);
353 | }
354 |
355 |
356 | function updateBrushBG() {
357 | if (!brush.empty()) brush.extent(brushExtent);
358 | brushBG
359 | .data([brush.empty() ? x2.domain() : brushExtent])
360 | .each(function(d,i) {
361 | var leftWidth = x2(d[0]) - x.range()[0],
362 | rightWidth = x.range()[1] - x2(d[1]);
363 | d3.select(this).select('.left')
364 | .attr('width', leftWidth < 0 ? 0 : leftWidth);
365 |
366 | d3.select(this).select('.right')
367 | .attr('x', x2(d[1]))
368 | .attr('width', rightWidth < 0 ? 0 : rightWidth);
369 | });
370 | }
371 |
372 |
373 | function onBrush() {
374 | brushExtent = brush.empty() ? null : brush.extent();
375 | var extent = brush.empty() ? x2.domain() : brush.extent();
376 |
377 | //The brush extent cannot be less than one. If it is, don't update the line chart.
378 | if (Math.abs(extent[0] - extent[1]) <= 1) {
379 | return;
380 | }
381 |
382 | dispatch.brush({extent: extent, brush: brush});
383 |
384 |
385 | updateBrushBG();
386 |
387 | // Update Main (Focus)
388 | var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
389 | .datum(
390 | data
391 | .filter(function(d) { return !d.disabled })
392 | .map(function(d,i) {
393 | return {
394 | key: d.key,
395 | area: d.area,
396 | values: d.values.filter(function(d,i) {
397 | return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
398 | })
399 | }
400 | })
401 | );
402 | focusLinesWrap.transition().duration(transitionDuration).call(lines);
403 |
404 |
405 | // Update Main (Focus) Axes
406 | g.select('.nv-focus .nv-x.nv-axis').transition().duration(transitionDuration)
407 | .call(xAxis);
408 | g.select('.nv-focus .nv-y.nv-axis').transition().duration(transitionDuration)
409 | .call(yAxis);
410 | }
411 |
412 | //============================================================
413 |
414 |
415 | });
416 |
417 | return chart;
418 | }
419 |
420 |
421 | //============================================================
422 | // Event Handling/Dispatching (out of chart's scope)
423 | //------------------------------------------------------------
424 |
425 | lines.dispatch.on('elementMouseover.tooltip', function(e) {
426 | e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];
427 | dispatch.tooltipShow(e);
428 | });
429 |
430 | lines.dispatch.on('elementMouseout.tooltip', function(e) {
431 | dispatch.tooltipHide(e);
432 | });
433 |
434 | dispatch.on('tooltipHide', function() {
435 | if (tooltips) nv.tooltip.cleanup();
436 | });
437 |
438 | //============================================================
439 |
440 |
441 | //============================================================
442 | // Expose Public Variables
443 | //------------------------------------------------------------
444 |
445 | // expose chart's sub-components
446 | chart.dispatch = dispatch;
447 | chart.legend = legend;
448 | chart.lines = lines;
449 | chart.lines2 = lines2;
450 | chart.xAxis = xAxis;
451 | chart.yAxis = yAxis;
452 | chart.x2Axis = x2Axis;
453 | chart.y2Axis = y2Axis;
454 |
455 | d3.rebind(chart, lines, 'defined', 'isArea', 'size', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');
456 |
457 | chart.options = nv.utils.optionsFunc.bind(chart);
458 |
459 | chart.x = function(_) {
460 | if (!arguments.length) return lines.x;
461 | lines.x(_);
462 | lines2.x(_);
463 | return chart;
464 | };
465 |
466 | chart.y = function(_) {
467 | if (!arguments.length) return lines.y;
468 | lines.y(_);
469 | lines2.y(_);
470 | return chart;
471 | };
472 |
473 | chart.margin = function(_) {
474 | if (!arguments.length) return margin;
475 | margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
476 | margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
477 | margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
478 | margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
479 | return chart;
480 | };
481 |
482 | chart.margin2 = function(_) {
483 | if (!arguments.length) return margin2;
484 | margin2 = _;
485 | return chart;
486 | };
487 |
488 | chart.width = function(_) {
489 | if (!arguments.length) return width;
490 | width = _;
491 | return chart;
492 | };
493 |
494 | chart.height = function(_) {
495 | if (!arguments.length) return height;
496 | height = _;
497 | return chart;
498 | };
499 |
500 | chart.height2 = function(_) {
501 | if (!arguments.length) return height2;
502 | height2 = _;
503 | return chart;
504 | };
505 |
506 | chart.color = function(_) {
507 | if (!arguments.length) return color;
508 | color =nv.utils.getColor(_);
509 | legend.color(color);
510 | return chart;
511 | };
512 |
513 | chart.showLegend = function(_) {
514 | if (!arguments.length) return showLegend;
515 | showLegend = _;
516 | return chart;
517 | };
518 |
519 | chart.tooltips = function(_) {
520 | if (!arguments.length) return tooltips;
521 | tooltips = _;
522 | return chart;
523 | };
524 |
525 | chart.tooltipContent = function(_) {
526 | if (!arguments.length) return tooltip;
527 | tooltip = _;
528 | return chart;
529 | };
530 |
531 | chart.interpolate = function(_) {
532 | if (!arguments.length) return lines.interpolate();
533 | lines.interpolate(_);
534 | lines2.interpolate(_);
535 | return chart;
536 | };
537 |
538 | chart.noData = function(_) {
539 | if (!arguments.length) return noData;
540 | noData = _;
541 | return chart;
542 | };
543 |
544 | // Chart has multiple similar Axes, to prevent code duplication, probably need to link all axis functions manually like below
545 | chart.xTickFormat = function(_) {
546 | if (!arguments.length) return xAxis.tickFormat();
547 | xAxis.tickFormat(_);
548 | x2Axis.tickFormat(_);
549 | return chart;
550 | };
551 |
552 | chart.yTickFormat = function(_) {
553 | if (!arguments.length) return yAxis.tickFormat();
554 | yAxis.tickFormat(_);
555 | y2Axis.tickFormat(_);
556 | return chart;
557 | };
558 |
559 | chart.brushExtent = function(_) {
560 | if (!arguments.length) return brushExtent;
561 | brushExtent = _;
562 | return chart;
563 | };
564 |
565 | chart.transitionDuration = function(_) {
566 | if (!arguments.length) return transitionDuration;
567 | transitionDuration = _;
568 | return chart;
569 | };
570 |
571 | //============================================================
572 |
573 |
574 | return chart;
575 | }
--------------------------------------------------------------------------------