浏览代码

Fixed editor not working in release builds:

1. All external dependencies of the editor like css and js must be included inside the html file.
2. External html files in Android can't be required, so they must be placed in the assets folder and accessed via uri

Also removed using keyboard spacer on Android in the example app.
Artal Druk 8 年前
父节点
当前提交
27cc519d28

+ 1658
- 0
example/android/app/src/main/assets/editor.html
文件差异内容过多而无法显示
查看文件


+ 3
- 2
example/app.js 查看文件

@@ -2,7 +2,8 @@ import React, { Component } from 'react';
2 2
 import {
3 3
     StyleSheet,
4 4
     Text,
5
-    View
5
+    View,
6
+    Platform
6 7
 } from 'react-native';
7 8
 import {RichTextEditor, RichTextToolbar} from 'react-native-ZSSRichTextEditor'
8 9
 import KeyboardSpacer from 'react-native-keyboard-spacer';
@@ -28,7 +29,7 @@ export default class RichTextExample extends Component {
28 29
           <RichTextToolbar
29 30
             getEditor={() => this.richtext}
30 31
           />
31
-          <KeyboardSpacer/>
32
+          {Platform.OS === 'ios' && <KeyboardSpacer/>}
32 33
         </View>
33 34
     );
34 35
   }

+ 4
- 2
src/RichTextEditor.js 查看文件

@@ -2,7 +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
+import {Modal, View, Text, StyleSheet, TextInput, TouchableOpacity, Platform} from 'react-native';
6 6
 
