Werdna has uploaded a new change for review.
https://gerrit.wikimedia.org/r/192783
Change subject: Add template syntax for OOUI in wikitext.
......................................................................
Add template syntax for OOUI in wikitext.
Warning: Currently has no XSS protection. If you do not want to be XSS'd,
then you should not allow untrusted users to edit any pages.
Bug: T88026
Change-Id: I69d7059f10eda73696b6257d9243f7785c0f783b
---
M autoload.php
D generateLibAutoload.php
A includes/ContainerAccess.php
M includes/DeferredWidget.php
A includes/OOUILightNCandy.php
M includes/ParserHooks.php
M includes/WidgetFactory.php
M includes/WidgetInfo.php
A includes/argument-filters/DeferredGroupElementFilter.php
A includes/argument-filters/FlagsFilter.php
M includes/argument-filters/GroupElementFilter.php
M includes/container.php
M resources/Resources.php
M resources/defer.js
14 files changed, 523 insertions(+), 60 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/OOUIPlayground
refs/changes/83/192783/1
diff --git a/autoload.php b/autoload.php
index 6ee40ca..9725d95 100644
--- a/autoload.php
+++ b/autoload.php
@@ -7,6 +7,9 @@
'OOUIPlayground\\ArgumentFilterGroup' => __DIR__ .
'/includes/argument-filters/ArgumentFilter.php',
'OOUIPlayground\\ArgumentFilterInterface' => __DIR__ .
'/includes/argument-filters/ArgumentFilter.php',
'OOUIPlayground\\ConfiguredCodeRenderer' => __DIR__ .
'/includes/CodeRenderer.php',
+ 'OOUIPlayground\\Container' => __DIR__ .
'/includes/ContainerAccess.php',
+ 'OOUIPlayground\\DeferredGroupElementFilter' => __DIR__ .
'/includes/argument-filters/DeferredGroupElementFilter.php',
+ 'OOUIPlayground\\FlagsFilter' => __DIR__ .
'/includes/argument-filters/FlagsFilter.php',
'OOUIPlayground\\GeSHICodeRenderer' => __DIR__ .
'/includes/CodeRenderer.php',
'OOUIPlayground\\GroupElementFilter' => __DIR__ .
'/includes/argument-filters/GroupElementFilter.php',
'OOUIPlayground\\ICodeRenderer' => __DIR__ .
'/includes/CodeRenderer.php',
@@ -18,6 +21,8 @@
'OOUIPlayground\\NoSuchWidgetException' => __DIR__ .
'/includes/WidgetInfo.php',
'OOUIPlayground\\NoTypeGiven' => __DIR__ .
'/includes/WidgetFactory.php',
'OOUIPlayground\\NullCodeRenderer' => __DIR__ .
'/includes/CodeRenderer.php',
+ 'OOUIPlayground\\OOUILightNCandy' => __DIR__ .
'/includes/OOUILightNCandy.php',
+ 'OOUIPlayground\\OOUIStatic' => __DIR__ .
'/includes/OOUILightNCandy.php',
'OOUIPlayground\\ParserHooks' => __DIR__ . '/includes/ParserHooks.php',
'OOUIPlayground\\PreCodeRenderer' => __DIR__ .
'/includes/CodeRenderer.php',
'OOUIPlayground\\WidgetDocumenter' => __DIR__ .
'/includes/WidgetDocumenter.php',
diff --git a/generateLibAutoload.php b/generateLibAutoload.php
deleted file mode 100644
index 108d90e..0000000
--- a/generateLibAutoload.php
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php
-
-require_once __DIR__ . '/../../includes/utils/AutoloadGenerator.php';
-
-function main() {
- $base = __DIR__ . '/lib';
- $generator = new AutoloadGenerator( $base );
- foreach ( array( 'oojs-ui/php' ) as $dir ) {
- $generator->readDir( $base . '/' . $dir );
- }
-
- $generator->generateAutoload( $base );
-
- echo "Done.\n\n";
-}
-
-main();
diff --git a/includes/ContainerAccess.php b/includes/ContainerAccess.php
new file mode 100644
index 0000000..24fd8d8
--- /dev/null
+++ b/includes/ContainerAccess.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace OOUIPlayground;
+
+class Container {
+ protected static $container;
+
+ /**
+ * Gets an object from the container.
+ * @param string $obj The object to get
+ * @return mixed|null That section in config.php, or null if it does
not exist.
+ */
+ public static function get( $obj ) {
+ if ( self::$container === null ) {
+ self::$container = require __DIR__ . '/container.php';
+ }
+
+ return self::$container[$obj];
+ }
+}
\ No newline at end of file
diff --git a/includes/DeferredWidget.php b/includes/DeferredWidget.php
index e2495b9..725212c 100644
--- a/includes/DeferredWidget.php
+++ b/includes/DeferredWidget.php
@@ -3,14 +3,26 @@
namespace OOUI;
use FormatJson;
+use MWException;
class DeferredWidget extends Widget {
+ protected $config;
+
/**
* @param string[]|bool $config['testparam'] A test parameter
*/
function __construct( array $config ) {
+ if ( ! isset( $config['class'] ) ) {
+ throw new MWException( "No class specified for
DeferredWidget" );
+ }
+
+ $this->config = $config;
$this->setAttributes( array( 'data-params' =>
FormatJson::encode( $config ) ) );
$this->addClasses( array( 'ooui-deferred' ) );
$this->tag = 'span';
}
+
+ public function getConfig() {
+ return $this->config;
+ }
}
diff --git a/includes/OOUILightNCandy.php b/includes/OOUILightNCandy.php
new file mode 100644
index 0000000..21bdb55
--- /dev/null
+++ b/includes/OOUILightNCandy.php
@@ -0,0 +1,165 @@
+<?php
+
+namespace OOUIPlayground;
+
+use FormatJson;
+use LightnCandy;
+use OOUI\DeferredWidget;
+use OOUI\MediaWikiTheme;
+use OOUI\Theme;
+use SimpleLightNCandy;
+
+class OOUILightNCandy extends SimpleLightNCandy {
+ protected $widgetRepo;
+ protected $widgetFactory;
+
+ function __construct( WidgetRepository $repo = null, WidgetFactory
$factory = null, $dir ) {
+ parent::__construct( $dir );
+ $this->widgetRepo = $repo;
+ $this->widgetFactory = $factory;
+
+ $this->setupHelpers();
+ }
+
+ public function setupRendering() {
+ Theme::setSingleton( new MediaWikiTheme );
+
+ OOUIStatic::overrideFactory( $this->widgetFactory );
+ OOUIStatic::overrideRepository( $this->widgetRepo );
+ }
+
+ public function teardownRendering() {
+ OOUIStatic::clearOverrides();
+ }
+
+ public function renderTemplate( $templateName, array $input ) {
+ $this->setupRendering();
+ $output = parent::renderTemplate( $templateName, $input );
+ $this->teardownRendering();
+ return $output;
+ }
+
+ public function renderString( $templateStr, array $input ) {
+ $this->setupRendering();
+ $output = parent::renderString( $templateStr, $input );
+ $this->teardownRendering();
+ return $output;
+ }
+
+ protected function setupHelpers() {
+ $this->addHBHelper( 'ooui',
+ function( $context, array $options ) {
+ return OOUIPlayground\OOUIStatic::oouiHelper(
$context, $options );
+ }
+ );
+ }
+
+ protected function getCompileOptions() {
+ $options = parent::getCompileOptions();
+
+ $options['flags'] ^= LightnCandy::FLAG_MUSTACHE;
+ $options['flags'] |= LightnCandy::FLAG_HANDLEBARSJS;
+
+ return $options;
+ }
+}
+
+/**
+ * It's not possible to pass the WidgetRepo or WidgetFactory into a
LightNCandy template,
+ * by design. So this is a hack we're using to get things working. It's
probably the wrong
+ * way to approach the problem but it works for now.
+ */
+abstract class OOUIStatic {
+ protected static $overrideRepo = null;
+ protected static $overrideFactory = null;
+
+ public static function oouiHelper( $context, array $options ) {
+ $widgetName = $context;
+
+ set_error_handler( function( $errno, $errstr, $errfile,
$errline ) {
+ die( "$errstr at $errfile:$errline\n" . wfBacktrace() );
+ } );
+
+ $widgetInfo = self::getRepo()->getInfo( $widgetName );
+ $params = self::getParams( $widgetInfo, $options );
+ if ( isset( $options['old_ctx']['_ooui_mode'] ) ) {
+ $params['type'] = $widgetInfo->getType();
+ $ret = array( FormatJson::encode( $params ) . ',',
'raw' );
+ } else {
+ $widget = self::getFactory()->getWidget( $widgetInfo,
$params );
+ if ( ! $widget instanceof DeferredWidget ) {
+ $widget->setAttributes(
+ array( 'data-params' =>
FormatJson::encode( $params ) )
+ );
+ }
+
+ $ret = array( $widget->__toString(), 'raw' );
+ }
+
+ restore_error_handler();
+ return $ret;
+ }
+
+ public static function getParams( WidgetInfo $widgetInfo, array
$options ) {
+ $params = array();
+
+ foreach( $options['hash'] as $key => $value ) {
+ if ( substr( $key, -strlen( '_json' ) ) === '_json' ) {
+ $params[substr( $key, 0, -strlen( '_json' ) )]
= FormatJson::encode( $value );
+ } elseif ( substr( $key, -strlen( '_list' ) ) ===
'_list' ) {
+ $params[substr( $key, 0, -strlen( '_list' ) )]
= explode( ' ', $value );
+ } else {
+ $params[$key] = $value;
+ }
+ }
+
+ // Handle contents if relevant
+ if ( isset( $options['fn'] ) ) {
+ $contentMode = $widgetInfo->getContentMode();
+ $contentVar = $widgetInfo->getContentVar();
+
+ if ( $contentMode === 'var' ) {
+ $params[$contentVar] = $options['fn']( array()
);
+ } elseif ( $contentMode === 'group' ) {
+ $input = $options['fn']( array( '_ooui_mode' =>
'groupelement' ) );
+ $input = trim( $input );
+ $input = rtrim( $input, ',' );
+ $input = "[$input]";
+ $input = FormatJson::decode( $input, true );
+
+ $params[$contentVar] = $input;
+ }
+ }
+
+ return $params;
+ }
+
+ public static function overrideRepository( WidgetRepository $repo =
null ) {
+ self::$overrideRepo = $repo;
+ }
+
+ public static function overrideFactory( WidgetFactory $factory = null )
{
+ self::$overrideFactory = $factory;
+ }
+
+ public static function clearOverrides() {
+ self::overrideRepository( null );
+ self::overrideFactory( null );
+ }
+
+ protected static function getRepo() {
+ if ( self::$overrideRepo !== null ) {
+ return self::$overrideRepo;
+ } else {
+ return Container::get( 'widgetRepository' );
+ }
+ }
+
+ protected static function getFactory() {
+ if ( self::$overrideFactory !== null ) {
+ return self::$overrideFactory;
+ } else {
+ return Container::get( 'widgetFactory' );
+ }
+ }
+}
diff --git a/includes/ParserHooks.php b/includes/ParserHooks.php
index 8bf03d9..c698e26 100755
--- a/includes/ParserHooks.php
+++ b/includes/ParserHooks.php
@@ -13,8 +13,6 @@
use Status;
class ParserHooks {
- protected static $container = null;
-
/**
* Handler for ParserFirstCallInit hook
* @param Parser $parser Parser to initialise
@@ -23,21 +21,9 @@
public static function setupParser( Parser $parser ) {
$parser->setHook( 'ooui-demo', array( __CLASS__, 'renderDemo' )
);
$parser->setHook( 'ooui-doc', array( __CLASS__, 'renderDoc' ) );
+ $parser->setHook( 'ooui-template', array( __CLASS__,
'renderTemplate' ) );
return true;
- }
-
- /**
- * Gets an object from the container.
- * @param string $obj The object to get
- * @return mixed|null That section in config.php, or null if it does
not exist.
- */
- protected static function getContainer( $obj ) {
- if ( self::$container === null ) {
- self::$container = require __DIR__ . '/container.php';
- }
-
- return self::$container[$obj];
}
/**
@@ -51,6 +37,15 @@
}
}
+ /**
+ * Gets an object from the container.
+ * @param string $obj The object to get
+ * @return mixed|null That section in config.php, or null if it does
not exist.
+ */
+ protected static function getContainer( $obj ) {
+ return Container::get( $obj );
+ }
+
public static function renderDoc( $input, array $args, Parser $parser,
PPFrame $frame ) {
$classStatus = self::getWidgetFromAttributes( $args );
@@ -62,6 +57,19 @@
$params = $doc->getOptions( $classStatus->getValue() );
return self::getContainer( 'templating' )->renderTemplate(
'widget_doc', $params );
+ }
+
+ public static function renderTemplate( $input, array $args, Parser
$parser, PPFrame $frame ) {
+ $parser->getOutput()->addModules(
'ext.ooui-playground.deferred-widgets' );
+ $parser->getOutput()->addModuleStyles( array( 'oojs-ui.styles'
) );
+
+ $templating = new OOUILightNCandy(
+ null /* default repo */,
+ null /* default factory */,
+ __DIR__ . "/../templates"
+ );
+
+ return $templating->renderString( $input, array() );
}
/**
@@ -113,7 +121,7 @@
}
/**
- * Reads the attributes of a tag call to get info about the requested
class
+ * Reads the attributes of a tag call to get info about the requested
class
* @param array $attributes Attributes of a tag call.
* @todo Merge with WidgetRepository::create
* @return WidgetInfo
diff --git a/includes/WidgetFactory.php b/includes/WidgetFactory.php
index 5bff766..ed9bb7a 100644
--- a/includes/WidgetFactory.php
+++ b/includes/WidgetFactory.php
@@ -2,50 +2,75 @@
namespace OOUIPlayground;
+use OOUI\DeferredWidget;
use MWException;
class WidgetFactory {
/** @var ArgumentFilterGroup */
protected $filter;
+ /** @var ArgumentFilterGroup */
+ protected $deferredFilters;
/** @var WidgetRepository */
protected $repo;
/**
* @param WidgetRepository $repo
* @param array[ArgumentFilterInterface] $filters
+ * * @param array[ArgumentFilterInterface] $deferredFilters
*/
- function __construct( WidgetRepository $repo, array $filters = array()
) {
+ function __construct( WidgetRepository $repo, array $filters = array(),
array $deferredFilters = array() ) {
$this->repo = $repo;
$this->filter = new ArgumentFilterGroup( $filters );
+ $this->deferredFilter = new ArgumentFilterGroup(
$deferredFilters );
}
- function getWidget( WidgetInfo $info, array $args ) {
- $this->filter->filter( $info, $args );
- $className = $info->getFullClassName();
- return new $className( $args );
+ /**
+ * [getWidget description]
+ * @param WidgetInfo $info Widget description retrieved from a
WidgetRepository
+ * @param array $args Parameters to pass to the widget
constructor.
+ * @param boolean $defer Set to true if this widget should
unconditionally
+ * be rendered by OOUI-JS instead of OOUI-PHP
+ * @return \OOUI\Widget
+ */
+ function getWidget( WidgetInfo $info, array $args, $defer = false ) {
+ if ( $defer || $info->isDeferred() ) {
+ $this->deferredFilter->filter( $info, $args );
+ $args['class'] = $info->getClassName();
+ $args['passthru'][] = __METHOD__;
+ return new DeferredWidget( $args );
+ } else {
+ $this->filter->filter( $info, $args );
+ $className = $info->getFullClassName();
+
+ return $info->instantiate( $args );
+ }
}
/**
* Creates a widget from an array configuration
* @param array $args Array of parameters for the widget.
* The 'type' parameter is required
+ * @param boolean $defer Set to true if this widget should
unconditionally
+ * be rendered by OOUI-JS instead of OOUI-PHP
* @throws NoSuchWidgetException
* @throws NoTypeGivenException
- * @return Widget
+ * @return \OOUI\Widget
*/
- public function create( array $args ) {
+ public function create( array $args, $defer = false ) {
if ( ! isset( $args['type'] ) ) {
throw new NoTypeGivenException();
}
$widgetClass = $this->repo->getInfo( $args['type'] );
unset( $args['type'] );
+ $args['passthru'][] = __METHOD__;
- return $this->getWidget( $widgetClass, $args );
+ return $this->getWidget( $widgetClass, $args, $defer );
}
- public function addFilter( ArgumentFilterInterface $filter ) {
- $this->filter->addFilter( $filter );
+ public function addFilter( ArgumentFilterInterface $filter, $deferred =
false ) {
+ $modifyFilter = $deferred ? $this->deferredFilter :
$this->filter;
+ $modifyFilter->addFilter( $filter );
}
}
diff --git a/includes/WidgetInfo.php b/includes/WidgetInfo.php
index efc1f15..c9cc058 100644
--- a/includes/WidgetInfo.php
+++ b/includes/WidgetInfo.php
@@ -21,13 +21,7 @@
* (cannot be used with new because it's in the wrong namespace)
*/
public function getClassName( $type ) {
- $type = strtolower( $type );
-
- if ( ! isset( $this->classMap[$type] ) ) {
- throw new NoSuchWidgetException( $type );
- } else {
- return $this->classMap[$type]['class'];
- }
+ return $this->getInfo( $type )['className'];
}
/**
@@ -37,10 +31,12 @@
* @return WidgetInfo
*/
public function getInfo( $type ) {
- $className = $this->getClassName( $type );
+ $type = strtolower( $type );
- if ( $className ) {
+ if ( isset( $this->classMap[$type] ) ) {
return new WidgetInfo( $type, $this->classMap[$type] );
+ } else {
+ throw new NoSuchWidgetException( $type );
}
}
}
@@ -118,6 +114,10 @@
* @return ReflectionClass
*/
public function getReflection() {
+ if ( $this->isDeferred() ) {
+ throw new MWException( "Getting reflection is not
supported on deferred widgets" );
+ }
+
return new ReflectionClass( $this->getFullClassName() );
}
@@ -128,16 +128,45 @@
return 'OOUI\\' . $this->className;
}
+ public function getContentMode() {
+ return $this->getAttribute( 'contentMode' ) ?: 'var';
+ }
+
+ public function getContentVar() {
+ return $this->getAttribute( 'contentVar' ) ?: 'content';
+ }
+
+ public function isDeferred() {
+ return $this->getAttribute( 'deferred' ) != null;
+ }
+
+ public function hasSpecialInstantiator() {
+ return is_callable( $this->getSpecialInstantiator() );
+ }
+
+ public function getSpecialInstantiator() {
+ return $this->getAttribute( 'instantiator' );
+ }
+
+ protected function getAttribute( $name ) {
+ return isset( $this->classInfo[$name] ) ?
$this->classInfo[$name] : null;
+ }
+
/**
* Get an instance of the OOUI-PHP class
- * Only for internal use, outside this class
+ * Only for internal use, outside this class and
WidgetFactory::getWidget
* you should use a correctly configured WidgetFactory.
* @param array $args Options for instantiation
* @return OOUI\Widget The requested class
*/
- protected function instantiate( array $args = array() ) {
+ public function instantiate( array $args = array() ) {
$fullClass = $this->getFullClassName();
- return new $fullClass( $args );
+ if ( $this->hasSpecialInstantiator() ) {
+ $instantiator = $this->getSpecialInstantiator();
+ return $instantiator( $fullClass, $args );
+ } else {
+ return new $fullClass( $args );
+ }
}
}
diff --git a/includes/argument-filters/DeferredGroupElementFilter.php
b/includes/argument-filters/DeferredGroupElementFilter.php
new file mode 100644
index 0000000..77974d8
--- /dev/null
+++ b/includes/argument-filters/DeferredGroupElementFilter.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace OOUIPlayground;
+
+use MWException;
+use OOUI\DeferredWidget;
+
+class DeferredGroupElementFilter extends GroupElementFilter {
+ protected function instantiateWidget( array $item ) {
+ $widget = $this->widgetFactory->create( $item, true );
+
+ if ( ! $widget instanceof DeferredWidget ) {
+ throw new MWException( "Created a non-deferred widget
of type " . get_class( $widget ) );
+ }
+
+ return $widget->getConfig();
+ }
+}
+
diff --git a/includes/argument-filters/FlagsFilter.php
b/includes/argument-filters/FlagsFilter.php
new file mode 100644
index 0000000..0773b1c
--- /dev/null
+++ b/includes/argument-filters/FlagsFilter.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace OOUIPlayground;
+
+class FlagsFilter implements ArgumentFilterInterface {
+ function filter( WidgetInfo $widget, array &$args ) {
+ if ( isset( $args['flags'] ) ) {
+ $args['flags'] = explode( ' ', $args['flags'] );
+ }
+ }
+}
diff --git a/includes/argument-filters/GroupElementFilter.php
b/includes/argument-filters/GroupElementFilter.php
index 0c907d5..6044bb6 100644
--- a/includes/argument-filters/GroupElementFilter.php
+++ b/includes/argument-filters/GroupElementFilter.php
@@ -13,19 +13,30 @@
}
public function filter( WidgetInfo $widget, array &$arguments ) {
- if ( $widget->isA( 'GroupElement' ) && isset(
$arguments['items'] ) ) {
+ if ( $this->shouldProcess( $widget, $arguments ) ) {
$newItems = array();
foreach( $arguments['items'] as $item ) {
if ( ! is_array( $item ) ) {
throw new
InvalidGroupElementItemException();
} else {
- $newItems[] =
$this->widgetFactory->create( $item );
+ $newItems[] = $this->instantiateWidget(
$item );
}
}
$arguments['items'] = $newItems;
}
}
+
+ // @todo This works right now but it's fragile.
+ // We'd like to check for the GroupElement mixin, but some things that
+ // we treat as GroupElements (e.g. FieldLayout) don't mix that in.
+ protected function shouldProcess( WidgetInfo $widget, array $arguments
) {
+ return isset( $arguments['items'] ) && is_array( reset(
$arguments['items'] ) );
+ }
+
+ protected function instantiateWidget( array $item ) {
+ return $this->widgetFactory->create( $item );
+ }
}
class InvalidGroupElementItemException extends MWException {
diff --git a/includes/container.php b/includes/container.php
index 462fec9..02a6858 100644
--- a/includes/container.php
+++ b/includes/container.php
@@ -8,18 +8,42 @@
$container = new Container;
+// Options:
+// class: Required, class name
+// deferred: Optional, default false.
+// If set to true, this element will be rendered in JS instead of PHP.
+// contentVar: Optional, default 'content'.
+// If this element is called with the block helper, the config variable to be
+// filled with the processed block content.
+// contentMode: Optional, default 'var'.
+// If the element is called with the block helper, what to do with the
contents.
+// Has the following possible values:
+// * var: Take the raw content and put it unprocessed into the variable.
+// * group: The parent element is a group element, add all OOUI elements
inside
+// it to the parent element.
+// instantiator: Optional.
+// If this element's constructor has a nonstandard signature
+// (the standard signature is function __construct( array $config ))
+// This should be a function with the following signature:
+// function( string $className, array $config ) :OOUI\Widget
+// It should be able to cope with empty $config
$container['classMap'] = array(
'buttongroup' => array(
'class' => 'ButtonGroupWidget',
+ 'contentMode' => 'group',
+ 'contentVar' => 'items',
),
'buttoninput' => array(
'class' => 'ButtonInputWidget',
+ 'contentVar' => 'label',
),
'button' => array(
'class' => 'ButtonWidget',
+ 'contentVar' => 'label',
),
'checkboxinput' => array(
'class' => 'CheckboxInputWidget',
+ 'contentVar' => 'label',
),
'icon' => array(
'class' => 'IconWidget',
@@ -32,15 +56,153 @@
),
'label' => array(
'class' => 'LabelWidget',
+ 'contentVar' => 'label',
),
'radioinput' => array(
'class' => 'RadioInputWidget',
),
'textinput' => array(
'class' => 'TextInputWidget',
+ 'contentVar' => 'value',
),
'deferred' => array(
'class' => 'DeferredWidget',
+ ),
+ 'action' => array(
+ 'class' => 'ActionWidget',
+ 'deferred' => true,
+ ),
+ 'buttonoption' => array(
+ 'class' => 'ButtonOptionWidget',
+ 'deferred' => true,
+ 'contentVar' => 'label',
+ ),
+ 'buttonselect' => array(
+ 'class' => 'ButtonSelectWidget',
+ 'deferred' => true,
+ 'contentMode' => 'group',
+ 'contentVar' => 'items',
+ ),
+ 'combobox' => array(
+ 'class' => 'ComboBoxWidget',
+ 'deferred' => true,
+ ),
+ 'decoratedoption' => array(
+ 'class' => 'DecoratedOptionWidget',
+ 'deferred' => true,
+ ),
+ 'dropdown' => array(
+ 'class' => 'DropdownWidget',
+ 'deferred' => true,
+ ),
+ 'menuoption' => array(
+ 'class' => 'MenuOptionWidget',
+ 'deferred' => true,
+ ),
+ 'menusectionoption' => array(
+ 'class' => 'MenuSectionOptionWidget',
+ 'deferred' => true,
+ ),
+ 'menuselect' => array(
+ 'class' => 'MenuSelectWidget',
+ 'deferred' => true,
+ 'contentMode' => 'group',
+ 'contentVar' => 'items',
+ ),
+ 'option' => array(
+ 'class' => 'OptionWidget',
+ 'deferred' => true,
+ ),
+ 'outlinecontrols' => array(
+ 'class' => 'OutlineControlsWidget',
+ 'deferred' => true,
+ ),
+ 'outlineoption' => array(
+ 'class' => 'OutlineOptionWidget',
+ 'deferred' => true,
+ 'contentVar' => 'label',
+ ),
+ 'outlineselect' => array(
+ 'class' => 'OutlineSelectWidget',
+ 'deferred' => true,
+ 'contentMode' => 'group',
+ 'contentVar' => 'items',
+ ),
+ 'popupbutton' => array(
+ 'class' => 'PopupButtonWidget',
+ 'deferred' => true,
+ ),
+ 'popup' => array(
+ 'class' => 'PopupWidget',
+ 'deferred' => true,
+ ),
+ 'progressbar' => array(
+ 'class' => 'ProgressBarWidget',
+ 'deferred' => true,
+ ),
+ 'radiooption' => array(
+ 'class' => 'RadioOptionWidget',
+ 'deferred' => true,
+ 'contentVar' => 'label',
+ ),
+ 'radioselect' => array(
+ 'class' => 'RadioSelectWidget',
+ 'deferred' => true,
+ 'contentMode' => 'group',
+ 'contentVar' => 'items',
+ ),
+ 'search' => array(
+ 'class' => 'SearchWidget',
+ 'deferred' => true,
+ ),
+ 'select' => array(
+ 'class' => 'SelectWidget',
+ 'deferred' => true,
+ ),
+ 'textinputmenuselect' => array(
+ 'class' => 'TextInputMenuSelectWidget',
+ 'deferred' => true,
+ ),
+ 'togglebutton' => array(
+ 'class' => 'ToggleButtonWidget',
+ 'deferred' => true,
+ ),
+ 'toggleswitch' => array(
+ 'class' => 'ToggleSwitchWidget',
+ 'deferred' => true,
+ ),
+ 'fieldlayout' => array(
+ 'class' => 'FieldLayout',
+ 'contentMode' => 'group',
+ 'contentVar' => 'items',
+ 'instantiator' => function( $className, array $config ) {
+ $element = false;
+ if (
+ isset( $config['items'] ) &&
+ is_array( $config['items'] ) &&
+ count( $config['items'] )
+ ) {
+ $element = reset( $config['items'] );
+ }
+
+ // If there's an empty $config, give a dummy element.
+ if ( ! $element ) {
+ $element = new \OOUI\LabelWidget;
+ }
+
+ if ( is_array( $element ) ) {
+ var_dump( $element, $config );
+ die( wfBacktrace() );
+ }
+
+ unset( $config['items'] );
+ return new $className( $element, $config );
+ },
+ ),
+ 'fieldsetlayout' => array(
+ 'class' => 'FieldsetLayout',
+ 'contentMode' => 'group',
+ 'contentVar' => 'items',
),
);
@@ -74,6 +236,7 @@
// Some filters want a WidgetFactory
$factory->addFilter( new GroupElementFilter( $factory ) );
+ $factory->addFilter( new DeferredGroupElementFilter( $factory ), true );
return $factory;
};
diff --git a/resources/Resources.php b/resources/Resources.php
index 25b7327..dcacc38 100644
--- a/resources/Resources.php
+++ b/resources/Resources.php
@@ -7,8 +7,12 @@
);
$wgResourceModules['ext.ooui-playground'] = array(
- 'scripts' => array( 'display.js', 'defer.js' ),
- 'dependencies' => array( 'oojs-ui' ),
+ 'styles' => 'display.less',
+ 'scripts' => array( 'display.js' ),
+ 'dependencies' => array(
+ 'oojs-ui',
+ 'ext.ooui-playground.deferred-widgets',
+ ),
'messages' => array(
"ooui-playground-language-php",
"ooui-playground-language-javascript",
@@ -19,3 +23,9 @@
'styles' => array( 'display.less', 'hidecode.css' ),
'position' => 'top',
) + $oouiPlaygroundResourceTemplate;
+$wgResourceModules['ext.ooui-playground.deferred-widgets'] = array(
+ 'scripts' => 'defer.js',
+ 'dependencies' => array(
+ 'oojs-ui',
+ ),
+) + $oouiPlaygroundResourceTemplate;
diff --git a/resources/defer.js b/resources/defer.js
index a2476ae..b668f60 100644
--- a/resources/defer.js
+++ b/resources/defer.js
@@ -7,6 +7,8 @@
newItems;
if ( typeof OO.ui[className] === 'undefined' ) {
+ console.log( "Unable to load " + className );
+ console.dir( config );
return $( '<span/>' ).addClass( 'error' )
.text( 'Unable to load ' + className );
}
@@ -41,7 +43,7 @@
$( '.ooui-deferred' ).each( function() {
var config = $( this ).data( 'params' ),
- widget = instantiateFromParameters( config );
+ widget = instantiateFromParameters( $.extend( {},
config ) );
if ( widget.$element ) {
$( this ).replaceWith( widget.$element );
--
To view, visit https://gerrit.wikimedia.org/r/192783
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I69d7059f10eda73696b6257d9243f7785c0f783b
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/OOUIPlayground
Gerrit-Branch: master
Gerrit-Owner: Werdna <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits