diff --git a/package.json b/package.json
index 9ec89f52..b808c271 100644
--- a/package.json
+++ b/package.json
@@ -2,17 +2,17 @@
"name": "react-native-zss-rich-text-editor",
"repository": {
"type": "git",
- "url": "https://github.com/wix/react-native-zss-rich-text-editor.git"
+ "url": "https://github.com/HoneyBook/react-native-zss-rich-text-editor.git"
},
- "version": "1.1.0",
+ "version": "1.2.10",
"description": "React Native Wrapper for ZSSRichTextEditor",
"main": "index.js",
"license": "SEE LICENSE IN LICENSE",
"dependencies": {
- "react-native-webview-bridge-updated": "^1.0.0"
+ "react-native-webview-bridge": "github:HoneyBook/react-native-webview-bridge.git"
},
"peerDependencies": {
"react": "*",
- "react-native": ">=0.31.0"
+ "react-native": "0.66.4"
}
}
diff --git a/src/RichTextEditor.js b/src/RichTextEditor.js
index 51e212ef..9da58bb0 100644
--- a/src/RichTextEditor.js
+++ b/src/RichTextEditor.js
@@ -1,9 +1,9 @@
-import React, {Component} from 'react';
-import PropTypes from 'prop-types';
-import WebViewBridge from 'react-native-webview-bridge-updated';
-import {InjectedMessageHandler} from './WebviewMessageHandler';
-import {actions, messages} from './const';
-import {Modal, View, Text, StyleSheet, TextInput, TouchableOpacity, Platform, PixelRatio, Keyboard, Dimensions} from 'react-native';
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import WebViewBridge from "react-native-webview-bridge";
+import { InjectedMessageHandler } from "./WebviewMessageHandler";
+import { actions, messages } from "./const";
+import { Dimensions, Keyboard, Platform, View } from "react-native";
const injectScript = `
(function () {
@@ -42,16 +42,18 @@ export default class RichTextEditor extends Component {
this.state = {
selectionChangeListeners: [],
onChange: [],
- showLinkDialog: false,
linkInitialUrl: '',
linkTitle: '',
linkUrl: '',
keyboardHeight: 0
};
this._selectedTextChangeListeners = [];
+ this.inputFieldResolves = {};
+ this.inputFieldRejects = {};
+ this.inputFieldTimers = {};
}
- componentWillMount() {
+ componentDidMount() {
if(PlatformIOS) {
this.keyboardEventListeners = [
Keyboard.addListener('keyboardWillShow', this._onKeyboardWillShow),
@@ -66,7 +68,9 @@ export default class RichTextEditor extends Component {
}
componentWillUnmount() {
- this.keyboardEventListeners.forEach((eventListener) => eventListener.remove());
+ if (this.keyboardEventListeners) {
+ this.keyboardEventListeners.forEach((eventListener) => eventListener.remove());
+ }
}
_onKeyboardWillShow(event) {
@@ -89,9 +93,12 @@ export default class RichTextEditor extends Component {
const {top = 0, bottom = 0} = this.props.contentInset;
const {marginTop = 0, marginBottom = 0} = this.props.style;
const spacing = marginTop + marginBottom + top + bottom;
+ const zibi = Dimensions.get('window').height- spacing -keyboardHeight
- const editorAvailableHeight = Dimensions.get('window').height - keyboardHeight - spacing;
- this.setEditorHeight(editorAvailableHeight);
+ const editorAvailableHeight = Dimensions.get('window').height - keyboardHeight*2 - spacing;
+ console.log('xzx original', editorAvailableHeight)
+ console.log('xzx elad ', zibi)
+ // this.setEditorHeight(zibi);
}
onBridgeMessage(str){
@@ -132,6 +139,17 @@ export default class RichTextEditor extends Component {
}
}
break;
+ case messages.INPUT_FIELD_TEXT_RESPONSE:
+ let key = message.key;
+ if (this.inputFieldResolves[key]) {
+ this.inputFieldResolves[key](message.data);
+ this.inputFieldRejects[key] = undefined;
+ if (this.inputFieldTimers[key]) {
+ clearTimeout(this.inputFieldTimers[key]);
+ this.inputFieldTimers[key] = undefined;
+ }
+ }
+ break;
case messages.SELECTED_TEXT_RESPONSE:
if (this.selectedTextResolve) {
this.selectedTextResolve(message.data);
@@ -148,6 +166,7 @@ export default class RichTextEditor extends Component {
this.setCustomCSS(this.props.customCSS);
}
this.setTitlePlaceholder(this.props.titlePlaceholder);
+ this.setInputFields(this.props.inputFields);
this.setContentPlaceholder(this.props.contentPlaceholder);
this.setTitleHTML(this.props.initialTitleHTML);
this.setContentHTML(this.props.initialContentHTML);
@@ -157,6 +176,12 @@ export default class RichTextEditor extends Component {
this.props.editorInitializedCallback && this.props.editorInitializedCallback();
+ break;
+ case messages.TOP_REACHED:
+ this.thresholdHandler && this.thresholdHandler({top:true})
+ break;
+ case messages.BOTTOM_REACHED:
+ this.thresholdHandler && this.thresholdHandler({bottom:true})
break;
case messages.LINK_TOUCHED:
this.prepareInsert();
@@ -175,6 +200,11 @@ export default class RichTextEditor extends Component {
case messages.CONTENT_FOCUSED:
this.contentFocusHandler && this.contentFocusHandler();
break;
+ case messages.INPUT_FIELD_FOCUSED:
+ let specialKey = message.data;
+ let focusFieldName = 'inputFieldFocusHandler_' + specialKey;
+ this[focusFieldName] && this[focusFieldName]();
+ break;
case messages.SELECTION_CHANGE: {
const items = message.data.items;
this.state.selectionChangeListeners.map((listener) => {
@@ -188,156 +218,110 @@ export default class RichTextEditor extends Component {
break;
}
case messages.SELECTED_TEXT_CHANGED: {
+
const selectedText = message.data;
+
this._selectedTextChangeListeners.forEach((listener) => {
+
listener(selectedText);
});
break;
}
+ case messages.ADD_RECIPIENT:{
+ this.props.addRecipient && this.props.addRecipient();
+ break;
+ }
+ case messages.CANCEL_SCHEDULE_SEND:{
+ this.props.cancelScheduleSend && this.props.cancelScheduleSend();
+ break;
+ }
+
+ case messages.OPEN_SCHEDULE_MENU:{
+ this.props.openScheduleEmail && this.props.openScheduleEmail();
+ break;
+ }
}
} catch(e) {
//alert('NON JSON MESSAGE');
}
}
- _renderLinkModal() {
- return (
- this.setState({showLinkDialog: false})}
- >
-
-
- Title
-
- this.setState({linkTitle: text})}
- value={this.state.linkTitle}
- />
-
- URL
-
- this.setState({linkUrl: text})}
- value={this.state.linkUrl}
- keyboardType="url"
- autoCapitalize="none"
- autoCorrect={false}
- />
-
- {PlatformIOS && }
- {this._renderModalButtons()}
-
-
-
- );
- }
-
- _hideModal() {
- this.setState({
- showLinkDialog: false,
- linkInitialUrl: '',
- linkTitle: '',
- linkUrl: ''
- })
- }
-
- _renderModalButtons() {
- const insertUpdateDisabled = this.state.linkTitle.trim().length <= 0 || this.state.linkUrl.trim().length <= 0;
- const containerPlatformStyle = PlatformIOS ? {justifyContent: 'space-between'} : {paddingTop: 15};
- const buttonPlatformStyle = PlatformIOS ? {flex: 1, height: 45, justifyContent: 'center'} : {};
- return (
-
- {!PlatformIOS && }
- this._hideModal()}
- style={buttonPlatformStyle}
- >
-
- {this._upperCaseButtonTextIfNeeded('Cancel')}
-
-
- {
- if (this._linkIsNew()) {
- this.insertLink(this.state.linkUrl, this.state.linkTitle);
- } else {
- this.updateLink(this.state.linkUrl, this.state.linkTitle);
- }
- this._hideModal();
- }}
- disabled={insertUpdateDisabled}
- style={buttonPlatformStyle}
- >
-
- {this._upperCaseButtonTextIfNeeded(this._linkIsNew() ? 'Insert' : 'Update')}
-
-
-
- );
- }
-
- _linkIsNew() {
- return !this.state.linkInitialUrl;
- }
-
- _upperCaseButtonTextIfNeeded(buttonText) {
- return PlatformIOS ? buttonText : buttonText.toUpperCase();
- }
-
render() {
//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
- const pageSource = PlatformIOS ? require('./editor.html') : { uri: 'file:///android_asset/editor.html' };
+ const pageSource = PlatformIOS ? (this.props.source ? this.props.source:require('./editor.html')) : { uri: 'file:///android_asset/editor.html' };
return (
-
- {this.webviewBridge = r}}
- onBridgeMessage={(message) => this.onBridgeMessage(message)}
- injectedJavaScript={injectScript}
- source={pageSource}
- onLoad={() => this.init()}
- />
- {this._renderLinkModal()}
-
+
+ {this.webviewBridge = r}}
+ onBridgeMessage={(message) => this.onBridgeMessage(message)}
+ injectedJavaScript={injectScript}
+ source={pageSource}
+ onLoad={() => this.init()}
+ />
+
);
}
escapeJSONString = function(string) {
return string
- .replace(/[\\]/g, '\\\\')
- .replace(/[\"]/g, '\\\"')
- .replace(/[\']/g, '\\\'')
- .replace(/[\/]/g, '\\/')
- .replace(/[\b]/g, '\\b')
- .replace(/[\f]/g, '\\f')
- .replace(/[\n]/g, '\\n')
- .replace(/[\r]/g, '\\r')
- .replace(/[\t]/g, '\\t');
+ .replace(/[\\]/g, '\\\\')
+ .replace(/[\"]/g, '\\\"')
+ .replace(/[\’]/g, '\'')
+ .replace(/[\']/g, '\\\'')
+ .replace(/[\/]/g, '\\/')
+ .replace(/[\b]/g, '\\b')
+ .replace(/[\f]/g, '\\f')
+ .replace(/[\n]/g, '\\n')
+ .replace(/[\r]/g, '\\r')
+ .replace(/[\t]/g, '\\t');
};
_sendAction(action, data) {
+
let jsonString = JSON.stringify({type: action, data});
- jsonString = this.escapeJSONString(jsonString);
- this.webviewBridge.sendToBridge(jsonString);
+ let test = this.btoa(unescape(encodeURIComponent(jsonString)));
+ this.webviewBridge.sendToBridge(test);
+ }
+
+ btoa(input= '') {
+ const CHARS =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+ let map;
+ let i = 0;
+ let block = 0;
+ let output = '';
+ for (
+ block = 0, i = 0, map = CHARS;
+ input.charAt(i | 0) || ((map = '='), i % 1);
+ output += map.charAt(63 & (block >> (8 - (i % 1) * 8)))
+ ) {
+ const charCode = input.charCodeAt((i += 3 / 4));
+ if (charCode > 0xff) {
+ throw new Error(
+ "'RNFirebase.utils.btoa' failed: The string to be encoded contains characters outside of the Latin1 range."
+ );
+ }
+ block = (block << 8) | charCode;
+ }
+ return output;
}
//-------------------------------------------------------------------------------
//--------------- Public API
- showLinkDialog(optionalTitle = '', optionalUrl = '') {
- this.setState({
- linkInitialUrl: optionalUrl,
- linkTitle: optionalTitle,
- linkUrl: optionalUrl,
- showLinkDialog: true
- });
+ showLinkDialog(optionalTitle = "", optionalUrl = "") {
+ if (this.props.showModal) {
+ this.props.showModal(
+ optionalTitle,
+ optionalUrl,
+ (url, title) => {
+ this.insertLink(url, title);
+ }
+ );
+ }
}
focusTitle() {
@@ -505,6 +489,17 @@ export default class RichTextEditor extends Component {
this._sendAction(actions.setTitlePlaceholder, placeholder);
}
+ setInputFields(inputFields) {
+ if (inputFields && Array.isArray(inputFields)) {
+ if (PlatformIOS) {
+ inputFields.reverse(); //iOS reverses the provided order
+ }
+ for (let i = 0; i < inputFields.length; i++) {
+ this._sendAction(actions.insertInputField, inputFields[i]);
+ }
+ }
+ }
+
setContentPlaceholder(placeholder) {
this._sendAction(actions.setContentPlaceholder, placeholder);
}
@@ -583,6 +578,41 @@ export default class RichTextEditor extends Component {
});
}
+ async setScheduleSendDate(scheduleObj) {
+ this._sendAction(actions.setScheduleSendDate, scheduleObj);
+ }
+
+ async getInputFieldText(fieldKey) {
+ return new Promise((resolve, reject) => {
+ this.inputFieldResolves[fieldKey] = resolve;
+ this.inputFieldRejects[fieldKey] = reject;
+ this.inputFieldTimers[fieldKey] = reject;
+ this._sendAction(actions.getInputFieldText, fieldKey);
+
+ this.inputFieldTimers[fieldKey] = setTimeout(() => {
+ if (this.inputFieldRejects[fieldKey]) {
+ this.inputFieldRejects[fieldKey]('timeout')
+ }
+ }, 5000);
+ });
+ }
+
+ setInputFieldText(fieldKey, text) {
+ this._sendAction(actions.setInputFieldText, {key: fieldKey, text});
+ }
+
+ deleteScheduleSend() {
+ this._sendAction(actions.deleteScheduleSend);
+ }
+
+ focusInputField(fieldKey) {
+ this._sendAction(actions.focusInputField, fieldKey);
+ }
+
+ blurInputField(fieldKey) {
+ this._sendAction(actions.blurInputField, fieldKey);
+ }
+
async getSelectedText() {
return new Promise((resolve, reject) => {
this.selectedTextResolve = resolve;
@@ -602,56 +632,20 @@ export default class RichTextEditor extends Component {
this._sendAction(actions.setTitleFocusHandler);
}
+ setThresholdHandler(callbackHandler) {
+ this.thresholdHandler = callbackHandler;
+ }
+
setContentFocusHandler(callbackHandler) {
this.contentFocusHandler = callbackHandler;
this._sendAction(actions.setContentFocusHandler);
}
+ setInputFieldFocusHandler(fieldKey, callbackHandler){
+ this['inputFieldFocusHandler_'+fieldKey] = callbackHandler;
+ }
+
addSelectedTextChangeListener(listener) {
this._selectedTextChangeListeners.push(listener);
}
}
-
-const styles = StyleSheet.create({
- modal: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: 'rgba(0, 0, 0, 0.5)'
- },
- innerModal: {
- backgroundColor: 'rgba(255, 255, 255, 0.9)',
- paddingTop: 20,
- paddingBottom: PlatformIOS ? 0 : 20,
- paddingLeft: 20,
- paddingRight: 20,
- alignSelf: 'stretch',
- margin: 40,
- borderRadius: PlatformIOS ? 8 : 2
- },
- button: {
- fontSize: 16,
- color: '#4a4a4a',
- textAlign: 'center'
- },
- inputWrapper: {
- marginTop: 5,
- marginBottom: 10,
- borderBottomColor: '#4a4a4a',
- borderBottomWidth: PlatformIOS ? 1 / PixelRatio.get() : 0
- },
- inputTitle: {
- color: '#4a4a4a'
- },
- input: {
- height: PlatformIOS ? 20 : 40,
- paddingTop: 0
- },
- lineSeparator: {
- height: 1 / PixelRatio.get(),
- backgroundColor: '#d5d5d5',
- marginLeft: -20,
- marginRight: -20,
- marginTop: 20
- }
-});
diff --git a/src/RichTextToolbar.js b/src/RichTextToolbar.js
index d97f4cb7..86c53f2e 100644
--- a/src/RichTextToolbar.js
+++ b/src/RichTextToolbar.js
@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import {ListView, View, TouchableOpacity, Image, StyleSheet} from 'react-native';
+import { FlatList, View, TouchableOpacity, Image, StyleSheet } from 'react-native';
import {actions} from './const';
const defaultActions = [
@@ -46,15 +46,15 @@ export default class RichTextToolbar extends Component {
editor: undefined,
selectedItems: [],
actions,
- ds: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}).cloneWithRows(this.getRows(actions, []))
+ dataSet: this.getRows(actions, [])
};
}
- componentDidReceiveProps(newProps) {
+ componentWillReceiveProps(newProps) {
const actions = newProps.actions ? newProps.actions : defaultActions;
this.setState({
actions,
- ds: this.state.ds.cloneWithRows(this.getRows(actions, this.state.selectedItems))
+ dataSet: this.getRows(actions, this.state.selectedItems)
});
}
@@ -76,7 +76,7 @@ export default class RichTextToolbar extends Component {
if (selectedItems !== this.state.selectedItems) {
this.setState({
selectedItems,
- ds: this.state.ds.cloneWithRows(this.getRows(this.state.actions, selectedItems))
+ dataSet: this.getRows(this.state.actions, selectedItems)
});
}
}
@@ -102,16 +102,16 @@ export default class RichTextToolbar extends Component {
_defaultRenderAction(action, selected) {
const icon = this._getButtonIcon(action);
return (
- this._onPress(action)}
- >
- {icon ? : null}
-
+ this._onPress(action)}
+ >
+ {icon ? : null}
+
);
}
@@ -121,18 +121,27 @@ export default class RichTextToolbar extends Component {
this._defaultRenderAction(action, selected);
}
+ _keyExtractor=(item, index)=>{
+ return item + index;
+ }
+
render() {
return (
-
- this._renderAction(row.action, row.selected)}
- />
-
+
+ this._renderAction(item.item.action, item.item.selected)}
+ ListHeaderComponent={()=>{
+ return this.props.headerView && this.props.headerView() || undefined
+ }}
+ ListFooterComponent={this.props.footerView}
+ />
+ {this.props.fixedRight && this.props.fixedRight()}
+
);
}
@@ -179,7 +188,6 @@ export default class RichTextToolbar extends Component {
this.props.onPressAddImage();
}
break;
- break;
}
}
}
@@ -189,4 +197,4 @@ const styles = StyleSheet.create({
backgroundColor: 'red'
},
defaultUnselectedButton: {}
-});
\ No newline at end of file
+});
diff --git a/src/WebviewMessageHandler.js b/src/WebviewMessageHandler.js
index 05a66ea6..807cc285 100644
--- a/src/WebviewMessageHandler.js
+++ b/src/WebviewMessageHandler.js
@@ -2,9 +2,37 @@ import {actions, messages} from './const';
export const InjectedMessageHandler = `
if (WebViewBridge) {
- WebViewBridge.onMessage = function (message) {
+ const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+ const hbAtob = function(input){
+ let i = 0;
+ let bc = 0;
+ let bs = 0;
+ let buffer;
+ let output = '';
+
+ const str = input.replace(/=+$/, '');
+
+ if (str.length % 4 === 1) {
+ throw new Error(
+ "'RNFirebase.utils.atob' failed: The string to be decoded is not correctly encoded."
+ );
+ }
+
+ for (
+ bc = 0, bs = 0, i = 0;
+ (buffer = str.charAt(i++));
+ ~buffer && ((bs = bc % 4 ? bs * 64 + buffer : buffer), bc++ % 4)
+ ? (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6))))
+ : 0
+ ) {
+ buffer = CHARS.indexOf(buffer);
+ }
- const action = JSON.parse(message);
+ return output;
+ };
+
+ WebViewBridge.onMessage = function (message) {
+ const action = JSON.parse(decodeURIComponent(escape(hbAtob(message))));
switch(action.type) {
case '${actions.enableOnChange}':
@@ -109,12 +137,18 @@ export const InjectedMessageHandler = `
case '${actions.setOutdent}':
zss_editor.setOutdent();
break;
+ case '${actions.insertInputField}':
+ zss_editor.insertInputField(action.data);
+ break;
case '${actions.setTitlePlaceholder}':
zss_editor.setTitlePlaceholder(action.data);
break;
case '${actions.setContentPlaceholder}':
zss_editor.setContentPlaceholder(action.data);
break;
+ case '${actions.addRecipient}':
+ WebViewBridge.send(JSON.stringify({type: '${messages.ADD_RECIPIENT}'}));
+ break;
case '${actions.getTitleHtml}':
var html = zss_editor.getTitleHTML();
WebViewBridge.send(JSON.stringify({type: '${messages.TITLE_HTML_RESPONSE}', data: html}));
@@ -127,12 +161,31 @@ export const InjectedMessageHandler = `
var html = zss_editor.getContentHTML();
WebViewBridge.send(JSON.stringify({type: '${messages.CONTENT_HTML_RESPONSE}', data: html}));
break;
+ case '${actions.getInputFieldText}':
+ var text = zss_editor.getInputFieldText(action.data);
+ WebViewBridge.send(JSON.stringify({type: '${messages.INPUT_FIELD_TEXT_RESPONSE}', data: text, key: action.data}));
+ break;
+ case '${actions.setScheduleSendDate}':
+ var data = zss_editor.setScheduleSendDate(action.data);
+ break;
+ case '${actions.setInputFieldText}':
+ zss_editor.setInputFieldText(action.data);
+ break;
+ case '${actions.deleteScheduleSend}':
+ zss_editor.deleteScheduleSend();
+ break;
+ case '${actions.focusInputField}':
+ zss_editor.focusInputField(action.data);
+ break;
+ case '${actions.blurInputField}':
+ zss_editor.blurInputField(action.data);
+ break;
case '${actions.setTitleFocusHandler}':
zss_editor.setTitleFocusHandler();
break;
case '${actions.setContentFocusHandler}':
zss_editor.setContentFocusHandler();
- break;
+ break;
case '${actions.getSelectedText}':
var selectedText = getSelection().toString();
WebViewBridge.send(JSON.stringify({type: '${messages.SELECTED_TEXT_RESPONSE}', data: selectedText}));
diff --git a/src/const.js b/src/const.js
index 653b43f8..7f9b8b72 100644
--- a/src/const.js
+++ b/src/const.js
@@ -2,12 +2,19 @@ export const actions = {
enableOnChange: 'ENABLE_ON_CHANGE',
setTitleHtml: 'SET_TITLE_HTML',
setContentHtml: 'SET_CONTENT_HTML',
+ addRecipient: 'ADD_RECIPIENT',
getTitleHtml: 'GET_TITLE_HTML',
getTitleText: 'GET_TITLE_TEXT',
toggleTitle: 'TOGGLE_TITLE',
hideTitle: 'HIDE_TITLE',
showTitle: 'SHOW_TITLE',
getContentHtml: 'GET_CONTENT_HTML',
+ getInputFieldText: 'GET_INPUT_FIELD_TEXT',
+ setScheduleSendDate: 'SET_SCHEDULE_SEND_DATE',
+ setInputFieldText: 'SET_INPUT_FIELD_TEXT',
+ deleteScheduleSend: 'DELETE_SCHEDULE_SEND',
+ focusInputField: 'FOCUS_INPUT_FIELD',
+ blurInputField: 'BLUR_INPUT_FIELD',
getSelectedText: 'GET_SELECTED_TEXT',
blurTitleEditor: 'BLUR_TITLE_EDITOR',
blurContentEditor: 'BLUR_CONTENT_EDITOR',
@@ -41,6 +48,7 @@ export const actions = {
setIndent: 'indent',
setOutdent: 'outdent',
setTitlePlaceholder: 'SET_TITLE_PLACEHOLDER',
+ insertInputField: 'INSERT_INPUT_FIELD',
setContentPlaceholder: 'SET_CONTENT_PLACEHOLDER',
setTitleFocusHandler: 'SET_TITLE_FOCUS_HANDLER',
setContentFocusHandler: 'SET_CONTENT_FOCUS_HANDLER',
@@ -57,14 +65,21 @@ export const actions = {
export const messages = {
+ ADD_RECIPIENT: 'ADD_RECIPIENT',
+ CANCEL_SCHEDULE_SEND: 'CANCEL_SCHEDULE_SEND',
+ OPEN_SCHEDULE_MENU: 'OPEN_SCHEDULE_MENU',
TITLE_HTML_RESPONSE: 'TITLE_HTML_RESPONSE',
TITLE_TEXT_RESPONSE: 'TITLE_TEXT_RESPONSE',
CONTENT_HTML_RESPONSE: 'CONTENT_HTML_RESPONSE',
+ INPUT_FIELD_TEXT_RESPONSE: 'INPUT_FIELD_TEXT_RESPONSE',
ZSS_INITIALIZED: 'ZSS_INITIALIZED',
SCROLL: 'SCROLL',
LOG: 'LOG',
TITLE_FOCUSED: 'TITLE_FOCUSED',
CONTENT_FOCUSED: 'CONTENT_FOCUSED',
+ INPUT_FIELD_FOCUSED: 'INPUT_FIELD_FOCUSED',
+ TOP_REACHED: 'TOP_REACHED',
+ BOTTOM_REACHED: 'BOTTOM_REACHED',
SELECTION_CHANGE: 'SELECTION_CHANGE',
CONTENT_CHANGE: 'CONTENT_CHANGE',
SELECTED_TEXT_RESPONSE: 'SELECTED_TEXT_RESPONSE',
diff --git a/src/editor.html b/src/editor.html
index 1b30f937..5986bcb1 100644
--- a/src/editor.html
+++ b/src/editor.html
@@ -1,1033 +1,1154 @@
-
- ZSSRichTextEditor
-
-
-
-
+ } else {
+ zss_editor.currentEditingImage = null;
+ }
-
-
-
-
-
-
-
-
-
-
-
-
+ }
+
+ zss_editor.setCustomCSS = function(customCSS) {
+
+ document.getElementsByTagName('style')[1].innerHTML=customCSS;
+
+ //set focus
+ /*editor.focusout(function(){
+ var element = $(this);
+ if (!element.text().trim().length) {
+ element.empty();
+ }
+ });*/
+
+
+
+ }
+
+ function addFocusEvent(editorId, callbackHandler) {
+ var editor = $('#' + editorId);
+ editor.focus(callbackHandler);
+ }
+
+ zss_editor.setTitleFocusHandler = function() {
+ addFocusEvent('zss_editor_title', function() {
+ WebViewBridge.send(JSON.stringify({type: 'TITLE_FOCUSED'}))
+ });
+ }
+
+ zss_editor.setContentFocusHandler = function() {
+ addFocusEvent('zss_editor_content', function() {
+ WebViewBridge.send(JSON.stringify({type: 'CONTENT_FOCUSED'}))
+ });
+ }
+
+ zss_editor.setEditorHeight = function(editorHeight) {
+ zss_editor.editorHeight = editorHeight;
+ }
+
+ zss_editor.setPlatform = function(platform) {
+ zss_editor.platform = platform;
+ }
+ $(window).on("scroll", function() {
+ var scrollHeight = $(document).height();
+ var scrollPosition = $(window).height() + $(window).scrollTop();
+ if ((scrollHeight - scrollPosition) / scrollHeight === 0) {
+ WebViewBridge.send(JSON.stringify({type: 'BOTTOM_REACHED'}))
+ }
+ if ((scrollPosition) === 0) {
+ WebViewBridge.send(JSON.stringify({type: 'TOP_REACHED'}))
+ }
+ });
+ //end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+