2021-04-11 19:51:12 +00:00
/*global gettext, interpolate, ngettext*/
'use strict' ;
{
function show ( selector ) {
document . querySelectorAll ( selector ) . forEach ( function ( el ) {
el . classList . remove ( 'hidden' ) ;
} ) ;
}
function hide ( selector ) {
document . querySelectorAll ( selector ) . forEach ( function ( el ) {
el . classList . add ( 'hidden' ) ;
} ) ;
}
function showQuestion ( options ) {
hide ( options . acrossClears ) ;
show ( options . acrossQuestions ) ;
hide ( options . allContainer ) ;
}
function showClear ( options ) {
show ( options . acrossClears ) ;
hide ( options . acrossQuestions ) ;
document . querySelector ( options . actionContainer ) . classList . remove ( options . selectedClass ) ;
show ( options . allContainer ) ;
hide ( options . counterContainer ) ;
}
function reset ( options ) {
hide ( options . acrossClears ) ;
hide ( options . acrossQuestions ) ;
hide ( options . allContainer ) ;
show ( options . counterContainer ) ;
}
function clearAcross ( options ) {
reset ( options ) ;
2021-12-14 14:37:47 +00:00
const acrossInputs = document . querySelectorAll ( options . acrossInput ) ;
acrossInputs . forEach ( function ( acrossInput ) {
acrossInput . value = 0 ;
} ) ;
2021-04-11 19:51:12 +00:00
document . querySelector ( options . actionContainer ) . classList . remove ( options . selectedClass ) ;
}
function checker ( actionCheckboxes , options , checked ) {
if ( checked ) {
showQuestion ( options ) ;
} else {
reset ( options ) ;
}
actionCheckboxes . forEach ( function ( el ) {
el . checked = checked ;
el . closest ( 'tr' ) . classList . toggle ( options . selectedClass , checked ) ;
} ) ;
}
function updateCounter ( actionCheckboxes , options ) {
const sel = Array . from ( actionCheckboxes ) . filter ( function ( el ) {
return el . checked ;
} ) . length ;
const counter = document . querySelector ( options . counterContainer ) ;
// data-actions-icnt is defined in the generated HTML
// and contains the total amount of objects in the queryset
const actions _icnt = Number ( counter . dataset . actionsIcnt ) ;
counter . textContent = interpolate (
ngettext ( '%(sel)s of %(cnt)s selected' , '%(sel)s of %(cnt)s selected' , sel ) , {
sel : sel ,
cnt : actions _icnt
} , true ) ;
const allToggle = document . getElementById ( options . allToggleId ) ;
allToggle . checked = sel === actionCheckboxes . length ;
if ( allToggle . checked ) {
showQuestion ( options ) ;
} else {
clearAcross ( options ) ;
}
}
const 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" ,
allToggleId : "action-toggle" ,
selectedClass : "selected"
} ;
window . Actions = function ( actionCheckboxes , options ) {
options = Object . assign ( { } , defaults , options ) ;
let list _editable _changed = false ;
2021-06-08 03:50:52 +00:00
let lastChecked = null ;
let shiftPressed = false ;
document . addEventListener ( 'keydown' , ( event ) => {
shiftPressed = event . shiftKey ;
} ) ;
document . addEventListener ( 'keyup' , ( event ) => {
shiftPressed = event . shiftKey ;
} ) ;
2021-04-11 19:51:12 +00:00
document . getElementById ( options . allToggleId ) . addEventListener ( 'click' , function ( event ) {
checker ( actionCheckboxes , options , this . checked ) ;
updateCounter ( actionCheckboxes , options ) ;
} ) ;
document . querySelectorAll ( options . acrossQuestions + " a" ) . forEach ( function ( el ) {
el . addEventListener ( 'click' , function ( event ) {
event . preventDefault ( ) ;
2021-12-14 14:37:47 +00:00
const acrossInputs = document . querySelectorAll ( options . acrossInput ) ;
acrossInputs . forEach ( function ( acrossInput ) {
acrossInput . value = 1 ;
} ) ;
2021-04-11 19:51:12 +00:00
showClear ( options ) ;
} ) ;
} ) ;
document . querySelectorAll ( options . acrossClears + " a" ) . forEach ( function ( el ) {
el . addEventListener ( 'click' , function ( event ) {
event . preventDefault ( ) ;
document . getElementById ( options . allToggleId ) . checked = false ;
clearAcross ( options ) ;
checker ( actionCheckboxes , options , false ) ;
updateCounter ( actionCheckboxes , options ) ;
} ) ;
} ) ;
2021-06-08 03:50:52 +00:00
function affectedCheckboxes ( target , withModifier ) {
const multiSelect = ( lastChecked && withModifier && lastChecked !== target ) ;
if ( ! multiSelect ) {
return [ target ] ;
}
const checkboxes = Array . from ( actionCheckboxes ) ;
const targetIndex = checkboxes . findIndex ( el => el === target ) ;
const lastCheckedIndex = checkboxes . findIndex ( el => el === lastChecked ) ;
const startIndex = Math . min ( targetIndex , lastCheckedIndex ) ;
const endIndex = Math . max ( targetIndex , lastCheckedIndex ) ;
const filtered = checkboxes . filter ( ( el , index ) => ( startIndex <= index ) && ( index <= endIndex ) ) ;
return filtered ;
} ;
2021-04-11 19:51:12 +00:00
Array . from ( document . getElementById ( 'result_list' ) . tBodies ) . forEach ( function ( el ) {
el . addEventListener ( 'change' , function ( event ) {
const target = event . target ;
if ( target . classList . contains ( 'action-select' ) ) {
2021-06-08 03:50:52 +00:00
const checkboxes = affectedCheckboxes ( target , shiftPressed ) ;
checker ( checkboxes , options , target . checked ) ;
2021-04-11 19:51:12 +00:00
updateCounter ( actionCheckboxes , options ) ;
2021-06-08 03:50:52 +00:00
lastChecked = target ;
2021-04-11 19:51:12 +00:00
} else {
list _editable _changed = true ;
}
} ) ;
} ) ;
2022-02-21 17:46:35 +00:00
document . querySelector ( '#changelist-form button[name=index]' ) . addEventListener ( 'click' , function ( event ) {
2021-04-11 19:51:12 +00:00
if ( list _editable _changed ) {
const confirmed = confirm ( gettext ( "You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost." ) ) ;
if ( ! confirmed ) {
event . preventDefault ( ) ;
}
}
} ) ;
const el = document . querySelector ( '#changelist-form input[name=_save]' ) ;
// The button does not exist if no fields are editable.
if ( el ) {
el . addEventListener ( 'click' , function ( event ) {
if ( document . querySelector ( '[name=action]' ) . value ) {
const text = list _editable _changed
? 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." )
: 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." ) ;
if ( ! confirm ( text ) ) {
event . preventDefault ( ) ;
}
}
} ) ;
}
2024-01-28 03:41:10 +00:00
// Sync counter when navigating to the page, such as through the back
// button.
window . addEventListener ( 'pageshow' , ( event ) => updateCounter ( actionCheckboxes , options ) ) ;
2021-04-11 19:51:12 +00:00
} ;
// Call function fn when the DOM is loaded and ready. If it is already
// loaded, call the function now.
// http://youmightnotneedjquery.com/#ready
function ready ( fn ) {
if ( document . readyState !== 'loading' ) {
fn ( ) ;
} else {
document . addEventListener ( 'DOMContentLoaded' , fn ) ;
}
}
ready ( function ( ) {
const actionsEls = document . querySelectorAll ( 'tr input.action-select' ) ;
if ( actionsEls . length > 0 ) {
Actions ( actionsEls ) ;
}
} ) ;
}