Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@
"datatables.net-select-bs5": "^3.1.3",
"dropzone": "6.0.0-beta.2",
"jqtree": "^1.8.11",
"jquery": "3.7.1",
"jquery-form": "4.3.0",
"jquery.browser": "0.1.0",
"jquery": "^4.0.0",
"js-cookie": "^3.0.5",
"select2": "github:ivaynberg/select2#95a977f674b6938af55ec5f28b7772df93786c5c",
"sortablejs": "^1.15.7",
Expand Down Expand Up @@ -66,7 +64,7 @@
"resolutions": {
"@patternslib/patternslib": "9.10.4",
"backbone": "1.6.1",
"jquery": "3.7.1",
"jquery": "4.0.0",
"sass": "~1.77.8",
"underscore": "1.13.8"
},
Expand Down
14 changes: 14 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ async function register_global_libraries() {

// Register jQuery globally
const jquery = (await import("jquery")).default;

// BBB: jQuery4 backports for select2
jquery.isFunction = function (obj) {
return typeof obj === "function";
};
jquery.isArray = function (obj) {
return Array.isArray
? Array.isArray(obj)
: Object.prototype.toString.call(obj) === "[object Array]";
};
jquery.trim = function (str) {
return str == null ? "" : String.prototype.trim.call(str);
};

window.jQuery = jquery;
window.$ = jquery;
}
Expand Down
1 change: 0 additions & 1 deletion src/pat/manageportlets/manageportlets.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export default Base.extend({
isModal: false,
dirty: false,
init: async function () {
(await import("jquery-form")).default;
var that = this;
var $modal = that.$el.parents(".plone-modal");
if ($modal.length === 1) {
Expand Down
120 changes: 85 additions & 35 deletions src/pat/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import dom from "@patternslib/patternslib/src/core/dom";
import utils from "../../core/utils";
import _t from "../../core/i18n-wrapper";

import "jquery-form";

export default Base.extend({
name: "plone-modal",
trigger: ".pat-plone-modal",
Expand Down Expand Up @@ -158,8 +156,8 @@ export default Base.extend({
self[actionOptions.modalFunction]();
// handle event on input/button using jquery.form library
} else if (
$.nodeName($action[0], "input") ||
$.nodeName($action[0], "button") ||
($action[0].nodeName.toLowerCase() == "input") ||
($action[0].nodeName.toLowerCase() == "button") ||
options.isForm === true
) {
self.options.handleFormAction.apply(self, [
Expand Down Expand Up @@ -231,29 +229,53 @@ export default Base.extend({
$form.trigger("submit");

self.loading.show(false);
$form.ajaxSubmit({
timeout: options.timeout,
data: extraData,
url: url,
error: function (xhr, textStatus, errorStatus) {
self.loading.hide();
if (textStatus === "timeout" && options.onTimeout) {
options.onTimeout.apply(self, xhr, errorStatus);
// on "error", "abort", and "parsererror"
} else if (options.onError) {
if (typeof options.onError === "string") {
window[options.onError](xhr, textStatus, errorStatus);
} else {
options.onError(xhr, textStatus, errorStatus);
}
} else {
// window.alert(_t('There was an error submitting the form.'));
console.log("error happened", textStatus, " do something");
}
self.emit("formActionError", [xhr, textStatus, errorStatus]);
},
success: function (response, state, xhr, form) {

// Use native fetch API with FormData
const formData = new FormData($form[0]);

// Add extra data from the clicked action
for (const key in extraData) {
if (extraData[key]) {
formData.append(key, extraData[key]);
}
}

// Setup timeout using AbortController
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), options.timeout);

fetch(url, {
method: $form.attr("method") || "POST",
body: formData,
signal: controller.signal,
credentials: "same-origin",
})
.then((response) => {
clearTimeout(timeoutId);

// Create a mock xhr object for compatibility with existing callbacks
const mockXhr = {
status: response.status,
statusText: response.statusText,
getResponseHeader: (header) => response.headers.get(header),
getAllResponseHeaders: () => {
let headers = "";
response.headers.forEach((value, key) => {
headers += `${key}: ${value}\r\n`;
});
return headers;
},
};

return response.text().then((text) => ({
response: text,
state: "success",
xhr: mockXhr,
}));
})
.then(({ response, state, xhr }) => {
self.loading.hide();

// if error is found (NOTE: check for both the portal errors
// and the form field-level errors)
if (
Expand All @@ -267,10 +289,10 @@ export default Base.extend({
response,
state,
xhr,
form
$form[0]
);
} else {
options.onFormError(self, response, state, xhr, form);
options.onFormError(self, response, state, xhr, $form[0]);
}
} else {
self.redraw(response, patternOptions);
Expand All @@ -292,9 +314,9 @@ export default Base.extend({

if (options.onSuccess) {
if (typeof options.onSuccess === "string") {
window[options.onSuccess](self, response, state, xhr, form);
window[options.onSuccess](self, response, state, xhr, $form[0]);
} else {
options.onSuccess(self, response, state, xhr, form);
options.onSuccess(self, response, state, xhr, $form[0]);
}
}

Expand All @@ -307,9 +329,37 @@ export default Base.extend({
self.reloadWindow();
}
}
self.emit("formActionSuccess", [response, state, xhr, form]);
},
});
self.emit("formActionSuccess", [response, state, xhr, $form[0]]);
})
.catch((error) => {
clearTimeout(timeoutId);
self.loading.hide();

const textStatus = error.name === "AbortError" ? "timeout" : "error";
const errorStatus = error.message;

// Create a mock xhr object for error callbacks
const mockXhr = {
status: 0,
statusText: textStatus,
responseText: "",
};

if (textStatus === "timeout" && options.onTimeout) {
options.onTimeout.apply(self, [mockXhr, errorStatus]);
// on "error", "abort", and "parsererror"
} else if (options.onError) {
if (typeof options.onError === "string") {
window[options.onError](mockXhr, textStatus, errorStatus);
} else {
options.onError(mockXhr, textStatus, errorStatus);
}
} else {
// window.alert(_t('There was an error submitting the form.'));
console.log("error happened", textStatus, " do something");
}
self.emit("formActionError", [mockXhr, textStatus, errorStatus]);
});
},
handleLinkAction: function ($action, options, patternOptions) {
var self = this;
Expand Down Expand Up @@ -531,7 +581,7 @@ export default Base.extend({
import("./modal.scss");

var self = this;
self.options.loadLinksWithinModal = $.parseJSON(
self.options.loadLinksWithinModal = JSON.parse(
self.options.loadLinksWithinModal
);

Expand Down Expand Up @@ -652,7 +702,7 @@ export default Base.extend({
self.$wrapper.addClass("image-modal");
var src = self.$el.attr("href");
var srcset = self.$el.attr("data-modal-srcset") || "";
var title = $.trim(self.$el.context.innerText) || "Image";
var title = (self.$el[0]?.innerText || "").trim() || "Image";
// XXX aria?
self.$raw = $(
"<div><h1>" +
Expand Down
22 changes: 7 additions & 15 deletions src/pat/querystring/querystring.test.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
import "./querystring";
import $ from "jquery";
import registry from "@patternslib/patternslib/src/core/registry";
import utils from "@patternslib/patternslib/src/core/utils";

const mockFetch =
(json = {}) =>
() =>
Promise.resolve({
json: () => Promise.resolve(json),
});
const mockFetch = global.mockFetch;

describe("Querystring", function () {
beforeEach(() => {
document.body.innerHTML = `
<div id="formfield-query"><input class="pat-querystring text-widget list-field"
type="text" name="form.widgets.ICollection.query"
style="display: none;"
value=\'[
value='[
{
"i": "portal_type",
"o": "plone.app.querystring.operation.selection.any",
Expand All @@ -31,8 +25,8 @@ describe("Querystring", function () {
"published"
]
}
]\'
data-pat-querystring=\'{
]'
data-pat-querystring='{
"indexOptionsUrl": "http://localhost:8080/Plone/@@qsOptions",
"previewURL": "http://localhost:8080/Plone/news/aggregator/@@querybuilder_html_results",
"previewCountURL": "http://localhost:8080/Plone/news/aggregator/@@querybuildernumberofresults",
Expand Down Expand Up @@ -124,7 +118,7 @@ describe("Querystring", function () {
}
]
}
}\'></div>
}'></div>
<div id="formfield-sort_on">
<input id="form-widgets-sort_on" value="start" type="text">
</div>
Expand Down Expand Up @@ -159,11 +153,9 @@ describe("Querystring", function () {
).toEqual(3);

// check for correct initialized values
expect($(".querystring-sort-wrapper select").val()).toEqual("start");
expect(document.querySelector(".querystring-sort-wrapper select").value).toEqual("start");
expect(
$(
".querystring-sort-wrapper .querystring-sortreverse input[type='checkbox']"
)[0].checked
document.querySelectorAll(".querystring-sort-wrapper .querystring-sortreverse input[type='checkbox']")[0].checked
).toBeTruthy();

global.fetch.mockClear();
Expand Down
8 changes: 4 additions & 4 deletions src/pat/relateditems/relateditems.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import registry from "@patternslib/patternslib/src/core/registry";
import Select2 from "../select2/select2";

const KEY = {
LEFT: 37,
RIGHT: 39,
LEFT: "ArrowLeft",
RIGHT: "ArrowRight",
};

export default Base.extend({
Expand Down Expand Up @@ -702,11 +702,11 @@ export default Base.extend({
return;
}

if (event.which === KEY.LEFT || event.which === KEY.RIGHT) {
if (event.key === KEY.LEFT || event.key === KEY.RIGHT) {
event.stopPropagation();

const selectorContext =
event.which === KEY.LEFT
event.key === KEY.LEFT
? ".pat-relateditems-result.one-level-up"
: ".select2-highlighted";

Expand Down
8 changes: 4 additions & 4 deletions src/pat/select2/select2.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,8 @@ describe("Select2", function () {

var $results = $("li.select2-search-choice");
expect($results.length).toEqual(2);
expect($.trim($results.eq(0).text())).toEqual("Yellow");
expect($.trim($results.eq(1).text())).toEqual("Red");
expect($results.eq(0).text().trim()).toEqual("Yellow");
expect($results.eq(1).text().trim()).toEqual("Red");

var firstElem = $results.eq(0);
// css class is set and proxy is created when starting to drag
Expand Down Expand Up @@ -330,7 +330,7 @@ describe("Select2", function () {
expect($("#test-select2").val()).toEqual("1;3");
var $results = $("li.select2-search-choice");
expect($results.length).toEqual(2);
expect($.trim($results.eq(0).text())).toEqual("One");
expect($.trim($results.eq(1).text())).toEqual("Three");
expect($results.eq(0).text().trim()).toEqual("One");
expect($results.eq(1).text().trim()).toEqual("Three");
});
});
7 changes: 1 addition & 6 deletions src/pat/structure/structure.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,7 @@ function getQueryVariable(url, variable) {

var extraDataJsonItem = null;

const mockFetch =
(json = {}) =>
() =>
Promise.resolve({
json: () => Promise.resolve(json),
});
const mockFetch = global.mockFetch;

/* ==========================
TEST: AppView constructor internal attribute/object correctness
Expand Down
2 changes: 1 addition & 1 deletion src/pat/tinymce/tinymce.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe("TinyMCE", function () {
for (const val of vars) {
const pair = val.split("=");
if (decodeURIComponent(pair[0]) === "query") {
query = $.parseJSON(decodeURIComponent(pair[1]));
query = JSON.parse(decodeURIComponent(pair[1]));
}
}
const results = [];
Expand Down
22 changes: 15 additions & 7 deletions src/pat/tree/tree.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import $ from "jquery";
import Base from "@patternslib/patternslib/src/core/base";
import utils from "../../core/utils";

Expand Down Expand Up @@ -39,20 +38,29 @@ export default Base.extend({
}

if (self.options.data && typeof self.options.data === "string") {
self.options.data = $.parseJSON(self.options.data);
self.options.data = JSON.parse(self.options.data);
}
if (self.options.onLoad !== null) {
// delay generating tree...
var options = $.extend({}, self.options);
const options = { ...self.options };

try {
const response = await fetch(options.dataUrl);

if (!response.ok) {
throw new Error("HTTP error " + response.status);
}

const data = await response.json();

$.getJSON(options.dataUrl, function (data) {
options.data = data;
delete options.dataUrl;

self.tree = self.$el.tree(options);
self.options.onLoad(self);
}).fail(function (response) { // eslint-disable-line no-unused-vars
console.log("failed to load json data");
});
} catch (error) {
console.log(`failed to load json data: ${error}`);
}
} else {
self.tree = self.$el.tree(self.options);
}
Expand Down
Loading
Loading