7 7
 const injectScript = `
8 8
   (function () {
@@ -165,6 +165,8 @@ export default class RichTextEditor extends Component {
165 165
   }
166 166
 
167 167
   render() {
168
+    //in release build, external html files in Android can't be required, so they must be placed in the assets folder and accessed via uri
169
+    const pageSource = Platform.OS === 'ios' ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' };
168 170
     return (
169 171
       <View style={{flex: 1}}>
170 172
         <WebViewBridge
@@ -174,7 +176,7 @@ export default class RichTextEditor extends Component {
174 176
           ref={(r) => {this.webviewBridge = r}}
175 177
           onBridgeMessage={(message) => this.onBridgeMessage(message)}
176 178
           injectedJavaScript={injectScript}
177
-          source={require('./editor.html')}
179
+          source={pageSource}
178 180
         />
179 181
         {this._renderLinkModal()}
180 182
       </View>

+ 0
- 766
src/ZSSRichTextEditor/JSBeautifier.js 查看文件

@@ -1,766 +0,0 @@
1
-/*
2
- 
3
- The MIT License (MIT)
4
- 
5
- Copyright (c) 2007-2013 Einar Lielmanis and contributors.
6
- 
7
- Permission is hereby granted, free of charge, to any person
8
- obtaining a copy of this software and associated documentation files
9
- (the "Software"), to deal in the Software without restriction,
10
- including without limitation the rights to use, copy, modify, merge,
11
- publish, distribute, sublicense, and/or sell copies of the Software,
12
- and to permit persons to whom the Software is furnished to do so,
13
- subject to the following conditions:
14
- 
15
- The above copyright notice and this permission notice shall be
16
- included in all copies or substantial portions of the Software.
17
- 
18
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22
- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23
- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
- SOFTWARE.
26
- 
27
- JS Beautifier
28
- ---------------
29
- 
30
- */
31
-
32
-function trim(s) {
33
-	return s.replace(/^\s+|\s+$/g, '');
34
-}
35
-
36
-function ltrim(s) {
37
-	return s.replace(/^\s+/g, '');
38
-}
39
-
40
-function style_html(html_source, options) {
41
-	//Wrapper function to invoke all the necessary constructors and deal with the output.
42
-
43
-	var multi_parser,
44
-		indent_inner_html,
45
-		indent_size,
46
-		indent_character,
47
-		wrap_line_length,
48
-		brace_style,
49
-		unformatted,
50
-		preserve_newlines,
51
-		max_preserve_newlines;
52
-
53
-	options = options || {};
54
-
55
-	// backwards compatibility to 1.3.4
56
-	if ((options.wrap_line_length === undefined || parseInt(options.wrap_line_length, 10) === 0) &&
57
-			(options.max_char === undefined || parseInt(options.max_char, 10) === 0)) {
58
-		options.wrap_line_length = options.max_char;
59
-	}
60
-
61
-	indent_inner_html = options.indent_inner_html || false;
62
-	indent_size = parseInt(options.indent_size || 4, 10);
63
-	indent_character = options.indent_char || ' ';
64
-	brace_style = options.brace_style || 'collapse';
65
-	wrap_line_length =  parseInt(options.wrap_line_length, 10) === 0 ? 32786 : parseInt(options.wrap_line_length || 250, 10);
66
-	unformatted = options.unformatted || ['a', 'span', 'bdo', 'em', 'strong', 'dfn', 'code', 'samp', 'kbd', 'var', 'cite', 'abbr', 'acronym', 'q', 'sub', 'sup', 'tt', 'i', 'b', 'big', 'small', 'u', 's', 'strike', 'font', 'ins', 'del', 'pre', 'address', 'dt', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
67
-	preserve_newlines = options.preserve_newlines || true;
68
-	max_preserve_newlines = preserve_newlines ? parseInt(options.max_preserve_newlines || 32786, 10) : 0;
69
-	indent_handlebars = options.indent_handlebars || false;
70
-
71
-	function Parser() {
72
-
73
-		this.pos = 0; //Parser position
74
-		this.token = '';
75
-		this.current_mode = 'CONTENT'; //reflects the current Parser mode: TAG/CONTENT
76
-		this.tags = { //An object to hold tags, their position, and their parent-tags, initiated with default values
77
-			parent: 'parent1',
78
-			parentcount: 1,
79
-			parent1: ''
80
-		};
81
-		this.tag_type = '';
82
-		this.token_text = this.last_token = this.last_text = this.token_type = '';
83
-		this.newlines = 0;
84
-		this.indent_content = indent_inner_html;
85
-
86
-		this.Utils = { //Uilities made available to the various functions
87
-			whitespace: "\n\r\t ".split(''),
88
-			single_token: 'br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed,?php,?,?='.split(','), //all the single tags for HTML
89
-			extra_liners: 'head,body,/html'.split(','), //for tags that need a line of whitespace before them
90
-			in_array: function(what, arr) {
91
-				for (var i = 0; i < arr.length; i++) {
92
-					if (what === arr[i]) {
93
-						return true;
94
-					}
95
-				}
96
-				return false;
97
-			}
98
-		};
99
-
100
-		this.traverse_whitespace = function() {
101
-			var input_char = '';
102
-
103
-			input_char = this.input.charAt(this.pos);
104
-			if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
105
-				this.newlines = 0;
106
-				while (this.Utils.in_array(input_char, this.Utils.whitespace)) {
107
-					if (preserve_newlines && input_char === '\n' && this.newlines <= max_preserve_newlines) {
108
-						this.newlines += 1;
109
-					}
110
-
111
-					this.pos++;
112
-					input_char = this.input.charAt(this.pos);
113
-				}
114
-				return true;
115
-			}
116
-			return false;
117
-		};
118
-
119
-		this.get_content = function() { //function to capture regular content between tags
120
-
121
-			var input_char = '',
122
-				content = [],
123
-				space = false; //if a space is needed
124
-
125
-			while (this.input.charAt(this.pos) !== '<') {
126
-				if (this.pos >= this.input.length) {
127
-					return content.length ? content.join('') : ['', 'TK_EOF'];
128
-				}
129
-
130
-				if (this.traverse_whitespace()) {
131
-					if (content.length) {
132
-						space = true;
133
-					}
134
-					continue; //don't want to insert unnecessary space
135
-				}
136
-
137
-				if (indent_handlebars) {
138
-					// Handlebars parsing is complicated.
139
-					// {{#foo}} and {{/foo}} are formatted tags.
140
-					// {{something}} should get treated as content, except:
141
-					// {{else}} specifically behaves like {{#if}} and {{/if}}
142
-					var peek3 = this.input.substr(this.pos, 3);
143
-					if (peek3 === '{{#' || peek3 === '{{/') {
144
-						// These are tags and not content.
145
-						break;
146
-					} else if (this.input.substr(this.pos, 2) === '{{') {
147
-						if (this.get_tag(true) === '{{else}}') {
148
-							break;
149
-						}
150
-					}
151
-				}
152
-
153
-				input_char = this.input.charAt(this.pos);
154
-				this.pos++;
155
-
156
-				if (space) {
157
-					if (this.line_char_count >= this.wrap_line_length) { //insert a line when the wrap_line_length is reached
158
-						this.print_newline(false, content);
159
-						this.print_indentation(content);
160
-					} else {
161
-						this.line_char_count++;
162
-						content.push(' ');
163
-					}
164
-					space = false;
165
-				}
166
-				this.line_char_count++;
167
-				content.push(input_char); //letter at-a-time (or string) inserted to an array
168
-			}
169
-			return content.length ? content.join('') : '';
170
-		};
171
-
172
-		this.get_contents_to = function(name) { //get the full content of a script or style to pass to js_beautify
173
-			if (this.pos === this.input.length) {
174
-				return ['', 'TK_EOF'];
175
-			}
176
-			var input_char = '';
177
-			var content = '';
178
-			var reg_match = new RegExp('</' + name + '\\s*>', 'igm');
179
-			reg_match.lastIndex = this.pos;
180
-			var reg_array = reg_match.exec(this.input);
181
-			var end_script = reg_array ? reg_array.index : this.input.length; //absolute end of script
182
-			if (this.pos < end_script) { //get everything in between the script tags
183
-				content = this.input.substring(this.pos, end_script);
184
-				this.pos = end_script;
185
-			}
186
-			return content;
187
-		};
188
-
189
-		this.record_tag = function(tag) { //function to record a tag and its parent in this.tags Object
190
-			if (this.tags[tag + 'count']) { //check for the existence of this tag type
191
-				this.tags[tag + 'count']++;
192
-				this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
193
-			} else { //otherwise initialize this tag type
194
-				this.tags[tag + 'count'] = 1;
195
-				this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
196
-			}
197
-			this.tags[tag + this.tags[tag + 'count'] + 'parent'] = this.tags.parent; //set the parent (i.e. in the case of a div this.tags.div1parent)
198
-			this.tags.parent = tag + this.tags[tag + 'count']; //and make this the current parent (i.e. in the case of a div 'div1')
199
-		};
200
-
201
-		this.retrieve_tag = function(tag) { //function to retrieve the opening tag to the corresponding closer
202
-			if (this.tags[tag + 'count']) { //if the openener is not in the Object we ignore it
203
-				var temp_parent = this.tags.parent; //check to see if it's a closable tag.
204
-				while (temp_parent) { //till we reach '' (the initial value);
205
-					if (tag + this.tags[tag + 'count'] === temp_parent) { //if this is it use it
206
-						break;
207
-					}
208
-					temp_parent = this.tags[temp_parent + 'parent']; //otherwise keep on climbing up the DOM Tree
209
-				}
210
-				if (temp_parent) { //if we caught something
211
-					this.indent_level = this.tags[tag + this.tags[tag + 'count']]; //set the indent_level accordingly
212
-					this.tags.parent = this.tags[temp_parent + 'parent']; //and set the current parent
213
-				}
214
-				delete this.tags[tag + this.tags[tag + 'count'] + 'parent']; //delete the closed tags parent reference...
215
-				delete this.tags[tag + this.tags[tag + 'count']]; //...and the tag itself
216
-				if (this.tags[tag + 'count'] === 1) {
217
-					delete this.tags[tag + 'count'];
218
-				} else {
219
-					this.tags[tag + 'count']--;
220
-				}
221
-			}
222
-		};
223
-
224
-		this.indent_to_tag = function(tag) {
225
-			// Match the indentation level to the last use of this tag, but don't remove it.
226
-			if (!this.tags[tag + 'count']) {
227
-				return;
228
-			}
229
-			var temp_parent = this.tags.parent;
230
-			while (temp_parent) {
231
-				if (tag + this.tags[tag + 'count'] === temp_parent) {
232
-					break;
233
-				}
234
-				temp_parent = this.tags[temp_parent + 'parent'];
235
-			}
236
-			if (temp_parent) {
237
-				this.indent_level = this.tags[tag + this.tags[tag + 'count']];
238
-			}
239
-		};
240
-
241
-		this.get_tag = function(peek) { //function to get a full tag and parse its type
242
-			var input_char = '',
243
-				content = [],
244
-				comment = '',
245
-				space = false,
246
-				tag_start, tag_end,
247
-				tag_start_char,
248
-				orig_pos = this.pos,
249
-				orig_line_char_count = this.line_char_count;
250
-
251
-			peek = peek !== undefined ? peek : false;
252
-
253
-			do {
254
-				if (this.pos >= this.input.length) {
255
-					if (peek) {
256
-						this.pos = orig_pos;
257
-						this.line_char_count = orig_line_char_count;
258
-					}
259
-					return content.length ? content.join('') : ['', 'TK_EOF'];
260
-				}
261
-
262
-				input_char = this.input.charAt(this.pos);
263
-				this.pos++;
264
-
265
-				if (this.Utils.in_array(input_char, this.Utils.whitespace)) { //don't want to insert unnecessary space
266
-					space = true;
267
-					continue;
268
-				}
269
-
270
-				if (input_char === "'" || input_char === '"') {
271
-					input_char += this.get_unformatted(input_char);
272
-					space = true;
273
-
274
-				}
275
-
276
-				if (input_char === '=') { //no space before =
277
-					space = false;
278
-				}
279
-
280
-				if (content.length && content[content.length - 1] !== '=' && input_char !== '>' && space) {
281
-					//no space after = or before >
282
-					if (this.line_char_count >= this.wrap_line_length) {
283
-						this.print_newline(false, content);
284
-						this.print_indentation(content);
285
-					} else {
286
-						content.push(' ');
287
-						this.line_char_count++;
288
-					}
289
-					space = false;
290
-				}
291
-
292
-				if (indent_handlebars && tag_start_char === '<') {
293
-					// When inside an angle-bracket tag, put spaces around
294
-					// handlebars not inside of strings.
295
-					if ((input_char + this.input.charAt(this.pos)) === '{{') {
296
-						input_char += this.get_unformatted('}}');
297
-						if (content.length && content[content.length - 1] !== ' ' && content[content.length - 1] !== '<') {
298
-							input_char = ' ' + input_char;
299
-						}
300
-						space = true;
301
-					}
302
-				}
303
-
304
-				if (input_char === '<' && !tag_start_char) {
305
-					tag_start = this.pos - 1;
306
-					tag_start_char = '<';
307
-				}
308
-
309
-				if (indent_handlebars && !tag_start_char) {
310
-					if (content.length >= 2 && content[content.length - 1] === '{' && content[content.length - 2] == '{') {
311
-						if (input_char === '#' || input_char === '/') {
312
-							tag_start = this.pos - 3;
313
-						} else {
314
-							tag_start = this.pos - 2;
315
-						}
316
-						tag_start_char = '{';
317
-					}
318
-				}
319
-
320
-				this.line_char_count++;
321
-				content.push(input_char); //inserts character at-a-time (or string)
322
-
323
-				if (content[1] && content[1] === '!') { //if we're in a comment, do something special
324
-					// We treat all comments as literals, even more than preformatted tags
325
-					// we just look for the appropriate close tag
326
-					content = [this.get_comment(tag_start)];
327
-					break;
328
-				}
329
-
330
-				if (indent_handlebars && tag_start_char === '{' && content.length > 2 && content[content.length - 2] === '}' && content[content.length - 1] === '}') {
331
-					break;
332
-				}
333
-			} while (input_char !== '>');
334
-
335
-			var tag_complete = content.join('');
336
-			var tag_index;
337
-			var tag_offset;
338
-
339
-			if (tag_complete.indexOf(' ') !== -1) { //if there's whitespace, thats where the tag name ends
340
-				tag_index = tag_complete.indexOf(' ');
341
-			} else if (tag_complete[0] === '{') {
342
-				tag_index = tag_complete.indexOf('}');
343
-			} else { //otherwise go with the tag ending
344
-				tag_index = tag_complete.indexOf('>');
345
-			}
346
-			if (tag_complete[0] === '<' || !indent_handlebars) {
347
-				tag_offset = 1;
348
-			} else {
349
-				tag_offset = tag_complete[2] === '#' ? 3 : 2;
350
-			}
351
-			var tag_check = tag_complete.substring(tag_offset, tag_index).toLowerCase();
352
-			if (tag_complete.charAt(tag_complete.length - 2) === '/' ||
353
-				this.Utils.in_array(tag_check, this.Utils.single_token)) { //if this tag name is a single tag type (either in the list or has a closing /)
354
-				if (!peek) {
355
-					this.tag_type = 'SINGLE';
356
-				}
357
-			} else if (indent_handlebars && tag_complete[0] === '{' && tag_check === 'else') {
358
-				if (!peek) {
359
-					this.indent_to_tag('if');
360
-					this.tag_type = 'HANDLEBARS_ELSE';
361
-					this.indent_content = true;
362
-					this.traverse_whitespace();
363
-				}
364
-			} else if (tag_check === 'script') { //for later script handling
365
-				if (!peek) {
366
-					this.record_tag(tag_check);
367
-					this.tag_type = 'SCRIPT';
368
-				}
369
-			} else if (tag_check === 'style') { //for future style handling (for now it justs uses get_content)
370
-				if (!peek) {
371
-					this.record_tag(tag_check);
372
-					this.tag_type = 'STYLE';
373
-				}
374
-			} else if (this.is_unformatted(tag_check, unformatted)) { // do not reformat the "unformatted" tags
375
-				comment = this.get_unformatted('</' + tag_check + '>', tag_complete); //...delegate to get_unformatted function
376
-				content.push(comment);
377
-				// Preserve collapsed whitespace either before or after this tag.
378
-				if (tag_start > 0 && this.Utils.in_array(this.input.charAt(tag_start - 1), this.Utils.whitespace)) {
379
-					content.splice(0, 0, this.input.charAt(tag_start - 1));
380
-				}
381
-				tag_end = this.pos - 1;
382
-				if (this.Utils.in_array(this.input.charAt(tag_end + 1), this.Utils.whitespace)) {
383
-					content.push(this.input.charAt(tag_end + 1));
384
-				}
385
-				this.tag_type = 'SINGLE';
386
-			} else if (tag_check.charAt(0) === '!') { //peek for <! comment
387
-				// for comments content is already correct.
388
-				if (!peek) {
389
-					this.tag_type = 'SINGLE';
390
-					this.traverse_whitespace();
391
-				}
392
-			} else if (!peek) {
393
-				if (tag_check.charAt(0) === '/') { //this tag is a double tag so check for tag-ending
394
-					this.retrieve_tag(tag_check.substring(1)); //remove it and all ancestors
395
-					this.tag_type = 'END';
396
-					this.traverse_whitespace();
397
-				} else { //otherwise it's a start-tag
398
-					this.record_tag(tag_check); //push it on the tag stack
399
-					if (tag_check.toLowerCase() !== 'html') {
400
-						this.indent_content = true;
401
-					}
402
-					this.tag_type = 'START';
403
-
404
-					// Allow preserving of newlines after a start tag
405
-					this.traverse_whitespace();
406
-				}
407
-				if (this.Utils.in_array(tag_check, this.Utils.extra_liners)) { //check if this double needs an extra line
408
-					this.print_newline(false, this.output);
409
-					if (this.output.length && this.output[this.output.length - 2] !== '\n') {
410
-						this.print_newline(true, this.output);
411
-					}
412
-				}
413
-			}
414
-
415
-			if (peek) {
416
-				this.pos = orig_pos;
417
-				this.line_char_count = orig_line_char_count;
418
-			}
419
-
420
-			return content.join(''); //returns fully formatted tag
421
-		};
422
-
423
-		this.get_comment = function(start_pos) { //function to return comment content in its entirety
424
-			// this is will have very poor perf, but will work for now.
425
-			var comment = '',
426
-				delimiter = '>',
427
-				matched = false;
428
-
429
-			this.pos = start_pos;
430
-			input_char = this.input.charAt(this.pos);
431
-			this.pos++;
432
-
433
-			while (this.pos <= this.input.length) {
434
-				comment += input_char;
435
-
436
-				// only need to check for the delimiter if the last chars match
437
-				if (comment[comment.length - 1] === delimiter[delimiter.length - 1] &&
438
-					comment.indexOf(delimiter) !== -1) {
439
-					break;
440
-				}
441
-
442
-				// only need to search for custom delimiter for the first few characters
443
-				if (!matched && comment.length < 10) {
444
-					if (comment.indexOf('<![if') === 0) { //peek for <![if conditional comment
445
-						delimiter = '<![endif]>';
446
-						matched = true;
447
-					} else if (comment.indexOf('<![cdata[') === 0) { //if it's a <[cdata[ comment...
448
-						delimiter = ']]>';
449
-						matched = true;
450
-					} else if (comment.indexOf('<![') === 0) { // some other ![ comment? ...
451
-						delimiter = ']>';
452
-						matched = true;
453
-					} else if (comment.indexOf('<!--') === 0) { // <!-- comment ...
454
-						delimiter = '-->';
455
-						matched = true;
456
-					}
457
-				}
458
-
459
-				input_char = this.input.charAt(this.pos);
460
-				this.pos++;
461
-			}
462
-
463
-			return comment;
464
-		};
465
-
466
-		this.get_unformatted = function(delimiter, orig_tag) { //function to return unformatted content in its entirety
467
-
468
-			if (orig_tag && orig_tag.toLowerCase().indexOf(delimiter) !== -1) {
469
-				return '';
470
-			}
471
-			var input_char = '';
472
-			var content = '';
473
-			var min_index = 0;
474
-			var space = true;
475
-			do {
476
-
477
-				if (this.pos >= this.input.length) {
478
-					return content;
479
-				}
480
-
481
-				input_char = this.input.charAt(this.pos);
482
-				this.pos++;
483
-
484
-				if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
485
-					if (!space) {
486
-						this.line_char_count--;
487
-						continue;
488
-					}
489
-					if (input_char === '\n' || input_char === '\r') {
490
-						content += '\n';
491
-						/*  Don't change tab indention for unformatted blocks.  If using code for html editing, this will greatly affect <pre> tags if they are specified in the 'unformatted array'
492
-			for (var i=0; i<this.indent_level; i++) {
493
-			  content += this.indent_string;
494
-			}
495
-			space = false; //...and make sure other indentation is erased
496
-			*/
497
-						this.line_char_count = 0;
498
-						continue;
499
-					}
500
-				}
501
-				content += input_char;
502
-				this.line_char_count++;
503
-				space = true;
504
-
505
-				if (indent_handlebars && input_char === '{' && content.length && content[content.length - 2] === '{') {
506
-					// Handlebars expressions in strings should also be unformatted.
507
-					content += this.get_unformatted('}}');
508
-					// These expressions are opaque.  Ignore delimiters found in them.
509
-					min_index = content.length;
510
-				}
511
-			} while (content.toLowerCase().indexOf(delimiter, min_index) === -1);
512
-			return content;
513
-		};
514
-
515
-		this.get_token = function() { //initial handler for token-retrieval
516
-			var token;
517
-
518
-			if (this.last_token === 'TK_TAG_SCRIPT' || this.last_token === 'TK_TAG_STYLE') { //check if we need to format javascript
519
-				var type = this.last_token.substr(7);
520
-				token = this.get_contents_to(type);
521
-				if (typeof token !== 'string') {
522
-					return token;
523
-				}
524
-				return [token, 'TK_' + type];
525
-			}
526
-			if (this.current_mode === 'CONTENT') {
527
-				token = this.get_content();
528
-				if (typeof token !== 'string') {
529
-					return token;
530
-				} else {
531
-					return [token, 'TK_CONTENT'];
532
-				}
533
-			}
534
-
535
-			if (this.current_mode === 'TAG') {
536
-				token = this.get_tag();
537
-				if (typeof token !== 'string') {
538
-					return token;
539
-				} else {
540
-					var tag_name_type = 'TK_TAG_' + this.tag_type;
541
-					return [token, tag_name_type];
542
-				}
543
-			}
544
-		};
545
-
546
-		this.get_full_indent = function(level) {
547
-			level = this.indent_level + level || 0;
548
-			if (level < 1) {
549
-				return '';
550
-			}
551
-
552
-			return Array(level + 1).join(this.indent_string);
553
-		};
554
-
555
-		this.is_unformatted = function(tag_check, unformatted) {
556
-			//is this an HTML5 block-level link?
557
-			if (!this.Utils.in_array(tag_check, unformatted)) {
558
-				return false;
559
-			}
560
-
561
-			if (tag_check.toLowerCase() !== 'a' || !this.Utils.in_array('a', unformatted)) {
562
-				return true;
563
-			}
564
-
565
-			//at this point we have an  tag; is its first child something we want to remain
566
-			//unformatted?
567
-			var next_tag = this.get_tag(true /* peek. */ );
568
-
569
-			// test next_tag to see if it is just html tag (no external content)
570
-			var tag = (next_tag || "").match(/^\s*<\s*\/?([a-z]*)\s*[^>]*>\s*$/);
571
-
572
-			// if next_tag comes back but is not an isolated tag, then
573
-			// let's treat the 'a' tag as having content
574
-			// and respect the unformatted option
575
-			if (!tag || this.Utils.in_array(tag, unformatted)) {
576
-				return true;
577
-			} else {
578
-				return false;
579
-			}
580
-		};
581
-
582
-		this.printer = function(js_source, indent_character, indent_size, wrap_line_length, brace_style) { //handles input/output and some other printing functions
583
-
584
-			this.input = js_source || ''; //gets the input for the Parser
585
-			this.output = [];
586
-			this.indent_character = indent_character;
587
-			this.indent_string = '';
588
-			this.indent_size = indent_size;
589
-			this.brace_style = brace_style;
590
-			this.indent_level = 0;
591
-			this.wrap_line_length = wrap_line_length;
592
-			this.line_char_count = 0; //count to see if wrap_line_length was exceeded
593
-
594
-			for (var i = 0; i < this.indent_size; i++) {
595
-				this.indent_string += this.indent_character;
596
-			}
597
-
598
-			this.print_newline = function(force, arr) {
599
-				this.line_char_count = 0;
600
-				if (!arr || !arr.length) {
601
-					return;
602
-				}
603
-				if (force || (arr[arr.length - 1] !== '\n')) { //we might want the extra line
604
-					arr.push('\n');
605
-				}
606
-			};
607
-
608
-			this.print_indentation = function(arr) {
609
-				for (var i = 0; i < this.indent_level; i++) {
610
-					arr.push(this.indent_string);
611
-					this.line_char_count += this.indent_string.length;
612
-				}
613
-			};
614
-
615
-			this.print_token = function(text) {
616
-				if (text || text !== '') {
617
-					if (this.output.length && this.output[this.output.length - 1] === '\n') {
618
-						this.print_indentation(this.output);
619
-						text = ltrim(text);
620
-					}
621
-				}
622
-				this.print_token_raw(text);
623
-			};
624
-
625
-			this.print_token_raw = function(text) {
626
-				if (text && text !== '') {
627
-					if (text.length > 1 && text[text.length - 1] === '\n') {
628
-						// unformatted tags can grab newlines as their last character
629
-						this.output.push(text.slice(0, -1));
630
-						this.print_newline(false, this.output);
631
-					} else {
632
-						this.output.push(text);
633
-					}
634
-				}
635
-
636
-				for (var n = 0; n < this.newlines; n++) {
637
-					this.print_newline(n > 0, this.output);
638
-				}
639
-				this.newlines = 0;
640
-			};
641
-
642
-			this.indent = function() {
643
-				this.indent_level++;
644
-			};
645
-
646
-			this.unindent = function() {
647
-				if (this.indent_level > 0) {
648
-					this.indent_level--;
649
-				}
650
-			};
651
-		};
652
-		return this;
653
-	}
654
-
655
-	/*_____________________--------------------_____________________*/
656
-
657
-	multi_parser = new Parser(); //wrapping functions Parser
658
-	multi_parser.printer(html_source, indent_character, indent_size, wrap_line_length, brace_style); //initialize starting values
659
-
660
-	while (true) {
661
-		var t = multi_parser.get_token();
662
-		multi_parser.token_text = t[0];
663
-		multi_parser.token_type = t[1];
664
-
665
-		if (multi_parser.token_type === 'TK_EOF') {
666
-			break;
667
-		}
668
-
669
-		switch (multi_parser.token_type) {
670
-			case 'TK_TAG_START':
671
-				multi_parser.print_newline(false, multi_parser.output);
672
-				multi_parser.print_token(multi_parser.token_text);
673
-				if (multi_parser.indent_content) {
674
-					multi_parser.indent();
675
-					multi_parser.indent_content = false;
676
-				}
677
-				multi_parser.current_mode = 'CONTENT';
678
-				break;
679
-			case 'TK_TAG_STYLE':
680
-			case 'TK_TAG_SCRIPT':
681
-				multi_parser.print_newline(false, multi_parser.output);
682
-				multi_parser.print_token(multi_parser.token_text);
683
-				multi_parser.current_mode = 'CONTENT';
684
-				break;
685
-			case 'TK_TAG_END':
686
-				//Print new line only if the tag has no content and has child
687
-				if (multi_parser.last_token === 'TK_CONTENT' && multi_parser.last_text === '') {
688
-					var tag_name = multi_parser.token_text.match(/\w+/)[0];
689
-					var tag_extracted_from_last_output = null;
690
-					if (multi_parser.output.length) {
691
-						tag_extracted_from_last_output = multi_parser.output[multi_parser.output.length - 1].match(/(?:<|{{#)\s*(\w+)/);
692
-					}
693
-					if (tag_extracted_from_last_output === null ||
694
-						tag_extracted_from_last_output[1] !== tag_name) {
695
-						multi_parser.print_newline(false, multi_parser.output);
696
-					}
697
-				}
698
-				multi_parser.print_token(multi_parser.token_text);
699
-				multi_parser.current_mode = 'CONTENT';
700
-				break;
701
-			case 'TK_TAG_SINGLE':
702
-				// Don't add a newline before elements that should remain unformatted.
703
-				var tag_check = multi_parser.token_text.match(/^\s*<([a-z]+)/i);
704
-				if (!tag_check || !multi_parser.Utils.in_array(tag_check[1], unformatted)) {
705
-					multi_parser.print_newline(false, multi_parser.output);
706
-				}
707
-				multi_parser.print_token(multi_parser.token_text);
708
-				multi_parser.current_mode = 'CONTENT';
709
-				break;
710
-			case 'TK_TAG_HANDLEBARS_ELSE':
711
-				multi_parser.print_token(multi_parser.token_text);
712
-				if (multi_parser.indent_content) {
713
-					multi_parser.indent();
714
-					multi_parser.indent_content = false;
715
-				}
716
-				multi_parser.current_mode = 'CONTENT';
717
-				break;
718
-			case 'TK_CONTENT':
719
-				multi_parser.print_token(multi_parser.token_text);
720
-				multi_parser.current_mode = 'TAG';
721
-				break;
722
-			case 'TK_STYLE':
723
-			case 'TK_SCRIPT':
724
-				if (multi_parser.token_text !== '') {
725
-					multi_parser.print_newline(false, multi_parser.output);
726
-					var text = multi_parser.token_text,
727
-						_beautifier,
728
-						script_indent_level = 1;
729
-					if (multi_parser.token_type === 'TK_SCRIPT') {
730
-						_beautifier = typeof js_beautify === 'function' && js_beautify;
731
-					} else if (multi_parser.token_type === 'TK_STYLE') {
732
-						_beautifier = typeof css_beautify === 'function' && css_beautify;
733
-					}
734
-
735
-					if (options.indent_scripts === "keep") {
736
-						script_indent_level = 0;
737
-					} else if (options.indent_scripts === "separate") {
738
-						script_indent_level = -multi_parser.indent_level;
739
-					}
740
-
741
-					var indentation = multi_parser.get_full_indent(script_indent_level);
742
-					if (_beautifier) {
743
-						// call the Beautifier if avaliable
744
-						text = _beautifier(text.replace(/^\s*/, indentation), options);
745
-					} else {
746
-						// simply indent the string otherwise
747
-						var white = text.match(/^\s*/)[0];
748
-						var _level = white.match(/[^\n\r]*$/)[0].split(multi_parser.indent_string).length - 1;
749
-						var reindent = multi_parser.get_full_indent(script_indent_level - _level);
750
-						text = text.replace(/^\s*/, indentation)
751
-							.replace(/\r\n|\r|\n/g, '\n' + reindent)
752
-							.replace(/\s+$/, '');
753
-					}
754
-					if (text) {
755
-						multi_parser.print_token_raw(indentation + trim(text));
756
-						multi_parser.print_newline(false, multi_parser.output);
757
-					}
758
-				}
759
-				multi_parser.current_mode = 'TAG';
760
-				break;
761
-		}
762
-		multi_parser.last_token = multi_parser.token_type;
763
-		multi_parser.last_text = multi_parser.token_text;
764
-	}
765
-	return multi_parser.output.join('');
766
-}

+ 0
- 774
src/ZSSRichTextEditor/ZSSRichTextEditor.js 查看文件

@@ -1,774 +0,0 @@
1
-/*!
2
- *
3
- * ZSSRichTextEditor v0.5.2
4
- * http://www.zedsaid.com
5
- *
6
- * Copyright 2014 Zed Said Studio LLC
7
- *
8
- */
9
-
10
-var zss_editor = {};
11
-
12
-// If we are using iOS or desktop
13
-zss_editor.isUsingiOS = true;
14
-
15
-// If the user is draging
16
-zss_editor.isDragging = false;
17
-
18
-// The current selection
19
-zss_editor.currentSelection;
20
-
21
-// The current editing image
22
-zss_editor.currentEditingImage;
23
-
24
-// The current editing link
25
-zss_editor.currentEditingLink;
26
-
27
-// The objects that are enabled
28
-zss_editor.enabledItems = {};
29
-
30
-// Height of content window, will be set by viewController
31
-zss_editor.contentHeight = 244;
32
-
33
-// Sets to true when extra footer gap shows and requires to hide
34
-zss_editor.updateScrollOffset = false;
35
-
36
-/**
37
- * The initializer function that must be called onLoad
38
- */
39
-
40
-function setupTouchEndEnableEditing(editorId) {
41
-    $(`#${editorId}`).on('touchend', function(e) {
42
-        zss_editor.enabledEditingItems(e);
43
-        var clicked = $(e.target);
44
-        if (!clicked.hasClass('zs_active')) {
45
-            $('img').removeClass('zs_active');
46
-        }
47
-    });
48
-}
49
-
50
-function setupSelectionChange(editorId) {
51
-    $(document).on('selectionchange',function(e){
52
-        zss_editor.calculateEditorHeightWithCaretPosition(editorId);
53
-        zss_editor.setScrollPosition();
54
-        zss_editor.enabledEditingItems(e);
55
-    });
56
-}
57
-
58
-function setupTouchEndFocus(editorId) {
59
-    $(window).on('touchend', function(e) {
60
-        if (!zss_editor.isDragging && (e.target.id == "zss_editor_footer"||e.target.nodeName.toLowerCase() == "html")) {
61
-            zss_editor.focusEditor(editorId);
62
-        }
63
-    });
64
-}
65
-
66
-function disableLineBreakIfNecessary(editorId) {
67
-    var editor = $(`#${editorId}`);
68
-    var disableLineBreaks = editor.attr("disableLineBreaks");
69
-    if (disableLineBreaks) {
70
-        editor.keypress(function(e){ return e.which != 13; });
71
-    }
72
-}
73
-
74
-zss_editor.init = function() {
75
-
76
-    disableLineBreakIfNecessary('zss_editor_title');
77
-    disableLineBreakIfNecessary('zss_editor_content');
78
-
79
-    setupTouchEndEnableEditing('zss_editor_title');
80
-    setupTouchEndEnableEditing('zss_editor_content');
81
-
82
-    setupSelectionChange('zss_editor_title');
83
-    setupSelectionChange('zss_editor_content');
84
-
85
-    $(window).on('scroll', function(e) {
86
-                 zss_editor.updateOffset();
87
-                 });
88
-    
89
-    // Make sure that when we tap anywhere in the document we focus on the editor
90
-    $(window).on('touchmove', function(e) {
91
-                 zss_editor.isDragging = true;
92
-                 zss_editor.updateScrollOffset = true;
93
-                 zss_editor.setScrollPosition();
94
-                 zss_editor.enabledEditingItems(e);
95
-                 });
96
-    $(window).on('touchstart', function(e) {
97
-                 zss_editor.isDragging = false;
98
-                 });
99
-
100
-    setupTouchEndFocus('zss_editor_title');
101
-    setupTouchEndFocus('zss_editor_content');
102
-
103
-    setTimeout(function() {
104
-        WebViewBridge.send(JSON.stringify({type: 'ZSS_INITIALIZED'}))
105
-    }, 20);
106
-    
107
-}//end
108
-
109
-zss_editor.updateOffset = function() {
110
-    
111
-    if (!zss_editor.updateScrollOffset)
112
-        return;
113
-    
114
-    var offsetY = window.document.body.scrollTop;
115
-    
116
-    var footer = $('#zss_editor_footer');
117
-    
118
-    var maxOffsetY = footer.offset().top - zss_editor.contentHeight;
119
-    
120
-    if (maxOffsetY < 0)
121
-        maxOffsetY = 0;
122
-    
123
-    if (offsetY > maxOffsetY)
124
-    {
125
-        window.scrollTo(0, maxOffsetY);
126
-    }
127
-    
128
-    zss_editor.setScrollPosition();
129
-}
130
-
131
-// This will show up in the XCode console as we are able to push this into an NSLog.
132
-zss_editor.debug = function(msg) {
133
-    WebViewBridge.send(JSON.stringify({type: 'LOG', data: msg}));
134
-}
135
-
136
-
137
-zss_editor.setScrollPosition = function() {
138
-    var position = window.pageYOffset;
139
-    WebViewBridge.send(JSON.stringify({type: 'SCROLL', data: position}));
140
-}
141
-
142
-function setPlaceholder(editorId, placeholder) {
143
-    var editor = $(`#${editorId}`);
144
-    
145
-    //set placeHolder
146
-    editor.attr("placeholder",placeholder);
147
-	
148
-    //set focus			 
149
-    editor.focusout(function(){
150
-        var element = $(this);
151
-        if (!element.text().trim().length) {
152
-            element.empty();
153
-        }
154
-    });
155
-}
156
-
157
-zss_editor.setTitlePlaceholder = function(placeholder) {
158
-    setPlaceholder('zss_editor_title', placeholder);
159
-}
160
-
161
-zss_editor.setContentPlaceholder = function(placeholder) {
162
-    setPlaceholder('zss_editor_content', placeholder);
163
-}
164
-
165
-zss_editor.setFooterHeight = function(footerHeight) {
166
-    var footer = $('#zss_editor_footer');
167
-    footer.height(footerHeight + 'px');
168
-}
169
-
170
-zss_editor.getCaretYPosition = function() {
171
-    var sel = window.getSelection();
172
-    // Next line is comented to prevent deselecting selection. It looks like work but if there are any issues will appear then uconmment it as well as code above.
173
-    //sel.collapseToStart();
174
-    var range = sel.getRangeAt(0);
175
-    var span = document.createElement('span');// something happening here preventing selection of elements
176
-    range.collapse(false);
177
-    range.insertNode(span);
178
-    var topPosition = span.offsetTop;
179
-    span.parentNode.removeChild(span);
180
-    return topPosition;
181
-}
182
-
183
-zss_editor.calculateEditorHeightWithCaretPosition = function(editorId) {
184
-    
185
-    var padding = 50;
186
-    var c = zss_editor.getCaretYPosition();
187
-    var e = document.getElementById(editorId);
188
-    
189
-    var editor = $(`#${editorId}`);
190
-    
191
-    var offsetY = window.document.body.scrollTop;
192
-    var height = zss_editor.contentHeight;
193
-    
194
-    var newPos = window.pageYOffset;
195
-    
196
-    if (c < offsetY) {
197
-        newPos = c;
198
-    } else if (c > (offsetY + height - padding)) {
199
-        newPos = c - height + padding - 18;
200
-    }
201
-    
202
-    window.scrollTo(0, newPos);
203
-}
204
-
205
-zss_editor.backuprange = function(){
206
-    var selection = window.getSelection();
207
-    var range = selection.getRangeAt(0);
208
-    zss_editor.currentSelection = {"startContainer": range.startContainer, "startOffset":range.startOffset,"endContainer":range.endContainer, "endOffset":range.endOffset};
209
-}
210
-
211
-zss_editor.restorerange = function(){
212
-    var selection = window.getSelection();
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);
218
-}
219
-
220
-zss_editor.getSelectedNode = function() {
221
-    var node,selection;
222
-    if (window.getSelection) {
223
-        selection = getSelection();
224
-        node = selection.anchorNode;
225
-    }
226
-    if (!node && document.selection) {
227
-        selection = document.selection
228
-        var range = selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange();
229
-        node = range.commonAncestorContainer ? range.commonAncestorContainer :
230
-        range.parentElement ? range.parentElement() : range.item(0);
231
-    }
232
-    if (node) {
233
-        return (node.nodeName == "#text" ? node.parentNode : node);
234
-    }
235
-};
236
-
237
-zss_editor.setBold = function() {
238
-    document.execCommand('bold', false, null);
239
-    zss_editor.enabledEditingItems();
240
-}
241
-
242
-zss_editor.setItalic = function() {
243
-    document.execCommand('italic', false, null);
244
-    zss_editor.enabledEditingItems();
245
-}
246
-
247
-zss_editor.setSubscript = function() {
248
-    document.execCommand('subscript', false, null);
249
-    zss_editor.enabledEditingItems();
250
-}
251
-
252
-zss_editor.setSuperscript = function() {
253
-    document.execCommand('superscript', false, null);
254
-    zss_editor.enabledEditingItems();
255
-}
256
-
257
-zss_editor.setStrikeThrough = function() {
258
-    document.execCommand('strikeThrough', false, null);
259
-    zss_editor.enabledEditingItems();
260
-}
261
-
262
-zss_editor.setUnderline = function() {
263
-    document.execCommand('underline', false, null);
264
-    zss_editor.enabledEditingItems();
265
-}
266
-
267
-zss_editor.setBlockquote = function() {
268
-    document.execCommand('formatBlock', false, '<blockquote>');
269
-    zss_editor.enabledEditingItems();
270
-}
271
-
272
-zss_editor.removeFormating = function() {
273
-    document.execCommand('removeFormat', false, null);
274
-    zss_editor.enabledEditingItems();
275
-}
276
-
277
-zss_editor.setHorizontalRule = function() {
278
-    document.execCommand('insertHorizontalRule', false, null);
279
-    zss_editor.enabledEditingItems();
280
-}
281
-
282
-zss_editor.setHeading = function(heading) {
283
-    var current_selection = $(zss_editor.getSelectedNode());
284
-    var t = current_selection.prop("tagName").toLowerCase();
285
-    var is_heading = (t == 'h1' || t == 'h2' || t == 'h3' || t == 'h4' || t == 'h5' || t == 'h6');
286
-    if (is_heading && heading == t) {
287
-        //var c = current_selection.html();
288
-        //current_selection.replaceWith(c);
289
-    } else {
290
-        document.execCommand('formatBlock', false, '<'+heading+'>');
291
-    }
292
-    
293
-    zss_editor.enabledEditingItems();
294
-}
295
-
296
-zss_editor.setParagraph = function() {
297
-    var current_selection = $(zss_editor.getSelectedNode());
298
-    var t = current_selection.prop("tagName").toLowerCase();
299
-    var is_paragraph = (t == 'p');
300
-    if (is_paragraph) {
301
-        var c = current_selection.html();
302
-        current_selection.replaceWith(c);
303
-    } else {
304
-        document.execCommand('formatBlock', false, '<p>');
305
-    }
306
-    
307
-    zss_editor.enabledEditingItems();
308
-}
309
-
310
-// Need way to remove formatBlock
311
-console.log('WARNING: We need a way to remove formatBlock items');
312
-
313
-zss_editor.undo = function() {
314
-    document.execCommand('undo', false, null);
315
-    zss_editor.enabledEditingItems();
316
-}
317
-
318
-zss_editor.redo = function() {
319
-    document.execCommand('redo', false, null);
320
-    zss_editor.enabledEditingItems();
321
-}
322
-
323
-zss_editor.setOrderedList = function() {
324
-    document.execCommand('insertOrderedList', false, null);
325
-    zss_editor.enabledEditingItems();
326
-}
327
-
328
-zss_editor.setUnorderedList = function() {
329
-    document.execCommand('insertUnorderedList', false, null);
330
-    zss_editor.enabledEditingItems();
331
-}
332
-
333
-zss_editor.setJustifyCenter = function() {
334
-    document.execCommand('justifyCenter', false, null);
335
-    zss_editor.enabledEditingItems();
336
-}
337
-
338
-zss_editor.setJustifyFull = function() {
339
-    document.execCommand('justifyFull', false, null);
340
-    zss_editor.enabledEditingItems();
341
-}
342
-
343
-zss_editor.setJustifyLeft = function() {
344
-    document.execCommand('justifyLeft', false, null);
345
-    zss_editor.enabledEditingItems();
346
-}
347
-
348
-zss_editor.setJustifyRight = function() {
349
-    document.execCommand('justifyRight', false, null);
350
-    zss_editor.enabledEditingItems();
351
-}
352
-
353
-zss_editor.setIndent = function() {
354
-    document.execCommand('indent', false, null);
355
-    zss_editor.enabledEditingItems();
356
-}
357
-
358
-zss_editor.setOutdent = function() {
359
-    document.execCommand('outdent', false, null);
360
-    zss_editor.enabledEditingItems();
361
-}
362
-
363
-zss_editor.setFontFamily = function(fontFamily) {
364
-
365
-	zss_editor.restorerange();
366
-	document.execCommand("styleWithCSS", null, true);
367
-	document.execCommand("fontName", false, fontFamily);
368
-	document.execCommand("styleWithCSS", null, false);
369
-	zss_editor.enabledEditingItems();
370
-		
371
-}
372
-
373
-zss_editor.setTextColor = function(color) {
374
-
375
-    if(zss_editor.currentSelection) {
376
-        zss_editor.restorerange();
377
-    }
378
-    document.execCommand("styleWithCSS", null, true);
379
-    document.execCommand('foreColor', false, color);
380
-    document.execCommand("styleWithCSS", null, false);
381
-    zss_editor.enabledEditingItems();
382
-    // document.execCommand("removeFormat", false, "foreColor"); // Removes just foreColor
383
-	
384
-}
385
-
386
-zss_editor.setBackgroundColor = function(color) {
387
-
388
-    if(zss_editor.currentSelection) {
389
-        zss_editor.restorerange();
390
-    }
391
-    document.execCommand("styleWithCSS", null, true);
392
-    document.execCommand('hiliteColor', false, color);
393
-    document.execCommand("styleWithCSS", null, false);
394
-    zss_editor.enabledEditingItems();
395
-}
396
-
397
-// Needs addClass method
398
-
399
-zss_editor.insertLink = function(url, title) {
400
-
401
-    zss_editor.restorerange();
402
-    var sel = document.getSelection();
403
-    console.log(sel);
404
-    if (sel.toString().length != 0) {
405
-        if (sel.rangeCount) {
406
-            
407
-            var el = document.createElement("a");
408
-            el.setAttribute("href", url);
409
-            el.setAttribute("title", title);
410
-            
411
-            var range = sel.getRangeAt(0).cloneRange();
412
-            range.surroundContents(el);
413
-            sel.removeAllRanges();
414
-            sel.addRange(range);
415
-        }
416
-    }
417
-    else
418
-    {
419
-        document.execCommand("insertHTML",false,"<a href='"+url+"'>"+title+"</a>");
420
-    }
421
-    
422
-    zss_editor.enabledEditingItems();
423
-}
424
-
425
-zss_editor.updateLink = function(url, title) {
426
-    
427
-    zss_editor.restorerange();
428
-    
429
-    if (zss_editor.currentEditingLink) {
430
-        var c = zss_editor.currentEditingLink;
431
-        c.attr('href', url);
432
-        c.attr('title', title);
433
-    }
434
-    zss_editor.enabledEditingItems();
435
-    
436
-}//end
437
-
438
-zss_editor.updateImage = function(url, alt) {
439
-    
440
-    zss_editor.restorerange();
441
-    
442
-    if (zss_editor.currentEditingImage) {
443
-        var c = zss_editor.currentEditingImage;
444
-        c.attr('src', url);
445
-        c.attr('alt', alt);
446
-    }
447
-    zss_editor.enabledEditingItems();
448
-    
449
-}//end
450
-
451
-zss_editor.updateImageBase64String = function(imageBase64String, alt) {
452
-    
453
-    zss_editor.restorerange();
454
-    
455
-    if (zss_editor.currentEditingImage) {
456
-        var c = zss_editor.currentEditingImage;
457
-        var src = 'data:image/jpeg;base64,' + imageBase64String;
458
-        c.attr('src', src);
459
-        c.attr('alt', alt);
460
-    }
461
-    zss_editor.enabledEditingItems();
462
-    
463
-}//end
464
-
465
-
466
-zss_editor.unlink = function() {
467
-    
468
-    if (zss_editor.currentEditingLink) {
469
-        var c = zss_editor.currentEditingLink;
470
-        c.contents().unwrap();
471
-    }
472
-    zss_editor.enabledEditingItems();
473
-}
474
-
475
-zss_editor.quickLink = function() {
476
-    
477
-    var sel = document.getSelection();
478
-    var link_url = "";
479
-    var test = new String(sel);
480
-    var mailregexp = new RegExp("^(.+)(\@)(.+)$", "gi");
481
-    if (test.search(mailregexp) == -1) {
482
-        checkhttplink = new RegExp("^http\:\/\/", "gi");
483
-        if (test.search(checkhttplink) == -1) {
484
-            checkanchorlink = new RegExp("^\#", "gi");
485
-            if (test.search(checkanchorlink) == -1) {
486
-                link_url = "http://" + sel;
487
-            } else {
488
-                link_url = sel;
489
-            }
490
-        } else {
491
-            link_url = sel;
492
-        }
493
-    } else {
494
-        checkmaillink = new RegExp("^mailto\:", "gi");
495
-        if (test.search(checkmaillink) == -1) {
496
-            link_url = "mailto:" + sel;
497
-        } else {
498
-            link_url = sel;
499
-        }
500
-    }
501
-    
502
-    var html_code = '<a href="' + link_url + '">' + sel + '</a>';
503
-    zss_editor.insertHTML(html_code);
504
-    
505
-}
506
-
507
-zss_editor.prepareInsert = function() {
508
-    zss_editor.backuprange();
509
-}
510
-
511
-zss_editor.insertImage = function(url, alt) {
512
-    zss_editor.restorerange();
513
-    var html = '<img src="'+url+'" alt="'+alt+'" />';
514
-    zss_editor.insertHTML(html);
515
-    zss_editor.enabledEditingItems();
516
-}
517
-
518
-zss_editor.insertImageBase64String = function(imageBase64String, alt) {
519
-    zss_editor.restorerange();
520
-    var html = '<img src="data:image/jpeg;base64,'+imageBase64String+'" alt="'+alt+'" />';
521
-    zss_editor.insertHTML(html);
522
-    zss_editor.enabledEditingItems();
523
-}
524
-
525
-function setHTML(editorId, html) {
526
-    var editor = $(`#${editorId}`);
527
-    editor.html(html);
528
-}
529
-
530
-zss_editor.setTitleHTML = function(html) {
531
-    setHTML('zss_editor_title', html);
532
-}
533
-
534
-zss_editor.setContentHTML = function(html) {
535
-    setHTML('zss_editor_content', html);
536
-}
537
-
538
-zss_editor.insertHTML = function(html) {
539
-    document.execCommand('insertHTML', false, html);
540
-    zss_editor.enabledEditingItems();
541
-}
542
-
543
-function getHtml(editorId) {
544
-    // Images
545
-    var img = $('img');
546
-    if (img.length != 0) {
547
-        $('img').removeClass('zs_active');
548
-        $('img').each(function(index, e) {
549
-            var image = $(this);
550
-            var zs_class = image.attr('class');
551
-            if (typeof(zs_class) != "undefined") {
552
-                if (zs_class == '') {
553
-                    image.removeAttr('class');
554
-                }
555
-            }
556
-        });
557
-    }
558
-
559
-    // Blockquote
560
-    var bq = $('blockquote');
561
-    if (bq.length != 0) {
562
-        bq.each(function() {
563
-            var b = $(this);
564
-            if (b.css('border').indexOf('none') != -1) {
565
-                b.css({'border': ''});
566
-            }
567
-            if (b.css('padding').indexOf('0px') != -1) {
568
-                b.css({'padding': ''});
569
-            }
570
-        });
571
-    }
572
-
573
-    // Get the contents
574
-    var h = document.getElementById(editorId).innerHTML;
575
-
576
-    return h;
577
-}
578
-
579
-zss_editor.getTitleHTML = function() {
580
-    return getHtml("zss_editor_title");
581
-}
582
-
583
-zss_editor.getContentHTML = function() {
584
-    return getHtml("zss_editor_content");
585
-}
586
-
587
-zss_editor.getTitleText = function() {
588
-    return $('#zss_editor_title').text();
589
-}
590
-
591
-zss_editor.getContentText = function() {
592
-    return $('#zss_editor_content').text();
593
-}
594
-
595
-zss_editor.isCommandEnabled = function(commandName) {
596
-    return document.queryCommandState(commandName);
597
-}
598
-
599
-zss_editor.enabledEditingItems = function(e) {
600
-    
601
-    console.log('enabledEditingItems');
602
-    var items = [];
603
-    if (zss_editor.isCommandEnabled('bold')) {
604
-        items.push('bold');
605
-    }
606
-    if (zss_editor.isCommandEnabled('italic')) {
607
-        items.push('italic');
608
-    }
609
-    if (zss_editor.isCommandEnabled('subscript')) {
610
-        items.push('subscript');
611
-    }
612
-    if (zss_editor.isCommandEnabled('superscript')) {
613
-        items.push('superscript');
614
-    }
615
-    if (zss_editor.isCommandEnabled('strikeThrough')) {
616
-        items.push('strikeThrough');
617
-    }
618
-    if (zss_editor.isCommandEnabled('underline')) {
619
-        items.push('underline');
620
-    }
621
-    if (zss_editor.isCommandEnabled('insertOrderedList')) {
622
-        items.push('orderedList');
623
-    }
624
-    if (zss_editor.isCommandEnabled('insertUnorderedList')) {
625
-        items.push('unorderedList');
626
-    }
627
-    if (zss_editor.isCommandEnabled('justifyCenter')) {
628
-        items.push('justifyCenter');
629
-    }
630
-    if (zss_editor.isCommandEnabled('justifyFull')) {
631
-        items.push('justifyFull');
632
-    }
633
-    if (zss_editor.isCommandEnabled('justifyLeft')) {
634
-        items.push('justifyLeft');
635
-    }
636
-    if (zss_editor.isCommandEnabled('justifyRight')) {
637
-        items.push('justifyRight');
638
-    }
639
-    if (zss_editor.isCommandEnabled('insertHorizontalRule')) {
640
-        items.push('horizontalRule');
641
-    }
642
-    var formatBlock = document.queryCommandValue('formatBlock');
643
-    if (formatBlock.length > 0) {
644
-        items.push(formatBlock);
645
-    }
646
-    // Images
647
-    $('img').bind('touchstart', function(e) {
648
-                  $('img').removeClass('zs_active');
649
-                  $(this).addClass('zs_active');
650
-                  });
651
-    
652
-    // Use jQuery to figure out those that are not supported
653
-    if (typeof(e) != "undefined") {
654
-        
655
-        // The target element
656
-        var s = zss_editor.getSelectedNode();
657
-        var t = $(s);
658
-        var nodeName = e.target.nodeName.toLowerCase();
659
-        
660
-        // Background Color
661
-        var bgColor = t.css('backgroundColor');
662
-        if (bgColor.length != 0 && bgColor != 'rgba(0, 0, 0, 0)' && bgColor != 'rgb(0, 0, 0)' && bgColor != 'transparent') {
663
-            items.push('backgroundColor');
664
-        }
665
-        // Text Color
666
-        var textColor = t.css('color');
667
-        if (textColor.length != 0 && textColor != 'rgba(0, 0, 0, 0)' && textColor != 'rgb(0, 0, 0)' && textColor != 'transparent') {
668
-            items.push('textColor');
669
-        }
670
-		
671
-		//Fonts
672
-		var font = t.css('font-family');
673
-		if (font.length != 0 && font != 'Arial, Helvetica, sans-serif') {
674
-			items.push('fonts');	
675
-		}
676
-		
677
-        // Link
678
-        if (nodeName == 'a') {
679
-            zss_editor.currentEditingLink = t;
680
-            var title = t.attr('title');
681
-            items.push('link:'+t.attr('href'));
682
-            if (t.attr('title') !== undefined) {
683
-                items.push('link-title:'+t.attr('title'));
684
-            }
685
-            
686
-        } else {
687
-            zss_editor.currentEditingLink = null;
688
-        }
689
-        // Blockquote
690
-        if (nodeName == 'blockquote') {
691
-            items.push('indent');
692
-        }
693
-        // Image
694
-        if (nodeName == 'img') {
695
-            zss_editor.currentEditingImage = t;
696
-            items.push('image:'+t.attr('src'));
697
-            if (t.attr('alt') !== undefined) {
698
-                items.push('image-alt:'+t.attr('alt'));
699
-            }
700
-            
701
-        } else {
702
-            zss_editor.currentEditingImage = null;
703
-        }
704
-        
705
-    }
706
-
707
-    WebViewBridge.send(JSON.stringify({type: 'SELECTION_CHANGE', data: {items}}))
708
-}
709
-
710
-zss_editor.focusContent = function() {
711
-    $('#zss_editor_content').focus();
712
-}
713
-
714
-zss_editor.focusTitle = function() {
715
-    $('#zss_editor_title').focus();
716
-}
717
-
718
-zss_editor.focusEditor = function(editorId) {
719
-    
720
-    // the following was taken from http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity/3866442#3866442
721
-    // and ensures we move the cursor to the end of the editor
722
-    var editor = $(`#${editorId}`);
723
-    var range = document.createRange();
724
-    range.selectNodeContents(editor.get(0));
725
-    range.collapse(false);
726
-    var selection = window.getSelection();
727
-    selection.removeAllRanges();
728
-    selection.addRange(range);
729
-    editor.focus();
730
-}
731
-
732
-
733
-zss_editor.blurTitleEditor = function() {
734
-    $('#zss_editor_title').blur();
735
-}
736
-
737
-zss_editor.blurContentEditor = function() {
738
-    $('#zss_editor_content').blur();
739
-}
740
-
741
-zss_editor.setCustomCSS = function(customCSS) {
742
-    
743
-    document.getElementsByTagName('style')[0].innerHTML=customCSS;
744
-    
745
-    //set focus
746
-    /*editor.focusout(function(){
747
-                    var element = $(this);
748
-                    if (!element.text().trim().length) {
749
-                    element.empty();
750
-                    }
751
-                    });*/
752
-    
753
-    
754
-    
755
-}
756
-
757
-function addFocusEvent(editorId, callbackHandler) {
758
-    var editor = $(`#${editorId}`);
759
-    editor.focus(callbackHandler);
760
-}
761
-
762
-zss_editor.setTitleFocusHandler = function() {
763
-    addFocusEvent('zss_editor_title', function() {
764
-        WebViewBridge.send(JSON.stringify({type: 'TITLE_FOCUSED'}))
765
-    });
766
-}
767
-
768
-zss_editor.setContentFocusHandler = function() {
769
-    addFocusEvent('zss_editor_content', function() {
770
-        WebViewBridge.send(JSON.stringify({type: 'CONTENT_FOCUSED'}))
771
-    });
772
-}
773
-
774
-//end

