'+a.addText+" "),h=b(this).parent().find("tr:last a")):(b(this).filter(":last").after('"),h=b(this).filter(":last").next().find("a"));h.click(function(){var c=b("#id_"+a.prefix+
3 | "-TOTAL_FORMS"),e=b("#"+a.prefix+"-empty"),d=e.clone(!0);d.removeClass(a.emptyCssClass).addClass(a.formCssClass).attr("id",a.prefix+"-"+g);d.is("tr")?d.children(":last").append('"):d.is("ul")||d.is("ol")?d.append(''+a.deleteText+" "):d.children(":first").append(''+a.deleteText+
4 | " ");d.find("*").each(function(){j(this,a.prefix,c.val())});d.insertBefore(b(e));b(c).val(parseInt(c.val())+1);g+=1;""!=f.val()&&0>=f.val()-c.val()&&h.parent().hide();d.find("a."+a.deleteCssClass).click(function(){var c=b(this).parents("."+a.formCssClass);c.remove();g-=1;a.removed&&a.removed(c);c=b("."+a.formCssClass);b("#id_"+a.prefix+"-TOTAL_FORMS").val(c.length);(""==f.val()||0 1:
49 | news['isMulti'] = True
50 | should_append = True
51 |
52 | for node in view_more:
53 | if node.find('a'):
54 | if node.find('a').text == u'查看知乎讨论':
55 | news['questionUrlList'].append(node.find('a')['href'])
56 | else:
57 | should_append = False
58 | else:
59 | continue
60 |
61 | for node in bs.find_all('h2'):
62 | title = node.get_text() if node.get_text() != "" else n['title']
63 | news['questionTitleList'].append(title)
64 |
65 | if should_append:
66 | news_list.append(news)
67 | elif len(view_more) == 1:
68 | question_element = (bs.find('div', {'class': 'view-more'})).find('a')
69 | if question_element.text == u'查看知乎讨论':
70 | news['questionUrl'] = question_element['href']
71 |
72 | title = bs.find('h2').get_text()
73 | news['questionTitle'] = title if title != "" else n['title']
74 |
75 | news_list.append(news)
76 |
77 | return json.dumps(news_list, ensure_ascii=False).encode('utf-8')
78 |
79 | def clean(self):
80 | if not self.date or not self.content:
81 | raise ValidationError("Content cannot be null")
82 | else:
83 | try:
84 | time.strptime(str(self.date), '%Y%m%d')
85 | except ValueError, e:
86 | raise ValidationError("Date illegal")
--------------------------------------------------------------------------------
/static/admin/js/admin/RelatedObjectLookups.js:
--------------------------------------------------------------------------------
1 | // Handles related-objects functionality: lookup link for raw_id_fields
2 | // and Add Another links.
3 |
4 | function html_unescape(text) {
5 | // Unescape a string that was escaped using django.utils.html.escape.
6 | text = text.replace(/</g, '<');
7 | text = text.replace(/>/g, '>');
8 | text = text.replace(/"/g, '"');
9 | text = text.replace(/'/g, "'");
10 | text = text.replace(/&/g, '&');
11 | return text;
12 | }
13 |
14 | // IE doesn't accept periods or dashes in the window name, but the element IDs
15 | // we use to generate popup window names may contain them, therefore we map them
16 | // to allowed characters in a reversible way so that we can locate the correct
17 | // element when the popup window is dismissed.
18 | function id_to_windowname(text) {
19 | text = text.replace(/\./g, '__dot__');
20 | text = text.replace(/\-/g, '__dash__');
21 | return text;
22 | }
23 |
24 | function windowname_to_id(text) {
25 | text = text.replace(/__dot__/g, '.');
26 | text = text.replace(/__dash__/g, '-');
27 | return text;
28 | }
29 |
30 | function showRelatedObjectLookupPopup(triggeringLink) {
31 | var name = triggeringLink.id.replace(/^lookup_/, '');
32 | name = id_to_windowname(name);
33 | var href;
34 | if (triggeringLink.href.search(/\?/) >= 0) {
35 | href = triggeringLink.href + '&pop=1';
36 | } else {
37 | href = triggeringLink.href + '?pop=1';
38 | }
39 | var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
40 | win.focus();
41 | return false;
42 | }
43 |
44 | function dismissRelatedLookupPopup(win, chosenId) {
45 | var name = windowname_to_id(win.name);
46 | var elem = document.getElementById(name);
47 | if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) {
48 | elem.value += ',' + chosenId;
49 | } else {
50 | document.getElementById(name).value = chosenId;
51 | }
52 | win.close();
53 | }
54 |
55 | function showAddAnotherPopup(triggeringLink) {
56 | var name = triggeringLink.id.replace(/^add_/, '');
57 | name = id_to_windowname(name);
58 | href = triggeringLink.href
59 | if (href.indexOf('?') == -1) {
60 | href += '?_popup=1';
61 | } else {
62 | href += '&_popup=1';
63 | }
64 | var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
65 | win.focus();
66 | return false;
67 | }
68 |
69 | function dismissAddAnotherPopup(win, newId, newRepr) {
70 | // newId and newRepr are expected to have previously been escaped by
71 | // django.utils.html.escape.
72 | newId = html_unescape(newId);
73 | newRepr = html_unescape(newRepr);
74 | var name = windowname_to_id(win.name);
75 | var elem = document.getElementById(name);
76 | if (elem) {
77 | var elemName = elem.nodeName.toUpperCase();
78 | if (elemName == 'SELECT') {
79 | var o = new Option(newRepr, newId);
80 | elem.options[elem.options.length] = o;
81 | o.selected = true;
82 | } else if (elemName == 'INPUT') {
83 | if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) {
84 | elem.value += ',' + newId;
85 | } else {
86 | elem.value = newId;
87 | }
88 | }
89 | } else {
90 | var toId = name + "_to";
91 | elem = document.getElementById(toId);
92 | var o = new Option(newRepr, newId);
93 | SelectBox.add_to_cache(toId, o);
94 | SelectBox.redisplay(toId);
95 | }
96 | win.close();
97 | }
98 |
--------------------------------------------------------------------------------
/static/admin/js/admin/ordering.js:
--------------------------------------------------------------------------------
1 | addEvent(window, 'load', reorder_init);
2 |
3 | var lis;
4 | var top = 0;
5 | var left = 0;
6 | var height = 30;
7 |
8 | function reorder_init() {
9 | lis = document.getElementsBySelector('ul#orderthese li');
10 | var input = document.getElementsBySelector('input[name=order_]')[0];
11 | setOrder(input.value.split(','));
12 | input.disabled = true;
13 | draw();
14 | // Now initialize the dragging behavior
15 | var limit = (lis.length - 1) * height;
16 | for (var i = 0; i < lis.length; i++) {
17 | var li = lis[i];
18 | var img = document.getElementById('handle'+li.id);
19 | li.style.zIndex = 1;
20 | Drag.init(img, li, left + 10, left + 10, top + 10, top + 10 + limit);
21 | li.onDragStart = startDrag;
22 | li.onDragEnd = endDrag;
23 | img.style.cursor = 'move';
24 | }
25 | }
26 |
27 | function submitOrderForm() {
28 | var inputOrder = document.getElementsBySelector('input[name=order_]')[0];
29 | inputOrder.value = getOrder();
30 | inputOrder.disabled=false;
31 | }
32 |
33 | function startDrag() {
34 | this.style.zIndex = '10';
35 | this.className = 'dragging';
36 | }
37 |
38 | function endDrag(x, y) {
39 | this.style.zIndex = '1';
40 | this.className = '';
41 | // Work out how far along it has been dropped, using x co-ordinate
42 | var oldIndex = this.index;
43 | var newIndex = Math.round((y - 10 - top) / height);
44 | // 'Snap' to the correct position
45 | this.style.top = (10 + top + newIndex * height) + 'px';
46 | this.index = newIndex;
47 | moveItem(oldIndex, newIndex);
48 | }
49 |
50 | function moveItem(oldIndex, newIndex) {
51 | // Swaps two items, adjusts the index and left co-ord for all others
52 | if (oldIndex == newIndex) {
53 | return; // Nothing to swap;
54 | }
55 | var direction, lo, hi;
56 | if (newIndex > oldIndex) {
57 | lo = oldIndex;
58 | hi = newIndex;
59 | direction = -1;
60 | } else {
61 | direction = 1;
62 | hi = oldIndex;
63 | lo = newIndex;
64 | }
65 | var lis2 = new Array(); // We will build the new order in this array
66 | for (var i = 0; i < lis.length; i++) {
67 | if (i < lo || i > hi) {
68 | // Position of items not between the indexes is unaffected
69 | lis2[i] = lis[i];
70 | continue;
71 | } else if (i == newIndex) {
72 | lis2[i] = lis[oldIndex];
73 | continue;
74 | } else {
75 | // Item is between the two indexes - move it along 1
76 | lis2[i] = lis[i - direction];
77 | }
78 | }
79 | // Re-index everything
80 | reIndex(lis2);
81 | lis = lis2;
82 | draw();
83 | // document.getElementById('hiddenOrder').value = getOrder();
84 | document.getElementsBySelector('input[name=order_]')[0].value = getOrder();
85 | }
86 |
87 | function reIndex(lis) {
88 | for (var i = 0; i < lis.length; i++) {
89 | lis[i].index = i;
90 | }
91 | }
92 |
93 | function draw() {
94 | for (var i = 0; i < lis.length; i++) {
95 | var li = lis[i];
96 | li.index = i;
97 | li.style.position = 'absolute';
98 | li.style.left = (10 + left) + 'px';
99 | li.style.top = (10 + top + (i * height)) + 'px';
100 | }
101 | }
102 |
103 | function getOrder() {
104 | var order = new Array(lis.length);
105 | for (var i = 0; i < lis.length; i++) {
106 | order[i] = lis[i].id.substring(1, 100);
107 | }
108 | return order.join(',');
109 | }
110 |
111 | function setOrder(id_list) {
112 | /* Set the current order to match the lsit of IDs */
113 | var temp_lis = new Array();
114 | for (var i = 0; i < id_list.length; i++) {
115 | var id = 'p' + id_list[i];
116 | temp_lis[temp_lis.length] = document.getElementById(id);
117 | }
118 | reIndex(temp_lis);
119 | lis = temp_lis;
120 | draw();
121 | }
122 |
123 | function addEvent(elm, evType, fn, useCapture)
124 | // addEvent and removeEvent
125 | // cross-browser event handling for IE5+, NS6 and Mozilla
126 | // By Scott Andrew
127 | {
128 | if (elm.addEventListener){
129 | elm.addEventListener(evType, fn, useCapture);
130 | return true;
131 | } else if (elm.attachEvent){
132 | var r = elm.attachEvent("on"+evType, fn);
133 | return r;
134 | } else {
135 | elm['on'+evType] = fn;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/static/admin/js/SelectBox.js:
--------------------------------------------------------------------------------
1 | var SelectBox = {
2 | cache: new Object(),
3 | init: function(id) {
4 | var box = document.getElementById(id);
5 | var node;
6 | SelectBox.cache[id] = new Array();
7 | var cache = SelectBox.cache[id];
8 | for (var i = 0; (node = box.options[i]); i++) {
9 | cache.push({value: node.value, text: node.text, displayed: 1});
10 | }
11 | },
12 | redisplay: function(id) {
13 | // Repopulate HTML select box from cache
14 | var box = document.getElementById(id);
15 | box.options.length = 0; // clear all options
16 | for (var i = 0, j = SelectBox.cache[id].length; i < j; i++) {
17 | var node = SelectBox.cache[id][i];
18 | if (node.displayed) {
19 | box.options[box.options.length] = new Option(node.text, node.value, false, false);
20 | }
21 | }
22 | },
23 | filter: function(id, text) {
24 | // Redisplay the HTML select box, displaying only the choices containing ALL
25 | // the words in text. (It's an AND search.)
26 | var tokens = text.toLowerCase().split(/\s+/);
27 | var node, token;
28 | for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
29 | node.displayed = 1;
30 | for (var j = 0; (token = tokens[j]); j++) {
31 | if (node.text.toLowerCase().indexOf(token) == -1) {
32 | node.displayed = 0;
33 | }
34 | }
35 | }
36 | SelectBox.redisplay(id);
37 | },
38 | delete_from_cache: function(id, value) {
39 | var node, delete_index = null;
40 | for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
41 | if (node.value == value) {
42 | delete_index = i;
43 | break;
44 | }
45 | }
46 | var j = SelectBox.cache[id].length - 1;
47 | for (var i = delete_index; i < j; i++) {
48 | SelectBox.cache[id][i] = SelectBox.cache[id][i+1];
49 | }
50 | SelectBox.cache[id].length--;
51 | },
52 | add_to_cache: function(id, option) {
53 | SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1});
54 | },
55 | cache_contains: function(id, value) {
56 | // Check if an item is contained in the cache
57 | var node;
58 | for (var i = 0; (node = SelectBox.cache[id][i]); i++) {
59 | if (node.value == value) {
60 | return true;
61 | }
62 | }
63 | return false;
64 | },
65 | move: function(from, to) {
66 | var from_box = document.getElementById(from);
67 | var to_box = document.getElementById(to);
68 | var option;
69 | for (var i = 0; (option = from_box.options[i]); i++) {
70 | if (option.selected && SelectBox.cache_contains(from, option.value)) {
71 | SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1});
72 | SelectBox.delete_from_cache(from, option.value);
73 | }
74 | }
75 | SelectBox.redisplay(from);
76 | SelectBox.redisplay(to);
77 | },
78 | move_all: function(from, to) {
79 | var from_box = document.getElementById(from);
80 | var to_box = document.getElementById(to);
81 | var option;
82 | for (var i = 0; (option = from_box.options[i]); i++) {
83 | if (SelectBox.cache_contains(from, option.value)) {
84 | SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1});
85 | SelectBox.delete_from_cache(from, option.value);
86 | }
87 | }
88 | SelectBox.redisplay(from);
89 | SelectBox.redisplay(to);
90 | },
91 | sort: function(id) {
92 | SelectBox.cache[id].sort( function(a, b) {
93 | a = a.text.toLowerCase();
94 | b = b.text.toLowerCase();
95 | try {
96 | if (a > 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 | /* dashboard styles */
88 |
89 | .dashboard .module table td a {
90 | padding-left: .6em;
91 | padding-right: 12px;
92 | }
93 |
94 | /* changelists styles */
95 |
96 | .change-list .filtered {
97 | background: white url(../img/changelist-bg_rtl.gif) top left repeat-y !important;
98 | }
99 |
100 | .change-list .filtered table {
101 | border-left: 1px solid #ddd;
102 | border-right: 0px none;
103 | }
104 |
105 | #changelist-filter {
106 | right: auto;
107 | left: 0;
108 | border-left: 0px none;
109 | border-right: 1px solid #ddd;
110 | }
111 |
112 | .change-list .filtered .results, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull {
113 | margin-right: 0px !important;
114 | margin-left: 160px !important;
115 | }
116 |
117 | #changelist-filter li.selected {
118 | border-left: 0px none;
119 | padding-left: 0px;
120 | margin-left: 0;
121 | border-right: 5px solid #ccc;
122 | padding-right: 5px;
123 | margin-right: -10px;
124 | }
125 |
126 | .filtered .actions {
127 | border-left:1px solid #DDDDDD;
128 | margin-left:160px !important;
129 | border-right: 0 none;
130 | margin-right:0 !important;
131 | }
132 |
133 | #changelist table tbody td:first-child, #changelist table tbody th:first-child {
134 | border-right: 0;
135 | border-left: 1px solid #ddd;
136 | }
137 |
138 | /* FORMS */
139 |
140 | .aligned label {
141 | padding: 0 0 3px 1em;
142 | float: right;
143 | }
144 |
145 | .submit-row {
146 | text-align: left
147 | }
148 |
149 | .submit-row p.deletelink-box {
150 | float: right;
151 | }
152 |
153 | .submit-row .deletelink {
154 | background: url(../img/icon_deletelink.gif) 0 50% no-repeat;
155 | padding-right: 14px;
156 | }
157 |
158 | .vDateField, .vTimeField {
159 | margin-left: 2px;
160 | }
161 |
162 | form ul.inline li {
163 | float: right;
164 | padding-right: 0;
165 | padding-left: 7px;
166 | }
167 |
168 | input[type=submit].default, .submit-row input.default {
169 | float: left;
170 | }
171 |
172 | fieldset .field-box {
173 | float: right;
174 | margin-left: 20px;
175 | margin-right: 0;
176 | }
177 |
178 | .errorlist li {
179 | background-position: 100% .3em;
180 | padding: 4px 25px 4px 5px;
181 | }
182 |
183 | .errornote {
184 | background-position: 100% .3em;
185 | padding: 4px 25px 4px 5px;
186 | }
187 |
188 | /* WIDGETS */
189 |
190 | .calendarnav-previous {
191 | top: 0;
192 | left: auto;
193 | right: 0;
194 | }
195 |
196 | .calendarnav-next {
197 | top: 0;
198 | right: auto;
199 | left: 0;
200 | }
201 |
202 | .calendar caption, .calendarbox h2 {
203 | text-align: center;
204 | }
205 |
206 | .selector {
207 | float: right;
208 | }
209 |
210 | .selector .selector-filter {
211 | text-align: right;
212 | }
213 |
214 | .inline-deletelink {
215 | float: left;
216 | }
217 |
218 | /* MISC */
219 |
220 | .inline-related h2, .inline-group h2 {
221 | text-align: right
222 | }
223 |
224 | .inline-related h3 span.delete {
225 | padding-right: 20px;
226 | padding-left: inherit;
227 | left: 10px;
228 | right: inherit;
229 | float:left;
230 | }
231 |
232 | .inline-related h3 span.delete label {
233 | margin-left: inherit;
234 | margin-right: 2px;
235 | }
236 |
237 | /* IE7 specific bug fixes */
238 |
239 | div.colM {
240 | position: relative;
241 | }
242 |
243 | .submit-row input {
244 | float: left;
245 | }
--------------------------------------------------------------------------------
/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 | checker = function(checked) {
7 | if (checked) {
8 | showQuestion();
9 | } else {
10 | reset();
11 | }
12 | $(actionCheckboxes).attr("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).attr("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).attr("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).attr("checked", false);
78 | clearAcross();
79 | checker(0);
80 | updateCounter();
81 | });
82 | lastChecked = null;
83 | $(actionCheckboxes).click(function(event) {
84 | if (!event) { var 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).attr("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).attr("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/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/js/calendar.js:
--------------------------------------------------------------------------------
1 | /*
2 | calendar.js - Calendar functions by Adrian Holovaty
3 | */
4 |
5 | function removeChildren(a) { // "a" is reference to an object
6 | while (a.hasChildNodes()) a.removeChild(a.lastChild);
7 | }
8 |
9 | // quickElement(tagType, parentReference, textInChildNode, [, attribute, attributeValue ...]);
10 | function quickElement() {
11 | var obj = document.createElement(arguments[0]);
12 | if (arguments[2] != '' && arguments[2] != null) {
13 | var textNode = document.createTextNode(arguments[2]);
14 | obj.appendChild(textNode);
15 | }
16 | var len = arguments.length;
17 | for (var i = 3; i < len; i += 2) {
18 | obj.setAttribute(arguments[i], arguments[i+1]);
19 | }
20 | arguments[1].appendChild(obj);
21 | return obj;
22 | }
23 |
24 | // CalendarNamespace -- Provides a collection of HTML calendar-related helper functions
25 | var CalendarNamespace = {
26 | monthsOfYear: gettext('January February March April May June July August September October November December').split(' '),
27 | daysOfWeek: gettext('S M T W T F S').split(' '),
28 | firstDayOfWeek: parseInt(get_format('FIRST_DAY_OF_WEEK')),
29 | isLeapYear: function(year) {
30 | return (((year % 4)==0) && ((year % 100)!=0) || ((year % 400)==0));
31 | },
32 | getDaysInMonth: function(month,year) {
33 | var days;
34 | if (month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12) {
35 | days = 31;
36 | }
37 | else if (month==4 || month==6 || month==9 || month==11) {
38 | days = 30;
39 | }
40 | else if (month==2 && CalendarNamespace.isLeapYear(year)) {
41 | days = 29;
42 | }
43 | else {
44 | days = 28;
45 | }
46 | return days;
47 | },
48 | draw: function(month, year, div_id, callback) { // month = 1-12, year = 1-9999
49 | var today = new Date();
50 | var todayDay = today.getDate();
51 | var todayMonth = today.getMonth()+1;
52 | var todayYear = today.getFullYear();
53 | var todayClass = '';
54 |
55 | month = parseInt(month);
56 | year = parseInt(year);
57 | var calDiv = document.getElementById(div_id);
58 | removeChildren(calDiv);
59 | var calTable = document.createElement('table');
60 | quickElement('caption', calTable, CalendarNamespace.monthsOfYear[month-1] + ' ' + year);
61 | var tableBody = quickElement('tbody', calTable);
62 |
63 | // Draw days-of-week header
64 | var tableRow = quickElement('tr', tableBody);
65 | for (var i = 0; i < 7; i++) {
66 | quickElement('th', tableRow, CalendarNamespace.daysOfWeek[(i + CalendarNamespace.firstDayOfWeek) % 7]);
67 | }
68 |
69 | var startingPos = new Date(year, month-1, 1 - CalendarNamespace.firstDayOfWeek).getDay();
70 | var days = CalendarNamespace.getDaysInMonth(month, year);
71 |
72 | // Draw blanks before first of month
73 | tableRow = quickElement('tr', tableBody);
74 | for (var i = 0; i < startingPos; i++) {
75 | var _cell = quickElement('td', tableRow, ' ');
76 | _cell.style.backgroundColor = '#f3f3f3';
77 | }
78 |
79 | // Draw days of month
80 | var currentDay = 1;
81 | for (var i = startingPos; currentDay <= days; i++) {
82 | if (i%7 == 0 && currentDay != 1) {
83 | tableRow = quickElement('tr', tableBody);
84 | }
85 | if ((currentDay==todayDay) && (month==todayMonth) && (year==todayYear)) {
86 | todayClass='today';
87 | } else {
88 | todayClass='';
89 | }
90 | var cell = quickElement('td', tableRow, '', 'class', todayClass);
91 |
92 | quickElement('a', cell, currentDay, 'href', 'javascript:void(' + callback + '('+year+','+month+','+currentDay+'));');
93 | currentDay++;
94 | }
95 |
96 | // Draw blanks after end of month (optional, but makes for valid code)
97 | while (tableRow.childNodes.length < 7) {
98 | var _cell = quickElement('td', tableRow, ' ');
99 | _cell.style.backgroundColor = '#f3f3f3';
100 | }
101 |
102 | calDiv.appendChild(calTable);
103 | }
104 | }
105 |
106 | // Calendar -- A calendar instance
107 | function Calendar(div_id, callback) {
108 | // div_id (string) is the ID of the element in which the calendar will
109 | // be displayed
110 | // callback (string) is the name of a JavaScript function that will be
111 | // called with the parameters (year, month, day) when a day in the
112 | // calendar is clicked
113 | this.div_id = div_id;
114 | this.callback = callback;
115 | this.today = new Date();
116 | this.currentMonth = this.today.getMonth() + 1;
117 | this.currentYear = this.today.getFullYear();
118 | }
119 | Calendar.prototype = {
120 | drawCurrent: function() {
121 | CalendarNamespace.draw(this.currentMonth, this.currentYear, this.div_id, this.callback);
122 | },
123 | drawDate: function(month, year) {
124 | this.currentMonth = month;
125 | this.currentYear = year;
126 | this.drawCurrent();
127 | },
128 | drawPreviousMonth: function() {
129 | if (this.currentMonth == 1) {
130 | this.currentMonth = 12;
131 | this.currentYear--;
132 | }
133 | else {
134 | this.currentMonth--;
135 | }
136 | this.drawCurrent();
137 | },
138 | drawNextMonth: function() {
139 | if (this.currentMonth == 12) {
140 | this.currentMonth = 1;
141 | this.currentYear++;
142 | }
143 | else {
144 | this.currentMonth++;
145 | }
146 | this.drawCurrent();
147 | },
148 | drawPreviousYear: function() {
149 | this.currentYear--;
150 | this.drawCurrent();
151 | },
152 | drawNextYear: function() {
153 | this.currentYear++;
154 | this.drawCurrent();
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/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
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 updateElementIndex = function(el, prefix, ndx) {
21 | var id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))");
22 | var replacement = prefix + "-" + ndx;
23 | if ($(el).attr("for")) {
24 | $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
25 | }
26 | if (el.id) {
27 | el.id = el.id.replace(id_regex, replacement);
28 | }
29 | if (el.name) {
30 | el.name = el.name.replace(id_regex, replacement);
31 | }
32 | };
33 | var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").attr("autocomplete", "off");
34 | var nextIndex = parseInt(totalForms.val());
35 | var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").attr("autocomplete", "off");
36 | // only show the add button if we are allowed to add more items,
37 | // note that max_num = None translates to a blank string.
38 | var showAddButton = maxForms.val() == '' || (maxForms.val()-totalForms.val()) > 0;
39 | $(this).each(function(i) {
40 | $(this).not("." + options.emptyCssClass).addClass(options.formCssClass);
41 | });
42 | if ($(this).length && showAddButton) {
43 | var addButton;
44 | if ($(this).attr("tagName") == "TR") {
45 | // If forms are laid out as table rows, insert the
46 | // "add" button in a new table row:
47 | var numCols = this.eq(0).children().length;
48 | $(this).parent().append('' + options.addText + " ");
49 | addButton = $(this).parent().find("tr:last a");
50 | } else {
51 | // Otherwise, insert it immediately after the last form:
52 | $(this).filter(":last").after('");
53 | addButton = $(this).filter(":last").next().find("a");
54 | }
55 | addButton.click(function() {
56 | var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS");
57 | var template = $("#" + options.prefix + "-empty");
58 | var row = template.clone(true);
59 | row.removeClass(options.emptyCssClass)
60 | .addClass(options.formCssClass)
61 | .attr("id", options.prefix + "-" + nextIndex);
62 | if (row.is("tr")) {
63 | // If the forms are laid out in table rows, insert
64 | // the remove button into the last table cell:
65 | row.children(":last").append('");
66 | } else if (row.is("ul") || row.is("ol")) {
67 | // If they're laid out as an ordered/unordered list,
68 | // insert an after the last list item:
69 | row.append(' ' + options.deleteText + " ");
70 | } else {
71 | // Otherwise, just insert the remove button as the
72 | // last child element of the form's container:
73 | row.children(":first").append('' + options.deleteText + " ");
74 | }
75 | row.find("*").each(function() {
76 | updateElementIndex(this, options.prefix, totalForms.val());
77 | });
78 | // Insert the new form when it has been fully edited
79 | row.insertBefore($(template));
80 | // Update number of total forms
81 | $(totalForms).val(parseInt(totalForms.val()) + 1);
82 | nextIndex += 1;
83 | // Hide add button in case we've hit the max, except we want to add infinitely
84 | if ((maxForms.val() != '') && (maxForms.val()-totalForms.val()) <= 0) {
85 | addButton.parent().hide();
86 | }
87 | // The delete button of each row triggers a bunch of other things
88 | row.find("a." + options.deleteCssClass).click(function() {
89 | // Remove the parent form containing this button:
90 | var row = $(this).parents("." + options.formCssClass);
91 | row.remove();
92 | nextIndex -= 1;
93 | // If a post-delete callback was provided, call it with the deleted form:
94 | if (options.removed) {
95 | options.removed(row);
96 | }
97 | // Update the TOTAL_FORMS form count.
98 | var forms = $("." + options.formCssClass);
99 | $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length);
100 | // Show add button again once we drop below max
101 | if ((maxForms.val() == '') || (maxForms.val()-forms.length) > 0) {
102 | addButton.parent().show();
103 | }
104 | // Also, update names and ids for all remaining form controls
105 | // so they remain in sequence:
106 | for (var i=0, formCount=forms.length; i -1) {
36 | // Token is an ID selector
37 | var bits = token.split('#');
38 | var tagName = bits[0];
39 | var id = bits[1];
40 | var element = document.getElementById(id);
41 | if (!element || (tagName && element.nodeName.toLowerCase() != tagName)) {
42 | // ID not found or tag with that ID not found, return false.
43 | return new Array();
44 | }
45 | // Set currentContext to contain just this element
46 | currentContext = new Array(element);
47 | continue; // Skip to next token
48 | }
49 | if (token.indexOf('.') > -1) {
50 | // Token contains a class selector
51 | var bits = token.split('.');
52 | var tagName = bits[0];
53 | var className = bits[1];
54 | if (!tagName) {
55 | tagName = '*';
56 | }
57 | // Get elements matching tag, filter them for class selector
58 | var found = new Array;
59 | var foundCount = 0;
60 | for (var h = 0; h < currentContext.length; h++) {
61 | var elements;
62 | if (tagName == '*') {
63 | elements = getAllChildren(currentContext[h]);
64 | } else {
65 | try {
66 | elements = currentContext[h].getElementsByTagName(tagName);
67 | }
68 | catch(e) {
69 | elements = [];
70 | }
71 | }
72 | for (var j = 0; j < elements.length; j++) {
73 | found[foundCount++] = elements[j];
74 | }
75 | }
76 | currentContext = new Array;
77 | var currentContextIndex = 0;
78 | for (var k = 0; k < found.length; k++) {
79 | if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) {
80 | currentContext[currentContextIndex++] = found[k];
81 | }
82 | }
83 | continue; // Skip to next token
84 | }
85 | // Code to deal with attribute selectors
86 | if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) {
87 | var tagName = RegExp.$1;
88 | var attrName = RegExp.$2;
89 | var attrOperator = RegExp.$3;
90 | var attrValue = RegExp.$4;
91 | if (!tagName) {
92 | tagName = '*';
93 | }
94 | // Grab all of the tagName elements within current context
95 | var found = new Array;
96 | var foundCount = 0;
97 | for (var h = 0; h < currentContext.length; h++) {
98 | var elements;
99 | if (tagName == '*') {
100 | elements = getAllChildren(currentContext[h]);
101 | } else {
102 | elements = currentContext[h].getElementsByTagName(tagName);
103 | }
104 | for (var j = 0; j < elements.length; j++) {
105 | found[foundCount++] = elements[j];
106 | }
107 | }
108 | currentContext = new Array;
109 | var currentContextIndex = 0;
110 | var checkFunction; // This function will be used to filter the elements
111 | switch (attrOperator) {
112 | case '=': // Equality
113 | checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
114 | break;
115 | case '~': // Match one of space seperated words
116 | checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); };
117 | break;
118 | case '|': // Match start with value followed by optional hyphen
119 | checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };
120 | break;
121 | case '^': // Match starts with value
122 | checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };
123 | break;
124 | case '$': // Match ends with value - fails with "Warning" in Opera 7
125 | checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };
126 | break;
127 | case '*': // Match ends with value
128 | checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };
129 | break;
130 | default :
131 | // Just test for existence of attribute
132 | checkFunction = function(e) { return e.getAttribute(attrName); };
133 | }
134 | currentContext = new Array;
135 | var currentContextIndex = 0;
136 | for (var k = 0; k < found.length; k++) {
137 | if (checkFunction(found[k])) {
138 | currentContext[currentContextIndex++] = found[k];
139 | }
140 | }
141 | // alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue);
142 | continue; // Skip to next token
143 | }
144 | // If we get here, token is JUST an element (not a class or ID selector)
145 | tagName = token;
146 | var found = new Array;
147 | var foundCount = 0;
148 | for (var h = 0; h < currentContext.length; h++) {
149 | var elements = currentContext[h].getElementsByTagName(tagName);
150 | for (var j = 0; j < elements.length; j++) {
151 | found[foundCount++] = elements[j];
152 | }
153 | }
154 | currentContext = found;
155 | }
156 | return currentContext;
157 | }
158 |
159 | /* That revolting regular expression explained
160 | /^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/
161 | \---/ \---/\-------------/ \-------/
162 | | | | |
163 | | | | The value
164 | | | ~,|,^,$,* or =
165 | | Attribute
166 | Tag
167 | */
168 |
--------------------------------------------------------------------------------
/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 | }
69 |
70 | .aligned ul label {
71 | display: inline;
72 | float: none;
73 | width: auto;
74 | }
75 |
76 | .colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField {
77 | width: 350px;
78 | }
79 |
80 | form .aligned p, form .aligned ul {
81 | margin-left: 7em;
82 | padding-left: 30px;
83 | }
84 |
85 | form .aligned table p {
86 | margin-left: 0;
87 | padding-left: 0;
88 | }
89 |
90 | form .aligned p.help {
91 | padding-left: 38px;
92 | }
93 |
94 | .aligned .vCheckboxLabel {
95 | float: none !important;
96 | display: inline;
97 | padding-left: 4px;
98 | }
99 |
100 | .colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField {
101 | width: 610px;
102 | }
103 |
104 | .checkbox-row p.help {
105 | margin-left: 0;
106 | padding-left: 0 !important;
107 | }
108 |
109 | fieldset .field-box {
110 | float: left;
111 | margin-right: 20px;
112 | }
113 |
114 | /* WIDE FIELDSETS */
115 |
116 | .wide label {
117 | width: 15em !important;
118 | }
119 |
120 | form .wide p {
121 | margin-left: 15em;
122 | }
123 |
124 | form .wide p.help {
125 | padding-left: 38px;
126 | }
127 |
128 | .colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField {
129 | width: 450px;
130 | }
131 |
132 | /* COLLAPSED FIELDSETS */
133 |
134 | fieldset.collapsed * {
135 | display: none;
136 | }
137 |
138 | fieldset.collapsed h2, fieldset.collapsed {
139 | display: block !important;
140 | }
141 |
142 | fieldset.collapsed h2 {
143 | background-image: url(../img/nav-bg.gif);
144 | background-position: bottom left;
145 | color: #999;
146 | }
147 |
148 | fieldset.collapsed .collapse-toggle {
149 | background: transparent;
150 | display: inline !important;
151 | }
152 |
153 | /* MONOSPACE TEXTAREAS */
154 |
155 | fieldset.monospace textarea {
156 | font-family: "Bitstream Vera Sans Mono",Monaco,"Courier New",Courier,monospace;
157 | }
158 |
159 | /* SUBMIT ROW */
160 |
161 | .submit-row {
162 | padding: 5px 7px;
163 | text-align: right;
164 | background: white url(../img/nav-bg.gif) 0 100% repeat-x;
165 | border: 1px solid #ccc;
166 | margin: 5px 0;
167 | overflow: hidden;
168 | }
169 |
170 | body.popup .submit-row {
171 | overflow: auto;
172 | }
173 |
174 | .submit-row input {
175 | margin: 0 0 0 5px;
176 | }
177 |
178 | .submit-row p {
179 | margin: 0.3em;
180 | }
181 |
182 | .submit-row p.deletelink-box {
183 | float: left;
184 | }
185 |
186 | .submit-row .deletelink {
187 | background: url(../img/icon_deletelink.gif) 0 50% no-repeat;
188 | padding-left: 14px;
189 | }
190 |
191 | /* CUSTOM FORM FIELDS */
192 |
193 | .vSelectMultipleField {
194 | vertical-align: top !important;
195 | }
196 |
197 | .vCheckboxField {
198 | border: none;
199 | }
200 |
201 | .vDateField, .vTimeField {
202 | margin-right: 2px;
203 | }
204 |
205 | .vURLField {
206 | width: 30em;
207 | }
208 |
209 | .vLargeTextField, .vXMLLargeTextField {
210 | width: 48em;
211 | }
212 |
213 | .flatpages-flatpage #id_content {
214 | height: 40.2em;
215 | }
216 |
217 | .module table .vPositiveSmallIntegerField {
218 | width: 2.2em;
219 | }
220 |
221 | .vTextField {
222 | width: 20em;
223 | }
224 |
225 | .vIntegerField {
226 | width: 5em;
227 | }
228 |
229 | .vForeignKeyRawIdAdminField {
230 | width: 5em;
231 | }
232 |
233 | /* INLINES */
234 |
235 | .inline-group {
236 | padding: 0;
237 | border: 1px solid #ccc;
238 | margin: 10px 0;
239 | }
240 |
241 | .inline-group .aligned label {
242 | width: 8em;
243 | }
244 |
245 | .inline-related {
246 | position: relative;
247 | }
248 |
249 | .inline-related h3 {
250 | margin: 0;
251 | color: #666;
252 | padding: 3px 5px;
253 | font-size: 11px;
254 | background: #e1e1e1 url(../img/nav-bg.gif) top left repeat-x;
255 | border-bottom: 1px solid #ddd;
256 | }
257 |
258 | .inline-related h3 span.delete {
259 | float: right;
260 | }
261 |
262 | .inline-related h3 span.delete label {
263 | margin-left: 2px;
264 | font-size: 11px;
265 | }
266 |
267 | .inline-related fieldset {
268 | margin: 0;
269 | background: #fff;
270 | border: none;
271 | }
272 |
273 | .inline-related fieldset.module h3 {
274 | margin: 0;
275 | padding: 2px 5px 3px 5px;
276 | font-size: 11px;
277 | text-align: left;
278 | font-weight: bold;
279 | background: #bcd;
280 | color: #fff;
281 | }
282 |
283 | .inline-group .tabular fieldset.module {
284 | border: none;
285 | border-bottom: 1px solid #ddd;
286 | }
287 |
288 | .inline-related.tabular fieldset.module table {
289 | width: 100%;
290 | }
291 |
292 | .last-related fieldset {
293 | border: none;
294 | }
295 |
296 | .inline-group .tabular tr.has_original td {
297 | padding-top: 2em;
298 | }
299 |
300 | .inline-group .tabular tr td.original {
301 | padding: 2px 0 0 0;
302 | width: 0;
303 | _position: relative;
304 | }
305 |
306 | .inline-group .tabular th.original {
307 | width: 0px;
308 | padding: 0;
309 | }
310 |
311 | .inline-group .tabular td.original p {
312 | position: absolute;
313 | left: 0;
314 | height: 1.1em;
315 | padding: 2px 7px;
316 | overflow: hidden;
317 | font-size: 9px;
318 | font-weight: bold;
319 | color: #666;
320 | _width: 700px;
321 | }
322 |
323 | .inline-group ul.tools {
324 | padding: 0;
325 | margin: 0;
326 | list-style: none;
327 | }
328 |
329 | .inline-group ul.tools li {
330 | display: inline;
331 | padding: 0 5px;
332 | }
333 |
334 | .inline-group div.add-row,
335 | .inline-group .tabular tr.add-row td {
336 | color: #666;
337 | padding: 3px 5px;
338 | border-bottom: 1px solid #ddd;
339 | background: #e1e1e1 url(../img/nav-bg.gif) top left repeat-x;
340 | }
341 |
342 | .inline-group .tabular tr.add-row td {
343 | padding: 4px 5px 3px;
344 | border-bottom: none;
345 | }
346 |
347 | .inline-group ul.tools a.add,
348 | .inline-group div.add-row a,
349 | .inline-group .tabular tr.add-row td a {
350 | background: url(../img/icon_addlink.gif) 0 50% no-repeat;
351 | padding-left: 14px;
352 | font-size: 11px;
353 | outline: 0; /* Remove dotted border around link */
354 | }
355 |
356 | .empty-form {
357 | display: none;
358 | }
359 |
--------------------------------------------------------------------------------
/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 | // quickElement(tagType, parentReference, textInChildNode, [, attribute, attributeValue ...]);
33 | function quickElement() {
34 | var obj = document.createElement(arguments[0]);
35 | if (arguments[2] != '' && arguments[2] != null) {
36 | var textNode = document.createTextNode(arguments[2]);
37 | obj.appendChild(textNode);
38 | }
39 | var len = arguments.length;
40 | for (var i = 3; i < len; i += 2) {
41 | obj.setAttribute(arguments[i], arguments[i+1]);
42 | }
43 | arguments[1].appendChild(obj);
44 | return obj;
45 | }
46 |
47 | // ----------------------------------------------------------------------------
48 | // Cross-browser xmlhttp object
49 | // from http://jibbering.com/2002/4/httprequest.html
50 | // ----------------------------------------------------------------------------
51 | var xmlhttp;
52 | /*@cc_on @*/
53 | /*@if (@_jscript_version >= 5)
54 | try {
55 | xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
56 | } catch (e) {
57 | try {
58 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
59 | } catch (E) {
60 | xmlhttp = false;
61 | }
62 | }
63 | @else
64 | xmlhttp = false;
65 | @end @*/
66 | if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
67 | xmlhttp = new XMLHttpRequest();
68 | }
69 |
70 | // ----------------------------------------------------------------------------
71 | // Find-position functions by PPK
72 | // See http://www.quirksmode.org/js/findpos.html
73 | // ----------------------------------------------------------------------------
74 | function findPosX(obj) {
75 | var curleft = 0;
76 | if (obj.offsetParent) {
77 | while (obj.offsetParent) {
78 | curleft += obj.offsetLeft - ((isOpera) ? 0 : obj.scrollLeft);
79 | obj = obj.offsetParent;
80 | }
81 | // IE offsetParent does not include the top-level
82 | if (isIE && obj.parentElement){
83 | curleft += obj.offsetLeft - obj.scrollLeft;
84 | }
85 | } else if (obj.x) {
86 | curleft += obj.x;
87 | }
88 | return curleft;
89 | }
90 |
91 | function findPosY(obj) {
92 | var curtop = 0;
93 | if (obj.offsetParent) {
94 | while (obj.offsetParent) {
95 | curtop += obj.offsetTop - ((isOpera) ? 0 : obj.scrollTop);
96 | obj = obj.offsetParent;
97 | }
98 | // IE offsetParent does not include the top-level
99 | if (isIE && obj.parentElement){
100 | curtop += obj.offsetTop - obj.scrollTop;
101 | }
102 | } else if (obj.y) {
103 | curtop += obj.y;
104 | }
105 | return curtop;
106 | }
107 |
108 | //-----------------------------------------------------------------------------
109 | // Date object extensions
110 | // ----------------------------------------------------------------------------
111 |
112 | Date.prototype.getTwelveHours = function() {
113 | hours = this.getHours();
114 | if (hours == 0) {
115 | return 12;
116 | }
117 | else {
118 | return hours <= 12 ? hours : hours-12
119 | }
120 | }
121 |
122 | Date.prototype.getTwoDigitMonth = function() {
123 | return (this.getMonth() < 9) ? '0' + (this.getMonth()+1) : (this.getMonth()+1);
124 | }
125 |
126 | Date.prototype.getTwoDigitDate = function() {
127 | return (this.getDate() < 10) ? '0' + this.getDate() : this.getDate();
128 | }
129 |
130 | Date.prototype.getTwoDigitTwelveHour = function() {
131 | return (this.getTwelveHours() < 10) ? '0' + this.getTwelveHours() : this.getTwelveHours();
132 | }
133 |
134 | Date.prototype.getTwoDigitHour = function() {
135 | return (this.getHours() < 10) ? '0' + this.getHours() : this.getHours();
136 | }
137 |
138 | Date.prototype.getTwoDigitMinute = function() {
139 | return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes();
140 | }
141 |
142 | Date.prototype.getTwoDigitSecond = function() {
143 | return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds();
144 | }
145 |
146 | Date.prototype.getHourMinute = function() {
147 | return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute();
148 | }
149 |
150 | Date.prototype.getHourMinuteSecond = function() {
151 | return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute() + ':' + this.getTwoDigitSecond();
152 | }
153 |
154 | Date.prototype.strftime = function(format) {
155 | var fields = {
156 | c: this.toString(),
157 | d: this.getTwoDigitDate(),
158 | H: this.getTwoDigitHour(),
159 | I: this.getTwoDigitTwelveHour(),
160 | m: this.getTwoDigitMonth(),
161 | M: this.getTwoDigitMinute(),
162 | p: (this.getHours() >= 12) ? 'PM' : 'AM',
163 | S: this.getTwoDigitSecond(),
164 | w: '0' + this.getDay(),
165 | x: this.toLocaleDateString(),
166 | X: this.toLocaleTimeString(),
167 | y: ('' + this.getFullYear()).substr(2, 4),
168 | Y: '' + this.getFullYear(),
169 | '%' : '%'
170 | };
171 | var result = '', i = 0;
172 | while (i < format.length) {
173 | if (format.charAt(i) === '%') {
174 | result = result + fields[format.charAt(i + 1)];
175 | ++i;
176 | }
177 | else {
178 | result = result + format.charAt(i);
179 | }
180 | ++i;
181 | }
182 | return result;
183 | }
184 |
185 | // ----------------------------------------------------------------------------
186 | // String object extensions
187 | // ----------------------------------------------------------------------------
188 | String.prototype.pad_left = function(pad_length, pad_string) {
189 | var new_string = this;
190 | for (var i = 0; new_string.length < pad_length; i++) {
191 | new_string = pad_string + new_string;
192 | }
193 | return new_string;
194 | }
195 |
196 | // ----------------------------------------------------------------------------
197 | // Get the computed style for and element
198 | // ----------------------------------------------------------------------------
199 | function getStyle(oElm, strCssRule){
200 | var strValue = "";
201 | if(document.defaultView && document.defaultView.getComputedStyle){
202 | strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
203 | }
204 | else if(oElm.currentStyle){
205 | strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
206 | return p1.toUpperCase();
207 | });
208 | strValue = oElm.currentStyle[strCssRule];
209 | }
210 | return strValue;
211 | }
212 |
--------------------------------------------------------------------------------
/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_media_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_media_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_media_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_media_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/css/widgets.css:
--------------------------------------------------------------------------------
1 | /* SELECTOR (FILTER INTERFACE) */
2 |
3 | .selector {
4 | width: 580px;
5 | float: left;
6 | }
7 |
8 | .selector select {
9 | width: 270px;
10 | height: 17.2em;
11 | }
12 |
13 | .selector-available, .selector-chosen {
14 | float: left;
15 | width: 270px;
16 | text-align: center;
17 | margin-bottom: 5px;
18 | }
19 |
20 | .selector-chosen select {
21 | border-top: none;
22 | }
23 |
24 | .selector-available h2, .selector-chosen h2 {
25 | border: 1px solid #ccc;
26 | }
27 |
28 | .selector .selector-available h2 {
29 | background: white url(../img/nav-bg.gif) bottom left repeat-x;
30 | color: #666;
31 | }
32 |
33 | .selector .selector-filter {
34 | background: white;
35 | border: 1px solid #ccc;
36 | border-width: 0 1px;
37 | padding: 3px;
38 | color: #999;
39 | font-size: 10px;
40 | margin: 0;
41 | text-align: left;
42 | }
43 |
44 | .selector .selector-filter label {
45 | width: 16px;
46 | padding: 2px;
47 | }
48 |
49 | .selector .selector-available input {
50 | width: 230px;
51 | }
52 |
53 | .selector ul.selector-chooser {
54 | float: left;
55 | width: 22px;
56 | height: 50px;
57 | background: url(../img/chooser-bg.gif) top center no-repeat;
58 | margin: 10em 5px 0 5px;
59 | padding: 0;
60 | }
61 |
62 | .selector-chooser li {
63 | margin: 0;
64 | padding: 3px;
65 | list-style-type: none;
66 | }
67 |
68 | .selector select {
69 | margin-bottom: 10px;
70 | margin-top: 0;
71 | }
72 |
73 | .selector-add, .selector-remove {
74 | width: 16px;
75 | height: 16px;
76 | display: block;
77 | text-indent: -3000px;
78 | overflow: hidden;
79 | }
80 |
81 | .selector-add {
82 | background: url(../img/selector-icons.gif) 0 -161px no-repeat;
83 | cursor: default;
84 | margin-bottom: 2px;
85 | }
86 |
87 | .active.selector-add {
88 | background: url(../img/selector-icons.gif) 0 -187px no-repeat;
89 | cursor: pointer;
90 | }
91 |
92 | .selector-remove {
93 | background: url(../img/selector-icons.gif) 0 -109px no-repeat;
94 | cursor: default;
95 | }
96 |
97 | .active.selector-remove {
98 | background: url(../img/selector-icons.gif) 0 -135px no-repeat;
99 | cursor: pointer;
100 | }
101 |
102 | a.selector-chooseall, a.selector-clearall {
103 | display: inline-block;
104 | text-align: left;
105 | margin-left: auto;
106 | margin-right: auto;
107 | font-weight: bold;
108 | color: #666;
109 | }
110 |
111 | a.selector-chooseall {
112 | padding: 3px 18px 3px 0;
113 | }
114 |
115 | a.selector-clearall {
116 | padding: 3px 0 3px 18px;
117 | }
118 |
119 | a.active.selector-chooseall:hover, a.active.selector-clearall:hover {
120 | color: #036;
121 | }
122 |
123 | a.selector-chooseall {
124 | background: url(../img/selector-icons.gif) right -263px no-repeat;
125 | cursor: default;
126 | }
127 |
128 | a.active.selector-chooseall {
129 | background: url(../img/selector-icons.gif) right -289px no-repeat;
130 | cursor: pointer;
131 | }
132 |
133 | a.selector-clearall {
134 | background: url(../img/selector-icons.gif) left -211px no-repeat;
135 | cursor: default;
136 | }
137 |
138 | a.active.selector-clearall {
139 | background: url(../img/selector-icons.gif) left -237px no-repeat;
140 | cursor: pointer;
141 | }
142 |
143 | /* STACKED SELECTORS */
144 |
145 | .stacked {
146 | float: left;
147 | width: 500px;
148 | }
149 |
150 | .stacked select {
151 | width: 480px;
152 | height: 10.1em;
153 | }
154 |
155 | .stacked .selector-available, .stacked .selector-chosen {
156 | width: 480px;
157 | }
158 |
159 | .stacked .selector-available {
160 | margin-bottom: 0;
161 | }
162 |
163 | .stacked .selector-available input {
164 | width: 442px;
165 | }
166 |
167 | .stacked ul.selector-chooser {
168 | height: 22px;
169 | width: 50px;
170 | margin: 0 0 3px 40%;
171 | background: url(../img/chooser_stacked-bg.gif) top center no-repeat;
172 | }
173 |
174 | .stacked .selector-chooser li {
175 | float: left;
176 | padding: 3px 3px 3px 5px;
177 | }
178 |
179 | .stacked .selector-chooseall, .stacked .selector-clearall {
180 | display: none;
181 | }
182 |
183 | .stacked .selector-add {
184 | background: url(../img/selector-icons.gif) 0 -57px no-repeat;
185 | cursor: default;
186 | }
187 |
188 | .stacked .active.selector-add {
189 | background: url(../img/selector-icons.gif) 0 -83px no-repeat;
190 | cursor: pointer;
191 | }
192 |
193 | .stacked .selector-remove {
194 | background: url(../img/selector-icons.gif) 0 -5px no-repeat;
195 | cursor: default;
196 | }
197 |
198 | .stacked .active.selector-remove {
199 | background: url(../img/selector-icons.gif) 0 -31px no-repeat;
200 | cursor: pointer;
201 | }
202 |
203 | /* DATE AND TIME */
204 |
205 | p.datetime {
206 | line-height: 20px;
207 | margin: 0;
208 | padding: 0;
209 | color: #666;
210 | font-size: 11px;
211 | font-weight: bold;
212 | }
213 |
214 | .datetime span {
215 | font-size: 11px;
216 | color: #ccc;
217 | font-weight: normal;
218 | white-space: nowrap;
219 | }
220 |
221 | table p.datetime {
222 | font-size: 10px;
223 | margin-left: 0;
224 | padding-left: 0;
225 | }
226 |
227 | /* FILE UPLOADS */
228 |
229 | p.file-upload {
230 | line-height: 20px;
231 | margin: 0;
232 | padding: 0;
233 | color: #666;
234 | font-size: 11px;
235 | font-weight: bold;
236 | }
237 |
238 | .file-upload a {
239 | font-weight: normal;
240 | }
241 |
242 | .file-upload .deletelink {
243 | margin-left: 5px;
244 | }
245 |
246 | span.clearable-file-input label {
247 | color: #333;
248 | font-size: 11px;
249 | display: inline;
250 | float: none;
251 | }
252 |
253 | /* CALENDARS & CLOCKS */
254 |
255 | .calendarbox, .clockbox {
256 | margin: 5px auto;
257 | font-size: 11px;
258 | width: 16em;
259 | text-align: center;
260 | background: white;
261 | position: relative;
262 | }
263 |
264 | .clockbox {
265 | width: auto;
266 | }
267 |
268 | .calendar {
269 | margin: 0;
270 | padding: 0;
271 | }
272 |
273 | .calendar table {
274 | margin: 0;
275 | padding: 0;
276 | border-collapse: collapse;
277 | background: white;
278 | width: 100%;
279 | }
280 |
281 | .calendar caption, .calendarbox h2 {
282 | margin: 0;
283 | font-size: 11px;
284 | text-align: center;
285 | border-top: none;
286 | }
287 |
288 | .calendar th {
289 | font-size: 10px;
290 | color: #666;
291 | padding: 2px 3px;
292 | text-align: center;
293 | background: #e1e1e1 url(../img/nav-bg.gif) 0 50% repeat-x;
294 | border-bottom: 1px solid #ddd;
295 | }
296 |
297 | .calendar td {
298 | font-size: 11px;
299 | text-align: center;
300 | padding: 0;
301 | border-top: 1px solid #eee;
302 | border-bottom: none;
303 | }
304 |
305 | .calendar td.selected a {
306 | background: #C9DBED;
307 | }
308 |
309 | .calendar td.nonday {
310 | background: #efefef;
311 | }
312 |
313 | .calendar td.today a {
314 | background: #ffc;
315 | }
316 |
317 | .calendar td a, .timelist a {
318 | display: block;
319 | font-weight: bold;
320 | padding: 4px;
321 | text-decoration: none;
322 | color: #444;
323 | }
324 |
325 | .calendar td a:hover, .timelist a:hover {
326 | background: #5b80b2;
327 | color: white;
328 | }
329 |
330 | .calendar td a:active, .timelist a:active {
331 | background: #036;
332 | color: white;
333 | }
334 |
335 | .calendarnav {
336 | font-size: 10px;
337 | text-align: center;
338 | color: #ccc;
339 | margin: 0;
340 | padding: 1px 3px;
341 | }
342 |
343 | .calendarnav a:link, #calendarnav a:visited, #calendarnav a:hover {
344 | color: #999;
345 | }
346 |
347 | .calendar-shortcuts {
348 | background: white;
349 | font-size: 10px;
350 | line-height: 11px;
351 | border-top: 1px solid #eee;
352 | padding: 3px 0 4px;
353 | color: #ccc;
354 | }
355 |
356 | .calendarbox .calendarnav-previous, .calendarbox .calendarnav-next {
357 | display: block;
358 | position: absolute;
359 | font-weight: bold;
360 | font-size: 12px;
361 | background: #C9DBED url(../img/default-bg.gif) bottom left repeat-x;
362 | padding: 1px 4px 2px 4px;
363 | color: white;
364 | }
365 |
366 | .calendarnav-previous:hover, .calendarnav-next:hover {
367 | background: #036;
368 | }
369 |
370 | .calendarnav-previous {
371 | top: 0;
372 | left: 0;
373 | }
374 |
375 | .calendarnav-next {
376 | top: 0;
377 | right: 0;
378 | }
379 |
380 | .calendar-cancel {
381 | margin: 0 !important;
382 | padding: 0 !important;
383 | font-size: 10px;
384 | background: #e1e1e1 url(../img/nav-bg.gif) 0 50% repeat-x;
385 | border-top: 1px solid #ddd;
386 | }
387 |
388 | .calendar-cancel:hover {
389 | background: #e1e1e1 url(../img/nav-bg-reverse.gif) 0 50% repeat-x;
390 | }
391 |
392 | .calendar-cancel a {
393 | color: black;
394 | display: block;
395 | }
396 |
397 | ul.timelist, .timelist li {
398 | list-style-type: none;
399 | margin: 0;
400 | padding: 0;
401 | }
402 |
403 | .timelist a {
404 | padding: 2px;
405 | }
406 |
407 | /* INLINE ORDERER */
408 |
409 | ul.orderer {
410 | position: relative;
411 | padding: 0 !important;
412 | margin: 0 !important;
413 | list-style-type: none;
414 | }
415 |
416 | ul.orderer li {
417 | list-style-type: none;
418 | display: block;
419 | padding: 0;
420 | margin: 0;
421 | border: 1px solid #bbb;
422 | border-width: 0 1px 1px 0;
423 | white-space: nowrap;
424 | overflow: hidden;
425 | background: #e2e2e2 url(../img/nav-bg-grabber.gif) repeat-y;
426 | }
427 |
428 | ul.orderer li:hover {
429 | cursor: move;
430 | background-color: #ddd;
431 | }
432 |
433 | ul.orderer li a.selector {
434 | margin-left: 12px;
435 | overflow: hidden;
436 | width: 83%;
437 | font-size: 10px !important;
438 | padding: 0.6em 0;
439 | }
440 |
441 | ul.orderer li a:link, ul.orderer li a:visited {
442 | color: #333;
443 | }
444 |
445 | ul.orderer li .inline-deletelink {
446 | position: absolute;
447 | right: 4px;
448 | margin-top: 0.6em;
449 | }
450 |
451 | ul.orderer li.selected {
452 | background-color: #f8f8f8;
453 | border-right-color: #f8f8f8;
454 | }
455 |
456 | ul.orderer li.deleted {
457 | background: #bbb url(../img/deleted-overlay.gif);
458 | }
459 |
460 | ul.orderer li.deleted a:link, ul.orderer li.deleted a:visited {
461 | color: #888;
462 | }
463 |
464 | ul.orderer li.deleted .inline-deletelink {
465 | background-image: url(../img/inline-restore.png);
466 | }
467 |
468 | ul.orderer li.deleted:hover, ul.orderer li.deleted a.selector:hover {
469 | cursor: default;
470 | }
471 |
472 | /* EDIT INLINE */
473 |
474 | .inline-deletelink {
475 | float: right;
476 | text-indent: -9999px;
477 | background: transparent url(../img/inline-delete.png) no-repeat;
478 | width: 15px;
479 | height: 15px;
480 | border: 0px none;
481 | outline: 0; /* Remove dotted border around link */
482 | }
483 |
484 | .inline-deletelink:hover {
485 | background-position: -15px 0;
486 | cursor: pointer;
487 | }
488 |
489 | .editinline button.addlink {
490 | border: 0px none;
491 | color: #5b80b2;
492 | font-size: 100%;
493 | cursor: pointer;
494 | }
495 |
496 | .editinline button.addlink:hover {
497 | color: #036;
498 | cursor: pointer;
499 | }
500 |
501 | .editinline table .help {
502 | text-align: right;
503 | float: right;
504 | padding-left: 2em;
505 | }
506 |
507 | .editinline tfoot .addlink {
508 | white-space: nowrap;
509 | }
510 |
511 | .editinline table thead th:last-child {
512 | border-left: none;
513 | }
514 |
515 | .editinline tr.deleted {
516 | background: #ddd url(../img/deleted-overlay.gif);
517 | }
518 |
519 | .editinline tr.deleted .inline-deletelink {
520 | background-image: url(../img/inline-restore.png);
521 | }
522 |
523 | .editinline tr.deleted td:hover {
524 | cursor: default;
525 | }
526 |
527 | .editinline tr.deleted td:first-child {
528 | background-image: none !important;
529 | }
530 |
531 | /* EDIT INLINE - STACKED */
532 |
533 | .editinline-stacked {
534 | min-width: 758px;
535 | }
536 |
537 | .editinline-stacked .inline-object {
538 | margin-left: 210px;
539 | background: white;
540 | }
541 |
542 | .editinline-stacked .inline-source {
543 | float: left;
544 | width: 200px;
545 | background: #f8f8f8;
546 | }
547 |
548 | .editinline-stacked .inline-splitter {
549 | float: left;
550 | width: 9px;
551 | background: #f8f8f8 url(../img/inline-splitter-bg.gif) 50% 50% no-repeat;
552 | border-right: 1px solid #ccc;
553 | }
554 |
555 | .editinline-stacked .controls {
556 | clear: both;
557 | background: #e1e1e1 url(../img/nav-bg.gif) top left repeat-x;
558 | padding: 3px 4px;
559 | font-size: 11px;
560 | border-top: 1px solid #ddd;
561 | }
562 |
563 |
--------------------------------------------------------------------------------
/static/admin/js/admin/DateTimeShortcuts.js:
--------------------------------------------------------------------------------
1 | // Inserts shortcut buttons after all of the following:
2 | //
3 | //
4 |
5 | var DateTimeShortcuts = {
6 | calendars: [],
7 | calendarInputs: [],
8 | clockInputs: [],
9 | calendarDivName1: 'calendarbox', // name of calendar
that gets toggled
10 | calendarDivName2: 'calendarin', // name of
that contains calendar
11 | calendarLinkName: 'calendarlink',// name of the link that is used to toggle
12 | clockDivName: 'clockbox', // name of clock
that gets toggled
13 | clockLinkName: 'clocklink', // name of the link that is used to toggle
14 | shortCutsClass: 'datetimeshortcuts', // class of the clock and cal shortcuts
15 | admin_media_prefix: '',
16 | init: function() {
17 | // Get admin_media_prefix by grabbing it off the window object. It's
18 | // set in the admin/base.html template, so if it's not there, someone's
19 | // overridden the template. In that case, we'll set a clearly-invalid
20 | // value in the hopes that someone will examine HTTP requests and see it.
21 | if (window.__admin_media_prefix__ != undefined) {
22 | DateTimeShortcuts.admin_media_prefix = window.__admin_media_prefix__;
23 | } else {
24 | DateTimeShortcuts.admin_media_prefix = '/missing-admin-media-prefix/';
25 | }
26 |
27 | var inputs = document.getElementsByTagName('input');
28 | for (i=0; i
63 | // Choose a time
64 | //
70 | // Cancel
71 | //
72 |
73 | var clock_box = document.createElement('div');
74 | clock_box.style.display = 'none';
75 | clock_box.style.position = 'absolute';
76 | clock_box.className = 'clockbox module';
77 | clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
78 | document.body.appendChild(clock_box);
79 | addEvent(clock_box, 'click', DateTimeShortcuts.cancelEventPropagation);
80 |
81 | quickElement('h2', clock_box, gettext('Choose a time'));
82 | var time_list = quickElement('ul', clock_box, '');
83 | time_list.className = 'timelist';
84 | var time_format = get_format('TIME_INPUT_FORMATS')[0];
85 | quickElement("a", quickElement("li", time_list, ""), gettext("Now"), "href", "javascript:DateTimeShortcuts.handleClockQuicklink(" + num + ", new Date().strftime('" + time_format + "'));");
86 | 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 + "'));");
87 | 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 + "'));");
88 | 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 + "'));");
89 |
90 | var cancel_p = quickElement('p', clock_box, '');
91 | cancel_p.className = 'calendar-cancel';
92 | quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
93 | django.jQuery(document).bind('keyup', function(event) {
94 | if (event.which == 27) {
95 | // ESC key closes popup
96 | DateTimeShortcuts.dismissClock(num);
97 | event.preventDefault();
98 | }
99 | });
100 | },
101 | openClock: function(num) {
102 | var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num)
103 | var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num)
104 |
105 | // Recalculate the clockbox position
106 | // is it left-to-right or right-to-left layout ?
107 | if (getStyle(document.body,'direction')!='rtl') {
108 | clock_box.style.left = findPosX(clock_link) + 17 + 'px';
109 | }
110 | else {
111 | // since style's width is in em, it'd be tough to calculate
112 | // px value of it. let's use an estimated px for now
113 | // TODO: IE returns wrong value for findPosX when in rtl mode
114 | // (it returns as it was left aligned), needs to be fixed.
115 | clock_box.style.left = findPosX(clock_link) - 110 + 'px';
116 | }
117 | clock_box.style.top = Math.max(0, findPosY(clock_link) - 30) + 'px';
118 |
119 | // Show the clock box
120 | clock_box.style.display = 'block';
121 | addEvent(window.document, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; });
122 | },
123 | dismissClock: function(num) {
124 | document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none';
125 | window.document.onclick = null;
126 | },
127 | handleClockQuicklink: function(num, val) {
128 | DateTimeShortcuts.clockInputs[num].value = val;
129 | DateTimeShortcuts.clockInputs[num].focus();
130 | DateTimeShortcuts.dismissClock(num);
131 | },
132 | // Add calendar widget to a given field.
133 | addCalendar: function(inp) {
134 | var num = DateTimeShortcuts.calendars.length;
135 |
136 | DateTimeShortcuts.calendarInputs[num] = inp;
137 |
138 | // Shortcut links (calendar icon and "Today" link)
139 | var shortcuts_span = document.createElement('span');
140 | shortcuts_span.className = DateTimeShortcuts.shortCutsClass;
141 | inp.parentNode.insertBefore(shortcuts_span, inp.nextSibling);
142 | var today_link = document.createElement('a');
143 | today_link.setAttribute('href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
144 | today_link.appendChild(document.createTextNode(gettext('Today')));
145 | var cal_link = document.createElement('a');
146 | cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
147 | cal_link.id = DateTimeShortcuts.calendarLinkName + num;
148 | quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/icon_calendar.gif', 'alt', gettext('Calendar'));
149 | shortcuts_span.appendChild(document.createTextNode('\240'));
150 | shortcuts_span.appendChild(today_link);
151 | shortcuts_span.appendChild(document.createTextNode('\240|\240'));
152 | shortcuts_span.appendChild(cal_link);
153 |
154 | // Create calendarbox div.
155 | //
156 | // Markup looks like:
157 | //
158 | //
159 | //
160 | // ‹
161 | // › February 2003
162 | //
163 | //
164 | //
165 | //
166 | //
169 | //
Cancel
170 | //
171 | var cal_box = document.createElement('div');
172 | cal_box.style.display = 'none';
173 | cal_box.style.position = 'absolute';
174 | cal_box.className = 'calendarbox module';
175 | cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
176 | document.body.appendChild(cal_box);
177 | addEvent(cal_box, 'click', DateTimeShortcuts.cancelEventPropagation);
178 |
179 | // next-prev links
180 | var cal_nav = quickElement('div', cal_box, '');
181 | var cal_nav_prev = quickElement('a', cal_nav, '<', 'href', 'javascript:DateTimeShortcuts.drawPrev('+num+');');
182 | cal_nav_prev.className = 'calendarnav-previous';
183 | var cal_nav_next = quickElement('a', cal_nav, '>', 'href', 'javascript:DateTimeShortcuts.drawNext('+num+');');
184 | cal_nav_next.className = 'calendarnav-next';
185 |
186 | // main box
187 | var cal_main = quickElement('div', cal_box, '', 'id', DateTimeShortcuts.calendarDivName2 + num);
188 | cal_main.className = 'calendar';
189 | DateTimeShortcuts.calendars[num] = new Calendar(DateTimeShortcuts.calendarDivName2 + num, DateTimeShortcuts.handleCalendarCallback(num));
190 | DateTimeShortcuts.calendars[num].drawCurrent();
191 |
192 | // calendar shortcuts
193 | var shortcuts = quickElement('div', cal_box, '');
194 | shortcuts.className = 'calendar-shortcuts';
195 | quickElement('a', shortcuts, gettext('Yesterday'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', -1);');
196 | shortcuts.appendChild(document.createTextNode('\240|\240'));
197 | quickElement('a', shortcuts, gettext('Today'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', 0);');
198 | shortcuts.appendChild(document.createTextNode('\240|\240'));
199 | quickElement('a', shortcuts, gettext('Tomorrow'), 'href', 'javascript:DateTimeShortcuts.handleCalendarQuickLink(' + num + ', +1);');
200 |
201 | // cancel bar
202 | var cancel_p = quickElement('p', cal_box, '');
203 | cancel_p.className = 'calendar-cancel';
204 | quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
205 | django.jQuery(document).bind('keyup', function(event) {
206 | if (event.which == 27) {
207 | // ESC key closes popup
208 | DateTimeShortcuts.dismissCalendar(num);
209 | event.preventDefault();
210 | }
211 | });
212 | },
213 | openCalendar: function(num) {
214 | var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
215 | var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
216 | var inp = DateTimeShortcuts.calendarInputs[num];
217 |
218 | // Determine if the current value in the input has a valid date.
219 | // If so, draw the calendar with that date's year and month.
220 | if (inp.value) {
221 | var date_parts = inp.value.split('-');
222 | var year = date_parts[0];
223 | var month = parseFloat(date_parts[1]);
224 | if (year.match(/\d\d\d\d/) && month >= 1 && month <= 12) {
225 | DateTimeShortcuts.calendars[num].drawDate(month, year);
226 | }
227 | }
228 |
229 | // Recalculate the clockbox position
230 | // is it left-to-right or right-to-left layout ?
231 | if (getStyle(document.body,'direction')!='rtl') {
232 | cal_box.style.left = findPosX(cal_link) + 17 + 'px';
233 | }
234 | else {
235 | // since style's width is in em, it'd be tough to calculate
236 | // px value of it. let's use an estimated px for now
237 | // TODO: IE returns wrong value for findPosX when in rtl mode
238 | // (it returns as it was left aligned), needs to be fixed.
239 | cal_box.style.left = findPosX(cal_link) - 180 + 'px';
240 | }
241 | cal_box.style.top = Math.max(0, findPosY(cal_link) - 75) + 'px';
242 |
243 | cal_box.style.display = 'block';
244 | addEvent(window.document, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; });
245 | },
246 | dismissCalendar: function(num) {
247 | document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'none';
248 | window.document.onclick = null;
249 | },
250 | drawPrev: function(num) {
251 | DateTimeShortcuts.calendars[num].drawPreviousMonth();
252 | },
253 | drawNext: function(num) {
254 | DateTimeShortcuts.calendars[num].drawNextMonth();
255 | },
256 | handleCalendarCallback: function(num) {
257 | format = get_format('DATE_INPUT_FORMATS')[0];
258 | // the format needs to be escaped a little
259 | format = format.replace('\\', '\\\\');
260 | format = format.replace('\r', '\\r');
261 | format = format.replace('\n', '\\n');
262 | format = format.replace('\t', '\\t');
263 | format = format.replace("'", "\\'");
264 | return ["function(y, m, d) { DateTimeShortcuts.calendarInputs[",
265 | num,
266 | "].value = new Date(y, m-1, d).strftime('",
267 | format,
268 | "');DateTimeShortcuts.calendarInputs[",
269 | num,
270 | "].focus();document.getElementById(DateTimeShortcuts.calendarDivName1+",
271 | num,
272 | ").style.display='none';}"].join('');
273 | },
274 | handleCalendarQuickLink: function(num, offset) {
275 | var d = new Date();
276 | d.setDate(d.getDate() + offset)
277 | DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]);
278 | DateTimeShortcuts.calendarInputs[num].focus();
279 | DateTimeShortcuts.dismissCalendar(num);
280 | },
281 | cancelEventPropagation: function(e) {
282 | if (!e) e = window.event;
283 | e.cancelBubble = true;
284 | if (e.stopPropagation) e.stopPropagation();
285 | }
286 | }
287 |
288 | addEvent(window, 'load', DateTimeShortcuts.init);
289 |
--------------------------------------------------------------------------------
/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 | table thead th .text span {
326 | padding: 2px 5px;
327 | display:block;
328 | }
329 |
330 | table thead th .text a {
331 | display: block;
332 | cursor: pointer;
333 | padding: 2px 5px;
334 | }
335 |
336 | table thead th.sortable:hover {
337 | background: white url(../img/nav-bg-reverse.gif) 0 -5px repeat-x;
338 | }
339 |
340 | thead th.sorted a.sortremove {
341 | visibility: hidden;
342 | }
343 |
344 | table thead th.sorted:hover a.sortremove {
345 | visibility: visible;
346 | }
347 |
348 | table thead th.sorted .sortoptions {
349 | display: block;
350 | padding: 4px 5px 0 5px;
351 | float: right;
352 | text-align: right;
353 | }
354 |
355 | table thead th.sorted .sortpriority {
356 | font-size: .8em;
357 | min-width: 12px;
358 | text-align: center;
359 | vertical-align: top;
360 | }
361 |
362 | table thead th.sorted .sortoptions a {
363 | width: 14px;
364 | height: 12px;
365 | display: inline-block;
366 | }
367 |
368 | table thead th.sorted .sortoptions a.sortremove {
369 | background: url(../img/sorting-icons.gif) -4px -5px no-repeat;
370 | }
371 |
372 | table thead th.sorted .sortoptions a.sortremove:hover {
373 | background: url(../img/sorting-icons.gif) -4px -27px no-repeat;
374 | }
375 |
376 | table thead th.sorted .sortoptions a.ascending {
377 | background: url(../img/sorting-icons.gif) -5px -50px no-repeat;
378 | }
379 |
380 | table thead th.sorted .sortoptions a.ascending:hover {
381 | background: url(../img/sorting-icons.gif) -5px -72px no-repeat;
382 | }
383 |
384 | table thead th.sorted .sortoptions a.descending {
385 | background: url(../img/sorting-icons.gif) -5px -94px no-repeat;
386 | }
387 |
388 | table thead th.sorted .sortoptions a.descending:hover {
389 | background: url(../img/sorting-icons.gif) -5px -115px no-repeat;
390 | }
391 |
392 | /* ORDERABLE TABLES */
393 |
394 | table.orderable tbody tr td:hover {
395 | cursor: move;
396 | }
397 |
398 | table.orderable tbody tr td:first-child {
399 | padding-left: 14px;
400 | background-image: url(../img/nav-bg-grabber.gif);
401 | background-repeat: repeat-y;
402 | }
403 |
404 | table.orderable-initalized .order-cell, body>tr>td.order-cell {
405 | display: none;
406 | }
407 |
408 | /* FORM DEFAULTS */
409 |
410 | input, textarea, select, .form-row p {
411 | margin: 2px 0;
412 | padding: 2px 3px;
413 | vertical-align: middle;
414 | font-family: "Lucida Grande", Verdana, Arial, sans-serif;
415 | font-weight: normal;
416 | font-size: 11px;
417 | }
418 |
419 | textarea {
420 | vertical-align: top !important;
421 | }
422 |
423 | input[type=text], input[type=password], textarea, select, .vTextField {
424 | border: 1px solid #ccc;
425 | }
426 |
427 | /* FORM BUTTONS */
428 |
429 | .button, input[type=submit], input[type=button], .submit-row input {
430 | background: white url(../img/nav-bg.gif) bottom repeat-x;
431 | padding: 3px 5px;
432 | color: black;
433 | border: 1px solid #bbb;
434 | border-color: #ddd #aaa #aaa #ddd;
435 | }
436 |
437 | .button:active, input[type=submit]:active, input[type=button]:active {
438 | background-image: url(../img/nav-bg-reverse.gif);
439 | background-position: top;
440 | }
441 |
442 | .button[disabled], input[type=submit][disabled], input[type=button][disabled] {
443 | background-image: url(../img/nav-bg.gif);
444 | background-position: bottom;
445 | opacity: 0.4;
446 | }
447 |
448 | .button.default, input[type=submit].default, .submit-row input.default {
449 | border: 2px solid #5b80b2;
450 | background: #7CA0C7 url(../img/default-bg.gif) bottom repeat-x;
451 | font-weight: bold;
452 | color: white;
453 | float: right;
454 | }
455 |
456 | .button.default:active, input[type=submit].default:active {
457 | background-image: url(../img/default-bg-reverse.gif);
458 | background-position: top;
459 | }
460 |
461 | .button[disabled].default, input[type=submit][disabled].default, input[type=button][disabled].default {
462 | background-image: url(../img/default-bg.gif);
463 | background-position: bottom;
464 | opacity: 0.4;
465 | }
466 |
467 |
468 | /* MODULES */
469 |
470 | .module {
471 | border: 1px solid #ccc;
472 | margin-bottom: 5px;
473 | background: white;
474 | }
475 |
476 | .module p, .module ul, .module h3, .module h4, .module dl, .module pre {
477 | padding-left: 10px;
478 | padding-right: 10px;
479 | }
480 |
481 | .module blockquote {
482 | margin-left: 12px;
483 | }
484 |
485 | .module ul, .module ol {
486 | margin-left: 1.5em;
487 | }
488 |
489 | .module h3 {
490 | margin-top: .6em;
491 | }
492 |
493 | .module h2, .module caption, .inline-group h2 {
494 | margin: 0;
495 | padding: 2px 5px 3px 5px;
496 | font-size: 11px;
497 | text-align: left;
498 | font-weight: bold;
499 | background: #7CA0C7 url(../img/default-bg.gif) top left repeat-x;
500 | color: white;
501 | }
502 |
503 | .module table {
504 | border-collapse: collapse;
505 | }
506 |
507 | /* MESSAGES & ERRORS */
508 |
509 | ul.messagelist {
510 | padding: 0 0 5px 0;
511 | margin: 0;
512 | }
513 |
514 | ul.messagelist li {
515 | font-size: 12px;
516 | display: block;
517 | padding: 4px 5px 4px 25px;
518 | margin: 0 0 3px 0;
519 | border-bottom: 1px solid #ddd;
520 | color: #666;
521 | background: #ffc url(../img/icon_success.gif) 5px .3em no-repeat;
522 | }
523 |
524 | ul.messagelist li.warning{
525 | background-image: url(../img/icon_alert.gif);
526 | }
527 |
528 | ul.messagelist li.error{
529 | background-image: url(../img/icon_error.gif);
530 | }
531 |
532 | .errornote {
533 | font-size: 12px !important;
534 | display: block;
535 | padding: 4px 5px 4px 25px;
536 | margin: 0 0 3px 0;
537 | border: 1px solid red;
538 | color: red;
539 | background: #ffc url(../img/icon_error.gif) 5px .3em no-repeat;
540 | }
541 |
542 | ul.errorlist {
543 | margin: 0 !important;
544 | padding: 0 !important;
545 | }
546 |
547 | .errorlist li {
548 | font-size: 12px !important;
549 | display: block;
550 | padding: 4px 5px 4px 25px;
551 | margin: 0 0 3px 0;
552 | border: 1px solid red;
553 | color: white;
554 | background: red url(../img/icon_alert.gif) 5px .3em no-repeat;
555 | }
556 |
557 | .errorlist li a {
558 | color: white;
559 | text-decoration: underline;
560 | }
561 |
562 | td ul.errorlist {
563 | margin: 0 !important;
564 | padding: 0 !important;
565 | }
566 |
567 | td ul.errorlist li {
568 | margin: 0 !important;
569 | }
570 |
571 | .errors {
572 | background: #ffc;
573 | }
574 |
575 | .errors input, .errors select, .errors textarea {
576 | border: 1px solid red;
577 | }
578 |
579 | div.system-message {
580 | background: #ffc;
581 | margin: 10px;
582 | padding: 6px 8px;
583 | font-size: .8em;
584 | }
585 |
586 | div.system-message p.system-message-title {
587 | padding: 4px 5px 4px 25px;
588 | margin: 0;
589 | color: red;
590 | background: #ffc url(../img/icon_error.gif) 5px .3em no-repeat;
591 | }
592 |
593 | .description {
594 | font-size: 12px;
595 | padding: 5px 0 0 12px;
596 | }
597 |
598 | /* BREADCRUMBS */
599 |
600 | div.breadcrumbs {
601 | background: white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x;
602 | padding: 2px 8px 3px 8px;
603 | font-size: 11px;
604 | color: #999;
605 | border-top: 1px solid white;
606 | border-bottom: 1px solid #ccc;
607 | text-align: left;
608 | }
609 |
610 | /* ACTION ICONS */
611 |
612 | .addlink {
613 | padding-left: 12px;
614 | background: url(../img/icon_addlink.gif) 0 .2em no-repeat;
615 | }
616 |
617 | .changelink {
618 | padding-left: 12px;
619 | background: url(../img/icon_changelink.gif) 0 .2em no-repeat;
620 | }
621 |
622 | .deletelink {
623 | padding-left: 12px;
624 | background: url(../img/icon_deletelink.gif) 0 .25em no-repeat;
625 | }
626 |
627 | a.deletelink:link, a.deletelink:visited {
628 | color: #CC3434;
629 | }
630 |
631 | a.deletelink:hover {
632 | color: #993333;
633 | }
634 |
635 | /* OBJECT TOOLS */
636 |
637 | .object-tools {
638 | font-size: 10px;
639 | font-weight: bold;
640 | font-family: Arial,Helvetica,sans-serif;
641 | padding-left: 0;
642 | float: right;
643 | position: relative;
644 | margin-top: -2.4em;
645 | margin-bottom: -2em;
646 | }
647 |
648 | .form-row .object-tools {
649 | margin-top: 5px;
650 | margin-bottom: 5px;
651 | float: none;
652 | height: 2em;
653 | padding-left: 3.5em;
654 | }
655 |
656 | .object-tools li {
657 | display: block;
658 | float: left;
659 | background: url(../img/tool-left.gif) 0 0 no-repeat;
660 | padding: 0 0 0 8px;
661 | margin-left: 2px;
662 | height: 16px;
663 | }
664 |
665 | .object-tools li:hover {
666 | background: url(../img/tool-left_over.gif) 0 0 no-repeat;
667 | }
668 |
669 | .object-tools a:link, .object-tools a:visited {
670 | display: block;
671 | float: left;
672 | color: white;
673 | padding: .1em 14px .1em 8px;
674 | height: 14px;
675 | background: #999 url(../img/tool-right.gif) 100% 0 no-repeat;
676 | }
677 |
678 | .object-tools a:hover, .object-tools li:hover a {
679 | background: #5b80b2 url(../img/tool-right_over.gif) 100% 0 no-repeat;
680 | }
681 |
682 | .object-tools a.viewsitelink, .object-tools a.golink {
683 | background: #999 url(../img/tooltag-arrowright.gif) top right no-repeat;
684 | padding-right: 28px;
685 | }
686 |
687 | .object-tools a.viewsitelink:hover, .object-tools a.golink:hover {
688 | background: #5b80b2 url(../img/tooltag-arrowright_over.gif) top right no-repeat;
689 | }
690 |
691 | .object-tools a.addlink {
692 | background: #999 url(../img/tooltag-add.gif) top right no-repeat;
693 | padding-right: 28px;
694 | }
695 |
696 | .object-tools a.addlink:hover {
697 | background: #5b80b2 url(../img/tooltag-add_over.gif) top right no-repeat;
698 | }
699 |
700 | /* OBJECT HISTORY */
701 |
702 | table#change-history {
703 | width: 100%;
704 | }
705 |
706 | table#change-history tbody th {
707 | width: 16em;
708 | }
709 |
710 | /* PAGE STRUCTURE */
711 |
712 | #container {
713 | position: relative;
714 | width: 100%;
715 | min-width: 760px;
716 | padding: 0;
717 | }
718 |
719 | #content {
720 | margin: 10px 15px;
721 | }
722 |
723 | #header {
724 | width: 100%;
725 | }
726 |
727 | #content-main {
728 | float: left;
729 | width: 100%;
730 | }
731 |
732 | #content-related {
733 | float: right;
734 | width: 18em;
735 | position: relative;
736 | margin-right: -19em;
737 | }
738 |
739 | #footer {
740 | clear: both;
741 | padding: 10px;
742 | }
743 |
744 | /* COLUMN TYPES */
745 |
746 | .colMS {
747 | margin-right: 20em !important;
748 | }
749 |
750 | .colSM {
751 | margin-left: 20em !important;
752 | }
753 |
754 | .colSM #content-related {
755 | float: left;
756 | margin-right: 0;
757 | margin-left: -19em;
758 | }
759 |
760 | .colSM #content-main {
761 | float: right;
762 | }
763 |
764 | .popup .colM {
765 | width: 95%;
766 | }
767 |
768 | .subcol {
769 | float: left;
770 | width: 46%;
771 | margin-right: 15px;
772 | }
773 |
774 | .dashboard #content {
775 | width: 500px;
776 | }
777 |
778 | /* HEADER */
779 |
780 | #header {
781 | background: #417690;
782 | color: #ffc;
783 | overflow: hidden;
784 | }
785 |
786 | #header a:link, #header a:visited {
787 | color: white;
788 | }
789 |
790 | #header a:hover {
791 | text-decoration: underline;
792 | }
793 |
794 | #branding h1 {
795 | padding: 0 10px;
796 | font-size: 18px;
797 | margin: 8px 0;
798 | font-weight: normal;
799 | color: #f4f379;
800 | }
801 |
802 | #branding h2 {
803 | padding: 0 10px;
804 | font-size: 14px;
805 | margin: -8px 0 8px 0;
806 | font-weight: normal;
807 | color: #ffc;
808 | }
809 |
810 | #user-tools {
811 | position: absolute;
812 | top: 0;
813 | right: 0;
814 | padding: 1.2em 10px;
815 | font-size: 11px;
816 | text-align: right;
817 | }
818 |
819 | /* SIDEBAR */
820 |
821 | #content-related h3 {
822 | font-size: 12px;
823 | color: #666;
824 | margin-bottom: 3px;
825 | }
826 |
827 | #content-related h4 {
828 | font-size: 11px;
829 | }
830 |
831 | #content-related .module h2 {
832 | background: #eee url(../img/nav-bg.gif) bottom left repeat-x;
833 | color: #666;
834 | }
835 |
836 |
--------------------------------------------------------------------------------