概述
WijmoJS 的客户通过技术社区(GCDN)联系我们,表示他们已准备好从Wijmo 3(基于JQuery的前端开发工具包)迁移到当前版本的WijmoJS,但他们需要一个Ribbon控件,不基于任何 Javascript 库。
最初,我们考虑创建一个新控件并将其添加到WijmoJS的nav导航模块,以及TreeView(树状图控件)和TabPanel(选项卡控件)中。 但经过一些研究,我们意识到使用TabPanel实现 Ribbon 功能区非常简单,因此不需要任何新的控件。
Ribbon(一种电脑用户界面)
Ribbon即功能区,是新的 Microsoft Office Fluent 用户界面 (UI) 的一部分。 在仪表板设计器中,功能区包含一些用于创建、编辑和导出仪表板及其元素的上下文工具。它是一个收藏了命令按钮和图示的面板。
它的本质把工具栏的命令,用一组组的"标签"进行组织分类,每一组包含了相关的命令。每一个应用程序都有一个不同的标签组,展示了程序所提供的功能。在每个标签里,各种的相关的选项被组在一起。
Wijmo 3的wijribbon控件
Wijmo 3(wijribbon)附带的功能区控件如下所示:
与大多数功能区控件一样,它提供了一个选项卡式UI,其中每个选项卡都包含命令组。 命令通常是按钮或下拉菜单,但可以使用任何UI控件。
WijmoJS的JavaScript功能区控件
为了在WijmoJS中实现类似的功能,我们使用了TabPanel 控件和一些CSS。
这就是 WijmoJS 功能区控件的样子:
其默认外观类似于现代UI和Material Design,但当然可以使用CSS轻松且广泛地自定义。 由于这个新功能区使用WijmoJS,它没有依赖任何前端组件库,完美适用于移动和桌面设备。
WijmoJS Ribbon控件架构
正如我们所提到的,WijmoJS 功能区控件实际上是一个TabPanel 扩展。 选项卡包含组元素。每个组元素都有一个托管命令控件的内容区域(wj-content)和一个显示组名称的头文件(wj-header)。
每个组内容(wj-content)元素包含具有列(wj-column)和/或行(wj-rows)的元素。 这允许设计者更加灵活地控制并定义组内容的布局。行和列元素托管命令控件,可以是常规HTML元素或其他WijmoJS控件类型。
这是用于定义功能区演示中第一个组的标记。请注意层次结构,其中每个选项卡包含两个元素(选项卡标题和内容),选项卡内容元素又包含组元素列表,这些组元素也有两个子组(组头和内容)。 组内容元素又包含用于布局各个控件的行和列元素的集合:
<div id="ribbon">
<!-- Format tab -->
<div>
<div>Format</div>
<div>
<div class="wj-group">
<!-- Group content (Action) -->
<div class="wj-content">
<div class="wj-column">
<button id="save" class="wj-btn wj-btn-large">
<i class="material-icons">save</i>
<br/>
Save
</button>
</div>
<div class="wj-column">
<div class="wj-row">
<button id="undo" class="wj-btn" aria-label="Undo">
<i class="material-icons">undo</i>
</button>
… more buttons in the row …
</div>
<div class="wj-row">
<button id="cut" class="wj-btn" aria-label="Cut">
<i class="material-icons">✂</i>
</button>
… more buttons in the row …
</div>
</div>
</div>
<!-- Group header -->
<div class="wj-header">
Actions
</div>
</div>
我们选择使用HTML标记指定功能区内容,因为它提供了灵活且熟悉的示例。此外,可以使用JSON文件或其他一些数据结构中提供的代码和数据填充功能区。
其他功能区行为
除了标准的TabPanel功能外,我们还添加了一些代码,用于在用户双击选项卡标题区域(如MS色带)时切换功能区内容,并在用户单击选项卡时显示选项卡区域:
// create ribbon
var ribbon = new wijmo.nav.TabPanel('#ribbon');
// toggle ribbon content visibility on double-clicks, restore on clicks
var headers = document.querySelector('.wj-tabheaders');
headers.addEventListener('dblclick', function (e) {
if (!wijmo.hasClass(e.target, 'wj-tabheader')) {
wijmo.toggleClass(ribbon.hostElement, 'hide-content');
}
});
headers.addEventListener('click', function (e) {
if (wijmo.hasClass(e.target, 'wj-tabheader')) {
wijmo.toggleClass(ribbon.hostElement, 'hide-content', false);
}
});
我们还定义了一个addTooltips函数,它扫描功能区(或任何其他 WijmoJS 控件)中的所有元素,并根据所包含控件的aria-label属性添加工具提示。这样做增强了应用程序的可访问性,并且无需保留冗余标签信息(如aria-label和title属性):
// add tooltips based on the element's aria-label attribute
function addTooltips(ctl) {
var tt = new wijmo.Tooltip(),
els = ctl.hostElement.querySelectorAll('[aria-label]');
for (var i = 0; i < els.length; i++) {
tt.setTooltip(els[i], els[i].getAttribute('aria-label'));
}
}
我们还定义了一个addTooltips函数,它扫描功能区(或任何其他 WijmoJS 控件)中的所有元素,并根据所包含控件的aria-label属性添加工具提示。这样做增强了应用程序的可访问性,并且无需保留冗余标签信息(如aria-label和title属性):
// add tooltips based on the element's aria-label attribute
function addTooltips(ctl) {
var tt = new wijmo.Tooltip(),
els = ctl.hostElement.querySelectorAll('[aria-label]');
for (var i = 0; i < els.length; i++) {
tt.setTooltip(els[i], els[i].getAttribute('aria-label'));
}
}
命令控件
每组中的控件都是正常创建和使用的:
// populate combos
var fontFace = new wijmo.input.ComboBox('#font-face', {
itemsSource: 'Arial,Courier New,…,WingDings'.split(','),
textChanged: function(s, e) {
execCommand('fontName', s.text);
}
});
var fontSize = new wijmo.input.ComboBox('#font-size', {
itemsSource: 'Very Small,Smaller,…,Very Large'.split(','),
selectedIndex: 3,
textChanged: function(s, e) {
execCommand('fontSize', s.selectedIndex + 1);
}
});
常规HTML按钮和输入元素也是如此:
// execute commands
ribbon.hostElement.addEventListener('click', function(e) {
switch (e.target.id) {
// format group
case 'save':
localStorage.editorContent = document.getElementById('editor').innerHTML;
alert('Document Saved to Local Storage.');
break;
case 'undo':
case 'redo':
case 'preview':
case 'removeFormat':
case 'cut':
case 'copy':
case 'paste':
case 'selectAll':
execCommand(e.target.id);
break;
// font group
case 'bold':
case 'italic':
case 'underline':
case 'strikethrough':
case 'subscript':
case 'superscript':
execCommand(e.target.id);
break;
case 'click-me':
alert('Wijmo Ribbon Sample');
}
});
圆满结局
我们的故事有一个圆满的结局:我们将sample发送给客户,他们能够将他们的应用程序从Wijmo 3迁移到 WijmoJS 中。 在此过程中,他们减少了应用程序的依赖性,并使其与移动/触摸设备完美兼容。 TabPanel控件已经提供了足够的功能和灵活性,客户不必进行任何更改或向WijmoJS添加任何代码。