From 25248da99adbb0221008974cc1e2aeba08bdfdde Mon Sep 17 00:00:00 2001
From: webchick <webchick@24967.no-reply.drupal.org>
Date: Sat, 7 Jul 2012 13:52:10 -0700
Subject: [PATCH] Issue #1071818 by JeremyFrench, nod_, reglogge, anthbel, xjm,
 sun, NROTC_Webmaster, lliss, Cottser: Fixed Lazy-loading CSS fails in IE.

---
 core/includes/ajax.inc                        | 25 ++++++++++++++++++-
 core/includes/common.inc                      |  6 ++++-
 core/misc/ajax.js                             | 20 +++++++++++++++
 .../lib/Drupal/simpletest/WebTestBase.php     |  2 ++
 .../Drupal/system/Tests/Ajax/CommandsTest.php |  8 ++++++
 .../Tests/Common/CascadingStylesheetsTest.php |  4 +++
 .../ajax_forms_test/ajax_forms_test.module    | 18 +++++++++++++
 7 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/core/includes/ajax.inc b/core/includes/ajax.inc
index a72fc5543a90..328f54cd55d9 100644
--- a/core/includes/ajax.inc
+++ b/core/includes/ajax.inc
@@ -276,7 +276,7 @@ function ajax_render($commands = array()) {
 
   $extra_commands = array();
   if (!empty($styles)) {
-    $extra_commands[] = ajax_command_prepend('head', $styles);
+    $extra_commands[] = ajax_command_add_css($styles);
   }
   if (!empty($scripts_header)) {
     $extra_commands[] = ajax_command_prepend('head', $scripts_header);
@@ -1186,3 +1186,26 @@ function ajax_command_restripe($selector) {
     'selector' => $selector,
   );
 }
+
+/**
+ * Creates a Drupal Ajax 'add_css' command.
+ *
+ * This method will add css via ajax in a cross-browser compatible way.
+ *
+ * This command is implemented by Drupal.ajax.prototype.commands.add_css()
+ * defined in misc/ajax.js.
+ *
+ * @param $styles
+ *   A string that contains the styles to be added.
+ *
+ * @return
+ *   An array suitable for use with the ajax_render() function.
+ *
+ * @see misc/ajax.js
+ */
+function ajax_command_add_css($styles) {
+  return array(
+    'command' => 'add_css',
+    'data' => $styles,
+  );
+}
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 5c5777a6abdd..0b95dcd8dbf9 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -3304,7 +3304,11 @@ function drupal_pre_render_styles($elements) {
             $import_batch = array_slice($import, 0, 31);
             $import = array_slice($import, 31);
             $element = $style_element_defaults;
-            $element['#value'] = implode("\n", $import_batch);
+            // This simplifies the JavaScript regex, allowing each line
+            // (separated by \n) to be treated as a completely different string.
+            // This means that we can use ^ and $ on one line at a time, and not
+            // worry about style tags since they'll never match the regex.
+            $element['#value'] = "\n" . implode("\n", $import_batch) . "\n";
             $element['#attributes']['media'] = $group['media'];
             $element['#browsers'] = $group['browsers'];
             $elements[] = $element;
diff --git a/core/misc/ajax.js b/core/misc/ajax.js
index aef9f310d7ae..71399c4d2171 100644
--- a/core/misc/ajax.js
+++ b/core/misc/ajax.js
@@ -609,6 +609,26 @@ Drupal.ajax.prototype.commands = {
       .removeClass('odd even')
       .filter(':even').addClass('odd').end()
       .filter(':odd').addClass('even');
+  },
+
+  /**
+   * Command to add css.
+   *
+   * Uses the proprietary addImport method if available as browsers which
+   * support that method ignore @import statements in dynamically added
+   * stylesheets.
+   */
+  add_css: function (ajax, response, status) {
+    // Add the styles in the normal way.
+    $('head').prepend(response.data);
+    // Add imports in the styles using the addImport method if available.
+    var match, importMatch = /^@import url\("(.*)"\);$/igm;
+    if (document.styleSheets[0].addImport && importMatch.test(response.data)) {
+      importMatch.lastIndex = 0;
+      while (match = importMatch.exec(response.data)) {
+        document.styleSheets[0].addImport(match[1]);
+      }
+    }
   }
 };
 
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 592e9d94aed4..0856611e60c8 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -1369,6 +1369,8 @@ protected function drupalPostAJAX($path, $edit, $triggering_element, $ajax_path
             break;
           case 'restripe':
             break;
+          case 'add_css':
+            break;
         }
       }
       $content = $dom->saveHTML();
