Introduction à JxLib

Jon Bomgardner

Traducteur

vermine

Jon Bomgardner contribue au projet jxlib.org. Après s'être abonné récemment aux envois d'e-mails des développeurs de MooTools, et après avoir partagé son expérience pour la mise à jour de JxLib pour la version 1.4.2 de MooTools, Aaron Newton (membre de l'équipe MooTools) lui a demandé d'expliquer plus en détail son travail sur JxLib, un framework JavaScript d'interfaçage utilisateur conçu avec MooTools.
Commentez ♪

- Titre : Introduction à JxLib

- Auteur : Jon Bomgardner

- Traducteur : vermine

- Parution : 16 janvier 2012

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2012 Jon Bomgardner. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- 1. Définition de JxLib

- 2. Quelques exemples

- 2-A. Exemple 1 : barre d'outils déroulante

- 2-B. Exemple 2 : Jx.Form et champs de formulaire

- 2-C. Exemple 3 : les nouvelles classes Jx.Container et Jx.LayoutManager

- 3. Résultats du travail sur la compatibilité avec le Core 1.4.2

- 4. Plus d'information

- 5. Remerciements

1 - Définition de JxLib

JxLib est un framework JavaScript d'interfaçage utilisateur conçu avec MooTools. Il permet aux développeurs et aux graphistes de construire rapidement des interfaces utilisateur pour leurs applications. JxLib est basé sur du HTML valide et tâche d'être entièrement conforme au niveau des CSS.

Toute cette flexibilité est possible, dans sa majorité, grâce à l'utilisation de MooTools. La bibliothèque est fortement orientée objets et comporte un nombre important de classes héritant d'une base simple. Si vous savez comment utiliser le système de classe MooTools, vous allez vous en sortir facilement avec JxLib. En plus d'être basée sur du HTML et des CSS qui fournissent une extraordinaire flexibilité, l'architecture de la bibliothèque est conçue avec un système de plugins qui permet d'ajouter de nouvelles fonctionnalités à chaque composant, selon le choix du développeur.

2 - Quelques exemples

Je souhaite montrer quelques exemples simples de ce que vous pouvez faire avec JxLib. Il y a une tonne de fonctionnalités possibles et pour avoir des exemples plus complets, vous pouvez regarder sur le site jxlib.org. Voici trois exemples qui vous donneront un petit aperçu de ces fonctionnalités.

2-A - Exemple 1 : barre d'outils déroulante

Cet exemple montre une barre d'outils en cascade.

Ressources :
jxlib.standalone.uncompressed.js
locale.js
jxtheme.uncompressed.css
tests.css

Javascript :

Code JavaScript de l'exemple 1

function menuToolbar() {
/* a set of grouped menu items */
var justifyLeft = new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'left'},
toggle: true,
imageClass: 'format-justify-left',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'
});
var justifyCenter = new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'center'},
toggle: true,
imageClass: 'format-justify-center',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'
});
var justifyRight = new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'right'},
toggle: true,
imageClass: 'format-justify-right',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'
});
var justifyFill = new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'fill'},
toggle: true,
imageClass: 'format-justify-fill',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'
});
new Jx.ButtonSet().add(
justifyLeft, justifyCenter, justifyRight, justifyFill
);

/* menus in toolbars work pretty much the same way as menu
* buttons
*/
new Jx.Toolbar({parent: 'toolbarMenu'}).add(
new Jx.Menu({label: {set:'Examples',key:'menu',value:'file'}}).add([
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'new'},
imageClass: 'file-new',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'}),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'open'},
imageClass: 'file-open',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'}),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'save'},
imageClass: 'file-save',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'}),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'saveAs'},
imageClass: 'file-save-as',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'}),
new Jx.Menu.Separator(),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'print'},
imageClass: 'file-print',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'}),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'printPreview'},
imageClass: 'file-print-preview',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'}),
new Jx.Menu.Separator(),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'properties'},
imageClass: 'file-properties',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'})]
),
new Jx.Menu({label: {set:'Examples',key:'menu',value:'edit'}}).add([
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'undo'},
imageClass: 'edit-undo',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png',
enabled: false}),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'redo'},
imageClass: 'edit-redo',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png',
enabled: false}),
new Jx.Menu.Separator(),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'cut'},
imageClass: 'edit-cut',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'}),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'copy'},
imageClass: 'edit-copy',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'}),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'paste'},
imageClass: 'edit-paste',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'})]
),
new Jx.Menu({label: {set:'Examples',key:'menu',value:'format'}}).add([
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'intendMore'},
toggle: true,
imageClass: 'format-indent-more',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png',}),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'intendLess'},
toggle: true,
imageClass: 'format-indent-less',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'}),
new Jx.Menu.SubMenu({label: {set:'Examples',key:'menu',value:'font'}}).add([
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'bold'},
toggle: true,
imageClass: 'format-text-bold',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'}),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'italic'},
toggle: true,
imageClass: 'format-text-italic',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'}),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'strikethrough'},
toggle: true,
imageClass: 'format-text-strikethrough',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'}),
new Jx.Menu.Item({
label: {set:'Examples',key:'menu',value:'underline'},
toggle: true,
imageClass: 'format-text-underline',
image: 'http://jxlib.org/reference/3.1.1/examples/images/file-edit-menu.png'})]
),
new Jx.Menu.SubMenu({label:{set:'Examples',key:'menu',value:'align'}}).add([
justifyLeft,
justifyCenter,
justifyRight,
justifyFill]
)]
)
);
}