+ 0
- 4
src/ZSSRichTextEditor/jQuery.js
文件差异内容过多而无法显示
查看文件


+ 0
- 87
src/ZSSRichTextEditor/style.css 查看文件

@@ -1,87 +0,0 @@
1
-/* Default ZSSRichTextEditor Styling */
2
-* {
3
-    outline: 0px solid transparent;
4
-    -webkit-tap-highlight-color: rgba(0,0,0,0);
5
-    -webkit-touch-callout: none;
6
-}
7
-
8
-html, body {
9
-    padding: 0;
10
-    margin: 0;
11
-    font-family: Arial, Helvetica, sans-serif;
12
-    font-size:1em;
13
-    color:#2d4150;
14
-}
15
-
16
-body {
17
-    padding-left:10px;
18
-    padding-right:10px;
19
-    padding-top: 0px;
20
-    padding-bottom: 0px;
21
-    overflow-y: scroll;
22
-    -webkit-overflow-scrolling: touch;
23
-    height: 100%;
24
-}
25
-
26
-img.zs_active {
27
-    /*border: 2px dashed #000;*/
28
-}
29
-
30
-img {
31
-    width: 98%;
32
-    margin-left:auto;
33
-    margin-right:auto;
34
-}
35
-
36
-audio {
37
-    padding: 20px 0;
38
-}
39
-
40
-div.zss_editor_content {
41
-    font-family: Arial, Helvetica, sans-serif;
42
-    color: #000;
43
-    width: 100%;
44
-    height: 100%;
45
-    -webkit-overflow-scrolling: touch;
46
-    overflow:auto;
47
-
48
-}
49
-
50
-#zss_editor_content {
51
-    padding-left: 10px;
52
-    padding-right: 10px;
53
-}
54
-
55
-div.zss_editor_title {
56
-    font-family: 'Helvetica Neue Light', sans-serif;
57
-    font-size: 23px;
58
-    line-height: 31px;
59
-    color: #2d4150;
60
-}
61
-
62
-#zss_editor_title {
63
-    padding-left: 10px;
64
-    padding-right: 10px;
65
-}
66
-
67
-[placeholder]:empty:before {
68
-    content: attr(placeholder);
69
-    color: #e0e0e0;
70
-}
71
-
72
-[placeholder]:empty:focus:before {
73
-    content: attr(placeholder);
74
-    color: #e0e0e0;
75
-}
76
-
77
-hr {
78
-    border: none;
79
-    height: 1px;
80
-    background-color: #e7e7e7;
81
-}
82
-
83
-#separatorContainer {
84
-    -webkit-user-select: none;
85
-    padding-left: 10px;
86
-    padding-right: 10px;
87
-}

+ 1639
- 11
src/editor.html
文件差异内容过多而无法显示
查看文件