From 3bd9fee895065ad467f40f9a72f5c33181ac8126 Mon Sep 17 00:00:00 2001 From: Aga Date: Tue, 3 Sep 2024 14:24:07 +0100 Subject: [PATCH 1/9] use standard doaj renderer --- portality/static/js/doaj.fieldrender.edges.js | 6 +- portality/static/js/formulaic.js | 600 +++++++++--------- .../application_form/js/_form_js.html | 1 + 3 files changed, 305 insertions(+), 302 deletions(-) diff --git a/portality/static/js/doaj.fieldrender.edges.js b/portality/static/js/doaj.fieldrender.edges.js index 09d172346d..a49c63ea6b 100644 --- a/portality/static/js/doaj.fieldrender.edges.js +++ b/portality/static/js/doaj.fieldrender.edges.js @@ -367,10 +367,12 @@ $.extend(true, doaj, { subjectBrowser: function (params) { var tree = params.tree; var hideEmpty = edges.getParam(params.hideEmpty, false); + var id = params.id ? params.id : "subject"; + var category = params.category ? params.category : "facet"; return edges.newTreeBrowser({ - id: "subject", - category: "facet", + id: id, + category: category, field: "index.schema_codes_tree.exact", tree: function (tree) { function recurse(ctx) { diff --git a/portality/static/js/formulaic.js b/portality/static/js/formulaic.js index 0c5932c3ce..35a5f02c11 100644 --- a/portality/static/js/formulaic.js +++ b/portality/static/js/formulaic.js @@ -773,307 +773,306 @@ var formulaic = { this.sourceInput.trigger("change"); this.edge.cycle(); }; - }, - - newSubjectBrowser : function(params) { - return edges.instantiate(formulaic.edges.SubjectBrowser, params, edges.newRenderer); - }, - SubjectBrowser : function(params) { - this.title = edges.getParam(params.title, ""); - - this.hideEmpty = edges.getParam(params.hideEmpty, false); - - this.expanded = []; - - this.lastScroll = 0; - - this.namespace = "formulaic-subject-browser"; - - this.draw = function() { - // for convenient short references ... - var st = this.component.syncTree; - var namespace = this.namespace; - // var that = this; - - // var checkboxClass = edges.css_classes(namespace, "selector", this); - // var countClass = edges.css_classes(namespace, "count", this); - - var treeReport = this._renderTree({tree: st, selectedPathOnly: false, showOneLevel: true}); - var treeFrag = treeReport.frag; - - if (treeFrag === "") { - treeFrag = "Loading..."; - } - - var toggleId = edges.css_id(namespace, "toggle", this); - var resultsId = edges.css_id(namespace, "results", this); - var searchId = edges.css_id(namespace, "search", this); - var filteredId = edges.css_id(namespace, "filtered", this); - var mainListId = edges.css_id(namespace, "main", this); - - var toggle = ""; - if (this.togglable) { - toggle = ''; - } - var frag = '

' + this.title + toggle + '

\ - '; - - // substitute in the component parts - frag = frag.replace(/{{FILTERS}}/g, treeFrag); - - // now render it into the page - this.component.context.html(frag); - feather.replace(); - - var mainListSelector = edges.css_id_selector(namespace, "main", this); - this.component.jq(mainListSelector).scrollTop(this.lastScroll); - - var checkboxSelector = edges.css_class_selector(namespace, "selector", this); - edges.on(checkboxSelector, "change", this, "filterToggle"); - - var searchSelector = edges.css_id_selector(namespace, "search", this); - edges.on(searchSelector, "keyup", this, "filterSubjects"); - - var fieldSelector = edges.css_class_selector(namespace, "field-toggle", this); - edges.on(fieldSelector, "click", this, "fieldToggle"); - }; - - this._renderTree = function(params) { - var st = edges.getParam(params.tree, []); - var selectedPathOnly = edges.getParam(params.selectedPathOnly, true); - var showOneLevel = edges.getParam(params.showOneLevel, true); - var that = this; - - var checkboxClass = edges.css_classes(this.namespace, "selector", this); - var toggleClass = edges.css_classes(that.namespace, "field-toggle", this); - - function renderEntry(entry) { - if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { - return ""; - } - - var id = edges.safeId(entry.value); - var checked = ""; - if (entry.selected) { - checked = ' checked="checked" '; - } - - // the various rules to do with how this will toggle. - // - whether the toggle is linked -> only when clickng it will have an effect - // - whether the thing is togglable at all -> only when there are children - var toggle = ""; - var chevron = ""; - var togglable = false; - if (entry.children) { - chevron = "chevron-right"; - togglable = true; - if (entry.expanded) { - chevron = "chevron-down"; - } - if (entry.selected) { - togglable = false; - } - } - - if (togglable) { - toggle = ''; - toggle = '' + toggle + 'Toggle this subject'; - } - // FIXME: putting this in for the moment, just so we can use it in dev - // var count = ' (' + entry.count + '/' + entry.childCount + ')'; - var count = ""; - - var frag = '\ - '; - - return frag; - } - - function recurse(tree) { - var selected = tree; - - // first check to see if there are any elements at this level that are selected. If there are, - // that is the only element that we'll render - if (selectedPathOnly) { - for (var i = 0; i < tree.length; i++) { - var entry = tree[i]; - if (entry.selected) { - selected = [entry]; - break; - } - } - } - - // now go through either this tree level or just the selected elements, and render the relevant - // bits of the sub-tree - var anySelected = false; - var rFrag = ""; - for (var i = 0; i < selected.length; i++) { - var entry = selected[i]; - entry.expanded = $.inArray(entry.value, that.expanded) > -1; - var entryFrag = renderEntry(entry); - if (entryFrag === "") { - continue; - } - if (entry.selected) { - anySelected = true; - } - if (entry.children) { - var childReport = recurse(entry.children); - if (childReport.anySelected) { - anySelected = true; - } - // only attach the children frag if, first any of these are true: - // - one of the children is selected - // - the entry itself is selected - // - we don't want to only show the selected path - // - the entry has been expanded - if (!selectedPathOnly || childReport.anySelected || entry.selected || entry.expanded) { - // Then, another level (separated out to save my brain from the tortuous logic) - // only attach the children frag if, any of these are true: - // - the entry or one of its children is selected - // - we want to show more than one level at a time - // - the entry has been expanded - if (childReport.anySelected || entry.selected || !showOneLevel || entry.expanded) { - var cFrag = childReport.frag; - if (cFrag !== "") { - entryFrag += ''; - } - } - } - } - - rFrag += '
  • '; - rFrag += entryFrag; - rFrag += '
  • '; - } - return {frag : rFrag, anySelected: anySelected}; - } - - return recurse(st); - }; - - this.fieldToggle = function(element) { - var value = this.component.jq(element).attr("data-value"); - - var existing = $.inArray(value, this.expanded); - if (existing > -1) { - this.expanded.splice(existing, 1); - } else { - this.expanded.push(value); - } - - var mainListSelector = edges.css_id_selector(this.namespace, "main", this); - this.lastScroll = this.component.jq(mainListSelector).scrollTop(); - this.component.edge.cycle(); - }; - - this.filterToggle = function(element) { - var mainListSelector = edges.css_id_selector(this.namespace, "main", this); - this.lastScroll = this.component.jq(mainListSelector).scrollTop(); - - // var filter_id = this.component.jq(element).attr("id"); - var checked = this.component.jq(element).is(":checked"); - var value = this.component.jq(element).attr("data-value"); - if (checked) { - this.component.addFilter({value: value}); - } else { - this.component.removeFilter({value: value}); - } - }; - - this.filterSubjects = function(element) { - var st = this.component.syncTree; - var term = $(element).val(); - var that = this; - - var filterSelector = edges.css_id_selector(this.namespace, "filtered", this); - var mainSelector = edges.css_id_selector(this.namespace, "main", this); - var filterEl = this.component.jq(filterSelector); - var mainEl = this.component.jq(mainSelector); - - if (term === "") { - filterEl.html(""); - filterEl.hide(); - mainEl.show(); - return; - } - if (term.length < 3) { - filterEl.html("
  • Enter 3 characters or more to search
  • "); - filterEl.show(); - mainEl.hide(); - return; - } - term = term.toLowerCase(); - - function entryMatch(entry) { - if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { - return false; - } - - var matchTerm = entry.index; - var includes = matchTerm.includes(term); - if (includes) { - var idx = matchTerm.indexOf(term); - var display = entry.display; - return display.substring(0, idx) + "" + display.substring(idx, idx + term.length) + "" + display.substring(idx + term.length); - } - } - - function recurse(tree) { - var filteredLayer = []; - for (var i = 0; i < tree.length; i++) { - var entry = tree[i]; - var childReport = []; - if (entry.children) { - childReport = recurse(entry.children); - } - var selfMatch = entryMatch(entry); - if (selfMatch || childReport.length > 0) { - var newEntry = $.extend({}, entry); - delete newEntry.children; - if (selfMatch) { - newEntry.display = selfMatch; - } - if (childReport.length > 0) { - newEntry.children = childReport; - } - filteredLayer.push(newEntry); - } - } - return filteredLayer; - } - - var filtered = recurse(st); - - if (filtered.length > 0) { - var displayReport = this._renderTree({tree: filtered, selectedPathOnly: false, showOneLevel: false}); - - filterEl.html(displayReport.frag); - mainEl.hide(); - filterEl.show(); - - var checkboxSelector = edges.css_class_selector(this.namespace, "selector", this); - edges.on(checkboxSelector, "change", this, "filterToggle"); - } else { - filterEl.html("
  • No subjects match your search
  • "); - mainEl.hide(); - filterEl.show(); - } - - }; - }, + } + // + // newSubjectBrowser : function(params) { + // return edges.instantiate(formulaic.edges.SubjectBrowser, params, edges.newRenderer); + // }, + // SubjectBrowser : function(params) { + // this.title = edges.getParam(params.title, ""); + // + // this.hideEmpty = edges.getParam(params.hideEmpty, false); + // + // this.expanded = []; + // + // this.lastScroll = 0; + // + // this.namespace = "formulaic-subject-browser"; + // + // this.draw = function() { + // // for convenient short references ... + // var st = this.component.syncTree; + // var namespace = this.namespace; + // // var that = this; + // + // // var checkboxClass = edges.css_classes(namespace, "selector", this); + // // var countClass = edges.css_classes(namespace, "count", this); + // + // var treeReport = this._renderTree({tree: st, selectedPathOnly: false, showOneLevel: true}); + // var treeFrag = treeReport.frag; + // + // if (treeFrag === "") { + // treeFrag = "Loading..."; + // } + // + // var toggleId = edges.css_id(namespace, "toggle", this); + // var resultsId = edges.css_id(namespace, "results", this); + // var searchId = edges.css_id(namespace, "search", this); + // var filteredId = edges.css_id(namespace, "filtered", this); + // var mainListId = edges.css_id(namespace, "main", this); + // + // var toggle = ""; + // if (this.togglable) { + // toggle = ''; + // } + // var frag = '

    ' + this.title + toggle + '

    \ + // '; + // + // // substitute in the component parts + // frag = frag.replace(/{{FILTERS}}/g, treeFrag); + // + // // now render it into the page + // this.component.context.html(frag); + // feather.replace(); + // + // var mainListSelector = edges.css_id_selector(namespace, "main", this); + // this.component.jq(mainListSelector).scrollTop(this.lastScroll); + // + // var checkboxSelector = edges.css_class_selector(namespace, "selector", this); + // edges.on(checkboxSelector, "change", this, "filterToggle"); + // + // var searchSelector = edges.css_id_selector(namespace, "search", this); + // edges.on(searchSelector, "keyup", this, "filterSubjects"); + // + // var fieldSelector = edges.css_class_selector(namespace, "field-toggle", this); + // edges.on(fieldSelector, "click", this, "fieldToggle"); + // }; + // + // this._renderTree = function(params) { + // var st = edges.getParam(params.tree, []); + // var selectedPathOnly = edges.getParam(params.selectedPathOnly, true); + // var showOneLevel = edges.getParam(params.showOneLevel, true); + // var that = this; + // + // var checkboxClass = edges.css_classes(this.namespace, "selector", this); + // var toggleClass = edges.css_classes(that.namespace, "field-toggle", this); + // + // function renderEntry(entry) { + // if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { + // return ""; + // } + // + // var id = edges.safeId(entry.value); + // var checked = ""; + // if (entry.selected) { + // checked = ' checked="checked" '; + // } + // + // // the various rules to do with how this will toggle. + // // - whether the toggle is linked -> only when clickng it will have an effect + // // - whether the thing is togglable at all -> only when there are children + // var toggle = ""; + // var chevron = ""; + // var togglable = false; + // if (entry.children) { + // chevron = "chevron-right"; + // togglable = true; + // if (entry.expanded) { + // chevron = "chevron-down"; + // } + // if (entry.selected) { + // togglable = false; + // } + // } + // + // if (togglable) { + // toggle = ''; + // toggle = '' + toggle + 'Toggle this subject'; + // } + // // FIXME: putting this in for the moment, just so we can use it in dev + // // var count = ' (' + entry.count + '/' + entry.childCount + ')'; + // var count = ""; + // + // var frag = '\ + // '; + // + // return frag; + // } + // + // function recurse(tree) { + // var selected = tree; + // + // // first check to see if there are any elements at this level that are selected. If there are, + // // that is the only element that we'll render + // if (selectedPathOnly) { + // for (var i = 0; i < tree.length; i++) { + // var entry = tree[i]; + // if (entry.selected) { + // selected = [entry]; + // break; + // } + // } + // } + // + // // now go through either this tree level or just the selected elements, and render the relevant + // // bits of the sub-tree + // var anySelected = false; + // var rFrag = ""; + // for (var i = 0; i < selected.length; i++) { + // var entry = selected[i]; + // entry.expanded = $.inArray(entry.value, that.expanded) > -1; + // var entryFrag = renderEntry(entry); + // if (entryFrag === "") { + // continue; + // } + // if (entry.selected) { + // anySelected = true; + // } + // if (entry.children) { + // var childReport = recurse(entry.children); + // if (childReport.anySelected) { + // anySelected = true; + // } + // // only attach the children frag if, first any of these are true: + // // - one of the children is selected + // // - the entry itself is selected + // // - we don't want to only show the selected path + // // - the entry has been expanded + // if (!selectedPathOnly || childReport.anySelected || entry.selected || entry.expanded) { + // // Then, another level (separated out to save my brain from the tortuous logic) + // // only attach the children frag if, any of these are true: + // // - the entry or one of its children is selected + // // - we want to show more than one level at a time + // // - the entry has been expanded + // if (childReport.anySelected || entry.selected || !showOneLevel || entry.expanded) { + // var cFrag = childReport.frag; + // if (cFrag !== "") { + // entryFrag += ''; + // } + // } + // } + // } + // + // rFrag += '
  • '; + // rFrag += entryFrag; + // rFrag += '
  • '; + // } + // return {frag : rFrag, anySelected: anySelected}; + // } + // + // return recurse(st); + // }; + // + // this.fieldToggle = function(element) { + // var value = this.component.jq(element).attr("data-value"); + // + // var existing = $.inArray(value, this.expanded); + // if (existing > -1) { + // this.expanded.splice(existing, 1); + // } else { + // this.expanded.push(value); + // } + // + // var mainListSelector = edges.css_id_selector(this.namespace, "main", this); + // this.lastScroll = this.component.jq(mainListSelector).scrollTop(); + // this.component.edge.cycle(); + // }; + // + // this.filterToggle = function(element) { + // var mainListSelector = edges.css_id_selector(this.namespace, "main", this); + // this.lastScroll = this.component.jq(mainListSelector).scrollTop(); + // + // // var filter_id = this.component.jq(element).attr("id"); + // var checked = this.component.jq(element).is(":checked"); + // var value = this.component.jq(element).attr("data-value"); + // if (checked) { + // this.component.addFilter({value: value}); + // } else { + // this.component.removeFilter({value: value}); + // } + // }; + // + // this.filterSubjects = function(element) { + // var st = this.component.syncTree; + // var term = $(element).val(); + // var that = this; + // + // var filterSelector = edges.css_id_selector(this.namespace, "filtered", this); + // var mainSelector = edges.css_id_selector(this.namespace, "main", this); + // var filterEl = this.component.jq(filterSelector); + // var mainEl = this.component.jq(mainSelector); + // + // if (term === "") { + // filterEl.html(""); + // filterEl.hide(); + // mainEl.show(); + // return; + // } + // if (term.length < 3) { + // filterEl.html("
  • Enter 3 characters or more to search
  • "); + // filterEl.show(); + // mainEl.hide(); + // return; + // } + // term = term.toLowerCase(); + // + // function entryMatch(entry) { + // if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { + // return false; + // } + // + // var matchTerm = entry.index; + // var includes = matchTerm.includes(term); + // if (includes) { + // var idx = matchTerm.indexOf(term); + // var display = entry.display; + // return display.substring(0, idx) + "" + display.substring(idx, idx + term.length) + "" + display.substring(idx + term.length); + // } + // } + // + // function recurse(tree) { + // var filteredLayer = []; + // for (var i = 0; i < tree.length; i++) { + // var entry = tree[i]; + // var childReport = []; + // if (entry.children) { + // childReport = recurse(entry.children); + // } + // var selfMatch = entryMatch(entry); + // if (selfMatch || childReport.length > 0) { + // var newEntry = $.extend({}, entry); + // delete newEntry.children; + // if (selfMatch) { + // newEntry.display = selfMatch; + // } + // if (childReport.length > 0) { + // newEntry.children = childReport; + // } + // filteredLayer.push(newEntry); + // } + // } + // return filteredLayer; + // } + // + // var filtered = recurse(st); + // + // if (filtered.length > 0) { + // var displayReport = this._renderTree({tree: filtered, selectedPathOnly: false, showOneLevel: false}); + // + // filterEl.html(displayReport.frag); + // mainEl.hide(); + // filterEl.show(); + // + // var checkboxSelector = edges.css_class_selector(this.namespace, "selector", this); + // edges.on(checkboxSelector, "change", this, "filterToggle"); + // } else { + // filterEl.html("
  • No subjects match your search
  • "); + // mainEl.hide(); + // filterEl.show(); + // } + // + // }; + // }, }, widgets : { - _select2_shift_focus: function(){ let id = $(this).attr("id"); console.log("focused on " + id); @@ -1189,6 +1188,7 @@ var formulaic = { newSubjectTree : function(params) { return edges.instantiate(formulaic.widgets.SubjectTree, params); + // return edges.instantiate(formulaic.widgets.SubjectTree, params); }, SubjectTree : function(params) { this.fieldDef = params.fieldDef; @@ -1201,7 +1201,6 @@ var formulaic = { this.init = function() { var tree = doaj.af.lccTree; - var containerId = edges.css_id(this.ns, "container"); var containerSelector = edges.css_id_selector(this.ns, "container"); var widgetId = edges.css_id(this.ns, this.fieldDef.name); @@ -1226,6 +1225,7 @@ var formulaic = { `); + var subjectBrowser = formulaic.edges.newTreeBrowser({ id: widgetId, sourceInput: this.input, @@ -1262,7 +1262,7 @@ var formulaic = { nodeIndex : function(node) { return node.display.toLowerCase(); }, - renderer: formulaic.edges.newSubjectBrowser({ + renderer: doaj.renderers.newSubjectBrowser({ title: "Subjects" }) }); diff --git a/portality/templates/application_form/js/_form_js.html b/portality/templates/application_form/js/_form_js.html index 323b90b656..1ee02b0ea3 100644 --- a/portality/templates/application_form/js/_form_js.html +++ b/portality/templates/application_form/js/_form_js.html @@ -4,6 +4,7 @@ {# #} + {% if lcc_tree %} From cfacb3f2768d37a70615e9e86fcba3cea78d0e28 Mon Sep 17 00:00:00 2001 From: Aga Date: Tue, 3 Sep 2024 14:47:33 +0100 Subject: [PATCH 2/9] use edges helper rather than the ternary operator --- portality/static/js/doaj.fieldrender.edges.js | 4 +- portality/static/js/formulaic.js | 592 +++++++++--------- 2 files changed, 298 insertions(+), 298 deletions(-) diff --git a/portality/static/js/doaj.fieldrender.edges.js b/portality/static/js/doaj.fieldrender.edges.js index a49c63ea6b..e28653030c 100644 --- a/portality/static/js/doaj.fieldrender.edges.js +++ b/portality/static/js/doaj.fieldrender.edges.js @@ -367,8 +367,8 @@ $.extend(true, doaj, { subjectBrowser: function (params) { var tree = params.tree; var hideEmpty = edges.getParam(params.hideEmpty, false); - var id = params.id ? params.id : "subject"; - var category = params.category ? params.category : "facet"; + var id = edges.getParam(params.id, "subject"); + var category = edges.getParam(params.category, "facet"); return edges.newTreeBrowser({ id: id, diff --git a/portality/static/js/formulaic.js b/portality/static/js/formulaic.js index 35a5f02c11..9f9c087dac 100644 --- a/portality/static/js/formulaic.js +++ b/portality/static/js/formulaic.js @@ -774,302 +774,302 @@ var formulaic = { this.edge.cycle(); }; } - // - // newSubjectBrowser : function(params) { - // return edges.instantiate(formulaic.edges.SubjectBrowser, params, edges.newRenderer); - // }, - // SubjectBrowser : function(params) { - // this.title = edges.getParam(params.title, ""); - // - // this.hideEmpty = edges.getParam(params.hideEmpty, false); - // - // this.expanded = []; - // - // this.lastScroll = 0; - // - // this.namespace = "formulaic-subject-browser"; - // - // this.draw = function() { - // // for convenient short references ... - // var st = this.component.syncTree; - // var namespace = this.namespace; - // // var that = this; - // - // // var checkboxClass = edges.css_classes(namespace, "selector", this); - // // var countClass = edges.css_classes(namespace, "count", this); - // - // var treeReport = this._renderTree({tree: st, selectedPathOnly: false, showOneLevel: true}); - // var treeFrag = treeReport.frag; - // - // if (treeFrag === "") { - // treeFrag = "Loading..."; - // } - // - // var toggleId = edges.css_id(namespace, "toggle", this); - // var resultsId = edges.css_id(namespace, "results", this); - // var searchId = edges.css_id(namespace, "search", this); - // var filteredId = edges.css_id(namespace, "filtered", this); - // var mainListId = edges.css_id(namespace, "main", this); - // - // var toggle = ""; - // if (this.togglable) { - // toggle = ''; - // } - // var frag = '

    ' + this.title + toggle + '

    \ - // '; - // - // // substitute in the component parts - // frag = frag.replace(/{{FILTERS}}/g, treeFrag); - // - // // now render it into the page - // this.component.context.html(frag); - // feather.replace(); - // - // var mainListSelector = edges.css_id_selector(namespace, "main", this); - // this.component.jq(mainListSelector).scrollTop(this.lastScroll); - // - // var checkboxSelector = edges.css_class_selector(namespace, "selector", this); - // edges.on(checkboxSelector, "change", this, "filterToggle"); - // - // var searchSelector = edges.css_id_selector(namespace, "search", this); - // edges.on(searchSelector, "keyup", this, "filterSubjects"); - // - // var fieldSelector = edges.css_class_selector(namespace, "field-toggle", this); - // edges.on(fieldSelector, "click", this, "fieldToggle"); - // }; - // - // this._renderTree = function(params) { - // var st = edges.getParam(params.tree, []); - // var selectedPathOnly = edges.getParam(params.selectedPathOnly, true); - // var showOneLevel = edges.getParam(params.showOneLevel, true); - // var that = this; - // - // var checkboxClass = edges.css_classes(this.namespace, "selector", this); - // var toggleClass = edges.css_classes(that.namespace, "field-toggle", this); - // - // function renderEntry(entry) { - // if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { - // return ""; - // } - // - // var id = edges.safeId(entry.value); - // var checked = ""; - // if (entry.selected) { - // checked = ' checked="checked" '; - // } - // - // // the various rules to do with how this will toggle. - // // - whether the toggle is linked -> only when clickng it will have an effect - // // - whether the thing is togglable at all -> only when there are children - // var toggle = ""; - // var chevron = ""; - // var togglable = false; - // if (entry.children) { - // chevron = "chevron-right"; - // togglable = true; - // if (entry.expanded) { - // chevron = "chevron-down"; - // } - // if (entry.selected) { - // togglable = false; - // } - // } - // - // if (togglable) { - // toggle = ''; - // toggle = '' + toggle + 'Toggle this subject'; - // } - // // FIXME: putting this in for the moment, just so we can use it in dev - // // var count = ' (' + entry.count + '/' + entry.childCount + ')'; - // var count = ""; - // - // var frag = '\ - // '; - // - // return frag; - // } - // - // function recurse(tree) { - // var selected = tree; - // - // // first check to see if there are any elements at this level that are selected. If there are, - // // that is the only element that we'll render - // if (selectedPathOnly) { - // for (var i = 0; i < tree.length; i++) { - // var entry = tree[i]; - // if (entry.selected) { - // selected = [entry]; - // break; - // } - // } - // } - // - // // now go through either this tree level or just the selected elements, and render the relevant - // // bits of the sub-tree - // var anySelected = false; - // var rFrag = ""; - // for (var i = 0; i < selected.length; i++) { - // var entry = selected[i]; - // entry.expanded = $.inArray(entry.value, that.expanded) > -1; - // var entryFrag = renderEntry(entry); - // if (entryFrag === "") { - // continue; - // } - // if (entry.selected) { - // anySelected = true; - // } - // if (entry.children) { - // var childReport = recurse(entry.children); - // if (childReport.anySelected) { - // anySelected = true; - // } - // // only attach the children frag if, first any of these are true: - // // - one of the children is selected - // // - the entry itself is selected - // // - we don't want to only show the selected path - // // - the entry has been expanded - // if (!selectedPathOnly || childReport.anySelected || entry.selected || entry.expanded) { - // // Then, another level (separated out to save my brain from the tortuous logic) - // // only attach the children frag if, any of these are true: - // // - the entry or one of its children is selected - // // - we want to show more than one level at a time - // // - the entry has been expanded - // if (childReport.anySelected || entry.selected || !showOneLevel || entry.expanded) { - // var cFrag = childReport.frag; - // if (cFrag !== "") { - // entryFrag += ''; - // } - // } - // } - // } - // - // rFrag += '
  • '; - // rFrag += entryFrag; - // rFrag += '
  • '; - // } - // return {frag : rFrag, anySelected: anySelected}; - // } - // - // return recurse(st); - // }; - // - // this.fieldToggle = function(element) { - // var value = this.component.jq(element).attr("data-value"); - // - // var existing = $.inArray(value, this.expanded); - // if (existing > -1) { - // this.expanded.splice(existing, 1); - // } else { - // this.expanded.push(value); - // } - // - // var mainListSelector = edges.css_id_selector(this.namespace, "main", this); - // this.lastScroll = this.component.jq(mainListSelector).scrollTop(); - // this.component.edge.cycle(); - // }; - // - // this.filterToggle = function(element) { - // var mainListSelector = edges.css_id_selector(this.namespace, "main", this); - // this.lastScroll = this.component.jq(mainListSelector).scrollTop(); - // - // // var filter_id = this.component.jq(element).attr("id"); - // var checked = this.component.jq(element).is(":checked"); - // var value = this.component.jq(element).attr("data-value"); - // if (checked) { - // this.component.addFilter({value: value}); - // } else { - // this.component.removeFilter({value: value}); - // } - // }; - // - // this.filterSubjects = function(element) { - // var st = this.component.syncTree; - // var term = $(element).val(); - // var that = this; - // - // var filterSelector = edges.css_id_selector(this.namespace, "filtered", this); - // var mainSelector = edges.css_id_selector(this.namespace, "main", this); - // var filterEl = this.component.jq(filterSelector); - // var mainEl = this.component.jq(mainSelector); - // - // if (term === "") { - // filterEl.html(""); - // filterEl.hide(); - // mainEl.show(); - // return; - // } - // if (term.length < 3) { - // filterEl.html("
  • Enter 3 characters or more to search
  • "); - // filterEl.show(); - // mainEl.hide(); - // return; - // } - // term = term.toLowerCase(); - // - // function entryMatch(entry) { - // if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { - // return false; - // } - // - // var matchTerm = entry.index; - // var includes = matchTerm.includes(term); - // if (includes) { - // var idx = matchTerm.indexOf(term); - // var display = entry.display; - // return display.substring(0, idx) + "" + display.substring(idx, idx + term.length) + "" + display.substring(idx + term.length); - // } - // } - // - // function recurse(tree) { - // var filteredLayer = []; - // for (var i = 0; i < tree.length; i++) { - // var entry = tree[i]; - // var childReport = []; - // if (entry.children) { - // childReport = recurse(entry.children); - // } - // var selfMatch = entryMatch(entry); - // if (selfMatch || childReport.length > 0) { - // var newEntry = $.extend({}, entry); - // delete newEntry.children; - // if (selfMatch) { - // newEntry.display = selfMatch; - // } - // if (childReport.length > 0) { - // newEntry.children = childReport; - // } - // filteredLayer.push(newEntry); - // } - // } - // return filteredLayer; - // } - // - // var filtered = recurse(st); - // - // if (filtered.length > 0) { - // var displayReport = this._renderTree({tree: filtered, selectedPathOnly: false, showOneLevel: false}); - // - // filterEl.html(displayReport.frag); - // mainEl.hide(); - // filterEl.show(); - // - // var checkboxSelector = edges.css_class_selector(this.namespace, "selector", this); - // edges.on(checkboxSelector, "change", this, "filterToggle"); - // } else { - // filterEl.html("
  • No subjects match your search
  • "); - // mainEl.hide(); - // filterEl.show(); - // } - // - // }; - // }, + + newSubjectBrowser : function(params) { + return edges.instantiate(formulaic.edges.SubjectBrowser, params, edges.newRenderer); + }, + SubjectBrowser : function(params) { + this.title = edges.getParam(params.title, ""); + + this.hideEmpty = edges.getParam(params.hideEmpty, false); + + this.expanded = []; + + this.lastScroll = 0; + + this.namespace = "formulaic-subject-browser"; + + this.draw = function() { + // for convenient short references ... + var st = this.component.syncTree; + var namespace = this.namespace; + // var that = this; + + // var checkboxClass = edges.css_classes(namespace, "selector", this); + // var countClass = edges.css_classes(namespace, "count", this); + + var treeReport = this._renderTree({tree: st, selectedPathOnly: false, showOneLevel: true}); + var treeFrag = treeReport.frag; + + if (treeFrag === "") { + treeFrag = "Loading..."; + } + + var toggleId = edges.css_id(namespace, "toggle", this); + var resultsId = edges.css_id(namespace, "results", this); + var searchId = edges.css_id(namespace, "search", this); + var filteredId = edges.css_id(namespace, "filtered", this); + var mainListId = edges.css_id(namespace, "main", this); + + var toggle = ""; + if (this.togglable) { + toggle = ''; + } + var frag = '

    ' + this.title + toggle + '

    \ + '; + + // substitute in the component parts + frag = frag.replace(/{{FILTERS}}/g, treeFrag); + + // now render it into the page + this.component.context.html(frag); + feather.replace(); + + var mainListSelector = edges.css_id_selector(namespace, "main", this); + this.component.jq(mainListSelector).scrollTop(this.lastScroll); + + var checkboxSelector = edges.css_class_selector(namespace, "selector", this); + edges.on(checkboxSelector, "change", this, "filterToggle"); + + var searchSelector = edges.css_id_selector(namespace, "search", this); + edges.on(searchSelector, "keyup", this, "filterSubjects"); + + var fieldSelector = edges.css_class_selector(namespace, "field-toggle", this); + edges.on(fieldSelector, "click", this, "fieldToggle"); + }; + + this._renderTree = function(params) { + var st = edges.getParam(params.tree, []); + var selectedPathOnly = edges.getParam(params.selectedPathOnly, true); + var showOneLevel = edges.getParam(params.showOneLevel, true); + var that = this; + + var checkboxClass = edges.css_classes(this.namespace, "selector", this); + var toggleClass = edges.css_classes(that.namespace, "field-toggle", this); + + function renderEntry(entry) { + if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { + return ""; + } + + var id = edges.safeId(entry.value); + var checked = ""; + if (entry.selected) { + checked = ' checked="checked" '; + } + + // the various rules to do with how this will toggle. + // - whether the toggle is linked -> only when clickng it will have an effect + // - whether the thing is togglable at all -> only when there are children + var toggle = ""; + var chevron = ""; + var togglable = false; + if (entry.children) { + chevron = "chevron-right"; + togglable = true; + if (entry.expanded) { + chevron = "chevron-down"; + } + if (entry.selected) { + togglable = false; + } + } + + if (togglable) { + toggle = ''; + toggle = '' + toggle + 'Toggle this subject'; + } + // FIXME: putting this in for the moment, just so we can use it in dev + // var count = ' (' + entry.count + '/' + entry.childCount + ')'; + var count = ""; + + var frag = '\ + '; + + return frag; + } + + function recurse(tree) { + var selected = tree; + + // first check to see if there are any elements at this level that are selected. If there are, + // that is the only element that we'll render + if (selectedPathOnly) { + for (var i = 0; i < tree.length; i++) { + var entry = tree[i]; + if (entry.selected) { + selected = [entry]; + break; + } + } + } + + // now go through either this tree level or just the selected elements, and render the relevant + // bits of the sub-tree + var anySelected = false; + var rFrag = ""; + for (var i = 0; i < selected.length; i++) { + var entry = selected[i]; + entry.expanded = $.inArray(entry.value, that.expanded) > -1; + var entryFrag = renderEntry(entry); + if (entryFrag === "") { + continue; + } + if (entry.selected) { + anySelected = true; + } + if (entry.children) { + var childReport = recurse(entry.children); + if (childReport.anySelected) { + anySelected = true; + } + // only attach the children frag if, first any of these are true: + // - one of the children is selected + // - the entry itself is selected + // - we don't want to only show the selected path + // - the entry has been expanded + if (!selectedPathOnly || childReport.anySelected || entry.selected || entry.expanded) { + // Then, another level (separated out to save my brain from the tortuous logic) + // only attach the children frag if, any of these are true: + // - the entry or one of its children is selected + // - we want to show more than one level at a time + // - the entry has been expanded + if (childReport.anySelected || entry.selected || !showOneLevel || entry.expanded) { + var cFrag = childReport.frag; + if (cFrag !== "") { + entryFrag += ''; + } + } + } + } + + rFrag += '
  • '; + rFrag += entryFrag; + rFrag += '
  • '; + } + return {frag : rFrag, anySelected: anySelected}; + } + + return recurse(st); + }; + + this.fieldToggle = function(element) { + var value = this.component.jq(element).attr("data-value"); + + var existing = $.inArray(value, this.expanded); + if (existing > -1) { + this.expanded.splice(existing, 1); + } else { + this.expanded.push(value); + } + + var mainListSelector = edges.css_id_selector(this.namespace, "main", this); + this.lastScroll = this.component.jq(mainListSelector).scrollTop(); + this.component.edge.cycle(); + }; + + this.filterToggle = function(element) { + var mainListSelector = edges.css_id_selector(this.namespace, "main", this); + this.lastScroll = this.component.jq(mainListSelector).scrollTop(); + + // var filter_id = this.component.jq(element).attr("id"); + var checked = this.component.jq(element).is(":checked"); + var value = this.component.jq(element).attr("data-value"); + if (checked) { + this.component.addFilter({value: value}); + } else { + this.component.removeFilter({value: value}); + } + }; + + this.filterSubjects = function(element) { + var st = this.component.syncTree; + var term = $(element).val(); + var that = this; + + var filterSelector = edges.css_id_selector(this.namespace, "filtered", this); + var mainSelector = edges.css_id_selector(this.namespace, "main", this); + var filterEl = this.component.jq(filterSelector); + var mainEl = this.component.jq(mainSelector); + + if (term === "") { + filterEl.html(""); + filterEl.hide(); + mainEl.show(); + return; + } + if (term.length < 3) { + filterEl.html("
  • Enter 3 characters or more to search
  • "); + filterEl.show(); + mainEl.hide(); + return; + } + term = term.toLowerCase(); + + function entryMatch(entry) { + if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { + return false; + } + + var matchTerm = entry.index; + var includes = matchTerm.includes(term); + if (includes) { + var idx = matchTerm.indexOf(term); + var display = entry.display; + return display.substring(0, idx) + "" + display.substring(idx, idx + term.length) + "" + display.substring(idx + term.length); + } + } + + function recurse(tree) { + var filteredLayer = []; + for (var i = 0; i < tree.length; i++) { + var entry = tree[i]; + var childReport = []; + if (entry.children) { + childReport = recurse(entry.children); + } + var selfMatch = entryMatch(entry); + if (selfMatch || childReport.length > 0) { + var newEntry = $.extend({}, entry); + delete newEntry.children; + if (selfMatch) { + newEntry.display = selfMatch; + } + if (childReport.length > 0) { + newEntry.children = childReport; + } + filteredLayer.push(newEntry); + } + } + return filteredLayer; + } + + var filtered = recurse(st); + + if (filtered.length > 0) { + var displayReport = this._renderTree({tree: filtered, selectedPathOnly: false, showOneLevel: false}); + + filterEl.html(displayReport.frag); + mainEl.hide(); + filterEl.show(); + + var checkboxSelector = edges.css_class_selector(this.namespace, "selector", this); + edges.on(checkboxSelector, "change", this, "filterToggle"); + } else { + filterEl.html("
  • No subjects match your search
  • "); + mainEl.hide(); + filterEl.show(); + } + + }; + } }, widgets : { From e01f9df9f459e95601830a09e7941c377943a739 Mon Sep 17 00:00:00 2001 From: Aga Date: Thu, 12 Sep 2024 11:05:45 +0100 Subject: [PATCH 3/9] first pass on refactoring --- portality/static/js/formulaic.js | 664 ++++++++++++------ .../application_form/js/_form_js.html | 1 + 2 files changed, 441 insertions(+), 224 deletions(-) diff --git a/portality/static/js/formulaic.js b/portality/static/js/formulaic.js index 9f9c087dac..297538460d 100644 --- a/portality/static/js/formulaic.js +++ b/portality/static/js/formulaic.js @@ -1,9 +1,9 @@ var formulaic = { - newFormulaic : function(params) { + newFormulaic: function (params) { return edges.instantiate(formulaic.Formulaic, params); }, - Formulaic : function(params) { + Formulaic: function (params) { // Construction Arguments /////////////////////////////////////////////////////// @@ -54,7 +54,7 @@ var formulaic = { /** * Construct the Formulaic instance */ - this.init = function() { + this.init = function () { // set up the save button this.bindSave(); @@ -93,7 +93,7 @@ var formulaic = { } };*/ - this.getElementName = function(element) { + this.getElementName = function (element) { var name = element.attr("data-formulaic-sync"); if (!name) { name = element.attr("name"); @@ -101,7 +101,7 @@ var formulaic = { return name; }; - this.getFieldDefinition = function(params) { + this.getFieldDefinition = function (params) { var field = params.field; for (var i = 0; i < this.fieldsets.length; i++) { @@ -122,7 +122,7 @@ var formulaic = { ////////////////////////////////////////////// // Functions for handling save - this.bindSave = function() { + this.bindSave = function () { edges.on(this.context.find(".formulaic-complete"), "click.Complete", this, "saveComplete", false, false, false); edges.on(this.context.find(".formulaic-draft"), "click.Draft", this, "saveDraftAndComplete", false, false, false); @@ -131,24 +131,26 @@ var formulaic = { } }; - this.backgroundSaveClosure = function() { + this.backgroundSaveClosure = function () { var that = this; - return function() { - that.save({validate: false, additional : {"draft" : "true", "async" : "true"}, complete: false}); + return function () { + that.save({validate: false, additional: {"draft": "true", "async": "true"}, complete: false}); setTimeout(that.backgroundSaveClosure(), that.autoSave); }; }; - this.saveComplete = function(element, event) { + this.saveComplete = function (element, event) { this.save({event: event}); }; - this.saveDraftAndComplete = function(element, event) { - this.save({validate: false, additional : {"draft" : "true", "async" : "true"}, event: event}); + this.saveDraftAndComplete = function (element, event) { + this.save({validate: false, additional: {"draft": "true", "async": "true"}, event: event}); }; - this.save = function(params) { - if (!params) { params = {};} + this.save = function (params) { + if (!params) { + params = {}; + } var validate = edges.getParam(params.validate, this.doValidation); var additional_params = edges.getParam(params.additional, {}); var complete = edges.getParam(params.complete, true); @@ -174,8 +176,9 @@ var formulaic = { $.post({ url: this.context.attr("action"), data: full_data, - error: function() {/*alert("background save failed")*/}, - success: function(response_data) { + error: function () {/*alert("background save failed")*/ + }, + success: function (response_data) { that.lastSaveVal = submit_data; var rd = JSON.parse(response_data); that.setId(rd); @@ -193,7 +196,7 @@ var formulaic = { } }; - this.setId = function(params) { + this.setId = function (params) { var id = params.id; var existing = this.context.find("[name=id]"); if (existing.length > 0) { @@ -208,7 +211,7 @@ var formulaic = { ///////////////////////////////////////////////////// // Functions for handling synchronised fields - this.registerSynchronised = function() { + this.registerSynchronised = function () { var fieldRegister = []; for (var i = 0; i < this.fieldsets.length; i++) { var fieldset = this.fieldsets[i]; @@ -230,7 +233,7 @@ var formulaic = { for (var i = 0; i < fields.length; i++) { var name = fields[i]; var allByName = this.controlSelect.input({name: name}); - allByName.each(function() { + allByName.each(function () { var that = $(this); var current_id = that.attr("id"); that.attr("data-formulaic-sync", name).attr("data-formulaic-id", current_id); @@ -240,7 +243,7 @@ var formulaic = { for (var j = 0; j < fieldsets.length; j++) { var fieldset = fieldsets[j]; var elements = this.controlSelect.input({fieldset: fieldset, name: name}); - elements.each(function() { + elements.each(function () { var newname = fieldset + "__" + name; var newid = fieldset + "__" + $(this).attr("id"); $(this).attr("name", newname).attr("id", newid); @@ -251,7 +254,7 @@ var formulaic = { } }; - this.synchroniseChange = function(element) { + this.synchroniseChange = function (element) { var that = $(element); var name = that.attr("data-formulaic-sync"); var original_id = that.attr("data-formulaic-id"); @@ -262,7 +265,7 @@ var formulaic = { if (type === "radio" || type === "checkbox") { var checked = that.is(":checked"); var toSync = this.controlSelect.input({syncName: name}); - toSync.each(function() { + toSync.each(function () { var el = $(this); if (el.attr("data-formulaic-id") === original_id) { el.prop("checked", checked); @@ -278,7 +281,7 @@ var formulaic = { // Functions for conditional fields /////////////////////////////////////////////////////// - this.bindConditional = function() { + this.bindConditional = function () { for (var i = 0; i < this.fieldsets.length; i++) { var fieldset = this.fieldsets[i]; for (var j = 0; j < fieldset.fields.length; j++) { @@ -312,7 +315,7 @@ var formulaic = { } }; - this.checkConditional = function(element) { + this.checkConditional = function (element) { var name = this.getElementName($(element)); var downstream = this.conditionals[name]; for (var i = 0; i < downstream.length; i++) { @@ -343,7 +346,7 @@ var formulaic = { }); }; - this.isConditionSatisfied = function(params) { + this.isConditionSatisfied = function (params) { var field = params.field; var definition = this.getFieldDefinition(params); for (var i = 0; i < definition.conditional.length; i++) { @@ -354,7 +357,7 @@ var formulaic = { if (type === "radio" || type === "checkbox") { var checkedValues = []; - elements.each(function() { + elements.each(function () { var that = $(this); if (that.is(":checked")) { checkedValues.push(that.val()); @@ -373,7 +376,7 @@ var formulaic = { // Functions for widget handling /////////////////////////////////////////////////////// - this.applyWidgets = function() { + this.applyWidgets = function () { for (var i = 0; i < this.fieldsets.length; i++) { var fieldset = this.fieldsets[i]; for (var j = 0; j < fieldset.fields.length; j++) { @@ -413,7 +416,7 @@ var formulaic = { } }; - this.getWidget = function(widgetName) { + this.getWidget = function (widgetName) { if (this.widgetRefs[widgetName]) { return this.widgetRefs[widgetName]; } @@ -441,7 +444,7 @@ var formulaic = { // Functions for exclusive checkboxes ////////////////////////////////////////////////////// - this.bindExclusiveCheckboxes = function() { + this.bindExclusiveCheckboxes = function () { // first register all the exclusive elements and values for (var i = 0; i < this.fieldsets.length; i++) { var fieldset = this.fieldsets[i]; @@ -475,7 +478,7 @@ var formulaic = { } }; - this.checkExclusive = function(element) { + this.checkExclusive = function (element) { var jqel = $(element); var name = jqel.attr("name"); var value = jqel.val(); @@ -491,7 +494,7 @@ var formulaic = { var checked = jqel.is(":checked"); var elements = this.controlSelect.input({name: name}); var that = this; - elements.each(function() { + elements.each(function () { if (checked && $(this).val() !== value) { $(this).prop("checked", false); $(this).prop('disabled', true); @@ -507,8 +510,10 @@ var formulaic = { // Parsley state management //////////////////////////////////////////////////// - this.destroyParsley = function() { - if (!this.doValidation) { return; } + this.destroyParsley = function () { + if (!this.doValidation) { + return; + } if (this.activeParsley) { this.activeParsley.destroy(); this.activeParsley = false; @@ -517,8 +522,10 @@ var formulaic = { // $(".has-error").removeClass("has-error"); }; - this.bounceParsley = function() { - if (!this.doValidation) { return; } + this.bounceParsley = function () { + if (!this.doValidation) { + return; + } this.destroyParsley(); this.activeParsley = this.context.parsley(); }; @@ -529,21 +536,21 @@ var formulaic = { this.init(); }, - newDefaultControlSelect : function(params) { + newDefaultControlSelect: function (params) { return edges.instantiate(formulaic.DefaultControlSelect, params); }, - DefaultControlSelect : function(params) { + DefaultControlSelect: function (params) { this.containerClassTemplate = edges.getParam(params.containerClassTemplate, "{name}__container"); this.groupSeparator = edges.getParam(params.groupSeparator, "-"); this.formulaic = false; - this.set_formuaic = function(f) { + this.set_formuaic = function (f) { this.formulaic = f; }; - this.get_context = function(params) { + this.get_context = function (params) { var context = this.formulaic.context; if (params.fieldset) { context = $("#" + params.fieldset, context); @@ -551,7 +558,7 @@ var formulaic = { return context; }; - this.localiseName = function(params) { + this.localiseName = function (params) { var name = params.name; var def = this.formulaic.getFieldDefinition({field: name}); if (def.hasOwnProperty("group")) { @@ -562,10 +569,10 @@ var formulaic = { } }; - this.input = function(params) { + this.input = function (params) { var context = this.get_context(params); if (params.name) { - var name = this.localiseName({name : params.name}); + var name = this.localiseName({name: params.name}); return $("[name=" + name + "], [data-formulaic-sync=" + name + "]", context).filter(":input"); } else if (params.id) { return $("#" + params.id, context).filter(":input"); @@ -575,24 +582,216 @@ var formulaic = { } }; - this.container = function(params) { + this.container = function (params) { var context = this.get_context(params); var name = params.name || params.syncName; var selector = "." + this.containerClassTemplate.replace("{name}", name); return $(selector, context); }; - this.widgetsContainer = function(params) { + this.widgetsContainer = function (params) { var context = this.get_context(params); return $("#" + params.name + "_widgets-container", context) } }, - edges : { - newTreeBrowser : function(params) { - return edges.instantiate(formulaic.edges.TreeBrowser, params, edges.newComponent); + edges: { + newTreeBrowser: function (params) { + // return edges.instantiate(formulaic.edges.TreeBrowserForm, params, edges.newComponent); + return edges.instantiate(formulaic.edges.TreeBrowserForm, params, edges.TreeBrowserCore); + }, + TreeBrowserForm: function (params) { + this.sourceInput = edges.getParam(params.sourceInput, false); + this.selected = []; + + this.init = function (edge) { + console.log("formulaic.edges.TreeBrowserForm") + // first kick the request up to the superclass + edges.newTreeBrowserCore().init.call(this, edge); + + // sourceInput can be false + // this is specific for the form, not the TreeBrowser itself + var text = this.sourceInput.val(); + if (text !== "") { + this.selected = text.split(",").map(function (x) { + return x.trim() + }) + } else { + this.selected = []; + } + }; + + this.synchronise = function () { + console.log("formulaic.edges.TreeBrowserForm.synchonise") + this.syncTree = $.extend(true, [], this.tree); + var selected = this.selected; + var that = this; + + var processNode = function (node) { + if (that.filterMatch(node, selected)) { + node.selected = true; + anySelected = true; + } + node.index = that.nodeIndex ? that.nodeIndex(node) : node.display; + }; + + var path = []; + this.baseRecurse(this.syncTree, path, processNode); + }; + + // this.synchronise = function() { + // + // this.syncTree = $.extend(true, [], this.tree); + // var selected = this.selected; + // var that = this; + // + // function recurse(tree, path) { + // var anySelected = false; + // var childCount = 0; + // + // for (var i = 0; i < tree.length; i++) { + // var node = tree[i]; + // that.nodeCount++; + // + // that.parentIndex[node.value] = $.extend(true, [], path); + // + // if (that.filterMatch(node, selected)) { + // node.selected = true; + // anySelected = true; + // } + // + // if (that.nodeIndex) { + // node.index = that.nodeIndex(node); + // } else { + // node.index = node.display; + // } + // + // if (node.children) { + // path.push(node.value); + // var childReport = recurse(node.children, path); + // path.pop(); + // if (childReport.anySelected) { + // node.selected = true; + // anySelected = true; + // } + // childCount += childReport.childCount; + // node.childCount = childReport.childCount; + // } else { + // node.childCount = 0; + // } + // + // } + // return {anySelected: anySelected, childCount: childCount} + // } + // var path = []; + // recurse(this.syncTree, path); + // }; + + this.addFilter = function (params) { + console.log("formulaic.edges.TreeBrowserForm.addFilter") + var value = params.value; + var parents = this.parentIndex[value]; + var terms = [params.value]; + var clearOthers = edges.getParam(params.clearOthers, false); + + var newValues = $.extend(true, [], this.selected); + + // if there is, just add the term to it (removing and parent terms along the way) + if (newValues.length > 0) { + newValues.sort(); + + // if this is an exclusive filter that clears all others, just do that + if (clearOthers) { + newValues = []; + } + + // next, if there are any terms left, remove all the parent terms + for (var i = 0; i < parents.length; i++) { + var parent = parents[i]; + var location = $.inArray(parent, newValues); + if (location !== -1) { + newValues.splice(location, 1); + } + } + + // now add all the provided terms + var hadTermAlready = 0; + for (var i = 0; i < terms.length; i++) { + var term = terms[i]; + if ($.inArray(term, newValues) !== -1) { + hadTermAlready++; + } else { + newValues.push(term); + } + } + } else { + newValues = terms; + } + + // store the new values on the object and in the form + this.selected = newValues; + this.sourceInput.val(newValues.join(",")); + this.sourceInput.trigger("change"); + this.edge.cycle(); + return true; + }; + + this.removeFilter = function (params) { + console.log("formulaic.edges.TreeBrowserForm.removeFilter") + var term = params.value; + + var newValues = $.extend(true, [], this.selected); + + if (newValues.length > 0) { + var location = $.inArray(term, newValues); + if (location !== -1) { + // the filter we are being asked to remove is the actual selected one + newValues.splice(location, 1); + } else { + // the filter we are being asked to remove may be a parent of the actual selected one + // first get all the parent sets of the values that are currently in force + var removes = []; + for (var i = 0; i < newValues.length; i++) { + var val = newValues[i]; + var parentSet = this.parentIndex[val]; + if ($.inArray(term, parentSet) > -1) { + removes.push(val); + } + } + for (var i = 0; i < removes.length; i++) { + var location = $.inArray(removes[i], newValues); + if (location !== -1) { + newValues.splice(location, 1); + } + } + } + + var grandparents = this.parentIndex[term]; + if (grandparents.length > 0) { + var immediate = grandparents[grandparents.length - 1]; + var sharedParent = false; + for (var i = 0; i < newValues.length; i++) { + var aunts = this.parentIndex[newValues[i]]; + if (aunts.length > 0 && aunts[aunts.length - 1] === immediate) { + sharedParent = true; + break; + } + } + if (!sharedParent && $.inArray(immediate, newValues) === -1) { + newValues.push(immediate); + } + } + } + + // reset the search page to the start and then trigger the next query + // store the new values on the object and in the form + this.selected = newValues; + this.sourceInput.val(newValues.join(",")); + this.sourceInput.trigger("change"); + this.edge.cycle(); + }; }, - TreeBrowser : function(params) { + /*TreeBrowserForm: function (params) { this.tree = edges.getParam(params.tree, {}); this.sourceInput = edges.getParam(params.sourceInput, false); @@ -611,68 +810,88 @@ var formulaic = { this.selected = []; - this.init = function(edge) { + this.init = function (edge) { // first kick the request up to the superclass edges.newSelector().init.call(this, edge); + // sourceInput can be false + // this is specific for the form, not the TreeBrowser itself var text = this.sourceInput.val(); if (text !== "") { - this.selected = text.split(",").map(function(x) {return x.trim()}) + this.selected = text.split(",").map(function (x) { + return x.trim() + }) } else { this.selected = []; } }; - - this.synchronise = function() { - + this.synchronise = function () { this.syncTree = $.extend(true, [], this.tree); var selected = this.selected; var that = this; - function recurse(tree, path) { - var anySelected = false; - var childCount = 0; - - for (var i = 0; i < tree.length; i++) { - var node = tree[i]; - that.nodeCount++; - - that.parentIndex[node.value] = $.extend(true, [], path); - - if (that.filterMatch(node, selected)) { - node.selected = true; - anySelected = true; - } - - if (that.nodeIndex) { - node.index = that.nodeIndex(node); - } else { - node.index = node.display; - } - - if (node.children) { - path.push(node.value); - var childReport = recurse(node.children, path); - path.pop(); - if (childReport.anySelected) { - node.selected = true; - anySelected = true; - } - childCount += childReport.childCount; - node.childCount = childReport.childCount; - } else { - node.childCount = 0; - } - + var processNode = function (node) { + if (that.filterMatch(node, selected)) { + node.selected = true; + anySelected = true; } - return {anySelected: anySelected, childCount: childCount} - } + node.index = that.nodeIndex ? that.nodeIndex(node) : node.display; + }; + var path = []; - recurse(this.syncTree, path); + this.baseRecurse(this.syncTree, path, processNode); }; - this.addFilter = function(params) { + // this.synchronise = function() { + // + // this.syncTree = $.extend(true, [], this.tree); + // var selected = this.selected; + // var that = this; + // + // function recurse(tree, path) { + // var anySelected = false; + // var childCount = 0; + // + // for (var i = 0; i < tree.length; i++) { + // var node = tree[i]; + // that.nodeCount++; + // + // that.parentIndex[node.value] = $.extend(true, [], path); + // + // if (that.filterMatch(node, selected)) { + // node.selected = true; + // anySelected = true; + // } + // + // if (that.nodeIndex) { + // node.index = that.nodeIndex(node); + // } else { + // node.index = node.display; + // } + // + // if (node.children) { + // path.push(node.value); + // var childReport = recurse(node.children, path); + // path.pop(); + // if (childReport.anySelected) { + // node.selected = true; + // anySelected = true; + // } + // childCount += childReport.childCount; + // node.childCount = childReport.childCount; + // } else { + // node.childCount = 0; + // } + // + // } + // return {anySelected: anySelected, childCount: childCount} + // } + // var path = []; + // recurse(this.syncTree, path); + // }; + + this.addFilter = function (params) { var value = params.value; var parents = this.parentIndex[value]; var terms = [params.value]; @@ -720,7 +939,7 @@ var formulaic = { return true; }; - this.removeFilter = function(params) { + this.removeFilter = function (params) { var term = params.value; var newValues = $.extend(true, [], this.selected); @@ -753,7 +972,7 @@ var formulaic = { if (grandparents.length > 0) { var immediate = grandparents[grandparents.length - 1]; var sharedParent = false; - for (var i = 0; i < newValues.length;i ++) { + for (var i = 0; i < newValues.length; i++) { var aunts = this.parentIndex[newValues[i]]; if (aunts.length > 0 && aunts[aunts.length - 1] === immediate) { sharedParent = true; @@ -773,23 +992,22 @@ var formulaic = { this.sourceInput.trigger("change"); this.edge.cycle(); }; - } + },*/ - newSubjectBrowser : function(params) { - return edges.instantiate(formulaic.edges.SubjectBrowser, params, edges.newRenderer); + newSubjectBrowserRenderer: function (params) { + return edges.instantiate(formulaic.edges.SubjectBrowserRenderer, params, edges.newRenderer); }, - SubjectBrowser : function(params) { + SubjectBrowserRenderer: function (params) { + console.log("formulaic.edges.SubjectBrowserRenderer") + edges.newRenderer().call(params); this.title = edges.getParam(params.title, ""); - this.hideEmpty = edges.getParam(params.hideEmpty, false); - this.expanded = []; - this.lastScroll = 0; - this.namespace = "formulaic-subject-browser"; - this.draw = function() { + this.draw = function () { + console.log("formulaic.edges.SubjectBrowserRenderer.draw") // for convenient short references ... var st = this.component.syncTree; var namespace = this.namespace; @@ -843,7 +1061,7 @@ var formulaic = { edges.on(fieldSelector, "click", this, "fieldToggle"); }; - this._renderTree = function(params) { + this._renderTree = function (params) { var st = edges.getParam(params.tree, []); var selectedPathOnly = edges.getParam(params.selectedPathOnly, true); var showOneLevel = edges.getParam(params.showOneLevel, true); @@ -954,13 +1172,13 @@ var formulaic = { rFrag += entryFrag; rFrag += ''; } - return {frag : rFrag, anySelected: anySelected}; + return {frag: rFrag, anySelected: anySelected}; } return recurse(st); }; - this.fieldToggle = function(element) { + this.fieldToggle = function (element) { var value = this.component.jq(element).attr("data-value"); var existing = $.inArray(value, this.expanded); @@ -975,7 +1193,7 @@ var formulaic = { this.component.edge.cycle(); }; - this.filterToggle = function(element) { + this.filterToggle = function (element) { var mainListSelector = edges.css_id_selector(this.namespace, "main", this); this.lastScroll = this.component.jq(mainListSelector).scrollTop(); @@ -989,7 +1207,7 @@ var formulaic = { } }; - this.filterSubjects = function(element) { + this.filterSubjects = function (element) { var st = this.component.syncTree; var term = $(element).val(); var that = this; @@ -1019,7 +1237,7 @@ var formulaic = { } var matchTerm = entry.index; - var includes = matchTerm.includes(term); + var includes = matchTerm.includes(term); if (includes) { var idx = matchTerm.indexOf(term); var display = entry.display; @@ -1054,7 +1272,11 @@ var formulaic = { var filtered = recurse(st); if (filtered.length > 0) { - var displayReport = this._renderTree({tree: filtered, selectedPathOnly: false, showOneLevel: false}); + var displayReport = this._renderTree({ + tree: filtered, + selectedPathOnly: false, + showOneLevel: false + }); filterEl.html(displayReport.frag); mainEl.hide(); @@ -1072,15 +1294,15 @@ var formulaic = { } }, - widgets : { - _select2_shift_focus: function(){ + widgets: { + _select2_shift_focus: function () { let id = $(this).attr("id"); console.log("focused on " + id); - let select2_elem = $("#s2id_" + id).find("input"); + let select2_elem = $("#s2id_" + id).find("input"); $(select2_elem).focus(); }, - _make_empty_container: function(namespace, containerName, form, fieldDef, additionalClasses, additionalStyles) { + _make_empty_container: function (namespace, containerName, form, fieldDef, additionalClasses, additionalStyles) { if (!additionalClasses) { additionalClasses = ""; } @@ -1108,16 +1330,16 @@ var formulaic = { return elements.find(containerSelector); }, - newAutocheck : function(params) { + newAutocheck: function (params) { return edges.instantiate(formulaic.widgets.Autocheck, params); }, - Autocheck: function(params) { + Autocheck: function (params) { this.fieldDef = params.fieldDef; this.form = params.formulaic; this.namespace = "formulaic-autocheck-" + this.fieldDef.name; - this.init = function() { + this.init = function () { let annos = this._getAutochecksForField(); if (annos.length === 0) { return; @@ -1139,7 +1361,7 @@ var formulaic = { feather.replace(); } - this._getAutochecksForField = function() { + this._getAutochecksForField = function () { if (!doaj.autochecks) { return []; } @@ -1152,21 +1374,21 @@ var formulaic = { return applicable; } - this._renderAutocheck = function(autocheck) { + this._renderAutocheck = function (autocheck) { let frag = "
  • "; - + if (autocheck.checked_by && doaj.autocheckers && doaj.autocheckers.registry.hasOwnProperty(autocheck.checked_by)) { frag += (new doaj.autocheckers.registry[autocheck.checked_by]()).draw(autocheck) } else { frag += this._defaultRender(autocheck); } - + frag += `
  • `; return frag; } - this._defaultRender = function(autocheck) { + this._defaultRender = function (autocheck) { let frag = ""; if (autocheck.advice) { frag += `${autocheck.advice}
    ` @@ -1186,11 +1408,10 @@ var formulaic = { this.init(); }, - newSubjectTree : function(params) { + newSubjectTree: function (params) { return edges.instantiate(formulaic.widgets.SubjectTree, params); - // return edges.instantiate(formulaic.widgets.SubjectTree, params); }, - SubjectTree : function(params) { + SubjectTree: function (params) { this.fieldDef = params.fieldDef; this.form = params.formulaic; @@ -1198,7 +1419,7 @@ var formulaic = { this.ns = "formulaic-subjecttree"; - this.init = function() { + this.init = function () { var tree = doaj.af.lccTree; var containerId = edges.css_id(this.ns, "container"); @@ -1229,7 +1450,7 @@ var formulaic = { var subjectBrowser = formulaic.edges.newTreeBrowser({ id: widgetId, sourceInput: this.input, - tree: function(tree) { + tree: function (tree) { function recurse(ctx) { var displayTree = []; for (var i = 0; i < ctx.length; i++) { @@ -1245,9 +1466,10 @@ var formulaic = { displayTree.sort((a, b) => a.display > b.display ? 1 : -1); return displayTree; } + return recurse(tree); }(tree), - nodeMatch: function(node, match_list) { + nodeMatch: function (node, match_list) { for (var i = 0; i < match_list.length; i++) { var m = match_list[i]; if (node.value === m.key) { @@ -1256,31 +1478,31 @@ var formulaic = { } return -1; }, - filterMatch: function(node, selected) { + filterMatch: function (node, selected) { return $.inArray(node.value, selected) > -1; }, - nodeIndex : function(node) { + nodeIndex: function (node) { return node.display.toLowerCase(); }, - renderer: doaj.renderers.newSubjectBrowser({ + renderer: doaj.renderers.newSubjectBrowserRenderer({ title: "Subjects" }) }); var e = edges.newEdge({ selector: containerSelector, - manageUrl : false, - components : [ + manageUrl: false, + components: [ subjectBrowser ], - callbacks : { - "edges:query-fail" : function() { + callbacks: { + "edges:query-fail": function () { alert("There was an unexpected error. Please reload the page and try again. If the issue persists please contact us."); }, - "edges:post-init" : function() { + "edges:post-init": function () { feather.replace(); }, - "edges:post-render" : function() { + "edges:post-render": function () { feather.replace(); } } @@ -1293,12 +1515,12 @@ var formulaic = { edges.on(closeSelector, "click", this, "closeModal"); }; - this.openModal = function() { + this.openModal = function () { var containerSelector = edges.css_id_selector(this.ns, "container"); $(containerSelector).show(); }; - this.closeModal = function() { + this.closeModal = function () { var containerSelector = edges.css_id_selector(this.ns, "container"); $(containerSelector).hide(); this.input.trigger("change"); @@ -1306,10 +1528,10 @@ var formulaic = { this.init(); }, - newClickableOwner : function(params) { + newClickableOwner: function (params) { return edges.instantiate(formulaic.widgets.ClickableOwner, params) }, - ClickableOwner : function(params) { + ClickableOwner: function (params) { this.fieldDef = params.fieldDef; this.form = params.formulaic; @@ -1317,7 +1539,7 @@ var formulaic = { this.link = false; - this.init = function() { + this.init = function () { var elements = this.form.controlSelect.input({name: this.fieldDef.name}); edges.on(elements, "change.ClickableOwner", this, "updateOwner"); for (var i = 0; i < elements.length; i++) { @@ -1325,7 +1547,7 @@ var formulaic = { } }; - this.updateOwner = function(element) { + this.updateOwner = function (element) { var that = $(element); var val = that.val(); @@ -1349,16 +1571,16 @@ var formulaic = { this.init(); }, - newClickToCopy : function(params) { + newClickToCopy: function (params) { return edges.instantiate(formulaic.widgets.ClickToCopy, params) }, - ClickToCopy : function(params) { + ClickToCopy: function (params) { this.fieldDef = params.fieldDef; - this.init = function() { + this.init = function () { var elements = $("#click-to-copy--" + this.fieldDef.name); edges.on(elements, "click", this, "copy"); }; - this.copy = function(element) { + this.copy = function (element) { let form = new doaj.af.BaseApplicationForm() let value = form.determineFieldsValue(this.fieldDef.name) let value_to_copy = form.convertValueToText(value); @@ -1370,10 +1592,10 @@ var formulaic = { this.init(); }, - newTrimWhitespace : function(params) { + newTrimWhitespace: function (params) { return edges.instantiate(formulaic.widgets.TrimWhitespace, params) }, - TrimWhitespace : function(params) { + TrimWhitespace: function (params) { this.fieldDef = params.fieldDef; this.form = params.formulaic; @@ -1391,7 +1613,7 @@ var formulaic = { } }; - this.trim = function(element) { + this.trim = function (element) { var that = $(element); var val = that.val(); var nv = val.trim(); @@ -1403,10 +1625,10 @@ var formulaic = { this.init(); }, - newClickableUrl : function(params) { + newClickableUrl: function (params) { return edges.instantiate(formulaic.widgets.ClickableUrl, params) }, - ClickableUrl : function(params) { + ClickableUrl: function (params) { this.fieldDef = params.fieldDef; this.form = params.formulaic; @@ -1414,7 +1636,7 @@ var formulaic = { this.link = false; - this.init = function() { + this.init = function () { var elements = this.form.controlSelect.input({name: this.fieldDef.name}); edges.on(elements, "keyup.ClickableUrl", this, "updateUrl"); @@ -1424,11 +1646,11 @@ var formulaic = { } }; - this.updateUrl = function(element) { + this.updateUrl = function (element) { var that = $(element); var val = that.val(); - if (val && (val.substring(0,7) === "http://" || val.substring(0,8) === "https://") && val.length > 10) { + if (val && (val.substring(0, 7) === "http://" || val.substring(0, 8) === "https://") && val.length > 10) { if (this.link) { this.link.attr("href", val); } else { @@ -1450,10 +1672,10 @@ var formulaic = { this.init(); }, - newFullContents : function(params) { + newFullContents: function (params) { return edges.instantiate(formulaic.widgets.FullContents, params) }, - FullContents : function(params) { + FullContents: function (params) { this.fieldDef = params.fieldDef; this.form = params.formulaic; this.args = params.args; @@ -1462,7 +1684,7 @@ var formulaic = { this.container = false; - this.init = function() { + this.init = function () { var elements = this.form.controlSelect.input({name: this.fieldDef.name}); edges.on(elements, "keyup.FullContents", this, "updateContents"); @@ -1471,7 +1693,7 @@ var formulaic = { } }; - this.updateContents = function(element) { + this.updateContents = function (element) { var that = $(element); var val = that.val(); @@ -1504,10 +1726,10 @@ var formulaic = { this.init(); }, - newNoteModal : function(params) { + newNoteModal: function (params) { return edges.instantiate(formulaic.widgets.NoteModal, params) }, - NoteModal : function(params) { + NoteModal: function (params) { this.fieldDef = params.fieldDef; this.form = params.formulaic; @@ -1515,7 +1737,7 @@ var formulaic = { this.container = false; - this.init = function() { + this.init = function () { var viewClass = edges.css_classes(this.ns, "view"); var closeClass = edges.css_classes(this.ns, "close"); let group = $("div[name='" + this.fieldDef["name"] + "__group']") @@ -1573,13 +1795,13 @@ var formulaic = { edges.on(closeSelector, "click", this, "closeModal"); }; - this.showModal = function(element) { + this.showModal = function (element) { var that = $(element); var modal = that.siblings(".modal"); modal.show(); }; - this.closeModal = function(element) { + this.closeModal = function (element) { var that = $(element); var modal = that.parents(".modal"); modal.hide(); @@ -1588,10 +1810,10 @@ var formulaic = { this.init(); }, - newInfiniteRepeat : function(params) { + newInfiniteRepeat: function (params) { return edges.instantiate(formulaic.widgets.InfiniteRepeat, params) }, - InfiniteRepeat: function(params) { + InfiniteRepeat: function (params) { this.fieldDef = params.fieldDef; this.args = params.args; @@ -1600,9 +1822,9 @@ var formulaic = { this.container = false; this.divs = false; - this.init = function() { + this.init = function () { this.divs = $("div[name='" + this.fieldDef["name"] + "__group']"); - for (var i = 0 ; i < this.divs.length; i++) { + for (var i = 0; i < this.divs.length; i++) { var div = $(this.divs[i]); div.append($('')); feather.replace(); @@ -1644,7 +1866,7 @@ var formulaic = { }; - this.addField = function() { + this.addField = function () { var currentLargest = -1; for (var i = 0; i < this.divs.length; i++) { var div = $(this.divs[i]); @@ -1660,7 +1882,7 @@ var formulaic = { var frag = '
    ' + this.template + '
    '; var jqt = $(frag); var that = this; - jqt.find(":input").each(function() { + jqt.find(":input").each(function () { var el = $(this); var id = el.attr("id"); @@ -1701,7 +1923,7 @@ var formulaic = { edges.on(this.removeFieldBtns, "click", this, "removeField"); }; - this.removeField = function(element) { + this.removeField = function (element) { var container = $(element).parents("div[name='" + this.fieldDef["name"] + "__group']"); container.remove(); this.divs = $("div[name='" + this.fieldDef["name"] + "__group']"); @@ -1710,10 +1932,10 @@ var formulaic = { this.init(); }, - newMultipleField : function(params) { + newMultipleField: function (params) { return edges.instantiate(formulaic.widgets.MultipleField, params) }, - MultipleField: function(params) { + MultipleField: function (params) { this.fieldDef = params.fieldDef; this.max = this.fieldDef["repeatable"]["initial"] - 1; @@ -1726,7 +1948,7 @@ var formulaic = { feather.replace(); }; - this._setupIndividualSelect2 = function() { + this._setupIndividualSelect2 = function () { for (var idx = 0; idx < this.fields.length; idx++) { let f = this.fields[idx]; let s2_input = $($(f).select2()); @@ -1786,7 +2008,7 @@ var formulaic = { }) }; - this._setupIndividualField = function() { + this._setupIndividualField = function () { for (var idx = 0; idx < this.fields.length; idx++) { let f = this.fields[idx]; let jqf = $(f); @@ -1809,7 +2031,7 @@ var formulaic = { this.addFieldBtn = $("#add_field__" + this.fieldDef["name"]); this.addFieldBtn.on("click", () => { - let next_input = $('[id="' + this.fieldDef["name"] + '-' + (this.count + 1) +'"]').parent(); + let next_input = $('[id="' + this.fieldDef["name"] + '-' + (this.count + 1) + '"]').parent(); // TODO: why .show() does not work? $(next_input).show(); this.count++; @@ -1837,7 +2059,7 @@ var formulaic = { this.count--; $(this.fields[this.count + 1]).val(""); - let last_input = $('[id="' + this.fieldDef["name"] + '-' + (this.count + 1) +'"]').parent(); + let last_input = $('[id="' + this.fieldDef["name"] + '-' + (this.count + 1) + '"]').parent(); $(last_input).hide(); if (this.count === 0) { $(this.remove_btns[0]).hide(); @@ -1849,19 +2071,19 @@ var formulaic = { }); }; - this._setupRepeatingIndividual = function() { + this._setupRepeatingIndividual = function () { let tag = this.fieldDef["input"] === "select" ? "select" : "input"; this.fields = $(tag + '[id^="' + this.fieldDef["name"] + '-"]'); this.count = 0; - if (tag === "select"){ + if (tag === "select") { this._setupIndividualSelect2(); } else { this._setupIndividualField(); } }; - this._setupRepeatingGroup = function() { + this._setupRepeatingGroup = function () { this.divs = $("div[name='" + this.fieldDef["name"] + "__group']"); this.count = 0; @@ -1918,28 +2140,26 @@ var formulaic = { nextDiv = nextDiv.next(); let thisInputs = $(thisDiv).find("select, input[id^='" + this.fieldDef["name"] + "']"); let nextInputs = $(nextDiv).find("select, input[id^='" + this.fieldDef["name"] + "']"); - for (let j = 0; j < thisInputs.length; j++){ + for (let j = 0; j < thisInputs.length; j++) { let thisInput = $(thisInputs[j]); let nextInput = $(nextInputs[j]); - if (thisInput.is("select")){ + if (thisInput.is("select")) { let data = $(nextInput).select2('data'); if (data === null) { data = {id: i, text: ""}; } $(thisInput).select2('data', {id: data.id, text: data.text}); - } - else { + } else { $(thisInputs[j]).val($(nextInputs[j]).val()); } } } this.count--; $(this.divs[this.count + 1]).find("select, input[id^='" + this.fieldDef["name"] + "']").each((idx, inp) => { - if ($(inp).is("select")){ + if ($(inp).is("select")) { $(inp).select2('data', {id: this.count + 1, text: ""}); - } - else { + } else { $(inp).val(""); } }); @@ -1957,10 +2177,10 @@ var formulaic = { this.init() }, - newSelect : function(params) { + newSelect: function (params) { return edges.instantiate(formulaic.widgets.Select, params); }, - Select : function(params) { + Select: function (params) { this.fieldDef = params.fieldDef; this.form = params.formulaic; this.args = params.args; @@ -1968,7 +2188,7 @@ var formulaic = { this.ns = "formulaic-select"; this.elements = false; - this.init = function() { + this.init = function () { let allow_clear = this.args.allow_clear || false; this.elements = $("select[name$='" + this.fieldDef.name + "']"); this.elements.select2({ @@ -1982,17 +2202,17 @@ var formulaic = { this.init(); }, - newTagList : function(params) { + newTagList: function (params) { return edges.instantiate(formulaic.widgets.TagList, params); }, - TagList : function(params) { + TagList: function (params) { this.fieldDef = params.fieldDef; this.form = params.formulaic; this.args = params.args; this.ns = "formulaic-taglist"; - this.init = function() { + this.init = function () { var stopWords = edges.getParam(this.args.stopWords, []); var ajax = { @@ -2049,17 +2269,17 @@ var formulaic = { this.init(); }, - newTagEntry : function(params) { + newTagEntry: function (params) { return edges.instantiate(formulaic.widgets.TagEntry, params); }, - TagEntry : function(params) { + TagEntry: function (params) { this.fieldDef = params.fieldDef; this.form = params.formulaic; this.args = params.args; this.ns = "formulaic-tagentry"; - this.init = function() { + this.init = function () { let selector = "[name='" + this.fieldDef.name + "']"; $(selector).select2({ minimumInputLength: 1, @@ -2074,50 +2294,44 @@ var formulaic = { }, - - newLoadEditors: function(params) { + newLoadEditors: function (params) { return edges.instantiate(formulaic.widgets.LoadEditors, params); }, - LoadEditors: function(params) { + LoadEditors: function (params) { this.fieldDef = params.fieldDef; this.params = params.args; this.groupField = false; this.editorField = false; - this.init = function() { + this.init = function () { this.groupField = $("[name='" + this.fieldDef.name + "']"); this.editorField = $("[name='" + this.params.field + "']"); edges.on(this.groupField, "change", this, "updateEditors"); }; - this.updateEditors = function(element) { + this.updateEditors = function (element) { var ed_group_name = $(element).val(); var ed_query_url = "/admin/dropdown/eg_associates"; // var ed_group_name = $("#s2id_editor_group").find('span').text(); var that = this; $.ajax({ - type : "GET", - data : {egn : ed_group_name}, + type: "GET", + data: {egn: ed_group_name}, dataType: "json", url: ed_query_url, - success: function(resp) - { + success: function (resp) { // Get the options for the drop-down from our ajax request var assoc_options = []; - if (resp != null) - { + if (resp != null) { assoc_options = [["", "No editor assigned"]]; - for (var i=0; i").attr("value", assoc_options[j][0]).text(assoc_options[j][1]) ); @@ -2137,15 +2351,15 @@ var formulaic = { this.init(); }, - newAutocomplete: function(params){ + newAutocomplete: function (params) { return edges.instantiate(formulaic.widgets.Autocomplete, params); }, - Autocomplete: function(params){ + Autocomplete: function (params) { this.fieldDef = params.fieldDef; this.params = params.args; - this.init = function() { + this.init = function () { let doc_type = this.params.type || "journal"; let doc_field = this.params.field; let mininput = this.params.min_input === undefined ? 3 : this.params.min_input; @@ -2161,11 +2375,13 @@ var formulaic = { }; }, results: function (data, page) { - return { results: data["suggestions"] }; + return {results: data["suggestions"]}; } }; - var csc = function(term) {return {"id":term, "text": term};}; + var csc = function (term) { + return {"id": term, "text": term}; + }; var initSel = function (element, callback) { var data = {id: element.val(), text: element.val()}; @@ -2182,7 +2398,7 @@ var formulaic = { minimumInputLength: mininput, ajax: ajax, createSearchChoice: csc, - initSelection : initSel, + initSelection: initSel, allowClear: allow_clear, width: 'resolve' }); @@ -2191,7 +2407,7 @@ var formulaic = { $(selector).select2({ minimumInputLength: mininput, ajax: ajax, - initSelection : initSel, + initSelection: initSel, allowClear: allow_clear, width: 'resolve' }); @@ -2202,10 +2418,10 @@ var formulaic = { this.init() }, - newIssnLink : function(params) { + newIssnLink: function (params) { return edges.instantiate(formulaic.widgets.IssnLink, params) }, - IssnLink : function(params) { + IssnLink: function (params) { this.fieldDef = params.fieldDef; this.form = params.formulaic; this.issn = params.issn; @@ -2215,7 +2431,7 @@ var formulaic = { this.link = false; this.url = "https://portal.issn.org/resource/ISSN/"; - this.init = function() { + this.init = function () { var elements = this.form.controlSelect.input( {name: this.fieldDef.name}); edges.on(elements, "keyup.IssnLink", this, "updateUrl"); @@ -2225,7 +2441,7 @@ var formulaic = { } }; - this.updateUrl = function(element) { + this.updateUrl = function (element) { var that = $(element); var val = that.val(); var id = edges.css_id(this.ns, this.fieldDef.name); diff --git a/portality/templates/application_form/js/_form_js.html b/portality/templates/application_form/js/_form_js.html index 1ee02b0ea3..84949df351 100644 --- a/portality/templates/application_form/js/_form_js.html +++ b/portality/templates/application_form/js/_form_js.html @@ -1,3 +1,4 @@ + From ab19b25429718e9099b666a0a8f29d7d46070859 Mon Sep 17 00:00:00 2001 From: Aga Date: Thu, 12 Sep 2024 11:11:01 +0100 Subject: [PATCH 4/9] edges changes --- portality/static/vendor/edges | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/portality/static/vendor/edges b/portality/static/vendor/edges index 990f422016..5b74a45712 160000 --- a/portality/static/vendor/edges +++ b/portality/static/vendor/edges @@ -1 +1 @@ -Subproject commit 990f4220163a3e18880f0bdc3ad5c80d234d22dd +Subproject commit 5b74a457128d66588b32c58848891dee38f64765 From 4ad068d7da4d1aa333e522d38a7592b40d644eb4 Mon Sep 17 00:00:00 2001 From: Aga Date: Mon, 16 Sep 2024 11:47:36 +0100 Subject: [PATCH 5/9] changes to edges --- portality/static/vendor/edges | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/portality/static/vendor/edges b/portality/static/vendor/edges index 5b74a45712..6c8f1e8f46 160000 --- a/portality/static/vendor/edges +++ b/portality/static/vendor/edges @@ -1 +1 @@ -Subproject commit 5b74a457128d66588b32c58848891dee38f64765 +Subproject commit 6c8f1e8f464de1e9840ad75d87afbe50cdc07551 From fc6663084f1dc4d0520247bcc4f0712f084d669f Mon Sep 17 00:00:00 2001 From: Aga Date: Mon, 23 Sep 2024 12:39:22 +0100 Subject: [PATCH 6/9] search tree selector works --- portality/static/js/doaj.fieldrender.edges.js | 2 ++ portality/static/vendor/edges | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/portality/static/js/doaj.fieldrender.edges.js b/portality/static/js/doaj.fieldrender.edges.js index e28653030c..60d4a9660d 100644 --- a/portality/static/js/doaj.fieldrender.edges.js +++ b/portality/static/js/doaj.fieldrender.edges.js @@ -907,6 +907,8 @@ $.extend(true, doaj, { term = term.toLowerCase(); function entryMatch(entry) { + console.log("entryMatch") + console.log(entry) if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { return false; } diff --git a/portality/static/vendor/edges b/portality/static/vendor/edges index 6c8f1e8f46..4df9898589 160000 --- a/portality/static/vendor/edges +++ b/portality/static/vendor/edges @@ -1 +1 @@ -Subproject commit 6c8f1e8f464de1e9840ad75d87afbe50cdc07551 +Subproject commit 4df98985894b004b5711597d32d4c4fb26cc6fad From 2c7ae60153393f1792a598e9fa10647d627cb759 Mon Sep 17 00:00:00 2001 From: Aga Date: Mon, 23 Sep 2024 13:28:55 +0100 Subject: [PATCH 7/9] form subject selector --- portality/static/js/doaj.fieldrender.edges.js | 4 +- portality/static/js/formulaic.js | 609 +++++++++--------- .../application_form/js/_form_js.html | 2 +- 3 files changed, 308 insertions(+), 307 deletions(-) diff --git a/portality/static/js/doaj.fieldrender.edges.js b/portality/static/js/doaj.fieldrender.edges.js index 60d4a9660d..7f0de89013 100644 --- a/portality/static/js/doaj.fieldrender.edges.js +++ b/portality/static/js/doaj.fieldrender.edges.js @@ -597,7 +597,7 @@ $.extend(true, doaj, { } } }, - + // SubjectBrowserRenderer! newSubjectBrowser: function (params) { return edges.instantiate(doaj.renderers.SubjectBrowser, params, edges.newRenderer); }, @@ -907,8 +907,6 @@ $.extend(true, doaj, { term = term.toLowerCase(); function entryMatch(entry) { - console.log("entryMatch") - console.log(entry) if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { return false; } diff --git a/portality/static/js/formulaic.js b/portality/static/js/formulaic.js index 297538460d..99f2bec0a2 100644 --- a/portality/static/js/formulaic.js +++ b/portality/static/js/formulaic.js @@ -597,8 +597,7 @@ var formulaic = { edges: { newTreeBrowser: function (params) { - // return edges.instantiate(formulaic.edges.TreeBrowserForm, params, edges.newComponent); - return edges.instantiate(formulaic.edges.TreeBrowserForm, params, edges.TreeBrowserCore); + return edges.instantiate(formulaic.edges.TreeBrowserForm, params, edges.newTreeBrowserCore); }, TreeBrowserForm: function (params) { this.sourceInput = edges.getParam(params.sourceInput, false); @@ -628,11 +627,13 @@ var formulaic = { var that = this; var processNode = function (node) { + node.index = that.nodeIndex ? that.nodeIndex(node) : node.display; if (that.filterMatch(node, selected)) { node.selected = true; anySelected = true; + return true; } - node.index = that.nodeIndex ? that.nodeIndex(node) : node.display; + return false; }; var path = []; @@ -994,304 +995,304 @@ var formulaic = { }; },*/ - newSubjectBrowserRenderer: function (params) { - return edges.instantiate(formulaic.edges.SubjectBrowserRenderer, params, edges.newRenderer); - }, - SubjectBrowserRenderer: function (params) { - console.log("formulaic.edges.SubjectBrowserRenderer") - edges.newRenderer().call(params); - this.title = edges.getParam(params.title, ""); - this.hideEmpty = edges.getParam(params.hideEmpty, false); - this.expanded = []; - this.lastScroll = 0; - this.namespace = "formulaic-subject-browser"; - - this.draw = function () { - console.log("formulaic.edges.SubjectBrowserRenderer.draw") - // for convenient short references ... - var st = this.component.syncTree; - var namespace = this.namespace; - // var that = this; - - // var checkboxClass = edges.css_classes(namespace, "selector", this); - // var countClass = edges.css_classes(namespace, "count", this); - - var treeReport = this._renderTree({tree: st, selectedPathOnly: false, showOneLevel: true}); - var treeFrag = treeReport.frag; - - if (treeFrag === "") { - treeFrag = "Loading..."; - } - - var toggleId = edges.css_id(namespace, "toggle", this); - var resultsId = edges.css_id(namespace, "results", this); - var searchId = edges.css_id(namespace, "search", this); - var filteredId = edges.css_id(namespace, "filtered", this); - var mainListId = edges.css_id(namespace, "main", this); - - var toggle = ""; - if (this.togglable) { - toggle = ''; - } - var frag = '

    ' + this.title + toggle + '

    \ - '; - - // substitute in the component parts - frag = frag.replace(/{{FILTERS}}/g, treeFrag); - - // now render it into the page - this.component.context.html(frag); - feather.replace(); - - var mainListSelector = edges.css_id_selector(namespace, "main", this); - this.component.jq(mainListSelector).scrollTop(this.lastScroll); - - var checkboxSelector = edges.css_class_selector(namespace, "selector", this); - edges.on(checkboxSelector, "change", this, "filterToggle"); - - var searchSelector = edges.css_id_selector(namespace, "search", this); - edges.on(searchSelector, "keyup", this, "filterSubjects"); - - var fieldSelector = edges.css_class_selector(namespace, "field-toggle", this); - edges.on(fieldSelector, "click", this, "fieldToggle"); - }; - - this._renderTree = function (params) { - var st = edges.getParam(params.tree, []); - var selectedPathOnly = edges.getParam(params.selectedPathOnly, true); - var showOneLevel = edges.getParam(params.showOneLevel, true); - var that = this; - - var checkboxClass = edges.css_classes(this.namespace, "selector", this); - var toggleClass = edges.css_classes(that.namespace, "field-toggle", this); - - function renderEntry(entry) { - if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { - return ""; - } - - var id = edges.safeId(entry.value); - var checked = ""; - if (entry.selected) { - checked = ' checked="checked" '; - } - - // the various rules to do with how this will toggle. - // - whether the toggle is linked -> only when clickng it will have an effect - // - whether the thing is togglable at all -> only when there are children - var toggle = ""; - var chevron = ""; - var togglable = false; - if (entry.children) { - chevron = "chevron-right"; - togglable = true; - if (entry.expanded) { - chevron = "chevron-down"; - } - if (entry.selected) { - togglable = false; - } - } - - if (togglable) { - toggle = ''; - toggle = '' + toggle + 'Toggle this subject'; - } - // FIXME: putting this in for the moment, just so we can use it in dev - // var count = ' (' + entry.count + '/' + entry.childCount + ')'; - var count = ""; - - var frag = '\ - '; - - return frag; - } - - function recurse(tree) { - var selected = tree; - - // first check to see if there are any elements at this level that are selected. If there are, - // that is the only element that we'll render - if (selectedPathOnly) { - for (var i = 0; i < tree.length; i++) { - var entry = tree[i]; - if (entry.selected) { - selected = [entry]; - break; - } - } - } - - // now go through either this tree level or just the selected elements, and render the relevant - // bits of the sub-tree - var anySelected = false; - var rFrag = ""; - for (var i = 0; i < selected.length; i++) { - var entry = selected[i]; - entry.expanded = $.inArray(entry.value, that.expanded) > -1; - var entryFrag = renderEntry(entry); - if (entryFrag === "") { - continue; - } - if (entry.selected) { - anySelected = true; - } - if (entry.children) { - var childReport = recurse(entry.children); - if (childReport.anySelected) { - anySelected = true; - } - // only attach the children frag if, first any of these are true: - // - one of the children is selected - // - the entry itself is selected - // - we don't want to only show the selected path - // - the entry has been expanded - if (!selectedPathOnly || childReport.anySelected || entry.selected || entry.expanded) { - // Then, another level (separated out to save my brain from the tortuous logic) - // only attach the children frag if, any of these are true: - // - the entry or one of its children is selected - // - we want to show more than one level at a time - // - the entry has been expanded - if (childReport.anySelected || entry.selected || !showOneLevel || entry.expanded) { - var cFrag = childReport.frag; - if (cFrag !== "") { - entryFrag += '
      '; - entryFrag += cFrag; - entryFrag += '
    '; - } - } - } - } - - rFrag += '
  • '; - rFrag += entryFrag; - rFrag += '
  • '; - } - return {frag: rFrag, anySelected: anySelected}; - } - - return recurse(st); - }; - - this.fieldToggle = function (element) { - var value = this.component.jq(element).attr("data-value"); - - var existing = $.inArray(value, this.expanded); - if (existing > -1) { - this.expanded.splice(existing, 1); - } else { - this.expanded.push(value); - } - - var mainListSelector = edges.css_id_selector(this.namespace, "main", this); - this.lastScroll = this.component.jq(mainListSelector).scrollTop(); - this.component.edge.cycle(); - }; - - this.filterToggle = function (element) { - var mainListSelector = edges.css_id_selector(this.namespace, "main", this); - this.lastScroll = this.component.jq(mainListSelector).scrollTop(); - - // var filter_id = this.component.jq(element).attr("id"); - var checked = this.component.jq(element).is(":checked"); - var value = this.component.jq(element).attr("data-value"); - if (checked) { - this.component.addFilter({value: value}); - } else { - this.component.removeFilter({value: value}); - } - }; - - this.filterSubjects = function (element) { - var st = this.component.syncTree; - var term = $(element).val(); - var that = this; - - var filterSelector = edges.css_id_selector(this.namespace, "filtered", this); - var mainSelector = edges.css_id_selector(this.namespace, "main", this); - var filterEl = this.component.jq(filterSelector); - var mainEl = this.component.jq(mainSelector); - - if (term === "") { - filterEl.html(""); - filterEl.hide(); - mainEl.show(); - return; - } - if (term.length < 3) { - filterEl.html("
  • Enter 3 characters or more to search
  • "); - filterEl.show(); - mainEl.hide(); - return; - } - term = term.toLowerCase(); - - function entryMatch(entry) { - if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { - return false; - } - - var matchTerm = entry.index; - var includes = matchTerm.includes(term); - if (includes) { - var idx = matchTerm.indexOf(term); - var display = entry.display; - return display.substring(0, idx) + "" + display.substring(idx, idx + term.length) + "" + display.substring(idx + term.length); - } - } - - function recurse(tree) { - var filteredLayer = []; - for (var i = 0; i < tree.length; i++) { - var entry = tree[i]; - var childReport = []; - if (entry.children) { - childReport = recurse(entry.children); - } - var selfMatch = entryMatch(entry); - if (selfMatch || childReport.length > 0) { - var newEntry = $.extend({}, entry); - delete newEntry.children; - if (selfMatch) { - newEntry.display = selfMatch; - } - if (childReport.length > 0) { - newEntry.children = childReport; - } - filteredLayer.push(newEntry); - } - } - return filteredLayer; - } - - var filtered = recurse(st); - - if (filtered.length > 0) { - var displayReport = this._renderTree({ - tree: filtered, - selectedPathOnly: false, - showOneLevel: false - }); - - filterEl.html(displayReport.frag); - mainEl.hide(); - filterEl.show(); - - var checkboxSelector = edges.css_class_selector(this.namespace, "selector", this); - edges.on(checkboxSelector, "change", this, "filterToggle"); - } else { - filterEl.html("
  • No subjects match your search
  • "); - mainEl.hide(); - filterEl.show(); - } - - }; - } + // newSubjectBrowserRenderer: function (params) { + // return edges.instantiate(formulaic.edges.SubjectBrowserRenderer, params, edges.newRenderer); + // }, + // SubjectBrowserRenderer: function (params) { + // console.log("formulaic.edges.SubjectBrowserRenderer") + // edges.newRenderer().call(params); + // this.title = edges.getParam(params.title, ""); + // this.hideEmpty = edges.getParam(params.hideEmpty, false); + // this.expanded = []; + // this.lastScroll = 0; + // this.namespace = "formulaic-subject-browser"; + // + // this.draw = function () { + // console.log("formulaic.edges.SubjectBrowserRenderer.draw") + // // for convenient short references ... + // var st = this.component.syncTree; + // var namespace = this.namespace; + // // var that = this; + // + // // var checkboxClass = edges.css_classes(namespace, "selector", this); + // // var countClass = edges.css_classes(namespace, "count", this); + // + // var treeReport = this._renderTree({tree: st, selectedPathOnly: false, showOneLevel: true}); + // var treeFrag = treeReport.frag; + // + // if (treeFrag === "") { + // treeFrag = "Loading..."; + // } + // + // var toggleId = edges.css_id(namespace, "toggle", this); + // var resultsId = edges.css_id(namespace, "results", this); + // var searchId = edges.css_id(namespace, "search", this); + // var filteredId = edges.css_id(namespace, "filtered", this); + // var mainListId = edges.css_id(namespace, "main", this); + // + // var toggle = ""; + // if (this.togglable) { + // toggle = ''; + // } + // var frag = '

    ' + this.title + toggle + '

    \ + // '; + // + // // substitute in the component parts + // frag = frag.replace(/{{FILTERS}}/g, treeFrag); + // + // // now render it into the page + // this.component.context.html(frag); + // feather.replace(); + // + // var mainListSelector = edges.css_id_selector(namespace, "main", this); + // this.component.jq(mainListSelector).scrollTop(this.lastScroll); + // + // var checkboxSelector = edges.css_class_selector(namespace, "selector", this); + // edges.on(checkboxSelector, "change", this, "filterToggle"); + // + // var searchSelector = edges.css_id_selector(namespace, "search", this); + // edges.on(searchSelector, "keyup", this, "filterSubjects"); + // + // var fieldSelector = edges.css_class_selector(namespace, "field-toggle", this); + // edges.on(fieldSelector, "click", this, "fieldToggle"); + // }; + // + // this._renderTree = function (params) { + // var st = edges.getParam(params.tree, []); + // var selectedPathOnly = edges.getParam(params.selectedPathOnly, true); + // var showOneLevel = edges.getParam(params.showOneLevel, true); + // var that = this; + // + // var checkboxClass = edges.css_classes(this.namespace, "selector", this); + // var toggleClass = edges.css_classes(that.namespace, "field-toggle", this); + // + // function renderEntry(entry) { + // if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { + // return ""; + // } + // + // var id = edges.safeId(entry.value); + // var checked = ""; + // if (entry.selected) { + // checked = ' checked="checked" '; + // } + // + // // the various rules to do with how this will toggle. + // // - whether the toggle is linked -> only when clickng it will have an effect + // // - whether the thing is togglable at all -> only when there are children + // var toggle = ""; + // var chevron = ""; + // var togglable = false; + // if (entry.children) { + // chevron = "chevron-right"; + // togglable = true; + // if (entry.expanded) { + // chevron = "chevron-down"; + // } + // if (entry.selected) { + // togglable = false; + // } + // } + // + // if (togglable) { + // toggle = ''; + // toggle = '' + toggle + 'Toggle this subject'; + // } + // // FIXME: putting this in for the moment, just so we can use it in dev + // // var count = ' (' + entry.count + '/' + entry.childCount + ')'; + // var count = ""; + // + // var frag = '\ + // '; + // + // return frag; + // } + // + // function recurse(tree) { + // var selected = tree; + // + // // first check to see if there are any elements at this level that are selected. If there are, + // // that is the only element that we'll render + // if (selectedPathOnly) { + // for (var i = 0; i < tree.length; i++) { + // var entry = tree[i]; + // if (entry.selected) { + // selected = [entry]; + // break; + // } + // } + // } + // + // // now go through either this tree level or just the selected elements, and render the relevant + // // bits of the sub-tree + // var anySelected = false; + // var rFrag = ""; + // for (var i = 0; i < selected.length; i++) { + // var entry = selected[i]; + // entry.expanded = $.inArray(entry.value, that.expanded) > -1; + // var entryFrag = renderEntry(entry); + // if (entryFrag === "") { + // continue; + // } + // if (entry.selected) { + // anySelected = true; + // } + // if (entry.children) { + // var childReport = recurse(entry.children); + // if (childReport.anySelected) { + // anySelected = true; + // } + // // only attach the children frag if, first any of these are true: + // // - one of the children is selected + // // - the entry itself is selected + // // - we don't want to only show the selected path + // // - the entry has been expanded + // if (!selectedPathOnly || childReport.anySelected || entry.selected || entry.expanded) { + // // Then, another level (separated out to save my brain from the tortuous logic) + // // only attach the children frag if, any of these are true: + // // - the entry or one of its children is selected + // // - we want to show more than one level at a time + // // - the entry has been expanded + // if (childReport.anySelected || entry.selected || !showOneLevel || entry.expanded) { + // var cFrag = childReport.frag; + // if (cFrag !== "") { + // entryFrag += '
      '; + // entryFrag += cFrag; + // entryFrag += '
    '; + // } + // } + // } + // } + // + // rFrag += '
  • '; + // rFrag += entryFrag; + // rFrag += '
  • '; + // } + // return {frag: rFrag, anySelected: anySelected}; + // } + // + // return recurse(st); + // }; + // + // this.fieldToggle = function (element) { + // var value = this.component.jq(element).attr("data-value"); + // + // var existing = $.inArray(value, this.expanded); + // if (existing > -1) { + // this.expanded.splice(existing, 1); + // } else { + // this.expanded.push(value); + // } + // + // var mainListSelector = edges.css_id_selector(this.namespace, "main", this); + // this.lastScroll = this.component.jq(mainListSelector).scrollTop(); + // this.component.edge.cycle(); + // }; + // + // this.filterToggle = function (element) { + // var mainListSelector = edges.css_id_selector(this.namespace, "main", this); + // this.lastScroll = this.component.jq(mainListSelector).scrollTop(); + // + // // var filter_id = this.component.jq(element).attr("id"); + // var checked = this.component.jq(element).is(":checked"); + // var value = this.component.jq(element).attr("data-value"); + // if (checked) { + // this.component.addFilter({value: value}); + // } else { + // this.component.removeFilter({value: value}); + // } + // }; + // + // this.filterSubjects = function (element) { + // var st = this.component.syncTree; + // var term = $(element).val(); + // var that = this; + // + // var filterSelector = edges.css_id_selector(this.namespace, "filtered", this); + // var mainSelector = edges.css_id_selector(this.namespace, "main", this); + // var filterEl = this.component.jq(filterSelector); + // var mainEl = this.component.jq(mainSelector); + // + // if (term === "") { + // filterEl.html(""); + // filterEl.hide(); + // mainEl.show(); + // return; + // } + // if (term.length < 3) { + // filterEl.html("
  • Enter 3 characters or more to search
  • "); + // filterEl.show(); + // mainEl.hide(); + // return; + // } + // term = term.toLowerCase(); + // + // function entryMatch(entry) { + // if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { + // return false; + // } + // + // var matchTerm = entry.index; + // var includes = matchTerm.includes(term); + // if (includes) { + // var idx = matchTerm.indexOf(term); + // var display = entry.display; + // return display.substring(0, idx) + "" + display.substring(idx, idx + term.length) + "" + display.substring(idx + term.length); + // } + // } + // + // function recurse(tree) { + // var filteredLayer = []; + // for (var i = 0; i < tree.length; i++) { + // var entry = tree[i]; + // var childReport = []; + // if (entry.children) { + // childReport = recurse(entry.children); + // } + // var selfMatch = entryMatch(entry); + // if (selfMatch || childReport.length > 0) { + // var newEntry = $.extend({}, entry); + // delete newEntry.children; + // if (selfMatch) { + // newEntry.display = selfMatch; + // } + // if (childReport.length > 0) { + // newEntry.children = childReport; + // } + // filteredLayer.push(newEntry); + // } + // } + // return filteredLayer; + // } + // + // var filtered = recurse(st); + // + // if (filtered.length > 0) { + // var displayReport = this._renderTree({ + // tree: filtered, + // selectedPathOnly: false, + // showOneLevel: false + // }); + // + // filterEl.html(displayReport.frag); + // mainEl.hide(); + // filterEl.show(); + // + // var checkboxSelector = edges.css_class_selector(this.namespace, "selector", this); + // edges.on(checkboxSelector, "change", this, "filterToggle"); + // } else { + // filterEl.html("
  • No subjects match your search
  • "); + // mainEl.hide(); + // filterEl.show(); + // } + // + // }; + // } }, widgets: { @@ -1484,8 +1485,10 @@ var formulaic = { nodeIndex: function (node) { return node.display.toLowerCase(); }, - renderer: doaj.renderers.newSubjectBrowserRenderer({ - title: "Subjects" + renderer: doaj.renderers.newSubjectBrowser({ + title: "Subjects", + open: true, + showCounts: false }) }); diff --git a/portality/templates/application_form/js/_form_js.html b/portality/templates/application_form/js/_form_js.html index 84949df351..24c00d3bb4 100644 --- a/portality/templates/application_form/js/_form_js.html +++ b/portality/templates/application_form/js/_form_js.html @@ -1,6 +1,6 @@ - + {# #} From 3cfb6dc093c06536599a5c3e625b141e165cebdc Mon Sep 17 00:00:00 2001 From: Aga Date: Mon, 23 Sep 2024 13:48:08 +0100 Subject: [PATCH 8/9] remove comments and console.logs --- portality/static/js/formulaic.js | 555 +------------------------------ portality/static/vendor/edges | 2 +- 2 files changed, 2 insertions(+), 555 deletions(-) diff --git a/portality/static/js/formulaic.js b/portality/static/js/formulaic.js index 99f2bec0a2..12bdee0175 100644 --- a/portality/static/js/formulaic.js +++ b/portality/static/js/formulaic.js @@ -604,7 +604,6 @@ var formulaic = { this.selected = []; this.init = function (edge) { - console.log("formulaic.edges.TreeBrowserForm") // first kick the request up to the superclass edges.newTreeBrowserCore().init.call(this, edge); @@ -621,7 +620,6 @@ var formulaic = { }; this.synchronise = function () { - console.log("formulaic.edges.TreeBrowserForm.synchonise") this.syncTree = $.extend(true, [], this.tree); var selected = this.selected; var that = this; @@ -640,258 +638,6 @@ var formulaic = { this.baseRecurse(this.syncTree, path, processNode); }; - // this.synchronise = function() { - // - // this.syncTree = $.extend(true, [], this.tree); - // var selected = this.selected; - // var that = this; - // - // function recurse(tree, path) { - // var anySelected = false; - // var childCount = 0; - // - // for (var i = 0; i < tree.length; i++) { - // var node = tree[i]; - // that.nodeCount++; - // - // that.parentIndex[node.value] = $.extend(true, [], path); - // - // if (that.filterMatch(node, selected)) { - // node.selected = true; - // anySelected = true; - // } - // - // if (that.nodeIndex) { - // node.index = that.nodeIndex(node); - // } else { - // node.index = node.display; - // } - // - // if (node.children) { - // path.push(node.value); - // var childReport = recurse(node.children, path); - // path.pop(); - // if (childReport.anySelected) { - // node.selected = true; - // anySelected = true; - // } - // childCount += childReport.childCount; - // node.childCount = childReport.childCount; - // } else { - // node.childCount = 0; - // } - // - // } - // return {anySelected: anySelected, childCount: childCount} - // } - // var path = []; - // recurse(this.syncTree, path); - // }; - - this.addFilter = function (params) { - console.log("formulaic.edges.TreeBrowserForm.addFilter") - var value = params.value; - var parents = this.parentIndex[value]; - var terms = [params.value]; - var clearOthers = edges.getParam(params.clearOthers, false); - - var newValues = $.extend(true, [], this.selected); - - // if there is, just add the term to it (removing and parent terms along the way) - if (newValues.length > 0) { - newValues.sort(); - - // if this is an exclusive filter that clears all others, just do that - if (clearOthers) { - newValues = []; - } - - // next, if there are any terms left, remove all the parent terms - for (var i = 0; i < parents.length; i++) { - var parent = parents[i]; - var location = $.inArray(parent, newValues); - if (location !== -1) { - newValues.splice(location, 1); - } - } - - // now add all the provided terms - var hadTermAlready = 0; - for (var i = 0; i < terms.length; i++) { - var term = terms[i]; - if ($.inArray(term, newValues) !== -1) { - hadTermAlready++; - } else { - newValues.push(term); - } - } - } else { - newValues = terms; - } - - // store the new values on the object and in the form - this.selected = newValues; - this.sourceInput.val(newValues.join(",")); - this.sourceInput.trigger("change"); - this.edge.cycle(); - return true; - }; - - this.removeFilter = function (params) { - console.log("formulaic.edges.TreeBrowserForm.removeFilter") - var term = params.value; - - var newValues = $.extend(true, [], this.selected); - - if (newValues.length > 0) { - var location = $.inArray(term, newValues); - if (location !== -1) { - // the filter we are being asked to remove is the actual selected one - newValues.splice(location, 1); - } else { - // the filter we are being asked to remove may be a parent of the actual selected one - // first get all the parent sets of the values that are currently in force - var removes = []; - for (var i = 0; i < newValues.length; i++) { - var val = newValues[i]; - var parentSet = this.parentIndex[val]; - if ($.inArray(term, parentSet) > -1) { - removes.push(val); - } - } - for (var i = 0; i < removes.length; i++) { - var location = $.inArray(removes[i], newValues); - if (location !== -1) { - newValues.splice(location, 1); - } - } - } - - var grandparents = this.parentIndex[term]; - if (grandparents.length > 0) { - var immediate = grandparents[grandparents.length - 1]; - var sharedParent = false; - for (var i = 0; i < newValues.length; i++) { - var aunts = this.parentIndex[newValues[i]]; - if (aunts.length > 0 && aunts[aunts.length - 1] === immediate) { - sharedParent = true; - break; - } - } - if (!sharedParent && $.inArray(immediate, newValues) === -1) { - newValues.push(immediate); - } - } - } - - // reset the search page to the start and then trigger the next query - // store the new values on the object and in the form - this.selected = newValues; - this.sourceInput.val(newValues.join(",")); - this.sourceInput.trigger("change"); - this.edge.cycle(); - }; - }, - /*TreeBrowserForm: function (params) { - this.tree = edges.getParam(params.tree, {}); - - this.sourceInput = edges.getParam(params.sourceInput, false); - - this.nodeMatch = edges.getParam(params.nodeMatch, false); - - this.filterMatch = edges.getParam(params.filterMatch, false); - - this.nodeIndex = edges.getParam(params.nodeIndex, false); - - this.syncTree = []; - - this.parentIndex = {}; - - this.nodeCount = 0; - - this.selected = []; - - this.init = function (edge) { - // first kick the request up to the superclass - edges.newSelector().init.call(this, edge); - - // sourceInput can be false - // this is specific for the form, not the TreeBrowser itself - var text = this.sourceInput.val(); - if (text !== "") { - this.selected = text.split(",").map(function (x) { - return x.trim() - }) - } else { - this.selected = []; - } - }; - - this.synchronise = function () { - this.syncTree = $.extend(true, [], this.tree); - var selected = this.selected; - var that = this; - - var processNode = function (node) { - if (that.filterMatch(node, selected)) { - node.selected = true; - anySelected = true; - } - node.index = that.nodeIndex ? that.nodeIndex(node) : node.display; - }; - - var path = []; - this.baseRecurse(this.syncTree, path, processNode); - }; - - // this.synchronise = function() { - // - // this.syncTree = $.extend(true, [], this.tree); - // var selected = this.selected; - // var that = this; - // - // function recurse(tree, path) { - // var anySelected = false; - // var childCount = 0; - // - // for (var i = 0; i < tree.length; i++) { - // var node = tree[i]; - // that.nodeCount++; - // - // that.parentIndex[node.value] = $.extend(true, [], path); - // - // if (that.filterMatch(node, selected)) { - // node.selected = true; - // anySelected = true; - // } - // - // if (that.nodeIndex) { - // node.index = that.nodeIndex(node); - // } else { - // node.index = node.display; - // } - // - // if (node.children) { - // path.push(node.value); - // var childReport = recurse(node.children, path); - // path.pop(); - // if (childReport.anySelected) { - // node.selected = true; - // anySelected = true; - // } - // childCount += childReport.childCount; - // node.childCount = childReport.childCount; - // } else { - // node.childCount = 0; - // } - // - // } - // return {anySelected: anySelected, childCount: childCount} - // } - // var path = []; - // recurse(this.syncTree, path); - // }; - this.addFilter = function (params) { var value = params.value; var parents = this.parentIndex[value]; @@ -993,306 +739,7 @@ var formulaic = { this.sourceInput.trigger("change"); this.edge.cycle(); }; - },*/ - - // newSubjectBrowserRenderer: function (params) { - // return edges.instantiate(formulaic.edges.SubjectBrowserRenderer, params, edges.newRenderer); - // }, - // SubjectBrowserRenderer: function (params) { - // console.log("formulaic.edges.SubjectBrowserRenderer") - // edges.newRenderer().call(params); - // this.title = edges.getParam(params.title, ""); - // this.hideEmpty = edges.getParam(params.hideEmpty, false); - // this.expanded = []; - // this.lastScroll = 0; - // this.namespace = "formulaic-subject-browser"; - // - // this.draw = function () { - // console.log("formulaic.edges.SubjectBrowserRenderer.draw") - // // for convenient short references ... - // var st = this.component.syncTree; - // var namespace = this.namespace; - // // var that = this; - // - // // var checkboxClass = edges.css_classes(namespace, "selector", this); - // // var countClass = edges.css_classes(namespace, "count", this); - // - // var treeReport = this._renderTree({tree: st, selectedPathOnly: false, showOneLevel: true}); - // var treeFrag = treeReport.frag; - // - // if (treeFrag === "") { - // treeFrag = "Loading..."; - // } - // - // var toggleId = edges.css_id(namespace, "toggle", this); - // var resultsId = edges.css_id(namespace, "results", this); - // var searchId = edges.css_id(namespace, "search", this); - // var filteredId = edges.css_id(namespace, "filtered", this); - // var mainListId = edges.css_id(namespace, "main", this); - // - // var toggle = ""; - // if (this.togglable) { - // toggle = ''; - // } - // var frag = '

    ' + this.title + toggle + '

    \ - // '; - // - // // substitute in the component parts - // frag = frag.replace(/{{FILTERS}}/g, treeFrag); - // - // // now render it into the page - // this.component.context.html(frag); - // feather.replace(); - // - // var mainListSelector = edges.css_id_selector(namespace, "main", this); - // this.component.jq(mainListSelector).scrollTop(this.lastScroll); - // - // var checkboxSelector = edges.css_class_selector(namespace, "selector", this); - // edges.on(checkboxSelector, "change", this, "filterToggle"); - // - // var searchSelector = edges.css_id_selector(namespace, "search", this); - // edges.on(searchSelector, "keyup", this, "filterSubjects"); - // - // var fieldSelector = edges.css_class_selector(namespace, "field-toggle", this); - // edges.on(fieldSelector, "click", this, "fieldToggle"); - // }; - // - // this._renderTree = function (params) { - // var st = edges.getParam(params.tree, []); - // var selectedPathOnly = edges.getParam(params.selectedPathOnly, true); - // var showOneLevel = edges.getParam(params.showOneLevel, true); - // var that = this; - // - // var checkboxClass = edges.css_classes(this.namespace, "selector", this); - // var toggleClass = edges.css_classes(that.namespace, "field-toggle", this); - // - // function renderEntry(entry) { - // if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { - // return ""; - // } - // - // var id = edges.safeId(entry.value); - // var checked = ""; - // if (entry.selected) { - // checked = ' checked="checked" '; - // } - // - // // the various rules to do with how this will toggle. - // // - whether the toggle is linked -> only when clickng it will have an effect - // // - whether the thing is togglable at all -> only when there are children - // var toggle = ""; - // var chevron = ""; - // var togglable = false; - // if (entry.children) { - // chevron = "chevron-right"; - // togglable = true; - // if (entry.expanded) { - // chevron = "chevron-down"; - // } - // if (entry.selected) { - // togglable = false; - // } - // } - // - // if (togglable) { - // toggle = ''; - // toggle = '' + toggle + 'Toggle this subject'; - // } - // // FIXME: putting this in for the moment, just so we can use it in dev - // // var count = ' (' + entry.count + '/' + entry.childCount + ')'; - // var count = ""; - // - // var frag = '\ - // '; - // - // return frag; - // } - // - // function recurse(tree) { - // var selected = tree; - // - // // first check to see if there are any elements at this level that are selected. If there are, - // // that is the only element that we'll render - // if (selectedPathOnly) { - // for (var i = 0; i < tree.length; i++) { - // var entry = tree[i]; - // if (entry.selected) { - // selected = [entry]; - // break; - // } - // } - // } - // - // // now go through either this tree level or just the selected elements, and render the relevant - // // bits of the sub-tree - // var anySelected = false; - // var rFrag = ""; - // for (var i = 0; i < selected.length; i++) { - // var entry = selected[i]; - // entry.expanded = $.inArray(entry.value, that.expanded) > -1; - // var entryFrag = renderEntry(entry); - // if (entryFrag === "") { - // continue; - // } - // if (entry.selected) { - // anySelected = true; - // } - // if (entry.children) { - // var childReport = recurse(entry.children); - // if (childReport.anySelected) { - // anySelected = true; - // } - // // only attach the children frag if, first any of these are true: - // // - one of the children is selected - // // - the entry itself is selected - // // - we don't want to only show the selected path - // // - the entry has been expanded - // if (!selectedPathOnly || childReport.anySelected || entry.selected || entry.expanded) { - // // Then, another level (separated out to save my brain from the tortuous logic) - // // only attach the children frag if, any of these are true: - // // - the entry or one of its children is selected - // // - we want to show more than one level at a time - // // - the entry has been expanded - // if (childReport.anySelected || entry.selected || !showOneLevel || entry.expanded) { - // var cFrag = childReport.frag; - // if (cFrag !== "") { - // entryFrag += '
      '; - // entryFrag += cFrag; - // entryFrag += '
    '; - // } - // } - // } - // } - // - // rFrag += '
  • '; - // rFrag += entryFrag; - // rFrag += '
  • '; - // } - // return {frag: rFrag, anySelected: anySelected}; - // } - // - // return recurse(st); - // }; - // - // this.fieldToggle = function (element) { - // var value = this.component.jq(element).attr("data-value"); - // - // var existing = $.inArray(value, this.expanded); - // if (existing > -1) { - // this.expanded.splice(existing, 1); - // } else { - // this.expanded.push(value); - // } - // - // var mainListSelector = edges.css_id_selector(this.namespace, "main", this); - // this.lastScroll = this.component.jq(mainListSelector).scrollTop(); - // this.component.edge.cycle(); - // }; - // - // this.filterToggle = function (element) { - // var mainListSelector = edges.css_id_selector(this.namespace, "main", this); - // this.lastScroll = this.component.jq(mainListSelector).scrollTop(); - // - // // var filter_id = this.component.jq(element).attr("id"); - // var checked = this.component.jq(element).is(":checked"); - // var value = this.component.jq(element).attr("data-value"); - // if (checked) { - // this.component.addFilter({value: value}); - // } else { - // this.component.removeFilter({value: value}); - // } - // }; - // - // this.filterSubjects = function (element) { - // var st = this.component.syncTree; - // var term = $(element).val(); - // var that = this; - // - // var filterSelector = edges.css_id_selector(this.namespace, "filtered", this); - // var mainSelector = edges.css_id_selector(this.namespace, "main", this); - // var filterEl = this.component.jq(filterSelector); - // var mainEl = this.component.jq(mainSelector); - // - // if (term === "") { - // filterEl.html(""); - // filterEl.hide(); - // mainEl.show(); - // return; - // } - // if (term.length < 3) { - // filterEl.html("
  • Enter 3 characters or more to search
  • "); - // filterEl.show(); - // mainEl.hide(); - // return; - // } - // term = term.toLowerCase(); - // - // function entryMatch(entry) { - // if (that.hideEmpty && entry.count === 0 && entry.childCount === 0) { - // return false; - // } - // - // var matchTerm = entry.index; - // var includes = matchTerm.includes(term); - // if (includes) { - // var idx = matchTerm.indexOf(term); - // var display = entry.display; - // return display.substring(0, idx) + "" + display.substring(idx, idx + term.length) + "" + display.substring(idx + term.length); - // } - // } - // - // function recurse(tree) { - // var filteredLayer = []; - // for (var i = 0; i < tree.length; i++) { - // var entry = tree[i]; - // var childReport = []; - // if (entry.children) { - // childReport = recurse(entry.children); - // } - // var selfMatch = entryMatch(entry); - // if (selfMatch || childReport.length > 0) { - // var newEntry = $.extend({}, entry); - // delete newEntry.children; - // if (selfMatch) { - // newEntry.display = selfMatch; - // } - // if (childReport.length > 0) { - // newEntry.children = childReport; - // } - // filteredLayer.push(newEntry); - // } - // } - // return filteredLayer; - // } - // - // var filtered = recurse(st); - // - // if (filtered.length > 0) { - // var displayReport = this._renderTree({ - // tree: filtered, - // selectedPathOnly: false, - // showOneLevel: false - // }); - // - // filterEl.html(displayReport.frag); - // mainEl.hide(); - // filterEl.show(); - // - // var checkboxSelector = edges.css_class_selector(this.namespace, "selector", this); - // edges.on(checkboxSelector, "change", this, "filterToggle"); - // } else { - // filterEl.html("
  • No subjects match your search
  • "); - // mainEl.hide(); - // filterEl.show(); - // } - // - // }; - // } + } }, widgets: { diff --git a/portality/static/vendor/edges b/portality/static/vendor/edges index 4df9898589..bbd3567e71 160000 --- a/portality/static/vendor/edges +++ b/portality/static/vendor/edges @@ -1 +1 @@ -Subproject commit 4df98985894b004b5711597d32d4c4fb26cc6fad +Subproject commit bbd3567e7158b3db0b627339d75852c42042e3b6 From d6c4e5791deb8bb039f16c327fb0019e10d13d51 Mon Sep 17 00:00:00 2001 From: Aga Date: Mon, 23 Sep 2024 14:00:12 +0100 Subject: [PATCH 9/9] change renderer name --- portality/static/js/doaj.fieldrender.edges.js | 9 ++++----- portality/static/js/formulaic.js | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/portality/static/js/doaj.fieldrender.edges.js b/portality/static/js/doaj.fieldrender.edges.js index 7f0de89013..7d9c5a21d6 100644 --- a/portality/static/js/doaj.fieldrender.edges.js +++ b/portality/static/js/doaj.fieldrender.edges.js @@ -410,7 +410,7 @@ $.extend(true, doaj, { nodeIndex: function (node) { return node.display.toLowerCase(); }, - renderer: doaj.renderers.newSubjectBrowser({ + renderer: doaj.renderers.newSubjectBrowserRenderer({ title: "Subjects", open: true, hideEmpty: hideEmpty, @@ -597,11 +597,10 @@ $.extend(true, doaj, { } } }, - // SubjectBrowserRenderer! - newSubjectBrowser: function (params) { - return edges.instantiate(doaj.renderers.SubjectBrowser, params, edges.newRenderer); + newSubjectBrowserRenderer: function (params) { + return edges.instantiate(doaj.renderers.SubjectBrowserRenderer, params, edges.newRenderer); }, - SubjectBrowser: function (params) { + SubjectBrowserRenderer: function (params) { this.title = edges.getParam(params.title, ""); this.selectMode = edges.getParam(params.selectMode, "multiple"); diff --git a/portality/static/js/formulaic.js b/portality/static/js/formulaic.js index 12bdee0175..8318328ca4 100644 --- a/portality/static/js/formulaic.js +++ b/portality/static/js/formulaic.js @@ -932,7 +932,7 @@ var formulaic = { nodeIndex: function (node) { return node.display.toLowerCase(); }, - renderer: doaj.renderers.newSubjectBrowser({ + renderer: doaj.renderers.newSubjectBrowserRenderer({ title: "Subjects", open: true, showCounts: false