menuToolbar();

HTML :

Code HTML de l'exemple 1

<div id="toolbarMenu" class="toolbarBox"></div>

2-B - Exemple 2 : Jx.Form et champs de formulaire

Cet exemple montre une grande partie des champs que vous pouvez créer.

Ressources :
jxlib.standalone.uncompressed.js
locale.js
jxtheme.uncompressed.css
tests.css

Javascript :

Code JavaScript de l'exemple 2

var form;
function drawBasicForm() {
form = new Jx.Form({
name: 'testForm',
formClass: 'jxFormInline'
}).addTo('formBasic');

// First Fieldset

var fieldSet1 = new Jx.Fieldset({
legend: 'Inline-Block Form',
id: 'FieldSet1',
fieldsetClass: 'jxFormInlineblock'
}).addTo(form);

new Jx.Field.Text({
id: 'Text11',
name: 'Text11',
label: 'Text One',
value: 'Initial Value',
tag: 'a tag',
required: true
}).addTo(fieldSet1);

var c1 = new Jx.Field.Combo({
id: 'Select11',
name: 'Select11',
label: 'Combo Test',
readonly: true,
tag: 'another tag',
items: [
{image: 'http://jxlib.org/reference/3.1.1/examples/images/swatches.png', imageClass: 'comboRed', label: 'red'},
{image: 'http://jxlib.org/reference/3.1.1/examples/images/swatches.png', imageClass: 'comboMagenta', label: 'magenta'},
{image: 'http://jxlib.org/reference/3.1.1/examples/images/swatches.png', imageClass: 'comboBlue'},
{label: 'cyan'},
{image: 'http://jxlib.org/reference/3.1.1/examples/images/swatches.png', imageClass: 'comboGreen'},
{image: 'http://jxlib.org/reference/3.1.1/examples/images/swatches.png', imageClass: 'comboYellow'}
]
}).addTo(fieldSet1);

new Jx.Field.Select({
id: 'Select12',
name: 'Select12',
label: 'Select One',
tag: 'another tag',
comboOpts: [{
value: 'opt11',
text: 'Option #1',
selected: false
},{
value: 'opt12',
text: 'Option #2',
selected: true
},{
value: 'opt13',
text: 'Option #3',
selected: false
}]
}).addTo(fieldSet1);

new Jx.Field.Select({
id: 'Select13',
name: 'Select13',
label: 'Select One',
tag: 'another tag',
size: 5,
multiple: true,
comboOpts: [{
value: 'opt121',
text: 'Option #1',
selected: false
},{
value: 'opt122',
text: 'Option #2',
selected: true
},{
value: 'opt123',
text: 'Option #3',
selected: true
}]
}).addTo(fieldSet1);

new Jx.Field.Textarea({
id: 'TextArea11',
name: 'TextArea11',
label: 'TextArea One',
rows: 6,
columns: 40,
tag: 'textarea tag'
}).addTo(fieldSet1);

var radioSet = new Jx.Fieldset({
legend: 'Radio Group',
fieldsetClass: 'jxInputGroup',
template: '<fieldset class="jxFieldset"><legend><span class="jxFieldsetLegend"></span></legend></fieldset>'
}).addTo(fieldSet1);

new Jx.Field.Radio({
id: 'radio11',
name: 'InputGroup1',
value: 'radio11',
label: 'Radio 1',
labelSeparator: ''
}).addTo(radioSet);

new Jx.Field.Radio({
id: 'radio12',
name: 'InputGroup1',
value: 'radio12',
label: 'Radio 2',
checked: true,
labelSeparator: ''
}).addTo(radioSet);

new Jx.Field.Button({
buttonClass: Jx.Button.Color,
buttonOptions:{label: 'Foreground', color: '#f0f', alpha: 50},
label: 'Choose a Color'
}).addTo(fieldSet1);

new Jx.Field.Color({
label: 'Choose a Color',
buttonOptions: {
color: '#f00'
}
}).addTo(fieldSet1);

new Jx.Field.OptionGroup({
label: 'Select One or More of these',
columns: 3,
asArray: true,
name: 'test',
items: [
{
label: 'test item 1',
value: 'test1'
},{
label: 'test item 2',
value: 'test2'
},{
label: 'test item 3',
value: 'test3'
},{
label: 'test item 4',
value: 'test4'
},{
label: 'test item 5',
value: 'test5'
},{
label: 'test item 6',
value: 'test6'
}
]
}).addTo(fieldSet1);

new Jx.Field.NumberSpinner({
label: 'Pick a positive number',
allowNegative: false,
name: 'spinnerfield'
}).addTo(fieldSet1);

//this is the new Jx.Field.ComboBox
var data = [];
for (i = 1; i < 30; i++) {
data.push({id: i, label: 'test' + i});
}
var parser = new Jx.Store.Parser.JSON();
var paginate = new Jx.Store.Strategy.Paginate({
startingItemsPerPage: 10
});

var store = new Jx.Store({
fields: [{
name: 'label',
type: 'alphanumeric'
}, {
name: 'id',
type: 'numeric'
}],
protocol: new Jx.Store.Protocol.Local(data, {
parser: parser
}),
strategies: [paginate],
record: Jx.Record,
recordOptions: {
primaryKey: 'id'
}
});

store.load();

new Jx.Field.ComboBox({
label: 'Pick something',
store: store,
displayField: 'label',
valueField: 'id',
emptyMessage: '',
name: 'comboBox'
}).addTo(fieldSet1);

new Jx.Field.Date({
label: 'Start Date',
value: '05/05/1984',
format: '%m/%d/%Y',
name: 'startDate'
}).addTo(fieldSet1);

//The new Jx.Field.TreeCombo
var treeData = [{
label: 'test1',
children: [
{
label: 'test1.1',
children: [
{ label: 'test1.1.1'},
{ label: 'test1.1.2'}
]
},
{
label: 'test1.2',
children: [
{label: 'test1.2.1'},
{label: 'test1.2.2'}
]
}
]
},{
label: 'test2'
}]
new Jx.Field.TreeCombo({
protocol: new Jx.Store.Protocol.Local(treeData,{
parser: parser
}),
name: 'treeCombo',
label: 'Choose from the tree'
}).addTo(fieldSet1);

// Second Fieldset

var fieldSet2 = new Jx.Fieldset({
legend: 'Inline Form',
id: 'FieldSet2',
fieldsetClass: 'jxFormInline'
}).addTo(form);

new Jx.Field.Text({
id: 'Text21',
name: 'Text21',
label: 'Text One',
value: 'Initial Value',
tag: 'a tag'
}).addTo(fieldSet2);

new Jx.Field.Select({
id: 'Select21',
name: 'Select21',
label: 'Select One',
comboOpts: [{
value: 'opt21',
text: 'Option #1',
selected: false
},{
value: 'opt22',
text: 'Option #2',
selected: true
},{
value: 'opt23',
text: 'Option #3',
selected: false
}]
}).addTo(fieldSet2);

new Jx.Field.Text({
id: 'Text22',
name: 'Text22',
label: 'Text Two',
value: 'Initial Value',
tag: 'a tag'
}).addTo(fieldSet2);

var checkSet = new Jx.Fieldset({
legend: 'Check Group',
fieldsetClass: 'jxInputGroup',
template: '<fieldset class="jxFieldset"><legend><span class="jxFieldsetLegend"></span></legend></fieldset>'
}).addTo(fieldSet2);

new Jx.Field.Checkbox({
id: 'check21',
name: 'check21',
value: 'check21',
label: 'Check 1',
checked: true,
labelSeparator: ''
}).addTo(checkSet);

new Jx.Field.Checkbox({
id: 'check22',
name: 'check22',
value: 'check22',
label: 'check 2',
checked: false,
labelSeparator: ''
}).addTo(checkSet);

new Jx.Field.Button({
buttonOptions:{label: 'Apply'}
}).addTo(fieldSet2);

new Jx.Field.Button({
buttonOptions:{label: 'Cancel'}
}).addTo(fieldSet2);

// Third Fieldset

var fieldSet3 = new Jx.Fieldset({
// no legend in this one
id: 'FieldSet3',
fieldsetClass: 'jxFormBlock'
}).addTo(form);

new Jx.Field.Text({
id: 'Text31',
name: 'Text31',
label: 'Text One',
value: 'Initial Value',
tag: 'a tag'
}).addTo(fieldSet3);

new Jx.Field.Select({
id: 'Select31',
name: 'Select31',
label: 'Select One',
tag: 'another tag',
comboOpts: [{
value: 'opt31',
text: 'Option #1',
selected: false
},{
value: 'opt32',
text: 'Option #2',
selected: true
},{
value: 'opt33',
text: 'Option #3',
selected: false
}]
}).addTo(fieldSet3);

new Jx.Field.Checkbox({
id: 'check31',
name: 'check31',
value: 'check31',
label: 'Check 1',
labelSeparator: ''
}).addTo(fieldSet3);

new Jx.Field.Checkbox({
id: 'check32',
name: 'check32',
value: 'check32',
label: 'Check 2',
labelSeparator: ''
}).addTo(fieldSet3);

new Jx.Field.Textarea({
id: 'TextArea31',
name: 'TextArea31',
label: 'TextArea One',
rows: 6,
columns: 40
}).addTo(fieldSet3);

new Jx.Field.Button({
buttonOptions:{
label: 'Go',
onClick: function() {
console.log(form.getValues());
}
},
defaultAction: true
}).addTo(form);
}

