diff --git a/README.md b/README.md index 2cfa861..f0c0e89 100644 --- a/README.md +++ b/README.md @@ -1 +1,16 @@ # Madlib + +The madlib module uses the Drupal Form API to display text about Giraffes in a fun way. + +It is currently working with the minimum desired functionality. On both JS enabled clients and JS disabled clients. + +POSSIBLE ADDITIONS: + +* Errors output to screen on each element during ajax callback +* Add AJAX to the submit button +* Recognition (intelligence) of JS enabled clients versus JS disabled clients (possible form value) + +REFACTOR: + +* Separate user input ajax from submit ajax +* Separate validation into two categories the entire form versus a single element diff --git a/madlib.admin.inc b/madlib.admin.inc new file mode 100644 index 0000000..df9a1ba --- /dev/null +++ b/madlib.admin.inc @@ -0,0 +1,34 @@ + 'checkbox', + '#title' => t('Debug mode'), + '#default_value' => variable_get('madlib_checkbox', 0), + '#description' => t('Turn on/off debug mode'), + ); + + return system_settings_form($form); +} + +/** + * Madlib administration menu block page. + */ +function madlib_admin_menu_block_page() { + $build = array( + 'header_text' => array( + '#type' => 'markup', + '#markup' => '

' . l(t('Madlib Settings'), 'admin/config/madlib/settings') . '

', + ), + ); + return $build; +} diff --git a/madlib.info b/madlib.info index fa612f1..452a1d5 100644 --- a/madlib.info +++ b/madlib.info @@ -3,4 +3,4 @@ description = Madlib form core = 7.x package = Custom -configure = admin/madlib +configure = admin/config/madlib/settings diff --git a/madlib.module b/madlib.module index 886dc6c..f88ad62 100644 --- a/madlib.module +++ b/madlib.module @@ -10,19 +10,28 @@ function madlib_menu() { $items = array(); - $items['admin/madlib'] = array( + $items['admin/config/madlib'] = array( 'title' => 'Madlib', - 'description' => 'Madlib Settings', + 'description' => 'Settings for the Madlib module.', + 'page callback' => 'madlib_admin_menu_block_page', + 'access arguments' => array('administer madlib settings'), + 'file' => 'madlib.admin.inc', + 'file path' => drupal_get_path('module', 'madlib'), + ); + + $items['admin/config/madlib/settings'] = array( + 'title' => 'Madlib Settings', + 'description' => 'Settings for the Madlib module.', 'page callback' => 'drupal_get_form', - 'page arguments' => array('madlib_admin'), - 'access arguments' => array('administer settings'), - 'type' => MENU_NORMAL_ITEM, - 'expanded' => TRUE, + 'page arguments' => array('madlib_admin_settings'), + 'access arguments' => array('administer madlib settings'), + 'file' => 'madlib.admin.inc', + 'file path' => drupal_get_path('module', 'madlib'), ); $items['madlib'] = array( - 'title' => 'Madlib', - 'description' => 'Madlib Skeleton Form', + 'title' => 'Have I got a Giraffe for You!', + 'description' => 'A madlib using drupal form api', 'page callback' => 'drupal_get_form', 'page arguments' => array('madlib_form'), 'access arguments' => array('view published content'), @@ -45,19 +54,16 @@ function madlib_permission() { } /** - * Page callback for administration settings. + * Implements hook_form_alter(). */ -function madlib_admin() { - $form = array(); - - $form['madlib_checkbox'] = array( - '#type' => 'checkbox', - '#title' => t('Debug mode'), - '#default_value' => variable_get('madlib_checkbox', 0), - '#description' => t('Turn on/off debug mode'), - ); - - return system_settings_form($form); +function madlib_form_alter(&$form, &$form_state, $form_id) { + if ($form_id == 'madlib_form') { + if (variable_get('madlib_checkbox', 0) == 1) { + $form['madlib_note'] = array( + '#markup' => '

