zhangchao 4 years ago
parent
commit
b4f4a9253d
4 changed files with 63 additions and 28 deletions
  1. 27
    6
      src/RichTextEditor.js
  2. 6
    2
      src/WebviewMessageHandler.js
  3. 2
    0
      src/const.js
  4. 28
    20
      src/editor.html

+ 27
- 6
src/RichTextEditor.js View File

@@ -147,7 +147,7 @@ export default class RichTextEditor extends Component {
147 147
           this.setContentHTML(this.props.initialContentHTML || '');
148 148
           !this.props.hiddenTitle && this.showTitle();
149 149
           this.props.enableOnChange && this.enableOnChange();
150
-
150
+          
151 151
           this.props.editorInitializedCallback && this.props.editorInitializedCallback();
152 152
 
153 153
           break;
@@ -170,6 +170,9 @@ export default class RichTextEditor extends Component {
170 170
         case messages.CONTENT_BLUR:
171 171
           this.contentBlurHandler && this.contentBlurHandler();
172 172
           break;
173
+        case messages.ONCHANGE_EMPTY_OR_NOT:
174
+          this.onChangeEmptyOrNot && this.onChangeEmptyOrNot();
175
+          break;
173 176
         case messages.SELECTION_CHANGE: {
174 177
           const items = message.data.items;
175 178
           this.state.selectionChangeListeners.map((listener) => {
@@ -310,7 +313,8 @@ export default class RichTextEditor extends Component {
310 313
   //-------------------------------------------------------------------------------
311 314
   //--------------- Public API
312 315
 
313
-  showLinkDialog(optionalTitle = '', optionalUrl = '') {
316
+  showLinkDialog(optionalTitle = '', optionalUrl = '', notCheckedUrlCallback) {
317
+    this.notCheckedUrlCallback = notCheckedUrlCallback || this.notCheckedUrlCallback;
314 318
     this.prepareInsert();
315 319
     this.setState({
316 320
       linkInitialUrl: optionalUrl,
@@ -437,11 +441,19 @@ export default class RichTextEditor extends Component {
437 441
   }
438 442
 
439 443
   insertLink(url, title) {
440
-    this._sendAction(actions.insertLink, {url, title});
444
+    if (/^(http:\/\/|https:\/\/)/.test(url)) {
445
+      this._sendAction(actions.insertLink, {url, title});
446
+    } else {
447
+      this.notCheckedUrlCallback && this.notCheckedUrlCallback()
448
+    }
441 449
   }
442 450
 
443 451
   updateLink(url, title) {
444
-    this._sendAction(actions.updateLink, {url, title});
452
+    if (/^(http:\/\/|https:\/\/)/.test(url)) {
453
+      this._sendAction(actions.updateLink, {url, title});
454
+    } else {
455
+      this.notCheckedUrlCallback && this.notCheckedUrlCallback()
456
+    }
445 457
   }
446 458
 
447 459
   insertImage(url) {
@@ -452,6 +464,10 @@ export default class RichTextEditor extends Component {
452 464
     this._sendAction(actions.insertEmoji, url);
453 465
   }
454 466
 
467
+  deleteEmoji(url) {
468
+    this._sendAction(actions.deleteEmoji, url);
469
+  }
470
+  
455 471
   setSubscript() {
456 472
     this._sendAction(actions.setSubscript);
457 473
   }
@@ -496,8 +512,8 @@ export default class RichTextEditor extends Component {
496 512
     this._sendAction(actions.setCustomCSS, css);
497 513
   }
498 514
 
499
-  prepareInsert() {
500
-    this._sendAction(actions.prepareInsert);
515
+  prepareInsert(showCaretPlaceholder) {
516
+    this._sendAction(actions.prepareInsert, showCaretPlaceholder);
501 517
   }
502 518
 
503 519
   restoreSelection() {
@@ -595,6 +611,11 @@ export default class RichTextEditor extends Component {
595 611
     this._sendAction(actions.setContentBlurHandler);
596 612
   }
597 613
 
614
+  setOnChangeEmptyOrNot(callbackHandler) {
615
+    this.onChangeEmptyOrNot = callbackHandler;
616
+    this._sendAction(actions.setOnChangeEmptyOrNot);
617
+  }
618
+
598 619
   addSelectedTextChangeListener(listener) {
599 620
     this._selectedTextChangeListeners.push(listener);
600 621
   }

+ 6
- 2
src/WebviewMessageHandler.js View File

@@ -59,11 +59,13 @@ export const MessageConverter = (action) => {
59 59
     case `${actions.insertLink}`:
60 60
       return `zss_editor.insertLink('${action.data.url}', '${action.data.title}');`;
61 61
     case `${actions.updateLink}`:
62
-      return `zss_editor.updateLink('${action.data.url}, ${action.data.title}');`;
62
+      return `zss_editor.updateLink('${action.data.url}', '${action.data.title}');`;
63 63
     case `${actions.insertImage}`:
64 64
       return `zss_editor.insertImage('${action.data}');`;
65 65
     case `${actions.insertEmoji}`:
66 66
         return `zss_editor.insertEmoji('${action.data}');`;
67
+    case `${actions.deleteEmoji}`:
68
+        return `zss_editor.deleteEmoji();`;
67 69
     case `${actions.setSubscript}`:
68 70
       return `zss_editor.setSubscript();`;
69 71
     case `${actions.setSuperscript}`:
@@ -85,7 +87,7 @@ export const MessageConverter = (action) => {
85 87
     case `${actions.focusTitle}`:
86 88
       return `zss_editor.focusTitle();`;
87 89
     case `${actions.prepareInsert}`:
88
-      return `zss_editor.prepareInsert();`;
90
+      return `zss_editor.prepareInsert(${action.data});`;
89 91
     case `${actions.restoreSelection}`:
90 92
       return `zss_editor.restorerange();`;
91 93
     case `${actions.setCustomCSS}`:
@@ -106,6 +108,8 @@ export const MessageConverter = (action) => {
106 108
       return `zss_editor.setContentFocusHandler();`;
107 109
     case `${actions.setContentBlurHandler}`:
108 110
         return `zss_editor.setContentBlurHandler();`;
111
+    case `${actions.setOnChangeEmptyOrNot}`:
112
+        return `zss_editor.setOnChangeEmptyOrNot();`;
109 113
     case `${actions.getTitleHtml}`:
110 114
       return `var html = zss_editor.getTitleHTML();
111 115
       ReactNativeWebView.postMessage(JSON.stringify({type: '${messages.TITLE_HTML_RESPONSE}', data: html}));`

+ 2
- 0
src/const.js View File

@@ -35,6 +35,7 @@ export const actions = {
35 35
   updateLink: 'UPDATE_LINK',
36 36
   insertImage: 'INST_IMAGE',
37 37
   insertEmoji: 'INST_EMOJI',
38
+  deleteEmoji: 'DELETE_EMOJI',
38 39
   setSubscript: 'subscript',
39 40
   setSuperscript: 'superscript',
40 41
   setStrikethrough: 'strikeThrough',
@@ -46,6 +47,7 @@ export const actions = {
46 47
   setTitleFocusHandler: 'SET_TITLE_FOCUS_HANDLER',
47 48
   setContentFocusHandler: 'SET_CONTENT_FOCUS_HANDLER',
48 49
   setContentBlurHandler: 'SET_CONTENT_BLUR_HANDLER',
50
+  setOnChangeEmptyOrNot: 'SET_ONCHANGE_EMPTY_OR_NOT',
49 51
   prepareInsert: 'PREPARE_INSERT',
50 52
   restoreSelection: 'RESTORE_SELECTION',
51 53
   setCustomCSS: 'SET_CUSTOM_CSS',

+ 28
- 20
src/editor.html View File

@@ -1057,12 +1057,12 @@
1057 1057
 				}
1058 1058
 			}
1059 1059
 
1060
-			zss_editor.backuprange = function(){
1060
+			zss_editor.backuprange = function(showCaretPlaceholder){
1061 1061
 				var selection = window.getSelection();
1062 1062
 				try {
1063 1063
 					var range = selection.getRangeAt(0);
1064 1064
 					zss_editor.currentSelection = {"startContainer": range.startContainer, "startOffset":range.startOffset,"endContainer":range.endContainer, "endOffset":range.endOffset};
1065
-					if (range.endOffset === range.startOffset) {
1065
+					if (range.endOffset === range.startOffset && showCaretPlaceholder === true) {
1066 1066
 						zss_editor.insertHTML('<div class="caret_placeholder">&nbsp;&nbsp;</div>');
1067 1067
 					}
1068 1068
 				} catch (err) {}
@@ -1260,8 +1260,9 @@
1260 1260
 			zss_editor.insertLink = function(url, title) {
1261 1261
 				zss_editor.restorerange();
1262 1262
 				var sel = window.getSelection();
1263
-				sel.deleteFromDocument();
1263
+				// sel.deleteFromDocument();
1264 1264
 				zss_editor.insertHTML('<a href="'+ url +'">'+ title +'</a>');
1265
+				zss_editor.focusContent();
1265 1266
 				zss_editor.enabledEditingItems();
1266 1267
 			}
1267 1268
 
@@ -1344,8 +1345,8 @@
1344 1345
 
1345 1346
 			}
1346 1347
 
1347
-			zss_editor.prepareInsert = function() {
1348
-				zss_editor.backuprange();
1348
+			zss_editor.prepareInsert = function(showCaretPlaceholder) {
1349
+				zss_editor.backuprange(showCaretPlaceholder);
1349 1350
 			}
1350 1351
 
1351 1352
 			zss_editor.insertImage = function(url) {
@@ -1359,9 +1360,17 @@
1359 1360
 			zss_editor.insertEmoji = function(url) {
1360 1361
 				zss_editor.restorerange();
1361 1362
 				document.execCommand('insertHTML', false, '<img class="emoji" src="' + encodeHtmlEntities(url) + '"/>');
1362
-				zss_editor.backuprange();
1363
+				zss_editor.backuprange(true);
1364
+				zss_editor.blurContentEditor();
1365
+				zss_editor.enabledEditingItems();
1366
+
1367
+			}
1368
+
1369
+			zss_editor.deleteEmoji = function(url) {
1370
+				zss_editor.restorerange();
1371
+				document.execCommand('Delete', false, null);
1372
+				zss_editor.backuprange(true);
1363 1373
 				zss_editor.blurContentEditor();
1364
-				
1365 1374
 				zss_editor.enabledEditingItems();
1366 1375
 			}
1367 1376
 
@@ -1406,6 +1415,7 @@
1406 1415
 			}
1407 1416
 
1408 1417
 			zss_editor.setContentHTML = function(html) {
1418
+				contentIsEmpty = html.length === 0; 
1409 1419
 				setHTML('zss_editor_content', html);
1410 1420
 			}
1411 1421
 
@@ -1590,7 +1600,6 @@
1590 1600
 			}
1591 1601
 
1592 1602
 			zss_editor.focusEditor = function(editorId) {
1593
-
1594 1603
 				// the following was taken from http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity/3866442#3866442
1595 1604
 				// and ensures we move the cursor to the end of the editor
1596 1605
 				var editor = $('#' + editorId);
@@ -1613,19 +1622,7 @@
1613 1622
 			}
1614 1623
 
1615 1624
 			zss_editor.setCustomCSS = function(customCSS) {
1616
-
1617 1625
 				document.getElementsByTagName('style')[1].innerHTML=customCSS;
1618
-
1619
-				//set focus
1620
-				/*editor.focusout(function(){
1621
-				 var element = $(this);
1622
-				 if (!element.text().trim().length) {
1623
-				 element.empty();
1624
-				 }
1625
-				 });*/
1626
-
1627
-
1628
-
1629 1626
 			}
1630 1627
 
1631 1628
 			function addFocusEvent(editorId, callbackHandler) {
@@ -1657,6 +1654,17 @@
1657 1654
 				});
1658 1655
 			}
1659 1656
 
1657
+			var contentIsEmpty = true;
1658
+			zss_editor.setOnChangeEmptyOrNot = function() {
1659
+				$('#zss_editor_content').on('input', function() {
1660
+					if (!this.textContent && this.querySelectorAll('img, li').length === 0 && !contentIsEmpty) {
1661
+						ReactNativeWebView.postMessage(JSON.stringify({type: 'ONCHANGE_EMPTY_OR_NOT', isEmpty: true}))
1662
+					} else if (contentIsEmpty && (this.textContent || this.querySelectorAll('img, li').length > 0)) {
1663
+						ReactNativeWebView.postMessage(JSON.stringify({type: 'ONCHANGE_EMPTY_OR_NOT', isEmpty: false}))
1664
+					}
1665
+				});
1666
+			}
1667
+
1660 1668
 			zss_editor.setEditorHeight = function(editorHeight) {
1661 1669
 				zss_editor.editorHeight = editorHeight;
1662 1670
 			}