diff options
Diffstat (limited to 'components/sessionstore/DocumentUtils.jsm')
-rw-r--r-- | components/sessionstore/DocumentUtils.jsm | 230 |
1 files changed, 0 insertions, 230 deletions
diff --git a/components/sessionstore/DocumentUtils.jsm b/components/sessionstore/DocumentUtils.jsm deleted file mode 100644 index 6b3f729..0000000 --- a/components/sessionstore/DocumentUtils.jsm +++ /dev/null @@ -1,230 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -this.EXPORTED_SYMBOLS = [ "DocumentUtils" ]; - -const Cu = Components.utils; -const Ci = Components.interfaces; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource:///modules/sessionstore/XPathGenerator.jsm"); - -this.DocumentUtils = { - /** - * Obtain form data for a DOMDocument instance. - * - * The returned object has 2 keys, "id" and "xpath". Each key holds an object - * which further defines form data. - * - * The "id" object maps element IDs to values. The "xpath" object maps the - * XPath of an element to its value. - * - * @param aDocument - * DOMDocument instance to obtain form data for. - * @return object - * Form data encoded in an object. - */ - getFormData: function DocumentUtils_getFormData(aDocument) { - let formNodes = aDocument.evaluate( - XPathGenerator.restorableFormNodes, - aDocument, - XPathGenerator.resolveNS, - Ci.nsIDOMXPathResult.UNORDERED_NODE_ITERATOR_TYPE, null - ); - - let node; - let ret = {id: {}, xpath: {}}; - - // Limit the number of XPath expressions for performance reasons. See - // bug 477564. - const MAX_TRAVERSED_XPATHS = 100; - let generatedCount = 0; - - while (node = formNodes.iterateNext()) { - let nId = node.id; - let hasDefaultValue = true; - let value; - - // Only generate a limited number of XPath expressions for perf reasons - // (cf. bug 477564) - if (!nId && generatedCount > MAX_TRAVERSED_XPATHS) { - continue; - } - - if (node instanceof Ci.nsIDOMHTMLInputElement || - node instanceof Ci.nsIDOMHTMLTextAreaElement) { - switch (node.type) { - case "checkbox": - case "radio": - value = node.checked; - hasDefaultValue = value == node.defaultChecked; - break; - case "file": - value = { type: "file", fileList: node.mozGetFileNameArray() }; - hasDefaultValue = !value.fileList.length; - break; - default: // text, textarea - value = node.value; - hasDefaultValue = value == node.defaultValue; - break; - } - } else if (!node.multiple) { - // <select>s without the multiple attribute are hard to determine the - // default value, so assume we don't have the default. - hasDefaultValue = false; - value = { selectedIndex: node.selectedIndex, value: node.value }; - } else { - // <select>s with the multiple attribute are easier to determine the - // default value since each <option> has a defaultSelected - let options = Array.map(node.options, function(aOpt, aIx) { - let oSelected = aOpt.selected; - hasDefaultValue = hasDefaultValue && (oSelected == aOpt.defaultSelected); - return oSelected ? aOpt.value : -1; - }); - value = options.filter(function(aIx) aIx !== -1); - } - - // In order to reduce XPath generation (which is slow), we only save data - // for form fields that have been changed. (cf. bug 537289) - if (!hasDefaultValue) { - if (nId) { - ret.id[nId] = value; - } else { - generatedCount++; - ret.xpath[XPathGenerator.generate(node)] = value; - } - } - } - - return ret; - }, - - /** - * Merges form data on a document from previously obtained data. - * - * This is the inverse of getFormData(). The data argument is the same object - * type which is returned by getFormData(): an object containing the keys - * "id" and "xpath" which are each objects mapping element identifiers to - * form values. - * - * Where the document has existing form data for an element, the value - * will be replaced. Where the document has a form element but no matching - * data in the passed object, the element is untouched. - * - * @param aDocument - * DOMDocument instance to which to restore form data. - * @param aData - * Object defining form data. - */ - mergeFormData: function DocumentUtils_mergeFormData(aDocument, aData) { - if ("xpath" in aData) { - for each (let [xpath, value] in Iterator(aData.xpath)) { - let node = XPathGenerator.resolve(aDocument, xpath); - - if (node) { - this.restoreFormValue(node, value, aDocument); - } - } - } - - if ("id" in aData) { - for each (let [id, value] in Iterator(aData.id)) { - let node = aDocument.getElementById(id); - - if (node) { - this.restoreFormValue(node, value, aDocument); - } - } - } - }, - - /** - * Low-level function to restore a form value to a DOMNode. - * - * If you want a higher-level interface, see mergeFormData(). - * - * When the value is changed, the function will fire the appropriate DOM - * events. - * - * @param aNode - * DOMNode to set form value on. - * @param aValue - * Value to set form element to. - * @param aDocument [optional] - * DOMDocument node belongs to. If not defined, node.ownerDocument - * is used. - */ - restoreFormValue: function DocumentUtils_restoreFormValue(aNode, aValue, aDocument) { - aDocument = aDocument || aNode.ownerDocument; - - let eventType; - - if (typeof aValue == "string" && aNode.type != "file") { - // Don't dispatch an input event if there is no change. - if (aNode.value == aValue) { - return; - } - - aNode.value = aValue; - eventType = "input"; - } else if (typeof aValue == "boolean") { - // Don't dispatch a change event for no change. - if (aNode.checked == aValue) { - return; - } - - aNode.checked = aValue; - eventType = "change"; - } else if (typeof aValue == "number") { - // handle select backwards compatibility, example { "#id" : index } - // We saved the value blindly since selects take more work to determine - // default values. So now we should check to avoid unnecessary events. - if (aNode.selectedIndex == aValue) { - return; - } - - if (aValue < aNode.options.length) { - aNode.selectedIndex = aValue; - eventType = "change"; - } - } else if (aValue && aValue.selectedIndex >= 0 && aValue.value) { - // handle select new format - - // Don't dispatch a change event for no change - if (aNode.options[aNode.selectedIndex].value == aValue.value) { - return; - } - - // find first option with matching aValue if possible - for (let i = 0; i < aNode.options.length; i++) { - if (aNode.options[i].value == aValue.value) { - aNode.selectedIndex = i; - break; - } - } - eventType = "change"; - } else if (aValue && aValue.fileList && aValue.type == "file" && - aNode.type == "file") { - aNode.mozSetFileNameArray(aValue.fileList, aValue.fileList.length); - eventType = "input"; - } else if (aValue && typeof aValue.indexOf == "function" && aNode.options) { - Array.forEach(aNode.options, function(opt, index) { - // don't worry about malformed options with same values - opt.selected = aValue.indexOf(opt.value) > -1; - - // Only fire the event here if this wasn't selected by default - if (!opt.defaultSelected) { - eventType = "change"; - } - }); - } - - // Fire events for this node if applicable - if (eventType) { - let event = aDocument.createEvent("UIEvents"); - event.initUIEvent(eventType, true, true, aDocument.defaultView, 0); - aNode.dispatchEvent(event); - } - } -}; |