DEBUG MODE: ON

', + ); + } + } } /** @@ -65,11 +71,23 @@ function madlib_admin() { */ function madlib_form($form, &$form_state) { + $form['madlib_ajax_status_messages'] = array( + '#type' => 'markup', + '#prefix' => '
', + '#suffix' => '
', + ); + $form['madlib_section_1_fieldset'] = array( '#type' => 'fieldset', '#title' => t('Section 1'), '#collapsible' => TRUE, '#collapsed' => FALSE, + '#attributes' => array('class' => array('madlib_hide_me')), + '#states' => array( + 'invisible' => array( + ':input[name="madlib_hidden"]' => array('value' => 'yes'), + ), + ), ); $form['madlib_section_1_fieldset']['madlib_plural_noun_1_textfield'] = array( @@ -79,6 +97,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_1_fieldset']['madlib_plural_noun_2_textfield'] = array( @@ -88,6 +109,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_1_fieldset']['madlib_part_of_body_1_textfield'] = array( @@ -97,6 +121,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_2_fieldset'] = array( @@ -104,6 +131,12 @@ function madlib_form($form, &$form_state) { '#title' => t('Section 2'), '#collapsible' => TRUE, '#collapsed' => FALSE, + '#attributes' => array('class' => array('madlib_hide_me')), + '#states' => array( + 'invisible' => array( + ':input[name="madlib_hidden"]' => array('value' => 'yes'), + ), + ), ); $form['madlib_section_2_fieldset']['madlib_number_select'] = array( @@ -123,6 +156,9 @@ function madlib_form($form, &$form_state) { ), '#default_value' => variable_get('madlib_number_select', ''), '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_2_fieldset']['madlib_plural_noun_3_textfield'] = array( @@ -132,6 +168,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_2_fieldset']['madlib_part_of_body_2_textfield'] = array( @@ -141,6 +180,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_2_fieldset']['madlib_type_of_liquid_textfield'] = array( @@ -150,6 +192,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_2_fieldset']['madlib_part_of_body_plural_textfield'] = array( @@ -159,6 +204,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_3_fieldset'] = array( @@ -166,25 +214,34 @@ function madlib_form($form, &$form_state) { '#title' => t('Section 3'), '#collapsible' => TRUE, '#collapsed' => FALSE, + '#attributes' => array('class' => array('madlib_hide_me')), + '#states' => array( + 'invisible' => array( + ':input[name="madlib_hidden"]' => array('value' => 'yes'), + ), + ), ); $form['madlib_section_3_fieldset']['madlib_part_of_body_3_select'] = array( '#type' => 'select', '#title' => t('Part of the body'), '#options' => array( - 'head' => array( + t('head') => array( 0 => t('eyes'), 1 => t('nose'), ), - 'torso' => array( - 0 => t('stomach'), + t('torso') => array( + 2 => t('stomach'), ), - 'legs' => array( - 0 => t('feet'), + t('legs') => array( + 3 => t('feet'), ), ), '#default_value' => variable_get('madlib_part_of_body_3_select', ''), '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_3_fieldset']['madlib_adjective_1_textfield'] = array( @@ -194,6 +251,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_3_fieldset']['madlib_plural_noun_4_textfield'] = array( @@ -203,6 +263,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_3_fieldset']['madlib_adjective_2_textfield'] = array( @@ -212,6 +275,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_3_fieldset']['madlib_adjective_3_textfield'] = array( @@ -221,6 +287,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_3_fieldset']['madlib_verb_ing_textfield'] = array( @@ -230,6 +299,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_3_fieldset']['madlib_noun_1_textfield'] = array( @@ -239,6 +311,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_3_fieldset']['madlib_plural_noun_5_textfield'] = array( @@ -248,6 +323,9 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_section_3_fieldset']['madlib_noun_2_textfield'] = array( @@ -257,28 +335,212 @@ function madlib_form($form, &$form_state) { '#size' => 60, '#maxlength' => 128, '#required' => TRUE, + '#ajax' => array( + 'callback' => 'madlib_form_ajax_user_input_callback', + ), ); $form['madlib_submit'] = array( '#type' => 'submit', '#value' => t('Submit'), + '#attributes' => array('class' => array('madlib_hide_me')), + '#states' => array( + 'invisible' => array( + ':input[name="madlib_hidden"]' => array('value' => 'yes'), + ), + ), ); $form['madlib_note'] = array( - '#markup' => '

