diff options
author | Trey Hunner <trey@treyhunner.com> | 2015-04-27 21:12:31 -0700 |
---|---|---|
committer | Tim Graham <timograham@gmail.com> | 2015-06-27 16:36:26 -0400 |
commit | ec4f219ecb7a5e43d0353633fac4dac42d0ee492 (patch) | |
tree | 149080086a963899ec8ca36f7ad8e086f81ce521 | |
parent | 1e63652e44f1c12c6e0fec6dacfae0c865b7cdbf (diff) | |
download | django-ec4f219ecb7a5e43d0353633fac4dac42d0ee492.tar.gz |
Fixed #22463 -- Added code style guide and JavaScript linting (EditorConfig and ESLint)
26 files changed, 1007 insertions, 842 deletions
diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..30d6fcc1e3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,37 @@ +# http://editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true +end_of_line = lf +charset = utf-8 + +# Use 2 spaces for the HTML files +[*.html] +indent_size = 2 + +# The JSON files contain newlines inconsistently +[*.json] +indent_size = 2 +insert_final_newline = ignore + +[**/admin/js/vendor/**] +indent_style = ignore +indent_size = ignore + +# Minified JavaScript files shouldn't be changed +[**.min.js] +indent_style = ignore +insert_final_newline = ignore + +# Makefiles always use tabs for indentation +[Makefile] +indent_style = tab + +# Batch files use tabs for indentation +[*.bat] +indent_style = tab diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..cb0447577b --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +**/{*.min,jquery}.js +django/contrib/gis/templates/**/*.js +node_modules/**.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000000..4d8f385896 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,51 @@ +{ + "rules": { + "camelcase": [1, {"properties": "always"}], + "comma-spacing": [1, {"before": false, "after": true}], + "dot-notation": [1, {"allowKeywords": true}], + "curly": [1, "all"], + "indent": [ + 2, + 4 + ], + "key-spacing": [1, { + "beforeColon": false, + "afterColon": true + }], + "new-cap": [1, {"newIsCap": true, "capIsNew": true}], + "no-alert": [0], + "no-eval": [1], + "no-extend-native": [2, {"exceptions": ["Date", "String"]}], + "no-multi-spaces": [1], + "no-octal-escape": [1], + "no-underscore-dangle": [1], + "no-unused-vars": [2, {"vars": "local", "args": "none"}], + "no-script-url": [1], + "no-shadow": [1, {"hoist": "functions"}], + "quotes": [ + 1, + "single" + ], + "linebreak-style": [ + 2, + "unix" + ], + "semi": [ + 2, + "always" + ], + "space-before-blocks": [2, "always"], + "space-before-function-paren": [1, {"anonymous": "always", "named": "never"}], + "space-infix-ops": [ + 1, + {"int32Hint": false} + ], + "strict": [1, "function"] + }, + "env": { + "browser": true + }, + "globals": { + "django": false + } +}
\ No newline at end of file diff --git a/.gitignore b/.gitignore index 5f1338f232..e873831f50 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ MANIFEST dist/ docs/_build/ docs/locale/ +node_modules/ tests/coverage_html/ tests/.coverage build/ diff --git a/django/contrib/admin/static/admin/js/SelectBox.js b/django/contrib/admin/static/admin/js/SelectBox.js index db3206ccf5..bbd30a2c58 100644 --- a/django/contrib/admin/static/admin/js/SelectBox.js +++ b/django/contrib/admin/static/admin/js/SelectBox.js @@ -1,9 +1,10 @@ +/*eslint no-cond-assign:1*/ var SelectBox = { - cache: new Object(), + cache: {}, init: function(id) { var box = document.getElementById(id); var node; - SelectBox.cache[id] = new Array(); + SelectBox.cache[id] = []; var cache = SelectBox.cache[id]; for (var i = 0; (node = box.options[i]); i++) { cache.push({value: node.value, text: node.text, displayed: 1}); @@ -31,7 +32,7 @@ var SelectBox = { for (var i = 0; (node = SelectBox.cache[id][i]); i++) { node.displayed = 1; for (var j = 0; (token = tokens[j]); j++) { - if (node.text.toLowerCase().indexOf(token) == -1) { + if (node.text.toLowerCase().indexOf(token) === -1) { node.displayed = 0; } } @@ -41,13 +42,13 @@ var SelectBox = { delete_from_cache: function(id, value) { var node, delete_index = null; for (var i = 0; (node = SelectBox.cache[id][i]); i++) { - if (node.value == value) { + if (node.value === value) { delete_index = i; break; } } var j = SelectBox.cache[id].length - 1; - for (var i = delete_index; i < j; i++) { + for (i = delete_index; i < j; i++) { SelectBox.cache[id][i] = SelectBox.cache[id][i+1]; } SelectBox.cache[id].length--; @@ -59,7 +60,7 @@ var SelectBox = { // Check if an item is contained in the cache var node; for (var i = 0; (node = SelectBox.cache[id][i]); i++) { - if (node.value == value) { + if (node.value === value) { return true; } } @@ -67,7 +68,6 @@ var SelectBox = { }, move: function(from, to) { var from_box = document.getElementById(from); - var to_box = document.getElementById(to); var option; for (var i = 0; (option = from_box.options[i]); i++) { if (option.selected && SelectBox.cache_contains(from, option.value)) { @@ -80,7 +80,6 @@ var SelectBox = { }, move_all: function(from, to) { var from_box = document.getElementById(from); - var to_box = document.getElementById(to); var option; for (var i = 0; (option = from_box.options[i]); i++) { if (SelectBox.cache_contains(from, option.value)) { @@ -111,4 +110,4 @@ var SelectBox = { box.options[i].selected = 'selected'; } } -} +}; diff --git a/django/contrib/admin/static/admin/js/SelectFilter2.js b/django/contrib/admin/static/admin/js/SelectFilter2.js index 8f417dd9df..f8aba12fd6 100644 --- a/django/contrib/admin/static/admin/js/SelectFilter2.js +++ b/django/contrib/admin/static/admin/js/SelectFilter2.js @@ -1,196 +1,197 @@ +/*global SelectBox, addEvent, gettext, interpolate, quickElement, SelectFilter*/ /* SelectFilter2 - Turns a multiple-select box into a filter interface. Requires core.js, SelectBox.js and addevent.js. */ (function($) { -function findForm(node) { - // returns the node of the form containing the given node - if (node.tagName.toLowerCase() != 'form') { - return findForm(node.parentNode); - } - return node; -} - -window.SelectFilter = { - init: function(field_id, field_name, is_stacked) { - if (field_id.match(/__prefix__/)){ - // Don't initialize on empty forms. - return; - } - var from_box = document.getElementById(field_id); - from_box.id += '_from'; // change its ID - from_box.className = 'filtered'; - - var ps = from_box.parentNode.getElementsByTagName('p'); - for (var i=0; i<ps.length; i++) { - if (ps[i].className.indexOf("info") != -1) { - // Remove <p class="info">, because it just gets in the way. - from_box.parentNode.removeChild(ps[i]); - } else if (ps[i].className.indexOf("help") != -1) { - // Move help text up to the top so it isn't below the select - // boxes or wrapped off on the side to the right of the add - // button: - from_box.parentNode.insertBefore(ps[i], from_box.parentNode.firstChild); - } + function findForm(node) { + // returns the node of the form containing the given node + if (node.tagName.toLowerCase() !== 'form') { + return findForm(node.parentNode); } + return node; + } - // <div class="selector"> or <div class="selector stacked"> - var selector_div = quickElement('div', from_box.parentNode); - selector_div.className = is_stacked ? 'selector stacked' : 'selector'; - - // <div class="selector-available"> - var selector_available = quickElement('div', selector_div); - selector_available.className = 'selector-available'; - var title_available = quickElement('h2', selector_available, interpolate(gettext('Available %s') + ' ', [field_name])); - quickElement( - 'span', title_available, '', - 'class', 'help help-tooltip help-icon', - '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] - ) - ); - - var filter_p = quickElement('p', selector_available, '', 'id', field_id + '_filter'); - filter_p.className = 'selector-filter'; - - var search_filter_label = quickElement('label', filter_p, '', 'for', field_id + "_input"); - - var search_selector_img = quickElement( - 'span', search_filter_label, '', - 'class', 'help-tooltip search-label-icon', - 'title', interpolate(gettext("Type into this box to filter down the list of available %s."), [field_name]) - ); - - filter_p.appendChild(document.createTextNode(' ')); - - var filter_input = quickElement('input', filter_p, '', 'type', 'text', 'placeholder', gettext("Filter")); - filter_input.id = field_id + '_input'; - - selector_available.appendChild(from_box); - var choose_all = quickElement('a', selector_available, gettext('Choose all'), 'title', interpolate(gettext('Click to choose all %s at once.'), [field_name]), 'href', 'javascript:void(0);', 'id', field_id + '_add_all_link'); - choose_all.className = 'selector-chooseall'; - - // <ul class="selector-chooser"> - var selector_chooser = quickElement('ul', selector_div); - selector_chooser.className = 'selector-chooser'; - var add_link = quickElement('a', quickElement('li', selector_chooser), gettext('Choose'), 'title', gettext('Choose'), 'href', 'javascript:void(0);', 'id', field_id + '_add_link'); - add_link.className = 'selector-add'; - var remove_link = quickElement('a', quickElement('li', selector_chooser), gettext('Remove'), 'title', gettext('Remove'), 'href', 'javascript:void(0);', 'id', field_id + '_remove_link'); - remove_link.className = 'selector-remove'; - - // <div class="selector-chosen"> - var selector_chosen = quickElement('div', selector_div); - selector_chosen.className = 'selector-chosen'; - var title_chosen = quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s') + ' ', [field_name])); - quickElement( - 'span', title_chosen, '', - 'class', 'help help-tooltip help-icon', - '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] - ) - ); - - 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('Remove all'), 'title', interpolate(gettext('Click to remove all chosen %s at once.'), [field_name]), 'href', 'javascript:void(0);', 'id', field_id + '_remove_all_link'); - clear_all.className = 'selector-clearall'; - - from_box.setAttribute('name', from_box.getAttribute('name') + '_old'); - - // Set up the JavaScript event handlers for the select box filter interface - addEvent(choose_all, 'click', function() { SelectBox.move_all(field_id + '_from', field_id + '_to'); SelectFilter.refresh_icons(field_id); }); - addEvent(add_link, 'click', function() { SelectBox.move(field_id + '_from', field_id + '_to'); SelectFilter.refresh_icons(field_id); }); - addEvent(remove_link, 'click', function() { SelectBox.move(field_id + '_to', field_id + '_from'); SelectFilter.refresh_icons(field_id); }); - addEvent(clear_all, 'click', function() { SelectBox.move_all(field_id + '_to', field_id + '_from'); SelectFilter.refresh_icons(field_id); }); - addEvent(filter_input, 'keypress', function(e) { SelectFilter.filter_key_press(e, field_id); }); - addEvent(filter_input, 'keyup', function(e) { SelectFilter.filter_key_up(e, field_id); }); - addEvent(filter_input, 'keydown', function(e) { SelectFilter.filter_key_down(e, field_id); }); - addEvent(from_box, 'change', function(e) { SelectFilter.refresh_icons(field_id) }); - addEvent(to_box, 'change', function(e) { SelectFilter.refresh_icons(field_id) }); - addEvent(from_box, 'dblclick', function() { SelectBox.move(field_id + '_from', field_id + '_to'); SelectFilter.refresh_icons(field_id); }); - addEvent(to_box, 'dblclick', function() { SelectBox.move(field_id + '_to', field_id + '_from'); SelectFilter.refresh_icons(field_id); }); - addEvent(findForm(from_box), 'submit', function() { SelectBox.select_all(field_id + '_to'); }); - SelectBox.init(field_id + '_from'); - SelectBox.init(field_id + '_to'); - // Move selected from_box options to to_box - SelectBox.move(field_id + '_from', field_id + '_to'); - - if (!is_stacked) { - // In horizontal mode, give the same height to the two boxes. - var j_from_box = $(from_box); - var j_to_box = $(to_box); - var resize_filters = function() { j_to_box.height($(filter_p).outerHeight() + j_from_box.outerHeight()); } - if (j_from_box.outerHeight() > 0) { - resize_filters(); // This fieldset is already open. Resize now. - } else { - // This fieldset is probably collapsed. Wait for its 'show' event. - j_to_box.closest('fieldset').one('show.fieldset', resize_filters); + window.SelectFilter = { + init: function(field_id, field_name, is_stacked) { + if (field_id.match(/__prefix__/)) { + // Don't initialize on empty forms. + return; + } + var from_box = document.getElementById(field_id); + from_box.id += '_from'; // change its ID + from_box.className = 'filtered'; + + var ps = from_box.parentNode.getElementsByTagName('p'); + for (var i=0; i<ps.length; i++) { + if (ps[i].className.indexOf("info") !== -1) { + // Remove <p class="info">, because it just gets in the way. + from_box.parentNode.removeChild(ps[i]); + } else if (ps[i].className.indexOf("help") !== -1) { + // Move help text up to the top so it isn't below the select + // boxes or wrapped off on the side to the right of the add + // button: + from_box.parentNode.insertBefore(ps[i], from_box.parentNode.firstChild); + } } - } - // Initial icon refresh - SelectFilter.refresh_icons(field_id); - }, - refresh_icons: function(field_id) { - var from = $('#' + field_id + '_from'); - var to = $('#' + field_id + '_to'); - var is_from_selected = from.find('option:selected').length > 0; - var is_to_selected = to.find('option:selected').length > 0; - // Active if at least one item is selected - $('#' + field_id + '_add_link').toggleClass('active', is_from_selected); - $('#' + field_id + '_remove_link').toggleClass('active', is_to_selected); - // Active if the corresponding box isn't empty - $('#' + field_id + '_add_all_link').toggleClass('active', from.find('option').length > 0); - $('#' + field_id + '_remove_all_link').toggleClass('active', to.find('option').length > 0); - }, - filter_key_press: function(event, field_id) { - var from = document.getElementById(field_id + '_from'); - // don't submit form if user pressed Enter - if ((event.which && event.which == 13) || (event.keyCode && event.keyCode == 13)) { - from.selectedIndex = 0; - SelectBox.move(field_id + '_from', field_id + '_to'); - from.selectedIndex = 0; - event.preventDefault() - return false; - } - }, - filter_key_up: function(event, field_id) { - var from = document.getElementById(field_id + '_from'); - var temp = from.selectedIndex; - SelectBox.filter(field_id + '_from', document.getElementById(field_id + '_input').value); - from.selectedIndex = temp; - return true; - }, - filter_key_down: function(event, field_id) { - var from = document.getElementById(field_id + '_from'); - // right arrow -- move across - if ((event.which && event.which == 39) || (event.keyCode && event.keyCode == 39)) { - var old_index = from.selectedIndex; + // <div class="selector"> or <div class="selector stacked"> + var selector_div = quickElement('div', from_box.parentNode); + selector_div.className = is_stacked ? 'selector stacked' : 'selector'; + + // <div class="selector-available"> + var selector_available = quickElement('div', selector_div); + selector_available.className = 'selector-available'; + var title_available = quickElement('h2', selector_available, interpolate(gettext('Available %s') + ' ', [field_name])); + quickElement( + 'span', title_available, '', + 'class', 'help help-tooltip help-icon', + '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] + ) + ); + + var filter_p = quickElement('p', selector_available, '', 'id', field_id + '_filter'); + filter_p.className = 'selector-filter'; + + var search_filter_label = quickElement('label', filter_p, '', 'for', field_id + '_input'); + + quickElement( + 'span', search_filter_label, '', + 'class', 'help-tooltip search-label-icon', + 'title', interpolate(gettext("Type into this box to filter down the list of available %s."), [field_name]) + ); + + filter_p.appendChild(document.createTextNode(' ')); + + var filter_input = quickElement('input', filter_p, '', 'type', 'text', 'placeholder', gettext("Filter")); + filter_input.id = field_id + '_input'; + + selector_available.appendChild(from_box); + var choose_all = quickElement('a', selector_available, gettext('Choose all'), 'title', interpolate(gettext('Click to choose all %s at once.'), [field_name]), 'href', 'javascript:void(0);', 'id', field_id + '_add_all_link'); + choose_all.className = 'selector-chooseall'; + + // <ul class="selector-chooser"> + var selector_chooser = quickElement('ul', selector_div); + selector_chooser.className = 'selector-chooser'; + var add_link = quickElement('a', quickElement('li', selector_chooser), gettext('Choose'), 'title', gettext('Choose'), 'href', 'javascript:void(0);', 'id', field_id + '_add_link'); + add_link.className = 'selector-add'; + var remove_link = quickElement('a', quickElement('li', selector_chooser), gettext('Remove'), 'title', gettext('Remove'), 'href', 'javascript:void(0);', 'id', field_id + '_remove_link'); + remove_link.className = 'selector-remove'; + + // <div class="selector-chosen"> + var selector_chosen = quickElement('div', selector_div); + selector_chosen.className = 'selector-chosen'; + var title_chosen = quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s') + ' ', [field_name])); + quickElement( + 'span', title_chosen, '', + 'class', 'help help-tooltip help-icon', + '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] + ) + ); + + 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('Remove all'), 'title', interpolate(gettext('Click to remove all chosen %s at once.'), [field_name]), 'href', 'javascript:void(0);', 'id', field_id + '_remove_all_link'); + clear_all.className = 'selector-clearall'; + + from_box.setAttribute('name', from_box.getAttribute('name') + '_old'); + + // Set up the JavaScript event handlers for the select box filter interface + addEvent(choose_all, 'click', function() { SelectBox.move_all(field_id + '_from', field_id + '_to'); SelectFilter.refresh_icons(field_id); }); + addEvent(add_link, 'click', function() { SelectBox.move(field_id + '_from', field_id + '_to'); SelectFilter.refresh_icons(field_id); }); + addEvent(remove_link, 'click', function() { SelectBox.move(field_id + '_to', field_id + '_from'); SelectFilter.refresh_icons(field_id); }); + addEvent(clear_all, 'click', function() { SelectBox.move_all(field_id + '_to', field_id + '_from'); SelectFilter.refresh_icons(field_id); }); + addEvent(filter_input, 'keypress', function(e) { SelectFilter.filter_key_press(e, field_id); }); + addEvent(filter_input, 'keyup', function(e) { SelectFilter.filter_key_up(e, field_id); }); + addEvent(filter_input, 'keydown', function(e) { SelectFilter.filter_key_down(e, field_id); }); + addEvent(from_box, 'change', function(e) { SelectFilter.refresh_icons(field_id); }); + addEvent(to_box, 'change', function(e) { SelectFilter.refresh_icons(field_id); }); + addEvent(from_box, 'dblclick', function() { SelectBox.move(field_id + '_from', field_id + '_to'); SelectFilter.refresh_icons(field_id); }); + addEvent(to_box, 'dblclick', function() { SelectBox.move(field_id + '_to', field_id + '_from'); SelectFilter.refresh_icons(field_id); }); + addEvent(findForm(from_box), 'submit', function() { SelectBox.select_all(field_id + '_to'); }); + SelectBox.init(field_id + '_from'); + SelectBox.init(field_id + '_to'); + // Move selected from_box options to to_box SelectBox.move(field_id + '_from', field_id + '_to'); - from.selectedIndex = (old_index == from.length) ? from.length - 1 : old_index; - return false; - } - // down arrow -- wrap around - if ((event.which && event.which == 40) || (event.keyCode && event.keyCode == 40)) { - from.selectedIndex = (from.length == from.selectedIndex + 1) ? 0 : from.selectedIndex + 1; - } - // up arrow -- wrap around - if ((event.which && event.which == 38) || (event.keyCode && event.keyCode == 38)) { - from.selectedIndex = (from.selectedIndex == 0) ? from.length - 1 : from.selectedIndex - 1; + + if (!is_stacked) { + // In horizontal mode, give the same height to the two boxes. + var j_from_box = $(from_box); + var j_to_box = $(to_box); + var resize_filters = function() { j_to_box.height($(filter_p).outerHeight() + j_from_box.outerHeight()); }; + if (j_from_box.outerHeight() > 0) { + resize_filters(); // This fieldset is already open. Resize now. + } else { + // This fieldset is probably collapsed. Wait for its 'show' event. + j_to_box.closest('fieldset').one('show.fieldset', resize_filters); + } + } + + // Initial icon refresh + SelectFilter.refresh_icons(field_id); + }, + refresh_icons: function(field_id) { + var from = $('#' + field_id + '_from'); + var to = $('#' + field_id + '_to'); + var is_from_selected = from.find('option:selected').length > 0; + var is_to_selected = to.find('option:selected').length > 0; + // Active if at least one item is selected + $('#' + field_id + '_add_link').toggleClass('active', is_from_selected); + $('#' + field_id + '_remove_link').toggleClass('active', is_to_selected); + // Active if the corresponding box isn't empty + $('#' + field_id + '_add_all_link').toggleClass('active', from.find('option').length > 0); + $('#' + field_id + '_remove_all_link').toggleClass('active', to.find('option').length > 0); + }, + filter_key_press: function(event, field_id) { + var from = document.getElementById(field_id + '_from'); + // don't submit form if user pressed Enter + if ((event.which && event.which === 13) || (event.keyCode && event.keyCode === 13)) { + from.selectedIndex = 0; + SelectBox.move(field_id + '_from', field_id + '_to'); + from.selectedIndex = 0; + event.preventDefault(); + return false; + } + }, + filter_key_up: function(event, field_id) { + var from = document.getElementById(field_id + '_from'); + var temp = from.selectedIndex; + SelectBox.filter(field_id + '_from', document.getElementById(field_id + '_input').value); + from.selectedIndex = temp; + return true; + }, + filter_key_down: function(event, field_id) { + var from = document.getElementById(field_id + '_from'); + // right arrow -- move across + if ((event.which && event.which === 39) || (event.keyCode && event.keyCode === 39)) { + var old_index = from.selectedIndex; + SelectBox.move(field_id + '_from', field_id + '_to'); + from.selectedIndex = (old_index === from.length) ? from.length - 1 : old_index; + return false; + } + // down arrow -- wrap around + if ((event.which && event.which === 40) || (event.keyCode && event.keyCode === 40)) { + from.selectedIndex = (from.length === from.selectedIndex + 1) ? 0 : from.selectedIndex + 1; + } + // up arrow -- wrap around + if ((event.which && event.which === 38) || (event.keyCode && event.keyCode === 38)) { + from.selectedIndex = (from.selectedIndex === 0) ? from.length - 1 : from.selectedIndex - 1; + } + return true; } - return true; - } -} + }; })(django.jQuery); diff --git a/django/contrib/admin/static/admin/js/actions.js b/django/contrib/admin/static/admin/js/actions.js index 58f572f252..e899000ab3 100644 --- a/django/contrib/admin/static/admin/js/actions.js +++ b/django/contrib/admin/static/admin/js/actions.js @@ -1,144 +1,145 @@ +/*global _actions_icnt, gettext, interpolate, ngettext*/ (function($) { - var lastChecked; + var lastChecked; - $.fn.actions = function(opts) { - var options = $.extend({}, $.fn.actions.defaults, opts); - var actionCheckboxes = $(this); - var list_editable_changed = false; - var checker = function(checked) { - if (checked) { - showQuestion(); - } else { - reset(); - } - $(actionCheckboxes).prop("checked", checked) - .parent().parent().toggleClass(options.selectedClass, checked); - }, - updateCounter = function() { - var sel = $(actionCheckboxes).filter(":checked").length; - // _actions_icnt is defined in the generated HTML - // and contains the total amount of objects in the queryset - $(options.counterContainer).html(interpolate( - ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), { - sel: sel, - cnt: _actions_icnt - }, true)); - $(options.allToggle).prop("checked", function() { - var value; - if (sel == actionCheckboxes.length) { - value = true; - showQuestion(); - } else { - value = false; - clearAcross(); - } - return value; - }); - }, - showQuestion = function() { - $(options.acrossClears).hide(); - $(options.acrossQuestions).show(); - $(options.allContainer).hide(); - }, - showClear = function() { - $(options.acrossClears).show(); - $(options.acrossQuestions).hide(); - $(options.actionContainer).toggleClass(options.selectedClass); - $(options.allContainer).show(); - $(options.counterContainer).hide(); - }, - reset = function() { - $(options.acrossClears).hide(); - $(options.acrossQuestions).hide(); - $(options.allContainer).hide(); - $(options.counterContainer).show(); - }, - clearAcross = function() { - reset(); - $(options.acrossInput).val(0); - $(options.actionContainer).removeClass(options.selectedClass); - }; - // Show counter by default - $(options.counterContainer).show(); - // Check state of checkboxes and reinit state if needed - $(this).filter(":checked").each(function(i) { - $(this).parent().parent().toggleClass(options.selectedClass); - updateCounter(); - if ($(options.acrossInput).val() == 1) { - showClear(); - } - }); - $(options.allToggle).show().click(function() { - checker($(this).prop("checked")); - updateCounter(); - }); - $("a", options.acrossQuestions).click(function(event) { - event.preventDefault(); - $(options.acrossInput).val(1); - showClear(); - }); - $("a", options.acrossClears).click(function(event) { - event.preventDefault(); - $(options.allToggle).prop("checked", false); - clearAcross(); - checker(0); - updateCounter(); - }); - lastChecked = null; - $(actionCheckboxes).click(function(event) { - if (!event) { event = window.event; } - var target = event.target ? event.target : event.srcElement; - if (lastChecked && $.data(lastChecked) != $.data(target) && event.shiftKey === true) { - var inrange = false; - $(lastChecked).prop("checked", target.checked) - .parent().parent().toggleClass(options.selectedClass, target.checked); - $(actionCheckboxes).each(function() { - if ($.data(this) == $.data(lastChecked) || $.data(this) == $.data(target)) { - inrange = (inrange) ? false : true; - } - if (inrange) { - $(this).prop("checked", target.checked) - .parent().parent().toggleClass(options.selectedClass, target.checked); - } - }); - } - $(target).parent().parent().toggleClass(options.selectedClass, target.checked); - lastChecked = target; - updateCounter(); - }); - $('form#changelist-form table#result_list tr').find('td:gt(0) :input').change(function() { - list_editable_changed = true; - }); - $('form#changelist-form button[name="index"]').click(function(event) { - if (list_editable_changed) { - return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.")); - } - }); - $('form#changelist-form input[name="_save"]').click(function(event) { - var action_changed = false; - $('select option:selected', options.actionContainer).each(function() { - if ($(this).val()) { - action_changed = true; - } - }); - if (action_changed) { - if (list_editable_changed) { - 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.")); - } else { - 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.")); - } - } - }); - }; - /* Setup plugin defaults */ - $.fn.actions.defaults = { - actionContainer: "div.actions", - counterContainer: "span.action-counter", - allContainer: "div.actions span.all", - acrossInput: "div.actions input.select-across", - acrossQuestions: "div.actions span.question", - acrossClears: "div.actions span.clear", - allToggle: "#action-toggle", - selectedClass: "selected" - }; + $.fn.actions = function(opts) { + var options = $.extend({}, $.fn.actions.defaults, opts); + var actionCheckboxes = $(this); + var list_editable_changed = false; + var showQuestion = function() { + $(options.acrossClears).hide(); + $(options.acrossQuestions).show(); + $(options.allContainer).hide(); + }, + showClear = function() { + $(options.acrossClears).show(); + $(options.acrossQuestions).hide(); + $(options.actionContainer).toggleClass(options.selectedClass); + $(options.allContainer).show(); + $(options.counterContainer).hide(); + }, + reset = function() { + $(options.acrossClears).hide(); + $(options.acrossQuestions).hide(); + $(options.allContainer).hide(); + $(options.counterContainer).show(); + }, + clearAcross = function() { + reset(); + $(options.acrossInput).val(0); + $(options.actionContainer).removeClass(options.selectedClass); + }, + checker = function(checked) { + if (checked) { + showQuestion(); + } else { + reset(); + } + $(actionCheckboxes).prop("checked", checked) + .parent().parent().toggleClass(options.selectedClass, checked); + }, + updateCounter = function() { + var sel = $(actionCheckboxes).filter(":checked").length; + // _actions_icnt is defined in the generated HTML + // and contains the total amount of objects in the queryset + $(options.counterContainer).html(interpolate( + ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), { + sel: sel, + cnt: _actions_icnt + }, true)); + $(options.allToggle).prop("checked", function() { + var value; + if (sel === actionCheckboxes.length) { + value = true; + showQuestion(); + } else { + value = false; + clearAcross(); + } + return value; + }); + }; + // Show counter by default + $(options.counterContainer).show(); + // Check state of checkboxes and reinit state if needed + $(this).filter(":checked").each(function(i) { + $(this).parent().parent().toggleClass(options.selectedClass); + updateCounter(); + if ($(options.acrossInput).val() === 1) { + showClear(); + } + }); + $(options.allToggle).show().click(function() { + checker($(this).prop("checked")); + updateCounter(); + }); + $("a", options.acrossQuestions).click(function(event) { + event.preventDefault(); + $(options.acrossInput).val(1); + showClear(); + }); + $("a", options.acrossClears).click(function(event) { + event.preventDefault(); + $(options.allToggle).prop("checked", false); + clearAcross(); + checker(0); + updateCounter(); + }); + lastChecked = null; + $(actionCheckboxes).click(function(event) { + if (!event) { event = window.event; } + var target = event.target ? event.target : event.srcElement; + if (lastChecked && $.data(lastChecked) !== $.data(target) && event.shiftKey === true) { + var inrange = false; + $(lastChecked).prop("checked", target.checked) + .parent().parent().toggleClass(options.selectedClass, target.checked); + $(actionCheckboxes).each(function() { + if ($.data(this) === $.data(lastChecked) || $.data(this) === $.data(target)) { + inrange = (inrange) ? false : true; + } + if (inrange) { + $(this).prop("checked", target.checked) + .parent().parent().toggleClass(options.selectedClass, target.checked); + } + }); + } + $(target).parent().parent().toggleClass(options.selectedClass, target.checked); + lastChecked = target; + updateCounter(); + }); + $('form#changelist-form table#result_list tr').find('td:gt(0) :input').change(function() { + list_editable_changed = true; + }); + $('form#changelist-form button[name="index"]').click(function(event) { + if (list_editable_changed) { + return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost.")); + } + }); + $('form#changelist-form input[name="_save"]').click(function(event) { + var action_changed = false; + $('select option:selected', options.actionContainer).each(function() { + if ($(this).val()) { + action_changed = true; + } + }); + if (action_changed) { + if (list_editable_changed) { + 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.")); + } else { + 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.")); + } + } + }); + }; + /* Setup plugin defaults */ + $.fn.actions.defaults = { + actionContainer: "div.actions", + counterContainer: "span.action-counter", + allContainer: "div.actions span.all", + acrossInput: "div.actions input.select-across", + acrossQuestions: "div.actions span.question", + acrossClears: "div.actions span.clear", + allToggle: "#action-toggle", + selectedClass: "selected" + }; })(django.jQuery); diff --git a/django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js b/django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js index 9b25b9df36..987ee9004f 100644 --- a/django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js +++ b/django/contrib/admin/static/admin/js/admin/DateTimeShortcuts.js @@ -1,3 +1,4 @@ +/*global addEvent, Calendar, cancelEventPropagation, findPosX, findPosY, getStyle, get_format, gettext, interpolate, ngettext, quickElement, removeEvent*/ // Inserts shortcut buttons after all of the following: // <input type="text" class="vDateField"> // <input type="text" class="vTimeField"> @@ -17,20 +18,20 @@ var DateTimeShortcuts = { timezoneWarningClass: 'timezonewarning', // class of the warning for timezone mismatch timezoneOffset: 0, init: function() { - if (window.__admin_utc_offset__ != undefined) { + if (window.__admin_utc_offset__ !== undefined) { var serverOffset = window.__admin_utc_offset__; var localOffset = new Date().getTimezoneOffset() * -60; DateTimeShortcuts.timezoneOffset = localOffset - serverOffset; } var inputs = document.getElementsByTagName('input'); - for (i=0; i<inputs.length; i++) { + for (var i=0; i<inputs.length; i++) { var inp = inputs[i]; - if (inp.getAttribute('type') == 'text' && inp.className.match(/vTimeField/)) { + if (inp.getAttribute('type') === 'text' && inp.className.match(/vTimeField/)) { DateTimeShortcuts.addClock(inp); DateTimeShortcuts.addTimezoneWarning(inp); } - else if (inp.getAttribute('type') == 'text' && inp.className.match(/vDateField/)) { + else if (inp.getAttribute('type') === 'text' && inp.className.match(/vDateField/)) { DateTimeShortcuts.addCalendar(inp); DateTimeShortcuts.addTimezoneWarning(inp); } @@ -38,7 +39,7 @@ var DateTimeShortcuts = { }, // Return the current time while accounting for the server timezone. now: function() { - if (window.__admin_utc_offset__ != undefined) { + if (window.__admin_utc_offset__ !== undefined) { var serverOffset = window.__admin_utc_offset__; var localNow = new Date(); var localOffset = localNow.getTimezoneOffset() * -60; @@ -71,7 +72,7 @@ var DateTimeShortcuts = { ); } else { - timezoneOffset *= -1 + timezoneOffset *= -1; message = ngettext( 'Note: You are %s hour behind server time.', 'Note: You are %s hours behind server time.', @@ -86,7 +87,7 @@ var DateTimeShortcuts = { $(inp).parent() .append($('<br>')) - .append($warning) + .append($warning); }, // Add clock widget to a given field addClock: function(inp) { @@ -150,7 +151,7 @@ var DateTimeShortcuts = { cancel_p.className = 'calendar-cancel'; quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');'); django.jQuery(document).bind('keyup', function(event) { - if (event.which == 27) { + if (event.which === 27) { // ESC key closes popup DateTimeShortcuts.dismissClock(num); event.preventDefault(); @@ -158,12 +159,12 @@ var DateTimeShortcuts = { }); }, openClock: function(num) { - var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num) - var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num) + var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num); + var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num); // Recalculate the clockbox position // is it left-to-right or right-to-left layout ? - if (getStyle(document.body,'direction')!='rtl') { + if (getStyle(document.body,'direction')!=='rtl') { clock_box.style.left = findPosX(clock_link) + 17 + 'px'; } else { @@ -180,20 +181,20 @@ var DateTimeShortcuts = { addEvent(document, 'click', DateTimeShortcuts.dismissClockFunc[num]); }, dismissClock: function(num) { - document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none'; - removeEvent(document, 'click', DateTimeShortcuts.dismissClockFunc[num]); + document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'none'; + removeEvent(document, 'click', DateTimeShortcuts.dismissClockFunc[num]); }, handleClockQuicklink: function(num, val) { - var d; - if (val == -1) { - d = DateTimeShortcuts.now(); - } - else { - d = new Date(1970, 1, 1, val, 0, 0, 0) - } - DateTimeShortcuts.clockInputs[num].value = d.strftime(get_format('TIME_INPUT_FORMATS')[0]); - DateTimeShortcuts.clockInputs[num].focus(); - DateTimeShortcuts.dismissClock(num); + var d; + if (val === -1) { + d = DateTimeShortcuts.now(); + } + else { + d = new Date(1970, 1, 1, val, 0, 0, 0); + } + DateTimeShortcuts.clockInputs[num].value = d.strftime(get_format('TIME_INPUT_FORMATS')[0]); + DateTimeShortcuts.clockInputs[num].focus(); + DateTimeShortcuts.dismissClock(num); }, // Add calendar widget to a given field. addCalendar: function(inp) { @@ -274,7 +275,7 @@ var DateTimeShortcuts = { cancel_p.className = 'calendar-cancel'; quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');'); django.jQuery(document).bind('keyup', function(event) { - if (event.which == 27) { + if (event.which === 27) { // ESC key closes popup DateTimeShortcuts.dismissCalendar(num); event.preventDefault(); @@ -282,8 +283,8 @@ var DateTimeShortcuts = { }); }, openCalendar: function(num) { - var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num) - var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+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. @@ -293,7 +294,7 @@ var DateTimeShortcuts = { var selected = inp.value.strptime(format); var year = selected.getFullYear(); var month = selected.getMonth() + 1; - var re = /\d{4}/ + var re = /\d{4}/; if (re.test(year.toString()) && month >= 1 && month <= 12) { DateTimeShortcuts.calendars[num].drawDate(month, year, selected); } @@ -301,7 +302,7 @@ var DateTimeShortcuts = { // Recalculate the clockbox position // is it left-to-right or right-to-left layout ? - if (getStyle(document.body,'direction')!='rtl') { + if (getStyle(document.body,'direction')!=='rtl') { cal_box.style.left = findPosX(cal_link) + 17 + 'px'; } else { @@ -345,12 +346,12 @@ var DateTimeShortcuts = { ").style.display='none';}"].join(''); }, handleCalendarQuickLink: function(num, offset) { - var d = DateTimeShortcuts.now(); - d.setDate(d.getDate() + offset) - DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]); - DateTimeShortcuts.calendarInputs[num].focus(); - DateTimeShortcuts.dismissCalendar(num); + var d = DateTimeShortcuts.now(); + d.setDate(d.getDate() + offset); + DateTimeShortcuts.calendarInputs[num].value = d.strftime(get_format('DATE_INPUT_FORMATS')[0]); + DateTimeShortcuts.calendarInputs[num].focus(); + DateTimeShortcuts.dismissCalendar(num); } -} +}; addEvent(window, 'load', DateTimeShortcuts.init); diff --git a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js index 4a577c4187..e8b8dd7890 100644 --- a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js +++ b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js @@ -1,3 +1,4 @@ +/*global SelectBox, interpolate*/ // Handles related-objects functionality: lookup link for raw_id_fields // and Add Another links. @@ -32,7 +33,7 @@ function showAdminPopup(triggeringLink, name_regexp, add_popup) { name = id_to_windowname(name); var href = triggeringLink.href; if (add_popup) { - if (href.indexOf('?') == -1) { + if (href.indexOf('?') === -1) { href += '?_popup=1'; } else { href += '&_popup=1'; @@ -50,7 +51,7 @@ function showRelatedObjectLookupPopup(triggeringLink) { function dismissRelatedLookupPopup(win, chosenId) { var name = windowname_to_id(win.name); var elem = document.getElementById(name); - if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) { + if (elem.className.indexOf('vManyToManyRawIdAdminField') !== -1 && elem.value) { elem.value += ',' + chosenId; } else { document.getElementById(name).value = chosenId; @@ -86,10 +87,10 @@ function dismissAddRelatedObjectPopup(win, newId, newRepr) { var elem = document.getElementById(name); if (elem) { var elemName = elem.nodeName.toUpperCase(); - if (elemName == 'SELECT') { + if (elemName === 'SELECT') { elem.options[elem.options.length] = new Option(newRepr, newId, true, true); - } else if (elemName == 'INPUT') { - if (elem.className.indexOf('vManyToManyRawIdAdminField') != -1 && elem.value) { + } else if (elemName === 'INPUT') { + if (elem.className.indexOf('vManyToManyRawIdAdminField') !== -1 && elem.value) { elem.value += ',' + newId; } else { elem.value = newId; @@ -113,13 +114,13 @@ function dismissChangeRelatedObjectPopup(win, objId, newRepr, newId) { var selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]); var selects = django.jQuery(selectsSelector); selects.find('option').each(function() { - if (this.value == objId) { + if (this.value === objId) { this.innerHTML = newRepr; this.value = newId; } }); win.close(); -}; +} function dismissDeleteRelatedObjectPopup(win, objId) { objId = html_unescape(objId); @@ -127,13 +128,13 @@ function dismissDeleteRelatedObjectPopup(win, objId) { var selectsSelector = interpolate('#%s, #%s_from, #%s_to', [id, id, id]); var selects = django.jQuery(selectsSelector); selects.find('option').each(function() { - if (this.value == objId) { + if (this.value === objId) { django.jQuery(this).remove(); } }).trigger('change'); win.close(); -}; +} // Kept for backward compatibility -showAddAnotherPopup = showRelatedObjectPopup; -dismissAddAnotherPopup = dismissAddRelatedObjectPopup; +var showAddAnotherPopup = showRelatedObjectPopup; +var dismissAddAnotherPopup = dismissAddRelatedObjectPopup; diff --git a/django/contrib/admin/static/admin/js/calendar.js b/django/contrib/admin/static/admin/js/calendar.js index 458eece92f..deaac8ec20 100644 --- a/django/contrib/admin/static/admin/js/calendar.js +++ b/django/contrib/admin/static/admin/js/calendar.js @@ -1,3 +1,4 @@ +/*global gettext, get_format, quickElement, removeChildren*/ /* calendar.js - Calendar functions by Adrian Holovaty depends on core.js for utility functions like removeChildren or quickElement @@ -9,17 +10,17 @@ var CalendarNamespace = { daysOfWeek: gettext('S M T W T F S').split(' '), firstDayOfWeek: parseInt(get_format('FIRST_DAY_OF_WEEK')), isLeapYear: function(year) { - return (((year % 4)==0) && ((year % 100)!=0) || ((year % 400)==0)); + return (((year % 4)===0) && ((year % 100)!==0) || ((year % 400)===0)); }, getDaysInMonth: function(month,year) { var days; - if (month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12) { + if (month===1 || month===3 || month===5 || month===7 || month===8 || month===10 || month===12) { days = 31; } - else if (month==4 || month==6 || month==9 || month==11) { + else if (month===4 || month===6 || month===9 || month===11) { days = 30; } - else if (month==2 && CalendarNamespace.isLeapYear(year)) { + else if (month===2 && CalendarNamespace.isLeapYear(year)) { days = 29; } else { @@ -46,8 +47,8 @@ var CalendarNamespace = { // The day variable above will be 1 instead of 2 in, say, US Pacific time // zone. var isSelectedMonth = false; - if (typeof selected != 'undefined') { - isSelectedMonth = (selected.getUTCFullYear() == year && (selected.getUTCMonth()+1) == month); + if (typeof selected !== 'undefined') { + isSelectedMonth = (selected.getUTCFullYear() === year && (selected.getUTCMonth()+1) === month); } month = parseInt(month); @@ -67,28 +68,30 @@ var CalendarNamespace = { var startingPos = new Date(year, month-1, 1 - CalendarNamespace.firstDayOfWeek).getDay(); var days = CalendarNamespace.getDaysInMonth(month, year); + var _cell; + // Draw blanks before first of month tableRow = quickElement('tr', tableBody); - for (var i = 0; i < startingPos; i++) { - var _cell = quickElement('td', tableRow, ' '); + for (i = 0; i < startingPos; i++) { + _cell = quickElement('td', tableRow, ' '); _cell.className = "nonday"; } // Draw days of month var currentDay = 1; - for (var i = startingPos; currentDay <= days; i++) { - if (i%7 == 0 && currentDay != 1) { + for (i = startingPos; currentDay <= days; i++) { + if (i%7 === 0 && currentDay !== 1) { tableRow = quickElement('tr', tableBody); } - if ((currentDay==todayDay) && (month==todayMonth) && (year==todayYear)) { + if ((currentDay===todayDay) && (month===todayMonth) && (year===todayYear)) { todayClass='today'; } else { todayClass=''; } // use UTC function; see above for explanation. - if (isSelectedMonth && currentDay == selected.getUTCDate()) { - if (todayClass != '') todayClass += " "; + if (isSelectedMonth && currentDay === selected.getUTCDate()) { + if (todayClass !== '') todayClass += " "; todayClass += "selected"; } @@ -100,13 +103,13 @@ var CalendarNamespace = { // Draw blanks after end of month (optional, but makes for valid code) while (tableRow.childNodes.length < 7) { - var _cell = quickElement('td', tableRow, ' '); + _cell = quickElement('td', tableRow, ' '); _cell.className = "nonday"; } calDiv.appendChild(calTable); } -} +}; // Calendar -- A calendar instance function Calendar(div_id, callback, selected) { @@ -120,7 +123,7 @@ function Calendar(div_id, callback, selected) { this.today = new Date(); this.currentMonth = this.today.getMonth() + 1; this.currentYear = this.today.getFullYear(); - if (typeof selected != 'undefined') { + if (typeof selected !== 'undefined') { this.selected = selected; } } @@ -139,7 +142,7 @@ Calendar.prototype = { this.drawCurrent(); }, drawPreviousMonth: function() { - if (this.currentMonth == 1) { + if (this.currentMonth === 1) { this.currentMonth = 12; this.currentYear--; } @@ -149,7 +152,7 @@ Calendar.prototype = { this.drawCurrent(); }, drawNextMonth: function() { - if (this.currentMonth == 12) { + if (this.currentMonth === 12) { this.currentMonth = 1; this.currentYear++; } @@ -166,4 +169,4 @@ Calendar.prototype = { this.currentYear++; this.drawCurrent(); } -} +}; diff --git a/django/contrib/admin/static/admin/js/collapse.js b/django/contrib/admin/static/admin/js/collapse.js index 3b1f31bd23..b11fcd68f3 100644 --- a/django/contrib/admin/static/admin/js/collapse.js +++ b/django/contrib/admin/static/admin/js/collapse.js @@ -1,24 +1,25 @@ +/*global gettext*/ (function($) { - $(document).ready(function() { - // Add anchor tag for Show/Hide link - $("fieldset.collapse").each(function(i, elem) { - // Don't hide if fields in this fieldset have errors - if ($(elem).find("div.errors").length == 0) { - $(elem).addClass("collapsed").find("h2").first().append(' (<a id="fieldsetcollapser' + - i +'" class="collapse-toggle" href="#">' + gettext("Show") + - '</a>)'); - } - }); - // Add toggle to anchor tag - $("fieldset.collapse a.collapse-toggle").click(function(ev) { - if ($(this).closest("fieldset").hasClass("collapsed")) { - // Show - $(this).text(gettext("Hide")).closest("fieldset").removeClass("collapsed").trigger("show.fieldset", [$(this).attr("id")]); - } else { - // Hide - $(this).text(gettext("Show")).closest("fieldset").addClass("collapsed").trigger("hide.fieldset", [$(this).attr("id")]); - } - return false; - }); - }); + $(document).ready(function() { + // Add anchor tag for Show/Hide link + $("fieldset.collapse").each(function(i, elem) { + // Don't hide if fields in this fieldset have errors + if ($(elem).find("div.errors").length === 0) { + $(elem).addClass("collapsed").find("h2").first().append(' (<a id="fieldsetcollapser' + + i +'" class="collapse-toggle" href="#">' + gettext("Show") + + '</a>)'); + } + }); + // Add toggle to anchor tag + $("fieldset.collapse a.collapse-toggle").click(function(ev) { + if ($(this).closest("fieldset").hasClass("collapsed")) { + // Show + $(this).text(gettext("Hide")).closest("fieldset").removeClass("collapsed").trigger("show.fieldset", [$(this).attr("id")]); + } else { + // Hide + $(this).text(gettext("Show")).closest("fieldset").addClass("collapsed").trigger("hide.fieldset", [$(this).attr("id")]); + } + return false; + }); + }); })(django.jQuery); diff --git a/django/contrib/admin/static/admin/js/collapse.min.js b/django/contrib/admin/static/admin/js/collapse.min.js index 0a8c20ea44..6251d91666 100644 --- a/django/contrib/admin/static/admin/js/collapse.min.js +++ b/django/contrib/admin/static/admin/js/collapse.min.js @@ -1,2 +1,2 @@ -(function(a){a(document).ready(function(){a("fieldset.collapse").each(function(c,b){a(b).find("div.errors").length==0&&a(b).addClass("collapsed").find("h2").first().append(' (<a id="fieldsetcollapser'+c+'" class="collapse-toggle" href="#">'+gettext("Show")+"</a>)")});a("fieldset.collapse a.collapse-toggle").click(function(){a(this).closest("fieldset").hasClass("collapsed")?a(this).text(gettext("Hide")).closest("fieldset").removeClass("collapsed").trigger("show.fieldset",[a(this).attr("id")]):a(this).text(gettext("Show")).closest("fieldset").addClass("collapsed").trigger("hide.fieldset", -[a(this).attr("id")]);return false})})})(django.jQuery); +(function(a){a(document).ready(function(){a("fieldset.collapse").each(function(b,c){0===a(c).find("div.errors").length&&a(c).addClass("collapsed").find("h2").first().append(' (<a id="fieldsetcollapser'+b+'" class="collapse-toggle" href="#">'+gettext("Show")+"</a>)")});a("fieldset.collapse a.collapse-toggle").click(function(b){a(this).closest("fieldset").hasClass("collapsed")?a(this).text(gettext("Hide")).closest("fieldset").removeClass("collapsed").trigger("show.fieldset",[a(this).attr("id")]):a(this).text(gettext("Show")).closest("fieldset").addClass("collapsed").trigger("hide.fieldset", +[a(this).attr("id")]);return!1})})})(django.jQuery); diff --git a/django/contrib/admin/static/admin/js/core.js b/django/contrib/admin/static/admin/js/core.js index 2c096aac6d..7702c66194 100644 --- a/django/contrib/admin/static/admin/js/core.js +++ b/django/contrib/admin/static/admin/js/core.js @@ -74,8 +74,8 @@ var xmlhttp; @else xmlhttp = false; @end @*/ -if (!xmlhttp && typeof XMLHttpRequest != 'undefined') { - xmlhttp = new XMLHttpRequest(); +if (!xmlhttp && typeof XMLHttpRequest !== 'undefined') { + xmlhttp = new XMLHttpRequest(); } // ---------------------------------------------------------------------------- @@ -90,7 +90,7 @@ function findPosX(obj) { obj = obj.offsetParent; } // IE offsetParent does not include the top-level - if (isIE && obj.parentElement){ + if (isIE && obj.parentElement) { curleft += obj.offsetLeft - obj.scrollLeft; } } else if (obj.x) { @@ -107,7 +107,7 @@ function findPosY(obj) { obj = obj.offsetParent; } // IE offsetParent does not include the top-level - if (isIE && obj.parentElement){ + if (isIE && obj.parentElement) { curtop += obj.offsetTop - obj.scrollTop; } } else if (obj.y) { @@ -121,46 +121,46 @@ function findPosY(obj) { // ---------------------------------------------------------------------------- Date.prototype.getTwelveHours = function() { - hours = this.getHours(); - if (hours == 0) { + var hours = this.getHours(); + if (hours === 0) { return 12; } else { - return hours <= 12 ? hours : hours-12 + return hours <= 12 ? hours : hours-12; } -} +}; Date.prototype.getTwoDigitMonth = function() { return (this.getMonth() < 9) ? '0' + (this.getMonth()+1) : (this.getMonth()+1); -} +}; Date.prototype.getTwoDigitDate = function() { return (this.getDate() < 10) ? '0' + this.getDate() : this.getDate(); -} +}; Date.prototype.getTwoDigitTwelveHour = function() { return (this.getTwelveHours() < 10) ? '0' + this.getTwelveHours() : this.getTwelveHours(); -} +}; Date.prototype.getTwoDigitHour = function() { return (this.getHours() < 10) ? '0' + this.getHours() : this.getHours(); -} +}; Date.prototype.getTwoDigitMinute = function() { return (this.getMinutes() < 10) ? '0' + this.getMinutes() : this.getMinutes(); -} +}; Date.prototype.getTwoDigitSecond = function() { return (this.getSeconds() < 10) ? '0' + this.getSeconds() : this.getSeconds(); -} +}; Date.prototype.getHourMinute = function() { return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute(); -} +}; Date.prototype.getHourMinuteSecond = function() { return this.getTwoDigitHour() + ':' + this.getTwoDigitMinute() + ':' + this.getTwoDigitSecond(); -} +}; Date.prototype.strftime = function(format) { var fields = { @@ -191,7 +191,7 @@ Date.prototype.strftime = function(format) { ++i; } return result; -} +}; // ---------------------------------------------------------------------------- // String object extensions @@ -202,42 +202,43 @@ String.prototype.pad_left = function(pad_length, pad_string) { new_string = pad_string + new_string; } return new_string; -} +}; String.prototype.strptime = function(format) { var split_format = format.split(/[.\-/]/); var date = this.split(/[.\-/]/); var i = 0; + var day, month, year; while (i < split_format.length) { switch (split_format[i]) { case "%d": - var day = date[i]; + day = date[i]; break; case "%m": - var month = date[i] - 1; + month = date[i] - 1; break; case "%Y": - var year = date[i]; + year = date[i]; break; case "%y": - var year = date[i]; + year = date[i]; break; } ++i; - }; + } return new Date(year, month, day); -} +}; // ---------------------------------------------------------------------------- // Get the computed style for and element // ---------------------------------------------------------------------------- -function getStyle(oElm, strCssRule){ +function getStyle(oElm, strCssRule) { var strValue = ""; - if(document.defaultView && document.defaultView.getComputedStyle){ + if(document.defaultView && document.defaultView.getComputedStyle) { strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule); } - else if(oElm.currentStyle){ - strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){ + else if(oElm.currentStyle) { + strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1) { return p1.toUpperCase(); }); strValue = oElm.currentStyle[strCssRule]; diff --git a/django/contrib/admin/static/admin/js/inlines.js b/django/contrib/admin/static/admin/js/inlines.js index 6f127365e6..e977fc9fa5 100644 --- a/django/contrib/admin/static/admin/js/inlines.js +++ b/django/contrib/admin/static/admin/js/inlines.js @@ -1,3 +1,4 @@ +/*global DateTimeShortcuts, SelectFilter*/ /** * Django admin inlines * @@ -15,258 +16,260 @@ * See: http://www.opensource.org/licenses/bsd-license.php */ (function($) { - $.fn.formset = function(opts) { - var options = $.extend({}, $.fn.formset.defaults, opts); - var $this = $(this); - var $parent = $this.parent(); - var updateElementIndex = function(el, prefix, ndx) { - var id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))"); - var replacement = prefix + "-" + ndx; - if ($(el).prop("for")) { - $(el).prop("for", $(el).prop("for").replace(id_regex, replacement)); - } - if (el.id) { - el.id = el.id.replace(id_regex, replacement); - } - if (el.name) { - el.name = el.name.replace(id_regex, replacement); - } - }; - var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").prop("autocomplete", "off"); - var nextIndex = parseInt(totalForms.val(), 10); - var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").prop("autocomplete", "off"); - // only show the add button if we are allowed to add more items, + $.fn.formset = function(opts) { + var options = $.extend({}, $.fn.formset.defaults, opts); + var $this = $(this); + var $parent = $this.parent(); + var updateElementIndex = function(el, prefix, ndx) { + var id_regex = new RegExp("(" + prefix + "-(\\d+|__prefix__))"); + var replacement = prefix + "-" + ndx; + if ($(el).prop("for")) { + $(el).prop("for", $(el).prop("for").replace(id_regex, replacement)); + } + if (el.id) { + el.id = el.id.replace(id_regex, replacement); + } + if (el.name) { + el.name = el.name.replace(id_regex, replacement); + } + }; + var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS").prop("autocomplete", "off"); + var nextIndex = parseInt(totalForms.val(), 10); + var maxForms = $("#id_" + options.prefix + "-MAX_NUM_FORMS").prop("autocomplete", "off"); + // only show the add button if we are allowed to add more items, // note that max_num = None translates to a blank string. - var showAddButton = maxForms.val() === '' || (maxForms.val()-totalForms.val()) > 0; - $this.each(function(i) { - $(this).not("." + options.emptyCssClass).addClass(options.formCssClass); - }); - if ($this.length && showAddButton) { - var addButton; - if ($this.prop("tagName") == "TR") { - // If forms are laid out as table rows, insert the - // "add" button in a new table row: - var numCols = this.eq(-1).children().length; - $parent.append('<tr class="' + options.addCssClass + '"><td colspan="' + numCols + '"><a href="javascript:void(0)">' + options.addText + "</a></tr>"); - addButton = $parent.find("tr:last a"); - } else { - // Otherwise, insert it immediately after the last form: - $this.filter(":last").after('<div class="' + options.addCssClass + '"><a href="javascript:void(0)">' + options.addText + "</a></div>"); - addButton = $this.filter(":last").next().find("a"); - } - addButton.click(function(e) { - e.preventDefault(); - var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS"); - var template = $("#" + options.prefix + "-empty"); - var row = template.clone(true); - row.removeClass(options.emptyCssClass) - .addClass(options.formCssClass) - .attr("id", options.prefix + "-" + nextIndex); - if (row.is("tr")) { - // If the forms are laid out in table rows, insert - // the remove button into the last table cell: - row.children(":last").append('<div><a class="' + options.deleteCssClass +'" href="javascript:void(0)">' + options.deleteText + "</a></div>"); - } else if (row.is("ul") || row.is("ol")) { - // If they're laid out as an ordered/unordered list, - // insert an <li> after the last list item: - row.append('<li><a class="' + options.deleteCssClass +'" href="javascript:void(0)">' + options.deleteText + "</a></li>"); - } else { - // Otherwise, just insert the remove button as the - // last child element of the form's container: - row.children(":first").append('<span><a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + options.deleteText + "</a></span>"); - } - row.find("*").each(function() { - updateElementIndex(this, options.prefix, totalForms.val()); + var showAddButton = maxForms.val() === '' || (maxForms.val()-totalForms.val()) > 0; + $this.each(function(i) { + $(this).not("." + options.emptyCssClass).addClass(options.formCssClass); }); - // Insert the new form when it has been fully edited - row.insertBefore($(template)); - // Update number of total forms - $(totalForms).val(parseInt(totalForms.val(), 10) + 1); - nextIndex += 1; - // Hide add button in case we've hit the max, except we want to add infinitely - if ((maxForms.val() !== '') && (maxForms.val()-totalForms.val()) <= 0) { - addButton.parent().hide(); - } - // The delete button of each row triggers a bunch of other things - row.find("a." + options.deleteCssClass).click(function(e) { - e.preventDefault(); - // Remove the parent form containing this button: - var row = $(this).parents("." + options.formCssClass); - row.remove(); - nextIndex -= 1; - // If a post-delete callback was provided, call it with the deleted form: - if (options.removed) { - options.removed(row); - } - // Update the TOTAL_FORMS form count. - var forms = $("." + options.formCssClass); - $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length); - // Show add button again once we drop below max - if ((maxForms.val() === '') || (maxForms.val()-forms.length) > 0) { - addButton.parent().show(); - } - // Also, update names and ids for all remaining form controls - // so they remain in sequence: - for (var i=0, formCount=forms.length; i<formCount; i++) - { - updateElementIndex($(forms).get(i), options.prefix, i); - $(forms.get(i)).find("*").each(function() { - updateElementIndex(this, options.prefix, i); + if ($this.length && showAddButton) { + var addButton; + if ($this.prop("tagName") === "TR") { + // If forms are laid out as table rows, insert the + // "add" button in a new table row: + var numCols = this.eq(-1).children().length; + $parent.append('<tr class="' + options.addCssClass + '"><td colspan="' + numCols + '"><a href="javascript:void(0)">' + options.addText + "</a></tr>"); + addButton = $parent.find("tr:last a"); + } else { + // Otherwise, insert it immediately after the last form: + $this.filter(":last").after('<div class="' + options.addCssClass + '"><a href="javascript:void(0)">' + options.addText + "</a></div>"); + addButton = $this.filter(":last").next().find("a"); + } + addButton.click(function(e) { + e.preventDefault(); + var totalForms = $("#id_" + options.prefix + "-TOTAL_FORMS"); + var template = $("#" + options.prefix + "-empty"); + var row = template.clone(true); + row.removeClass(options.emptyCssClass) + .addClass(options.formCssClass) + .attr("id", options.prefix + "-" + nextIndex); + if (row.is("tr")) { + // If the forms are laid out in table rows, insert + // the remove button into the last table cell: + row.children(":last").append('<div><a class="' + options.deleteCssClass +'" href="javascript:void(0)">' + options.deleteText + "</a></div>"); + } else if (row.is("ul") || row.is("ol")) { + // If they're laid out as an ordered/unordered list, + // insert an <li> after the last list item: + row.append('<li><a class="' + options.deleteCssClass +'" href="javascript:void(0)">' + options.deleteText + "</a></li>"); + } else { + // Otherwise, just insert the remove button as the + // last child element of the form's container: + row.children(":first").append('<span><a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + options.deleteText + "</a></span>"); + } + row.find("*").each(function() { + updateElementIndex(this, options.prefix, totalForms.val()); + }); + // Insert the new form when it has been fully edited + row.insertBefore($(template)); + // Update number of total forms + $(totalForms).val(parseInt(totalForms.val(), 10) + 1); + nextIndex += 1; + // Hide add button in case we've hit the max, except we want to add infinitely + if ((maxForms.val() !== '') && (maxForms.val()-totalForms.val()) <= 0) { + addButton.parent().hide(); + } + // The delete button of each row triggers a bunch of other things + row.find("a." + options.deleteCssClass).click(function(e) { + e.preventDefault(); + // Remove the parent form containing this button: + var row = $(this).parents("." + options.formCssClass); + row.remove(); + nextIndex -= 1; + // If a post-delete callback was provided, call it with the deleted form: + if (options.removed) { + options.removed(row); + } + // Update the TOTAL_FORMS form count. + var forms = $("." + options.formCssClass); + $("#id_" + options.prefix + "-TOTAL_FORMS").val(forms.length); + // Show add button again once we drop below max + if ((maxForms.val() === '') || (maxForms.val()-forms.length) > 0) { + addButton.parent().show(); + } + // Also, update names and ids for all remaining form controls + // so they remain in sequence: + var i, formCount; + var updateElementCallback = function() { + updateElementIndex(this, options.prefix, i); + }; + for (i=0, formCount=forms.length; i<formCount; i++) + { + updateElementIndex($(forms).get(i), options.prefix, i); + $(forms.get(i)).find("*").each(updateElementCallback); + } + }); + // If a post-add callback was supplied, call it with the added form: + if (options.added) { + options.added(row); + } }); - } - }); - // If a post-add callback was supplied, call it with the added form: - if (options.added) { - options.added(row); } - }); - } - return this; - }; + return this; + }; - /* Setup plugin defaults */ - $.fn.formset.defaults = { - prefix: "form", // The form prefix for your django formset - addText: "add another", // Text for the add link - deleteText: "remove", // Text for the delete link - addCssClass: "add-row", // CSS class applied to the add link - deleteCssClass: "delete-row", // CSS class applied to the delete link - emptyCssClass: "empty-row", // CSS class applied to the empty row - formCssClass: "dynamic-form", // CSS class applied to each form in a formset - added: null, // Function called each time a new form is added - removed: null // Function called each time a form is deleted - }; + /* Setup plugin defaults */ + $.fn.formset.defaults = { + prefix: "form", // The form prefix for your django formset + addText: "add another", // Text for the add link + deleteText: "remove", // Text for the delete link + addCssClass: "add-row", // CSS class applied to the add link + deleteCssClass: "delete-row", // CSS class applied to the delete link + emptyCssClass: "empty-row", // CSS class applied to the empty row + formCssClass: "dynamic-form", // CSS class applied to each form in a formset + added: null, // Function called each time a new form is added + removed: null // Function called each time a form is deleted + }; - // Tabular inlines --------------------------------------------------------- - $.fn.tabularFormset = function(options) { - var $rows = $(this); - var alternatingRows = function(row) { - $($rows.selector).not(".add-row").removeClass("row1 row2") - .filter(":even").addClass("row1").end() - .filter(":odd").addClass("row2"); - }; + // Tabular inlines --------------------------------------------------------- + $.fn.tabularFormset = function(options) { + var $rows = $(this); + var alternatingRows = function(row) { + $($rows.selector).not(".add-row").removeClass("row1 row2") + .filter(":even").addClass("row1").end() + .filter(":odd").addClass("row2"); + }; - var reinitDateTimeShortCuts = function() { - // Reinitialize the calendar and clock widgets by force - if (typeof DateTimeShortcuts != "undefined") { - $(".datetimeshortcuts").remove(); - DateTimeShortcuts.init(); - } - }; + var reinitDateTimeShortCuts = function() { + // Reinitialize the calendar and clock widgets by force + if (typeof DateTimeShortcuts !== "undefined") { + $(".datetimeshortcuts").remove(); + DateTimeShortcuts.init(); + } + }; - var updateSelectFilter = function() { - // If any SelectFilter widgets are a part of the new form, - // instantiate a new SelectFilter instance for it. - if (typeof SelectFilter != 'undefined'){ - $('.selectfilter').each(function(index, value){ - var namearr = value.name.split('-'); - SelectFilter.init(value.id, namearr[namearr.length-1], false); - }); - $('.selectfilterstacked').each(function(index, value){ - var namearr = value.name.split('-'); - SelectFilter.init(value.id, namearr[namearr.length-1], true); - }); - } - }; + var updateSelectFilter = function() { + // If any SelectFilter widgets are a part of the new form, + // instantiate a new SelectFilter instance for it. + if (typeof SelectFilter !== 'undefined') { + $('.selectfilter').each(function(index, value) { + var namearr = value.name.split('-'); + SelectFilter.init(value.id, namearr[namearr.length-1], false); + }); + $('.selectfilterstacked').each(function(index, value) { + var namearr = value.name.split('-'); + SelectFilter.init(value.id, namearr[namearr.length-1], true); + }); + } + }; + + var initPrepopulatedFields = function(row) { + row.find('.prepopulated_field').each(function() { + var field = $(this), + input = field.find('input, select, textarea'), + dependency_list = input.data('dependency_list') || [], + dependencies = []; + $.each(dependency_list, function(i, field_name) { + dependencies.push('#' + row.find('.field-' + field_name).find('input, select, textarea').attr('id')); + }); + if (dependencies.length) { + input.prepopulate(dependencies, input.attr('maxlength')); + } + }); + }; - var initPrepopulatedFields = function(row) { - row.find('.prepopulated_field').each(function() { - var field = $(this), - input = field.find('input, select, textarea'), - dependency_list = input.data('dependency_list') || [], - dependencies = []; - $.each(dependency_list, function(i, field_name) { - dependencies.push('#' + row.find('.field-' + field_name).find('input, select, textarea').attr('id')); + $rows.formset({ + prefix: options.prefix, + addText: options.addText, + formCssClass: "dynamic-" + options.prefix, + deleteCssClass: "inline-deletelink", + deleteText: options.deleteText, + emptyCssClass: "empty-form", + removed: alternatingRows, + added: function(row) { + initPrepopulatedFields(row); + reinitDateTimeShortCuts(); + updateSelectFilter(); + alternatingRows(row); + } }); - if (dependencies.length) { - input.prepopulate(dependencies, input.attr('maxlength')); - } - }); + + return $rows; }; - $rows.formset({ - prefix: options.prefix, - addText: options.addText, - formCssClass: "dynamic-" + options.prefix, - deleteCssClass: "inline-deletelink", - deleteText: options.deleteText, - emptyCssClass: "empty-form", - removed: alternatingRows, - added: function(row) { - initPrepopulatedFields(row); - reinitDateTimeShortCuts(); - updateSelectFilter(); - alternatingRows(row); - } - }); + // Stacked inlines --------------------------------------------------------- + $.fn.stackedFormset = function(options) { + var $rows = $(this); + var updateInlineLabel = function(row) { + $($rows.selector).find(".inline_label").each(function(i) { + var count = i + 1; + $(this).html($(this).html().replace(/(#\d+)/g, "#" + count)); + }); + }; - return $rows; - }; + var reinitDateTimeShortCuts = function() { + // Reinitialize the calendar and clock widgets by force, yuck. + if (typeof DateTimeShortcuts !== "undefined") { + $(".datetimeshortcuts").remove(); + DateTimeShortcuts.init(); + } + }; - // Stacked inlines --------------------------------------------------------- - $.fn.stackedFormset = function(options) { - var $rows = $(this); - var updateInlineLabel = function(row) { - $($rows.selector).find(".inline_label").each(function(i) { - var count = i + 1; - $(this).html($(this).html().replace(/(#\d+)/g, "#" + count)); - }); - }; + var updateSelectFilter = function() { + // If any SelectFilter widgets were added, instantiate a new instance. + if (typeof SelectFilter !== "undefined") { + $(".selectfilter").each(function(index, value) { + var namearr = value.name.split('-'); + SelectFilter.init(value.id, namearr[namearr.length-1], false); + }); + $(".selectfilterstacked").each(function(index, value) { + var namearr = value.name.split('-'); + SelectFilter.init(value.id, namearr[namearr.length-1], true); + }); + } + }; - var reinitDateTimeShortCuts = function() { - // Reinitialize the calendar and clock widgets by force, yuck. - if (typeof DateTimeShortcuts != "undefined") { - $(".datetimeshortcuts").remove(); - DateTimeShortcuts.init(); - } - }; + var initPrepopulatedFields = function(row) { + row.find('.prepopulated_field').each(function() { + var field = $(this), + input = field.find('input, select, textarea'), + dependency_list = input.data('dependency_list') || [], + dependencies = []; + $.each(dependency_list, function(i, field_name) { + dependencies.push('#' + row.find('.form-row .field-' + field_name).find('input, select, textarea').attr('id')); + }); + if (dependencies.length) { + input.prepopulate(dependencies, input.attr('maxlength')); + } + }); + }; - var updateSelectFilter = function() { - // If any SelectFilter widgets were added, instantiate a new instance. - if (typeof SelectFilter != "undefined"){ - $(".selectfilter").each(function(index, value){ - var namearr = value.name.split('-'); - SelectFilter.init(value.id, namearr[namearr.length-1], false); + $rows.formset({ + prefix: options.prefix, + addText: options.addText, + formCssClass: "dynamic-" + options.prefix, + deleteCssClass: "inline-deletelink", + deleteText: options.deleteText, + emptyCssClass: "empty-form", + removed: updateInlineLabel, + added: function(row) { + initPrepopulatedFields(row); + reinitDateTimeShortCuts(); + updateSelectFilter(); + updateInlineLabel(row); + } }); - $(".selectfilterstacked").each(function(index, value){ - var namearr = value.name.split('-'); - SelectFilter.init(value.id, namearr[namearr.length-1], true); - }); - } - }; - var initPrepopulatedFields = function(row) { - row.find('.prepopulated_field').each(function() { - var field = $(this), - input = field.find('input, select, textarea'), - dependency_list = input.data('dependency_list') || [], - dependencies = []; - $.each(dependency_list, function(i, field_name) { - dependencies.push('#' + row.find('.form-row .field-' + field_name).find('input, select, textarea').attr('id')); - }); - if (dependencies.length) { - input.prepopulate(dependencies, input.attr('maxlength')); - } - }); + return $rows; }; - - $rows.formset({ - prefix: options.prefix, - addText: options.addText, - formCssClass: "dynamic-" + options.prefix, - deleteCssClass: "inline-deletelink", - deleteText: options.deleteText, - emptyCssClass: "empty-form", - removed: updateInlineLabel, - added: (function(row) { - initPrepopulatedFields(row); - reinitDateTimeShortCuts(); - updateSelectFilter(); - updateInlineLabel(row); - }) - }); - - return $rows; - }; })(django.jQuery); diff --git a/django/contrib/admin/static/admin/js/inlines.min.js b/django/contrib/admin/static/admin/js/inlines.min.js index aa698cf4e1..64bcd0d8e7 100644 --- a/django/contrib/admin/static/admin/js/inlines.min.js +++ b/django/contrib/admin/static/admin/js/inlines.min.js @@ -1,9 +1,9 @@ -(function(c){c.fn.formset=function(b){var a=c.extend({},c.fn.formset.defaults,b),d=c(this);b=d.parent();var k=function(a,f,l){var h=new RegExp("("+f+"-(\\d+|__prefix__))");f=f+"-"+l;c(a).prop("for")&&c(a).prop("for",c(a).prop("for").replace(h,f));a.id&&(a.id=a.id.replace(h,f));a.name&&(a.name=a.name.replace(h,f))},e=c("#id_"+a.prefix+"-TOTAL_FORMS").prop("autocomplete","off"),l=parseInt(e.val(),10),f=c("#id_"+a.prefix+"-MAX_NUM_FORMS").prop("autocomplete","off"),e=""===f.val()||0<f.val()-e.val(); -d.each(function(f){c(this).not("."+a.emptyCssClass).addClass(a.formCssClass)});if(d.length&&e){var h;"TR"==d.prop("tagName")?(d=this.eq(-1).children().length,b.append('<tr class="'+a.addCssClass+'"><td colspan="'+d+'"><a href="javascript:void(0)">'+a.addText+"</a></tr>"),h=b.find("tr:last a")):(d.filter(":last").after('<div class="'+a.addCssClass+'"><a href="javascript:void(0)">'+a.addText+"</a></div>"),h=d.filter(":last").next().find("a"));h.click(function(b){b.preventDefault();var d=c("#id_"+a.prefix+ -"-TOTAL_FORMS");b=c("#"+a.prefix+"-empty");var g=b.clone(!0);g.removeClass(a.emptyCssClass).addClass(a.formCssClass).attr("id",a.prefix+"-"+l);g.is("tr")?g.children(":last").append('<div><a class="'+a.deleteCssClass+'" href="javascript:void(0)">'+a.deleteText+"</a></div>"):g.is("ul")||g.is("ol")?g.append('<li><a class="'+a.deleteCssClass+'" href="javascript:void(0)">'+a.deleteText+"</a></li>"):g.children(":first").append('<span><a class="'+a.deleteCssClass+'" href="javascript:void(0)">'+a.deleteText+ -"</a></span>");g.find("*").each(function(){k(this,a.prefix,d.val())});g.insertBefore(c(b));c(d).val(parseInt(d.val(),10)+1);l+=1;""!==f.val()&&0>=f.val()-d.val()&&h.parent().hide();g.find("a."+a.deleteCssClass).click(function(b){b.preventDefault();b=c(this).parents("."+a.formCssClass);b.remove();--l;a.removed&&a.removed(b);b=c("."+a.formCssClass);c("#id_"+a.prefix+"-TOTAL_FORMS").val(b.length);(""===f.val()||0<f.val()-b.length)&&h.parent().show();for(var d=0,g=b.length;d<g;d++)k(c(b).get(d),a.prefix, -d),c(b.get(d)).find("*").each(function(){k(this,a.prefix,d)})});a.added&&a.added(g)})}return this};c.fn.formset.defaults={prefix:"form",addText:"add another",deleteText:"remove",addCssClass:"add-row",deleteCssClass:"delete-row",emptyCssClass:"empty-row",formCssClass:"dynamic-form",added:null,removed:null};c.fn.tabularFormset=function(b){var a=c(this),d=function(b){c(a.selector).not(".add-row").removeClass("row1 row2").filter(":even").addClass("row1").end().filter(":odd").addClass("row2")},k=function(){"undefined"!= -typeof SelectFilter&&(c(".selectfilter").each(function(a,c){var b=c.name.split("-");SelectFilter.init(c.id,b[b.length-1],!1)}),c(".selectfilterstacked").each(function(a,c){var b=c.name.split("-");SelectFilter.init(c.id,b[b.length-1],!0)}))},e=function(a){a.find(".prepopulated_field").each(function(){var b=c(this).find("input, select, textarea"),d=b.data("dependency_list")||[],e=[];c.each(d,function(c,b){e.push("#"+a.find(".field-"+b).find("input, select, textarea").attr("id"))});e.length&&b.prepopulate(e, -b.attr("maxlength"))})};a.formset({prefix:b.prefix,addText:b.addText,formCssClass:"dynamic-"+b.prefix,deleteCssClass:"inline-deletelink",deleteText:b.deleteText,emptyCssClass:"empty-form",removed:d,added:function(a){e(a);"undefined"!=typeof DateTimeShortcuts&&(c(".datetimeshortcuts").remove(),DateTimeShortcuts.init());k();d(a)}});return a};c.fn.stackedFormset=function(b){var a=c(this),d=function(b){c(a.selector).find(".inline_label").each(function(a){a+=1;c(this).html(c(this).html().replace(/(#\d+)/g, -"#"+a))})},k=function(){"undefined"!=typeof SelectFilter&&(c(".selectfilter").each(function(a,c){var b=c.name.split("-");SelectFilter.init(c.id,b[b.length-1],!1)}),c(".selectfilterstacked").each(function(a,c){var b=c.name.split("-");SelectFilter.init(c.id,b[b.length-1],!0)}))},e=function(a){a.find(".prepopulated_field").each(function(){var b=c(this).find("input, select, textarea"),d=b.data("dependency_list")||[],e=[];c.each(d,function(b,c){e.push("#"+a.find(".form-row .field-"+c).find("input, select, textarea").attr("id"))}); -e.length&&b.prepopulate(e,b.attr("maxlength"))})};a.formset({prefix:b.prefix,addText:b.addText,formCssClass:"dynamic-"+b.prefix,deleteCssClass:"inline-deletelink",deleteText:b.deleteText,emptyCssClass:"empty-form",removed:d,added:function(a){e(a);"undefined"!=typeof DateTimeShortcuts&&(c(".datetimeshortcuts").remove(),DateTimeShortcuts.init());k();d(a)}});return a}})(django.jQuery); +(function(c){c.fn.formset=function(b){var a=c.extend({},c.fn.formset.defaults,b),d=c(this);b=d.parent();var k=function(a,g,l){var h=new RegExp("("+g+"-(\\d+|__prefix__))");g=g+"-"+l;c(a).prop("for")&&c(a).prop("for",c(a).prop("for").replace(h,g));a.id&&(a.id=a.id.replace(h,g));a.name&&(a.name=a.name.replace(h,g))},f=c("#id_"+a.prefix+"-TOTAL_FORMS").prop("autocomplete","off"),l=parseInt(f.val(),10),g=c("#id_"+a.prefix+"-MAX_NUM_FORMS").prop("autocomplete","off"),f=""===g.val()||0<g.val()-f.val(); +d.each(function(g){c(this).not("."+a.emptyCssClass).addClass(a.formCssClass)});if(d.length&&f){var h;"TR"==d.prop("tagName")?(d=this.eq(-1).children().length,b.append('<tr class="'+a.addCssClass+'"><td colspan="'+d+'"><a href="javascript:void(0)">'+a.addText+"</a></tr>"),h=b.find("tr:last a")):(d.filter(":last").after('<div class="'+a.addCssClass+'"><a href="javascript:void(0)">'+a.addText+"</a></div>"),h=d.filter(":last").next().find("a"));h.click(function(b){b.preventDefault();var d=c("#id_"+a.prefix+ +"-TOTAL_FORMS");b=c("#"+a.prefix+"-empty");var e=b.clone(!0);e.removeClass(a.emptyCssClass).addClass(a.formCssClass).attr("id",a.prefix+"-"+l);e.is("tr")?e.children(":last").append('<div><a class="'+a.deleteCssClass+'" href="javascript:void(0)">'+a.deleteText+"</a></div>"):e.is("ul")||e.is("ol")?e.append('<li><a class="'+a.deleteCssClass+'" href="javascript:void(0)">'+a.deleteText+"</a></li>"):e.children(":first").append('<span><a class="'+a.deleteCssClass+'" href="javascript:void(0)">'+a.deleteText+ +"</a></span>");e.find("*").each(function(){k(this,a.prefix,d.val())});e.insertBefore(c(b));c(d).val(parseInt(d.val(),10)+1);l+=1;""!==g.val()&&0>=g.val()-d.val()&&h.parent().hide();e.find("a."+a.deleteCssClass).click(function(b){b.preventDefault();b=c(this).parents("."+a.formCssClass);b.remove();--l;a.removed&&a.removed(b);b=c("."+a.formCssClass);c("#id_"+a.prefix+"-TOTAL_FORMS").val(b.length);(""===g.val()||0<g.val()-b.length)&&h.parent().show();for(var d=function(){k(this,a.prefix,e)},e=0,f=b.length;e< +f;e++)k(c(b).get(e),a.prefix,e),c(b.get(e)).find("*").each(d)});a.added&&a.added(e)})}return this};c.fn.formset.defaults={prefix:"form",addText:"add another",deleteText:"remove",addCssClass:"add-row",deleteCssClass:"delete-row",emptyCssClass:"empty-row",formCssClass:"dynamic-form",added:null,removed:null};c.fn.tabularFormset=function(b){var a=c(this),d=function(b){c(a.selector).not(".add-row").removeClass("row1 row2").filter(":even").addClass("row1").end().filter(":odd").addClass("row2")},k=function(){"undefined"!= +typeof SelectFilter&&(c(".selectfilter").each(function(a,c){var b=c.name.split("-");SelectFilter.init(c.id,b[b.length-1],!1)}),c(".selectfilterstacked").each(function(a,c){var b=c.name.split("-");SelectFilter.init(c.id,b[b.length-1],!0)}))},f=function(a){a.find(".prepopulated_field").each(function(){var b=c(this).find("input, select, textarea"),d=b.data("dependency_list")||[],f=[];c.each(d,function(c,b){f.push("#"+a.find(".field-"+b).find("input, select, textarea").attr("id"))});f.length&&b.prepopulate(f, +b.attr("maxlength"))})};a.formset({prefix:b.prefix,addText:b.addText,formCssClass:"dynamic-"+b.prefix,deleteCssClass:"inline-deletelink",deleteText:b.deleteText,emptyCssClass:"empty-form",removed:d,added:function(a){f(a);"undefined"!=typeof DateTimeShortcuts&&(c(".datetimeshortcuts").remove(),DateTimeShortcuts.init());k();d(a)}});return a};c.fn.stackedFormset=function(b){var a=c(this),d=function(b){c(a.selector).find(".inline_label").each(function(a){a+=1;c(this).html(c(this).html().replace(/(#\d+)/g, +"#"+a))})},k=function(){"undefined"!=typeof SelectFilter&&(c(".selectfilter").each(function(a,c){var b=c.name.split("-");SelectFilter.init(c.id,b[b.length-1],!1)}),c(".selectfilterstacked").each(function(a,c){var b=c.name.split("-");SelectFilter.init(c.id,b[b.length-1],!0)}))},f=function(a){a.find(".prepopulated_field").each(function(){var b=c(this).find("input, select, textarea"),d=b.data("dependency_list")||[],f=[];c.each(d,function(b,c){f.push("#"+a.find(".form-row .field-"+c).find("input, select, textarea").attr("id"))}); +f.length&&b.prepopulate(f,b.attr("maxlength"))})};a.formset({prefix:b.prefix,addText:b.addText,formCssClass:"dynamic-"+b.prefix,deleteCssClass:"inline-deletelink",deleteText:b.deleteText,emptyCssClass:"empty-form",removed:d,added:function(a){f(a);"undefined"!=typeof DateTimeShortcuts&&(c(".datetimeshortcuts").remove(),DateTimeShortcuts.init());k();d(a)}});return a}})(django.jQuery); diff --git a/django/contrib/admin/static/admin/js/jquery.init.js b/django/contrib/admin/static/admin/js/jquery.init.js index 22a4c8bfd3..f3ac162514 100644 --- a/django/contrib/admin/static/admin/js/jquery.init.js +++ b/django/contrib/admin/static/admin/js/jquery.init.js @@ -1,3 +1,4 @@ +/*global django:true, jQuery:false*/ /* Puts the included jQuery into our own namespace using noConflict and passing * it 'true'. This ensures that the included jQuery doesn't pollute the global * namespace (i.e. this preserves pre-existing values for both window.$ and diff --git a/django/contrib/admin/static/admin/js/prepopulate.js b/django/contrib/admin/static/admin/js/prepopulate.js index db7903a5ef..1b268999f3 100644 --- a/django/contrib/admin/static/admin/js/prepopulate.js +++ b/django/contrib/admin/static/admin/js/prepopulate.js @@ -1,3 +1,4 @@ +/*global URLify*/ (function($) { $.fn.prepopulate = function(dependencies, maxLength) { /* diff --git a/django/contrib/admin/static/admin/js/prepopulate.min.js b/django/contrib/admin/static/admin/js/prepopulate.min.js index 4a75827c97..dfac041b40 100644 --- a/django/contrib/admin/static/admin/js/prepopulate.min.js +++ b/django/contrib/admin/static/admin/js/prepopulate.min.js @@ -1 +1 @@ -(function(b){b.fn.prepopulate=function(e,g){return this.each(function(){var a=b(this),d=function(){if(!a.data("_changed")){var f=[];b.each(e,function(h,c){c=b(c);c.val().length>0&&f.push(c.val())});a.val(URLify(f.join(" "),g))}};a.data("_changed",false);a.change(function(){a.data("_changed",true)});a.val()||b(e.join(",")).keyup(d).change(d).focus(d)})}})(django.jQuery); +(function(c){c.fn.prepopulate=function(e,f){return this.each(function(){var a=c(this),b=function(){if(!a.data("_changed")){var b=[];c.each(e,function(a,d){d=c(d);0<d.val().length&&b.push(d.val())});a.val(URLify(b.join(" "),f))}};a.data("_changed",!1);a.change(function(){a.data("_changed",!0)});a.val()||c(e.join(",")).keyup(b).change(b).focus(b)})}})(django.jQuery); diff --git a/django/contrib/admin/static/admin/js/timeparse.js b/django/contrib/admin/static/admin/js/timeparse.js index 882f41d56e..50747c8199 100644 --- a/django/contrib/admin/static/admin/js/timeparse.js +++ b/django/contrib/admin/static/admin/js/timeparse.js @@ -2,7 +2,7 @@ var timeParsePatterns = [ // 9 { re: /^\d{1,2}$/i, handler: function(bits) { - if (bits[0].length == 1) { + if (bits[0].length === 1) { return '0' + bits[0] + ':00'; } else { return bits[0] + ':00'; @@ -25,11 +25,11 @@ var timeParsePatterns = [ { re: /^(\d+)\s*([ap])(?:.?m.?)?$/i, handler: function(bits) { var hour = parseInt(bits[1]); - if (hour == 12) { + if (hour === 12) { hour = 0; } - if (bits[2].toLowerCase() == 'p') { - if (hour == 12) { + if (bits[2].toLowerCase() === 'p') { + if (hour === 12) { hour = 0; } return (hour + 12) + ':00'; @@ -50,11 +50,11 @@ var timeParsePatterns = [ if (mins < 10) { mins = '0' + mins; } - if (hour == 12) { + if (hour === 12) { hour = 0; } - if (bits[3].toLowerCase() == 'p') { - if (hour == 12) { + if (bits[3].toLowerCase() === 'p') { + if (hour === 12) { hour = 0; } return (hour + 12) + ':' + mins; diff --git a/django/contrib/gis/static/gis/js/OLMapWidget.js b/django/contrib/gis/static/gis/js/OLMapWidget.js index e743310632..fde1f3cf23 100644 --- a/django/contrib/gis/static/gis/js/OLMapWidget.js +++ b/django/contrib/gis/static/gis/js/OLMapWidget.js @@ -1,10 +1,12 @@ +/*global OpenLayers*/ +/*eslint indent:1*/ (function() { -/** - * Transforms an array of features to a single feature with the merged - * geometry of geom_type - */ + /** + * Transforms an array of features to a single feature with the merged + * geometry of geom_type + */ OpenLayers.Util.properFeatures = function(features, geom_type) { - if (features.constructor == Array) { + if (features.constructor === Array) { var geoms = []; for (var i=0; i<features.length; i++) { geoms.push(features[i].geometry); @@ -13,7 +15,7 @@ OpenLayers.Util.properFeatures = function(features, geom_type) { features = new OpenLayers.Feature.Vector(geom); } return features; -} +}; /** * @requires OpenLayers/Format/WKT.js @@ -128,7 +130,7 @@ OpenLayers.Format.DjangoWKT = OpenLayers.Class(OpenLayers.Format.WKT, { geometry = geometry.clone(); geometry.transform(this.internalProjection, this.externalProjection); } - var wktType = type == 'collection' ? 'GEOMETRYCOLLECTION' : type.toUpperCase(); + var wktType = type === 'collection' ? 'GEOMETRYCOLLECTION' : type.toUpperCase(); var data = wktType + '(' + this.extract[type].apply(this, [geometry]) + ')'; return data; }, @@ -138,8 +140,8 @@ OpenLayers.Format.DjangoWKT = OpenLayers.Class(OpenLayers.Format.WKT, { * geometrycollections. */ write: function(features) { - var collection, geometry, type, data, isCollection; - isCollection = features.geometry.CLASS_NAME == "OpenLayers.Geometry.Collection"; + var collection, isCollection; + isCollection = features.geometry.CLASS_NAME === "OpenLayers.Geometry.Collection"; var pieces = []; if (isCollection) { collection = features.geometry.components; @@ -168,8 +170,8 @@ function MapWidget(options) { this.wkt_f = new OpenLayers.Format.DjangoWKT(); // Mapping from OGRGeomType name to OpenLayers.Geometry name - if (options['geom_name'] == 'Unknown') options['geom_type'] = OpenLayers.Geometry; - else if (options['geom_name'] == 'GeometryCollection') options['geom_type'] = OpenLayers.Geometry.Collection; + if (options['geom_name'] === 'Unknown') options['geom_type'] = OpenLayers.Geometry; + else if (options['geom_name'] === 'GeometryCollection') options['geom_type'] = OpenLayers.Geometry.Collection; else options['geom_type'] = eval('OpenLayers.Geometry.' + options['geom_name']); // Default options @@ -204,7 +206,7 @@ function MapWidget(options) { 'fillOpacity': this.options.opacity, 'strokeColor': '#' + this.options.color }; - if (this.options.geom_name == 'LineString') { + if (this.options.geom_name === 'LineString') { defaults_style['strokeWidth'] = 3; } var styleMap = new OpenLayers.StyleMap({'default': OpenLayers.Util.applyDefaults(defaults_style, OpenLayers.Feature.Vector.style['default'])}); @@ -222,7 +224,7 @@ function MapWidget(options) { this.layers.vector.addFeatures([feat]); } this.map.zoomToExtent(feat.geometry.getBounds()); - if (this.options.geom_name == 'Point') { + if (this.options.geom_name === 'Point') { this.map.zoomTo(this.options.point_zoom); } } else { @@ -262,7 +264,7 @@ MapWidget.prototype.create_map = function() { if (this.options.base_layer) this.layers.base = this.options.base_layer; else this.layers.base = new OpenLayers.Layer.WMS('OpenLayers WMS', 'http://vmap0.tiles.osgeo.org/wms/vmap0', {layers: 'basic'}); map.addLayer(this.layers.base); - return map + return map; }; MapWidget.prototype.get_ewkt = function(feat) { @@ -270,7 +272,7 @@ MapWidget.prototype.get_ewkt = function(feat) { }; MapWidget.prototype.read_wkt = function(wkt) { - var prefix = 'SRID=' + this.options.map_srid + ';' + var prefix = 'SRID=' + this.options.map_srid + ';'; if (wkt.indexOf(prefix) === 0) { wkt = wkt.slice(prefix.length); } @@ -296,7 +298,7 @@ MapWidget.prototype.add_wkt = function(event) { this.write_wkt(feat); } else { if (this.layers.vector.features.length > 1) { - old_feats = [this.layers.vector.features[0]]; + var old_feats = [this.layers.vector.features[0]]; this.layers.vector.removeFeatures(old_feats); this.layers.vector.destroyFeatures(old_feats); } @@ -306,7 +308,7 @@ MapWidget.prototype.add_wkt = function(event) { MapWidget.prototype.modify_wkt = function(event) { if (this.options.is_collection) { - if (this.options.geom_name == 'MultiPoint') { + if (this.options.geom_name === 'MultiPoint') { this.add_wkt(event); return; } else { @@ -359,13 +361,13 @@ MapWidget.prototype.getControls = function(layer) { this.controls = [new OpenLayers.Control.Navigation()]; if (!this.options.modifiable && layer.features.length) return; - if (this.options.geom_name.indexOf('LineString') >= 0 || this.options.geom_name == 'GeometryCollection' || this.options.geom_name == 'Unknown') { + if (this.options.geom_name.indexOf('LineString') >= 0 || this.options.geom_name === 'GeometryCollection' || this.options.geom_name === 'Unknown') { this.controls.push(new OpenLayers.Control.DrawFeature(layer, OpenLayers.Handler.Path, {'displayClass': 'olControlDrawFeaturePath'})); } - if (this.options.geom_name.indexOf('Polygon') >= 0 || this.options.geom_name == 'GeometryCollection' || this.options.geom_name == 'Unknown') { + if (this.options.geom_name.indexOf('Polygon') >= 0 || this.options.geom_name === 'GeometryCollection' || this.options.geom_name === 'Unknown') { this.controls.push(new OpenLayers.Control.DrawFeature(layer, OpenLayers.Handler.Polygon, {'displayClass': 'olControlDrawFeaturePolygon'})); } - if (this.options.geom_name.indexOf('Point') >= 0 || this.options.geom_name == 'GeometryCollection' || this.options.geom_name == 'Unknown') { + if (this.options.geom_name.indexOf('Point') >= 0 || this.options.geom_name === 'GeometryCollection' || this.options.geom_name === 'Unknown') { this.controls.push(new OpenLayers.Control.DrawFeature(layer, OpenLayers.Handler.Point, {'displayClass': 'olControlDrawFeaturePoint'})); } if (this.options.modifiable) { diff --git a/django/contrib/gis/templates/gis/admin/openlayers.js b/django/contrib/gis/templates/gis/admin/openlayers.js index 4425fee27e..dd00bfd70a 100644 --- a/django/contrib/gis/templates/gis/admin/openlayers.js +++ b/django/contrib/gis/templates/gis/admin/openlayers.js @@ -12,98 +12,98 @@ OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:3857", OpenLayers.Layer.Sp {{ module }}.is_point = {{ is_point|yesno:"true,false" }}; {% endblock %} {{ module }}.get_ewkt = function(feat){ - return 'SRID={{ srid|unlocalize }};' + {{ module }}.wkt_f.write(feat); + return 'SRID={{ srid|unlocalize }};' + {{ module }}.wkt_f.write(feat); }; {{ module }}.read_wkt = function(wkt){ - // OpenLayers cannot handle EWKT -- we make sure to strip it out. - // EWKT is only exposed to OL if there's a validation error in the admin. - var match = {{ module }}.re.exec(wkt); - if (match){wkt = match[1];} - return {{ module }}.wkt_f.read(wkt); + // OpenLayers cannot handle EWKT -- we make sure to strip it out. + // EWKT is only exposed to OL if there's a validation error in the admin. + var match = {{ module }}.re.exec(wkt); + if (match){wkt = match[1];} + return {{ module }}.wkt_f.read(wkt); }; {{ module }}.write_wkt = function(feat){ - if ({{ module }}.is_collection){ {{ module }}.num_geom = feat.geometry.components.length;} - else { {{ module }}.num_geom = 1;} - document.getElementById('{{ id }}').value = {{ module }}.get_ewkt(feat); + if ({{ module }}.is_collection){ {{ module }}.num_geom = feat.geometry.components.length;} + else { {{ module }}.num_geom = 1;} + document.getElementById('{{ id }}').value = {{ module }}.get_ewkt(feat); }; {{ module }}.add_wkt = function(event){ - // This function will sync the contents of the `vector` layer with the - // WKT in the text field. - if ({{ module }}.is_collection){ - var feat = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.{{ geom_type }}()); - for (var i = 0; i < {{ module }}.layers.vector.features.length; i++){ - feat.geometry.addComponents([{{ module }}.layers.vector.features[i].geometry]); - } - {{ module }}.write_wkt(feat); - } else { - // Make sure to remove any previously added features. - if ({{ module }}.layers.vector.features.length > 1){ - old_feats = [{{ module }}.layers.vector.features[0]]; - {{ module }}.layers.vector.removeFeatures(old_feats); - {{ module }}.layers.vector.destroyFeatures(old_feats); + // This function will sync the contents of the `vector` layer with the + // WKT in the text field. + if ({{ module }}.is_collection){ + var feat = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.{{ geom_type }}()); + for (var i = 0; i < {{ module }}.layers.vector.features.length; i++){ + feat.geometry.addComponents([{{ module }}.layers.vector.features[i].geometry]); + } + {{ module }}.write_wkt(feat); + } else { + // Make sure to remove any previously added features. + if ({{ module }}.layers.vector.features.length > 1){ + old_feats = [{{ module }}.layers.vector.features[0]]; + {{ module }}.layers.vector.removeFeatures(old_feats); + {{ module }}.layers.vector.destroyFeatures(old_feats); + } + {{ module }}.write_wkt(event.feature); } - {{ module }}.write_wkt(event.feature); - } }; {{ module }}.modify_wkt = function(event){ - if ({{ module }}.is_collection){ - if ({{ module }}.is_point){ - {{ module }}.add_wkt(event); - return; + if ({{ module }}.is_collection){ + if ({{ module }}.is_point){ + {{ module }}.add_wkt(event); + return; + } else { + // When modifying the selected components are added to the + // vector layer so we only increment to the `num_geom` value. + var feat = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.{{ geom_type }}()); + for (var i = 0; i < {{ module }}.num_geom; i++){ + feat.geometry.addComponents([{{ module }}.layers.vector.features[i].geometry]); + } + {{ module }}.write_wkt(feat); + } } else { - // When modifying the selected components are added to the - // vector layer so we only increment to the `num_geom` value. - var feat = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.{{ geom_type }}()); - for (var i = 0; i < {{ module }}.num_geom; i++){ - feat.geometry.addComponents([{{ module }}.layers.vector.features[i].geometry]); - } - {{ module }}.write_wkt(feat); + {{ module }}.write_wkt(event.feature); } - } else { - {{ module }}.write_wkt(event.feature); - } }; // Function to clear vector features and purge wkt from div {{ module }}.deleteFeatures = function(){ - {{ module }}.layers.vector.removeFeatures({{ module }}.layers.vector.features); - {{ module }}.layers.vector.destroyFeatures(); + {{ module }}.layers.vector.removeFeatures({{ module }}.layers.vector.features); + {{ module }}.layers.vector.destroyFeatures(); }; {{ module }}.clearFeatures = function (){ - {{ module }}.deleteFeatures(); - document.getElementById('{{ id }}').value = ''; - {% localize off %} - {{ module }}.map.setCenter(new OpenLayers.LonLat({{ default_lon }}, {{ default_lat }}), {{ default_zoom }}); - {% endlocalize %} + {{ module }}.deleteFeatures(); + document.getElementById('{{ id }}').value = ''; + {% localize off %} + {{ module }}.map.setCenter(new OpenLayers.LonLat({{ default_lon }}, {{ default_lat }}), {{ default_zoom }}); + {% endlocalize %} }; // Add Select control {{ module }}.addSelectControl = function(){ - var select = new OpenLayers.Control.SelectFeature({{ module }}.layers.vector, {'toggle' : true, 'clickout' : true}); - {{ module }}.map.addControl(select); - select.activate(); + var select = new OpenLayers.Control.SelectFeature({{ module }}.layers.vector, {'toggle' : true, 'clickout' : true}); + {{ module }}.map.addControl(select); + select.activate(); }; {{ module }}.enableDrawing = function(){ - {{ module }}.map.getControlsByClass('OpenLayers.Control.DrawFeature')[0].activate(); + {{ module }}.map.getControlsByClass('OpenLayers.Control.DrawFeature')[0].activate(); }; {{ module }}.enableEditing = function(){ - {{ module }}.map.getControlsByClass('OpenLayers.Control.ModifyFeature')[0].activate(); + {{ module }}.map.getControlsByClass('OpenLayers.Control.ModifyFeature')[0].activate(); }; // Create an array of controls based on geometry type {{ module }}.getControls = function(lyr){ - {{ module }}.panel = new OpenLayers.Control.Panel({'displayClass': 'olControlEditingToolbar'}); - {{ module }}.controls = [new OpenLayers.Control.Navigation()]; - if (!{{ module }}.modifiable && lyr.features.length) return; - if ({{ module }}.is_linestring || {{ module }}.is_generic){ - {{ module }}.controls.push(new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Path, {'displayClass': 'olControlDrawFeaturePath'})); - } - if ({{ module }}.is_polygon || {{ module }}.is_generic){ - {{ module }}.controls.push(new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Polygon, {'displayClass': 'olControlDrawFeaturePolygon'})); - } - if ({{ module }}.is_point || {{ module }}.is_generic){ - {{ module }}.controls.push(new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Point, {'displayClass': 'olControlDrawFeaturePoint'})); - } - if ({{ module }}.modifiable){ - {{ module }}.controls.push(new OpenLayers.Control.ModifyFeature(lyr, {'displayClass': 'olControlModifyFeature'})); - } + {{ module }}.panel = new OpenLayers.Control.Panel({'displayClass': 'olControlEditingToolbar'}); + {{ module }}.controls = [new OpenLayers.Control.Navigation()]; + if (!{{ module }}.modifiable && lyr.features.length) return; + if ({{ module }}.is_linestring || {{ module }}.is_generic){ + {{ module }}.controls.push(new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Path, {'displayClass': 'olControlDrawFeaturePath'})); + } + if ({{ module }}.is_polygon || {{ module }}.is_generic){ + {{ module }}.controls.push(new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Polygon, {'displayClass': 'olControlDrawFeaturePolygon'})); + } + if ({{ module }}.is_point || {{ module }}.is_generic){ + {{ module }}.controls.push(new OpenLayers.Control.DrawFeature(lyr, OpenLayers.Handler.Point, {'displayClass': 'olControlDrawFeaturePoint'})); + } + if ({{ module }}.modifiable){ + {{ module }}.controls.push(new OpenLayers.Control.ModifyFeature(lyr, {'displayClass': 'olControlModifyFeature'})); + } }; {{ module }}.init = function(){ {% block map_options %}// The options hash, w/ zoom, resolution, and projection settings. @@ -124,28 +124,28 @@ OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:3857", OpenLayers.Layer.Sp // Read WKT from the text field. var wkt = document.getElementById('{{ id }}').value; if (wkt){ - // After reading into geometry, immediately write back to - // WKT <textarea> as EWKT (so that SRID is included). - var admin_geom = {{ module }}.read_wkt(wkt); - {{ module }}.write_wkt(admin_geom); - if ({{ module }}.is_collection){ - // If geometry collection, add each component individually so they may be - // edited individually. - for (var i = 0; i < {{ module }}.num_geom; i++){ - {{ module }}.layers.vector.addFeatures([new OpenLayers.Feature.Vector(admin_geom.geometry.components[i].clone())]); + // After reading into geometry, immediately write back to + // WKT <textarea> as EWKT (so that SRID is included). + var admin_geom = {{ module }}.read_wkt(wkt); + {{ module }}.write_wkt(admin_geom); + if ({{ module }}.is_collection){ + // If geometry collection, add each component individually so they may be + // edited individually. + for (var i = 0; i < {{ module }}.num_geom; i++){ + {{ module }}.layers.vector.addFeatures([new OpenLayers.Feature.Vector(admin_geom.geometry.components[i].clone())]); + } + } else { + {{ module }}.layers.vector.addFeatures([admin_geom]); + } + // Zooming to the bounds. + {{ module }}.map.zoomToExtent(admin_geom.geometry.getBounds()); + if ({{ module }}.is_point){ + {{ module }}.map.zoomTo({{ point_zoom }}); } - } else { - {{ module }}.layers.vector.addFeatures([admin_geom]); - } - // Zooming to the bounds. - {{ module }}.map.zoomToExtent(admin_geom.geometry.getBounds()); - if ({{ module }}.is_point){ - {{ module }}.map.zoomTo({{ point_zoom }}); - } } else { - {% localize off %} - {{ module }}.map.setCenter(new OpenLayers.LonLat({{ default_lon }}, {{ default_lat }}), {{ default_zoom }}); - {% endlocalize %} + {% localize off %} + {{ module }}.map.setCenter(new OpenLayers.LonLat({{ default_lon }}, {{ default_lat }}), {{ default_zoom }}); + {% endlocalize %} } // This allows editing of the geographic fields -- the modified WKT is // written back to the content field (as EWKT, so that the ORM will know @@ -167,10 +167,10 @@ OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:3857", OpenLayers.Layer.Sp {% if not scrollable %}{{ module }}.map.getControlsByClass('OpenLayers.Control.Navigation')[0].disableZoomWheel();{% endif %} {% endblock %} if (wkt){ - if ({{ module }}.modifiable){ - {{ module }}.enableEditing(); - } + if ({{ module }}.modifiable){ + {{ module }}.enableEditing(); + } } else { - {{ module }}.enableDrawing(); + {{ module }}.enableDrawing(); } }; diff --git a/docs/internals/contributing/writing-code/coding-style.txt b/docs/internals/contributing/writing-code/coding-style.txt index 2aa967c88d..54c2bd47e2 100644 --- a/docs/internals/contributing/writing-code/coding-style.txt +++ b/docs/internals/contributing/writing-code/coding-style.txt @@ -7,6 +7,11 @@ Please follow these coding standards when writing code for inclusion in Django. Python style ------------ +* Please conform to the indentation style dictated in the ``.editorconfig`` + file. We recommend using a text editor with `EditorConfig`_ support to avoid + indentation and whitespace issues. The Python files use 4 spaces for + indentation and the HTML files use 2 spaces. + * Unless otherwise specified, follow :pep:`8`. Use `flake8`_ to check for problems in this area. Note that our ``setup.cfg`` @@ -286,4 +291,11 @@ Miscellaneous change to the ``AUTHORS`` file in your patch if you make more than a single trivial change. +JavaScript style +---------------- + +For details about the JavaScript code style used by Django, see +:doc:`javascript`. + +.. _editorconfig: http://editorconfig.org/ .. _flake8: https://pypi.python.org/pypi/flake8 diff --git a/docs/internals/contributing/writing-code/index.txt b/docs/internals/contributing/writing-code/index.txt index fe9c3cc933..98e2b8dfa2 100644 --- a/docs/internals/contributing/writing-code/index.txt +++ b/docs/internals/contributing/writing-code/index.txt @@ -13,3 +13,4 @@ chances to be included in Django core: unit-tests submitting-patches working-with-git + javascript diff --git a/docs/internals/contributing/writing-code/javascript.txt b/docs/internals/contributing/writing-code/javascript.txt new file mode 100644 index 0000000000..fa3685720e --- /dev/null +++ b/docs/internals/contributing/writing-code/javascript.txt @@ -0,0 +1,64 @@ +========== +JavaScript +========== + +While most of Django core is Python, the ``admin`` and ``gis`` contrib apps +contain JavaScript code. + +Please follow these coding standards when writing JavaScript code for inclusion +in Django. + +Code style +---------- + +* Please conform to the indentation style dictated in the ``.editorconfig`` + file. We recommend using a text editor with `EditorConfig`_ support to avoid + indentation and whitespace issues. Most of the JavaScript files use 4 spaces + for indentation, but there are some exceptions. + +* When naming variables, use ``camelCase`` instead of ``underscore_case``. + Different JavaScript files sometimes use a different code style. Please try to + conform to the code style of each file. + +* Use the `JSHint`_ code linter to check your code for bugs and style errors. + JSHint will be run when you run the JavaScript tests. We also recommended + installing a JSHint plugin in your text editor. + +.. _javascript-patches: + +JavaScript patches +------------------ + +Django's admin system leverages the jQuery framework to increase the +capabilities of the admin interface. In conjunction, there is an emphasis on +admin JavaScript performance and minimizing overall admin media file size. +Serving compressed or "minified" versions of JavaScript files is considered +best practice in this regard. + +To that end, patches for JavaScript files should include both the original +code for future development (e.g. ``foo.js``), and a compressed version for +production use (e.g. ``foo.min.js``). Any links to the file in the codebase +should point to the compressed version. + +Compressing JavaScript +~~~~~~~~~~~~~~~~~~~~~~ + +To simplify the process of providing optimized JavaScript code, Django +includes a handy Python script which should be used to create a "minified" +version. To run it:: + + python django/contrib/admin/bin/compress.py + +Behind the scenes, ``compress.py`` is a front-end for Google's +`Closure Compiler`_ which is written in Java. However, the Closure Compiler +library is not bundled with Django directly, so those wishing to contribute +complete JavaScript patches will need to download and install the library +independently. The Closure Compiler library requires `Java`_ 7 or higher. + +Please don't forget to run ``compress.py`` and include the ``diff`` of the +minified scripts when submitting patches for Django's JavaScript. + +.. _Closure Compiler: https://developers.google.com/closure/compiler/ +.. _EditorConfig: http://editorconfig.org/ +.. _Java: https://www.java.com +.. _jshint: http://jshint.com/ diff --git a/docs/internals/contributing/writing-code/submitting-patches.txt b/docs/internals/contributing/writing-code/submitting-patches.txt index d9302169b6..bc7503518f 100644 --- a/docs/internals/contributing/writing-code/submitting-patches.txt +++ b/docs/internals/contributing/writing-code/submitting-patches.txt @@ -145,6 +145,8 @@ Regardless of the way you submit your work, follow these steps. obvious that the ticket includes a patch, and it will add the ticket to the `list of tickets with patches`_. +.. _list of tickets with patches: https://code.djangoproject.com/query?status=new&status=assigned&status=reopened&has_patch=1&order=priority +.. _ticket tracker: https://code.djangoproject.com/newticket Non-trivial patches ------------------- @@ -245,39 +247,8 @@ the new version are removed. JavaScript patches ------------------ -Django's admin system leverages the jQuery framework to increase the -capabilities of the admin interface. In conjunction, there is an emphasis on -admin JavaScript performance and minimizing overall admin media file size. -Serving compressed or "minified" versions of JavaScript files is considered -best practice in this regard. - -To that end, patches for JavaScript files should include both the original -code for future development (e.g. ``foo.js``), and a compressed version for -production use (e.g. ``foo.min.js``). Any links to the file in the codebase -should point to the compressed version. - -Compressing JavaScript -~~~~~~~~~~~~~~~~~~~~~~ - -To simplify the process of providing optimized JavaScript code, Django -includes a handy Python script which should be used to create a "minified" -version. To run it:: - - python django/contrib/admin/bin/compress.py - -Behind the scenes, ``compress.py`` is a front-end for Google's -`Closure Compiler`_ which is written in Java. However, the Closure Compiler -library is not bundled with Django directly, so those wishing to contribute -complete JavaScript patches will need to download and install the library -independently. The Closure Compiler library requires `Java`_ 7 or higher. - -Please don't forget to run ``compress.py`` and include the ``diff`` of the -minified scripts when submitting patches for Django's JavaScript. - -.. _Closure Compiler: https://developers.google.com/closure/compiler/ -.. _list of tickets with patches: https://code.djangoproject.com/query?status=new&status=assigned&status=reopened&has_patch=1&order=priority -.. _ticket tracker: https://code.djangoproject.com/newticket -.. _Java: https://www.java.com +For information on JavaScript patches, see the :ref:`javascript-patches` +documentation. .. _patch-review-checklist: diff --git a/package.json b/package.json new file mode 100644 index 0000000000..3370c8c04e --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "name": "Django", + "private": true, + "scripts": { + "pretest": "eslint django/" + }, + "devDependencies": { + "eslint": "^0.22.1" + } +} |