summaryrefslogtreecommitdiff
path: root/media/admin_media/js
diff options
context:
space:
mode:
Diffstat (limited to 'media/admin_media/js')
-rw-r--r--media/admin_media/js/SelectBox.js12
-rw-r--r--media/admin_media/js/SelectFilter2.js2
-rw-r--r--media/admin_media/js/admin/CollapsedFieldsets.js2
-rw-r--r--media/admin_media/js/admin/DateTimeShortcuts.js15
-rw-r--r--media/admin_media/js/admin/RelatedObjectLookups.js51
-rw-r--r--media/admin_media/js/core.js16
-rw-r--r--media/admin_media/js/urlify.js125
7 files changed, 205 insertions, 18 deletions
diff --git a/media/admin_media/js/SelectBox.js b/media/admin_media/js/SelectBox.js
index af8de204..f28c8615 100644
--- a/media/admin_media/js/SelectBox.js
+++ b/media/admin_media/js/SelectBox.js
@@ -6,7 +6,7 @@ var SelectBox = {
SelectBox.cache[id] = new Array();
var cache = SelectBox.cache[id];
for (var i = 0; (node = box.options[i]); i++) {
- cache.push({ value: node.value, text: node.text, displayed: 1 });
+ cache.push({value: node.value, text: node.text, displayed: 1});
}
},
redisplay: function(id) {
@@ -50,7 +50,7 @@ var SelectBox = {
SelectBox.cache[id].length--;
},
add_to_cache: function(id, option) {
- SelectBox.cache[id].push({ value: option.value, text: option.text, displayed: 1 });
+ SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1});
},
cache_contains: function(id, value) {
// Check if an item is contained in the cache
@@ -68,7 +68,7 @@ var SelectBox = {
var option;
for (var i = 0; (option = from_box.options[i]); i++) {
if (option.selected && SelectBox.cache_contains(from, option.value)) {
- SelectBox.add_to_cache(to, { value: option.value, text: option.text, displayed: 1 });
+ SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1});
SelectBox.delete_from_cache(from, option.value);
}
}
@@ -80,8 +80,10 @@ var SelectBox = {
var to_box = document.getElementById(to);
var option;
for (var i = 0; (option = from_box.options[i]); i++) {
- SelectBox.add_to_cache(to, { value: option.value, text: option.text, displayed: 1 });
- SelectBox.delete_from_cache(from, option.value);
+ if (SelectBox.cache_contains(from, option.value)) {
+ SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1});
+ SelectBox.delete_from_cache(from, option.value);
+ }
}
SelectBox.redisplay(from);
SelectBox.redisplay(to);
diff --git a/media/admin_media/js/SelectFilter2.js b/media/admin_media/js/SelectFilter2.js
index 8f6079e0..db946a6f 100644
--- a/media/admin_media/js/SelectFilter2.js
+++ b/media/admin_media/js/SelectFilter2.js
@@ -58,7 +58,7 @@ var SelectFilter = {
quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s'), [field_name]));
var selector_filter = quickElement('p', selector_chosen, gettext('Select your choice(s) and click '));
selector_filter.className = 'selector-filter';
- quickElement('img', selector_filter, '', 'src', admin_media_prefix + 'img/admin/selector-add.gif', 'alt', 'Add');
+ quickElement('img', selector_filter, '', 'src', admin_media_prefix + (is_stacked ? 'img/admin/selector_stacked-add.gif':'img/admin/selector-add.gif'), 'alt', 'Add');
var to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', 'multiple', 'size', from_box.size, 'name', from_box.getAttribute('name'));
to_box.className = 'filtered';
var clear_all = quickElement('a', selector_chosen, gettext('Clear all'), 'href', 'javascript: (function() { SelectBox.move_all("' + field_id + '_to", "' + field_id + '_from");})()');
diff --git a/media/admin_media/js/admin/CollapsedFieldsets.js b/media/admin_media/js/admin/CollapsedFieldsets.js
index c8426db2..d66bec0d 100644
--- a/media/admin_media/js/admin/CollapsedFieldsets.js
+++ b/media/admin_media/js/admin/CollapsedFieldsets.js
@@ -47,7 +47,7 @@ var CollapsedFieldsets = {
// Returns true if any fields in the fieldset have validation errors.
var divs = fs.getElementsByTagName('div');
for (var i=0; i<divs.length; i++) {
- if (divs[i].className.match(/\berror\b/)) {
+ if (divs[i].className.match(/\berrors\b/)) {
return true;
}
}
diff --git a/media/admin_media/js/admin/DateTimeShortcuts.js b/media/admin_media/js/admin/DateTimeShortcuts.js
index b1504fc8..f57f97e7 100644
--- a/media/admin_media/js/admin/DateTimeShortcuts.js
+++ b/media/admin_media/js/admin/DateTimeShortcuts.js
@@ -195,6 +195,19 @@ var DateTimeShortcuts = {
openCalendar: function(num) {
var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
+ var inp = DateTimeShortcuts.calendarInputs[num];
+
+ // Determine if the current value in the input has a valid date.
+ // If so, draw the calendar with that date's year and month.
+ if (inp.value) {
+ var date_parts = inp.value.split('-');
+ var year = date_parts[0];
+ var month = parseFloat(date_parts[1]);
+ if (year.match(/\d\d\d\d/) && month >= 1 && month <= 12) {
+ DateTimeShortcuts.calendars[num].drawDate(month, year);
+ }
+ }
+
// Recalculate the clockbox position
// is it left-to-right or right-to-left layout ?
@@ -223,7 +236,7 @@ var DateTimeShortcuts = {
DateTimeShortcuts.calendars[num].drawNextMonth();
},
handleCalendarCallback: function(num) {
- return "function(y, m, d) { DateTimeShortcuts.calendarInputs["+num+"].value = y+'-'+m+'-'+d; document.getElementById(DateTimeShortcuts.calendarDivName1+"+num+").style.display='none';}";
+ return "function(y, m, d) { DateTimeShortcuts.calendarInputs["+num+"].value = y+'-'+(m<10?'0':'')+m+'-'+(d<10?'0':'')+d; document.getElementById(DateTimeShortcuts.calendarDivName1+"+num+").style.display='none';}";
},
handleCalendarQuickLink: function(num, offset) {
var d = new Date();
diff --git a/media/admin_media/js/admin/RelatedObjectLookups.js b/media/admin_media/js/admin/RelatedObjectLookups.js
index db4ed1a9..d201f390 100644
--- a/media/admin_media/js/admin/RelatedObjectLookups.js
+++ b/media/admin_media/js/admin/RelatedObjectLookups.js
@@ -1,10 +1,35 @@
-// Handles related-objects functionality: lookup link for raw_id_admin=True
+// Handles related-objects functionality: lookup link for raw_id_fields
// and Add Another links.
+function html_unescape(text) {
+ // Unescape a string that was escaped using django.utils.html.escape.
+ text = text.replace(/&lt;/g, '<');
+ text = text.replace(/&gt;/g, '>');
+ text = text.replace(/&quot;/g, '"');
+ text = text.replace(/&#39;/g, "'");
+ text = text.replace(/&amp;/g, '&');
+ return text;
+}
+
+// IE doesn't accept periods or dashes in the window name, but the element IDs
+// we use to generate popup window names may contain them, therefore we map them
+// to allowed characters in a reversible way so that we can locate the correct
+// element when the popup window is dismissed.
+function id_to_windowname(text) {
+ text = text.replace(/\./g, '__dot__');
+ text = text.replace(/\-/g, '__dash__');
+ return text;
+}
+
+function windowname_to_id(text) {
+ text = text.replace(/__dot__/g, '.');
+ text = text.replace(/__dash__/g, '-');
+ return text;
+}
+
function showRelatedObjectLookupPopup(triggeringLink) {
var name = triggeringLink.id.replace(/^lookup_/, '');
- // IE doesn't like periods in the window name, so convert temporarily.
- name = name.replace(/\./g, '___');
+ name = id_to_windowname(name);
var href;
if (triggeringLink.href.search(/\?/) >= 0) {
href = triggeringLink.href + '&pop=1';
@@ -17,9 +42,9 @@ function showRelatedObjectLookupPopup(triggeringLink) {
}
function dismissRelatedLookupPopup(win, chosenId) {
- var name = win.name.replace(/___/g, '.');
+ var name = windowname_to_id(win.name);
var elem = document.getElementById(name);
- if (elem.className.indexOf('vRawIdAdminField') != -1 && elem.value) {
+ if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) {
elem.value += ',' + chosenId;
} else {
document.getElementById(name).value = chosenId;
@@ -29,14 +54,24 @@ function dismissRelatedLookupPopup(win, chosenId) {
function showAddAnotherPopup(triggeringLink) {
var name = triggeringLink.id.replace(/^add_/, '');
- name = name.replace(/\./g, '___');
- var win = window.open(triggeringLink.href + '?_popup=1', name, 'height=500,width=800,resizable=yes,scrollbars=yes');
+ name = id_to_windowname(name);
+ href = triggeringLink.href
+ if (href.indexOf('?') == -1) {
+ href += '?_popup=1';
+ } else {
+ href += '&_popup=1';
+ }
+ var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
return false;
}
function dismissAddAnotherPopup(win, newId, newRepr) {
- var name = win.name.replace(/___/g, '.');
+ // newId and newRepr are expected to have previously been escaped by
+ // django.utils.html.escape.
+ newId = html_unescape(newId);
+ newRepr = html_unescape(newRepr);
+ var name = windowname_to_id(win.name);
var elem = document.getElementById(name);
if (elem) {
if (elem.nodeName == 'SELECT') {
diff --git a/media/admin_media/js/core.js b/media/admin_media/js/core.js
index a17ac8a4..c8d0db6a 100644
--- a/media/admin_media/js/core.js
+++ b/media/admin_media/js/core.js
@@ -1,5 +1,9 @@
// Core javascript helper functions
+// basic browser identification & version
+var isOpera = (navigator.userAgent.indexOf("Opera")>=0) && parseFloat(navigator.appVersion);
+var isIE = ((document.all) && (!isOpera)) && parseFloat(navigator.appVersion.split("MSIE ")[1].split(";")[0]);
+
// Cross-browser event handlers.
function addEvent(obj, evType, fn) {
if (obj.addEventListener) {
@@ -71,9 +75,13 @@ function findPosX(obj) {
var curleft = 0;
if (obj.offsetParent) {
while (obj.offsetParent) {
- curleft += obj.offsetLeft;
+ curleft += obj.offsetLeft - ((isOpera) ? 0 : obj.scrollLeft);
obj = obj.offsetParent;
}
+ // IE offsetParent does not include the top-level
+ if (isIE && obj.parentElement){
+ curleft += obj.offsetLeft - obj.scrollLeft;
+ }
} else if (obj.x) {
curleft += obj.x;
}
@@ -84,9 +92,13 @@ function findPosY(obj) {
var curtop = 0;
if (obj.offsetParent) {
while (obj.offsetParent) {
- curtop += obj.offsetTop;
+ curtop += obj.offsetTop - ((isOpera) ? 0 : obj.scrollTop);
obj = obj.offsetParent;
}
+ // IE offsetParent does not include the top-level
+ if (isIE && obj.parentElement){
+ curtop += obj.offsetTop - obj.scrollTop;
+ }
} else if (obj.y) {
curtop += obj.y;
}
diff --git a/media/admin_media/js/urlify.js b/media/admin_media/js/urlify.js
index 9b871136..d8f2549e 100644
--- a/media/admin_media/js/urlify.js
+++ b/media/admin_media/js/urlify.js
@@ -1,15 +1,140 @@
+var LATIN_MAP = {
+ 'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 'Ç':
+ 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 'Î': 'I',
+ 'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 'Õ': 'O', 'Ö':
+ 'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ű': 'U',
+ 'Ý': 'Y', 'Þ': 'TH', 'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã': 'a', 'ä':
+ 'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e',
+ 'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó':
+ 'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u',
+ 'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
+}
+var LATIN_SYMBOLS_MAP = {
+ '©':'(c)'
+}
+var GREEK_MAP = {
+ 'α':'a', 'β':'b', 'γ':'g', 'δ':'d', 'ε':'e', 'ζ':'z', 'η':'h', 'θ':'8',
+ 'ι':'i', 'κ':'k', 'λ':'l', 'μ':'m', 'ν':'n', 'ξ':'3', 'ο':'o', 'π':'p',
+ 'ρ':'r', 'σ':'s', 'τ':'t', 'υ':'y', 'φ':'f', 'χ':'x', 'ψ':'ps', 'ω':'w',
+ 'ά':'a', 'έ':'e', 'ί':'i', 'ό':'o', 'ύ':'y', 'ή':'h', 'ώ':'w', 'ς':'s',
+ 'ϊ':'i', 'ΰ':'y', 'ϋ':'y', 'ΐ':'i',
+ 'Α':'A', 'Β':'B', 'Γ':'G', 'Δ':'D', 'Ε':'E', 'Ζ':'Z', 'Η':'H', 'Θ':'8',
+ 'Ι':'I', 'Κ':'K', 'Λ':'L', 'Μ':'M', 'Ν':'N', 'Ξ':'3', 'Ο':'O', 'Π':'P',
+ 'Ρ':'R', 'Σ':'S', 'Τ':'T', 'Υ':'Y', 'Φ':'F', 'Χ':'X', 'Ψ':'PS', 'Ω':'W',
+ 'Ά':'A', 'Έ':'E', 'Ί':'I', 'Ό':'O', 'Ύ':'Y', 'Ή':'H', 'Ώ':'W', 'Ϊ':'I',
+ 'Ϋ':'Y'
+}
+var TURKISH_MAP = {
+ 'ş':'s', 'Ş':'S', 'ı':'i', 'İ':'I', 'ç':'c', 'Ç':'C', 'ü':'u', 'Ü':'U',
+ 'ö':'o', 'Ö':'O', 'ğ':'g', 'Ğ':'G'
+}
+var RUSSIAN_MAP = {
+ 'а':'a', 'б':'b', 'в':'v', 'г':'g', 'д':'d', 'е':'e', 'ё':'yo', 'ж':'zh',
+ 'з':'z', 'и':'i', 'й':'j', 'к':'k', 'л':'l', 'м':'m', 'н':'n', 'о':'o',
+ 'п':'p', 'р':'r', 'с':'s', 'т':'t', 'у':'u', 'ф':'f', 'х':'h', 'ц':'c',
+ 'ч':'ch', 'ш':'sh', 'щ':'sh', 'ъ':'', 'ы':'y', 'ь':'', 'э':'e', 'ю':'yu',
+ 'я':'ya',
+ 'А':'A', 'Б':'B', 'В':'V', 'Г':'G', 'Д':'D', 'Е':'E', 'Ё':'Yo', 'Ж':'Zh',
+ 'З':'Z', 'И':'I', 'Й':'J', 'К':'K', 'Л':'L', 'М':'M', 'Н':'N', 'О':'O',
+ 'П':'P', 'Р':'R', 'С':'S', 'Т':'T', 'У':'U', 'Ф':'F', 'Х':'H', 'Ц':'C',
+ 'Ч':'Ch', 'Ш':'Sh', 'Щ':'Sh', 'Ъ':'', 'Ы':'Y', 'Ь':'', 'Э':'E', 'Ю':'Yu',
+ 'Я':'Ya'
+}
+var UKRAINIAN_MAP = {
+ 'Є':'Ye', 'І':'I', 'Ї':'Yi', 'Ґ':'G', 'є':'ye', 'і':'i', 'ї':'yi', 'ґ':'g'
+}
+var CZECH_MAP = {
+ 'č':'c', 'ď':'d', 'ě':'e', 'ň': 'n', 'ř':'r', 'š':'s', 'ť':'t', 'ů':'u',
+ 'ž':'z', 'Č':'C', 'Ď':'D', 'Ě':'E', 'Ň': 'N', 'Ř':'R', 'Š':'S', 'Ť':'T',
+ 'Ů':'U', 'Ž':'Z'
+}
+
+var POLISH_MAP = {
+ 'ą':'a', 'ć':'c', 'ę':'e', 'ł':'l', 'ń':'n', 'ó':'o', 'ś':'s', 'ź':'z',
+ 'ż':'z', 'Ą':'A', 'Ć':'C', 'Ę':'e', 'Ł':'L', 'Ń':'N', 'Ó':'o', 'Ś':'S',
+ 'Ź':'Z', 'Ż':'Z'
+}
+
+var LATVIAN_MAP = {
+ 'ā':'a', 'č':'c', 'ē':'e', 'ģ':'g', 'ī':'i', 'ķ':'k', 'ļ':'l', 'ņ':'n',
+ 'š':'s', 'ū':'u', 'ž':'z', 'Ā':'A', 'Č':'C', 'Ē':'E', 'Ģ':'G', 'Ī':'i',
+ 'Ķ':'k', 'Ļ':'L', 'Ņ':'N', 'Š':'S', 'Ū':'u', 'Ž':'Z'
+}
+
+var ALL_DOWNCODE_MAPS=new Array()
+ALL_DOWNCODE_MAPS[0]=LATIN_MAP
+ALL_DOWNCODE_MAPS[1]=LATIN_SYMBOLS_MAP
+ALL_DOWNCODE_MAPS[2]=GREEK_MAP
+ALL_DOWNCODE_MAPS[3]=TURKISH_MAP
+ALL_DOWNCODE_MAPS[4]=RUSSIAN_MAP
+ALL_DOWNCODE_MAPS[5]=UKRAINIAN_MAP
+ALL_DOWNCODE_MAPS[6]=CZECH_MAP
+ALL_DOWNCODE_MAPS[7]=POLISH_MAP
+ALL_DOWNCODE_MAPS[8]=LATVIAN_MAP
+
+var Downcoder = new Object();
+Downcoder.Initialize = function()
+{
+ if (Downcoder.map) // already made
+ return ;
+ Downcoder.map ={}
+ Downcoder.chars = '' ;
+ for(var i in ALL_DOWNCODE_MAPS)
+ {
+ var lookup = ALL_DOWNCODE_MAPS[i]
+ for (var c in lookup)
+ {
+ Downcoder.map[c] = lookup[c] ;
+ Downcoder.chars += c ;
+ }
+ }
+ Downcoder.regex = new RegExp('[' + Downcoder.chars + ']|[^' + Downcoder.chars + ']+','g') ;
+}
+
+downcode= function( slug )
+{
+ Downcoder.Initialize() ;
+ var downcoded =""
+ var pieces = slug.match(Downcoder.regex);
+ if(pieces)
+ {
+ for (var i = 0 ; i < pieces.length ; i++)
+ {
+ if (pieces[i].length == 1)
+ {
+ var mapped = Downcoder.map[pieces[i]] ;
+ if (mapped != null)
+ {
+ downcoded+=mapped;
+ continue ;
+ }
+ }
+ downcoded+=pieces[i];
+ }
+ }
+ else
+ {
+ downcoded = slug;
+ }
+ return downcoded;
+}
+
+
function URLify(s, num_chars) {
// changes, e.g., "Petty theft" to "petty_theft"
// remove all these words from the string before urlifying
+ s = downcode(s);
removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from",
"is", "in", "into", "like", "of", "off", "on", "onto", "per",
"since", "than", "the", "this", "that", "to", "up", "via",
"with"];
r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
s = s.replace(r, '');
+ // if downcode doesn't hit, the char will be stripped here
s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars
s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens
s = s.toLowerCase(); // convert to lowercase
return s.substring(0, num_chars);// trim to first num_chars chars
}
+