Click it, you know you want to.

', + '#markup' => '

Click it, you know you want to.

', + '#states' => array( + 'invisible' => array( + ':input[name="madlib_hidden"]' => array('value' => 'yes'), + ), + ), + ); + + // For non-JS enabled clients we need to set this form element so that + // form states know what state the form is in (show / hide). + if ($form_state['rebuild'] == FALSE || + (variable_get('madlib_checkbox', 0) == 1)) { + $form['madlib_hidden'] = array( + '#type' => 'hidden', + '#value' => 'no', + ); + } + else { + $form['madlib_hidden'] = array( + '#type' => 'hidden', + '#value' => 'yes', + ); + + // Apparently we can't hide markup type so we set it equal to nothing. + $form['madlib_note'] = array(); + } + + // If JS is enabled we only need the div. + $form['madlib_output'] = array( + '#type' => 'markup', + '#prefix' => '
', + '#suffix' => '
', + '#markup' => '', + '#states' => array( + 'visible' => array( + ':input[name="madlib_hidden"]' => array('value' => 'yes'), + ), + ), ); + // If JS is disabled output the madlib. + if ($form_state['rebuild'] == TRUE) { + $form['madlib_output']['#markup'] + = madlib_form_output_text_with_t($form, $form_state); + } + + // If JS is disabled and debug is off output the madlib and clear form array. + if ($form_state['rebuild'] == TRUE && + variable_get('madlib_checkbox', 0) == 0) { + + $form = array(); + $form['madlib_output']['#markup'] + = madlib_form_output_text_with_t($form, $form_state); + } + return $form; } +/** + * AJAX callback for user inputs. + * + * @return array + * Renderable array (the markup element) + */ +function madlib_form_ajax_user_input_callback($form, &$form_state) { + + // If the form has not been rebuilt allow the user to enter + // data and change nothing. + if ($form_state['rebuild'] == TRUE) { + + // Clear previous messages (error) or they pile up and display all at once. + drupal_get_messages(); + + // Validation function is NOT automatically called so we must call it. + // TODO: may be related to returning commands instead of part of a form. + madlib_form_validate($form, $form_state); + $errors = form_get_errors(); + + $commands = array(); + + // AJAX commands to run if the form did not pass validation. + if (!empty($errors)) { + $commands[] = ajax_command_replace('#madlib_output_div', + '
'); + } + + // AJAX command to run if the form passed validation. + else { + + // Passed validation and debug mode is ON. + if (variable_get('madlib_checkbox', 0) == 1) { + drupal_set_message(t('Answers received')); + } + + // Passed validation and debug mode is OFF. + elseif (variable_get('madlib_checkbox', 0) == 0) { + drupal_set_message(t('Answers received')); + $commands[] + = ajax_command_css('.madlib_hide_me', array('display' => none)); + } + + // Common ajax commands for a validated form (no errors) and has been + // rebuilt at least once. + $commands[] + = ajax_command_replace('.messages', '
'); + $commands[] + = ajax_command_replace('#madlib_ajax_status_messages', + '
' . + theme('status_messages') . '
'); + $commands[] + = ajax_command_replace('#madlib_output_div', + madlib_form_output_text_with_t($form, + $form_state)); + $commands[] + = ajax_command_invoke('input.error', 'removeClass', array('error')); + } + } + + return array('#type' => 'ajax', '#commands' => $commands); +} + /** * Madlib validate handler. */ function madlib_form_validate($form, &$form_state) { - $verb_ing = $form_state['values']['madlib_verb_ing_textfield']; - if (strtolower(substr($verb_ing, strlen($verb_ing) - 3, 3)) != 'ing') { - form_set_error('madlib_verb_ing_textfield', + $required_keys = array( + 'madlib_plural_noun_1_textfield', + 'madlib_plural_noun_2_textfield', + 'madlib_plural_noun_3_textfield', + 'madlib_plural_noun_4_textfield', + 'madlib_plural_noun_5_textfield', + 'madlib_part_of_body_1_textfield', + 'madlib_part_of_body_2_textfield', + 'madlib_part_of_body_3_select', + 'madlib_number_select', + 'madlib_type_of_liquid_textfield', + 'madlib_part_of_body_plural_textfield', + 'madlib_adjective_1_textfield', + 'madlib_adjective_2_textfield', + 'madlib_adjective_3_textfield', + 'madlib_verb_ing_textfield', + 'madlib_noun_1_textfield', + 'madlib_noun_2_textfield', + ); + + $valid_keys = $required_keys; + array_push($valid_keys, + 'madlib_ajax_status_messages', + 'madlib_submit', + 'madlib_note', + 'madlib_output', + 'madlib_hidden', + 'form_build_id', + 'form_token', + 'form_id', + 'op' + ); + + if (!empty($form_state['values']['madlib_verb_ing_textfield'])) { + $verb_ing = $form_state['values']['madlib_verb_ing_textfield']; + + if (strtolower(substr($verb_ing, strlen($verb_ing) - 3, 3)) != 'ing') { + form_set_error('madlib_verb_ing_textfield', 'Verb_ing: Please enter a word that ends in "ing"'); + } + } + + foreach ($form_state['values'] as $form_item_key => $value) { + + $plain_form_item_key = check_plain($form_item_key); + $plain_value = check_plain($value); + + if (in_array($plain_form_item_key, $valid_keys)) { + + if ($plain_value <> $value) { + form_set_error($plain_form_item_key, + $plain_form_item_key . ': A form value should not contain anything other than plain text'); + } + + if (in_array($plain_form_item_key, $required_keys)) { + if ($plain_value == '') { + form_set_error($plain_value, + $plain_form_item_key . ': is a required text field, please enter a value'); + } + } + } + else { + form_set_error($plain_form_item_key, $plain_form_item_key . ': Form key not recognized'); + } } } @@ -289,3 +551,108 @@ function madlib_form_submit($form, &$form_state) { drupal_set_message(t('Answers received')); $form_state['rebuild'] = TRUE; } + +/** + * Madlib form output text in the t(). + */ +function madlib_form_output_text_with_t($form, &$form_state) { + + // CYA for logic flaws, if this function is called with errors return nothing. + madlib_form_validate($form, $form_state); + $errors = form_get_errors(); + if (!empty($errors)) { + return; + } + + if (empty($form_state['values']['madlib_plural_noun_1_textfield'])) { + return; + } + + // Find selected body part value. + $body_part_text_value = ''; + + $body_part_options + = $form_state['complete form']['madlib_section_3_fieldset']['madlib_part_of_body_3_select']['#options']; + + foreach ($body_part_options as $array) { + foreach ($array as $body_part => $text_value) { + if ($body_part == $form_state['values']['madlib_part_of_body_3_select']) { + $body_part_text_value = $text_value; + } + } + } + + // Correct a/an to a or an. + // Technically this isn't 100% correct but it is better than before. + $vowels = array('a', 'e', 'i', 'o', 'u'); + + $madlib_adjective_2_textfield_a_an = ''; + if (in_array(substr(check_plain($form_state['values']['madlib_adjective_2_textfield']), 0, 1), $vowels)) { + $madlib_adjective_2_textfield_a_an = 'a'; + } + else { + $madlib_adjective_2_textfield_a_an = 'an'; + } + + $madlib_adjective_3_textfield_a_an = ''; + if (in_array(substr(check_plain($form_state['values']['madlib_adjective_3_textfield']), 0, 1), $vowels)) { + $madlib_adjective_3_textfield_a_an = 'a'; + } + else { + $madlib_adjective_3_textfield_a_an = 'an'; + } + + // For cleaner code create two variables. + $madlib_number_select_value = $form_state['values']['madlib_number_select']; + $madlib_number_select + = $form_state['complete form']['madlib_section_2_fieldset']['madlib_number_select']['#options'][$madlib_number_select_value]; + + // Generate the text using the t(). + $output + = '

