Browse Source

Links, prepareInsert()

Yedidya Kennard 8 years ago
parent
commit
3ecc5c89a6
5 changed files with 153 additions and 30 deletions
  1. 129
    11
      src/RichTextEditor.js
  2. 4
    0
      src/RichTextToolbar.js
  3. 7
    3
      src/WebviewMessageHandler.js
  4. 10
    15
      src/ZSSRichTextEditor/ZSSRichTextEditor.js
  5. 3
    1
      src/const.js

+ 129
- 11
src/RichTextEditor.js View File

@@ -2,6 +2,7 @@ import React, {Component, PropTypes} from 'react';
2 2
 import WebViewBridge from 'react-native-webview-bridge-updated';
3 3
 import {InjectedMessageHandler} from './WebviewMessageHandler';
4 4
 import {actions, messages} from './const';
5
+import {Modal, View, Text, StyleSheet, TextInput, TouchableOpacity} from 'react-native';
5 6
 
6 7
 const injectScript = `
7 8
   (function () {
@@ -22,7 +23,10 @@ export default class RichTextEditor extends Component {
22 23
     this.registerToolbar = this.registerToolbar.bind(this);
23 24
     this.onBridgeMessage = this.onBridgeMessage.bind(this);
24 25
     this.state = {
25
-      listeners: []
26
+      listeners: [],
27
+      showLinkDialog: false,
28
+      linkTitle: '',
29
+      linkUrl: ''
26 30
     };
27 31
   }
28 32
 
@@ -80,16 +84,91 @@ export default class RichTextEditor extends Component {
80 84
     }
81 85
   }
82 86
 
87
+  _renderLinkModal() {
88
+    return (
89
+        <Modal
90
+            animationType={"fade"}
91
+            transparent
92
+            visible={this.state.showLinkDialog}
93
+            onRequestClose={() => this.setState({showLinkDialog: false})}
94
+        >
95
+          <View style={styles.modal}>
96
+
97
+
98
+            <View style={styles.innerModal}>
99
+
100
+              <Text>Title</Text>
101
+              <View style={styles.inputWrapper}>
102
+                <TextInput
103
+                    style={{height: 20}}
104
+                    onChangeText={(text) => this.setState({linkTitle: text})}
105
+                    value={this.state.linkTitle}
106
+                />
107
+              </View>
108
+
109
+              <Text style={{marginTop: 10}}>URL</Text>
110
+              <View style={styles.inputWrapper}>
111
+                <TextInput
112
+                    style={{height: 20}}
113
+                    onChangeText={(text) => this.setState({linkUrl: text})}
114
+                    value={this.state.linkUrl}
115
+                />
116
+              </View>
117
+
118
+              {this._renderModalButtons()}
119
+            </View>
120
+          </View>
121
+        </Modal>
122
+    );
123
+  }
124
+
125
+  _hideModal() {
126
+    this.setState({
127
+      showLinkDialog: false,
128
+      linkTitle: '',
129
+      linkUrl: ''
130
+    })
131
+  }
132
+
133
+  _renderModalButtons() {
134
+    return (
135
+      <View style={{paddingTop: 10, alignSelf: 'stretch', flexDirection: 'row'}}>
136
+        <View style={{flex: 1}}/>
137
+        <TouchableOpacity
138
+            onPress={() => this._hideModal()}
139
+        >
140
+          <Text style={[styles.button, {paddingRight: 10}]}>
141
+            Cancel
142
+          </Text>
143
+        </TouchableOpacity>
144
+        <TouchableOpacity
145
+            onPress={() => {
146
+              this.insertLink(this.state.linkUrl, this.state.linkTitle);
147
+              this._hideModal();
148
+            }}
149
+        >
150
+          <Text style={styles.button}>
151
+            OK
152
+          </Text>
153
+        </TouchableOpacity>
154
+      </View>
155
+    );
156
+  }
157
+
83 158
   render() {
84 159
     return (
85
-      <WebViewBridge
86
-        {...this.props}
87
-        hideKeyboardAccessoryView={true}
88
-        ref={(r) => {this.webviewBridge = r}}
89
-        onBridgeMessage={(message) => this.onBridgeMessage(message)}
90
-        injectedJavaScript={injectScript}
91
-        source={require('./editor.html')}
92
-      />
160
+      <View style={{flex: 1}}>
161
+        <WebViewBridge
162
+          style={{flex: 1}}
163
+          {...this.props}
164
+          hideKeyboardAccessoryView={true}
165
+          ref={(r) => {this.webviewBridge = r}}
166
+          onBridgeMessage={(message) => this.onBridgeMessage(message)}
167
+          injectedJavaScript={injectScript}
168
+          source={require('./editor.html')}
169
+        />
170
+        {this._renderLinkModal()}
171
+      </View>
93 172
     );
94 173
   }
95 174
 
@@ -114,9 +193,15 @@ export default class RichTextEditor extends Component {
114 193
   //-------------------------------------------------------------------------------
115 194
   //--------------- Public API
116 195
 
196
+  showLinkDialog() {
197
+    this.setState({
198
+      showLinkDialog: true
199
+    });
200
+  }
201
+
117 202
   focusTitle() {
118 203
     this._sendAction(actions.focusTitle);
119
-  }wewe
204
+  }
120 205
 
121 206
   focusContent() {
122 207
     this._sendAction(actions.focusContent);
@@ -213,6 +298,7 @@ export default class RichTextEditor extends Component {
213 298
   }
214 299
 
215 300
   insertLink(url, title) {
301
+
216 302
     this._sendAction(actions.insertLink, {url, title});
217 303
   }
218 304
 
@@ -252,6 +338,14 @@ export default class RichTextEditor extends Component {
252 338
     this._sendAction(actions.setContentPlaceholder);
253 339
   }
254 340
 
341
+  prepareInsert() {
342
+    this._sendAction(actions.prepareInsert);
343
+  }
344
+
345
+  restoreSelection() {
346
+    this._sendAction(actions.restoreSelection);
347
+  }
348
+
255 349
   async getTitleHtml() {
256 350
     return new Promise((resolve, reject) => {
257 351
       this.titleResolve = resolve;
@@ -289,4 +383,28 @@ export default class RichTextEditor extends Component {
289 383
     this.contentFocusHandler = callbackHandler;
290 384
     this._sendAction(actions.setContentFocusHandler);
291 385
   }
292
-}
386
+}
387
+
388
+const styles = StyleSheet.create({
389
+  modal: {
390
+    flex: 1,
391
+    justifyContent: 'center',
392
+    alignItems: 'center',
393
+    backgroundColor: 'rgba(0, 0, 0, 0.5)'
394
+  },
395
+  innerModal: {
396
+    backgroundColor: '#ffffff',
397
+    padding: 20,
398
+    alignSelf: 'stretch',
399
+    margin: 40
400
+  },
401
+  button: {
402
+    fontSize: 16
403
+  },
404
+  inputWrapper: {
405
+    marginTop: 10,
406
+    marginBottom: 10,
407
+    borderBottomColor: '#000000',
408
+    borderBottomWidth: 1
409
+  }
410
+});

+ 4
- 0
src/RichTextToolbar.js View File

@@ -144,11 +144,15 @@ export default class RichTextToolbar extends Component {
144 144
         this.state.editor._sendAction(action);
145 145
         break;
146 146
       case actions.insertLink:
147
+        this.state.editor.prepareInsert();
147 148
         if(this.props.onPressAddLink) {
148 149
           this.props.onPressAddLink();
150
+        } else {
151
+          this.state.editor.showLinkDialog();
149 152
         }
150 153
         break;
151 154
       case actions.insertImage:
155
+        this.state.editor.prepareInsert();
152 156
         if(this.props.onPressAddImage) {
153 157
           this.props.onPressAddImage();
154 158
         }

+ 7
- 3
src/WebviewMessageHandler.js View File

@@ -69,11 +69,9 @@ export const InjectedMessageHandler = `
69 69
           zss_editor.setOrderedList();
