Commit 1af6ca3c authored by Boris Kocherov's avatar Boris Kocherov

add gadget_html5_select.* and dependence

parent 5eeb34d8
/*global window, RSVP, Array, isNaN */
/*jslint indent: 2, maxerr: 3, nomen: true, unparam: true */
(function (window, RSVP, Array, isNaN) {
"use strict";
window.calculatePageTitle = function (gadget, erp5_document) {
return new RSVP.Queue()
.push(function () {
var title = erp5_document.title,
portal_type = erp5_document._links.type.name;
if (/ Module$/.test(erp5_document._links.type.href)) {
return portal_type;
}
return portal_type + ': ' + title;
});
};
/** Return true if the value truly represents an empty value.
Calling isEmpty(x) is more robust than expression !x.
*/
function isEmpty(value) {
return (value === undefined ||
value === null ||
value.length === 0 ||
(typeof value === "number" && isNaN(value)));
}
window.isEmpty = isEmpty;
/** Make sure that returned object is an Array instance.
*/
function ensureArray(obj) {
if (Array.isArray(obj)) {return obj; }
if (isEmpty(obj)) {return []; }
return [obj];
}
window.ensureArray = ensureArray;
/** Return first non-empty variable or the last one.
Calling getNonEmpy(a, b, "") is more robust way of writing a || b || "".
Variables coercing to false (e.g 0) do not get skipped anymore.
*/
function getFirstNonEmpty() {
var i;
if (arguments.length === 0) {
return null;
}
for (i = 0; i < arguments.length; i++) {
if (!isEmpty(arguments[i])) {
return arguments[i];
}
}
if (arguments.length === 1) {
return arguments[0];
}
return arguments[arguments.length - 1];
}
window.getFirstNonEmpty = getFirstNonEmpty;
/** Convert anything to boolean value correctly (even "false" will be false)*/
function asBoolean(obj) {
if (typeof obj === "boolean") {
return obj;
}
if (typeof obj === "string") {
return obj.toLowerCase() === "true" || obj === "1";
}
if (typeof obj === "number") {
return obj !== 0;
}
return Boolean(obj);
}
window.asBoolean = asBoolean;
}(window, RSVP, Array, isNaN));
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>HTML5 Select</title>
<!-- renderjs -->
<script src="rsvp.js" type="text/javascript"></script>
<script src="renderjs.js" type="text/javascript"></script>
<script src="handlebars.js" type="text/javascript"></script>
<script src="gadget_erp5_global.js" type="text/javascript"></script>
<!-- custom script -->
<script id="option-template" type="text/x-handlebars-template">
<option value="{{value}}" data-i18n="{{text}}">{{text}}</option>
</script>
<script id="selected-option-template" type="text/x-handlebars-template">
<option selected="selected" data-i18n="{{text}}" value="{{value}}">{{text}}</option>
</script>
<script id="disabled-option-template" type="text/x-handlebars-template">
<option disabled="disabled" data-i18n="{{text}}">{{text}}</option>
</script>
<script src="gadget_html5_select.js" type="text/javascript"></script>
</head>
<body><select /></body>
</html>
\ No newline at end of file
/*global window, rJS, RSVP, Handlebars, getFirstNonEmpty */
/*jslint indent: 2, maxerr: 3, maxlen: 80, nomen: true */
(function (window, rJS, RSVP, Handlebars, getFirstNonEmpty) {
"use strict";
// How to change html selected option using JavaScript?
// http://stackoverflow.com/a/20662180
/////////////////////////////////////////////////////////////////
// Handlebars
/////////////////////////////////////////////////////////////////
// Precompile the templates while loading the first gadget instance
var gadget_klass = rJS(window),
option_source = gadget_klass.__template_element
.getElementById("option-template")
.innerHTML,
option_template = Handlebars.compile(option_source),
selected_option_source = gadget_klass.__template_element
.getElementById("selected-option-template")
.innerHTML,
selected_option_template = Handlebars.compile(selected_option_source),
disabled_option_source = gadget_klass.__template_element
.getElementById("disabled-option-template")
.innerHTML,
disabled_option_template = Handlebars.compile(disabled_option_source);
gadget_klass
.setState({
editable: false,
value: undefined,
checked: undefined,
title: '',
item_list: [],
required: false
})
.declareMethod('render', function (options) {
var state_dict = {
value: getFirstNonEmpty(options.value, ""),
item_list: JSON.stringify(options.item_list),
editable: options.editable,
required: options.required,
id: options.id,
name: options.name,
title: options.title,
hidden: options.hidden
};
return this.changeState(state_dict);
})
.onStateChange(function (modification_dict) {
var i,
found = false,
template,
select = this.element.querySelector('select'),
item_list = JSON.parse(this.state.item_list),
tmp = "";
select.id = this.state.id || this.state.name;
select.setAttribute('name', this.state.name);
if (this.state.title) {
select.setAttribute('title', this.state.title);
}
if (this.state.required) {
select.required = true;
} else {
select.required = false;
}
if (this.state.editable) {
select.readonly = true;
} else {
select.readonly = false;
}
if (this.state.hidden) {
select.hidden = true;
} else {
select.hidden = false;
}
if (modification_dict.hasOwnProperty('value') ||
modification_dict.hasOwnProperty('item_list')) {
for (i = 0; i < item_list.length; i += 1) {
if (item_list[i][1] === null) {
template = disabled_option_template;
} else if (item_list[i][1] === this.state.value) {
template = selected_option_template;
found = true;
} else {
template = option_template;
}
tmp += template({
value: item_list[i][1],
text: item_list[i][0]
});
}
if (!found) {
tmp += selected_option_template({
value: this.state.value,
text: '??? (' + this.state.value + ')'
});
}
select.innerHTML = tmp;
}
})
.declareMethod('getContent', function () {
var result = {},
select = this.element.querySelector('select');
if (this.state.editable) {
result[select.getAttribute('name')] =
select.options[select.selectedIndex].value;
// Change the value state in place
// This will prevent the gadget to be changed if
// its parent call render with the same value
// (as ERP5 does in case of formulator error)
this.state.value = result[select.getAttribute('name')];
}
return result;
})
.declareAcquiredMethod("notifyValid", "notifyValid")
.declareMethod('checkValidity', function () {
var result = this.element.querySelector('select').checkValidity();
if (result) {
return this.notifyValid()
.push(function () {
return result;
});
}
return result;
})
.declareAcquiredMethod("notifyChange", "notifyChange")
.onEvent('change', function () {
return RSVP.all([
this.checkValidity(),
this.notifyChange()
]);
}, false, false)
.onEvent('input', function () {
return RSVP.all([
this.checkValidity(),
this.notifyChange()
]);
}, false, false)
.declareAcquiredMethod("notifyInvalid", "notifyInvalid")
.onEvent('invalid', function (evt) {
// invalid event does not bubble
return this.notifyInvalid(evt.target.validationMessage);
}, true, false);
}(window, rJS, RSVP, Handlebars, getFirstNonEmpty));
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment