
* fix(deps): bump ztoolkit, scaffold and other deps - use web-ext to reload plugin - remove itembox example - update all deps * docs: add scaffold to readme and replace plugin dev documentation with zotero-chinese.com
853 lines
24 KiB
TypeScript
853 lines
24 KiB
TypeScript
import { config } from "../../package.json";
|
|
import { getLocaleID, getString } from "../utils/locale";
|
|
|
|
function example(
|
|
target: any,
|
|
propertyKey: string | symbol,
|
|
descriptor: PropertyDescriptor,
|
|
) {
|
|
const original = descriptor.value;
|
|
descriptor.value = function (...args: any) {
|
|
try {
|
|
ztoolkit.log(`Calling example ${target.name}.${String(propertyKey)}`);
|
|
return original.apply(this, args);
|
|
} catch (e) {
|
|
ztoolkit.log(`Error in example ${target.name}.${String(propertyKey)}`, e);
|
|
throw e;
|
|
}
|
|
};
|
|
return descriptor;
|
|
}
|
|
|
|
export class BasicExampleFactory {
|
|
@example
|
|
static registerNotifier() {
|
|
const callback = {
|
|
notify: async (
|
|
event: string,
|
|
type: string,
|
|
ids: number[] | string[],
|
|
extraData: { [key: string]: any },
|
|
) => {
|
|
if (!addon?.data.alive) {
|
|
this.unregisterNotifier(notifierID);
|
|
return;
|
|
}
|
|
addon.hooks.onNotify(event, type, ids, extraData);
|
|
},
|
|
};
|
|
|
|
// Register the callback in Zotero as an item observer
|
|
const notifierID = Zotero.Notifier.registerObserver(callback, [
|
|
"tab",
|
|
"item",
|
|
"file",
|
|
]);
|
|
|
|
// Unregister callback when the window closes (important to avoid a memory leak)
|
|
window.addEventListener(
|
|
"unload",
|
|
(e: Event) => {
|
|
this.unregisterNotifier(notifierID);
|
|
},
|
|
false,
|
|
);
|
|
}
|
|
|
|
@example
|
|
static exampleNotifierCallback() {
|
|
new ztoolkit.ProgressWindow(config.addonName)
|
|
.createLine({
|
|
text: "Open Tab Detected!",
|
|
type: "success",
|
|
progress: 100,
|
|
})
|
|
.show();
|
|
}
|
|
|
|
@example
|
|
private static unregisterNotifier(notifierID: string) {
|
|
Zotero.Notifier.unregisterObserver(notifierID);
|
|
}
|
|
|
|
@example
|
|
static registerPrefs() {
|
|
Zotero.PreferencePanes.register({
|
|
pluginID: config.addonID,
|
|
src: rootURI + "chrome/content/preferences.xhtml",
|
|
label: getString("prefs-title"),
|
|
image: `chrome://${config.addonRef}/content/icons/favicon.png`,
|
|
});
|
|
}
|
|
}
|
|
|
|
export class KeyExampleFactory {
|
|
@example
|
|
static registerShortcuts() {
|
|
// Register an event key for Alt+L
|
|
ztoolkit.Keyboard.register((ev, keyOptions) => {
|
|
ztoolkit.log(ev, keyOptions.keyboard);
|
|
if (keyOptions.keyboard?.equals("shift,l")) {
|
|
addon.hooks.onShortcuts("larger");
|
|
}
|
|
if (ev.shiftKey && ev.key === "S") {
|
|
addon.hooks.onShortcuts("smaller");
|
|
}
|
|
});
|
|
|
|
new ztoolkit.ProgressWindow(config.addonName)
|
|
.createLine({
|
|
text: "Example Shortcuts: Alt+L/S/C",
|
|
type: "success",
|
|
})
|
|
.show();
|
|
}
|
|
|
|
@example
|
|
static exampleShortcutLargerCallback() {
|
|
new ztoolkit.ProgressWindow(config.addonName)
|
|
.createLine({
|
|
text: "Larger!",
|
|
type: "default",
|
|
})
|
|
.show();
|
|
}
|
|
|
|
@example
|
|
static exampleShortcutSmallerCallback() {
|
|
new ztoolkit.ProgressWindow(config.addonName)
|
|
.createLine({
|
|
text: "Smaller!",
|
|
type: "default",
|
|
})
|
|
.show();
|
|
}
|
|
}
|
|
|
|
export class UIExampleFactory {
|
|
@example
|
|
static registerStyleSheet() {
|
|
const styles = ztoolkit.UI.createElement(document, "link", {
|
|
properties: {
|
|
type: "text/css",
|
|
rel: "stylesheet",
|
|
href: `chrome://${config.addonRef}/content/zoteroPane.css`,
|
|
},
|
|
});
|
|
document.documentElement.appendChild(styles);
|
|
document
|
|
.getElementById("zotero-item-pane-content")
|
|
?.classList.add("makeItRed");
|
|
}
|
|
|
|
@example
|
|
static registerRightClickMenuItem() {
|
|
const menuIcon = `chrome://${config.addonRef}/content/icons/favicon@0.5x.png`;
|
|
// item menuitem with icon
|
|
ztoolkit.Menu.register("item", {
|
|
tag: "menuitem",
|
|
id: "zotero-itemmenu-addontemplate-test",
|
|
label: getString("menuitem-label"),
|
|
commandListener: (ev) => addon.hooks.onDialogEvents("dialogExample"),
|
|
icon: menuIcon,
|
|
});
|
|
}
|
|
|
|
@example
|
|
static registerRightClickMenuPopup() {
|
|
ztoolkit.Menu.register(
|
|
"item",
|
|
{
|
|
tag: "menu",
|
|
label: getString("menupopup-label"),
|
|
children: [
|
|
{
|
|
tag: "menuitem",
|
|
label: getString("menuitem-submenulabel"),
|
|
oncommand: "alert('Hello World! Sub Menuitem.')",
|
|
},
|
|
],
|
|
},
|
|
"before",
|
|
document.querySelector(
|
|
"#zotero-itemmenu-addontemplate-test",
|
|
) as XUL.MenuItem,
|
|
);
|
|
}
|
|
|
|
@example
|
|
static registerWindowMenuWithSeparator() {
|
|
ztoolkit.Menu.register("menuFile", {
|
|
tag: "menuseparator",
|
|
});
|
|
// menu->File menuitem
|
|
ztoolkit.Menu.register("menuFile", {
|
|
tag: "menuitem",
|
|
label: getString("menuitem-filemenulabel"),
|
|
oncommand: "alert('Hello World! File Menuitem.')",
|
|
});
|
|
}
|
|
|
|
@example
|
|
static async registerExtraColumn() {
|
|
const field = "test1";
|
|
await Zotero.ItemTreeManager.registerColumns({
|
|
pluginID: config.addonID,
|
|
dataKey: field,
|
|
label: "text column",
|
|
dataProvider: (item: Zotero.Item, dataKey: string) => {
|
|
return field + String(item.id);
|
|
},
|
|
iconPath: "chrome://zotero/skin/cross.png",
|
|
});
|
|
}
|
|
|
|
@example
|
|
static async registerExtraColumnWithCustomCell() {
|
|
const field = "test2";
|
|
await Zotero.ItemTreeManager.registerColumns({
|
|
pluginID: config.addonID,
|
|
dataKey: field,
|
|
label: "custom column",
|
|
dataProvider: (item: Zotero.Item, dataKey: string) => {
|
|
return field + String(item.id);
|
|
},
|
|
renderCell(index, data, column) {
|
|
ztoolkit.log("Custom column cell is rendered!");
|
|
const span = document.createElementNS(
|
|
"http://www.w3.org/1999/xhtml",
|
|
"span",
|
|
);
|
|
span.className = `cell ${column.className}`;
|
|
span.style.background = "#0dd068";
|
|
span.innerText = "⭐" + data;
|
|
return span;
|
|
},
|
|
});
|
|
}
|
|
|
|
@example
|
|
static registerItemPaneSection() {
|
|
Zotero.ItemPaneManager.registerSection({
|
|
paneID: "example",
|
|
pluginID: config.addonID,
|
|
header: {
|
|
l10nID: getLocaleID("item-section-example1-head-text"),
|
|
icon: "chrome://zotero/skin/16/universal/book.svg",
|
|
},
|
|
sidenav: {
|
|
l10nID: getLocaleID("item-section-example1-sidenav-tooltip"),
|
|
icon: "chrome://zotero/skin/20/universal/save.svg",
|
|
},
|
|
onRender: ({ body, item, editable, tabType }) => {
|
|
body.textContent = JSON.stringify({
|
|
id: item?.id,
|
|
editable,
|
|
tabType,
|
|
});
|
|
},
|
|
});
|
|
}
|
|
|
|
@example
|
|
static async registerReaderItemPaneSection() {
|
|
Zotero.ItemPaneManager.registerSection({
|
|
paneID: "reader-example",
|
|
pluginID: config.addonID,
|
|
header: {
|
|
l10nID: getLocaleID("item-section-example2-head-text"),
|
|
// Optional
|
|
l10nArgs: `{"status": "Initialized"}`,
|
|
// Can also have a optional dark icon
|
|
icon: "chrome://zotero/skin/16/universal/book.svg",
|
|
},
|
|
sidenav: {
|
|
l10nID: getLocaleID("item-section-example2-sidenav-tooltip"),
|
|
icon: "chrome://zotero/skin/20/universal/save.svg",
|
|
},
|
|
// Optional
|
|
bodyXHTML: '<html:h1 id="test">THIS IS TEST</html:h1>',
|
|
// Optional, Called when the section is first created, must be synchronous
|
|
onInit: ({ item }) => {
|
|
ztoolkit.log("Section init!", item?.id);
|
|
},
|
|
// Optional, Called when the section is destroyed, must be synchronous
|
|
onDestroy: (props) => {
|
|
ztoolkit.log("Section destroy!");
|
|
},
|
|
// Optional, Called when the section data changes (setting item/mode/tabType/inTrash), must be synchronous. return false to cancel the change
|
|
onItemChange: ({ item, setEnabled, tabType }) => {
|
|
ztoolkit.log(`Section item data changed to ${item?.id}`);
|
|
setEnabled(tabType === "reader");
|
|
return true;
|
|
},
|
|
// Called when the section is asked to render, must be synchronous.
|
|
onRender: ({
|
|
body,
|
|
item,
|
|
setL10nArgs,
|
|
setSectionSummary,
|
|
setSectionButtonStatus,
|
|
}) => {
|
|
ztoolkit.log("Section rendered!", item?.id);
|
|
const title = body.querySelector("#test") as HTMLElement;
|
|
title.style.color = "red";
|
|
title.textContent = "LOADING";
|
|
setL10nArgs(`{ "status": "Loading" }`);
|
|
setSectionSummary("loading!");
|
|
setSectionButtonStatus("test", { hidden: true });
|
|
},
|
|
// Optional, can be asynchronous.
|
|
onAsyncRender: async ({
|
|
body,
|
|
item,
|
|
setL10nArgs,
|
|
setSectionSummary,
|
|
setSectionButtonStatus,
|
|
}) => {
|
|
ztoolkit.log("Section secondary render start!", item?.id);
|
|
await Zotero.Promise.delay(1000);
|
|
ztoolkit.log("Section secondary render finish!", item?.id);
|
|
const title = body.querySelector("#test") as HTMLElement;
|
|
title.style.color = "green";
|
|
title.textContent = item.getField("title");
|
|
setL10nArgs(`{ "status": "Loaded" }`);
|
|
setSectionSummary("rendered!");
|
|
setSectionButtonStatus("test", { hidden: false });
|
|
},
|
|
// Optional, Called when the section is toggled. Can happen anytime even if the section is not visible or not rendered
|
|
onToggle: ({ item }) => {
|
|
ztoolkit.log("Section toggled!", item?.id);
|
|
},
|
|
// Optional, Buttons to be shown in the section header
|
|
sectionButtons: [
|
|
{
|
|
type: "test",
|
|
icon: "chrome://zotero/skin/16/universal/empty-trash.svg",
|
|
l10nID: getLocaleID("item-section-example2-button-tooltip"),
|
|
onClick: ({ item, paneID }) => {
|
|
ztoolkit.log("Section clicked!", item?.id);
|
|
Zotero.ItemPaneManager.unregisterSection(paneID);
|
|
},
|
|
},
|
|
],
|
|
});
|
|
}
|
|
}
|
|
|
|
export class PromptExampleFactory {
|
|
@example
|
|
static registerNormalCommandExample() {
|
|
ztoolkit.Prompt.register([
|
|
{
|
|
name: "Normal Command Test",
|
|
label: "Plugin Template",
|
|
callback(prompt) {
|
|
ztoolkit.getGlobal("alert")("Command triggered!");
|
|
},
|
|
},
|
|
]);
|
|
}
|
|
|
|
@example
|
|
static registerAnonymousCommandExample() {
|
|
ztoolkit.Prompt.register([
|
|
{
|
|
id: "search",
|
|
callback: async (prompt) => {
|
|
// https://github.com/zotero/zotero/blob/7262465109c21919b56a7ab214f7c7a8e1e63909/chrome/content/zotero/integration/quickFormat.js#L589
|
|
function getItemDescription(item: Zotero.Item) {
|
|
const nodes = [];
|
|
let str = "";
|
|
let author,
|
|
authorDate = "";
|
|
if (item.firstCreator) {
|
|
author = authorDate = item.firstCreator;
|
|
}
|
|
let date = item.getField("date", true, true) as string;
|
|
if (date && (date = date.substr(0, 4)) !== "0000") {
|
|
authorDate += " (" + parseInt(date) + ")";
|
|
}
|
|
authorDate = authorDate.trim();
|
|
if (authorDate) nodes.push(authorDate);
|
|
|
|
const publicationTitle = item.getField(
|
|
"publicationTitle",
|
|
false,
|
|
true,
|
|
);
|
|
if (publicationTitle) {
|
|
nodes.push(`<i>${publicationTitle}</i>`);
|
|
}
|
|
let volumeIssue = item.getField("volume");
|
|
const issue = item.getField("issue");
|
|
if (issue) volumeIssue += "(" + issue + ")";
|
|
if (volumeIssue) nodes.push(volumeIssue);
|
|
|
|
const publisherPlace = [];
|
|
let field;
|
|
if ((field = item.getField("publisher")))
|
|
publisherPlace.push(field);
|
|
if ((field = item.getField("place"))) publisherPlace.push(field);
|
|
if (publisherPlace.length) nodes.push(publisherPlace.join(": "));
|
|
|
|
const pages = item.getField("pages");
|
|
if (pages) nodes.push(pages);
|
|
|
|
if (!nodes.length) {
|
|
const url = item.getField("url");
|
|
if (url) nodes.push(url);
|
|
}
|
|
|
|
// compile everything together
|
|
for (let i = 0, n = nodes.length; i < n; i++) {
|
|
const node = nodes[i];
|
|
|
|
if (i != 0) str += ", ";
|
|
|
|
if (typeof node === "object") {
|
|
const label = document.createElement("label");
|
|
label.setAttribute("value", str);
|
|
label.setAttribute("crop", "end");
|
|
str = "";
|
|
} else {
|
|
str += node;
|
|
}
|
|
}
|
|
str.length && (str += ".");
|
|
return str;
|
|
}
|
|
function filter(ids: number[]) {
|
|
ids = ids.filter(async (id) => {
|
|
const item = (await Zotero.Items.getAsync(id)) as Zotero.Item;
|
|
return item.isRegularItem() && !(item as any).isFeedItem;
|
|
});
|
|
return ids;
|
|
}
|
|
const text = prompt.inputNode.value;
|
|
prompt.showTip("Searching...");
|
|
const s = new Zotero.Search();
|
|
s.addCondition("quicksearch-titleCreatorYear", "contains", text);
|
|
s.addCondition("itemType", "isNot", "attachment");
|
|
let ids = await s.search();
|
|
// prompt.exit will remove current container element.
|
|
// @ts-ignore ignore
|
|
prompt.exit();
|
|
const container = prompt.createCommandsContainer();
|
|
container.classList.add("suggestions");
|
|
ids = filter(ids);
|
|
console.log(ids.length);
|
|
if (ids.length == 0) {
|
|
const s = new Zotero.Search();
|
|
const operators = [
|
|
"is",
|
|
"isNot",
|
|
"true",
|
|
"false",
|
|
"isInTheLast",
|
|
"isBefore",
|
|
"isAfter",
|
|
"contains",
|
|
"doesNotContain",
|
|
"beginsWith",
|
|
];
|
|
let hasValidCondition = false;
|
|
let joinMode = "all";
|
|
if (/\s*\|\|\s*/.test(text)) {
|
|
joinMode = "any";
|
|
}
|
|
text.split(/\s*(&&|\|\|)\s*/g).forEach((conditinString: string) => {
|
|
const conditions = conditinString.split(/\s+/g);
|
|
if (
|
|
conditions.length == 3 &&
|
|
operators.indexOf(conditions[1]) != -1
|
|
) {
|
|
hasValidCondition = true;
|
|
s.addCondition(
|
|
"joinMode",
|
|
joinMode as Zotero.Search.Operator,
|
|
"",
|
|
);
|
|
s.addCondition(
|
|
conditions[0] as string,
|
|
conditions[1] as Zotero.Search.Operator,
|
|
conditions[2] as string,
|
|
);
|
|
}
|
|
});
|
|
if (hasValidCondition) {
|
|
ids = await s.search();
|
|
}
|
|
}
|
|
ids = filter(ids);
|
|
console.log(ids.length);
|
|
if (ids.length > 0) {
|
|
ids.forEach((id: number) => {
|
|
const item = Zotero.Items.get(id);
|
|
const title = item.getField("title");
|
|
const ele = ztoolkit.UI.createElement(document, "div", {
|
|
namespace: "html",
|
|
classList: ["command"],
|
|
listeners: [
|
|
{
|
|
type: "mousemove",
|
|
listener: function () {
|
|
// @ts-ignore ignore
|
|
prompt.selectItem(this);
|
|
},
|
|
},
|
|
{
|
|
type: "click",
|
|
listener: () => {
|
|
prompt.promptNode.style.display = "none";
|
|
Zotero_Tabs.select("zotero-pane");
|
|
ZoteroPane.selectItem(item.id);
|
|
},
|
|
},
|
|
],
|
|
styles: {
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
justifyContent: "start",
|
|
},
|
|
children: [
|
|
{
|
|
tag: "span",
|
|
styles: {
|
|
fontWeight: "bold",
|
|
overflow: "hidden",
|
|
textOverflow: "ellipsis",
|
|
whiteSpace: "nowrap",
|
|
},
|
|
properties: {
|
|
innerText: title,
|
|
},
|
|
},
|
|
{
|
|
tag: "span",
|
|
styles: {
|
|
overflow: "hidden",
|
|
textOverflow: "ellipsis",
|
|
whiteSpace: "nowrap",
|
|
},
|
|
properties: {
|
|
innerHTML: getItemDescription(item),
|
|
},
|
|
},
|
|
],
|
|
});
|
|
container.appendChild(ele);
|
|
});
|
|
} else {
|
|
// @ts-ignore ignore
|
|
prompt.exit();
|
|
prompt.showTip("Not Found.");
|
|
}
|
|
},
|
|
},
|
|
]);
|
|
}
|
|
|
|
@example
|
|
static registerConditionalCommandExample() {
|
|
ztoolkit.Prompt.register([
|
|
{
|
|
name: "Conditional Command Test",
|
|
label: "Plugin Template",
|
|
// The when function is executed when Prompt UI is woken up by `Shift + P`, and this command does not display when false is returned.
|
|
when: () => {
|
|
const items = ZoteroPane.getSelectedItems();
|
|
return items.length > 0;
|
|
},
|
|
callback(prompt) {
|
|
prompt.inputNode.placeholder = "Hello World!";
|
|
const items = ZoteroPane.getSelectedItems();
|
|
ztoolkit.getGlobal("alert")(
|
|
`You select ${items.length} items!\n\n${items
|
|
.map(
|
|
(item, index) =>
|
|
String(index + 1) + ". " + item.getDisplayTitle(),
|
|
)
|
|
.join("\n")}`,
|
|
);
|
|
},
|
|
},
|
|
]);
|
|
}
|
|
}
|
|
|
|
export class HelperExampleFactory {
|
|
@example
|
|
static async dialogExample() {
|
|
const dialogData: { [key: string | number]: any } = {
|
|
inputValue: "test",
|
|
checkboxValue: true,
|
|
loadCallback: () => {
|
|
ztoolkit.log(dialogData, "Dialog Opened!");
|
|
},
|
|
unloadCallback: () => {
|
|
ztoolkit.log(dialogData, "Dialog closed!");
|
|
},
|
|
};
|
|
const dialogHelper = new ztoolkit.Dialog(10, 2)
|
|
.addCell(0, 0, {
|
|
tag: "h1",
|
|
properties: { innerHTML: "Helper Examples" },
|
|
})
|
|
.addCell(1, 0, {
|
|
tag: "h2",
|
|
properties: { innerHTML: "Dialog Data Binding" },
|
|
})
|
|
.addCell(2, 0, {
|
|
tag: "p",
|
|
properties: {
|
|
innerHTML:
|
|
"Elements with attribute 'data-bind' are binded to the prop under 'dialogData' with the same name.",
|
|
},
|
|
styles: {
|
|
width: "200px",
|
|
},
|
|
})
|
|
.addCell(3, 0, {
|
|
tag: "label",
|
|
namespace: "html",
|
|
attributes: {
|
|
for: "dialog-checkbox",
|
|
},
|
|
properties: { innerHTML: "bind:checkbox" },
|
|
})
|
|
.addCell(
|
|
3,
|
|
1,
|
|
{
|
|
tag: "input",
|
|
namespace: "html",
|
|
id: "dialog-checkbox",
|
|
attributes: {
|
|
"data-bind": "checkboxValue",
|
|
"data-prop": "checked",
|
|
type: "checkbox",
|
|
},
|
|
properties: { label: "Cell 1,0" },
|
|
},
|
|
false,
|
|
)
|
|
.addCell(4, 0, {
|
|
tag: "label",
|
|
namespace: "html",
|
|
attributes: {
|
|
for: "dialog-input",
|
|
},
|
|
properties: { innerHTML: "bind:input" },
|
|
})
|
|
.addCell(
|
|
4,
|
|
1,
|
|
{
|
|
tag: "input",
|
|
namespace: "html",
|
|
id: "dialog-input",
|
|
attributes: {
|
|
"data-bind": "inputValue",
|
|
"data-prop": "value",
|
|
type: "text",
|
|
},
|
|
},
|
|
false,
|
|
)
|
|
.addCell(5, 0, {
|
|
tag: "h2",
|
|
properties: { innerHTML: "Toolkit Helper Examples" },
|
|
})
|
|
.addCell(
|
|
6,
|
|
0,
|
|
{
|
|
tag: "button",
|
|
namespace: "html",
|
|
attributes: {
|
|
type: "button",
|
|
},
|
|
listeners: [
|
|
{
|
|
type: "click",
|
|
listener: (e: Event) => {
|
|
addon.hooks.onDialogEvents("clipboardExample");
|
|
},
|
|
},
|
|
],
|
|
children: [
|
|
{
|
|
tag: "div",
|
|
styles: {
|
|
padding: "2.5px 15px",
|
|
},
|
|
properties: {
|
|
innerHTML: "example:clipboard",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
false,
|
|
)
|
|
.addCell(
|
|
7,
|
|
0,
|
|
{
|
|
tag: "button",
|
|
namespace: "html",
|
|
attributes: {
|
|
type: "button",
|
|
},
|
|
listeners: [
|
|
{
|
|
type: "click",
|
|
listener: (e: Event) => {
|
|
addon.hooks.onDialogEvents("filePickerExample");
|
|
},
|
|
},
|
|
],
|
|
children: [
|
|
{
|
|
tag: "div",
|
|
styles: {
|
|
padding: "2.5px 15px",
|
|
},
|
|
properties: {
|
|
innerHTML: "example:filepicker",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
false,
|
|
)
|
|
.addCell(
|
|
8,
|
|
0,
|
|
{
|
|
tag: "button",
|
|
namespace: "html",
|
|
attributes: {
|
|
type: "button",
|
|
},
|
|
listeners: [
|
|
{
|
|
type: "click",
|
|
listener: (e: Event) => {
|
|
addon.hooks.onDialogEvents("progressWindowExample");
|
|
},
|
|
},
|
|
],
|
|
children: [
|
|
{
|
|
tag: "div",
|
|
styles: {
|
|
padding: "2.5px 15px",
|
|
},
|
|
properties: {
|
|
innerHTML: "example:progressWindow",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
false,
|
|
)
|
|
.addCell(
|
|
9,
|
|
0,
|
|
{
|
|
tag: "button",
|
|
namespace: "html",
|
|
attributes: {
|
|
type: "button",
|
|
},
|
|
listeners: [
|
|
{
|
|
type: "click",
|
|
listener: (e: Event) => {
|
|
addon.hooks.onDialogEvents("vtableExample");
|
|
},
|
|
},
|
|
],
|
|
children: [
|
|
{
|
|
tag: "div",
|
|
styles: {
|
|
padding: "2.5px 15px",
|
|
},
|
|
properties: {
|
|
innerHTML: "example:virtualized-table",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
false,
|
|
)
|
|
.addButton("Confirm", "confirm")
|
|
.addButton("Cancel", "cancel")
|
|
.addButton("Help", "help", {
|
|
noClose: true,
|
|
callback: (e) => {
|
|
dialogHelper.window?.alert(
|
|
"Help Clicked! Dialog will not be closed.",
|
|
);
|
|
},
|
|
})
|
|
.setDialogData(dialogData)
|
|
.open("Dialog Example");
|
|
addon.data.dialog = dialogHelper;
|
|
await dialogData.unloadLock.promise;
|
|
addon.data.dialog = undefined;
|
|
addon.data.alive &&
|
|
ztoolkit.getGlobal("alert")(
|
|
`Close dialog with ${dialogData._lastButtonId}.\nCheckbox: ${dialogData.checkboxValue}\nInput: ${dialogData.inputValue}.`,
|
|
);
|
|
ztoolkit.log(dialogData);
|
|
}
|
|
|
|
@example
|
|
static clipboardExample() {
|
|
new ztoolkit.Clipboard()
|
|
.addText(
|
|
"",
|
|
"text/unicode",
|
|
)
|
|
.addText(
|
|
'<a href="https://github.com/windingwind/zotero-plugin-template">Plugin Template</a>',
|
|
"text/html",
|
|
)
|
|
.copy();
|
|
ztoolkit.getGlobal("alert")("Copied!");
|
|
}
|
|
|
|
@example
|
|
static async filePickerExample() {
|
|
const path = await new ztoolkit.FilePicker(
|
|
"Import File",
|
|
"open",
|
|
[
|
|
["PNG File(*.png)", "*.png"],
|
|
["Any", "*.*"],
|
|
],
|
|
"image.png",
|
|
).open();
|
|
ztoolkit.getGlobal("alert")(`Selected ${path}`);
|
|
}
|
|
|
|
@example
|
|
static progressWindowExample() {
|
|
new ztoolkit.ProgressWindow(config.addonName)
|
|
.createLine({
|
|
text: "ProgressWindow Example!",
|
|
type: "success",
|
|
progress: 100,
|
|
})
|
|
.show();
|
|
}
|
|
|
|
@example
|
|
static vtableExample() {
|
|
ztoolkit.getGlobal("alert")("See src/modules/preferenceScript.ts");
|
|
}
|
|
}
|