70 70
           break;
71 71
         case '${actions.insertLink}':
72
-          zss_editor.prepareInsert();
73 72
           zss_editor.insertLink(action.data.url, action.data.title);
74 73
           break;
75 74
         case '${actions.insertImage}':
76
-          zss_editor.prepareInsert();
77 75
           zss_editor.insertImage(action.data.url, action.data.alt);
78 76
           break;
79 77
         case '${actions.setSubscript}':
@@ -120,7 +118,13 @@ export const InjectedMessageHandler = `
120 118
         case '${actions.focusTitle}':
121 119
           zss_editor.focusTitle();
122 120
           break;
121
+        case '${actions.prepareInsert}':
122
+          zss_editor.prepareInsert();
123
+          break;
124
+        case '${actions.restoreSelection}':
125
+          zss_editor.restorerange();
126
+          break;
123 127
       }
124 128
     };
125 129
   }
126
-`;
130
+`;

+ 10
- 15
src/ZSSRichTextEditor/ZSSRichTextEditor.js View File

@@ -204,21 +204,17 @@ zss_editor.calculateEditorHeightWithCaretPosition = function(editorId) {
204 204
 
205 205
 zss_editor.backuprange = function(){
206 206
     var selection = window.getSelection();
207
-    if(selection && selection.length > 0) {
208
-        var range = selection.getRangeAt(0);
209
-        zss_editor.currentSelection = {"startContainer": range.startContainer, "startOffset":range.startOffset,"endContainer":range.endContainer, "endOffset":range.endOffset};
210
-    }
207
+    var range = selection.getRangeAt(0);
208
+    zss_editor.currentSelection = {"startContainer": range.startContainer, "startOffset":range.startOffset,"endContainer":range.endContainer, "endOffset":range.endOffset};
211 209
 }
212 210
 
213 211
 zss_editor.restorerange = function(){
214 212
     var selection = window.getSelection();
215
-    if(selection && selection.length > 0) {
216
-        selection.removeAllRanges();
217
-        var range = document.createRange();
218
-        range.setStart(zss_editor.currentSelection.startContainer, zss_editor.currentSelection.startOffset);
219
-        range.setEnd(zss_editor.currentSelection.endContainer, zss_editor.currentSelection.endOffset);
220
-        selection.addRange(range);
221
-    }
213
+    selection.removeAllRanges();
214
+    var range = document.createRange();
215
+    range.setStart(zss_editor.currentSelection.startContainer, zss_editor.currentSelection.startOffset);
216
+    range.setEnd(zss_editor.currentSelection.endContainer, zss_editor.currentSelection.endOffset);
217
+    selection.addRange(range);
222 218
 }
223 219
 
224 220
 zss_editor.getSelectedNode = function() {
@@ -396,7 +392,7 @@ zss_editor.setBackgroundColor = function(color) {
396 392
 // Needs addClass method
397 393
 
398 394
 zss_editor.insertLink = function(url, title) {
399
-    
395
+
400 396
     zss_editor.restorerange();
401 397
     var sel = document.getSelection();
402 398
     console.log(sel);
@@ -508,7 +504,6 @@ zss_editor.prepareInsert = function() {
508 504
 }
509 505
 
510 506
 zss_editor.insertImage = function(url, alt) {
511
-    zss_editor.focusContent();
512 507
     zss_editor.restorerange();
513 508
     var html = '<img src="'+url+'" alt="'+alt+'" />';
514 509
     zss_editor.insertHTML(html);
@@ -708,11 +703,11 @@ zss_editor.enabledEditingItems = function(e) {
708 703
 }
709 704
 
710 705
 zss_editor.focusContent = function() {
711
-    zss_editor.focusEditor('zss_editor_content');
706
+    $('#zss_editor_content').focus();
712 707
 }
713 708
 
714 709
 zss_editor.focusTitle = function() {
715
-    zss_editor.focusEditor('zss_editor_title');
710
+    $('#zss_editor_title').focus();
716 711
 }
717 712
 
718 713
 zss_editor.focusEditor = function(editorId) {

+ 3
- 1
src/const.js View File

@@ -36,7 +36,9 @@ export const actions = {
36 36
   setTitlePlaceholder: 'SET_TITLE_PLACEHOLDER',
37 37
   setContentPlaceholder: 'SET_TITLE_PLACEHOLDER',
38 38
   setTitleFocusHandler: 'SET_TITLE_FOCUS_HANDLER',
39
-  setContentFocusHandler: 'SET_CONTENT_FOCUS_HANDLER'
39
+  setContentFocusHandler: 'SET_CONTENT_FOCUS_HANDLER',
40
+  prepareInsert: 'PREPARE_INSERT',
41
+  restoreSelection: 'RESTORE_SELECTION'
40 42
 };
41 43
 
42 44