Questions

Events happening in the community are now at Drupal community events on www.drupal.org.
silence's picture

Hi everyone,

I updated the Form Builder module today to give it some improvements. You can get it from the modules>formbuilder folder.

Please check the format of the $form array that is being formed. I cant find examples of some of the widget properties. If someone can provide them, It'll be really really helpful.

form[checkboxes][' #default_value'] // 0,1,2 or value of the key?
form[checkbox]['#default_value']     // 0,1 or true/false
form[radios]['#default_value']       // similar problem
form[radio]['#default_value']        // similar problem
form[select]['#default_value']       // similar problem
form[date]['#default_value']        // (what will the format of the date be?)

So basically .... all the default_value properties.

secondly, Right now the #options property of checkboxes and select are strings of format:


'#options' : "array('key1' => 'value 1', 'key2' => 'value 2'",

Now is this correct or am I supposed to keep the type of #options as an array? In the latter case it will be something like this:


'#options' : {
'key1' : 'value 1',
'key2' : 'value 2'
}

Everything till now was javascript.

I am also having problems with Urls. here is the code:

<?php
function formbuilder_menu($may_cache) {
 
$items = array();
  if (
$may_cache) {
   
$items[] = array(
     
'path' => 'formbuilder/receive',
     
'title' => t('formbuilder receive'),
     
'access' => user_access('formbuilder save forms'),
     
'type' => MENU_CALLBACK,
     
'callback' => 'formbuilder_receive'
    
);
:
:
?>

This code basically defines a page which on my computer I can access via browser at:
http://localhost/drupal-4.7.2/?q=formbuilder/receive

Now I am trying to post the js form object through AJAX. For posting the form object, I need the url of the above page and I can't figure out how to get that. Simeple js files are included without a problem because drupal_get_path provides the absolute path. But for "formbuilder/receive", the page does not exist so I get a 404. Please help me out here...
Right now I am using a workaround posted below but I dont think this is going to work is all cases.

function send()
{
  $.post("?q=formbuilder/receive",{      // The address of the page. A proper alternative for this is what I need
    "formId" : formId,                    // Id of the form.
"properties" : s.object(properties)  // The serialized js form Object
  },function(xml){ alert( decodeURIComponent(xml));  });  // Some call back function
}

Please Help me out here :)

Comments

Nice progress!

nedjo's picture

You're really pushing ahead. The formbuilder is looking very good.

A few comments and suggestions:

  • The newer look to the UI is nice.
  • Form saving works on my testing.
  • It's not totally clear to me using the formbuilder how I save an element when I'm done editing it. Should there be a 'save' button at the bottom of the element properties editing section?
  • I got a couple of errors: 1. a javascript error on trying to create a new form element. 2. When I tried to resave a form, I got a message that a form with that id already exists.
  • "am I supposed to keep the type of #options as an array?" Yes, they should be arrays, with the keys being the data to be saved and the values being the text to be displayed.
  • "I am also having problems with Urls." This is a general problem in Drupal. If you wish you can look at the use of the jsTools.query variable in jstools.module. It tracks whether clean_urls are enabled, and therefore whether site urls should have the '?q='. I'd say what you have is fine for now though.
  • Regarding the #default_value settings, these are generally references to objects passed into a function building a form. For example, a node title has a default value of $node->title--the title assigned to the node in a previous submit. This might be displayed on preview or on edit of a previously-submitted node. I don't see any way for you to know at this point what the appropriate value is--or, even if you did know, to put it in. So I'd say, leave it out, with a note in the readme. It can be added in later when we know more.
  • Have a look at the function __element_info() in form.inc. It invokes the 'elements' hook to load default data for all defined form elements. This might be a good replacement for the way you're trying to generate a default set of properties. You could do something like this:

<?php
/**
* Retrieve data on all defined element types.
*/
function formbuilder_element_types() {
 
$types = array();
 
$basic_defaults = array(
   
'#description' => NULL,
   
'#attributes' => array(),
   
'#required' => FALSE,
   
'#tree' => FALSE,
   
'#parents' => array()
  );
  foreach (
module_implements('elements') as $module) {
   
$elements = module_invoke($module, 'elements');
    if (isset(
$elements) && is_array($elements)) {
     
$cache = array_merge_recursive($types, $elements);
    }
  }
  if (
sizeof($types)) {
    foreach (
$types as $element_type => $info) {
     
$cache[$element_type] = array_merge_recursive($basic_defaults, $info);
    }
  }
  return
$types;
}
?>

Then you can send the data to the browser as:

<?php
print drupal_to_js(formbuilder_element_types());
?>

This might also allow you to drop the hard-coded indexes of element types 0 = 'checkbox', etc.), which would be good for extensibility.

  • functions.js should maybe be called formbuilder.js for clarity.
  • The code in functions.js should be formatted according to Drupal formatting conventions. See the various .js files in the /includes directory of Drupal's distribution. E.g.:
  • indent with double spaces (not tabs)
  • curly braces on same line as function names
  • etc.
  • function additem I think should first load the properties and then send the result to a theme function. You can adapt the various element theming functions in form.inc into js. Maybe it would make sense to put them all in a single function. You'll also need to write js versions of a few helper functions that are called in the theme functions. For example, theme_select() could be adapted into a general theme function in js. Here's a very rough suggestion:

