Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.981
diff -u -r1.981 common.inc
--- includes/common.inc	31 Aug 2009 18:43:12 -0000	1.981
+++ includes/common.inc	2 Sep 2009 03:43:54 -0000
@@ -3177,14 +3177,16 @@
 }
 
 /**
- * Adds all the attached libraries, JavaScript and CSS to the page.
+ * Add to the page all structures attached to the element like libraries,
+ * JavaScript, CSS and other types of custom structures. Attached structures
+ * are added to the element using attached properties. The property names for
+ * attached structures begin with #attached_ and the rest if the type of the
+ * structure. For example: #attached_library, #attached_js, #attached_css.
+ * A function named drupal_add_<type> must exists, where <type> is the type of
+ * the structure being addded.
  *
- * @param $libraries
- *   An array of depending libraries to be added.
- * @param $js
- *   An array of JavaScript components to add.
- * @param $css
- *   An array of cascading stylesheets to add.
+ * @param $elements
+ *   The structured array describing the data being rendered.
  * @param $weight
  *   The default weight of JavaScript and CSS being added. This is only applied
  *   to the stylesheets and JavaScript items that don't have an explicit weight
@@ -3197,12 +3199,26 @@
  *   Will return FALSE if there were any missing library dependencies. TRUE will
  *   be returned if all library dependencies were met.
  *
- * @see drupal_add_library(), drupal_render()
- */
-function drupal_process_attached(array $libraries = array(), array $js = array(), array $css = array(), $weight = JS_DEFAULT, $dependency_check = FALSE) {
+ * @see drupal_add_library().
+ * @see drupal_add_js().
+ * @see drupal_add_css().
+ * @see drupal_render().
+ */
+function drupal_process_attached($elements, $weight = JS_DEFAULT, $dependency_check = FALSE) {
+  $attached = element_attached($elements);
+  // If there is nothing to process return 
+  if (empty($attached)) {
+    return;
+  }
+  $elements += array(
+    '#attached_library' => array(),
+    '#attached_js' => array(),
+    '#attached_css' => array(),
+  );
+
   // Add the libraries first.
   $success = TRUE;
-  foreach ($libraries as $library) {
+  foreach ($elements['#attached_library'] as $library) {
     if (drupal_add_library($library[0], $library[1]) === FALSE) {
       $success = FALSE;
       // Exit if the dependency is missing.
@@ -3213,8 +3229,8 @@
   }
 
   // Add both the JavaScript and the CSS.
-  foreach (array('js' => $js, 'css' => $css) as $type => $items) {
-    foreach ($items as $data => $options) {
+  foreach (array('js', 'css') as $type) {
+    foreach ($elements["#attached_$type"] as $data => $options) {
       // If the value is not an array, it's a filename and passed as first
       // (and only) argument.
       if (!is_array($options)) {
@@ -3234,6 +3250,13 @@
       call_user_func('drupal_add_' . $type, $data, $options);
     }
   }
+
+  // Add additional types of attachments specified in the render() structure.
+  $attached = array_diff($attached, array('#attached_library', '#attached_js', '#attached_css'));
+  foreach ($attached as $type) {
+    call_user_func_array('drupal_add_'. str_replace('#attached_', '', $type), $elements[$type]);
+  }
+  
   return $success;
 }
 
@@ -3266,7 +3289,12 @@
   if (!isset($added[$module][$name])) {
     if ($library = drupal_get_library($module, $name)) {
       // Add all components within the library.
-      $added[$module][$name] = drupal_process_attached($library['dependencies'], $library['js'], $library['css'], JS_LIBRARY, TRUE);
+      $elements = array(
+        '#attached_library' => $library['dependencies'],
+        '#attached_js' => $library['js'],
+        '#attached_css' => $library['css'],
+      );
+      $added[$module][$name] = drupal_process_attached($elements, JS_LIBRARY, TRUE);
     }
     else {
       // Requested library does not exist.
@@ -4115,12 +4143,9 @@
     }
   }
 
-  // Add additional libraries, CSS and JavaScript associated with this element.
-  drupal_process_attached(
-    isset($elements['#attached_library']) ? $elements['#attached_library'] : array(),
-    isset($elements['#attached_js']) ? $elements['#attached_js'] : array(),
-    isset($elements['#attached_css']) ? $elements['#attached_css'] : array()
-  );
+  // Add additional libraries, CSS, JavaScript an other custom
+  // attached structures associated with this element.
+  drupal_process_attached($elements);
 
   $prefix = isset($elements['#prefix']) ? $elements['#prefix'] : '';
   $suffix = isset($elements['#suffix']) ? $elements['#suffix'] : '';
@@ -4226,12 +4251,9 @@
   $bin = isset($elements['#cache']['bin']) ? $elements['#cache']['bin'] : 'cache';
 
   if (!empty($cid) && $cache = cache_get($cid, $bin)) {
-    // Add additional libraries, CSS and JavaScript associated with this element.
-    drupal_process_attached(
-      isset($cache->data['#attached_library']) ? $cache->data['#attached_library'] : array(),
-      isset($cache->data['#attached_js']) ? $cache->data['#attached_js'] : array(),
-      isset($cache->data['#attached_css']) ? $cache->data['#attached_css'] : array()
-    );
+    // Add additional libraries, JavaScript, CSS and other custom structures
+    // attached to this element.
+    drupal_process_attached($cache->data);
     // Return the rendered output.
     return $cache->data['#markup'];;
   }
@@ -4409,6 +4431,23 @@
 }
 
 /**
+ * Check if the key is an attached property.
+ */
+function element_attached_property($key) {
+  return strpos($key, '#attached_') === 0;
+}
+
+/**
+ * Get attached properties of a structured array element. Attached properties
+ * begin with '#attached_' and the rest after the underscore is used
+ * for the type of the attached structure. For example: #attached_js,
+ * #attached_css, #attached_library.  
+ */
+function element_attached($element) {
+  return array_filter(array_keys((array) $element), 'element_attached_property');
+}
+
+/**
  * Get properties of a structured array element. Properties begin with '#'.
  */
 function element_properties($element) {
