Created
May 12, 2020 18:34
-
-
Save lorawoodford/69cf61d3ea0bae72dc1d6f9297d935bd to your computer and use it in GitHub Desktop.
ANW-700 draft
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//= require jquery.tokeninput | |
$(function() { | |
$.fn.linker = function() { | |
$(this).each(function() { | |
var $this = $(this); | |
var $linkerWrapper = $this.parents(".linker-wrapper:first"); | |
if ($this.hasClass("initialised")) { | |
return; | |
} | |
$this.addClass("initialised"); | |
// this is a bit hacky, but we need to have some input fields present in | |
// the form so we don't have to rely on the linker to make sure data | |
// presists. we can remove those after the linker does its thing. | |
$(".prelinker", $linkerWrapper).remove(); | |
var config = { | |
url: decodeURIComponent($this.data("url")), | |
browse_url: decodeURIComponent($this.data("browse-url")), | |
span_class: $this.data("span-class"), | |
format_template: $this.data("format_template"), | |
format_template_id: $this.data("format_template_id"), | |
format_property: $this.data("format_property"), | |
path: $this.data("path"), | |
name: $this.data("name"), | |
multiplicity: $this.data("multiplicity") || "many", | |
label: $this.data("label"), | |
label_plural: $this.data("label_plural"), | |
modal_id: $this.data("modal_id") || ($this.attr("id") + "_modal"), | |
sortable: $this.data("sortable") === true, | |
types: $this.data("types"), | |
exclude_ids: $this.data("exclude") || [] | |
}; | |
config.allow_multiple = config.multiplicity === "many"; | |
if (config.format_template && config.format_template.substring(0,2) != "${") { | |
config.format_template = "${" + config.format_template + "}"; | |
} | |
var renderCreateFormForObject = function(form_uri) { | |
var $modal = $("#"+config.modal_id); | |
var initCreateForm = function(formEl) { | |
$(".linker-container", $modal).html(formEl); | |
$("#createAndLinkButton", $modal).removeAttr("disabled"); | |
$("form", $modal).ajaxForm({ | |
data: { | |
inline: true | |
}, | |
beforeSubmit: function() { | |
$("#createAndLinkButton", $modal).attr("disabled","disabled"); | |
}, | |
success: function(response, status, xhr) { | |
if ($(response).is("form")) { | |
initCreateForm(response); | |
} else { | |
if (config.multiplicity === "one") { | |
clearTokens(); | |
} | |
$this.tokenInput("add", { | |
id: response.uri, | |
name: response.display_string || response.title, | |
json: response | |
}); | |
$this.triggerHandler("change"); | |
$modal.modal("hide"); | |
} | |
}, | |
error: function(obj, errorText, errorDesc) { | |
$("#createAndLinkButton", $modal).removeAttr("disabled"); | |
} | |
}); | |
$modal.scrollTo(".alert"); | |
$modal.trigger("resize"); | |
$(document).triggerHandler("loadedrecordform.aspace", [$modal]); | |
}; | |
$.ajax({ | |
url: form_uri, | |
success: initCreateForm | |
}); | |
$("#createAndLinkButton", $modal).click(function() { | |
$("form", $modal).triggerHandler("submit"); | |
}); | |
}; | |
var showLinkerCreateModal = function() { | |
AS.openCustomModal(config.modal_id, "Create "+ config.label, AS.renderTemplate("linker_createmodal_template", config), 'large', {}, this); | |
if ($(this).hasClass("linker-create-btn")) { | |
renderCreateFormForObject($(this).data("target")); | |
} else { | |
renderCreateFormForObject($(".linker-create-btn:first", $linkerWrapper).data("target")); | |
} | |
return false; // IE8 patch | |
}; | |
var initAndShowLinkerBrowseModal = function() { | |
var currentlySelected = {}; | |
var renderItemsInModal = function(page) { | |
$.each($this.tokenInput("get"), function() { | |
currentlySelected[this.id] = this.json; | |
}); | |
$.ajax({ | |
url: config.browse_url, | |
data: { | |
page: 1, | |
type: config.types, | |
linker: true, | |
exclude: config.exclude_ids, | |
multiplicity: config.multiplicity | |
}, | |
type: "GET", | |
dataType: "html", | |
success: function(html) { | |
var $modal = $("#"+config.modal_id); | |
var $linkerBrowseContainer = $(".linker-container", $modal); | |
var initBrowseFormInputs = function() { | |
// add some click handlers to allow clicking of the row | |
$(":input[name=linker-item]", $linkerBrowseContainer).each(function() { | |
var $input = $(this); | |
$input.click(function(event) { | |
event.stopPropagation(); | |
// If one-to-one, currentlySelected should only ever | |
// contain one record | |
if (!config.allow_multiple) { | |
currentlySelected = {}; | |
$("tr.selected", $input.closest("table")).removeClass("selected"); | |
} | |
if (currentlySelected.hasOwnProperty($input.val())) { | |
// remove from the list | |
delete currentlySelected[$input.val()]; | |
$input.closest("tr").removeClass("selected"); | |
} else { | |
// add to the selected list | |
currentlySelected[$input.val()] = $input.data("object"); | |
$input.closest("tr").addClass("selected"); | |
} | |
}); | |
$("td", $input.closest("tr")).click(function(event) { | |
event.preventDefault(); | |
$input.trigger("click"); | |
}); | |
}); | |
// select a result if it's currently a selected record | |
$.each(currentlySelected, function(uri) { | |
$(":input[value='"+uri+"']", $linkerBrowseContainer) | |
.attr("checked","checked") | |
.closest("tr").addClass("selected"); | |
}); | |
$modal.trigger("resize"); | |
}; | |
$linkerBrowseContainer.html(html); | |
$($linkerBrowseContainer).on("click", "a", function(event) { | |
event.preventDefault(); | |
$linkerBrowseContainer.load(event.target.href, initBrowseFormInputs); | |
}); | |
$($linkerBrowseContainer).on("submit", "form", function(event) { | |
event.preventDefault(); | |
var $form = $(event.target); | |
var method = ($form.attr("method") || "get").toUpperCase(); | |
if (method == "POST") { | |
jQuery.post($form.attr("action") + ".js", | |
$form.serializeArray(), | |
function(html) { | |
$linkerBrowseContainer.html(html); | |
initBrowseFormInputs(); | |
}); | |
} else { | |
$linkerBrowseContainer.load($form.attr("action") + ".js?" + $form.serialize(), initBrowseFormInputs); | |
} | |
}); | |
initBrowseFormInputs(); | |
} | |
}); | |
}; | |
var addSelected = function() { | |
selectedItems = []; | |
$(".token-input-delete-token", $linkerWrapper).each(function() { | |
$(this).triggerHandler("click"); | |
}); | |
$.each(currentlySelected, function(uri, object) { | |
$this.tokenInput("add", { | |
id: uri, | |
name: object.display_string || object.title, | |
json: object | |
}); | |
}); | |
$("#"+config.modal_id).modal('hide'); | |
$this.triggerHandler("change"); | |
}; | |
AS.openCustomModal(config.modal_id, "Browse "+ config.label_plural, AS.renderTemplate("linker_browsemodal_template",config), 'large', {}, this); | |
renderItemsInModal(); | |
$("#"+config.modal_id).on("click","#addSelectedButton", addSelected); | |
$("#"+config.modal_id).on("click", ".linker-list .pagination .navigation a", function() { | |
renderItemsInModal($(this).attr("rel")); | |
}); | |
return false; // IE patch | |
}; | |
var formatResults = function(searchData) { | |
var formattedResults = []; | |
var currentlySelectedIds = []; | |
$.each($this.tokenInput("get"), function(obj) {currentlySelectedIds.push(obj.id);}); | |
$.each(searchData.search_data.results, function(index, obj) { | |
// only allow selection of unselected items | |
if ($.inArray(obj.uri, currentlySelectedIds) === -1) { | |
formattedResults.push({ | |
name: (obj.four_part_id !== undefined ? obj.four_part_id + ": " : '') + (obj.display_string || obj.title), | |
id: obj.id, | |
json: obj | |
}); | |
} | |
}); | |
return formattedResults; | |
}; | |
var addEventBindings = function() { | |
$(".linker-browse-btn", $linkerWrapper).on("click", initAndShowLinkerBrowseModal); | |
$(".linker-create-btn", $linkerWrapper).on("click", showLinkerCreateModal); | |
// Initialise popover on demand to improve performance | |
$linkerWrapper.one("mouseenter focus", ".has-popover", function() { | |
$(document).triggerHandler("init.popovers", [$this.parent()]); | |
}); | |
}; | |
var clearTokens = function() { | |
// as tokenInput plugin won't clear a token | |
// if it has an input.. remove all inputs first! | |
var $tokenList = $(".token-input-list", $this.parent()); | |
for (var i=0; i<$this.tokenInput("get").length; i++) { | |
var id_to_remove = $this.tokenInput("get")[i].id.replace(/\//g,"_"); | |
$("#"+id_to_remove + " :input", $tokenList).remove(); | |
} | |
$this.tokenInput("clear"); | |
}; | |
var enableSorting = function() { | |
if ($(".token-input-list", $linkerWrapper).data("sortable")) { | |
$(".token-input-list", $linkerWrapper).sortable("destroy"); | |
} | |
$(".token-input-list", $linkerWrapper).sortable({ | |
items: 'li.token-input-token' | |
}); | |
$(".token-input-list", $linkerWrapper).off("sortupdate").on("sortupdate", function() { | |
$this.parents("form:first").triggerHandler("formchanged.aspace"); | |
}); | |
}; | |
var tokensForPrepopulation = function() { | |
if ($this.data("multiplicity") === "one") { | |
if ($.isEmptyObject($this.data("selected"))) { | |
return []; | |
} | |
return [{ | |
id: $this.data("selected").uri, | |
name: ($this.data("selected").id_0 !== undefined ? $this.data("selected").id_0 : '') | |
+ ($this.data("selected").id_1 !== undefined ? "." + $this.data("selected").id_1 : '') | |
+ ($this.data("selected").id_2 !== undefined ? "." + $this.data("selected").id_2 : '') | |
+ ($this.data("selected").id_3 !== undefined ? "." + $this.data("selected").id_3 : '') | |
+ ($this.data("selected").id_0 !== undefined ? ": " : '') | |
+ ($this.data("selected").display_string || $this.data("selected").title), | |
json: $this.data("selected") | |
}]; | |
} else { | |
if (!$this.data("selected") || $this.data("selected").length === 0) { | |
return []; | |
} | |
return $this.data("selected").map(function(item) { | |
if (typeof item == 'string') { | |
item = JSON.parse(item); | |
} | |
return { | |
id: item.uri, | |
name: item.display_string || item.title, | |
json: item | |
}; | |
}); | |
} | |
}; | |
// ANW-521: For subjects, we want to have specialized icons based on the subjects' term type. | |
var tag_subjects_by_term_type = function(obj) { | |
if(obj.json.jsonmodel_type == "subject") { | |
switch(obj.json.first_term_type) { | |
case "cultural_context": | |
return "subject_type_cultural_context"; | |
case "function": | |
return "subject_type_function"; | |
case "genre_form": | |
return "subject_type_genre_form"; | |
case "geographic": | |
return "subject_type_geographic"; | |
case "occupation": | |
return "subject_type_occupation"; | |
case "style_period": | |
return "subject_type_style_period"; | |
case "technique": | |
return "subject_type_technique"; | |
case "temporal": | |
return "subject_type_temporal"; | |
case "topical": | |
return "subject_type_topical"; | |
case "uniform_title": | |
return "subject_type_uniform_title"; | |
default: | |
return ""; | |
} | |
} | |
else { | |
return ""; | |
} | |
}; | |
var init = function() { | |
var tokenInputConfig = $.extend({}, AS.linker_locales, { | |
animateDropdown: false, | |
preventDuplicates: true, | |
allowFreeTagging: false, | |
tokenLimit: (config.multiplicity==="one"? 1 :null), | |
caching: false, | |
onCachedResult: formatResults, | |
onResult: formatResults, | |
zindex: 1100, | |
tokenFormatter: function(item) { | |
var tokenEl = $(AS.renderTemplate("linker_selectedtoken_template", {item: item, config: config})); | |
tokenEl.children("div").children(".icon-token").addClass(config.span_class); | |
$("input[name*=resolved]", tokenEl).val(JSON.stringify(item.json)); | |
return tokenEl; | |
}, | |
resultsFormatter: function(item) { | |
var string = item.name; | |
var $resultSpan = $("<span class='"+ item.json.jsonmodel_type + "'>"); | |
var extra_class = tag_subjects_by_term_type(item); | |
$resultSpan.text(string); | |
$resultSpan.prepend("<span class='icon-token " + extra_class + "'></span>"); | |
var $resultLi = $("<li>"); | |
$resultLi.append($resultSpan); | |
return $resultLi[0].outerHTML; | |
}, | |
prePopulate: tokensForPrepopulation(), | |
onDelete: function() { | |
$this.triggerHandler("change"); | |
}, | |
onAdd: function(item) { | |
// ANW-521: After adding a subject, find the added node and apply the special class for that node. | |
var extra_class = tag_subjects_by_term_type(item); | |
var added_node_id = "#" + item.id.replace(/\//g, "_"); | |
added_node = $(added_node_id); | |
added_node.children("div").children(".icon-token").addClass(extra_class); | |
if (config.sortable && config.allow_multiple) { | |
enableSorting(); | |
} | |
// $this.triggerHandler("change"); | |
$(document).triggerHandler("init.popovers", [$this.parent()]); | |
}, | |
formatQueryParam: function(q, ajax_params) { | |
if ($this.tokenInput("get").length > 0 || config.exclude_ids.length > 0) { | |
var currentlySelectedIds = $.merge([], config.exclude_ids); | |
$.each($this.tokenInput("get"), function(i, obj) {currentlySelectedIds.push(obj.id);}); | |
ajax_params.data["exclude[]"] = currentlySelectedIds; | |
} | |
if (config.types && config.types.length > 0) { | |
ajax_params.data["type"] = config.types; | |
} | |
return (q+"*").toLowerCase(); | |
} | |
}); | |
setTimeout(function() { | |
$this.tokenInput(config.url, tokenInputConfig); | |
$("> :input[type=text]", $(".token-input-input-token", $this.parent())).attr("placeholder", AS.linker_locales.hintText).attr("aria-label", config.label); | |
$("> :input[type=text]", $(".token-input-input-token", $this.parent())).addClass('form-control'); | |
$this.parent().addClass("multiplicity-"+config.multiplicity); | |
if (config.sortable && config.allow_multiple) { | |
enableSorting(); | |
$linkerWrapper.addClass("sortable"); | |
} | |
}); | |
addEventBindings(); | |
}; | |
init(); | |
}); | |
}; | |
}); | |
$(document).ready(function() { | |
$(document).bind("loadedrecordsubforms.aspace", function(event, $container) { | |
$(".linker-wrapper:visible > .linker:not(.initialised)", $container).linker(); | |
// we can go ahead and init dropdowns ( such as those in the toolbars ) | |
$("#archives_tree_toolbar .linker:not(.initialised)").linker(); | |
}); | |
$(document).bind("subrecordcreated.aspace", function(event, object_name, subform) { | |
$(".linker:not(.initialised)", subform).linker(); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment