From cf7412acc25aba271b07b6f47086771a1c3c84e5 Mon Sep 17 00:00:00 2001 From: Berni Date: Fri, 24 Apr 2020 12:28:38 +0200 Subject: [PATCH] chore(*): Rewrite in TypeScript --- .gitignore | 1 + README.markdown => README.md | 2 +- lib/strophe.x.d.ts | 150 +++++++ lib/strophe.x.js | 556 +++++++++++++++++++++++ package-lock.json | 41 ++ package.json | 38 ++ src/strophe.x.coffee | 445 ------------------ src/strophe.x.js | 845 ----------------------------------- src/strophe.x.ts | 690 ++++++++++++++++++++++++++++ tsconfig.json | 12 + 10 files changed, 1489 insertions(+), 1291 deletions(-) create mode 100644 .gitignore rename README.markdown => README.md (96%) create mode 100644 lib/strophe.x.d.ts create mode 100644 lib/strophe.x.js create mode 100644 package-lock.json create mode 100644 package.json delete mode 100644 src/strophe.x.coffee delete mode 100644 src/strophe.x.js create mode 100644 src/strophe.x.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40b878d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/README.markdown b/README.md similarity index 96% rename from README.markdown rename to README.md index 281b298..2503534 100644 --- a/README.markdown +++ b/README.md @@ -16,7 +16,7 @@ Creating a form is easy: fields: [f1, f2] }); -You can call the constructor for Forms directly with $form: +You can call the constructor for Forms directly with \$form: $form({ ... diff --git a/lib/strophe.x.d.ts b/lib/strophe.x.d.ts new file mode 100644 index 0000000..59d7a36 --- /dev/null +++ b/lib/strophe.x.d.ts @@ -0,0 +1,150 @@ +declare type FormType = "form" | "submit" | "cancel" | "result"; +declare type FormOptions = { + type?: FormType; + title?: string; + instructions?: string; + fields?: Field[]; + items?: Item[]; +}; +declare class Form { + type: FormType; + title: string | undefined; + instructions: string | undefined; + fields: Field[]; + items: Item[]; + reported: string[]; + constructor(opt?: FormOptions); + updateReported(): void; + toXML(): Element; + toJSON(): { + type: FormType; + title: string | undefined; + instructions: string | undefined; + fields: { + type: FieldType; + var: string; + required: boolean; + desc: string | undefined; + label: string | undefined; + values: string[]; + options: { + label: string; + value: string; + }[]; + }[]; + items: { + fields: { + type: FieldType; + var: string; + required: boolean; + desc: string | undefined; + label: string | undefined; + values: string[]; + options: { + label: string; + value: string; + }[]; + }[]; + }[]; + reported: string[]; + }; + toHTML(): HTMLElement; + static fromXML(xmlIn: Element): Form; + static fromHTML(htmlIn: HTMLElement): Form; +} +declare type FieldType = "boolean" | "fixed" | "hidden" | "jid-multi" | "jid-single" | "list-multi" | "list-single" | "text-multi" | "text-private" | "text-single"; +declare type FieldValue = string | number; +interface FieldOptions { + type: FieldType; + desc?: string; + label?: string; + var?: string; + required?: boolean | "true"; + options?: FieldOption[]; + value?: FieldValue; + values?: FieldValue[]; +} +declare class Field { + type: FieldType; + desc: string | undefined; + label: string | undefined; + var: string; + required: boolean; + options: FieldOption[]; + values: string[]; + constructor(opt: FieldOptions); + addValue(val: FieldValue): this; + addValues(vals: FieldValue[]): this; + addOption(opt: FieldOption): this; + addOptions(opts: FieldOption[]): this; + toJSON(): { + type: FieldType; + var: string; + required: boolean; + desc: string | undefined; + label: string | undefined; + values: string[]; + options: { + label: string; + value: string; + }[]; + }; + toXML(): Element; + toHTML(): HTMLElement; + static fromXML(xmlIn: Element): Field; + static _htmlElementToFieldType(html: HTMLElement): FieldType; + static fromHTML(htmlIn: HTMLElement): Field; +} +declare type FieldOptionOptions = { + label?: string; + value?: FieldValue; +}; +declare class FieldOption { + label: string; + value: string; + constructor(opt?: FieldOptionOptions); + toXML(): Element; + toJSON(): { + label: string; + value: string; + }; + toHTML(): HTMLElement; + static fromXML(xml: Element): FieldOption; + static fromHTML(html: HTMLElement): FieldOption; +} +declare type ItemOptions = { + fields?: Field[]; +}; +declare class Item { + fields: Field[]; + constructor(opts?: ItemOptions); + toXML(): Element; + toJSON(): { + fields: { + type: FieldType; + var: string; + required: boolean; + desc: string | undefined; + label: string | undefined; + values: string[]; + options: { + label: string; + value: string; + }[]; + }[]; + }; + toHTML(): HTMLElement; + static fromXML(xmlIn: Element): Item; + static fromHTML(html: HTMLElement): Item; +} +declare type StropheDataforms = { + Form: typeof Form; + Field: typeof Field; + Option: typeof FieldOption; + Item: typeof Item; +}; +declare const $form: (opt: FormOptions) => Form; +declare const $field: (opt: FieldOptions) => Field; +declare const $opt: (opt: FieldOptionOptions) => FieldOption; +declare const $item: (opt: ItemOptions) => Item; +export { $form, $field, $opt, $item, StropheDataforms }; diff --git a/lib/strophe.x.js b/lib/strophe.x.js new file mode 100644 index 0000000..8f12ce2 --- /dev/null +++ b/lib/strophe.x.js @@ -0,0 +1,556 @@ +"use strict"; +// Copyright (c) Markus Kohlhase, 2011 +var __spreadArrays = (this && this.__spreadArrays) || function () { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var strophe_js_1 = require("strophe.js"); +// a little helper +var helper = { + fill: function (src, target, klass) { + return __spreadArrays(target, src.map(function (f) { return (f instanceof klass ? f : new klass(f)); })); + }, + createHtmlFieldCouple: function (f) { + var div = $("
"); + var id = "Strophe.x.Field-" + f.type + "-" + f.var; + div + .append("") + .append($(f.toHTML()).attr("id", id)) + .append("
"); + return div.children(); + }, + getHtmlFields: function (htmlIn) { + var html = $(htmlIn); + return __spreadArrays(html.find("input").toArray(), html.find("select").toArray(), html.find("textarea").toArray()); + }, +}; +var Form = /** @class */ (function () { + function Form(opt) { + this.type = "form"; + this.fields = []; + this.items = []; + this.reported = []; + this.reported = []; + if (opt) { + if (opt.type) { + this.type = opt.type; + } + this.title = opt.title; + this.instructions = opt.instructions; + if (opt.fields) { + if (opt.fields) { + this.fields = helper.fill(opt.fields, this.fields, Field); + } + } + else if (opt.items) { + if (opt.items) { + this.items = helper.fill(opt.items, this.items, Item); + } + this.updateReported(); + } + } + } + Form.prototype.updateReported = function () { + var _this = this; + this.items.forEach(function (item) { + return item.fields.forEach(function (field) { + if (!_this.reported.some(function (val) { return val === field.var; })) { + _this.reported = __spreadArrays(_this.reported, [field.var]); + } + }); + }); + }; + Form.prototype.toXML = function () { + var xml = strophe_js_1.$build("x", { xmlns: "jabber:x:data", type: this.type }); + if (this.title) { + xml.c("title").t(this.title.toString()).up(); + } + if (this.instructions) { + xml.c("instructions").t(this.instructions.toString()).up(); + } + if (this.fields.length > 0) { + this.fields.forEach(function (f) { return xml.cnode(f.toXML()).up(); }); + } + else if (this.items.length > 0) { + xml.c("reported"); + this.reported.forEach(function (r) { return xml.c("field", { var: r }).up(); }); + xml.up(); + this.items.forEach(function (i) { return xml.cnode(i.toXML()).up(); }); + } + return xml.tree(); + }; + Form.prototype.toJSON = function () { + var json = { + type: this.type, + title: this.title, + instructions: this.instructions, + fields: this.fields.map(function (field) { return field.toJSON(); }), + items: this.items.map(function (item) { return item.toJSON(); }), + reported: this.reported, + }; + return json; + }; + Form.prototype.toHTML = function () { + var form = $("
"); + if (this.title) { + form.append("

" + this.title + "

"); + } + if (this.instructions) { + form.append("

" + this.instructions + "

"); + } + if (this.fields.length > 0) { + this.fields.forEach(function (f) { + return helper.createHtmlFieldCouple(f).appendTo(form); + }); + } + else if (this.items.length > 0) { + this.items.forEach(function (i) { return $(i.toHTML()).appendTo(form); }); + } + return form[0]; + }; + Form.fromXML = function (xmlIn) { + var xml = $(xmlIn); + var f = new Form({ + type: xml.attr("type"), + }); + var title = xml.find("title"); + if (title.length === 1) { + f.title = title.text(); + } + var instr = xml.find("instructions"); + if (instr.length === 1) { + f.instructions = instr.text(); + } + var fields = xml.find("field"); + var items = xml.find("item"); + if (items.length > 0) { + f.items = items.toArray().map(Item.fromXML); + } + else if (fields.length > 0) { + f.fields = fields.toArray().map(Field.fromXML); + } + var reported = xml.find("reported"); + if (reported.length === 1) { + fields = reported.find("field"); + f.reported = fields.toArray().map(function (r) { return $(r).attr("var"); }); + } + return f; + }; + Form.fromHTML = function (htmlIn) { + var html = $(htmlIn); + var f = new Form({ + type: html.attr("data-type"), + }); + var title = html.find("h1").text(); + if (title) { + f.title = title; + } + var instructions = html.find("p").text(); + if (instructions) { + f.instructions = instructions; + } + var items = html.find("fieldset"); + var fields = helper.getHtmlFields(htmlIn); + if (items.length > 0) { + f.items = items.toArray().map(Item.fromHTML); + f.updateReported(); + } + else if (fields.length > 0) { + f.fields = fields.map(Field.fromHTML); + } + return f; + }; + return Form; +}()); +var FieldMultiType; +(function (FieldMultiType) { + FieldMultiType["list-multi"] = "list-multi"; + FieldMultiType["jid-multi"] = "jid-multi"; + FieldMultiType["text-multi"] = "text-multi"; + FieldMultiType["hidden"] = "hidden"; +})(FieldMultiType || (FieldMultiType = {})); +var Field = /** @class */ (function () { + function Field(opt) { + var _a; + this.type = "text-single"; + this.var = "_no_var_was_defined_"; + this.required = false; + this.options = []; + this.values = []; + if (opt) { + this.type = opt.type; + if (opt.desc) { + this.desc = opt.desc; + } + if (opt.label) { + this.label = opt.label; + } + this.var = (_a = opt.var) !== null && _a !== void 0 ? _a : "_no_var_was_defined_"; + this.required = opt.required === true || opt.required === "true"; + if (opt.options) { + this.addOptions(opt.options); + } + if (opt.value) { + this.addValue(opt.value); + } + if (opt.values) { + this.addValues(opt.values); + } + } + } + Field.prototype.addValue = function (val) { + return this.addValues([val]); + }; + Field.prototype.addValues = function (vals) { + var multi = this.type in FieldMultiType; + if (multi || (!multi && vals.length === 1)) { + this.values = __spreadArrays(this.values, vals.map(function (v) { return v.toString(); })); + } + return this; + }; + Field.prototype.addOption = function (opt) { + return this.addOptions([opt]); + }; + Field.prototype.addOptions = function (opts) { + if (this.type === "list-single" || this.type === "list-multi") { + if (typeof opts[0] !== "object") { + opts = opts.map(function (o) { return new FieldOption({ value: o.toString() }); }); + } + this.options = helper.fill(opts, this.options, FieldOption); + } + return this; + }; + Field.prototype.toJSON = function () { + var json = { + type: this.type, + var: this.var, + required: this.required, + desc: this.desc, + label: this.label, + values: this.values, + options: this.options.map(function (o) { return o.toJSON(); }), + }; + return json; + }; + Field.prototype.toXML = function () { + var attrs = { + type: this.type, + var: this.var, + label: this.label, + }; + var xml = strophe_js_1.$build("field", attrs); + if (this.desc) { + xml.c("desc").t(this.desc).up(); + } + if (this.required) { + xml.c("required").up(); + } + if (this.values) { + this.values.forEach(function (v) { return xml.c("value").t(v.toString()).up(); }); + } + if (this.options) { + this.options.forEach(function (o) { return xml.cnode(o.toXML()).up(); }); + } + return xml.tree(); + }; + Field.prototype.toHTML = function () { + var _this = this; + var el; + switch (this.type.toLowerCase()) { + case "list-single": + case "list-multi": + el = $("