PageSourceSearch

https://roycekimmons.com/js/etb-editor/editor.settings.js

js roycekimmons.com collected 2026-09-25 21:04:37 UTC 9,645 bytes, 209 lines download raw bytes

1
2async function RenderSettingHeading(table, text) {
3    let th = $('<th></th>').attr('colspan', 2).text(text).addClass('fs-4 pt-3');
4    let tr = $('<tr></tr>').append(th);
5    table.append(tr);
6}
7
8async function RenderSettingRole(table, entity, label, role) {
9    let v = entity.roles.includes(role);
10    let rt = $('<tr><th></th><td></td></tr>');
11    let h = rt.children('th');
12    let cell = rt.children('td').first();
13    h.first().html(label).off('click').on('click', function () {
14        $(this).next('td').find('input, textarea, select').first().focus();
15    });
16    input = $('<input></input>').addClass('form-check-input m-0 fs-3 mb-2').attr('type', 'checkbox').attr('role', 'switch');
17    let s = $('<div class="form-check form-switch"></div>');
18    if (v) $(input).prop('checked', true);
19    s.append(input).appendTo(cell);
20    input.off('change').on('change', {id: entity.id, role: role}, async (event) => {
21        if ($(event.target).is(':checked')) {
22            await GrantRole(event.data.id, event.data.role);
23        } else {
24            await RevokeRole(event.data.id, event.data.role);
25        }
26    });
27    table.append(rt);
28}
29
30/**
31 * Render a form for selecting a user role
32 * @param {*} table 
33 * @param {*} entity 
34 * @param {*} label 
35 * @param {*} options 
36 */
37async function RenderSettingRoleSelect(table, entity, label, options) {
38    let rt = $('<tr><th></th><td></td></tr>');
39    let h = rt.children('th');
40    let cell = rt.children('td').first();
41    h.first().html(label).off('click').on('click', function () {
42        $(this).next('td').find('input, textarea, select').first().focus();
43    });
44    input = $('<select></select>').addClass('form-select m-0 fs-5 mb-2').appendTo(cell);
45    let roles = [];
46    for(let option of options) {
47        roles.push(option.value);
48        let o = $('<option></option>').text(option.label).val(option.value).appendTo(input);
49        if(entity.roles.includes(option.value)) o.attr('selected',true);
50    }
51    input.off('change').on('change', {id: entity.id, roles: roles}, async (event) => {
52        await GrantRole(event.data.id, $(event.target).val(), {conflicts: event.data.roles});
53    });
54    table.append(rt);
55}
56
57async function RenderSetting(table, entity, name, label, type = 'text', options = []) {
58    let v = entity[name];
59    if (v == undefined) v = entity.settings[name];
60    if (v == undefined) v = '';
61    let rt = $('<tr><th></th><td></td></tr>');
62    let h = rt.children('th');
63    let s = null;
64    let cell = rt.children('td').first();
65    h.first().html(label).off('click').on('click', function () {
66        $(this).next('td').find('input, textarea, select').first().focus();
67    });
68    let input = null;
69    switch (type) {
70        case 'select':
71            let select = $('<select></select>');
72            select.addClass('form-select');
73            for (let option of options) {
74                let o = $('<option></option>');
75                o.val(option.value).html(option.label);
76                if (option.value == entity.settings[name] || option.value == entity[name]) o.attr('selected', true);
77                select.append(o);
78            }
79            cell.append(select);
80            select.off('change').on('change', async function () {
81                let settings = {};
82                settings[name] = $(this).val();
83                $(this).attr('disabled', true);
84                if (SaveSetting(entity.type, entity.id, settings)) {
85                    $(this).removeAttr('disabled');
86                } else {
87                    $(this).addClass('is-invalid');
88                }
89            });
90            break;
91        case 'switch':
92            input = $('<input></input>').addClass('form-check-input m-0 fs-3 mb-2').attr('type', 'checkbox').attr('role', 'switch');
93            s = $('<div class="form-check form-switch"></div>');
94            if (v == 1) $(input).prop('checked', true);
95            s.append(input).appendTo(cell);
96            input.off('change').on('change', async function () {
97                let settings = {};
98                settings[name] = ($(this).is(':checked')) ? 1 : 0;
99                $(this).attr('disabled', true);
100                if (await SaveSetting(entity.type, entity.id, settings)) {
101                    $(this).removeAttr('disabled');
102                } else {
103                    $(this).addClass('is-invalid');
104                }
105            });
106            break;
107        case 'switch-invert':
108            input = $('<input></input>').addClass('form-check-input m-0 fs-3 mb-2').attr('type', 'checkbox').attr('role', 'switch');
109            s = $('<div class="form-check form-switch"></div>');
110            if (v == undefined || v == 0) $(input).prop('checked', true);
111            s.append(input).appendTo(cell);
112            input.off('change').on('change', async function () {
113                let settings = {};
114                settings[name] = ($(this).is(':checked')) ? 0 : 1;
115                $(this).attr('disabled', true);
116                if (await SaveSetting(entity.type, entity.id, settings)) {
117                    $(this).removeAttr('disabled');
118                } else {
119                    $(this).addClass('is-invalid');
120                }
121            });
122            break;
123        case 'move-chapter':
124            input = $('<select></select>').addClass('form-select').addClass('rounded-start-0').attr('data-entity-id', entity.id);
125            if (current_user !== null) {
126                for (let link of await GetBookLinksForAuthor(current_user.id)) {
127                    let option = $('<option></option>').text(link.text).attr('value', link.entity_id).appendTo(input);
128                    if (link.entity_id == entity.book_id) option.attr('selected', true);
129                }
130                cell.append(input);
131                input.off('change').on('change', async function () {
132                    $(this).attr('disabled', true);
133                    if (await MoveChapter($(this).closest('[data-entity-id]').attr('data-entity-id'), $(this).val())) {
134                        Toast('Content Moved', 'The content was moved to a new publication.', 'bg-success text-light');
135                        $(this).removeAttr('disabled');
136                    } else {
137                        $(this).addClass('is-invalid');
138                    }
139                });
140            }
141            break;
142        case 'rename-chapter':
143            input = $('<input></input>');
144            input.val(v).addClass('rounded-start-0').addClass('form-control').attr('required', true);
145            cell.append(input).attr('data-field', name);
146            input.off('change').on('change', async function () {
147                if ($(this).val() == '') return;
148                $(this).removeClass('is-invalid');
149                $(this).attr('disabled', true);
150                let short_name = $(this).val();
151                console.log("Changing the chapter URI to " + short_name);
152                if (await (RenameChapter(entity.id, entity.book_id, short_name))) {
153                    Toast('Address Changed', 'The address (location or URI) was successfully changed.', 'bg-success text-light');
154                    $(this).removeAttr('disabled');
155                } else {
156                    $(this).removeAttr('disabled');
157                    $(this).addClass('is-invalid');
158                }
159            });
160            break;
161        case 'rename-book':
162            input = $('<input></input>');
163            input.val(v).addClass('rounded-start-0').addClass('form-control').attr('required', true);
164            cell.append(input).attr('data-field', name);
165            input.off('change').on('change', async function () {
166                if ($(this).val() == '') return;
167                $(this).removeClass('is-invalid');
168                $(this).attr('disabled', true);
169                try {
170                    if (await RenameBook(entity.id, $(this).val())) {
171                        Toast('Address Changed', 'The address (location or URI) was successfully changed.', 'bg-success text-light');
172                        $(this).removeAttr('disabled');
173                    } else {
174                        $(this).removeAttr('disabled');
175                        $(this).addClass('is-invalid');
176                    }
177                    $(this).val(current_book.short_name);
178                } catch (error) {
179                    console.error(error);
180                    $(this).removeAttr('disabled');
181                    $(this).addClass('is-invalid');
182                    Toast('Error', error, 'bg-danger text-light');
183                }
184            });
185            break;
186        case 'button':
187            let b = $('<button></button>').text(label).addClass('btn btn-primary').attr('data-action', options[0]);
188            if (options.length > 0) b.attr('data-action-value', options[1]);
189            cell.append(b);
190            break;
191        case 'textarea':
192            input = $('<textarea></textarea>').attr('rows', 4);
193        default:
194            if (input == null) input = $('<input></input>');
195            input.val(v).addClass('rounded-start-0');
196            cell.append(input).attr('data-field', name);
197            input.addClass('form-control').off('change').on('change', async function () {
198                let settings = {};
199                settings[name] = $(this).val();
200                $(this).attr('disabled', true);
201                if (await SaveSetting(entity.type, entity.id, settings)) {
202                    $(this).removeAttr('disabled');
203                } else {
204                    $(this).addClass('is-invalid');
205                }
206            });
207    }
208    table.append(rt);
209}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.