diff --git a/apps/documenteditor/mobile/locale/en.json b/apps/documenteditor/mobile/locale/en.json index 612cb2a27..b6004ece5 100644 --- a/apps/documenteditor/mobile/locale/en.json +++ b/apps/documenteditor/mobile/locale/en.json @@ -261,6 +261,12 @@ "textNextPage": "Next Page", "textContinuousPage": "Continuous Page", "textEvenPage": "Even Page", - "textOddPage": "Odd Page" + "textOddPage": "Odd Page", + "textInsertFootnote": "Insert Footnote", + "textBottomOfPage": "Bottom Of Page", + "textBelowText": "Below Text", + "textStartAt": "Start At", + "textLocation": "Location", + "textFormat": "Format" } } \ No newline at end of file diff --git a/apps/documenteditor/mobile/src/controller/add/AddOther.jsx b/apps/documenteditor/mobile/src/controller/add/AddOther.jsx index f4e68ef1b..9793ebfb3 100644 --- a/apps/documenteditor/mobile/src/controller/add/AddOther.jsx +++ b/apps/documenteditor/mobile/src/controller/add/AddOther.jsx @@ -5,6 +5,64 @@ import { withTranslation} from 'react-i18next'; import {AddOther} from '../../view/add/AddOther'; +// footnote converting metods +const _10toS = (value) => { + value = parseInt(value); + let n = Math.ceil(value / 26), + code = String.fromCharCode((value-1) % 26 + "A".charCodeAt(0)) , + result = ''; + for (var i=0; i { + if ( str.length<1 || (new RegExp('[^' + str.charAt(0) + ']')).test(str) || !/[A-Z]/.test(str)) return 1; + let n = str.length-1, + result = str.charCodeAt(0) - "A".charCodeAt(0) + 1; + result += 26*n; + return result; +}; +const _10toRome = (value) => { + value = parseInt(value); + let result = '', + digits = [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400], ['C', 100], ['XC', 90], ['L', 50], ['XL', 40], ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1]]; + let val = digits[0][1], + div = Math.floor(value / val), + n = 0; + for (var i=0; i0) { + val = digits[n][1]; + div = value - val; + if (div>=0) { + result += digits[n][0]; + value = div; + } else + n++; + } + return result; +}; +const _Rometo10 = (str) => { + if ( !/[IVXLCDM]/.test(str) || str.length<1 ) return 1; + let digits = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}; + var n = str.length-1, + result = digits[str.charAt(n)], + prev = result; + for (var i=n-1; i>=0; i-- ) { + var val = digits[str.charAt(i)]; + if (val10) return 1; + val *= -1; + } + result += val; + prev = Math.abs(val); + } + return result; +}; + class AddOtherController extends Component { constructor (props) { super(props); @@ -13,6 +71,11 @@ class AddOtherController extends Component { this.onPageBreak = this.onPageBreak.bind(this); this.onColumnBreak = this.onColumnBreak.bind(this); this.onInsertSectionBreak = this.onInsertSectionBreak.bind(this); + this.getFootnoteStartAt = this.getFootnoteStartAt.bind(this); + this.onFootnoteStartAt = this.onFootnoteStartAt.bind(this); + this.onInsertFootnote = this.onInsertFootnote.bind(this); + this.initFootnoteStartAt = this.initFootnoteStartAt.bind(this); + this.getFootnoteProps = this.getFootnoteProps.bind(this); } closeModal () { @@ -124,6 +187,96 @@ class AddOtherController extends Component { this.closeModal(); } + // Footnote + + getFootnoteProps () { + if (!this.footnoteProps) { + const api = Common.EditorApi.get(); + const props = api.asc_GetFootnoteProps(); + this.footnoteProps = {propsFormat: props.get_NumFormat(), propsPos: props.get_Pos()}; + } + return this.footnoteProps; + } + + initFootnoteStartAt () { + if (!this.footnoteCurStart) { + const api = Common.EditorApi.get(); + const currValue = api.asc_GetFootnoteProps().get_NumStart(); + this.toCustomFormat = value => { + return value; + }; + this.fromCustomFormat = value => { + return value; + }; + this.footnoteCurStart = this.toCustomFormat(currValue); + } + return this.footnoteCurStart; + } + + getFootnoteStartAt (value, start) { + const currValue = this.fromCustomFormat(start); + + switch (value) { + case Asc.c_oAscNumberingFormat.UpperRoman: // I, II, III, ... + this.toCustomFormat = _10toRome; + this.fromCustomFormat = _Rometo10; + break; + case Asc.c_oAscNumberingFormat.LowerRoman: // i, ii, iii, ... + this.toCustomFormat = value => { return _10toRome(value).toLocaleLowerCase(); }; + this.fromCustomFormat = value => { return _Rometo10(value.toLocaleUpperCase()); }; + break; + case Asc.c_oAscNumberingFormat.UpperLetter: // A, B, C, ... + this.toCustomFormat = _10toS; + this.fromCustomFormat = _Sto10; + break; + case Asc.c_oAscNumberingFormat.LowerLetter: // a, b, c, ... + this.toCustomFormat = value => { return _10toS(value).toLocaleLowerCase(); }; + this.fromCustomFormat = value => { return _Sto10(value.toLocaleUpperCase()); }; + break; + default: // 1, 2, 3, ... + this.toCustomFormat = value => { return value; }; + this.fromCustomFormat = value => { return value; }; + break; + } + return this.toCustomFormat(currValue); + } + + onFootnoteStartAt (value, isDecrement) { + let intValue; + const step = 1; + const maxValue = 16383; + if(this.fromCustomFormat) { + intValue = parseInt(this.fromCustomFormat(value)); + } else { + const api = Common.EditorApi.get(); + intValue = api.asc_GetFootnoteProps().get_NumStart(); + } + if (isDecrement) { + intValue = Math.max(1, intValue - step); + } else { + intValue = Math.min(maxValue, intValue + step); + } + return this.toCustomFormat(intValue); + } + + onInsertFootnote (format, start, location) { + const api = Common.EditorApi.get(); + const props = new Asc.CAscFootnotePr(); + let startTo10; + if (this.fromCustomFormat) { + startTo10 = parseInt(this.fromCustomFormat(start)); + } else { + startTo10 = api.asc_GetFootnoteProps().get_NumStart(); + } + props.put_Pos(location); + props.put_NumFormat(format); + props.put_NumStart(startTo10); + props.put_NumRestart(Asc.c_oAscFootnoteRestart.Continuous); + api.asc_SetFootnoteProps(props, false); + api.asc_AddFootnote(); + this.closeModal(); + } + render () { return ( ) } diff --git a/apps/documenteditor/mobile/src/view/add/Add.jsx b/apps/documenteditor/mobile/src/view/add/Add.jsx index fbc47f05f..0e5088920 100644 --- a/apps/documenteditor/mobile/src/view/add/Add.jsx +++ b/apps/documenteditor/mobile/src/view/add/Add.jsx @@ -11,7 +11,7 @@ import {AddImageController} from "../../controller/add/AddImage"; import {AddOtherController} from "../../controller/add/AddOther"; import {PageImageLinkSettings} from "../add/AddImage"; -import {PageAddLink, PageAddNumber, PageAddBreak, PageAddSectionBreak} from "../add/AddOther"; +import {PageAddLink, PageAddNumber, PageAddBreak, PageAddSectionBreak, PageAddFootnote} from "../add/AddOther"; const routes = [ // Image @@ -36,6 +36,10 @@ const routes = [ path: '/add-section-break/', component: PageAddSectionBreak, }, + { + path: '/add-footnote/', + component: PageAddFootnote, + }, ]; const AddLayoutNavbar = ({ tabs, inPopover }) => { diff --git a/apps/documenteditor/mobile/src/view/add/AddOther.jsx b/apps/documenteditor/mobile/src/view/add/AddOther.jsx index e50a23ad5..06ad6f3b5 100644 --- a/apps/documenteditor/mobile/src/view/add/AddOther.jsx +++ b/apps/documenteditor/mobile/src/view/add/AddOther.jsx @@ -1,7 +1,8 @@ import React, {useState} from 'react'; import {observer, inject} from "mobx-react"; -import {List, ListItem, Page, Navbar, Icon, ListButton, ListInput, BlockTitle} from 'framework7-react'; +import {List, ListItem, Page, Navbar, Icon, ListButton, ListInput, BlockTitle, Segmented, Button} from 'framework7-react'; import { useTranslation } from 'react-i18next'; +import {Device} from "../../../../../common/mobile/utils/device"; const PageLink = props => { const { t } = useTranslation(); @@ -118,6 +119,82 @@ const PageSectionBreak = props => { ) }; +const PageFootnote = props => { + const isAndroid = Device.android; + const { t } = useTranslation(); + const _t = t('Add', {returnObjects: true}); + + const dataFormatFootnote = [ + { text: '1, 2, 3,...', value: Asc.c_oAscNumberingFormat.Decimal }, + { text: 'a, b, c,...', value: Asc.c_oAscNumberingFormat.LowerLetter }, + { text: 'A, B, C,...', value: Asc.c_oAscNumberingFormat.UpperLetter }, + { text: 'i, ii, iii,...', value: Asc.c_oAscNumberingFormat.LowerRoman }, + { text: 'I, II, III,...', value: Asc.c_oAscNumberingFormat.UpperRoman } + ]; + const dataPosFootnote = [ + {value: Asc.c_oAscFootnotePos.PageBottom, displayValue: _t.textBottomOfPage }, + {value: Asc.c_oAscFootnotePos.BeneathText, displayValue: _t.textBelowText } + ]; + + const [stateStartAt, setStartAt] = useState(props.initFootnoteStartAt()); + const [stateLocation, setLocation] = useState(props.getFootnoteProps().propsPos); + const [stateFormat, setFormat] = useState(props.getFootnoteProps().propsFormat); + + return ( + + + {_t.textFormat} + + {dataFormatFootnote.map((format, index)=>{ + return ( + { + setStartAt(props.getFootnoteStartAt(format.value, stateStartAt)); + setFormat(format.value) + }}> + ) + })} + + + + {!isAndroid &&
{stateStartAt}
} +
+ + + {isAndroid && } + + +
+
+
+ {_t.textLocation} + + {dataPosFootnote.map((location, index)=>{ + return ( + {setLocation(location.value)}}> + ) + })} + + + { + props.onInsertFootnote(stateFormat, stateStartAt, stateLocation); + }}> + +
+ ) +}; + const AddOther = props => { const { t } = useTranslation(); const _t = t('Add', {returnObjects: true}); @@ -144,7 +221,13 @@ const AddOther = props => { }}> - + @@ -155,4 +238,5 @@ export {AddOther, PageLink as PageAddLink, PageNumber as PageAddNumber, PageBreak as PageAddBreak, - PageSectionBreak as PageAddSectionBreak}; \ No newline at end of file + PageSectionBreak as PageAddSectionBreak, + PageFootnote as PageAddFootnote}; \ No newline at end of file