UNPKG

@yeatszhang/tiddlywiki

Version:
188 lines (170 loc) 5.2 kB
/*\ title: $:/core/modules/widgets/select.js type: application/javascript module-type: widget Select widget: ``` <$select tiddler="MyTiddler" field="text"> <$list filter="[tag[chapter]]"> <option value=<<currentTiddler>>> <$view field="description"/> </option> </$list> </$select> ``` \*/ (function(){ /*jslint node: true, browser: true */ /*global $tw: false */ "use strict"; var Widget = require("$:/core/modules/widgets/widget.js").widget; var SelectWidget = function(parseTreeNode,options) { this.initialise(parseTreeNode,options); }; /* Inherit from the base widget class */ SelectWidget.prototype = new Widget(); /* Render this widget into the DOM */ SelectWidget.prototype.render = function(parent,nextSibling) { this.parentDomNode = parent; this.computeAttributes(); this.execute(); this.renderChildren(parent,nextSibling); this.setSelectValue(); $tw.utils.addEventListeners(this.getSelectDomNode(),[ {name: "change", handlerObject: this, handlerMethod: "handleChangeEvent"} ]); }; /* Handle a change event */ SelectWidget.prototype.handleChangeEvent = function(event) { // Get the new value and assign it to the tiddler if(this.selectMultiple == false) { var value = this.getSelectDomNode().value; } else { var value = this.getSelectValues() value = $tw.utils.stringifyList(value); } this.wiki.setText(this.selectTitle,this.selectField,this.selectIndex,value); // Trigger actions if(this.selectActions) { this.invokeActionString(this.selectActions,this,event); } }; /* If necessary, set the value of the select element to the current value */ SelectWidget.prototype.setSelectValue = function() { var value = this.selectDefault; // Get the value if(this.selectIndex) { value = this.wiki.extractTiddlerDataItem(this.selectTitle,this.selectIndex); } else { var tiddler = this.wiki.getTiddler(this.selectTitle); if(tiddler) { if(this.selectField === "text") { // Calling getTiddlerText() triggers lazy loading of skinny tiddlers value = this.wiki.getTiddlerText(this.selectTitle); } else { if($tw.utils.hop(tiddler.fields,this.selectField)) { value = tiddler.getFieldString(this.selectField); } } } else { if(this.selectField === "title") { value = this.selectTitle; } } } // Assign it to the select element if it's different than the current value if (this.selectMultiple) { value = value === undefined ? "" : value; var select = this.getSelectDomNode(); var values = Array.isArray(value) ? value : $tw.utils.parseStringArray(value); for(var i=0; i < select.children.length; i++){ if(values.indexOf(select.children[i].value) != -1) { select.children[i].selected = true; } } } else { var domNode = this.getSelectDomNode(); if(domNode.value !== value) { domNode.value = value; } } }; /* Get the DOM node of the select element */ SelectWidget.prototype.getSelectDomNode = function() { return this.children[0].domNodes[0]; }; // Return an array of the selected opion values // select is an HTML select element SelectWidget.prototype.getSelectValues = function() { var select, result, options, opt; select = this.getSelectDomNode(); result = []; options = select && select.options; for (var i=0; i<options.length; i++) { opt = options[i]; if (opt.selected) { result.push(opt.value || opt.text); } } return result; } /* Compute the internal state of the widget */ SelectWidget.prototype.execute = function() { // Get our parameters this.selectActions = this.getAttribute("actions"); this.selectTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler")); this.selectField = this.getAttribute("field","text"); this.selectIndex = this.getAttribute("index"); this.selectClass = this.getAttribute("class"); this.selectDefault = this.getAttribute("default"); this.selectMultiple = this.getAttribute("multiple", false); this.selectSize = this.getAttribute("size"); // Make the child widgets var selectNode = { type: "element", tag: "select", children: this.parseTreeNode.children }; if(this.selectClass) { $tw.utils.addAttributeToParseTreeNode(selectNode,"class",this.selectClass); } if(this.selectMultiple) { $tw.utils.addAttributeToParseTreeNode(selectNode,"multiple","multiple"); } if(this.selectSize) { $tw.utils.addAttributeToParseTreeNode(selectNode,"size",this.selectSize); } this.makeChildWidgets([selectNode]); }; /* Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering */ SelectWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); // If we're using a different tiddler/field/index then completely refresh ourselves if(changedAttributes.selectTitle || changedAttributes.selectField || changedAttributes.selectIndex) { this.refreshSelf(); return true; // If the target tiddler value has changed, just update setting and refresh the children } else { var childrenRefreshed = this.refreshChildren(changedTiddlers); if(changedTiddlers[this.selectTitle] || childrenRefreshed) { this.setSelectValue(); } return childrenRefreshed; } }; exports.select = SelectWidget; })();