From 322b5492ce46a432fc01c6fa9de1ee4bf60c4277 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Sep 2015 12:22:47 -0400 Subject: [PATCH 1/5] added a method or as Ben calls them a function called getVocabulary that finds vocabularies for xml elements --- src/jquery.xmleditor.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/jquery.xmleditor.js b/src/jquery.xmleditor.js index f3037d3..e79ab2a 100644 --- a/src/jquery.xmleditor.js +++ b/src/jquery.xmleditor.js @@ -1165,5 +1165,28 @@ $.widget( "xml.xmlEditor", { $("#" + xmlMenuHeaderPrefix + this.toString()).removeClass("disabled").data("menuItemData").enabled = true; else $("#" + xmlMenuHeaderPrefix + this.toString()).addClass("disabled").data("menuItemData").enabled = false; }); + }, + + // Finds the associated vocabulary for an xml element + getVocabulary: function(self, xmlElement) { + if (!this.options.vocabularies) { + return null; + } + + var matchingVocab = null; + $.each(this.options.vocabularies, function(selector, vocabulary){ + // find elements in xml document that match this vocabulary's selector + var matches = $(selector, self.xmlState.xml); + + // Check to see if our xmlElement was in the matching list + for (var i = 0; i < matches.length; i++) { + if (xmlElement.xmlNode === matches[i]) { + matchingVocab = vocabulary; + return false; + } + } + }); + + return matchingVocab; } }); From 4f73996c602e6e3ca0ff01c8d93be7f36043f6f3 Mon Sep 17 00:00:00 2001 From: Sonoe Nakasone Date: Wed, 30 Sep 2015 16:09:48 -0400 Subject: [PATCH 2/5] added autocomplete for vocabularies. --- demo/relator.html | 69 +++++++++++++++++++++++++++++++++++++++++ jquery.xmleditor.js | 36 +++++++++++++++++++-- src/jquery.xmleditor.js | 7 +++-- src/xml_element.js | 4 ++- src/xml_text_node.js | 8 ++++- 5 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 demo/relator.html diff --git a/demo/relator.html b/demo/relator.html new file mode 100644 index 0000000..2b3f04a --- /dev/null +++ b/demo/relator.html @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + +
+ <mods xmlns="http://www.loc.gov/mods/v3"> + <name> + <role> + <roleTerm /> + </role> + </name> + </mods> +
+ + + diff --git a/jquery.xmleditor.js b/jquery.xmleditor.js index d0fdfaa..f04b49b 100644 --- a/jquery.xmleditor.js +++ b/jquery.xmleditor.js @@ -1165,6 +1165,30 @@ $.widget( "xml.xmlEditor", { $("#" + xmlMenuHeaderPrefix + this.toString()).removeClass("disabled").data("menuItemData").enabled = true; else $("#" + xmlMenuHeaderPrefix + this.toString()).addClass("disabled").data("menuItemData").enabled = false; }); + }, + + // Finds the associated vocabulary for an xml element + getVocabulary: function(xmlElement) { + if (!this.options.vocabularies) { + return null; + } + + var matchingVocab = null; + var xmlDocument = this.xmlState.xml; + $.each(this.options.vocabularies, function(selector, vocabulary){ + // find elements in xml document that match this vocabulary's selector + var matches = $(selector, xmlDocument); + + // Check to see if our xmlElement was in the matching list + for (var i = 0; i < matches.length; i++) { + if (xmlElement.xmlNode[0] === matches[i]) { + matchingVocab = vocabulary; + return false; + } + } + }); + + return matchingVocab; } }); function AbstractXMLObject(objectType, editor) { @@ -4397,7 +4421,9 @@ XMLElement.prototype.renderChild = function(childNode, recursive) { }; XMLElement.prototype.renderText = function(childNode, prepend) { - var textNode = new XMLTextNode(childNode, this.objectType.type, this.editor); + var vocabulary = this.editor.getVocabulary(this); + + var textNode = new XMLTextNode(childNode, this.objectType.type, this.editor, vocabulary); textNode.render(this, prepend); this.nodeCount++; @@ -5064,7 +5090,7 @@ XMLTemplates.prototype.loadEvents = function(dialog) { self.processForm(); }); }; -function XMLTextNode(textNode, dataType, editor) { +function XMLTextNode(textNode, dataType, editor, vocabulary) { var textType = { text : true, type : dataType @@ -5072,6 +5098,7 @@ function XMLTextNode(textNode, dataType, editor) { this.textNode = textNode; this.xmlNode = $(textNode); + this.vocabulary = vocabulary; AbstractXMLObject.call(this, textType, editor); @@ -5133,6 +5160,11 @@ XMLTextNode.prototype.render = function(parentElement, prepend) { this.textInput = AbstractXMLObject.prototype.createElementInput.call(this, this.domNodeID + "_text", textValue, inputColumn); this.textInput.addClass('element_text'); + if (this.vocabulary) { + this.textInput.autocomplete({ + source : this.vocabulary + }); + } this.deleteButton = document.createElement('div'); this.deleteButton.className = 'xml_delete'; diff --git a/src/jquery.xmleditor.js b/src/jquery.xmleditor.js index e79ab2a..9810c85 100644 --- a/src/jquery.xmleditor.js +++ b/src/jquery.xmleditor.js @@ -1168,19 +1168,20 @@ $.widget( "xml.xmlEditor", { }, // Finds the associated vocabulary for an xml element - getVocabulary: function(self, xmlElement) { + getVocabulary: function(xmlElement) { if (!this.options.vocabularies) { return null; } var matchingVocab = null; + var xmlDocument = this.xmlState.xml; $.each(this.options.vocabularies, function(selector, vocabulary){ // find elements in xml document that match this vocabulary's selector - var matches = $(selector, self.xmlState.xml); + var matches = $(selector, xmlDocument); // Check to see if our xmlElement was in the matching list for (var i = 0; i < matches.length; i++) { - if (xmlElement.xmlNode === matches[i]) { + if (xmlElement.xmlNode[0] === matches[i]) { matchingVocab = vocabulary; return false; } diff --git a/src/xml_element.js b/src/xml_element.js index 5a519e3..d97a9f1 100644 --- a/src/xml_element.js +++ b/src/xml_element.js @@ -382,7 +382,9 @@ XMLElement.prototype.renderChild = function(childNode, recursive) { }; XMLElement.prototype.renderText = function(childNode, prepend) { - var textNode = new XMLTextNode(childNode, this.objectType.type, this.editor); + var vocabulary = this.editor.getVocabulary(this); + + var textNode = new XMLTextNode(childNode, this.objectType.type, this.editor, vocabulary); textNode.render(this, prepend); this.nodeCount++; diff --git a/src/xml_text_node.js b/src/xml_text_node.js index 52f5902..7996713 100644 --- a/src/xml_text_node.js +++ b/src/xml_text_node.js @@ -1,4 +1,4 @@ -function XMLTextNode(textNode, dataType, editor) { +function XMLTextNode(textNode, dataType, editor, vocabulary) { var textType = { text : true, type : dataType @@ -6,6 +6,7 @@ function XMLTextNode(textNode, dataType, editor) { this.textNode = textNode; this.xmlNode = $(textNode); + this.vocabulary = vocabulary; AbstractXMLObject.call(this, textType, editor); @@ -67,6 +68,11 @@ XMLTextNode.prototype.render = function(parentElement, prepend) { this.textInput = AbstractXMLObject.prototype.createElementInput.call(this, this.domNodeID + "_text", textValue, inputColumn); this.textInput.addClass('element_text'); + if (this.vocabulary) { + this.textInput.autocomplete({ + source : this.vocabulary + }); + } this.deleteButton = document.createElement('div'); this.deleteButton.className = 'xml_delete'; From 7d0ec62d2f1a93b6d00cbff92f016969071165f7 Mon Sep 17 00:00:00 2001 From: Sonoe Nakasone Date: Mon, 26 Oct 2015 12:01:18 -0400 Subject: [PATCH 3/5] added ability to load vocabs url --- demo/examples/marc_relators.json | 1 + demo/relator.html | 44 ++++++++++++---------- jquery.xmleditor.js | 63 ++++++++++++++++++++++++++++---- src/jquery.xmleditor.js | 63 ++++++++++++++++++++++++++++---- 4 files changed, 137 insertions(+), 34 deletions(-) create mode 100644 demo/examples/marc_relators.json diff --git a/demo/examples/marc_relators.json b/demo/examples/marc_relators.json new file mode 100644 index 0000000..d39ce1e --- /dev/null +++ b/demo/examples/marc_relators.json @@ -0,0 +1 @@ +[ "Abridger", "Art copyist", "Actor", "Art director", "Adapter", "Author of afterword, colophon, etc.", "Analyst", "Animator", "Annotator", "Bibliographic antecedent", "Appellee", "Appellant", "Applicant", "Author in quotations or text abstracts", "Architect", "Artistic director", "Arranger", "Artist", "Assignee", "Associated name", "Autographer", "Attributed name", "Auctioneer", "Author of dialog", "Author of introduction, etc.", "Screenwriter", "Author", "Binding designer", "Bookjacket designer", "Book designer", "Book producer", "Blurb writer", "Binder", "Bookplate designer", "Broadcaster", "Braille embosser", "Bookseller", "Caster", "Conceptor", "Choreographer", "Client", "Calligrapher", "Colorist", "Collotyper", "Commentator", "Composer", "Compositor", "Conductor", "Cinematographer", "Censor", "Contestant-appellee", "Collector", "Compiler", "Conservator", "Collection registrar", "Contestant", "Contestant-appellant", "Court governed", "Cover designer", "Copyright claimant", "Complainant-appellee", "Copyright holder", "Complainant", "Complainant-appellant", "Creator", "Correspondent", "Corrector", "Court reporter", "Consultant", "Consultant to a project", "Costume designer", "Contributor", "Contestee-appellee", "Cartographer", "Contractor", "Contestee", "Contestee-appellant", "Curator", "Commentator for written text", "Distribution place", "Defendant", "Defendant-appellee", "Defendant-appellant", "Degree granting institution", "Degree supervisor", "Dissertant", "Delineator", "Dancer", "Donor", "Depicted", "Depositor", "Draftsman", "Director", "Designer", "Distributor", "Data contributor", "Dedicatee", "Data manager", "Dedicator", "Dubious author", "Editor of compilation", "Editor of moving image work", "Editor", "Engraver", "Electrician", "Electrotyper", "Engineer", "Enacting jurisdiction", "Etcher", "Event place", "Expert", "Facsimilist", "Film distributor", "Field director", "Film editor", "Film director", "Filmmaker", "Former owner", "Film producer", "Funder", "First party", "Forger", "Geographic information specialist", "Host institution", "Honoree", "Host", "Illustrator", "Illuminator", "Inscriber", "Inventor", "Issuing body", "Instrumentalist", "Interviewee", "Interviewer", "Judge", "Jurisdiction governed", "Laboratory", "Librettist", "Laboratory director", "Lead", "Libelee-appellee", "Libelee", "Lender", "Libelee-appellant", "Lighting designer", "Libelant-appellee", "Libelant", "Libelant-appellant", "Landscape architect", "Licensee", "Licensor", "Lithographer", "Lyricist", "Music copyist", "Metadata contact", "Medium", "Manufacture place", "Manufacturer", "Moderator", "Monitor", "Marbler", "Markup editor", "Musical director", "Metal-engraver", "Minute taker", "Musician", "Narrator", "Opponent", "Originator", "Organizer", "Onscreen presenter", "Other", "Owner", "Panelist", "Patron", "Publishing director", "Publisher", "Project director", "Proofreader", "Photographer", "Platemaker", "Permitting agency", "Production manager", "Printer of plates", "Papermaker", "Puppeteer", "Praeses", "Process contact", "Production personnel", "Presenter", "Performer", "Programmer", "Printmaker", "Production company", "Producer", "Production place", "Production designer", "Printer", "Provider", "Patent applicant", "Plaintiff-appellee", "Plaintiff", "Patent holder", "Plaintiff-appellant", "Publication place", "Rubricator", "Recordist", "Recording engineer", "Addressee", "Radio director", "Redaktor", "Renderer", "Researcher", "Reviewer", "Radio producer", "Repository", "Reporter", "Responsible party", "Respondent-appellee", "Restager", "Respondent", "Restorationist", "Respondent-appellant", "Research team head", "Research team member", "Scientific advisor", "Scenarist", "Sculptor", "Scribe", "Sound designer", "Secretary", "Stage director", "Signer", "Supporting host", "Seller", "Singer", "Speaker", "Sponsor", "Second party", "Surveyor", "Set designer", "Setting", "Storyteller", "Stage manager", "Standards body", "Stereotyper", "Technical director", "Teacher", "Thesis advisor", "Television director", "Television producer", "Transcriber", "Translator", "Type designer", "Typographer", "University place", "Voice actor", "Videographer", "Writer of added commentary", "Writer of added lyrics", "Writer of accompanying material", "Writer of added text", "Woodcutter", "Wood engraver", "Writer of introduction", "Witness", "Writer of preface", "Writer of supplementary textual content" ] \ No newline at end of file diff --git a/demo/relator.html b/demo/relator.html index 2b3f04a..2955c90 100644 --- a/demo/relator.html +++ b/demo/relator.html @@ -33,35 +33,39 @@ diff --git a/jquery.xmleditor.js b/jquery.xmleditor.js index f04b49b..c162c07 100644 --- a/jquery.xmleditor.js +++ b/jquery.xmleditor.js @@ -319,6 +319,7 @@ $.widget( "xml.xmlEditor", { // Start loading the document for editing this.loadDocument(this.options.ajaxOptions, localXMLContent); + this.loadVocabularies(this.options.vocabularyConfigs); }, // Load the schema object @@ -416,6 +417,33 @@ $.widget( "xml.xmlEditor", { } }, + loadVocabularies : function(vocabularyConfigs) { + var self = this; + this.loadingVocabs = 0; + + $.each(this.options.vocabularyConfigs.vocabularies, function(vocabName, vocabInfo) { + if ("url" in vocabInfo) { + self.loadingVocabs++; + } + }); + + $.each(this.options.vocabularyConfigs.vocabularies, function(vocabName, vocabInfo) { + if ("url" in vocabInfo) { + $.ajax({ + url : vocabInfo["url"], + type : "GET", + dataType : "json" + }).done(function(data){ + vocabInfo.values = data; + self.loadingVocabs--; + if (self.loadingVocabs == 0) { + self._everythingReady(); + } + }); + } + }); + }, + _templating : function() { var dialog; var self = this; @@ -434,7 +462,7 @@ $.widget( "xml.xmlEditor", { this.undoHistory.setStateChangeEvent(function() { self.refreshDisplay(); }); - this._documentAndSchemaReady(); + this._everythingReady(); }, // Schema object loaded event @@ -444,14 +472,14 @@ $.widget( "xml.xmlEditor", { } this.schemaTree = new SchemaTree(this.schema); this.schemaTree.build(); - this._documentAndSchemaReady(); + this._everythingReady(); }, // Performs initialization of editor after rejoining document and schema loading workflows // to support asychronous/multithreaded loading - _documentAndSchemaReady : function() { + _everythingReady : function() { // Join back up asynchronous loading of document and schema - if (!this.schemaTree || !this.xmlState) + if (!this.schemaTree || !this.xmlState || this.loadingVocabs != 0) return; this.targetPrefix = this.xmlState.namespaces.getNamespacePrefix(this.options.targetNS); @@ -1172,10 +1200,11 @@ $.widget( "xml.xmlEditor", { if (!this.options.vocabularies) { return null; } - + var self = this; var matchingVocab = null; var xmlDocument = this.xmlState.xml; - $.each(this.options.vocabularies, function(selector, vocabulary){ + if (this.options.vocabularyConfigs.cssSelectors) { + $.each(this.options.vocabularyConfigs.cssSelectors, function(selector, vocabulary){ // find elements in xml document that match this vocabulary's selector var matches = $(selector, xmlDocument); @@ -1186,9 +1215,29 @@ $.widget( "xml.xmlEditor", { return false; } } + });} + + var nsResolver = function nsResolver(prefix) { + return self.options.vocabularyConfigs.xpathNamespaces[prefix] || null; + }; + nsResolver.lookupNamespaceURI = nsResolver; + + $.each(this.options.vocabularyConfigs.xpathSelectors, function(selector, vocabulary){ + // find elements in xml document that match this vocabulary's selector + var matchesIterate = xmlDocument[0].evaluate(selector, xmlDocument[0], nsResolver, null, null); + + // Check to see if our xmlElement was in the matching 0list + var match = matchesIterate.iterateNext() + while (match) { + if (xmlElement.xmlNode[0] === match) { + matchingVocab = vocabulary; + return false; + } + match = matchesIterate.iterateNext(); + } }); - return matchingVocab; + return self.options.vocabularyConfigs.vocabularies[matchingVocab]["values"]; } }); function AbstractXMLObject(objectType, editor) { diff --git a/src/jquery.xmleditor.js b/src/jquery.xmleditor.js index 9810c85..7213889 100644 --- a/src/jquery.xmleditor.js +++ b/src/jquery.xmleditor.js @@ -319,6 +319,7 @@ $.widget( "xml.xmlEditor", { // Start loading the document for editing this.loadDocument(this.options.ajaxOptions, localXMLContent); + this.loadVocabularies(this.options.vocabularyConfigs); }, // Load the schema object @@ -416,6 +417,33 @@ $.widget( "xml.xmlEditor", { } }, + loadVocabularies : function(vocabularyConfigs) { + var self = this; + this.loadingVocabs = 0; + + $.each(this.options.vocabularyConfigs.vocabularies, function(vocabName, vocabInfo) { + if ("url" in vocabInfo) { + self.loadingVocabs++; + } + }); + + $.each(this.options.vocabularyConfigs.vocabularies, function(vocabName, vocabInfo) { + if ("url" in vocabInfo) { + $.ajax({ + url : vocabInfo["url"], + type : "GET", + dataType : "json" + }).done(function(data){ + vocabInfo.values = data; + self.loadingVocabs--; + if (self.loadingVocabs == 0) { + self._everythingReady(); + } + }); + } + }); + }, + _templating : function() { var dialog; var self = this; @@ -434,7 +462,7 @@ $.widget( "xml.xmlEditor", { this.undoHistory.setStateChangeEvent(function() { self.refreshDisplay(); }); - this._documentAndSchemaReady(); + this._everythingReady(); }, // Schema object loaded event @@ -444,14 +472,14 @@ $.widget( "xml.xmlEditor", { } this.schemaTree = new SchemaTree(this.schema); this.schemaTree.build(); - this._documentAndSchemaReady(); + this._everythingReady(); }, // Performs initialization of editor after rejoining document and schema loading workflows // to support asychronous/multithreaded loading - _documentAndSchemaReady : function() { + _everythingReady : function() { // Join back up asynchronous loading of document and schema - if (!this.schemaTree || !this.xmlState) + if (!this.schemaTree || !this.xmlState || this.loadingVocabs != 0) return; this.targetPrefix = this.xmlState.namespaces.getNamespacePrefix(this.options.targetNS); @@ -1172,10 +1200,11 @@ $.widget( "xml.xmlEditor", { if (!this.options.vocabularies) { return null; } - + var self = this; var matchingVocab = null; var xmlDocument = this.xmlState.xml; - $.each(this.options.vocabularies, function(selector, vocabulary){ + if (this.options.vocabularyConfigs.cssSelectors) { + $.each(this.options.vocabularyConfigs.cssSelectors, function(selector, vocabulary){ // find elements in xml document that match this vocabulary's selector var matches = $(selector, xmlDocument); @@ -1186,8 +1215,28 @@ $.widget( "xml.xmlEditor", { return false; } } + });} + + var nsResolver = function nsResolver(prefix) { + return self.options.vocabularyConfigs.xpathNamespaces[prefix] || null; + }; + nsResolver.lookupNamespaceURI = nsResolver; + + $.each(this.options.vocabularyConfigs.xpathSelectors, function(selector, vocabulary){ + // find elements in xml document that match this vocabulary's selector + var matchesIterate = xmlDocument[0].evaluate(selector, xmlDocument[0], nsResolver, null, null); + + // Check to see if our xmlElement was in the matching 0list + var match = matchesIterate.iterateNext() + while (match) { + if (xmlElement.xmlNode[0] === match) { + matchingVocab = vocabulary; + return false; + } + match = matchesIterate.iterateNext(); + } }); - return matchingVocab; + return self.options.vocabularyConfigs.vocabularies[matchingVocab]["values"]; } }); From b09e22598c2fea8249dd726f791fe2a44d1574b9 Mon Sep 17 00:00:00 2001 From: Sonoe Nakasone Date: Fri, 30 Oct 2015 15:23:26 -0400 Subject: [PATCH 4/5] Ben added so many things to make it work better. Thanks ben. He made it so that instead of returning the values of the vocabulary, it now returns all the little thingies inside the vocabulary like the values or the url if there is one and the type. That way, if the type is something like select, then it can become a drop down. or if the type is something like query, it could query things from a url in real time. So smart. YOSH. --- jquery.xmleditor.js | 65 +++++++++++++++++++++++------------------ src/jquery.xmleditor.js | 61 +++++++++++++++++++++----------------- src/xml_text_node.js | 4 +-- 3 files changed, 74 insertions(+), 56 deletions(-) diff --git a/jquery.xmleditor.js b/jquery.xmleditor.js index c162c07..c47cf38 100644 --- a/jquery.xmleditor.js +++ b/jquery.xmleditor.js @@ -317,9 +317,11 @@ $.widget( "xml.xmlEditor", { }); } + // Load any external vocabularies + this.loadVocabularies(this.options.vocabularyConfigs); + // Start loading the document for editing this.loadDocument(this.options.ajaxOptions, localXMLContent); - this.loadVocabularies(this.options.vocabularyConfigs); }, // Load the schema object @@ -1197,7 +1199,7 @@ $.widget( "xml.xmlEditor", { // Finds the associated vocabulary for an xml element getVocabulary: function(xmlElement) { - if (!this.options.vocabularies) { + if (!this.options.vocabularyConfigs) { return null; } var self = this; @@ -1205,39 +1207,46 @@ $.widget( "xml.xmlEditor", { var xmlDocument = this.xmlState.xml; if (this.options.vocabularyConfigs.cssSelectors) { $.each(this.options.vocabularyConfigs.cssSelectors, function(selector, vocabulary){ - // find elements in xml document that match this vocabulary's selector - var matches = $(selector, xmlDocument); - - // Check to see if our xmlElement was in the matching list - for (var i = 0; i < matches.length; i++) { - if (xmlElement.xmlNode[0] === matches[i]) { - matchingVocab = vocabulary; - return false; + // find elements in xml document that match this vocabulary's selector + var matches = $(selector, xmlDocument); + + // Check to see if our xmlElement was in the matching list + for (var i = 0; i < matches.length; i++) { + if (xmlElement.xmlNode[0] === matches[i]) { + matchingVocab = vocabulary; + return false; + } } - } - });} + }); + } var nsResolver = function nsResolver(prefix) { return self.options.vocabularyConfigs.xpathNamespaces[prefix] || null; }; nsResolver.lookupNamespaceURI = nsResolver; - $.each(this.options.vocabularyConfigs.xpathSelectors, function(selector, vocabulary){ - // find elements in xml document that match this vocabulary's selector - var matchesIterate = xmlDocument[0].evaluate(selector, xmlDocument[0], nsResolver, null, null); - - // Check to see if our xmlElement was in the matching 0list - var match = matchesIterate.iterateNext() - while (match) { - if (xmlElement.xmlNode[0] === match) { - matchingVocab = vocabulary; - return false; + if (this.options.vocabularyConfigs.xpathSelectors) { + $.each(this.options.vocabularyConfigs.xpathSelectors, function(selector, vocabulary){ + // find elements in xml document that match this vocabulary's selector + var matchesIterate = xmlDocument[0].evaluate(selector, xmlDocument[0], nsResolver, null, null); + + // Check to see if our xmlElement was in the matching 0list + var match = matchesIterate.iterateNext() + while (match) { + if (xmlElement.xmlNode[0] === match) { + matchingVocab = vocabulary; + return false; + } + match = matchesIterate.iterateNext(); } - match = matchesIterate.iterateNext(); - } - }); + }); + } + + if (!matchingVocab || !(matchingVocab in this.options.vocabularyConfigs.vocabularies)) { + return null; + } - return self.options.vocabularyConfigs.vocabularies[matchingVocab]["values"]; + return this.options.vocabularyConfigs.vocabularies[matchingVocab]; } }); function AbstractXMLObject(objectType, editor) { @@ -5209,9 +5218,9 @@ XMLTextNode.prototype.render = function(parentElement, prepend) { this.textInput = AbstractXMLObject.prototype.createElementInput.call(this, this.domNodeID + "_text", textValue, inputColumn); this.textInput.addClass('element_text'); - if (this.vocabulary) { + if (this.vocabulary && this.vocabulary.values) { this.textInput.autocomplete({ - source : this.vocabulary + source : this.vocabulary.values }); } diff --git a/src/jquery.xmleditor.js b/src/jquery.xmleditor.js index 7213889..351a085 100644 --- a/src/jquery.xmleditor.js +++ b/src/jquery.xmleditor.js @@ -317,9 +317,11 @@ $.widget( "xml.xmlEditor", { }); } + // Load any external vocabularies + this.loadVocabularies(this.options.vocabularyConfigs); + // Start loading the document for editing this.loadDocument(this.options.ajaxOptions, localXMLContent); - this.loadVocabularies(this.options.vocabularyConfigs); }, // Load the schema object @@ -1197,7 +1199,7 @@ $.widget( "xml.xmlEditor", { // Finds the associated vocabulary for an xml element getVocabulary: function(xmlElement) { - if (!this.options.vocabularies) { + if (!this.options.vocabularyConfigs) { return null; } var self = this; @@ -1205,38 +1207,45 @@ $.widget( "xml.xmlEditor", { var xmlDocument = this.xmlState.xml; if (this.options.vocabularyConfigs.cssSelectors) { $.each(this.options.vocabularyConfigs.cssSelectors, function(selector, vocabulary){ - // find elements in xml document that match this vocabulary's selector - var matches = $(selector, xmlDocument); - - // Check to see if our xmlElement was in the matching list - for (var i = 0; i < matches.length; i++) { - if (xmlElement.xmlNode[0] === matches[i]) { - matchingVocab = vocabulary; - return false; + // find elements in xml document that match this vocabulary's selector + var matches = $(selector, xmlDocument); + + // Check to see if our xmlElement was in the matching list + for (var i = 0; i < matches.length; i++) { + if (xmlElement.xmlNode[0] === matches[i]) { + matchingVocab = vocabulary; + return false; + } } - } - });} + }); + } var nsResolver = function nsResolver(prefix) { return self.options.vocabularyConfigs.xpathNamespaces[prefix] || null; }; nsResolver.lookupNamespaceURI = nsResolver; - $.each(this.options.vocabularyConfigs.xpathSelectors, function(selector, vocabulary){ - // find elements in xml document that match this vocabulary's selector - var matchesIterate = xmlDocument[0].evaluate(selector, xmlDocument[0], nsResolver, null, null); - - // Check to see if our xmlElement was in the matching 0list - var match = matchesIterate.iterateNext() - while (match) { - if (xmlElement.xmlNode[0] === match) { - matchingVocab = vocabulary; - return false; + if (this.options.vocabularyConfigs.xpathSelectors) { + $.each(this.options.vocabularyConfigs.xpathSelectors, function(selector, vocabulary){ + // find elements in xml document that match this vocabulary's selector + var matchesIterate = xmlDocument[0].evaluate(selector, xmlDocument[0], nsResolver, null, null); + + // Check to see if our xmlElement was in the matching 0list + var match = matchesIterate.iterateNext() + while (match) { + if (xmlElement.xmlNode[0] === match) { + matchingVocab = vocabulary; + return false; + } + match = matchesIterate.iterateNext(); } - match = matchesIterate.iterateNext(); - } - }); + }); + } + + if (!matchingVocab || !(matchingVocab in this.options.vocabularyConfigs.vocabularies)) { + return null; + } - return self.options.vocabularyConfigs.vocabularies[matchingVocab]["values"]; + return this.options.vocabularyConfigs.vocabularies[matchingVocab]; } }); diff --git a/src/xml_text_node.js b/src/xml_text_node.js index 7996713..ec7612f 100644 --- a/src/xml_text_node.js +++ b/src/xml_text_node.js @@ -68,9 +68,9 @@ XMLTextNode.prototype.render = function(parentElement, prepend) { this.textInput = AbstractXMLObject.prototype.createElementInput.call(this, this.domNodeID + "_text", textValue, inputColumn); this.textInput.addClass('element_text'); - if (this.vocabulary) { + if (this.vocabulary && this.vocabulary.values) { this.textInput.autocomplete({ - source : this.vocabulary + source : this.vocabulary.values }); } From 81b00fc39404c7d6df17cc2cd4566c3d33fcc580 Mon Sep 17 00:00:00 2001 From: Ben Pennell Date: Mon, 2 Nov 2015 15:15:28 -0500 Subject: [PATCH 5/5] Check for missing vocab config during loading --- jquery.xmleditor.js | 4 ++++ src/jquery.xmleditor.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/jquery.xmleditor.js b/jquery.xmleditor.js index c47cf38..b367097 100644 --- a/jquery.xmleditor.js +++ b/jquery.xmleditor.js @@ -423,6 +423,10 @@ $.widget( "xml.xmlEditor", { var self = this; this.loadingVocabs = 0; + if (!this.options.vocabularyConfigs || !this.options.vocabularyConfigs.vocabularies) { + return; + } + $.each(this.options.vocabularyConfigs.vocabularies, function(vocabName, vocabInfo) { if ("url" in vocabInfo) { self.loadingVocabs++; diff --git a/src/jquery.xmleditor.js b/src/jquery.xmleditor.js index 351a085..6dabdad 100644 --- a/src/jquery.xmleditor.js +++ b/src/jquery.xmleditor.js @@ -423,6 +423,10 @@ $.widget( "xml.xmlEditor", { var self = this; this.loadingVocabs = 0; + if (!this.options.vocabularyConfigs || !this.options.vocabularyConfigs.vocabularies) { + return; + } + $.each(this.options.vocabularyConfigs.vocabularies, function(vocabName, vocabInfo) { if ("url" in vocabInfo) { self.loadingVocabs++;