Make WordPress Core

Opened 12 years ago

Last modified 5 years ago

#20558 new enhancement

allow wp_localize_script data to be added to existing objects

Reported by: ryanve's profile ryanve Owned by:
Milestone: Priority: normal
Severity: normal Version: 3.3
Component: Script Loader Keywords: dev-feedback needs-patch
Focuses: Cc:

Description

Re: WP_Scripts::localize() located in wp-includes/class.wp-scripts.php

Currently when WP_Scripts::localize() handles the printing of wp_localize_script data to JavaScript, it starts the string with a var declaration, like this:

$script = "var $object_name = " . json_encode($l10n) . ';';

Because this is printed in the global scope, it becomes a global variable regardless of whether it's preceded by var. As far as JavaScript is concerned the above string would be equivalent to:

$script = $object_name . ' = ' . json_encode($l10n) . ';';

or

$script = 'this.' . $object_name . ' = ' . json_encode($l10n) . 
';';

or

$script = 'window.' . $object_name . ' = ' . json_encode($l10n) . 
';';

But I suppose it's possible thru hooks to make it so that the localization data prints outside of the global scope, in which case you might want the var to be there (if it we're wrapped in a closure). So I think the overall best solution would to check if the $object_name contains a period . character. If it does, omit the var. In other words, make it so that:

wp_localize_script('myplugin', 'myPluginData', $object )

would print:

var myPluginData = {...};

but that:

`wp_localize_script('myplugin', 'myPlugin.data', $object )`

would print:

myPlugin.data = {...};

By default the localization data runs before any enqueued scripts, in which case myPlugin would not yet be defined, but we should leave that for the JavaScript dev work out. My point is that the flexiblity should be there. Another route would be to apply a filter on that line but I don't think a filter is necessary if the above change is made.

Change History (10)

#1 @ryanve
12 years ago

Another future consideration would be if an $object_name is not provided, then expose the data to a single global object called wordpress:

window.wordpress = {};

so that wp_localize_script($handle, false, $object) would do

$script =  'wordpress["' . $handle . '"] = ' . json_encode($object) . ';';

You'd have to use bracket notation to accomodate stuff like

wordpress["jquery-ui-core"] =  { ... };

Should probably do sanitize_key($handle) first to be safe.

#2 follow-up: @scribu
12 years ago

Another future consideration would be if an $object_name is not provided, then expose the data to a single global object called wordpress

How would that help? Plugins would still have to prefix their options.

#3 in reply to: ↑ 2 @ryanve
12 years ago

Replying to scribu:
@scribu The less pollution of JavaScript's global namespace, the better, both for performance and for avoiding conflicts. The script handles already provide a unique identifier for each script. Having a single object could also make it easier to integrate modular code along the lines of http://requirejs.org

#4 @westonruter
11 years ago

  • Cc weston@… added

#5 @ocean90
11 years ago

  • Cc ocean90 added
  • Keywords reporter-feedback removed
  • Severity changed from minor to normal

#6 @swissspidy
11 years ago

  • Cc hello@… added

#7 @nacin
11 years ago

  • Component changed from Performance to Script Loader

It'd be cool if WP core could assign stuff directly into the wp object or whatever. However, this needs a patch. I've looked at this before and for whatever reason decided it against doing it myself.

#8 @abdessamad idrissi
10 years ago

+1 for this. I'm using requirejs in one of my themes, and the script needs to be called with data-main attribute set, like:

<script data-main="path/to/main" src="path/to/require.js"></script>

I suggest passing an extra array of attributes to the wp_register_script/wp_enqueue_script.

#9 @here
10 years ago

Add a 4th argument for object name?

wp_localize_script('gimme-objects', 'bar', array( "a" => 1 ), 'foo');

var foo = foo || {};
foo.bar = foo.bar || {"a" : 1};

See also, this hack: https://gist.github.com/here/8c908f00fd3f45e76805

#10 @chriscct7
9 years ago

  • Keywords needs-patch added; 2nd-opinion removed
Note: See TracTickets for help on using tickets.