PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/oojs/oojs-ui/demos/demo.js

https://gitlab.com/link233/bootmw
JavaScript | 491 lines | 306 code | 53 blank | 132 comment | 18 complexity | 60f0e3ad1497783b2efa8c0826f9d97a MD5 | raw file
  1. /**
  2. * @class
  3. * @extends {OO.ui.Element}
  4. *
  5. * @constructor
  6. */
  7. OO.ui.Demo = function OoUiDemo() {
  8. // Parent
  9. OO.ui.Demo.parent.call( this );
  10. // Normalization
  11. this.normalizeHash();
  12. // Properties
  13. this.stylesheetLinks = this.getStylesheetLinks();
  14. this.mode = this.getCurrentMode();
  15. this.$menu = $( '<div>' );
  16. this.pageDropdown = new OO.ui.DropdownWidget( {
  17. menu: {
  18. items: [
  19. new OO.ui.MenuOptionWidget( { data: 'dialogs', label: 'Dialogs' } ),
  20. new OO.ui.MenuOptionWidget( { data: 'icons', label: 'Icons' } ),
  21. new OO.ui.MenuOptionWidget( { data: 'toolbars', label: 'Toolbars' } ),
  22. new OO.ui.MenuOptionWidget( { data: 'widgets', label: 'Widgets' } )
  23. ]
  24. },
  25. classes: [ 'oo-ui-demo-pageDropdown' ]
  26. } );
  27. this.pageMenu = this.pageDropdown.getMenu();
  28. this.themeSelect = new OO.ui.ButtonSelectWidget().addItems( [
  29. new OO.ui.ButtonOptionWidget( { data: 'mediawiki', label: 'MediaWiki' } ),
  30. new OO.ui.ButtonOptionWidget( { data: 'apex', label: 'Apex' } )
  31. ] );
  32. this.directionSelect = new OO.ui.ButtonSelectWidget().addItems( [
  33. new OO.ui.ButtonOptionWidget( { data: 'ltr', label: 'LTR' } ),
  34. new OO.ui.ButtonOptionWidget( { data: 'rtl', label: 'RTL' } )
  35. ] );
  36. this.jsPhpSelect = new OO.ui.ButtonGroupWidget().addItems( [
  37. new OO.ui.ButtonWidget( { label: 'JS' } ).setActive( true ),
  38. new OO.ui.ButtonWidget( {
  39. label: 'PHP',
  40. href: 'demos.php' +
  41. '?page=widgets' +
  42. '&theme=' + this.mode.theme +
  43. '&direction=' + this.mode.direction
  44. } )
  45. ] );
  46. // Events
  47. this.pageMenu.on( 'choose', OO.ui.bind( this.onModeChange, this ) );
  48. this.themeSelect.on( 'choose', OO.ui.bind( this.onModeChange, this ) );
  49. this.directionSelect.on( 'choose', OO.ui.bind( this.onModeChange, this ) );
  50. // Initialization
  51. this.pageMenu.selectItemByData( this.mode.page );
  52. this.themeSelect.selectItemByData( this.mode.theme );
  53. this.directionSelect.selectItemByData( this.mode.direction );
  54. this.$menu
  55. .addClass( 'oo-ui-demo-menu' )
  56. .append(
  57. this.pageDropdown.$element,
  58. this.themeSelect.$element,
  59. this.directionSelect.$element,
  60. this.jsPhpSelect.$element
  61. );
  62. this.$element
  63. .addClass( 'oo-ui-demo' )
  64. .append( this.$menu );
  65. $( 'html' ).attr( 'dir', this.mode.direction );
  66. $( 'head' ).append( this.stylesheetLinks );
  67. OO.ui.theme = new ( this.constructor.static.themes[ this.mode.theme ].theme )();
  68. };
  69. /* Setup */
  70. OO.inheritClass( OO.ui.Demo, OO.ui.Element );
  71. /* Static Properties */
  72. /**
  73. * Available pages.
  74. *
  75. * Populated by each of the page scripts in the `pages` directory.
  76. *
  77. * @static
  78. * @property {Object.<string,Function>} pages List of functions that render a page, keyed by
  79. * symbolic page name
  80. */
  81. OO.ui.Demo.static.pages = {};
  82. /**
  83. * Available themes.
  84. *
  85. * List of theme descriptions, each containing a `fileSuffix` property used for linking to the
  86. * correct stylesheet file and a `theme` property containing a theme class
  87. *
  88. * @static
  89. * @property {Object.<string,Object>}
  90. */
  91. OO.ui.Demo.static.themes = {
  92. mediawiki: {
  93. fileSuffix: '-mediawiki',
  94. additionalSuffixes: [
  95. '-icons-movement',
  96. '-icons-content',
  97. '-icons-alerts',
  98. '-icons-interactions',
  99. '-icons-moderation',
  100. '-icons-editing-core',
  101. '-icons-editing-styling',
  102. '-icons-editing-list',
  103. '-icons-editing-advanced',
  104. '-icons-media',
  105. '-icons-location',
  106. '-icons-user',
  107. '-icons-layout',
  108. '-icons-accessibility',
  109. '-icons-wikimedia'
  110. ],
  111. theme: OO.ui.MediaWikiTheme
  112. },
  113. apex: {
  114. fileSuffix: '-apex',
  115. additionalSuffixes: [
  116. '-icons-movement',
  117. '-icons-content',
  118. '-icons-interactions',
  119. '-icons-moderation',
  120. '-icons-editing-core',
  121. '-icons-editing-styling',
  122. '-icons-editing-list',
  123. '-icons-editing-advanced',
  124. '-icons-media'
  125. ],
  126. theme: OO.ui.ApexTheme
  127. }
  128. };
  129. /**
  130. * Available text directions.
  131. *
  132. * List of text direction descriptions, each containing a `fileSuffix` property used for linking to
  133. * the correct stylesheet file.
  134. *
  135. * @static
  136. * @property {Object.<string,Object>}
  137. */
  138. OO.ui.Demo.static.directions = {
  139. ltr: { fileSuffix: '' },
  140. rtl: { fileSuffix: '.rtl' }
  141. };
  142. /**
  143. * Default page.
  144. *
  145. * Set by one of the page scripts in the `pages` directory.
  146. *
  147. * @static
  148. * @property {string|null}
  149. */
  150. OO.ui.Demo.static.defaultPage = null;
  151. /**
  152. * Default page.
  153. *
  154. * Set by one of the page scripts in the `pages` directory.
  155. *
  156. * @static
  157. * @property {string}
  158. */
  159. OO.ui.Demo.static.defaultTheme = 'mediawiki';
  160. /**
  161. * Default page.
  162. *
  163. * Set by one of the page scripts in the `pages` directory.
  164. *
  165. * @static
  166. * @property {string}
  167. */
  168. OO.ui.Demo.static.defaultDirection = 'ltr';
  169. /* Methods */
  170. /**
  171. * Load the demo page. Must be called after $element is attached.
  172. */
  173. OO.ui.Demo.prototype.initialize = function () {
  174. var demo = this,
  175. promises = this.stylesheetLinks.map( function ( el ) {
  176. return $( el ).data( 'load-promise' );
  177. } );
  178. // Helper function to get high resolution profiling data, where available.
  179. function now() {
  180. /*global performance */
  181. return ( typeof performance !== 'undefined' ) ? performance.now() :
  182. Date.now ? Date.now() : new Date().getTime();
  183. }
  184. $.when.apply( $, promises )
  185. .done( function () {
  186. var start, end;
  187. start = now();
  188. demo.constructor.static.pages[ demo.mode.page ]( demo );
  189. end = now();
  190. window.console.log( 'Took ' + ( end - start ) + ' ms to build demo page.' );
  191. } )
  192. .fail( function () {
  193. demo.$element.append( $( '<p>' ).text( 'Demo styles failed to load.' ) );
  194. } );
  195. };
  196. /**
  197. * Handle mode change events.
  198. *
  199. * Will load a new page.
  200. */
  201. OO.ui.Demo.prototype.onModeChange = function () {
  202. var page = this.pageMenu.getSelectedItem().getData(),
  203. theme = this.themeSelect.getSelectedItem().getData(),
  204. direction = this.directionSelect.getSelectedItem().getData();
  205. location.hash = '#' + [ page, theme, direction ].join( '-' );
  206. };
  207. /**
  208. * Get a list of mode factors.
  209. *
  210. * Factors are a mapping between symbolic names used in the URL hash and internal information used
  211. * to act on those symbolic names.
  212. *
  213. * Factor lists are in URL order: page, theme, direction. Page contains the symbolic
  214. * page name, others contain file suffixes.
  215. *
  216. * @return {Object[]} List of mode factors, keyed by symbolic name
  217. */
  218. OO.ui.Demo.prototype.getFactors = function () {
  219. var key,
  220. factors = [ {}, {}, {} ];
  221. for ( key in this.constructor.static.pages ) {
  222. factors[ 0 ][ key ] = key;
  223. }
  224. for ( key in this.constructor.static.themes ) {
  225. factors[ 1 ][ key ] = this.constructor.static.themes[ key ].fileSuffix;
  226. }
  227. for ( key in this.constructor.static.directions ) {
  228. factors[ 2 ][ key ] = this.constructor.static.directions[ key ].fileSuffix;
  229. }
  230. return factors;
  231. };
  232. /**
  233. * Get a list of default factors.
  234. *
  235. * Factor defaults are in URL order: page, theme, direction. Each contains a symbolic
  236. * factor name which should be used as a fallback when the URL hash is missing or invalid.
  237. *
  238. * @return {Object[]} List of default factors
  239. */
  240. OO.ui.Demo.prototype.getDefaultFactorValues = function () {
  241. return [
  242. this.constructor.static.defaultPage,
  243. this.constructor.static.defaultTheme,
  244. this.constructor.static.defaultDirection
  245. ];
  246. };
  247. /**
  248. * Parse the current URL hash into factor values.
  249. *
  250. * @return {string[]} Factor values in URL order: page, theme, direction
  251. */
  252. OO.ui.Demo.prototype.getCurrentFactorValues = function () {
  253. return location.hash.slice( 1 ).split( '-' );
  254. };
  255. /**
  256. * Get the current mode.
  257. *
  258. * Generated from parsed URL hash values.
  259. *
  260. * @return {Object} List of factor values keyed by factor name
  261. */
  262. OO.ui.Demo.prototype.getCurrentMode = function () {
  263. var factorValues = this.getCurrentFactorValues();
  264. return {
  265. page: factorValues[ 0 ],
  266. theme: factorValues[ 1 ],
  267. direction: factorValues[ 2 ]
  268. };
  269. };
  270. /**
  271. * Get link elements for the current mode.
  272. *
  273. * @return {HTMLElement[]} List of link elements
  274. */
  275. OO.ui.Demo.prototype.getStylesheetLinks = function () {
  276. var i, len, links, fragments,
  277. factors = this.getFactors(),
  278. theme = this.getCurrentFactorValues()[ 1 ],
  279. suffixes = this.constructor.static.themes[ theme ].additionalSuffixes || [],
  280. urls = [];
  281. // Translate modes to filename fragments
  282. fragments = this.getCurrentFactorValues().map( function ( val, index ) {
  283. return factors[ index ][ val ];
  284. } );
  285. // Theme styles
  286. urls.push( 'dist/oojs-ui' + fragments.slice( 1 ).join( '' ) + '.css' );
  287. for ( i = 0, len = suffixes.length; i < len; i++ ) {
  288. urls.push( 'dist/oojs-ui' + fragments[ 1 ] + suffixes[ i ] + '.css' );
  289. }
  290. // Demo styles
  291. urls.push( 'styles/demo' + fragments[ 2 ] + '.css' );
  292. // Add link tags
  293. links = urls.map( function ( url ) {
  294. var
  295. link = document.createElement( 'link' ),
  296. $link = $( link ),
  297. deferred = $.Deferred();
  298. $link.data( 'load-promise', deferred.promise() );
  299. $link.on( {
  300. load: deferred.resolve,
  301. error: deferred.reject
  302. } );
  303. link.rel = 'stylesheet';
  304. link.href = url;
  305. return link;
  306. } );
  307. return links;
  308. };
  309. /**
  310. * Normalize the URL hash.
  311. */
  312. OO.ui.Demo.prototype.normalizeHash = function () {
  313. var i, len, factorValues,
  314. modes = [],
  315. factors = this.getFactors(),
  316. defaults = this.getDefaultFactorValues();
  317. factorValues = this.getCurrentFactorValues();
  318. for ( i = 0, len = factors.length; i < len; i++ ) {
  319. modes[ i ] = factors[ i ][ factorValues[ i ] ] !== undefined ? factorValues[ i ] : defaults[ i ];
  320. }
  321. // Update hash
  322. location.hash = modes.join( '-' );
  323. };
  324. /**
  325. * Destroy demo.
  326. */
  327. OO.ui.Demo.prototype.destroy = function () {
  328. $( 'body' ).removeClass( 'oo-ui-ltr oo-ui-rtl' );
  329. $( this.stylesheetLinks ).remove();
  330. this.$element.remove();
  331. };
  332. /**
  333. * Build a console for interacting with an element.
  334. *
  335. * @param {OO.ui.Layout} item
  336. * @param {string} layout Variable name for layout
  337. * @param {string} widget Variable name for layout's field widget
  338. * @return {jQuery} Console interface element
  339. */
  340. OO.ui.Demo.prototype.buildConsole = function ( item, layout, widget ) {
  341. var $toggle, $log, $label, $input, $submit, $console, $form,
  342. console = window.console;
  343. function exec( str ) {
  344. var func, ret;
  345. /*jshint evil:true */
  346. if ( str.indexOf( 'return' ) !== 0 ) {
  347. str = 'return ' + str;
  348. }
  349. try {
  350. func = new Function( layout, widget, 'item', str );
  351. ret = { value: func( item, item.fieldWidget, item.fieldWidget ) };
  352. } catch ( error ) {
  353. ret = {
  354. value: undefined,
  355. error: error
  356. };
  357. }
  358. return ret;
  359. }
  360. function submit() {
  361. var val, result, logval;
  362. val = $input.val();
  363. $input.val( '' );
  364. $input[ 0 ].focus();
  365. result = exec( val );
  366. logval = String( result.value );
  367. if ( logval === '' ) {
  368. logval = '""';
  369. }
  370. $log.append(
  371. $( '<div>' )
  372. .addClass( 'oo-ui-demo-console-log-line oo-ui-demo-console-log-line-input' )
  373. .text( val ),
  374. $( '<div>' )
  375. .addClass( 'oo-ui-demo-console-log-line oo-ui-demo-console-log-line-return' )
  376. .text( logval || result.value )
  377. );
  378. if ( result.error ) {
  379. $log.append( $( '<div>' ).addClass( 'oo-ui-demo-console-log-line oo-ui-demo-console-log-line-error' ).text( result.error ) );
  380. }
  381. if ( console && console.log ) {
  382. console.log( '[demo]', result.value );
  383. if ( result.error ) {
  384. if ( console.error ) {
  385. console.error( '[demo]', String( result.error ), result.error );
  386. } else {
  387. console.log( '[demo] Error: ', result.error );
  388. }
  389. }
  390. }
  391. // Scrol to end
  392. $log.prop( 'scrollTop', $log.prop( 'scrollHeight' ) );
  393. }
  394. $toggle = $( '<span>' )
  395. .addClass( 'oo-ui-demo-console-toggle' )
  396. .attr( 'title', 'Toggle console' )
  397. .on( 'click', function ( e ) {
  398. e.preventDefault();
  399. $console.toggleClass( 'oo-ui-demo-console-collapsed oo-ui-demo-console-expanded' );
  400. if ( $input.is( ':visible' ) ) {
  401. $input[ 0 ].focus();
  402. if ( console && console.log ) {
  403. window[ layout ] = item;
  404. window[ widget ] = item.fieldWidget;
  405. console.log( '[demo]', 'Globals ' + layout + ', ' + widget + ' have been set' );
  406. console.log( '[demo]', item );
  407. }
  408. }
  409. } );
  410. $log = $( '<div>' )
  411. .addClass( 'oo-ui-demo-console-log' );
  412. $label = $( '<label>' )
  413. .addClass( 'oo-ui-demo-console-label' );
  414. $input = $( '<input>' )
  415. .addClass( 'oo-ui-demo-console-input' )
  416. .prop( 'placeholder', '... (predefined: ' + layout + ', ' + widget + ')' );
  417. $submit = $( '<div>' )
  418. .addClass( 'oo-ui-demo-console-submit' )
  419. .text( '↵' )
  420. .on( 'click', submit );
  421. $form = $( '<form>' ).on( 'submit', function ( e ) {
  422. e.preventDefault();
  423. submit();
  424. } );
  425. $console = $( '<div>' )
  426. .addClass( 'oo-ui-demo-console oo-ui-demo-console-collapsed' )
  427. .append(
  428. $toggle,
  429. $log,
  430. $form.append(
  431. $label.append(
  432. $input
  433. ),
  434. $submit
  435. )
  436. );
  437. return $console;
  438. };