mediawiki-extensions-Visual.../modules/ve/ui/layouts/ve.ui.GridLayout.js
Moriel Schottlender c4c9923c91 Dir fix for iframes and widgets
This fix adds a directionality property to the frame objects so directions
can be inherited and manipulated inside the frame <body> tags.
There are also several corrections to flipping positioning of panels
in the GridLayout and of the icons in fieldsets and labeled elements
so they appear properly (right instead of left).

I've added a 've-rtl' / 've-ltr' class to frame content divs to serve as
selectors for rtl fixes and general language fixes. Most CSS corrections
would likely be fixed when CSSJanus works in iframes, but the selectors
would still be useful.

This sets the stage for directionality inheritance inside iframes,
and fixes most of the problem with the Page Settings window in RTL wikis.
It also fixes all the labels with icons across VE interface.

Bug: 49613
Change-Id: I418e669b0999552167683352acb365a4249ab9cc
2013-07-02 20:20:43 +00:00

171 lines
3.6 KiB
JavaScript

/*!
* VisualEditor UserInterface GridLayout class.
*
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* Grid layout.
*
* @class
* @extends ve.ui.Layout
*
* @constructor
* @param {ve.ui.PanelLayout[]} panels Panels in the grid
* @param {Object} [config] Config options
* @cfg {number[]} [widths] Widths of columns as ratios
* @cfg {number[]} [heights] Heights of columns as ratios
*/
ve.ui.GridLayout = function VeUiGridLayout( panels, config ) {
var i, len, widths;
// Config initialization
config = config || {};
// Parent constructor
ve.ui.Layout.call( this, config );
// Properties
this.panels = [];
this.widths = [];
this.heights = [];
// Initialization
this.$.addClass( 've-ui-gridLayout' );
for ( i = 0, len = panels.length; i < len; i++ ) {
this.panels.push( panels[i] );
this.$.append( panels[i].$ );
}
if ( config.widths || config.heights ) {
this.layout( config.widths || [1], config.heights || [1] );
} else {
// Arrange in columns by default
widths = [];
for ( i = 0, len = this.panels.length; i < len; i++ ) {
widths[i] = 1;
}
this.layout( widths, [1] );
}
};
/* Inheritance */
ve.inheritClass( ve.ui.GridLayout, ve.ui.Layout );
/* Events */
/**
* @event layout
*/
/**
* @event update
*/
/* Static Properties */
ve.ui.GridLayout.static.tagName = 'div';
/* Methods */
/**
* Set grid dimensions.
*
* @method
* @param {number[]} widths Widths of columns as ratios
* @param {number[]} heights Heights of rows as ratios
* @emits layout
* @throws {Error} If grid is not large enough to fit all panels
*/
ve.ui.GridLayout.prototype.layout = function ( widths, heights ) {
var x, y,
xd = 0,
yd = 0,
cols = widths.length,
rows = heights.length;
// Verify grid is big enough to fit panels
if ( cols * rows < this.panels.length ) {
throw new Error( 'Grid is not large enough to fit ' + this.panels.length + 'panels' );
}
// Sum up denominators
for ( x = 0; x < cols; x++ ) {
xd += widths[x];
}
for ( y = 0; y < rows; y++ ) {
yd += heights[y];
}
// Store factors
this.widths = [];
this.heights = [];
for ( x = 0; x < cols; x++ ) {
this.widths[x] = widths[x] / xd;
}
for ( y = 0; y < rows; y++ ) {
this.heights[y] = heights[y] / yd;
}
// Synchronize view
this.update();
this.emit( 'layout' );
};
/**
* Update panel positions and sizes.
*
* @method
* @emits update
*/
ve.ui.GridLayout.prototype.update = function () {
var x, y, panel,
i = 0,
left = 0,
top = 0,
dimensions,
width = 0,
height = 0,
cols = this.widths.length,
rows = this.heights.length;
for ( y = 0; y < rows; y++ ) {
for ( x = 0; x < cols; x++ ) {
panel = this.panels[i];
width = this.widths[x];
height = this.heights[y];
dimensions = {
'width': Math.round( width * 100 ) + '%',
'height': Math.round( height * 100 ) + '%',
'top': Math.round( top * 100 ) + '%'
};
// If RTL, reverse:
if ( this.$$.frame.dir === 'rtl' ) {
dimensions.right = Math.round( left * 100 ) + '%';
} else {
dimensions.left = Math.round( left * 100 ) + '%';
}
panel.$.css( dimensions );
i++;
left += width;
}
top += height;
left = 0;
}
this.emit( 'update' );
};
/**
* Get a panel at a given position.
*
* The x and y position is affected by the current grid layout.
*
* @method
* @param {number} x Horizontal position
* @param {number} y Vertical position
* @returns {ve.ui.PanelLayout} The panel at the given postion
*/
ve.ui.GridLayout.prototype.getPanel = function ( x, y ) {
return this.panels[( x * this.widths.length ) + y];
};