diff --git a/core/modules/system/lib/Drupal/system/Tests/Ajax/CommandsTest.php b/core/modules/system/lib/Drupal/system/Tests/Ajax/CommandsTest.php
index 299b674583f6..faa35bbbe3a3 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Ajax/CommandsTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Ajax/CommandsTest.php
@@ -157,5 +157,13 @@ function testAjaxCommands() {
       'settings' => array('ajax_forms_test' => array('foo' => 42)),
     );
     $this->assertCommand($commands, $expected, "'settings' AJAX command issued with correct data");
+
+    // Tests the 'add_css' command.
+    $commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'add_css' command")));
+    $expected = array(
+      'command' => 'add_css',
+      'data' => 'my/file.css',
+    );
+    $this->assertCommand($commands, $expected, "'add_css' AJAX command issued with correct data");
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/CascadingStylesheetsTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/CascadingStylesheetsTest.php
index 441a2ba3c67b..397762bf4de6 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/CascadingStylesheetsTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/CascadingStylesheetsTest.php
@@ -89,6 +89,10 @@ function testRenderFile() {
     drupal_add_css($css);
     $styles = drupal_get_css();
     $this->assertTrue(strpos($styles, $css) > 0, t('Rendered CSS includes the added stylesheet.'));
+    // Verify that newlines are properly added inside style tags.
+    $query_string = variable_get('css_js_query_string', '0');
+    $css_processed = "<style media=\"all\">\n@import url(\"" . check_plain(file_create_url($css)) . "?" . $query_string ."\");\n</style>";
+    $this->assertEqual(trim($styles), $css_processed, t('Rendered CSS includes newlines inside style tags for JavaScript use.'));
   }
 
   /**
diff --git a/core/modules/system/tests/modules/ajax_forms_test/ajax_forms_test.module b/core/modules/system/tests/modules/ajax_forms_test/ajax_forms_test.module
index 6a95710a80ad..d4074d1f8213 100644
--- a/core/modules/system/tests/modules/ajax_forms_test/ajax_forms_test.module
+++ b/core/modules/system/tests/modules/ajax_forms_test/ajax_forms_test.module
@@ -258,6 +258,15 @@ function ajax_forms_test_ajax_commands_form($form, &$form_state) {
     ),
   );
 
+  // Shows the Ajax 'add_css' command.
+  $form['add_css_command_example'] = array(
+    '#type' => 'submit',
+    '#value' => t("AJAX 'add_css' command"),
+    '#ajax' => array(
+      'callback' => 'ajax_forms_test_advanced_commands_add_css_callback',
+    ),
+  );
+
   $form['submit'] = array(
     '#type' => 'submit',
     '#value' => t('Submit'),
@@ -410,6 +419,15 @@ function ajax_forms_test_advanced_commands_settings_callback($form, $form_state)
   return array('#type' => 'ajax', '#commands' => $commands);
 }
 
+/**
+ * Ajax callback for 'add_css'.
+ */
+function ajax_forms_test_advanced_commands_add_css_callback($form, $form_state) {
+  $commands = array();
+  $commands[] = ajax_command_add_css('my/file.css');
+  return array('#type' => 'ajax', '#commands' => $commands);
+}
+
 /**
  * This form and its related submit and callback functions demonstrate
  * not validating another form element when a single Ajax element is triggered.
-- 
GitLab