drawBasicForm();

HTML :

Code HTML de l'exemple 2

<div id="formBasic" class="formBox"></div>

2-C - Exemple 3 : les nouvelles classes Jx.Container et Jx.LayoutManager

Celui-ci montre des nouveautés de JxLib 3.1.1. Il crée l'entièreté de la fenêtre en utilisant un simple objet JavaScript.

Ressources :
jxlib.standalone.uncompressed.js
locale.js
jxtheme.uncompressed.css

Javascript :

Code JavaScript de l'exemple 3

function drawContainerLayout() {

var data = [];
for (i = 1; i < 30; i++) {
data.push({id: i, label: 'test' + i});
}
var parser = new Jx.Store.Parser.JSON();
var paginate = new Jx.Store.Strategy.Paginate({
startingItemsPerPage: 10
});

var store = new Jx.Store({
fields: [{
name: 'label',
type: 'alphanumeric'
}, {
name: 'id',
type: 'numeric'
}],
protocol: new Jx.Store.Protocol.Local(data, {
parser: parser
}),
strategies: [paginate],
record: Jx.Record,
recordOptions: {
primaryKey: 'id'
}
});

store.load();

new Jx.Container({
parent: 'containerBox',
layoutManager: 'anchored',
topLevel: true,
items: [{
//Top
id: 'layoutOffsetElement1' ,
layoutOpts: {
height: 50
}
},{
//left
'class': Jx.Panel,
options: {
image: 'http://jxlib.org/reference/3.1.1/examples/images/page_white_world.png',
label: 'Just a Panel',
content: 'layoutOffsetElement2',
loadOnDemand: true,   // this option is ignored in panels
menu: true,
height: 200,
id: 'leftPanel'
},
layoutOpts: {
top: 50,
bottom: 50,
width: 200
}
},{
//center panel
'class': Jx.TabBox,
options: {
id: 'centerTabBox',
items: [{
'class': 'tab',
options: {
image: 'http://jxlib.org/reference/3.1.1/examples/images/star.png',
content: 'starContent'
}
},{
'class': 'tab',
options: {
label: 'Embedded Panel',
items: [{
'class': 'panel',
options: {
label: 'Panel in a Tab',
collapse: false,
content: '<p>This is a panel embedded in a tab.</p>'
}
}]
}
},{
'class': 'tab',
options: {
label: 'A Form in a tab',
image: 'http://jxlib.org/reference/3.1.1/examples/images/page_white_world.png',
items: [{
'class': 'form',
options: {
name: 'testForm',
formClass: 'jxFormInlineblock',
items: ['layoutOffsetElement4',
new Element('p', {
html: 'This is a paragraph that was added to the form.'
}),{
'class': 'text',
options: {
label: 'First example textbox',
name: 'textbox-1',
id: 'textbox-1'
}
},{
'class': 'fieldset',
options: {
legend: 'Fieldset #1',
items: [
{
'class': 'text',
options: {
label: 'first child in frameset',
id: 'frame-text-1',
name: 'frame-text-1',
required: true
}
},{
'class': 'checkbox',
options: {
label: 'a checkbox',
id: 'checkbox-1',
name: 'checkbox-1'
}
}
]
}
},{
'class': 'editor',
options: {
name: 'description',
label: 'Description',
id: 'description',
required: true,
value: '',
editorOptions: {
editorCssFile: 'css/editor.css',
buttons: [
['bold','italic','underline','strikethrough','separator','alignment',
'separator','orderedlist','unorderedlist','indent','outdent','separator','undo','redo'],
[{ name: 'customStyles',
options: {
styles: ['small','large','hide','quiet','loud','highlight',
'added','removed','first','last','top','bottom']
}
},'block', 'separator', 'link','unlink', 'image','separator', 'toggle']
]
}
}
}
],
plugins: [{
name: 'validator',
options: {
fields: {
'textbox-1': {
validators: ['minLength:5', 'maxLength:10']
},
'frame-text-1': {
//Need to add the empty validators array which will force it to
//also pick up the required option in the field itself.
validators: []
},
'description': {
validators: []
}
}
}
},{
name: 'notifier',
options: {
notifierType: 'inline'
}
}]
}
}]
}
},{
'class': 'tab',
options: {
label: 'A Tab using Split Layout Manager',
image: 'http://jxlib.org/reference/3.1.1/examples/images/page_white_code.png',
items: [{
'class': 'container',
options: {
layoutManager:  {
name: 'split',
//This just holds the Jx.Splitter options
options: {
containerOptions: [{
width: 400
},{
width: null
}]
}
},
items: [{
'class': 'panel',
options: {
label: 'A Panel',
toolbars: [new Jx.Toolbar().add(
new Jx.Button({ label:'b1' }),
new Jx.Button({ label:'b2' })
)]
},
layoutOpts: {
split: 0
}
},{
'class': 'container',
options: {
layoutManager:  {
name: 'split',
//This just holds the Jx.Splitter options
options: {
layout: 'vertical',
containerOptions: [{height: 300},{ height: null}]
}
},
items: [{
'class':'panel',
options: {
label: 'Top-Right Panel'
},
layoutOpts: {
split: 0
}
},{
'class':'panel',
options: {
label: 'Bottom-Right panel'
},
layoutOpts: {
split: 1
}
}]
},
layoutOpts: {
split: 1
}
}]
}
}]
}
},{
'class': 'tab',
options: {
label: 'Center Panel',
image: 'http://jxlib.org/reference/3.1.1/examples/images/page_white_code.png',
content: 'layoutOffsetElement3'
}
},{
'class': 'tab',
options: {
label: 'Closeable Tab',
close: true,
contentURL: 'tab_content.html'
}
}]
},
//id: 'layoutOffsetElement3',
layoutOpts: {
top: 50,
bottom: 50,
right: 200,
left: 200
}
},{
'class': Jx.Panel,
options: {
image: 'http://jxlib.org/reference/3.1.1/examples/images/page_white_world.png',
label: 'ListView in a Panel',
loadOnDemand: true,   // this option is ignored in panels
menu: true,
//height: 200,
id: 'rightPanel',
layoutManager: 'fill',
items: [{
'class': 'listView',
options: {
id: 'listViewBox',
plugins: [{
name: 'Fill',
options: {
itemTemplate: "<li class='jxListItemContainer'><a class='jxListItem' href='javascript:void(0);'>{item}</a></li>",
template: '{label}',
emptyMessage: "<p>No items.</p>",
store: store
}
}]

}
}]
},
layoutOpts: {
left: null,
top: 50,
bottom: 50,
width: 200
}
},{
id: 'layoutOffsetElement5',
layoutOpts: {
top: null,
height: 50
}
}]
});

};

