Fossil SCM

Added fileedit-content-replaced event for notification when content is replaced. Clear preview/diff views on fileedit-content-replaced. Changed the interface for providing custom content getter/setter. Fixed the load file button in the file selection widget - it's no longer cleared.

stephan 2020-05-15 22:13 fileedit-ajaxify
Commit 6f2649b9b0b47261670cb4406d63432da60f018c7cf223005794c5c6cdef26fa
--- src/fossil.bootstrap.js
+++ src/fossil.bootstrap.js
@@ -300,14 +300,14 @@
300300
};
301301
302302
/**
303303
Internal. Dispatches a new CustomEvent to all listeners
304304
registered for the given eventName via
305
- fossil.page.addEventListener(), passing on a new CustomEvent
306
- with a 'detail' property equal to the 2nd argument's
307
- value. Returns this object.
308
- */
305
+ fossil.page.addEventListener(), passing on a new CustomEvent with
306
+ a 'detail' property equal to the 2nd argument. Returns this
307
+ object.
308
+ */
309309
F.page.dispatchEvent = function(eventName, eventDetail){
310310
if(this.addEventListener.proxy){
311311
try{
312312
this.addEventListener.proxy.dispatchEvent(
313313
new CustomEvent(eventName,{detail: eventDetail})
314314
--- src/fossil.bootstrap.js
+++ src/fossil.bootstrap.js
@@ -300,14 +300,14 @@
300 };
301
302 /**
303 Internal. Dispatches a new CustomEvent to all listeners
304 registered for the given eventName via
305 fossil.page.addEventListener(), passing on a new CustomEvent
306 with a 'detail' property equal to the 2nd argument's
307 value. Returns this object.
308 */
309 F.page.dispatchEvent = function(eventName, eventDetail){
310 if(this.addEventListener.proxy){
311 try{
312 this.addEventListener.proxy.dispatchEvent(
313 new CustomEvent(eventName,{detail: eventDetail})
314
--- src/fossil.bootstrap.js
+++ src/fossil.bootstrap.js
@@ -300,14 +300,14 @@
300 };
301
302 /**
303 Internal. Dispatches a new CustomEvent to all listeners
304 registered for the given eventName via
305 fossil.page.addEventListener(), passing on a new CustomEvent with
306 a 'detail' property equal to the 2nd argument. Returns this
307 object.
308 */
309 F.page.dispatchEvent = function(eventName, eventDetail){
310 if(this.addEventListener.proxy){
311 try{
312 this.addEventListener.proxy.dispatchEvent(
313 new CustomEvent(eventName,{detail: eventDetail})
314
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -31,20 +31,27 @@
3131
/**
3232
Removes all child DOM elements from the given element
3333
and returns that element.
3434
3535
If e has a forEach method (is an array or DOM element
36
- collection), this function instead clears each element
37
- in the collection and returns e.
36
+ collection), this function instead clears each element in the
37
+ collection. May be passed any number of arguments, each of
38
+ which must be a DOM element or a container of DOM elements with
39
+ a forEach() method. Returns its first argument.
3840
*/
3941
clearElement: function f(e){
40
- if(e.forEach){
41
- e.forEach((x)=>f(x));
42
- return e;
42
+ if(!f.each){
43
+ f.each = function(e){
44
+ if(e.forEach){
45
+ e.forEach((x)=>f(x));
46
+ return e;
47
+ }
48
+ while(e.firstChild) e.removeChild(e.firstChild);
49
+ };
4350
}
44
- while(e.firstChild) e.removeChild(e.firstChild);
45
- return e;
51
+ argsToArray(arguments).forEach(f.each);
52
+ return arguments[0];
4653
},
4754
}/* dom object */;
4855
4956
/**
5057
Returns the result of splitting the given str on
@@ -416,13 +423,13 @@
416423
var i = 1, n = arguments.length;
417424
for( ; i < n; ++i ){
418425
let e = arguments[i];
419426
if(e.forEach){
420427
e.forEach((x)=>f(enable,x));
421
- return e;
428
+ }else{
429
+ e.disabled = !enable;
422430
}
423
- e.disabled = !enable;
424431
}
425432
return arguments[1];
426433
};
427434
428435
/**
429436
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -31,20 +31,27 @@
31 /**
32 Removes all child DOM elements from the given element
33 and returns that element.
34
35 If e has a forEach method (is an array or DOM element
36 collection), this function instead clears each element
37 in the collection and returns e.
 
 
38 */
39 clearElement: function f(e){
40 if(e.forEach){
41 e.forEach((x)=>f(x));
42 return e;
 
 
 
 
 
43 }
44 while(e.firstChild) e.removeChild(e.firstChild);
45 return e;
46 },
47 }/* dom object */;
48
49 /**
50 Returns the result of splitting the given str on
@@ -416,13 +423,13 @@
416 var i = 1, n = arguments.length;
417 for( ; i < n; ++i ){
418 let e = arguments[i];
419 if(e.forEach){
420 e.forEach((x)=>f(enable,x));
421 return e;
 
422 }
423 e.disabled = !enable;
424 }
425 return arguments[1];
426 };
427
428 /**
429
--- src/fossil.dom.js
+++ src/fossil.dom.js
@@ -31,20 +31,27 @@
31 /**
32 Removes all child DOM elements from the given element
33 and returns that element.
34
35 If e has a forEach method (is an array or DOM element
36 collection), this function instead clears each element in the
37 collection. May be passed any number of arguments, each of
38 which must be a DOM element or a container of DOM elements with
39 a forEach() method. Returns its first argument.
40 */
41 clearElement: function f(e){
42 if(!f.each){
43 f.each = function(e){
44 if(e.forEach){
45 e.forEach((x)=>f(x));
46 return e;
47 }
48 while(e.firstChild) e.removeChild(e.firstChild);
49 };
50 }
51 argsToArray(arguments).forEach(f.each);
52 return arguments[0];
53 },
54 }/* dom object */;
55
56 /**
57 Returns the result of splitting the given str on
@@ -416,13 +423,13 @@
423 var i = 1, n = arguments.length;
424 for( ; i < n; ++i ){
425 let e = arguments[i];
426 if(e.forEach){
427 e.forEach((x)=>f(enable,x));
428 }else{
429 e.disabled = !enable;
430 }
 
431 }
432 return arguments[1];
433 };
434
435 /**
436
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -11,19 +11,21 @@
1111
1212
{
1313
filename: string,
1414
checkin: UUID string,
1515
isExe: bool,
16
- mimetype: mimetype stringas determined by the fossil server.
16
+ mimetype: mimetype string, as determined by the fossil server.
1717
}
1818
1919
The fossil.page.fileContent() method gets or sets the current file
20
- content for the page. Hypothetically, this can be overridden by
21
- skin-level JS in order to use a custom 3rd-party editing widget
22
- in place of the built-in textarea, but that is as yet untested.
23
- In order to do so the client would need to replace DOM element
24
- #fileedit-content-editor with their custom widget.
20
+ content for the page.
21
+
22
+ - Event 'fileedit-content-replaced': when the editor's content is
23
+ replaced, as opposed to it being edited via user
24
+ interaction. This normally happens via selecting a file to
25
+ load. The event detail is the fossil.page object, not the current
26
+ file content.
2527
2628
- Event 'fileedit-preview-updated': when the preview is refreshed
2729
from the server, this event passes on information about the preview
2830
change in the form of an object:
2931
@@ -114,11 +116,11 @@
114116
if(!ciUuid){
115117
D.clearElement(D.disable(selFiles, this.e.btnLoadFile));
116118
return this;
117119
}
118120
const onload = (response)=>{
119
- D.clearElement(selFiles, this.e.btnLoadFile);
121
+ D.clearElement(selFiles);
120122
D.append(
121123
D.clearElement(this.e.fileListLabel),
122124
"Editable files for ",
123125
D.append(
124126
D.code(), "[",
@@ -246,10 +248,11 @@
246248
selectFontSizeWrap: E('#select-font-size'),
247249
selectDiffWS: E('select[name=diff_ws]'),
248250
cbLineNumbersWrap: E('#cb-line-numbers'),
249251
cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'),
250252
previewTarget: E('#fileedit-tab-preview-wrapper'),
253
+ diffTarget: E('#fileedit-tab-diff-wrapper'),
251254
cbIsExe: E('input[type=checkbox][name=exec_bit]'),
252255
fsFileVersionDetails: E('#file-version-details'),
253256
tabs:{
254257
content: E('#fileedit-tab-content'),
255258
preview: E('#fileedit-tab-preview'),
@@ -375,12 +378,17 @@
375378
'fileedit-file-loaded',
376379
(e)=>console.debug('fileedit-file-loaded ==>',e)
377380
);
378381
}
379382
380
- /* Tell the user about which storage is being used... */
381
- const storageMsgTarget = P.e.tabs.content;
383
+ P.addEventListener(
384
+ // Clear diff/preview when new content is loaded/set
385
+ 'fileedit-content-replaced',
386
+ ()=>D.clearElement(P.e.diffTarget, P.e.previewTarget)
387
+ );
388
+
389
+ /* Tell the user about which fossil.storage is being used... */
382390
let storageMsg = D.addClass(D.div(),'flex-container','flex-row',
383391
'fileedit-hint');
384392
if(F.storage.isTransient()){
385393
D.append(
386394
D.addClass(storageMsg,'warning'),
@@ -393,30 +401,56 @@
393401
storageMsg,
394402
"Current storage mechanism for local edits: "+
395403
F.storage.storageImplName()
396404
);
397405
}
398
- storageMsgTarget.insertBefore(storageMsg, storageMsgTarget.lastElementChild);
406
+ P.e.tabs.content.insertBefore(storageMsg, P.e.tabs.content.lastElementChild);
399407
}, false)/*onload event handler*/;
400408
401409
/**
402410
Getter (if called with no args) or setter (if passed an arg) for
403
- the current file content. We use a function, rather than direct
404
- access, so that clients can hypothetically swap out this method
405
- from their skin in order to facilitate plugging-in of a fancy
406
- 3rd-party editor widget.
407
-
408
- The setter form returns this object, and re-implementations must
409
- do the same.
410
- */
411
- P.fileContent = function(){
411
+ the current file content.
412
+
413
+ The setter form sets the content, dispatches a
414
+ 'fileedit-content-replaced' event, and returns this object.
415
+ */
416
+ P.fileContent = function f(){
412417
if(0===arguments.length){
413
- return this.e.taEditor.value;
418
+ return f.get();
414419
}else{
415
- this.e.taEditor.value = arguments[0] || '';
420
+ f.set(arguments[0] || '');
421
+ this.dispatchEvent('fileedit-content-replaced', this);
416422
return this;
417423
}
424
+ };
425
+ /* Default get/set impls for file content */
426
+ P.fileContent.get = function(){return P.e.taEditor.value};
427
+ P.fileContent.set = function(content){P.e.taEditor.value = content};
428
+
429
+ /**
430
+ For use when installing a custom editor widget. Pass it the
431
+ getter and setter callbacks to fetch resp. set the content of the
432
+ custom widget. They will be triggered via
433
+ P.fileContent(). Returns this object.
434
+ */
435
+ P.setFileContentMethods = function(getter, setter){
436
+ this.fileContent.get = getter;
437
+ this.fileContent.set = setter;
438
+ return this;
439
+ };
440
+
441
+ /**
442
+ Removes the default editor widget (and any dependent elements)
443
+ from the DOM, adds the given element in its place, removes this
444
+ method from this object, and returns this object.
445
+ */
446
+ P.replaceEditorElement = function(newEditor){
447
+ P.e.taEditor.parentNode.insertBefore(newEditor, P.e.taEditor);
448
+ P.e.taEditor.remove();
449
+ P.e.selectFontSizeWrap.remove();
450
+ delete this.replaceEditorElement;
451
+ return P;
418452
};
419453
420454
/**
421455
If either of...
422456
@@ -562,26 +596,10 @@
562596
);
563597
this.setPageTitle("Edit: "+this.finfo.filename);
564598
return this;
565599
};
566600
567
- /**
568
- Removes the default editor widget (and any dependent elements)
569
- from the DOM, adds the given element in its place, removes this
570
- method from this object, and returns this object.
571
- */
572
- P.replaceEditorElement = function(newEditor){
573
- P.e.taEditor.parentNode.insertBefore(
574
- newEditor,
575
- P.e.taEditor
576
- );
577
- P.e.taEditor.remove();
578
- P.e.selectFontSizeWrap.remove();
579
- delete this.replaceEditorElement;
580
- return P;
581
- };
582
-
583601
/**
584602
loadFile() loads (file,checkinVersion) and updates the relevant
585603
UI elements to reflect the loaded state. If passed no arguments
586604
then it re-uses the values from the currently-loaded file, reloading
587605
it (emitting an error message if no file is loaded).
@@ -710,16 +728,12 @@
710728
Returns this object, noting that the operation is async.
711729
*/
712730
P.diff = function f(sbs){
713731
if(!affirmHasFile()) return this;
714732
const content = this.fileContent(),
715
- self = this;
716
- if(!f.target){
717
- f.target = this.e.tabs.diff.querySelector(
718
- '#fileedit-tab-diff-wrapper'
719
- );
720
- }
733
+ self = this,
734
+ target = this.e.diffTarget;
721735
const fd = new FormData();
722736
fd.append('filename',this.finfo.filename);
723737
fd.append('checkin', this.finfo.checkin);
724738
fd.append('sbs', sbs ? 1 : 0);
725739
fd.append('content',content);
@@ -728,11 +742,11 @@
728742
"Fetching diff..."
729743
).fetch('fileedit',{
730744
urlParams: {ajax: 'diff'},
731745
payload: fd,
732746
onload: function(c){
733
- f.target.innerHTML = [
747
+ target.innerHTML = [
734748
"<div>Diff <code>[",
735749
self.finfo.checkin,
736750
"]</code> &rarr; Local Edits</div>",
737751
c||'No changes.'
738752
].join('');
739753
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -11,19 +11,21 @@
11
12 {
13 filename: string,
14 checkin: UUID string,
15 isExe: bool,
16 mimetype: mimetype stringas determined by the fossil server.
17 }
18
19 The fossil.page.fileContent() method gets or sets the current file
20 content for the page. Hypothetically, this can be overridden by
21 skin-level JS in order to use a custom 3rd-party editing widget
22 in place of the built-in textarea, but that is as yet untested.
23 In order to do so the client would need to replace DOM element
24 #fileedit-content-editor with their custom widget.
 
 
25
26 - Event 'fileedit-preview-updated': when the preview is refreshed
27 from the server, this event passes on information about the preview
28 change in the form of an object:
29
@@ -114,11 +116,11 @@
114 if(!ciUuid){
115 D.clearElement(D.disable(selFiles, this.e.btnLoadFile));
116 return this;
117 }
118 const onload = (response)=>{
119 D.clearElement(selFiles, this.e.btnLoadFile);
120 D.append(
121 D.clearElement(this.e.fileListLabel),
122 "Editable files for ",
123 D.append(
124 D.code(), "[",
@@ -246,10 +248,11 @@
246 selectFontSizeWrap: E('#select-font-size'),
247 selectDiffWS: E('select[name=diff_ws]'),
248 cbLineNumbersWrap: E('#cb-line-numbers'),
249 cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'),
250 previewTarget: E('#fileedit-tab-preview-wrapper'),
 
251 cbIsExe: E('input[type=checkbox][name=exec_bit]'),
252 fsFileVersionDetails: E('#file-version-details'),
253 tabs:{
254 content: E('#fileedit-tab-content'),
255 preview: E('#fileedit-tab-preview'),
@@ -375,12 +378,17 @@
375 'fileedit-file-loaded',
376 (e)=>console.debug('fileedit-file-loaded ==>',e)
377 );
378 }
379
380 /* Tell the user about which storage is being used... */
381 const storageMsgTarget = P.e.tabs.content;
 
 
 
 
 
382 let storageMsg = D.addClass(D.div(),'flex-container','flex-row',
383 'fileedit-hint');
384 if(F.storage.isTransient()){
385 D.append(
386 D.addClass(storageMsg,'warning'),
@@ -393,30 +401,56 @@
393 storageMsg,
394 "Current storage mechanism for local edits: "+
395 F.storage.storageImplName()
396 );
397 }
398 storageMsgTarget.insertBefore(storageMsg, storageMsgTarget.lastElementChild);
399 }, false)/*onload event handler*/;
400
401 /**
402 Getter (if called with no args) or setter (if passed an arg) for
403 the current file content. We use a function, rather than direct
404 access, so that clients can hypothetically swap out this method
405 from their skin in order to facilitate plugging-in of a fancy
406 3rd-party editor widget.
407
408 The setter form returns this object, and re-implementations must
409 do the same.
410 */
411 P.fileContent = function(){
412 if(0===arguments.length){
413 return this.e.taEditor.value;
414 }else{
415 this.e.taEditor.value = arguments[0] || '';
 
416 return this;
417 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418 };
419
420 /**
421 If either of...
422
@@ -562,26 +596,10 @@
562 );
563 this.setPageTitle("Edit: "+this.finfo.filename);
564 return this;
565 };
566
567 /**
568 Removes the default editor widget (and any dependent elements)
569 from the DOM, adds the given element in its place, removes this
570 method from this object, and returns this object.
571 */
572 P.replaceEditorElement = function(newEditor){
573 P.e.taEditor.parentNode.insertBefore(
574 newEditor,
575 P.e.taEditor
576 );
577 P.e.taEditor.remove();
578 P.e.selectFontSizeWrap.remove();
579 delete this.replaceEditorElement;
580 return P;
581 };
582
583 /**
584 loadFile() loads (file,checkinVersion) and updates the relevant
585 UI elements to reflect the loaded state. If passed no arguments
586 then it re-uses the values from the currently-loaded file, reloading
587 it (emitting an error message if no file is loaded).
@@ -710,16 +728,12 @@
710 Returns this object, noting that the operation is async.
711 */
712 P.diff = function f(sbs){
713 if(!affirmHasFile()) return this;
714 const content = this.fileContent(),
715 self = this;
716 if(!f.target){
717 f.target = this.e.tabs.diff.querySelector(
718 '#fileedit-tab-diff-wrapper'
719 );
720 }
721 const fd = new FormData();
722 fd.append('filename',this.finfo.filename);
723 fd.append('checkin', this.finfo.checkin);
724 fd.append('sbs', sbs ? 1 : 0);
725 fd.append('content',content);
@@ -728,11 +742,11 @@
728 "Fetching diff..."
729 ).fetch('fileedit',{
730 urlParams: {ajax: 'diff'},
731 payload: fd,
732 onload: function(c){
733 f.target.innerHTML = [
734 "<div>Diff <code>[",
735 self.finfo.checkin,
736 "]</code> &rarr; Local Edits</div>",
737 c||'No changes.'
738 ].join('');
739
--- src/fossil.page.fileedit.js
+++ src/fossil.page.fileedit.js
@@ -11,19 +11,21 @@
11
12 {
13 filename: string,
14 checkin: UUID string,
15 isExe: bool,
16 mimetype: mimetype string, as determined by the fossil server.
17 }
18
19 The fossil.page.fileContent() method gets or sets the current file
20 content for the page.
21
22 - Event 'fileedit-content-replaced': when the editor's content is
23 replaced, as opposed to it being edited via user
24 interaction. This normally happens via selecting a file to
25 load. The event detail is the fossil.page object, not the current
26 file content.
27
28 - Event 'fileedit-preview-updated': when the preview is refreshed
29 from the server, this event passes on information about the preview
30 change in the form of an object:
31
@@ -114,11 +116,11 @@
116 if(!ciUuid){
117 D.clearElement(D.disable(selFiles, this.e.btnLoadFile));
118 return this;
119 }
120 const onload = (response)=>{
121 D.clearElement(selFiles);
122 D.append(
123 D.clearElement(this.e.fileListLabel),
124 "Editable files for ",
125 D.append(
126 D.code(), "[",
@@ -246,10 +248,11 @@
248 selectFontSizeWrap: E('#select-font-size'),
249 selectDiffWS: E('select[name=diff_ws]'),
250 cbLineNumbersWrap: E('#cb-line-numbers'),
251 cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'),
252 previewTarget: E('#fileedit-tab-preview-wrapper'),
253 diffTarget: E('#fileedit-tab-diff-wrapper'),
254 cbIsExe: E('input[type=checkbox][name=exec_bit]'),
255 fsFileVersionDetails: E('#file-version-details'),
256 tabs:{
257 content: E('#fileedit-tab-content'),
258 preview: E('#fileedit-tab-preview'),
@@ -375,12 +378,17 @@
378 'fileedit-file-loaded',
379 (e)=>console.debug('fileedit-file-loaded ==>',e)
380 );
381 }
382
383 P.addEventListener(
384 // Clear diff/preview when new content is loaded/set
385 'fileedit-content-replaced',
386 ()=>D.clearElement(P.e.diffTarget, P.e.previewTarget)
387 );
388
389 /* Tell the user about which fossil.storage is being used... */
390 let storageMsg = D.addClass(D.div(),'flex-container','flex-row',
391 'fileedit-hint');
392 if(F.storage.isTransient()){
393 D.append(
394 D.addClass(storageMsg,'warning'),
@@ -393,30 +401,56 @@
401 storageMsg,
402 "Current storage mechanism for local edits: "+
403 F.storage.storageImplName()
404 );
405 }
406 P.e.tabs.content.insertBefore(storageMsg, P.e.tabs.content.lastElementChild);
407 }, false)/*onload event handler*/;
408
409 /**
410 Getter (if called with no args) or setter (if passed an arg) for
411 the current file content.
412
413 The setter form sets the content, dispatches a
414 'fileedit-content-replaced' event, and returns this object.
415 */
416 P.fileContent = function f(){
 
 
 
417 if(0===arguments.length){
418 return f.get();
419 }else{
420 f.set(arguments[0] || '');
421 this.dispatchEvent('fileedit-content-replaced', this);
422 return this;
423 }
424 };
425 /* Default get/set impls for file content */
426 P.fileContent.get = function(){return P.e.taEditor.value};
427 P.fileContent.set = function(content){P.e.taEditor.value = content};
428
429 /**
430 For use when installing a custom editor widget. Pass it the
431 getter and setter callbacks to fetch resp. set the content of the
432 custom widget. They will be triggered via
433 P.fileContent(). Returns this object.
434 */
435 P.setFileContentMethods = function(getter, setter){
436 this.fileContent.get = getter;
437 this.fileContent.set = setter;
438 return this;
439 };
440
441 /**
442 Removes the default editor widget (and any dependent elements)
443 from the DOM, adds the given element in its place, removes this
444 method from this object, and returns this object.
445 */
446 P.replaceEditorElement = function(newEditor){
447 P.e.taEditor.parentNode.insertBefore(newEditor, P.e.taEditor);
448 P.e.taEditor.remove();
449 P.e.selectFontSizeWrap.remove();
450 delete this.replaceEditorElement;
451 return P;
452 };
453
454 /**
455 If either of...
456
@@ -562,26 +596,10 @@
596 );
597 this.setPageTitle("Edit: "+this.finfo.filename);
598 return this;
599 };
600
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
601 /**
602 loadFile() loads (file,checkinVersion) and updates the relevant
603 UI elements to reflect the loaded state. If passed no arguments
604 then it re-uses the values from the currently-loaded file, reloading
605 it (emitting an error message if no file is loaded).
@@ -710,16 +728,12 @@
728 Returns this object, noting that the operation is async.
729 */
730 P.diff = function f(sbs){
731 if(!affirmHasFile()) return this;
732 const content = this.fileContent(),
733 self = this,
734 target = this.e.diffTarget;
 
 
 
 
735 const fd = new FormData();
736 fd.append('filename',this.finfo.filename);
737 fd.append('checkin', this.finfo.checkin);
738 fd.append('sbs', sbs ? 1 : 0);
739 fd.append('content',content);
@@ -728,11 +742,11 @@
742 "Fetching diff..."
743 ).fetch('fileedit',{
744 urlParams: {ajax: 'diff'},
745 payload: fd,
746 onload: function(c){
747 target.innerHTML = [
748 "<div>Diff <code>[",
749 self.finfo.checkin,
750 "]</code> &rarr; Local Edits</div>",
751 c||'No changes.'
752 ].join('');
753
--- www/fileedit-page.md
+++ www/fileedit-page.md
@@ -187,24 +187,17 @@
187187
*Hypothetically*, though this is currently unproven "in the wild," it
188188
is possible to replace `/filepage`'s basic text-editing widget (a
189189
`textarea` element) with a fancy 3rd-party editor widget by doing the
190190
following:
191191
192
-First, replace the `fossil.page.fileContent()` method with a custom
193
-implementation which can get and set the being-edited text from/to the
194
-custom editor widget:
192
+First, install proxy functions so that `fossil.page.fileContent()`
193
+can get and set your content:
195194
196195
```
197
-fossil.page.fileContent = function(){
198
- if(0===arguments.length){//call as a "getter"
199
- return the text-form content of your custom widget
200
- }
201
- else{// called as a setter
202
- set the content of your custom widget to arguments[0]
203
- and then:
204
- return this; // required by the interface!
205
- }
196
+fossil.page.setFileContentMethods(
197
+ function(){ return text-form content of your widget },
198
+ function(content){ set text-form content of your widget }
206199
};
207200
```
208201
209202
Secondly, inject the custom editor widget into the UI, replacing
210203
the default editor widget:
@@ -215,8 +208,10 @@
215208
216209
That method must be passed a DOM element and may only be called once:
217210
it *removes itself* the first time it is called.
218211
219212
That "should" be all there is to it. When `fossil.page` needs to get
220
-the being-edited content, it will call `fossil.page.fileContent()` with no
221
-arguments, and when it sets the content (immediately after (re)loading
222
-a file), it will pass that content to `fossil.page.fileContent()`.
213
+the being-edited content, it will call `fossil.page.fileContent()`
214
+with no arguments, and when it sets the content (immediately after
215
+(re)loading a file), it will pass that content to
216
+`fossil.page.fileContent()`. Those, in turn will trigger the installed
217
+proxies and fire any related events.
223218
--- www/fileedit-page.md
+++ www/fileedit-page.md
@@ -187,24 +187,17 @@
187 *Hypothetically*, though this is currently unproven "in the wild," it
188 is possible to replace `/filepage`'s basic text-editing widget (a
189 `textarea` element) with a fancy 3rd-party editor widget by doing the
190 following:
191
192 First, replace the `fossil.page.fileContent()` method with a custom
193 implementation which can get and set the being-edited text from/to the
194 custom editor widget:
195
196 ```
197 fossil.page.fileContent = function(){
198 if(0===arguments.length){//call as a "getter"
199 return the text-form content of your custom widget
200 }
201 else{// called as a setter
202 set the content of your custom widget to arguments[0]
203 and then:
204 return this; // required by the interface!
205 }
206 };
207 ```
208
209 Secondly, inject the custom editor widget into the UI, replacing
210 the default editor widget:
@@ -215,8 +208,10 @@
215
216 That method must be passed a DOM element and may only be called once:
217 it *removes itself* the first time it is called.
218
219 That "should" be all there is to it. When `fossil.page` needs to get
220 the being-edited content, it will call `fossil.page.fileContent()` with no
221 arguments, and when it sets the content (immediately after (re)loading
222 a file), it will pass that content to `fossil.page.fileContent()`.
 
 
223
--- www/fileedit-page.md
+++ www/fileedit-page.md
@@ -187,24 +187,17 @@
187 *Hypothetically*, though this is currently unproven "in the wild," it
188 is possible to replace `/filepage`'s basic text-editing widget (a
189 `textarea` element) with a fancy 3rd-party editor widget by doing the
190 following:
191
192 First, install proxy functions so that `fossil.page.fileContent()`
193 can get and set your content:
 
194
195 ```
196 fossil.page.setFileContentMethods(
197 function(){ return text-form content of your widget },
198 function(content){ set text-form content of your widget }
 
 
 
 
 
 
199 };
200 ```
201
202 Secondly, inject the custom editor widget into the UI, replacing
203 the default editor widget:
@@ -215,8 +208,10 @@
208
209 That method must be passed a DOM element and may only be called once:
210 it *removes itself* the first time it is called.
211
212 That "should" be all there is to it. When `fossil.page` needs to get
213 the being-edited content, it will call `fossil.page.fileContent()`
214 with no arguments, and when it sets the content (immediately after
215 (re)loading a file), it will pass that content to
216 `fossil.page.fileContent()`. Those, in turn will trigger the installed
217 proxies and fire any related events.
218

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button