How to build a js calculator on a drupal 7 page/node?

18 replies [Last post]
marshallexcavating
Offline
Last seen: 8 years 22 weeks ago
Joined: 2011-02-03

I am trying to build a simple calculator module or I should say I am trying to learn the principals required to make a Drupal 7 math/calculator module that simply takes users inputs (form(numbers)) and dose some math on them and then displays the results on the same page with out a page refresh. I Dont need form validation because not going to db; just calculating and displaying results.

I have been able to get hook_menu to work and build a path to js script function to work in my .module file:

<?php

/**
 * Implements hook_menu().
 */

function calculator_jquery_menu() {
  $items['calculator_jquery'] = array(
    'title' => "Craig's jquery calculator module",
    'description' => 'Demonstration of various JavaScript utilities',
    'page callback' => 'calculator_jquery_p',
    'access callback' => TRUE,
  );
  return $items;
}

function calculator_jquery_p(){
  // Set the path to our script.
  $script = drupal_get_path('module', 'calculator_jquery') . '/calculator_jquery.js';

  // Include a JavaScript file.
  $js = drupal_add_js($script);

 $build = array(
 //  '#type' => 'markup',
 //  '#markup' => '<p>This is an examples page.</p>',
  );

  return $build;
}

My .js file is working:

jQuery(document).ready(function () {
//var text = jQuery('h1').text();
alert(1);
//<input type="checkbox" class="option" value="200" /> Name<br />;
//<input type="CHECKBOX" name="check1" value="yes" checked>;
//document.write('eee');
});

Sense I don't need a form validation I would like to use js forms not the Drupal form api. I have tried the following code in the js file with no luck as a simple test case using checkbox:

input type="checkbox" class="option" value="200"

the check box is not recognized by Drupal.

Dose any body have a suggestion how I can get this to work? or a good code resource/strategy to making this type of module? I am confused with how to write js code in drupal that is self running; all info for js in Drupal that I have found is hooking into the csm content/frame work. I would think that there is value to making some modules that just perform simple stuff(calculators, ect) with out hooking in to something else.

Thank you for any suggestions.

Chris Shattuck
Offline
Last seen: 10 weeks 4 days ago
Joined: 2009-08-16
Hey there, Have you tried

Hey there,

Have you tried starting from the 03.input.module.validation.step file in the /input/steps/ folder in the resource pack? Try installing that module and get it working. Then, tweak the inputs to include the inputs for calulating, and adjust the validation function to use your calculator logic. Use the drupal_set_message() to display the output. Once you have something functioning, then as a next step you can layer on the Ajax. But try starting there.

Hope that helps!
Chris

marshallexcavating
Offline
Last seen: 8 years 22 weeks ago
Joined: 2011-02-03
I see that hook_validate has

I see that hook_validate has the $form_state['values']['color'] form value that a user inputs. I see how to validate as a number and then do math with this but I am not following how you suggest to use Drupal_set_message(); the Drupal api example is from "includes/bootstrap.inc, line 1530" witch is not clear to me. Please point me to an examples to display $form_state['values']['color'] using Drupal_set_message()? Is there a way to display the calculated results in a form text area? This is something simple to do with in html pages.

Thank you for pointing me in this direction of getting the "Drupal form input to work" and then overlaying js. I was thinking that I could work exclusively with js.

marshallexcavating
Offline
Last seen: 8 years 22 weeks ago
Joined: 2011-02-03
I was able to find a example

I was able to find a example for the 6 – 7 drupal_set_message api (http://api.drupal.org/api/drupal/includes--bootstrap.inc/function/drupal...) and got it work:

function calculator_form_submit(&$elements, &$form_state, $form_id = NULL){
variable_set('volume', $form_state['values']['volume']);
//dsm($form_state);
drupal_set_message(t('form input: %title',array('%title'=>$form_state['values']['volume'])));
}

I would still like to be able to display the calculated results in a form text area instead of a drupal_set_message, but thank you for the suggestion. Any ideas how to display in a form text area?

Chris Shattuck
Offline
Last seen: 10 weeks 4 days ago
Joined: 2009-08-16
I'm glad you got something

I'm glad you got something working, that's always a good feeling. :)