function formbuilderThemeElement(type, element) {
  switch(type) {
    case 'select':
      var select = '';
      var size = element['#size'] ? ' size="' . element['#size'] . '"' : '';
      if (!element['#atrributes']) {
        element['#attributes'] = [];
      }
      element['#attributes']['class'] = formbuilderGetClass(element);
      return theme('form_element', element['#title'], ''. formbuilerSelectOptions(element) .'', element['#description'], element['#id'], element['#required'], form_get_error($element));
}

This would need the additional functions formbuilderGetClass() (based on form_set_class()), formbuilderAttributes() (based on drupal_attributes()), formbuilderSelectOptions() (based on form_select_options()).

Here's a rough idea of formbuilderGetClass. We return a class because we can't pass by reference as is done in the Drupal equivalent.

/**
* Sets a form element's class attribute.
*
* Adds 'required' and 'error' classes as needed.
*
* @param element
*   The form element.
* @param name
*   Array of new class names to be added.
*/
function formbuilderGetClass(element, class) {
  if (class == null) {
    class = [];
  }
  if (element['#required']) {
    class[class.length] = 'required';
  }
  if (element['#attributes'] && element['#attributes']['class'])) {
    class[class.length] = element['#attributes']['class'];
  }
  return class.split(' ');
}

A few more suggestions...

nedjo's picture
  • It would be useful to be able to load a PHP version of the form. You could do this through an AJAX call. Post the form array, convert it from JSON to PHP, use var_export() to turn the PHP into a string, then send the string back to the browser.
  • Are you referring to the "Form Controls" and "Special Elements" tables at http://api.drupal.org/api/HEAD/file/developer/topics/forms_api_reference... ? This is the best source for the types of elements we'll want to support along with their properties.
  • The form element itself can accept several properties in addition to an id, e.g, #prefix, #suffix, etc.
  • It might be useful to have a variety of options for how to display the form. Right now you are mixing a preview with elements to edit the element (drag it, delete it). Possibly it would be better to separate the preview into a different tab, and have the repositioning and deleting as, e.g., a tree menu. That would facilitate eventual nested form elements--which are common. PHP view as suggested above would then be a third tab.
  • Instead of writing the theme functions in js, you could consider just posting the form array to the server, theming it there, and returning the result. In some ways that might be cleaner--it would mean you wouldn't need to update the js every time there was a theming change in the PHP code. It would also respect any theme overrides present on the server. And it would save a lot of coding.

Format?

silence's picture
  1. Should there be just one column and multiple tabs or 2 columns + tabs or some other combinatation?
  2. Are these the only possible tabs: Adding an item, Preview, PHP code View, Properties view, Editing view?
  3. How should I place them? as in which should be shown permanently and which should be in tabs form?

I'll work on some of the

silence's picture

I'll work on some of the easier points right now and send u a reply in a a day or two. For the others, I'll work on and submit more by this week-end.

problem...

silence's picture

Hi!
I tried to use the _element_info to get the default values for an item as you said. I am getting a problem in the sense that the specifications at the http://api.drupal.org/api/HEAD/file/developer/topics/forms_api_reference... page are different from what is returned.

Value returned by the function for text area:

array (
  '#description' => NULL,
  '#attributes' =>
  array (
  ),
  '#required' => false,
  '#tree' => false,
  '#parents' =>
  array (
  ),
  '#input' => true,
  '#cols' => 60,
  '#rows' => 5,
)

whereas the values defined in reference have following extra : after_build, default_value, prefix,suffix, title, type, weight. Also "input" was returned by the function but it is not there in reference.

As far as I can see only the properties which are common to all the widgets are not there and some "INTERNAL" properties are show. So I'll add these properties through code and do what you asked me to do.

SoC 2006: AJAX Form Builder

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds:

Hot content this week