drawContainerLayout();

HTML :

Code HTML de l'exemple 3

<div id="containerBox"></div>

<div id="layoutOffsetElement1">
<p>This element has variable width and a fixed height, attached to the top of the container.</p>
</div>
<div id="layoutOffsetElement2">
<p>This element has fixed width, variable height, and is attached to the left of the container.</p>
</div>
<div id="layoutOffsetElement3">
<p>This element has variable width and height with fixed left, top, right and bottom offsets.</p>
</div>
<div id="layoutOffsetElement4">
<p>This element was pulled from the HTML and added to this form.</p>
</div>
<div id="layoutOffsetElement5">
<p>This element has variable width and fixed height, attached to the bottom of the container.</p>
</div>
<div id="starContent"><p>This tab just has an image.</p></div>

CSS :

Code CSS de l'exemple 3

.jxContainerContent {
background: #fff;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
border-right: 1px solid #f0f0f0;
border-bottom: 1px solid #f0f0f0;
margin: 2px;
}

.jxContainerContent .jxContainerContent {
margin: 0;
border: none;
}

#containerBox {
position: relative;
width: 1000px;
height: 500px;
margin: 0 auto;
border: 1px solid #ccc;
}

3 - Résultats du travail sur la compatibilité avec le Core 1.4.2

Je suis content de conclure que la conversion vers le Core 1.4.2 s'est avérée relativement facile. Ce qui m'a donné le plus grand mal de tête, c'est lorsque j'essayais avant tout d'obtenir la compatibilité avec le Core 1.3.2 - c'était un énorme travail. Nous avons utilisé la plupart des méthodes globales $ ($defined, $H et $A étant les plus grosses) et elles ont été un peu redéfinies librement. Je n'ai vraiment pas voulu employer la couche de compatibilité que les gens de MooTools ont chacun aimablement fournie parce que le téléchargement en était bien trop gros. Cette transformation a pris beaucoup de temps. Ce faisant, j'ai cependant appris quelques petites choses très intéressantes.

Premièrement, c'est mieux de remplacer $defined() avec une vérification pour les undefined et les null. Par exemple :

if ($defined(some_variable)) {

devient :

if (some_variable !== undefined && some_variable !== null) {

Je me rends compte que les documentations sur la conversion déclarent que vérifier les undefined devrait être suffisant, mais quand j'ai essayé cela, j'ai d'abord obtenu beaucoup d'erreurs étranges. Ce changement les a fixées.

L'autre chose que j'ai découverte est que Object.each et Object.keys ne sont pas vraiment utiles lorsque l'objet que vous utilisez est dans le même prototypage que leur classe. Par exemple, nous avons ce code dans JxLib 2.0 :

processElements: function(template, classes) {
var keys = classes.getValues();
elements = this.processTemplate(template, keys);
classes.each(function(value, key) {
if (key != 'elements' && elements.get(value)) {
this[key] = elements.get(value);
}
}, this);
return elements;
}

Il semble que ces deux fonctions utilisent hasOwnProperty() qui ne donnait aucune itération de la boucle ci-dessus parce que la variable des classes était en fait this.classes, qui se retrouve sur le prototype de la classe. En convertissant le Core 1.3.2 et ensuite le Core 1.4.2, nous avons dû employer ceci :

processElements: function(template, classes) {
var keys = [],
values = [];
for (var key in classes){
if (key !== undefined) {
values.push(classes[key]);
keys.push(key);
}
}
elements = this.processTemplate(template, values);
keys.each(function(key){
if (key != 'elements' && elements[classes[key]] !== undefined && elements[classes[key]] !== null) {
this[key] =  elements[classes[key]];
}
},this);
return elements;
}

Une fois que cela était corrigé, et nous avions alors la pleine compatibilité avec le Core 1.3.2, la transformation jusqu'au Core 1.4.x était assez indolore. Pour plus d'information sur ce que j'ai appris pendant la conversion (tout ne concerne pas MooTools ni même le JavaScript) rendez-vous sur mon blog.

4 - Plus d'information

Vous pouvez obtenir plus d'information sur JxLib aux endroits suivants :

- Site Web JxLib ;

- JxLib github ;

- JxLib Google Group ;

- JxLib sur Lighthouse ;

- Blog sur comment débuter avec JxLib.

Si vous avez des questions ou des commentaires, n'hésitez pas à les faire sur le Google group (dont le lien est ci-dessus). De même, si vous avez apprécié cette présentation, vous pouvez apporter votre aide au projet pour améliorer JxLib. Nous avons plusieurs idées pour le futur et des mains supplémentaires sont les bienvenues.

5 - Remerciements

Je tiens à remercier chaleureusement Jon Bomgardner de m'avoir autorisé à traduire son article.
Je remercie également jacques_jean pour sa relecture et ses conseils avisés.