If you want to display the result in a text area, you could do the calculation in the validation function and return an error on a hidden element to prevent the form from completely submitting, but also prevent any errors from displaying on the page, using form_set_error (http://api.drupal.org/api/drupal/includes--form.inc/function/form_set_error).

Let me know if that works for you.

marshallexcavating
Offline
Last seen: 8 years 22 weeks ago
Joined: 2011-02-03
Thanks Chris for the

Thanks Chris for the suggestion but I did not get your #4 comment above to work.

The strategy I have finally got working is:

  1. create a form. Using (hook_form)
  2. check form inputs to be numeric. Using (hook_form_validate)
  3. rebuild form with #value=>"calculated results from original form". Using (hook_form_alter)

I am not sure if this is a efficient way to go but it is the only thing I can get to work so far.

Following is my working .module file/code:

<?php
// $Id$
/<strong>
 <em>Implements hook_permission()
 * define user roles to see and use calculator.
</em>/
function calculator_permission() {
 return array(
            'access calculator page' => array(
        'title' => t('view calculator'),
       'description' => t('Perform calculacions with calculator.'),
            ),
  );
}

/</strong>
 <em>Implements hook_menu()
</em>/

function calculator_menu() {
$items=array();
           $items['calculator'] = array(
            'title' => "Craig's Weight/Mass calculator module!",
           'page callback' => 'calculator_page',
           'access arguments'=>array('access calculator page'),
        );
return $items;
}

function calculator_page(){
return drupal_get_form('calculator_form');
}


function calculator_form($node, &$form_state){
       $form['description'] = array(
            '#type' => 'item',
          '#title' => t('This is a simple calculator to determine Weight from Volume and Density'),
       );

        $form['volume'] = array(
         '#type' => 'textfield',
         '#title' => t('Input Volume of material here:'),
            '#default_value' => '1',
        );
         
       $form['density'] = array(
            '#type' => 'textfield',
         '#title' => t('Input Density of material here:'),
           '#default_value' => '2',
        );
 
          $form['submit'] = array(
         '#type' => 'submit',
            '#value' => 'Calculate Weight',
         );
return $form;
}

function calculator_form_validate(&$elements, &$form_state, $form_id = NULL){
      if ($form_state['values']['volume']==is_numeric($form_state['values']['volume']) AND $form_state['values']['density']==is_numeric($form_state['values']['density'])){

     form_set_error('results', 'Great you entered a number.');
//        form_set_error('results','.');
//$form_state['a'][]=$form_state['values']['volume']<em>$form_state['values']['density'];
        }
      else if($form_state['values']['volume']==!is_numeric($form_state['values']['volume']) OR $form_state['values']['density']==!is_numeric($form_state['values']['density'])){

        form_set_error('results', 'Must enter a number.');
     //form_set_error('results','.');
       }

//   dsm($form_state);
      drupal_set_message(t('Volume input: %title',array('%title'=>$form_state['values']['volume'])));
     drupal_set_message(t('Density input: %title',array('%title'=>$form_state['values']['density'])));
}

function calculator_form_alter(&$form, &$form_state, $form_id){
//dsm($form_state);
if($form_id=="calculator_form" AND is_numeric($form_state['input']['volume']) AND is_numeric($form_state['input']['density'])) {
     $form['results'] = array(
            '#type' =>  'textfield',
            '#title' => t('Calculated Weight results:'),
            '#value' => $form_state['input']['volume']</em>$form_state['input']['density'],
//'#value' =>$result
         );
}
else if ($form_id=="calculator_form" and !is_numeric($form_state['input']['volume'])){
      $form['results'] = array(
            '#type' =>  'textfield',
            '#title' => t(''),
          '#value' =>'Must input volume mumbers above only!!!!',
          );
}
else if ($form_id=="calculator_form" and !is_numeric($form_state['input']['density'])){
     $form['results'] = array(
            '#type' =>  'textfield',
            '#title' => t(''),
          '#value' =>'Must input density mumbers above only!!!!',
         );
}
else{
}
}

If you have a better strategy I would like to know about it. Your "Learn Drupal7 Development" cd is very helpful to me trying to learning how to code with in the Drupal api.

Thank you,

Chris Shattuck
Offline
Last seen: 10 weeks 4 days ago
Joined: 2009-08-16
Hi Craig, I'm glad you got

Hi Craig,

I'm glad you got something working! I would still suggest using the validate function to set an error and set the #value of results input (in $form_state). Did you get any indicators when you tried that before as to what might be going wrong?

Cheers!
Chris

marshallexcavating
Offline
Last seen: 8 years 22 weeks ago
Joined: 2011-02-03
Hi Chris, I am able to set

Hi Chris,

I am able to set the calculated #value of results input in the validate function as:

function calculator_form_validate(&$elements, &$form_state, $form_id = NULL){
       if ($form_state['values']['volume']==is_numeric($form_state['values']['volume']) AND $form_state['values']['density']==is_numeric($form_state['values']['density'])){

     form_set_error('results', 'Great you entered a number.');
      $form_state['values']['results'][] = $form_state['input']['volume']*$form_state['input']['density'];
       }

     else if($form_state['values']['volume']==!is_numeric($form_state['values']['volume']) OR $form_state['values']['density']==!is_numeric($form_state['values']['density'])){

        form_set_error('results', 'Must enter a number.');
     }
}

know that I have built/defined "$form_state['values']['results']" with in the validate function I can not see how how to display the "$form_state['values']['results']" in a form field from element using "form_set_error".

Craig

marshallexcavating
Offline
Last seen: 8 years 22 weeks ago
Joined: 2011-02-03
I have been trying to use

I have been trying to use form_set_value with in the calculator_form_validate function to rebuild my results form field with out any luck. Dose any body know of a good working example using the form_set_value for Drupal 7? The Drupal api is of no help showing/explaning how to implement it.

Thank you.

Chris Shattuck
Offline
Last seen: 10 weeks 4 days ago
Joined: 2009-08-16
Hi Craig, I'm wondering if

Hi Craig,

I'm wondering if maybe you're on the wrong track with form_set_value(). If you're stopping the form process at the validate function, then form_set_value() won't have any use, since it's intended to modify the value for the purpose of then passing it to the submit function.

Does that make sense?

Chris

Chris Shattuck
Offline
Last seen: 10 weeks 4 days ago
Joined: 2009-08-16
One thing you asked that I

One thing you asked that I didn't address in my previous post:

know that I have built/defined "$form_state['values']['results']" with in the validate function I can not see how how to display the "$form_state['values']['results']" in a form field from element using "form_set_error".

The idea of using form_set_error() is simply to stop the processing of the form. It has the side-effect of leaving the values of the inputs intact, so you can replace the value of an input, which you've been trying to do.

So when you set the value of $form_state['values']['results'], and then stop the form with form_set_error(), does it display the value you expect?

marshallexcavating
Offline
Last seen: 8 years 22 weeks ago
Joined: 2011-02-03
Hi chris, I agree with you I

Hi chris,

I agree with you I am complicating things trying to use form_set_value(); I am abandoning this idea.

When I set the value of $form_state['values']['results'] in the validate function under the form_set_error like:

function calculator_form_validate(&$elements, &$form_state, $form_id = NULL){
   if ($form_state['values']['volume']==is_numeric($form_state['values']['volume']) AND $form_state['values']['density']==is_numeric($form_state['values']['density'])){
  $form_state['values']['results'][0] = $form_state['input']['volume']*$form_state['input']['density'];
  form_set_error('results', $form_state['values']['results'][0]);
  }
  else if($form_state['values']['volume']==!is_numeric($form_state['values']['volume']) OR $form_state['values']['density']==!is_numeric($form_state['values']['density'])){
 form_set_error('results', 'Must enter a number.');
 }
}

I get the correct value displayed at the top of the page in a red message and the form results element is also outlined in red but blank. I have been trying to get the calculated value/result to display in the form results element.

I am close to making your strategy work but am stuck getting the calculated value/result to display in the form results element.

craig

rovo
Offline
Last seen: 11 years 17 weeks ago
Joined: 2011-03-07
Progress

Hi Marshall,

I am trying to do the same thing currently. Have you found any way around the obstacles you've hit?

Thanks
Rob

marshallexcavating
Offline
Last seen: 8 years 22 weeks ago
Joined: 2011-02-03
Hi Rob, One strategy that

Hi Rob,

One strategy that uses hook_form_alter is working to make a simple calculator. The "calculator.module" file is posted in this thread #5.

I am currently attempting to make the calculator with out hook_form_alter. I will post the solution if i can get it working. If you find something that works please post it here.

Thanks,

Craig

Chris Shattuck
Offline
Last seen: 10 weeks 4 days ago
Joined: 2009-08-16
Hi Craig, If you're still

Hi Craig,

If you're still working on this, I believe you can set the value of an input in the validation function. If I remember right from doing this in the past, you can use a form_set_error() on a hidden input to stop the submitting of the form, but not display any errors. And then do the setting of the form input value. You can use drupal_set_message() to display a confirmation-type message if you'd like at that point.

Let me know if any of that doesn't make sense.

Cheers!
Chris

marshallexcavating
Offline
Last seen: 8 years 22 weeks ago
Joined: 2011-02-03
Hi Chris, I am still trying

Hi Chris,

I am still trying to get the calculator/calculated result to display/render in a form element. I do not understand how to "set the value of an input in the validation function" so that the value is displayed in the form element when the validation function is triggered. Do you have a example of how to set/define a form value from with in the validation function?

Thank You,
Craig

Chris Shattuck
Offline
Last seen: 10 weeks 4 days ago
Joined: 2009-08-16
Hi Craig, Okay, here's a

Hi Craig,

Okay, here's a working example:

<?php

/**
 * @file
 * Examples from Build a Module.com
 */



/**
 * Implements hook_menu().
 */

function examples_menu() {
  // Module settings.
  $items['example'] = array(
    'title' => 'Example form',
    'description' => 'Example page',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('examples_form'),
    'access arguments' => array('access content'),
  );
  return $items;
}


/**
 * Simple example form that gets stopped at validation function.
 */

function examples_form($form, &$form_submit) {
  $form['number_1'] = array(
    '#title' => t('First number'),
    '#type' => 'textfield',
  );
  $form['number_2'] = array(
    '#title' => t('Second number'),
    '#type' => 'textfield',
  );
  $form['results'] = array(
    '#type' => 'item',
    '#title' => t('Results'),
    '#markup' => '<p>This is where resuls will display.</p>',
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
  );
  return $form;
}


/**
 * Validation for examples_form().
 *
 * Calculates the two numbers multiplied, and sets the value of the results.
 */

function examples_form_validate(&$form, &$form_state) {
  drupal_set_message('See your total below');
  $form['results']['#markup'] = $form_state['values']['number_1'] * $form_state['values']['number_1'];
  form_set_error('submit');
}

In the validation function, you see that we're setting the value of the results input with the result of the calculation, and then using form_set_error() on the submit input (I forgot about that trick).

Just make sure to change the name of the functions to match your module name (i.e. replace examples with mymodule), and let me know if that works for you.

Cheers!
Chris

marshallexcavating
Offline
Last seen: 8 years 22 weeks ago
Joined: 2011-02-03
Thank you Chris. I have been

Thank you Chris. I have been studying your solution and after reading the API for "_form_validate" and "form_set_error" several times I would not have been able to solve this problem with out your help.

Thank you.

Craig

erno
Offline
Last seen: 8 years 25 weeks ago
Joined: 2012-12-05
Trying to do the same

Hello,

I'm trying to do pretty much the same thing here. What I've done differently is that I'm trying to edit existing webform. Now when I do:

function tyolaskuri_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'webform_client_form_3') {
 
  $form['#validate'][] = 'tyolaskuri_calc_validate';

  $form['results'] = array(
    '#type' => 'item',
    '#title' => t('Results'),
    '#markup' => '<p>This is where resuls will display.</p>',
  );
 
  }
}

