2016-12-20 16:21:35 -08:00
|
|
|
<!doctype html>
|
|
|
|
|
<!--
|
|
|
|
|
@license
|
|
|
|
|
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
|
|
|
|
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
|
|
|
|
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
|
|
|
|
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
|
|
|
|
Code distributed by Google as part of the polymer project is also
|
|
|
|
|
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
|
|
|
-->
|
|
|
|
|
<html>
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="utf-8">
|
|
|
|
|
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
|
|
|
|
|
<script src="../../../web-component-tester/browser.js"></script>
|
|
|
|
|
<link rel="import" href="../../polymer.html">
|
|
|
|
|
<link rel="import" href="array-selector-elements.html">
|
|
|
|
|
<body>
|
|
|
|
|
|
|
|
|
|
<test-fixture id="singleConfigured">
|
|
|
|
|
<template>
|
|
|
|
|
<array-selector
|
|
|
|
|
items='[{"name": "one"},{"name": "two"},{"name": "three"}]'>
|
|
|
|
|
</array-selector>
|
|
|
|
|
</template>
|
|
|
|
|
</test-fixture>
|
|
|
|
|
|
|
|
|
|
<test-fixture id="multiConfigured">
|
|
|
|
|
<template>
|
|
|
|
|
<array-selector multi
|
|
|
|
|
items='[{"name": "one"},{"name": "two"},{"name": "three"}]'>
|
|
|
|
|
</array-selector>
|
|
|
|
|
</template>
|
|
|
|
|
</test-fixture>
|
|
|
|
|
|
|
|
|
|
<test-fixture id="bind">
|
|
|
|
|
<template>
|
|
|
|
|
<dom-bind>
|
|
|
|
|
<template>
|
|
|
|
|
<observe-el id="observer" single-selected="{{singleSelected}}" multi-selected="{{multiSelected}}"></observe-el>
|
|
|
|
|
<array-selector id="singleBound" items="{{items}}" selected="{{singleSelected}}"></array-selector>
|
|
|
|
|
<array-selector id="multiBound" items="{{items}}" selected="{{multiSelected}}" multi></array-selector>
|
|
|
|
|
</template>
|
|
|
|
|
</dom-bind>
|
|
|
|
|
</template>
|
|
|
|
|
</test-fixture>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
/* global bind observer singleBound multiBound */
|
|
|
|
|
suite('basic', function() {
|
|
|
|
|
test('single selection', function() {
|
|
|
|
|
var el = fixture('singleConfigured');
|
|
|
|
|
// Nothing selected
|
|
|
|
|
assert.strictEqual(el.selectedItem, null);
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[0]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[1]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[2]));
|
|
|
|
|
// Select 0
|
|
|
|
|
el.select(el.items[0]);
|
|
|
|
|
assert.strictEqual(el.selectedItem, el.items[0]);
|
|
|
|
|
assert.isTrue(el.isSelected(el.items[0]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[1]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[2]));
|
|
|
|
|
// Re-select 0
|
|
|
|
|
el.select(el.items[0]);
|
|
|
|
|
assert.strictEqual(el.selectedItem, el.items[0]);
|
|
|
|
|
assert.isTrue(el.isSelected(el.items[0]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[1]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[2]));
|
|
|
|
|
// Select 2
|
|
|
|
|
el.select(el.items[2]);
|
|
|
|
|
assert.strictEqual(el.selectedItem, el.items[2]);
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[0]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[1]));
|
|
|
|
|
assert.isTrue(el.isSelected(el.items[2]));
|
|
|
|
|
// Toggle 2
|
|
|
|
|
el.toggle = true;
|
|
|
|
|
el.select(el.items[2]);
|
|
|
|
|
assert.strictEqual(el.selectedItem, null);
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[0]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[1]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[2]));
|
|
|
|
|
// Toggle 2
|
|
|
|
|
el.toggle = true;
|
|
|
|
|
el.select(el.items[2]);
|
|
|
|
|
assert.strictEqual(el.selectedItem, el.items[2]);
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[0]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[1]));
|
|
|
|
|
assert.isTrue(el.isSelected(el.items[2]));
|
|
|
|
|
// clearSelection
|
|
|
|
|
el.clearSelection();
|
|
|
|
|
assert.equal(el.selectedItem, null);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('multiple selection', function() {
|
|
|
|
|
var el = fixture('multiConfigured');
|
|
|
|
|
// Nothing selected
|
|
|
|
|
assert.sameMembers(el.selected, []);
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[0]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[1]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[2]));
|
|
|
|
|
// Select 0
|
|
|
|
|
el.select(el.items[0]);
|
|
|
|
|
assert.sameMembers(el.selected, [el.items[0]]);
|
|
|
|
|
assert.isTrue(el.isSelected(el.items[0]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[1]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[2]));
|
|
|
|
|
// Re-select 0
|
|
|
|
|
el.select(el.items[0]);
|
|
|
|
|
assert.sameMembers(el.selected, [el.items[0]]);
|
|
|
|
|
assert.isTrue(el.isSelected(el.items[0]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[1]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[2]));
|
|
|
|
|
// Select 2
|
|
|
|
|
el.select(el.items[2]);
|
|
|
|
|
assert.sameMembers(el.selected, [el.items[0], el.items[2]]);
|
|
|
|
|
assert.isTrue(el.isSelected(el.items[0]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[1]));
|
|
|
|
|
assert.isTrue(el.isSelected(el.items[2]));
|
|
|
|
|
// Toggle 2
|
|
|
|
|
el.toggle = true;
|
|
|
|
|
el.select(el.items[2]);
|
|
|
|
|
assert.sameMembers(el.selected, [el.items[0]]);
|
|
|
|
|
assert.isTrue(el.isSelected(el.items[0]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[1]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[2]));
|
|
|
|
|
// Toggle 2
|
|
|
|
|
el.toggle = true;
|
|
|
|
|
el.select(el.items[2]);
|
|
|
|
|
assert.sameMembers(el.selected, [el.items[0], el.items[2]]);
|
|
|
|
|
assert.isTrue(el.isSelected(el.items[0]));
|
|
|
|
|
assert.isFalse(el.isSelected(el.items[1]));
|
|
|
|
|
assert.isTrue(el.isSelected(el.items[2]));
|
|
|
|
|
// clear selection
|
|
|
|
|
el.clearSelection();
|
|
|
|
|
assert.sameMembers(el.selected, []);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('bound defaults', function() {
|
|
|
|
|
let bind = fixture('bind');
|
|
|
|
|
assert.equal(bind.$.observer.singleSelected, null);
|
|
|
|
|
assert.sameMembers(bind.$.observer.multiSelected, []);
|
|
|
|
|
bind.items = [
|
|
|
|
|
{name: 'one'},
|
|
|
|
|
{name: 'two'},
|
|
|
|
|
{name: 'three'}
|
|
|
|
|
];
|
|
|
|
|
assert.equal(bind.$.observer.singleSelected, null);
|
|
|
|
|
assert.sameMembers(bind.$.observer.multiSelected, []);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('single selection notification', function() {
|
|
|
|
|
let bind = fixture('bind');
|
|
|
|
|
bind.items = [
|
|
|
|
|
{name: 'one'},
|
|
|
|
|
{name: 'two'},
|
|
|
|
|
{name: 'three'}
|
|
|
|
|
];
|
|
|
|
|
bind.$.observer.singleChanged = sinon.spy();
|
|
|
|
|
bind.$.singleBound.select(bind.items[2]);
|
|
|
|
|
assert.isTrue(bind.$.observer.singleChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.singleChanged.firstCall.args[0].path, 'singleSelected');
|
|
|
|
|
assert.equal(bind.$.observer.singleChanged.firstCall.args[0].value, bind.items[2]);
|
|
|
|
|
assert.equal(bind.$.observer.singleSelected, bind.items[2]);
|
|
|
|
|
// clear selection
|
|
|
|
|
bind.$.observer.singleChanged = sinon.spy();
|
|
|
|
|
bind.$.singleBound.clearSelection();
|
|
|
|
|
assert.equal(bind.$.observer.singleSelected, null);
|
|
|
|
|
assert.isTrue(bind.$.observer.singleChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.singleChanged.firstCall.args[0].path, 'singleSelected');
|
|
|
|
|
assert.equal(bind.$.observer.singleChanged.firstCall.args[0].value, null);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('single selection sub-property change', function() {
|
|
|
|
|
let bind = fixture('bind');
|
|
|
|
|
bind.items = [
|
|
|
|
|
{name: 'one'},
|
|
|
|
|
{name: 'two'},
|
|
|
|
|
{name: 'three'}
|
|
|
|
|
];
|
|
|
|
|
bind.$.singleBound.select(bind.items[2]);
|
|
|
|
|
bind.$.observer.singleChanged = sinon.spy();
|
|
|
|
|
bind.set(['items', 2, 'name'], 'test');
|
|
|
|
|
assert.isTrue(bind.$.observer.singleChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.singleChanged.firstCall.args[0].path, 'singleSelected.name');
|
|
|
|
|
assert.equal(bind.$.observer.singleChanged.firstCall.args[0].value, 'test');
|
|
|
|
|
assert.equal(bind.$.observer.singleSelected.name, 'test');
|
|
|
|
|
|
|
|
|
|
bind.$.singleBound.select(bind.items[1]);
|
|
|
|
|
bind.$.observer.singleChanged = sinon.spy();
|
|
|
|
|
bind.set(['items', 1, 'name'], 'test2');
|
|
|
|
|
assert.isTrue(bind.$.observer.singleChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.singleChanged.firstCall.args[0].path, 'singleSelected.name');
|
|
|
|
|
assert.equal(bind.$.observer.singleChanged.firstCall.args[0].value, 'test2');
|
|
|
|
|
assert.equal(bind.$.observer.singleSelected.name, 'test2');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('single selection sub-property change after unshift', function() {
|
|
|
|
|
let bind = fixture('bind');
|
|
|
|
|
bind.items = [
|
|
|
|
|
{name: 'one'},
|
|
|
|
|
{name: 'two'},
|
|
|
|
|
{name: 'three'}
|
|
|
|
|
];
|
|
|
|
|
bind.$.singleBound.select(bind.items[2]);
|
|
|
|
|
bind.$.observer.singleChanged = sinon.spy();
|
|
|
|
|
bind.unshift('items', {name: 'zero'});
|
|
|
|
|
bind.set(['items', 3, 'name'], 'test2');
|
|
|
|
|
assert.isTrue(bind.$.observer.singleChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.singleChanged.firstCall.args[0].path, 'singleSelected.name');
|
|
|
|
|
assert.equal(bind.$.observer.singleChanged.firstCall.args[0].value, 'test2');
|
|
|
|
|
assert.equal(bind.$.observer.singleSelected.name, 'test2');
|
|
|
|
|
});
|
|
|
|
|
|
2016-12-20 16:38:53 -08:00
|
|
|
test('single selection removal via splice', function() {
|
|
|
|
|
let bind = fixture('bind');
|
|
|
|
|
bind.items = [
|
|
|
|
|
{name: 'one'},
|
|
|
|
|
{name: 'two'},
|
|
|
|
|
{name: 'three'}
|
|
|
|
|
];
|
|
|
|
|
bind.$.singleBound.select(bind.items[1]);
|
|
|
|
|
bind.$.observer.singleChanged = sinon.spy();
|
|
|
|
|
bind.splice('items', 1, 2);
|
|
|
|
|
assert.isTrue(bind.$.observer.singleChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.singleChanged.firstCall.args[0].path, 'singleSelected');
|
|
|
|
|
assert.equal(bind.$.observer.singleChanged.firstCall.args[0].value, null);
|
|
|
|
|
assert.equal(bind.$.observer.singleSelected, null);
|
|
|
|
|
});
|
|
|
|
|
|
2016-12-20 16:21:35 -08:00
|
|
|
test('multi selection notification', function() {
|
|
|
|
|
let bind = fixture('bind');
|
|
|
|
|
bind.items = [
|
|
|
|
|
{name: 'one'},
|
|
|
|
|
{name: 'two'},
|
|
|
|
|
{name: 'three'}
|
|
|
|
|
];
|
|
|
|
|
// select first
|
|
|
|
|
bind.$.observer.multiChanged = sinon.spy();
|
|
|
|
|
bind.$.multiBound.select(bind.items[2]);
|
|
|
|
|
assert.isTrue(bind.$.observer.multiChanged.calledTwice);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].path, 'multiSelected.splices');
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value.indexSplices.length, 1);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value.indexSplices[0].addedCount, 1);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value.indexSplices[0].removed.length, 0);
|
|
|
|
|
assert.sameMembers(bind.$.observer.multiSelected, [bind.items[2]]);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.secondCall.args[0].path, 'multiSelected.length');
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.secondCall.args[0].value, 1);
|
|
|
|
|
// select second
|
|
|
|
|
bind.$.observer.multiChanged = sinon.spy();
|
|
|
|
|
bind.$.multiBound.select(bind.items[0]);
|
|
|
|
|
assert.isTrue(bind.$.observer.multiChanged.calledTwice);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].path, 'multiSelected.splices');
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value.indexSplices.length, 1);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value.indexSplices[0].addedCount, 1);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value.indexSplices[0].removed.length, 0);
|
|
|
|
|
assert.sameMembers(bind.$.observer.multiSelected, [bind.items[2], bind.items[0]]);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.secondCall.args[0].path, 'multiSelected.length');
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.secondCall.args[0].value, 2);
|
|
|
|
|
// clear selection
|
|
|
|
|
bind.$.observer.multiChanged = sinon.spy();
|
|
|
|
|
bind.$.multiBound.clearSelection();
|
|
|
|
|
assert.sameMembers(bind.$.observer.multiSelected, []);
|
|
|
|
|
assert.isTrue(bind.$.observer.multiChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].path, 'multiSelected');
|
|
|
|
|
assert.sameMembers(bind.$.observer.multiChanged.firstCall.args[0].value, []);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('multi selection sub-property change', function() {
|
|
|
|
|
let bind = fixture('bind');
|
|
|
|
|
bind.items = [
|
|
|
|
|
{name: 'one'},
|
|
|
|
|
{name: 'two'},
|
|
|
|
|
{name: 'three'}
|
|
|
|
|
];
|
|
|
|
|
multiBound.select(bind.items[2]);
|
|
|
|
|
multiBound.select(bind.items[0]);
|
|
|
|
|
bind.$.observer.multiChanged = sinon.spy();
|
|
|
|
|
bind.set(['items', 2, 'name'], 'test');
|
|
|
|
|
assert.isTrue(bind.$.observer.multiChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].path, 'multiSelected.0.name');
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value, 'test');
|
|
|
|
|
assert.equal(bind.$.observer.multiSelected[0].name, 'test');
|
|
|
|
|
bind.$.observer.multiChanged = sinon.spy();
|
|
|
|
|
bind.set(['items', 0, 'name'], 'test2');
|
|
|
|
|
assert.isTrue(bind.$.observer.multiChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].path, 'multiSelected.1.name');
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value, 'test2');
|
|
|
|
|
assert.equal(bind.$.observer.multiSelected[1].name, 'test2');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test('multi selection sub-property change after unshift', function() {
|
|
|
|
|
let bind = fixture('bind');
|
|
|
|
|
bind.items = [
|
|
|
|
|
{name: 'one'},
|
|
|
|
|
{name: 'two'},
|
|
|
|
|
{name: 'three'}
|
|
|
|
|
];
|
|
|
|
|
multiBound.select(bind.items[2]);
|
|
|
|
|
multiBound.select(bind.items[0]);
|
|
|
|
|
bind.$.observer.multiChanged = sinon.spy();
|
|
|
|
|
bind.unshift('items', {name: 'zero'});
|
|
|
|
|
bind.set(['items', 1, 'name'], 'test');
|
|
|
|
|
assert.isTrue(bind.$.observer.multiChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].path, 'multiSelected.1.name');
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value, 'test');
|
|
|
|
|
assert.equal(bind.$.observer.multiSelected[1].name, 'test');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('multi selection sub-property change after splice (removal)', function() {
|
|
|
|
|
let bind = fixture('bind');
|
|
|
|
|
bind.items = [
|
|
|
|
|
{name: 'one'},
|
|
|
|
|
{name: 'two'},
|
|
|
|
|
{name: 'three'}
|
|
|
|
|
];
|
|
|
|
|
multiBound.select(bind.items[0]);
|
|
|
|
|
multiBound.select(bind.items[2]);
|
|
|
|
|
|
|
|
|
|
bind.$.observer.multiChanged = sinon.spy();
|
|
|
|
|
bind.splice('items', 0, 1);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].path, 'multiSelected.splices');
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value.indexSplices.length, 1);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value.indexSplices[0].index, 0);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value.indexSplices[0].addedCount, 0);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value.indexSplices[0].removed.length, 1);
|
|
|
|
|
|
|
|
|
|
bind.$.observer.multiChanged = sinon.spy();
|
|
|
|
|
bind.set(['items', 1, 'name'], 'test');
|
|
|
|
|
assert.isTrue(bind.$.observer.multiChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].path, 'multiSelected.0.name');
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value, 'test');
|
|
|
|
|
assert.equal(bind.$.observer.multiSelected[0].name, 'test');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('multi selection sub-property change after deselect', function() {
|
|
|
|
|
let bind = fixture('bind');
|
|
|
|
|
bind.items = [
|
|
|
|
|
{name: 'one'},
|
|
|
|
|
{name: 'two'},
|
|
|
|
|
{name: 'three'}
|
|
|
|
|
];
|
|
|
|
|
multiBound.select(bind.items[2]);
|
|
|
|
|
multiBound.select(bind.items[0]);
|
|
|
|
|
bind.$.observer.multiChanged = sinon.spy();
|
|
|
|
|
bind.set(['items', 0, 'name'], 'test');
|
|
|
|
|
assert.isTrue(bind.$.observer.multiChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].path, 'multiSelected.1.name');
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value, 'test');
|
|
|
|
|
assert.equal(bind.$.observer.multiSelected[1].name, 'test');
|
|
|
|
|
|
|
|
|
|
multiBound.deselect(bind.items[2]);
|
|
|
|
|
bind.$.observer.multiChanged = sinon.spy();
|
|
|
|
|
bind.set(['items', 0, 'name'], 'test4');
|
|
|
|
|
assert.isTrue(bind.$.observer.multiChanged.calledOnce);
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].path, 'multiSelected.0.name');
|
|
|
|
|
assert.equal(bind.$.observer.multiChanged.firstCall.args[0].value, 'test4');
|
|
|
|
|
assert.equal(bind.$.observer.multiSelected[0].name, 'test4');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|