Created
August 19, 2011 15:29
-
-
Save jpcody/1157078 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* QUESTION MAINTENANCE OPERATIONS | |
* | |
* This object contains the code to handle question maintenance. That includes, but is | |
* not limited to, switching to view administrative vs applicant questions, updating the | |
* qualification status of a given question, and selecting a new question to add. | |
* | |
*/ | |
SM.adminQuestions = { | |
init : function(){ | |
this.addAndRemove.init(); | |
SM.misc.makeSortable.init( $('tbody'), this.addAndRemove.updateAfterDrag ); | |
}, | |
// handles the addition and removal of questions from the list of asked questions and | |
// the bank of unasked questions | |
addAndRemove : { | |
config : { | |
currentVisibility : null | |
}, | |
init : function(){ | |
this.doDomBindings(); | |
}, | |
doDomBindings : function(){ | |
var that = this, | |
$unaskedQuestions = $('.unasked-questions'), | |
$addQuestion = $('.add-question'), | |
$toggleView = $('.create-question, .cancel-new-question'), | |
$questionLists = $('.question-list'), | |
editQuestion = '.edit-question, .cancel-question-edit', | |
removeQuestion = '.remove-asked-question', | |
$editFormField = $('.edit-form-field'), | |
$previewType = $('.form-type-preview'), | |
typeSelect = '.type-select', | |
addChoice = '.add-new-choice', | |
$showSetQuestions = $('.show-set-questions'), | |
addSetQuestion = '.add-question-to-set', | |
requiredFields = 'fieldset.has-requirements input.required', | |
$submitQuestion = $('.submit-new-question'), | |
showHelp = '.show-help', | |
addQuestionRow = '.add-unasked-question'; | |
// DISPLAY THE LIST OF UNASKED QUESTIONS | |
$addQuestion.click(function(e){ | |
e.preventDefault(); | |
that.config.currentVisibility = $(this).attr('data-visibility'); | |
that.displayUnaskedQuestions($(this)); | |
}); | |
// SWITCH BETWEEN LIST OF UNASKED QUESTIONS AND NEW CREATION FORM | |
$toggleView.click(function(e){ | |
e.preventDefault(); | |
that.toggleCreateOrAdd( $(this) ); | |
}); | |
$questionLists.delegate(removeQuestion, 'click', function(e){ | |
e.preventDefault(); | |
var $row = $(this).closest('tr').prev('tr'); | |
that.removeQuestionRow( $row, that.prepareExistingQuestion($row)); | |
}); | |
$questionLists.delegate(editQuestion, 'click', function(e){ | |
e.preventDefault(); | |
that.toggleQuestionEditor( $(this) ); | |
}); | |
$previewType.click(function(e){ | |
e.preventDefault(); | |
var $container = $(this).closest('div').find('.type-samples'); | |
SM.baseFormFields.previewQuestionType( $container ); | |
}); | |
$unaskedQuestions.delegate(addChoice, 'click', function(e){ | |
e.preventDefault(); | |
SM.baseFormFields.addNewChoice( $(this) ); | |
}); | |
$unaskedQuestions.delegate(typeSelect, 'change', function(){ | |
var $parent; | |
$parent = $(this).closest('.question-in-set').length ? $(this).closest('.question-in-set') : $(this).closest('fieldset'); | |
SM.baseFormFields.displayProperFields( $(this), $parent ); | |
}); | |
$showSetQuestions.click(function(e){ | |
e.preventDefault(); | |
that.displayQuestionsForSet( $(this) ); | |
}); | |
$unaskedQuestions.delegate(addSetQuestion, 'click', function(e){ | |
e.preventDefault(); | |
that.addNewQuestionforSet( $(this) ); | |
}); | |
$unaskedQuestions.delegate(requiredFields, 'keyup', function(){ | |
that.checkRequirements($(this).closest('fieldset')); | |
}); | |
$submitQuestion.click(function(e){ | |
e.preventDefault(); | |
that.submitQuestion( $(this).closest('form') ); | |
}); | |
$unaskedQuestions.delegate(showHelp, 'click', function(e){ | |
e.preventDefault(); | |
var $nextContainer = $(this).closest('div.full-width-rows').next('div.hidden'); | |
$nextContainer.slideDown(100, function(){ | |
$(this).removeClass('hidden'); | |
$(this).removeAttr('style'); | |
}); | |
SM.misc.wysiwyg.buildIt($nextContainer.find('textarea')); | |
}); | |
$editFormField.click(function(e){ | |
e.preventDefault(); | |
var formFieldId = $(this).attr('data-form-field-id'), | |
formFieldType = $(this).attr('data-form-field-type') === "QuestionSet" ? "FormFieldSet" : "FormField"; | |
that.displayFormFieldDetails( formFieldId, formFieldType ); | |
}); | |
$questionLists.delegate(addQuestionRow, 'click', function(e){ | |
e.preventDefault(); | |
var $this = $(this); | |
$this.closest('tr').remove(); | |
that.addQuestionRow( that.prepareExistingQuestion($this.closest('tr'))); | |
}); | |
}, | |
prepareNewQuestion : function( data ){ | |
var obj = { | |
id : data.id, | |
label : data.label, | |
fieldType : data.klass, | |
isRequired : false, | |
isReviewable : data.reviewer_visible, | |
isQuestionSet : function(){ | |
return data.klass === "QuestionSet"; | |
}, | |
isAdding : function(){ | |
return true; | |
} | |
}; | |
return obj; | |
}, | |
prepareExistingQuestion : function( $row ){ | |
var obj = { | |
id : $row.attr('data-field-id'), | |
label : $row.find('.label').text(), | |
fieldType : $row.find('.type').text(), | |
isRequired : $row.find('.required').text() === "Optional" ? "<span class='deemphasize'>Optional</span>" : "Required", | |
isReviewable : $row.find('.reviewable').text() === "Yes" ? "Yes" : "No", | |
isSetOfQuestions : function(){ | |
return $row.find('.type').text().replace(/\s/g, '') === "QuestionSet"; | |
} | |
}; | |
return obj; | |
}, | |
addQuestionRow : function( obj ){ | |
obj.isAdding = true; | |
obj.isRemoving = false; | |
var rowTpl = SM.templates.questions.questionRow, | |
editTpl = SM.templates.questions.questionRowEdit, | |
newRow = Mustache.to_html(rowTpl, obj), | |
newEdit = Mustache.to_html(editTpl, obj); | |
// go ahead and build a new row from our HTML | |
var $newRow = $(newRow).prependTo( $('#specific_' + this.config.currentVisibility + '_questions_asked') | |
.find('tbody')).effect('highlight'); | |
$(newEdit).insertAfter($newRow); | |
$('.lightboxed:visible').find('a.close').click(); | |
this.checkForEmptyRows( $newRow.closest('tbody')); | |
}, | |
removeQuestionRow : function( $row, obj ){ | |
obj.isAdding = false; | |
obj.isRemoving = true; | |
var rowTpl = SM.templates.questions.questionRow, | |
newRow = Mustache.to_html(rowTpl, obj); | |
// pull out our editing buddy, the actual row, then prepend it over on the other side | |
$row.next('tr').remove(); | |
$row.remove(); | |
$(newRow).prependTo($("#common_" + this.config.currentVisibility + "_questions_not_asked").find('tbody')); | |
this.checkForEmptyRows( $row.closest('tbody')); | |
}, | |
checkForEmptyRows : function( $fieldset ){ | |
var shownRows = $fieldset.find('tr').not(':last').length, | |
$lastRow = $fieldset.find('tr.last'); | |
$lastRow[ shownRows ? 'addClass' : 'removeClass' ]('hidden'); | |
}, | |
displayFormFieldDetails : function( formFieldId, formFieldType ){ | |
var that = this; | |
$.ajax( '/admin/form_field_collections/' + formFieldId + '/edit?klass=' + formFieldType, { | |
success : function(a){ | |
$newDiv = $('<div>', { | |
'class' : 'section lightboxed', | |
html : a | |
}); | |
$newDiv.lightbox_me({ | |
overlayCSS : { | |
background : '#000000', | |
opacity : 0.5 | |
}, | |
onLoad : function(){ that.checkRequirements( $newDiv.find('fieldset')); }, | |
destroyOnClose : true | |
}); | |
}, | |
type : 'GET', | |
dataType : 'html' | |
}); | |
}, | |
updateAfterDrag : function(e, ui){ | |
var $dragged = $(ui.item[0]), | |
editorSelector = '#' + $dragged.attr('id').replace(/show/, 'edit'), | |
$draggedEditor = $(editorSelector); | |
$draggedEditor.insertAfter($dragged); | |
$dragged.find('button').show(); | |
$dragged.removeClass('highlight'); | |
$dragged.effect("highlight"); | |
}, | |
checkRequirements : function( $fieldset ){ | |
var $requiredFields = $fieldset.find('input.required'), | |
unmet = _.any($requiredFields, function(el){ return $(el).val() === ''; }), | |
$submit = $('#' + $fieldset.attr('data-submit-id')); | |
if(!unmet){ | |
$submit.animate({ opacity : 1.0 }, 100); | |
$submit.removeClass('disabled'); | |
} | |
}, | |
createEmptyQuestion : function( $trigger ){ | |
var newHtml = Mustache.to_html( SM.templates.questions.questionInSet, {} ); | |
$newHtml = $(newHtml).insertAfter( $trigger.closest('.add-choice') ); | |
$newHtml.find('input.label').focus(); | |
}, | |
toggleQuestionDetails: function toggle( $trigger, $container, isContracted ){ | |
var $container = $trigger.closest('.add-choice').prev('.question-in-set'), | |
$rows = $container.find('.full-width-rows'), | |
isContracted = isContracted || false, | |
$edit = $('<button>', { | |
'class' : 'tertiary button edit', | |
'text' : 'Edit' | |
}); | |
$container.find('.full-width-rows').not(':first').not('.hidden')[ isContracted ? 'slideDown' : 'slideUp' ]( 100 ); | |
if( isContracted ){ | |
$($rows[0]).find('button.edit').remove(); | |
$($rows[0]).find('input').removeClass('almost-full'); | |
} else { | |
$($rows[0]).find('input').addClass('almost-full'); | |
$edit.insertAfter($($rows[0]).find('input')); | |
$edit.click(function(e){ | |
e.preventDefault(); | |
toggle( $trigger, $container, true ); | |
}); | |
} | |
}, | |
updateAddTrigger : function( $trigger ){ | |
$trigger.parent('div').addClass('complete'); | |
$trigger.hide(); | |
}, | |
addNewQuestionforSet : function( $trigger ){ | |
this.toggleQuestionDetails( $trigger ); | |
this.createEmptyQuestion( $trigger ); | |
this.updateAddTrigger( $trigger ); | |
}, | |
displayQuestionsForSet : function( $trigger ){ | |
var $form = $trigger.closest('form'); | |
$trigger.closest('div.form-complete').hide(); | |
$form.find('fieldset').removeClass('hidden'); | |
$form.find('.question-in-set').addClass('active'); | |
$form.find('.question-in-set input').eq(0).focus(); | |
}, | |
displayUnaskedQuestions : function( $trigger ){ | |
var that = this; | |
$('#' + this.config.currentVisibility + '-unasked-questions').lightbox_me({ | |
overlayCSS : { | |
background : '#000000', | |
opacity : 0.5 | |
} | |
}); | |
}, | |
restoreDefaultState : function(){ | |
}, | |
transferQuestionText : function( $trigger, $form ){ | |
var re = new RegExp('cancel', 'gi'), | |
isCancel = re.test($trigger.text()), | |
$starterQuestion = $('#' + this.config.currentVisibility + '-question-label-preview'), | |
$formLabel = $form.find('input.question-text').eq(0); | |
if(!isCancel && !($starterQuestion.val() === '')){ $formLabel.val($starterQuestion.val()); } | |
$starterQuestion.val(''); | |
}, | |
toggleCreateOrAdd : function( $trigger ){ | |
var $newItem = $('#' + $trigger.attr('data-next-step')), | |
$oldItem = $trigger.closest('.question-step'), | |
text = $trigger.closest(); | |
this.transferQuestionText( $trigger, $newItem ); | |
$newItem.insertAfter($oldItem); | |
$oldItem.hide().insertAfter($('#unasked-questions')); | |
$newItem.show(); | |
this.checkRequirements($newItem.find('fieldset:visible')); | |
}, | |
toggleQuestionEditor : function( $trigger ){ | |
var $row = $trigger.closest('tr'), | |
wasCancel = $row.hasClass('edit'); | |
if(wasCancel){ | |
$row.prev().removeClass('highlight'); | |
$row.prev().find('button').show(); | |
$row.addClass('hidden'); | |
} else { | |
$row.addClass('highlight'); | |
$row.next().removeClass('hidden'); | |
$trigger.hide(); | |
} | |
}, | |
buildQuestionData : function( $form, formFieldSetData ){ | |
var formFieldData, | |
vis = this.config.currentVisibility, | |
$reviewerVisibility = $form.find('.reviewable'), | |
applicantVisibility = this.config.currentVisibility === "applicant" ? true : false, | |
$reference = $form.find('.reference'), | |
$label = $form.find('.label'), | |
$overUnder = $form.find('.over-under'), | |
$type = $form.find('.type'), | |
$help = $form.find('.help'), | |
$valuesChoices = $form.find('.choices input'), | |
deferToSet = ["reviewer_visible", "applicant_visible", "required"]; | |
formFieldData = { | |
klass : "FormField", | |
reviewer_visible : $reviewerVisibility.is(':checked'), | |
applicant_visible : applicantVisibility, | |
reference : $reference.is(':checked'), | |
label : $label.val(), | |
over_under : $overUnder.is(':checked'), | |
type : $type.val(), | |
help_message : $help.val(), | |
values : _.map($valuesChoices, function(el){ return $(el).val(); }), | |
availability : "personal" | |
}; | |
if( formFieldSetData ){ | |
_.each(deferToSet, function(field){ delete formFieldData[field]; }); | |
return _.defaults(formFieldData, formFieldSetData); | |
} else { | |
return formFieldData; | |
} | |
}, | |
buildFormFieldSetData : function( $form ){ | |
var that = this, | |
formFieldSetData, | |
vis = this.config.currentVisibility, | |
applicantVisibility = this.config.currentVisibility === "applicant" ? true : false, | |
$label = $form.find('.label'), | |
$questions = $('.question-in-set.active'), | |
$reviewerVisibility = $form.find('.reviewable'), | |
passToFormField = ["reviewer_visible", "applicant_visible", "required"]; | |
formFieldSetData = { | |
klass : "FormFieldSet", | |
label : $label.val(), | |
reviewer_visible : $reviewerVisibility.is(':checked'), | |
applicant_visible : applicantVisibility, | |
form_fields : [], | |
availability : "personal" | |
}; | |
_.each($questions, function(el){ | |
var reducedformFieldSetData, | |
formFieldData; | |
reducedformFieldSetData = _.reduce(formFieldSetData, function(memo, val, ind){ | |
if(_.include(passToFormField, ind)){ | |
memo[ind] = {}; | |
memo[ind] = val; | |
} | |
return memo; | |
}, {}); | |
formFieldData = that.buildQuestionData( $(el), reducedformFieldSetData); | |
formFieldSetData.form_fields.push(formFieldData); | |
}); | |
return formFieldSetData; | |
}, | |
submitQuestion : function( $form ){ | |
var that = this, | |
isGroup = $form.attr('data-type') === "question-group", | |
formData, | |
postUrl = "/admin/form_field_collections"; | |
formData = this[ isGroup ? 'buildFormFieldSetData' : 'buildQuestionData' ]($form); | |
$.ajax( postUrl, { | |
data : {'form_field_collection' : JSON.stringify(formData)}, | |
dataType : 'json', | |
type : 'POST', | |
success : function(data){ | |
that.addQuestionRow( that.prepareNewQuestion(data) ); | |
}, | |
error : function(a, b, c){ | |
console.log(a); | |
} | |
}); | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment