This issue is a delegate of #251578: More flexible js/css ordering and an alter operation to add an "external" type to drupal_add_js so that you can reference files that arn't hosted locally. If JavaScript performance is enabled, it will download the file and host it locally.

This will have to wait until at least #315797: JavaScript Patch #1: $options is in.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mfer’s picture

subscribe

hass’s picture

Status: Postponed » Closed (duplicate)
mfer’s picture

Title: JavaScript Patch #3: External Scripts » JavaScript Patch #3: JS Alter Operation
Status: Closed (duplicate) » Active

The external scripts part is at #91250: JavaScript Patch #4: External Scripts so we can remove it from the scope of this issue and concentrate on hook_js_alter.

RobLoach’s picture

Thanks, Matt!

RobLoach’s picture

Status: Active » Postponed
mfer’s picture

Now that #315798: JavaScript Patch #2: Weight is in it's time to get this patch rolling. The patch should be fairly simple (fingers crossed). Deciding on the placement of the alter call will be more difficult.

Should it be in drupal_add_js or in drupal_get_js?

If we place the alter call in drupal_add_js:

  • It will be called each time drupal_add_js is called with may be several times on a page.
  • The returned js array from drupal_add_js will contain the alterations.

If we place the alter call in drupal_get_js:

  • It will be called each time drupal_get_js is called. In core we would only see this called twice for the 2 regions (header and footer).
  • The returned js array from drupal_add_js would not contain the alterations. Alteration would happen at presentation.

Thoughts?

mfer’s picture

Status: Postponed » Active
webchick’s picture

subscriiiiibe. :)

Owen Barton’s picture

Assigned: Unassigned » Owen Barton

Taking a shot at this

RobLoach’s picture

Assigned: Owen Barton » Unassigned
Status: Active » Needs review
FileSize
2.43 KB

It doesn't make much sense to call alter twice when the page is displaying because you might want to move some JavaScript from the 'footer' scope to the 'header' scope, so essentially, you'd be moving that script up to the top of the page twice unnecessarily. I propose using a static variable to check if the alter has been called. I also believe that altering the JavaScript after all JavaScript is added is more important then altering individual elements, because what if one JavaScript file needs to somehow reference another one in the array?

This patch calls drupal_alter() at the first call to drupal_get_js(), as well as adds simpletest_js_alter(&$javascript), to stick simpletest.js before tableselect.js.

Any thoughts on removing the relative paths in the $javascript array so that instead of having $javascript['modules/simpletest/simpletest.js'], we have $javascript['simpletest.js']? This would make finding and modifying JavaScript files throughout the array much easier. All it would require is calling basename() when sticking the items in the array.

mfer’s picture

I don't know that I like the idea of making the key 'simpletest.js' rather than the full path. If we did this we would have to somehow get developers to follow a js file naming namespace. Although, it might be a good idea to enforce good namespacing with js file names. Imagine a case where 2 different modules called a file called script.js. How would you preform an alter on those 2 files differently?

We will run into an issue of modules and themes calling drupal_get_js that will need to be cleaned up. Imagine a module, for example OG which does this in drupal 6, that has a function og_preprocess_page call and in there calls drupal_add_js and drupal_get_js. In the order of the processing of these the drupal_get_js call isn't needed. If it's called before other hook_preprocess_page functions are called some drupal_add_js added files won't have the alter done on them.

Are there any use cases where we would run into a problem of calling the alter in drupal_get_js only once? I'm not saying the issues above are a stopper. We might want to include some usage examples to make sure contrib modules don't mess things up accidentally.

To put simply, we need some good documentation on this so developers don't misuse drupal_get_js.

RobLoach’s picture

Status: Needs review » Needs work

Also, some tests would be good.

RobLoach’s picture

Status: Needs work » Needs review
FileSize
4.6 KB
  • Adds a passing test
  • Removes check to see if we already called hook_js_alter() because footer JavaScript was ignoring the alterations
  • Added a note about hook_js_alter() in drupal_get_js()
Owen Barton’s picture

FileSize
8.8 KB

Locale module is a perfect example of where we should be implementing this alter (rather than calling locale code directly from drupal_get_js). The attached patch adds this - it could use some more testing.

RobLoach’s picture

Status: Needs review » Needs work

Great work there! I'm blind to not notice the locale example.

I noticed a documentation error in my code........

+ * Note that hook_js_alter(&$javascript) is called during this function call
+ * to allow alterations of the JavaScript during its presentation. Calls to
+ * drupal_add_js() from hook_js_alter() will reflect properly on screen as
+ * hook_js_alter() is made for modifying JavaScript, not adding JavaScript.

.... Should be something like:
"Calls to drupal_add_js() from hook_js_alter() will reflect improperly on screen. The correct way to add JavaScript during hook_js_alter() is to add another element to the $javascript array, deriving from drupal_get_js_defaults()."

mfer’s picture

Here is what I saw from a quick pass of the patch

  • Why, in locale_js_alter, is the if statement for type != 'setting' and 'inline' rather than = 'file'?
  • function locale_js_alter is an implementation of hook_js_alter() not hook_javascript_alter(). The comment needs to be updated.
  • In simpletest_js_alter we assume if simpletest.js is included that tableselect.js is included as well. Should we have that assumption or should we test for both simpletest.js and tableselect.js? If they are both present then set the simpletest.js weight to be just before tableselect.js.
  • In the testAlter method where we test the altering script there should be a comment to refer to simpletest_js_alter for the expected altering. I stared at that for more than a few seconds before it struck me what was happening. If I didn't know about simpletest_js_alter the test wouldn't make sense.
RobLoach’s picture

Status: Needs work » Needs review
FileSize
7.73 KB
  1. Fixed up locale_js_alter (removed changes that didn't need to be in there like mfer mentioned)
  2. Fixed up a bit of the documentation in drupal_get_js_defaults(), as well as added an optional $data parameter (nice idea, grugnog)
  3. Added a check to see if both simpletest.js and tableselect.js exist in simpletest_js_alter
  4. Fixed documentation error I mentioned in #15
  5. Added a note in testAlter about simpletest_js_alter like mfer mentioned.
mfer’s picture

Is the name drupal_get_js_defaults the correct name? The one place I found where a function returns defaults is _book_link_defaults (are there others?). On the other hand I don't see a drupal_get_* function returning defaults. See http://api.drupal.org/api/search/7/drupal_get_. Would a name like _js_defaults or _drupal_js_defaults be better?

This block doesn't read cleanly to me:

+ * Note that hook_js_alter(&$javascript) is called during this function call
+ * to allow alterations of the JavaScript during its presentation. Calls to
+ * drupal_add_js() from hook_js_alter() will reflect improperly on screen. The
+ * correct way to add JavaScript during hook_js_alter() is to add another
+ * element to the $javascript array, deriving from drupal_get_js_defaults().
+ * See locale_js_alter() for a demonstration of this.

Instead what if we use something like:

* Note that hook_js_alter(&$javascript) is called during this function call
* to allow alterations of the JavaScript during its presentation. Calls to
* drupal_add_js() from hook_js_alter() will not be add to the output 
* presentation. The correct way to add JavaScript during hook_js_alter()
* is to add another element to the $javascript array, deriving from 
* drupal_get_js_defaults(). See locale_js_alter() for an example.
* @see locale_js_alter()

I'll test the functionality tonight and make sure everything works as expected.

RobLoach’s picture

FileSize
7.77 KB
  1. Renames drupal_get_js_defaults() to _drupal_js_defaults()
  2. Hits up mfer's documentation fix drupal_get_js().
RobLoach’s picture

FileSize
7.69 KB

Taking a look at other uses of @see in Drupal core, it seems they're all on different lines, and use the parenthesis.

mfer’s picture

Status: Needs review » Reviewed & tested by the community

Looks good and passes test. Nice job Rob Loach and Grugnog2.

Status: Reviewed & tested by the community » Needs work

The last submitted patch failed testing.

webchick’s picture

Status: Needs work » Reviewed & tested by the community

Submitting for re-testing after HEAD-breakage snafu this afternoon.

webchick’s picture

In the words of catch, this is a lovely, lovely patch filled with loveliness. Nice job using SimpleTest and Locale as the use cases for the hook you've introduced. And unit tests too! What's not to love? :)

Testing bot seems to be stuck, so I'm running the tests locally here overnight. Assuming that pans out okay, I'll give this another look tomorrow.

RobLoach’s picture

FileSize
7.71 KB

Webchick and her eagle eye noticed a couple of @see's without the ()......

quicksketch’s picture

All in all, fantastic!

One head-scratcher though (even after reading #18 and #19):

+ * presentation. The correct way to add JavaScript during hook_js_alter()
+ * is to add another element to the $javascript array, deriving from
+ * _drupal_js_defaults(). See locale_js_alter() for an example of this.

It looks to me like _drupal_js_defaults() should not be "private", especially since we're recommending other modules call it directly (as locale.module does). It seems like the definition of a public API function if we're using it in 3rd party modules and outside of common.inc.

RobLoach’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
7.7 KB
webchick’s picture

Status: Needs review » Needs work

Excellent. :)

Committed to HEAD. Thanks! Docs please! :D

RobLoach’s picture

Status: Needs work » Fixed

http://drupal.org/node/224333#hook_js_alter
http://drupal.org/cvs?commit=154664

If you guys are better writers then me, then please feel free to update appropriately........ On a somewhat unrelated matter, I'd really like #314870: UNSTABLE-4 blocker: Add api.php for every core module so that hook documentation updates wouldn't require an entirely different commit.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.