When a form element doesn't specify a #weight, it is assumed internally as #weight 0. However, to ensure that our form elements display visually *as they were defined in the array* we, in form_builder, count the number of elements, divide by 1000, and set that as the weight:

# Assign a decimal placeholder weight to preserve original array order
if (!isset($form[$key]['#weight'])) {
  $form[$key]['#weight'] = $count/1000;
}

The above code will set the #weights of elements that have not defined a weight to something like 0 (first element in array definition), 0.001, 0.002, and so on. However, anytime a form element *explicitly* defines a #weight of 0, that #weight is kept at exactly 0, which would cause that form element to appear BEFORE the elements that didn't have a #weight defined (and thus received a #weight such as 0.002).

Consider the following pseudo example:

  $form['game_title'] = array(
    '#type'          => 'textfield',
    ...
  );
  $form['game_description'] = array(
    '#type'          => 'textarea',
    ...
  );
  $form['game_format'] = filter_form(variable_get('game_format', NULL));
  return $form;

Here, we're not definiing weights on our two textfields. We then add an filter_form. The second parameter of the filter_form is $weight, which defaults to 0. After this $form hits form_builder, we have weights 0 (game_title), 0.001 (game_description), and 0 (filter_form) respectively. This is then sorted by weight, which causes filter_form (the third element in the array) to appear BEFORE game_description (0 is lighter than 0.001).

The short lesson is: explicitly defining #weight 0 for a form element is probably a bad idea. This patch changes the default #weight of filter_form to NULL, instead of 0, and also removes any other explicit setting of #weight to 0 in core.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

chx’s picture

Now, that textarea & filter_form has its own subtree this is the sensible thing to do. Also, it leads to less code which is always a good thing :)

chx’s picture

Status: Needs review » Reviewed & tested by the community
Morbus Iff’s picture

Note that this patch doesn't just affect filter_form. Yes, filter_form will probably be the only time it will ever cause a visible issue (per the pseudo code), but we generally *want* the 0.001, 0.002, etc. stuff to happen, which is why the patch also removes any other explicit definitions of #weight 0.

With that said, chx does bring up another optimization, and I've attached an updated patch. With filter_form getting its weight changed to NULL (instead of 0), we no longer need to set #weight to 1 on our new body_filter branches, because we can just let the "divide by 1000" thing take effect (which would give the filter_form, in these cases, a weight of 0.001).

chx’s picture

Less code! Yay!

Zen’s picture

I just tested this too: +1.

-K
P.S I wonder if the Views form has more than 1000 unset weights? ;)

Dries’s picture

Status: Reviewed & tested by the community » Fixed

Committed to HEAD. Thanks.

Anonymous’s picture

Status: Fixed » Closed (fixed)