/*
This file is part of LONCAPA-Daxe.
LONCAPA-Daxe is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
LONCAPA-Daxe is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Daxe. If not, see <http://www.gnu.org/licenses/>.
*/
part of loncapa_daxe;
/**
* Display for essayresponse, with a possible simple UI.
* Jaxe display type: 'essayresponse'.
*/
class EssayResponse extends LCDBlock {
static List<String> simpleUIAttributes = ['id'];
static Map<String,Map<String,String>> paramDef = {
'handgrade': {
'name': 'handgrade',
'type': 'string_yesno',
'default': 'yes',
'description': 'Hand Graded'
},
'maxcollaborators': {
'name': 'maxcollaborators',
'type': 'int_zeropos',
'default': '0',
'description': 'Maximum Number of Collaborators'
},
'uploadedfiletypes': {
'name': 'uploadedfiletypes',
'type': 'string_fileext',
'default': '',
'description': 'Allowed File Extensions for Uploaded Files'
},
'maxfilesize': {
'name': 'maxfilesize',
'type': 'float_pos',
'default': '10.0',
'description': 'Max. cumulative size (MB) for submitted files'
}
};
EssayResponse.fromRef(x.Element elementRef) : super.fromRef(elementRef) {
displaySimpleButton = true;
}
EssayResponse.fromNode(x.Node node, DaxeNode parent) : super.fromNode(node, parent) {
displaySimpleButton = true;
if (simpleUIPossibleNoThrow()) {
bool node_simpleUI = node.getUserData('simpleUI');
if (node_simpleUI == null || node_simpleUI)
setupSimpleUI();
}
}
@override
bool simpleUIPossible() {
for (DaxeAttr att in attributes) {
if (!simpleUIAttributes.contains(att.name)) {
throw new SimpleUIException('essayresponse: ' + LCDStrings.get('attribute_problem') + ' ' + att.name);
}
}
int nbTextfield = 0;
for (DaxeNode dn=firstChild; dn!= null; dn=dn.nextSibling) {
if (dn is Textfield) {
if (!dn.simpleUIPossible())
return false;
nbTextfield++;
} else if (dn is LCDParameter) {
if (!paramDef.keys.contains(dn.getAttribute('name')))
return throw new SimpleUIException(LCDStrings.get('advanced_response_param'));
} else if (dn.nodeType != DaxeNode.TEXT_NODE) {
String title = doc.cfg.elementTitle(dn.ref);
throw new SimpleUIException(LCDStrings.get('element_prevents') + ' ' + dn.nodeName +
(title != null ? " ($title)" : ''));
} else if (dn.nodeValue.trim() != '') {
return false;
}
}
if (nbTextfield != 1)
throw new SimpleUIException(LCDStrings.get('one_textfield'));
return true;
}
@override
h.Element html() {
if (!simpleUI)
return super.html();
h.DivElement div = new h.DivElement();
div.id = "$id";
div.classes.add('dn');
if (!valid)
div.classes.add('invalid');
div.classes.add('dnblock');
h.DivElement headerDiv = createHeaderDiv();
headerDiv.classes.add('without-content-afterwards');
div.append(headerDiv);
return(div);
}
@override
h.Element createAttributesHTML() {
h.Element attHTML = super.createAttributesHTML();
if (!simpleUI || attHTML == null)
return attHTML;
// add the fake attribute (textfield spellcheck)
if (state == 0) {
h.TableElement table = attHTML;
for (DaxeNode dn in childNodes) {
if (dn is LCDParameter || dn is Textfield) {
h.Element he = dn.html(); // might be table or tr
if (he is h.TableRowElement) {
table.append(he);
} else if (he is h.TableElement) {
// turn the table into a tbody, for column alignment
h.TableSectionElement tbody = table.createTBody();
List<h.TableRowElement> rows = new List.from(he.rows);
for (h.Element tr in rows)
tbody.append(tr);
table.append(tbody);
}
}
}
return table;
} else if (state == 1) {
h.DivElement attDiv = attHTML;
for (DaxeNode dn=firstChild; dn!= null; dn=dn.nextSibling) {
if (dn is LCDParameter && dn.getAttribute('default') != null) {
attDiv.append(new h.Text(" "));
h.Element att_name = new h.SpanElement();
att_name.attributes['class'] = 'attribute_name';
att_name.text = dn.getAttribute('name');
attDiv.append(att_name);
attDiv.append(new h.Text("="));
h.Element att_val = new h.SpanElement();
att_val.attributes['class'] = 'attribute_value';
att_val.text = dn.getAttribute('default');
attDiv.append(att_val);
} else if (dn is Textfield && dn.getAttribute('spellcheck') != null) {
attDiv.append(new h.Text(" "));
h.Element att_name = new h.SpanElement();
att_name.attributes['class'] = 'attribute_name';
att_name.text = LCDStrings.get('spellcheck');
attDiv.append(att_name);
attDiv.append(new h.Text("="));
h.Element att_val = new h.SpanElement();
att_val.attributes['class'] = 'attribute_value';
att_val.text = dn.getAttribute('spellcheck');
attDiv.append(att_val);
}
}
return attDiv;
} else
return null;
}
@override
void updateHTMLAfterChildrenChange(List<DaxeNode> changed) {
updateHTML(); // because DaxeNode's update does not handle fake attributes
}
void setupRestrictions() {
for (int i=0; i<attRefs.length; i++) {
x.Element refAttr = attRefs[i];
if (!simpleUIAttributes.contains(doc.cfg.attributeName(refAttr))) {
attRefs.removeAt(i);
i--;
}
}
restrictedInserts = [];
}
@override
void setupSimpleUI() {
simpleUI = true;
setupRestrictions();
fixChildrenForSimpleUI();
}
@override
void newNodeCreationUI(ActionFunction okfct) {
setupSimpleUI();
okfct();
}
Textfield newTextfield() {
List<x.Element> textfieldRefs = doc.cfg.elementReferences('textfield');
x.Element textfieldRef = doc.cfg.findSubElement(ref, textfieldRefs);
Textfield textfield = NodeFactory.create(textfieldRef);
textfield.state = 1;
return textfield;
}
LCDParameter newResponseParam(Map<String,String> def) {
List<x.Element> responseparamRefs = doc.cfg.elementReferences('responseparam');
x.Element responseparamRef = doc.cfg.findSubElement(ref, responseparamRefs);
LCDParameter responseparam = new LCDParameter.fromRef(responseparamRef);
responseparam.setAttribute('name', def['name']);
responseparam.setAttribute('type', def['type']);
responseparam.setAttribute('default', def['default']);
responseparam.setAttribute('description', def['description']);
responseparam.state = 1;
return responseparam;
}
/**
* This inserts a textline, hintgroup if missing.
*/
void fixChildrenForSimpleUI() {
Textfield textfield = null;
List foundParams = [];
for (DaxeNode dn in childNodes) {
if (dn.nodeType == DaxeNode.ELEMENT_NODE) {
if (dn.nodeName == 'textfield')
textfield = dn;
else if (dn.nodeName == 'responseparam')
foundParams.add(dn.getAttribute('name'));
}
}
for (String paramName in paramDef.keys) {
if (!foundParams.contains(paramName) && paramName != 'handgrade')
insertBefore(newResponseParam(paramDef[paramName]), textfield);
}
if (textfield == null)
appendChild(newTextfield());
}
/**
* Remove parameters that are not set or set to default when serializing.
*/
@override
x.Node toDOMNode(x.Document domDocument) {
x.Element response = super.toDOMNode(domDocument);
List<x.Node> list = response.getElementsByTagName('responseparam');
for (x.Node n in list) {
x.Element p = n;
Map<String,String> param = paramDef[p.getAttribute('name')];
if (param != null && (p.getAttribute('default') == '' ||
(p.getAttribute('type') == param['type'] &&
p.getAttribute('default') == param['default'] &&
p.getAttribute('description') == param['description']))) {
if (p.nextSibling is x.Text && p.nextSibling.nodeValue == '\n')
p.parentNode.removeChild(p.nextSibling);
p.parentNode.removeChild(p);
}
}
return(response);
}
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>