2018-06-13 13:01:55 +01:00
// Form submission and validation
var submitBtn = $ ( "#submit-event-create" ) ;
2018-06-14 17:01:14 +01:00
var submitBtnLabel = "Create Event" ;
var submitBtnWaitLabel = "Please wait..." ;
var submitBtnErrLabel = "Errors Found" ;
var dateRegex = /^[0-9]{4}-(((0[13578]|(10|12))-(0[1-9]|[1-2][0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|((0[469]|11)-(0[1-9]|[1-2][0-9]|30)))\s[0-9]?[0-9]:[0-9]{2}\s\+[0-9]{2}:[0-9]{2}$/ ;
2018-06-13 13:01:55 +01:00
var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ ;
var reCaptchaValid = false ;
2018-06-14 17:01:14 +01:00
var generalErrorBlock = document . getElementById ( 'all-errors-help-block' ) ;
var errors = [ ] ;
2018-06-13 13:01:55 +01:00
$ ( "#election-form" ) . submit ( function ( e ) {
// Intercept submission of form and temporarily suspend it
e . preventDefault ( ) ;
var form = this ;
// Get a reference to the submit button
submitBtn . prop ( 'disabled' , true ) ;
2018-06-14 17:01:14 +01:00
submitBtn . val ( submitBtnWaitLabel ) ;
2018-06-13 13:01:55 +01:00
// Disable the cancel button during validation
var cancelBtn = $ ( "#cancel-event-create" ) ;
cancelBtn . prop ( 'disabled' , true ) ;
// Perform input validation
var formDataValid = isFormValid ( ) ;
if ( formDataValid === true ) {
2018-06-14 17:01:14 +01:00
clearErrors ( ) ;
2018-06-13 13:01:55 +01:00
form . submit ( ) ;
} else {
2018-06-14 17:01:14 +01:00
submitBtn . val ( submitBtnErrLabel ) ;
2018-06-13 13:01:55 +01:00
cancelBtn . removeAttr ( 'disabled' ) ;
2018-06-14 17:01:14 +01:00
highlightErrors ( ) ;
2018-06-13 13:01:55 +01:00
}
} ) ;
2018-06-14 17:01:14 +01:00
function validateForm ( ) {
var formDataValid = isFormValid ( ) ;
if ( formDataValid === true ) {
clearErrors ( ) ;
submitBtn . removeAttr ( 'disabled' ) ;
submitBtn . val ( submitBtnLabel ) ;
} else {
submitBtn . val ( submitBtnErrLabel ) ;
highlightErrors ( ) ;
}
}
2018-06-13 13:01:55 +01:00
function isFormValid ( ) {
var nameValid = isNameValid ( ) ;
var slugValid = isSlugValid ( ) ;
var voteStartValid = isVoteStartValid ( ) ;
var voteEndValid = isVoteEndValid ( ) ;
2018-06-14 17:01:14 +01:00
var pollOptsValid = isPollAndOptsValid ( ) ;
2018-06-13 13:01:55 +01:00
var organisersEmailsValid = areOrganisersEmailsValid ( ) ;
var trusteesEmailsValid = areTrusteesEmailsValid ( ) ;
var votersListValid = isVotersListValid ( ) ;
2018-06-14 17:01:14 +01:00
return nameValid && slugValid && voteStartValid && voteEndValid && pollOptsValid
&& organisersEmailsValid && trusteesEmailsValid && votersListValid ;
}
function validateFormField ( validationFn , helpBlockId ) {
var valid = validationFn ( ) ;
if ( valid === false ) {
highlightError ( helpBlockId ) ;
} else {
clearError ( helpBlockId ) ;
if ( reCaptchaValid === true ) {
if ( submitBtn . val ( ) === submitBtnErrLabel ) {
clearErrors ( ) ;
}
submitBtn . removeAttr ( 'disabled' ) ;
submitBtn . val ( submitBtnLabel ) ;
}
}
2018-06-13 13:01:55 +01:00
}
function isNameValid ( ) {
2018-06-14 17:01:14 +01:00
// Based on a list of names supplied from the create_event html template
if ( events _list !== undefined ) {
var valid = true ;
var event _name = $ ( '#name-input' ) . val ( ) ;
if ( event _name === '' ) {
checkAndAddError ( {
error : "The event name field is blank." ,
helpBlockId : "name-input-error-block"
} ) ;
return false ;
}
for ( var i = 0 ; i < events _list . length ; i ++ ) {
var name = events _list [ i ] . title ;
if ( name === event _name ) {
valid = false ;
// We need to flag this error to the user by generating an error that's
// later rendered
checkAndAddError ( {
error : "The event name '" + event _name + "' is already in use." ,
helpBlockId : "name-input-error-block"
} ) ;
}
}
return valid ;
} else {
// Can't perform validation
return true ;
}
2018-06-13 13:01:55 +01:00
}
2018-06-14 17:01:14 +01:00
$ ( '#name-input' ) . on ( 'input' , function ( e ) { // Validation performed with every keystroke
validateFormField ( isNameValid , "name-input-error-block" ) ;
} ) ;
2018-06-13 13:01:55 +01:00
function isSlugValid ( ) {
2018-06-14 17:01:14 +01:00
// Based on a list of identifiers supplied from the create_event html template
if ( events _list !== undefined ) {
var valid = true ;
var event _slug = $ ( '#identifier-input' ) . val ( ) ;
if ( event _slug === '' ) {
checkAndAddError ( {
error : "The event slug field is blank." ,
helpBlockId : "identifier-input-error-block"
} ) ;
return false ;
}
for ( var i = 0 ; i < events _list . length ; i ++ ) {
var slug = events _list [ i ] . slug ;
if ( slug === event _slug ) {
valid = false ;
// We need to flag this error to the user by generating an error that's
// later rendered
checkAndAddError ( {
error : "The event slug '" + event _slug + "' is already in use." ,
helpBlockId : "identifier-input-error-block"
} ) ;
}
}
return valid ;
} else {
// Can't perform validation
return true ;
}
2018-06-13 13:01:55 +01:00
}
2018-06-14 17:01:14 +01:00
$ ( '#identifier-input' ) . on ( 'input' , function ( e ) {
validateFormField ( isSlugValid , "identifier-input-error-block" ) ;
} ) ;
2018-06-13 13:01:55 +01:00
function isVoteStartValid ( ) {
2018-06-14 17:01:14 +01:00
var helpBlockId = "vote-start-input-error-block" ;
2018-06-13 13:01:55 +01:00
var start _date _time = $ ( '#vote-start-input' ) . val ( ) ;
2018-06-14 17:01:14 +01:00
var valid = isDateValid ( start _date _time ) ;
if ( valid === false ) {
checkAndAddError ( {
error : "The voting start date and time format is invalid." ,
helpBlockId : helpBlockId
} )
} else {
clearError ( helpBlockId ) ;
}
return valid ;
2018-06-13 13:01:55 +01:00
}
2018-06-14 17:01:14 +01:00
$ ( '#vote-start-input' ) . change ( function ( e ) {
validateFormField ( isVoteStartValid , "vote-start-input-error-block" ) ;
} ) ;
$ ( "#vote-start-input" ) . click ( function ( ) {
$ ( "#vote-start-input" ) . change ( ) ;
} ) ;
2018-06-13 13:01:55 +01:00
function isVoteEndValid ( ) {
var end _date _time = $ ( '#vote-end-input' ) . val ( ) ;
2018-06-14 17:01:14 +01:00
var valid = isDateValid ( end _date _time ) ;
if ( valid === false ) {
checkAndAddError ( {
error : "The voting end date and time format is invalid." ,
helpBlockId : "vote-end-input-error-block"
} )
}
return valid ;
2018-06-13 13:01:55 +01:00
}
2018-06-14 17:01:14 +01:00
$ ( '#vote-end-input' ) . change ( function ( e ) {
validateFormField ( isVoteEndValid , "vote-end-input-error-block" ) ;
} ) ;
$ ( "#vote-end-input" ) . click ( function ( ) {
$ ( "#vote-end-input" ) . change ( ) ;
} ) ;
2018-06-13 13:01:55 +01:00
function isDateValid ( date _time ) {
return dateRegex . test ( date _time ) ;
}
2018-06-14 17:01:14 +01:00
function isPollAndOptsValid ( ) {
var pollValid = true ;
var optsValid = true ;
var minMaxSelValid = true ;
// Check question is valid
pollValid = isPollValid ( ) ;
// Check opts are valid
optsValid = isPollOptionsValid ( ) ;
// Check min and max selections are valid
minMaxSelValid = isMinMaxSelectionValid ( ) ;
return pollValid && optsValid && minMaxSelValid ;
2018-06-13 13:01:55 +01:00
}
2018-06-14 17:01:14 +01:00
function isPollValid ( ) {
var valid = true ;
// Check question is valid
var question = $ ( '#question-input' ) . val ( ) ;
if ( question === '' ) {
checkAndAddError ( {
error : "Question / Statement for the poll is blank." ,
helpBlockId : "question-input-error-block"
} ) ;
valid = false ;
}
return valid ;
}
function isPollOptionsValid ( ) {
var valid = true ;
var optsInputs = $ ( '.option-formset #option-name-input' ) ;
var helpBlockId = "options-input-error-block" ;
var index = 0 ;
var errorStr = "Option " ;
for ( var i = 0 ; i < optsInputs . length ; i ++ ) {
var input = optsInputs [ i ] ;
if ( input . placeholder . indexOf ( "X" ) === - 1 ) {
if ( input . value === '' ) {
errorStr = errorStr + ( index + 1 ) + " " ;
valid = false ;
}
index ++ ;
}
}
if ( valid === false ) {
errorStr = errorStr + " is blank." ;
checkAndAddError ( {
error : errorStr ,
helpBlockId : helpBlockId
} ) ;
}
return valid ;
2018-06-13 13:01:55 +01:00
}
2018-06-14 17:01:14 +01:00
$ ( '#question-input' ) . on ( 'input' , function ( e ) {
validateFormField ( isPollValid , "question-input-error-block" ) ;
} ) ;
$ ( '.option-formset #option-name-input' ) . on ( 'input' , function ( e ) {
validateFormField ( isPollOptionsValid , "options-input-error-block" ) ;
} ) ;
function isMinMaxSelectionValid ( ) {
var valid = true ;
var minInput = $ ( '#minimum-input' ) ;
var minInputMinAttr = parseInt ( minInput [ 0 ] . min ) ;
var minInputVal = minInput . val ( ) ;
var helpBlockId = "selections-input-error-block" ;
var errorStr = "" ;
if ( minInputVal < minInputMinAttr ) {
errorStr = "The minimum option selection cannot be less than " + minInputMinAttr ;
valid = false ;
}
var maxInput = $ ( '#maximum-input' ) ;
var maxInputMinAttr = parseInt ( maxInput [ 0 ] . min ) ;
var maxInputVal = maxInput . val ( ) ;
if ( maxInputVal < maxInputMinAttr ) {
if ( errorStr !== '' ) {
errorStr = errorStr + " and the maximum cannot be less than " + maxInputMinAttr ;
} else {
errorStr = "The maximum option selection cannot be less than " + maxInputMinAttr ;
}
valid = false ;
}
if ( valid === false ) {
errorStr = errorStr + "." ;
checkAndAddError ( {
error : errorStr ,
helpBlockId : helpBlockId
} ) ;
}
return valid ;
2018-06-13 13:01:55 +01:00
}
2018-06-14 17:01:14 +01:00
$ ( '#minimum-input, #maximum-input' ) . on ( 'input' , function ( e ) {
validateFormField ( isMinMaxSelectionValid , "selections-input-error-block" ) ;
} ) ;
2018-06-13 13:01:55 +01:00
function areOrganisersEmailsValid ( ) {
2018-06-14 17:01:14 +01:00
var valid = true ;
var organiserInputs = $ ( '.organiser-formset #organiser-email-input' ) ;
var helpBlockId = "organisers-input-error-block" ;
var index = 0 ;
var errorBlankStr = "Organiser " ;
var errorInvalidStr = "Organiser " ;
var errorNotUserStr = "" ;
for ( var i = 0 ; i < organiserInputs . length ; i ++ ) {
var input = organiserInputs [ i ] ;
if ( input . placeholder . indexOf ( "X" ) === - 1 ) {
// Check if the input field is blank
if ( input . value === '' ) {
errorBlankStr = errorBlankStr + ( index + 1 ) + " " ;
valid = false ;
} else {
// Ensure that any email supplied is of a valid format
if ( emailRegex . test ( input . value ) === false ) {
errorInvalidStr = errorInvalidStr + ( index + 1 ) + " " ;
valid = false ;
} else {
// If the email format is valid, ensure that an email of a registered DemoUser is being
// supplied and not a random email address
var foundMatch = user _emails . some ( function ( obj ) {
return obj . email === input . value ;
} ) ;
if ( ! foundMatch ) {
errorNotUserStr = input . value + " is not a registered user and cannot be an organiser." ;
valid = false ;
}
}
}
index ++ ;
}
}
if ( valid === false ) {
var errorStr = "" ;
// Will be greater than 10 if either a blank input or invalid input has been detected (10 char is the base
// length of the original err strings)
if ( errorBlankStr . length > 10 ) {
errorStr = errorBlankStr + " email is blank. " ;
}
if ( errorInvalidStr . length > 10 ) {
errorStr = errorStr + errorInvalidStr + " email is invalid. " ;
}
// This means an invalid user has been detected
if ( errorNotUserStr . length > 0 ) {
errorStr = errorStr + errorNotUserStr ;
}
checkAndAddError ( {
error : errorStr ,
helpBlockId : helpBlockId
} ) ;
}
return valid ;
2018-06-13 13:01:55 +01:00
}
2018-06-14 17:01:14 +01:00
$ ( '.organiser-formset #organiser-email-input' ) . on ( 'input' , function ( e ) {
validateFormField ( areOrganisersEmailsValid , "organisers-input-error-block" ) ;
} ) ;
2018-06-13 13:01:55 +01:00
function areTrusteesEmailsValid ( ) {
2018-06-14 17:01:14 +01:00
var valid = true ;
var trusteeInputs = $ ( '.trustee-formset #trustee-email-input' ) ;
var helpBlockId = "trustees-input-error-block" ;
var index = 0 ;
var errorBlankStr = "Trustee " ;
var errorInvalidStr = "Trustee " ;
for ( var i = 0 ; i < trusteeInputs . length ; i ++ ) {
var input = trusteeInputs [ i ] ;
if ( input . placeholder . indexOf ( "X" ) === - 1 ) {
// Check if the input field is blank
if ( input . value === '' ) {
errorBlankStr = errorBlankStr + ( index + 1 ) + " " ;
valid = false ;
} else if ( emailRegex . test ( input . value ) === false ) {
errorInvalidStr = errorInvalidStr + ( index + 1 ) + " " ;
valid = false ;
}
index ++ ;
}
}
if ( valid === false ) {
var errorStr = "" ;
// Will be greater than 8 if either a blank input or invalid input has been detected (8 char is the base
// length of the original err strings)
if ( errorBlankStr . length > 8 ) {
errorStr = errorBlankStr + " email is blank. " ;
}
if ( errorInvalidStr . length > 8 ) {
errorStr = errorStr + errorInvalidStr + " email is invalid." ;
}
checkAndAddError ( {
error : errorStr ,
helpBlockId : helpBlockId
} ) ;
}
return valid ;
2018-06-13 13:01:55 +01:00
}
2018-06-14 17:01:14 +01:00
$ ( '.trustee-formset #trustee-email-input' ) . on ( 'input' , function ( e ) {
validateFormField ( areTrusteesEmailsValid , "trustees-input-error-block" ) ;
} ) ;
2018-06-13 13:01:55 +01:00
function isVotersListValid ( ) {
2018-06-14 17:01:14 +01:00
var valid = true ;
var votersInputVal = $ ( '#voters-list-input' ) . val ( ) ;
// Check if the text area is blank
if ( votersInputVal === '' ) {
checkAndAddError ( {
error : "The voters list is blank." ,
helpBlockId : "voters-input-error-block"
} ) ;
return false ;
}
var errorStr = "" ;
var invalidCount = 0 ;
// Check whether one or multiple emails have been supplied
if ( votersInputVal . indexOf ( ',' ) === - 1 ) {
// Check the validity of the single email address
if ( emailRegex . test ( votersInputVal ) === false ) {
errorStr = errorStr + votersInputVal + " " ;
valid = false ;
invalidCount ++ ;
}
} else {
// Proceed to check if the data within the text area is valid csv
var csvParseOutput = Papa . parse ( votersInputVal ) ;
if ( csvParseOutput . errors . length > 0 ) {
checkAndAddError ( {
error : "The voters list contains invalid data. It should be a csv list containing voter email addresses." ,
helpBlockId : "voters-input-error-block"
} ) ;
return false ;
}
// Check that the emails supplied are valid email addresses (using a basic regex)
var votersEmails = csvParseOutput . data [ 0 ] ;
for ( var i = 0 ; i < votersEmails . length ; i ++ ) {
var voter _email = votersEmails [ i ] . replace ( ' ' , '' ) ;
if ( emailRegex . test ( voter _email ) === false ) {
errorStr = errorStr + voter _email + " " ;
valid = false ;
invalidCount ++ ;
}
}
}
if ( valid === false ) {
if ( invalidCount > 1 ) {
errorStr = errorStr + "are invalid email addresses." ;
} else {
errorStr = errorStr + "is an invalid email address." ;
}
checkAndAddError ( {
error : errorStr ,
helpBlockId : "voters-input-error-block"
} ) ;
}
return valid ;
2018-06-13 13:01:55 +01:00
}
2018-06-14 17:01:14 +01:00
$ ( '#voters-list-input' ) . change ( function ( e ) {
validateFormField ( isVotersListValid , "voters-input-error-block" ) ;
} ) ;
function checkAndAddError ( newError ) { // Ensures that an error hasn't already been pushed
var found = errors . some ( function ( error ) {
return error . error === newError . error && error . helpBlockId === newError . helpBlockId
} ) ;
if ( ! found ) {
errors . push ( newError ) ;
}
2018-06-13 13:01:55 +01:00
}
2018-06-14 17:01:14 +01:00
function highlightErrors ( ) {
// Generate the general list of errors
var baseGeneralString = "Errors were found in the form as follows:\n" ;
generalErrorBlock . appendChild ( document . createTextNode ( baseGeneralString ) ) ;
generalErrorBlock . appendChild ( makeErrorUL ( ) ) ;
}
function highlightError ( helpBlockId ) {
for ( var i = 0 ; i < errors . length ; i ++ ) {
var error = errors [ i ] ;
if ( helpBlockId === error . helpBlockId ) {
$ ( '#' + helpBlockId ) . html ( error . error ) ;
}
2018-06-13 13:01:55 +01:00
}
2018-06-14 17:01:14 +01:00
}
function makeErrorUL ( ) {
// Create the list element:
var list = document . createElement ( 'ul' ) ;
for ( var i = 0 ; i < errors . length ; i ++ ) {
// Perform list item generation
// Create the list item:
var item = document . createElement ( 'li' ) ;
// Set its contents:
var errorText = errors [ i ] . error ;
item . appendChild ( document . createTextNode ( errorText ) ) ;
// Add it to the list:
list . appendChild ( item ) ;
// Populate the error's associated error block with the data
$ ( '#' + errors [ i ] . helpBlockId ) . html ( errorText ) ;
}
return list ;
}
function clearErrors ( ) {
// Clear the errors array
errors . splice ( 0 , errors . length ) ;
// Clear the general list of errors
$ ( '#all-errors-help-block' ) . html ( '' ) ;
}
function clearError ( helpBlockId ) {
$ ( '#' + helpBlockId ) . html ( '' ) ;
errors = errors . filter ( e => e . helpBlockId !== helpBlockId ) ;
}
2018-06-13 13:01:55 +01:00
2018-06-12 13:31:38 +01:00
// File handling
function processFileChange ( event ) {
var files = event . target . files ;
// By parsing the file we ensure that it's valid CSV at the client side. Papa parse
// also allows us to aggregate emails from multiple rows in a file.
if ( files !== undefined
&& files [ 0 ] !== undefined ) {
Papa . parse ( files [ 0 ] , {
complete : function ( results ) {
var errors = results . errors ;
if ( errors . length === 0 ) {
var data = results . data ;
var numRows = data . length ;
var totalNumEmails = 0 ;
var emails = [ ] ;
if ( numRows > 1 ) {
for ( var i = 0 ; i < numRows ; i ++ ) {
var numEmails = data [ i ] . length ;
totalNumEmails += numEmails ;
for ( var j = 0 ; j < numEmails ; j ++ ) {
emails . push ( data [ i ] [ j ] ) ;
}
}
} else if ( numRows === 1 ) {
totalNumEmails = data [ 0 ] . length ;
for ( var i = 0 ; i < totalNumEmails ; i ++ ) {
emails . push ( data [ 0 ] [ i ] ) ;
}
}
$ ( '#result' ) . removeClass ( "hidden" ) . html (
totalNumEmails + " email(s) have been successfully uploaded." ) ;
2018-06-14 17:01:14 +01:00
$ ( '#voters-list-input' ) . val ( emails . join ( ', ' ) ) ;
2018-06-12 13:31:38 +01:00
} else {
// There were errors, so inform the user
$ ( '#result' )
. removeClass ( "hidden" )
. html ( "Error reading uploaded file! Check the format and try again" )
. addClass ( "errorText" ) ;
}
}
} ) ;
}
}
document . getElementById ( 'files' ) . addEventListener ( 'change' , processFileChange , false ) ;
// reCAPTCHA
2018-06-12 14:30:23 +01:00
function reCVerificationCallback ( ) {
2018-06-13 13:01:55 +01:00
reCaptchaValid = true ;
2018-06-14 17:01:14 +01:00
validateForm ( ) ;
2018-06-12 13:31:38 +01:00
}
2018-06-12 14:30:23 +01:00
function reCExpiredCallback ( ) {
2018-06-13 13:01:55 +01:00
reCaptchaValid = false ;
submitBtn . prop ( 'disabled' , true ) ;
2018-06-12 14:30:23 +01:00
}
2018-06-12 13:31:38 +01:00
// Slug field.
function slugify ( value ) {
return value . toString ( )
. replace ( /[^\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\w\s-]+/g , '' )
. replace ( /^[-\s]+/ , '' )
. replace ( /[-\s]+$/ , '' )
. replace ( /[-\s]+/g , '-' )
. toLowerCase ( ) ;
}
$ ( '#name-input' ) . on ( 'input' , function ( e ) {
var slugField = $ ( '#identifier-input' ) ;
if ( ! slugField . data ( 'changed' ) ) {
var name = $ ( this ) . val ( ) ;
var maxLength = parseInt ( slugField . attr ( 'maxlength' ) ) ;
var slug = slugify ( name ) . substring ( 0 , maxLength ) ;
slugField . val ( slug ) ;
slugField . trigger ( 'input' ) ;
}
} ) ;
$ ( '#identifier-input' ) . change ( function ( e ) {
$ ( this ) . data ( 'changed' , $ ( this ) . val ( ) . length > 0 ) ;
} ) ;
// Poll start and end
var datetime _now = window . moment ( ) . seconds ( 0 ) ;
var datetime _format = "YYYY-MM-DD H:mm" ;
$ ( "#vote-start-input, #vote-end-input" ) . each ( function ( index , element ) {
// Set datetimepickers' current, default and minimum date/time
var datetime _picker = $ ( element ) ;
var datetime _iso8601 = datetime _picker . siblings ( ".datetime-iso8601-input" ) . val ( ) ;
var datetime _local = moment ( datetime _iso8601 ) ;
datetime _picker . datetimepicker ( {
sideBySide : false ,
minDate : datetime _now . clone ( ) . startOf ( "day" ) ,
format : datetime _format ,
widgetParent : $ ( datetime _picker )
} ) ;
var minutes = ( Math . ceil ( datetime _now . minute ( ) / 5 ) * 5 ) + 5 * index ;
var datetime _default = datetime _now . clone ( ) . minutes ( minutes ) ;
datetime _picker . data ( "DateTimePicker" ) . defaultDate ( datetime _default ) ;
datetime _local = datetime _local . isValid ( ) ? datetime _local . format ( datetime _format ) : "" ;
datetime _picker . children ( "input" ) . val ( datetime _local ) ;
} ) ;
$ ( '#vote-start-input, #vote-end-input' ) . parent ( '.date' ) . datetimepicker ( {
allowInputToggle : true ,
icons : {
time : 'fa fa-clock-o' ,
date : 'fa fa-calendar' ,
up : 'fa fa-chevron-up' ,
down : 'fa fa-chevron-down' ,
previous : 'fa fa-chevron-left' ,
next : 'fa fa-chevron-right'
} ,
minDate : moment ( ) . startOf ( 'day' ) ,
useCurrent : false ,
2018-06-13 13:01:55 +01:00
locale : moment . utc ( )
2018-06-12 13:31:38 +01:00
} ) ;
// Form management and Sortable rows
function update ( event , ui ) {
var formsetPrefix = $ ( event . target . lastElementChild ) . attr ( 'data-formset-prefix' ) ;
var formset = $ ( '.formset[data-formset-prefix="' + formsetPrefix + '"]' ) ;
updateFormset ( formset ) ;
}
$ ( "#options-input-table, #organisers-input-table, #trustees-input-table" ) . sortable ( {
items : "tr" ,
update : update
} ) ;
function updateFormset ( formset ) { // Ported from DEMOS 1. Updates the row number for the # and performs any removals.
var forms = formset . children ( '.formset-form:not(.formset-form-empty, .formset-form-removed)' ) ;
var removedForms = formset . children ( '.formset-form.formset-form-removed' ) ;
forms . each ( function ( index ) {
updateForm ( $ ( this ) , index ) ;
} ) ;
removedForms . each ( function ( index ) {
updateForm ( $ ( this ) , forms . length + index ) ;
} ) ;
}
function updateForm ( form , formIndex ) { // Ported from DEMOS 1.
// Specific update for option forms
var mayBeTextInput = form . find ( 'input:text' ) [ 0 ] ;
2018-06-14 17:01:14 +01:00
if ( mayBeTextInput . placeholder !== undefined ) {
if ( mayBeTextInput . placeholder . indexOf ( "Candidate" ) > - 1 ) {
mayBeTextInput . placeholder = "Example: Candidate " + ( formIndex + 1 ) ;
} else if ( mayBeTextInput . placeholder . indexOf ( "trusteeX" ) > - 1 ) {
mayBeTextInput . placeholder = "Example: trustee@example.com" ;
} else if ( mayBeTextInput . placeholder . indexOf ( "organiserX" ) > - 1 ) {
mayBeTextInput . placeholder = "Example: organiser@example.com" ;
}
2018-06-12 13:31:38 +01:00
}
var formset = form . parent ( '.formset' ) ;
var formsetPrefix = formset . attr ( 'data-formset-prefix' ) ;
var formPrefix = formsetPrefix + '-' + formIndex ;
var formPrefixRegex = new RegExp ( formsetPrefix + '-(?:__prefix__|\\d+)' ) ;
form . find ( '*' ) . addBack ( ) . each ( function ( index , element ) {
$ . each ( this . attributes , function ( index , attr ) {
$ ( element ) . attr ( attr . nodeName , function ( index , attrValue ) {
return attrValue . replace ( formPrefixRegex , formPrefix ) ;
} ) ;
} ) ;
} ) ;
form . find ( 'input[name="' + formPrefix + '-ORDER"]' ) . val ( formIndex ) ;
form . find ( '.formset-form-index:first' ) . text ( formIndex + 1 ) ;
}
function manageTotalForms ( formset , value ) { // Ported from DEMOS1.
var formsetPrefix = formset . attr ( 'data-formset-prefix' ) ;
var totalForms = $ ( '#id_' + formsetPrefix + '-TOTAL_FORMS' ) ;
var maxNumForms = $ ( '#id_' + formsetPrefix + '-MAX_NUM_FORMS' ) ;
totalForms . val ( parseInt ( totalForms . val ( ) ) + value ) ;
var addButton = $ ( '.formset-add[data-formset-prefix="' + formsetPrefix + '"]' ) ;
var removedForms = formset . children ( '.formset-form.formset-form-removed' ) ;
addButton . prop ( 'disabled' , parseInt ( totalForms . val ( ) ) - removedForms . length >= parseInt ( maxNumForms . val ( ) ) ) ;
}
$ ( '.formset-add' ) . click ( function ( e ) { // Ported from DEMOS1
var formsetPrefix = $ ( this ) . attr ( 'data-formset-prefix' ) ;
var formset = $ ( '.formset[data-formset-prefix="' + formsetPrefix + '"]' ) ;
var emptyForm = formset . children ( '.formset-form-empty' ) ;
var emptyFormCheckedInputs = emptyForm . find ( 'input:checkbox:checked, input:radio:checked' ) ;
var form = emptyForm . clone ( true ) . removeClass ( 'formset-form-empty' ) ;
var formIndex = formset . children ( '.formset-form:not(.formset-form-empty)' ) . length ;
formset . append ( form ) ;
updateForm ( form , formIndex ) ;
emptyFormCheckedInputs . each ( function ( index ) {
$ ( this ) . prop ( 'checked' , true ) ;
} ) ;
switch ( formset . attr ( 'data-formset-type' ) ) {
case 'modal' :
$ ( '#formset-modal' ) . data ( 'form' , form ) . data ( 'formAdd' , true ) . modal ( 'show' ) ;
break ;
case 'inline' :
manageTotalForms ( formset , + 1 ) ;
form . removeClass ( 'hidden' ) ;
formset . trigger ( 'formsetFormAdded' , [ form ] ) ;
break ;
}
} ) ;
$ ( '.formset-form-remove' ) . click ( function ( e ) { // Ported from DEMOS1
var form = $ ( this ) . closest ( '.formset-form' ) ;
var formPrefix = form . attr ( 'data-formset-form-prefix' ) ;
var formset = form . parent ( '.formset' ) ;
if ( $ ( '#id_' + formPrefix + '-id' ) . val ( ) ) {
$ ( '#id_' + formPrefix + '-DELETE' ) . prop ( 'checked' , true ) ;
form . addClass ( 'formset-form-removed hidden' ) ;
} else {
form . remove ( ) ;
manageTotalForms ( formset , - 1 ) ;
}
updateFormset ( formset ) ;
formset . trigger ( 'formsetFormRemoved' ) ;
2018-06-15 10:09:15 +01:00
// Perform validation now that a row has been removed
switch ( formPrefix ) {
case 'option' :
validateFormField ( isPollOptionsValid , "options-input-error-block" ) ;
break ;
case 'organiser' :
validateFormField ( areOrganisersEmailsValid , "organisers-input-error-block" ) ;
break ;
case 'trustee' :
validateFormField ( areTrusteesEmailsValid , "trustees-input-error-block" ) ;
break ;
}
2018-06-12 13:31:38 +01:00
} ) ;