' . + t( + 'Giraffes have aroused the curiousity of @madlib_plural_noun_1_textfield + since earliest times. The giraffe is the tallest of all living @madlib_plural_noun_2_textfield + , but scientists are unable to explain how it got its long @madlib_part_of_body_1_textfield + . The giraffe\'s tremendous height, which might reach @madlib_number_select + @madlib_plural_noun_3_textfield + , comes mostly from its legs and @madlib_part_of_body_2_textfield + . If a giraffe wants to take a drink of @madlib_type_of_liquid_textfield + from the ground, it has @madlib_part_of_body_plural_textfield + far apart in order to reach down and lap up the water with its huge @body_part_text_value + . The giraffe has @madlib_adjective_1_textfield + ears that are sensitive to the faintest @madlib_plural_noun_4_textfield + , and it has @madlib_adjective_2_textfield_a_an @madlib_adjective_2_textfield + sense of smell and sight. When attacked, + a giraffe can put up @madlib_adjective_2_textfield_a_an @madlib_adjective_3_textfield + fight by @madlib_verb_ing_textfield + out with its hind legs and using its head like a sledge @madlib_noun_1_textfield + . Finally, a giraffe can gallop at more than thirty @madlib_plural_noun_5_textfield + an hour when pursued and can outrun the fastest @madlib_noun_2_textfield + .', + array( + '@madlib_plural_noun_1_textfield' => $form_state['values']['madlib_plural_noun_1_textfield'], + '@madlib_plural_noun_2_textfield' => $form_state['values']['madlib_plural_noun_2_textfield'], + '@madlib_part_of_body_1_textfield' => $form_state['values']['madlib_part_of_body_1_textfield'], + '@madlib_number_select' => $madlib_number_select, + '@madlib_plural_noun_3_textfield' => $form_state['values']['madlib_plural_noun_3_textfield'], + '@madlib_part_of_body_2_textfield' => $form_state['values']['madlib_part_of_body_2_textfield'], + '@madlib_type_of_liquid_textfield' => $form_state['values']['madlib_type_of_liquid_textfield'], + '@madlib_part_of_body_plural_textfield' => $form_state['values']['madlib_part_of_body_plural_textfield'], + '@body_part_text_value' => $body_part_text_value, + '@madlib_adjective_1_textfield' => $form_state['values']['madlib_adjective_1_textfield'], + '@madlib_plural_noun_4_textfield' => $form_state['values']['madlib_plural_noun_4_textfield'], + '@madlib_adjective_2_textfield_a_an' => $madlib_adjective_2_textfield_a_an, + '@madlib_adjective_2_textfield' => $form_state['values']['madlib_adjective_2_textfield'], + '@madlib_adjective_3_textfield_a_an' => $madlib_adjective_3_textfield_a_an, + '@madlib_adjective_3_textfield' => $form_state['values']['madlib_adjective_3_textfield'], + '@madlib_verb_ing_textfield' => $form_state['values']['madlib_verb_ing_textfield'], + '@madlib_noun_1_textfield' => $form_state['values']['madlib_noun_1_textfield'], + '@madlib_plural_noun_5_textfield' => $form_state['values']['madlib_plural_noun_5_textfield'], + '@madlib_noun_2_textfield' => $form_state['values']['madlib_noun_2_textfield'], + ) + ) . + '

'; + + return $output; +}