function tyolaskuri_calc_validate($form, &$form_state) {
  $trololoo = $form_state['input']['submitted']['numero'];
  $form['results']['#markup'] = $trololoo;
  form_set_error('submit');
}

Everything seems to be okay, except nothing new shows up on #markup. $trololoo shows up correctly if I drupal_set_message it on validate.

Add to playlist

Add to , or

Add to new playlist:

Add to playlist
This is a member-only feature
But, it's easy to become a member

Add to cart:


Loading...
Contact us

Below are the supported keyboard shortcuts for our video player.

space
Start / stop video
shift
Go to next video
shift
Go to previous video
Increase or decrease player speed by 20%
Skip ahead or go back by 15 seconds
1...9
Jump to a percentage (2 is 20%, for example)
f
Toggle full screen
Videos Pricing More Search
BuildAModule Logo Icon BuildAModule Logo Icon
Become a member!
$29
1 month
$156
6 months
10% off
$276
12 months
20% off
All memberships come with the following:
24 / 7 access to the entire 1800+ video library
An innovative video player with a rolling transcript
Extensive Drupal and cross-platform training
A thorough and thoughtful training style
Progress tracking
Take notes on specific video sections
Intuitive multi-user management
How many users?
user
Go solo with a single user, or give multiple team members access through one account and get discounts by bundling multiple users into a single membership.