Skip to content

Commit c2b49d2

Browse files
阿思根阿思根
阿思根
authored and
阿思根
committed
better comment
1 parent da99a56 commit c2b49d2

File tree

8 files changed

+159
-45
lines changed

8 files changed

+159
-45
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"main": "index.js",
66
"scripts": {
77
"start": "webpack-dev-server",
8-
"lint": "eslint src"
8+
"build": "webpack --config webpack.config.build.js"
99
},
1010
"repository": {
1111
"type": "git",

src/component/paragraph.js

+80-3
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,21 @@ import util from '../mobx-script/util'
88
export default class Paragraph extends Component{
99
componentDidMount(){
1010
if(this.props.para.focus){
11+
// console.log('mount', this.props.unique)
1112
ReactDOM.findDOMNode(this).focus();
1213
if(this.props.para.text){
14+
// set cursor to position
1315
util.SetCaretPosition(ReactDOM.findDOMNode(this), this.props.para.selectionStart.offset);
1416
}
1517
}
1618
}
1719
componentDidUpdate(param){
1820
// console.log(param.unique, 'updated', param.para.selectionStart.offset);
1921
if(this.refs.true){
22+
// console.log('update', param.unique)
2023
ReactDOM.findDOMNode(this).focus();
2124
if(param.para.text){
25+
// set cursor to position
2226
util.SetCaretPosition(ReactDOM.findDOMNode(this), param.para.selectionStart.offset);
2327
}
2428
}
@@ -41,20 +45,93 @@ export default class Paragraph extends Component{
4145
e.target.innerHTML = tmpHead.concat(copyStuff,tmpTail);
4246

4347
// update cursor after paste
48+
// the same function may running twice if paste cause paragraph height changing which will case pageSeperation_monitor()
49+
// if pageSeperation_monitor decided to reRender page, componentDidUpdate will be called, but it's not big of a deal
4450
util.SetCaretPosition(e.target, tmpOffSet + copyStuff.length);
4551
}
4652
render(){
4753
const para = this.props.para;
48-
// const edit = this.props.edit;
54+
/*------------------------------------------------------
4955
56+
This is a home-made contentEditable div
57+
It's rough and simple and dumb as fuck, but => it's working !
58+
And I think that's what matters here
59+
60+
I once read a CKEditor developer's post on stackoverflow:
61+
- you can dive in this and hard coding all you want
62+
- but you'll GET LOST
63+
- because no matter what you do, html text editor will always be buggy
64+
- that's just the way it is
65+
66+
I set a goal before doing all of this: - as simple as possible -
67+
But somewhere in the middle I find myself dealing with paste, cursor position and all those dirty stuff
68+
And I don't see a way out ...
69+
70+
So I made my call =>
71+
Can you write a script based on what we have, yes you can, and that's enough
72+
73+
Not excusing myself, you can try write a story, and see for yourself if it's enough
74+
75+
===================== read below =====================
76+
77+
There's two state of text, just like other react apps
78+
- the one in Store(MobxScript), and the one in View(<Paragraph>)
79+
80+
Those two will synchronize:
81+
- when a Blur event happen - user start a new paragraph or save (MobxScript.handleBlur)
82+
- when Paragraph's height changing - pageSeperation_monitor decided to reRender page (MobxScript.handleKey)
83+
That's basicly the minimum Store changing, text is not an issue for rendering, yet it can go 100+ or even 200+ pages
84+
So we keep it as low as possible
85+
86+
Action between paragraphs:
87+
- key up, focus on previous one if cursor at line top, and set cursor at previous' line bottom
88+
- key down, focus on next one if cursor at line bottom, and set cursor at next's line top
89+
- key delete, when cursor at text-start,
90+
focus on previous one if both this and prevous one is not empty, and set cursor at end of previous
91+
else if this one is empty, delete this one, else if previous one is empty, then delete previous one
92+
- key backward, focus on previous one if cursor at text-start, and set cursor at end of previous
93+
- key forward, focus on next one if cursor at text-end, and set cursor at start of next
94+
95+
-key enter
96+
if current paragraph is not empty, start a new paragraph based on current one's type:
97+
FadeIn => new Scene
98+
Action => new Action
99+
Scene => new Action
100+
Character => new Dialogue
101+
Parenthetical => new Dialogue
102+
Dialogue => new Action
103+
Transition => new Scene
104+
Shot => new Action
105+
else pop up selectbox
106+
107+
- short-cut
108+
if current paragraph is not empty, start a new paragraph:
109+
ctrl + 1 => new Scene Heading
110+
ctrl + 2 => new Action
111+
ctrl + 3 => new Character
112+
ctrl + 4 => new Parenthetical
113+
ctrl + 5 => new Dialogue
114+
ctrl + 6 => new Transition
115+
ctrl + 7 => new Shot
116+
else pop up selectbox
117+
118+
- paste
119+
paste will only return plain text, with format is not possible, beacuse it's uncontrollable
120+
121+
- other
122+
command + b will generate bold font
123+
command + i will generate italic font
124+
125+
There you have it, folks, my shitty editor, aka DreamScript.
126+
127+
128+
------------------------------------------------------*/
50129
return (
51130
<div
52131
spellCheck
53132
contentEditable
54133
className={para.type}
55134
id={'paragraph'}
56-
onBlur={() => para.focus = false}
57-
onFocus={() => para.focus = true}
58135
onPaste={(e) => this.handlePaste(e)}
59136
dangerouslySetInnerHTML={{__html: para.innerHTML || ""}}
60137
data-placeholder={para.type.slice(5)}

src/component/script.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export default class Script extends Component{
3333
});
3434
}
3535
// componentWillUpdate(a,b){
36-
// // console.log(123);
36+
// console.log('this should not be happening... because mobx override this, nothing you can do here!');
3737
// return false;
3838
// }
3939
handleBack(){
@@ -47,10 +47,9 @@ export default class Script extends Component{
4747
return (
4848
<div
4949
className='script'
50-
// onKeyUp={(e) => e.target.id === 'paragraph' ? MobxScript.handleText(e) : ''}
5150
onKeyDown={(e) => e.target.id === 'paragraph' ? MobxScript.handleKey(e) : ''}
5251
onBlur={(e) => e.target.id === 'paragraph' ? MobxScript.handleBlur(e) : ''}
53-
>
52+
>
5453

5554
<div className='script_tool'>
5655
<div className='script_save' onClick={() => MobxScript.saveScript()}>save</div>

src/index.js

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const routes = (
2121
<Router history={browserHistory}>
2222
<Route path='/' component={DashBoard} />
2323
<Route path='/:id' component={Script} />
24-
{/* <Route path='*' component={Script} /> */}
2524
</Router>
2625
</Provider>
2726
)

src/mobx-script/mobx-script.js

+7-16
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ export default class scripts{
121121
------------------------------------------------------ */
122122
@action addNewScript(){
123123
this.titlePage = {title: 'NEW SCRIPT', author: 'AUTHOR', extra: 'EXTRA: this and that', contact: 'contact info:'};
124+
// First line is always FADE IN:
124125
this.paragraphs = [{type: 'para-fadein', focus: true, innerHTML: 'FADE IN:', text: 'FADE IN:', selectionStart: {line:0,offset:8}, height: 16 + this.Hdata['para-fadein'], key: Math.random(), line: 1}];
125126
this.pages = [[0,0]];
126127
this.lastSave = Date.now();
@@ -258,6 +259,7 @@ export default class scripts{
258259
// this.selectbox.display='none';
259260
// }
260261

262+
261263
/* ------------------------------------------------------
262264
263265
Handle blur of paragraph, text will be saved, and page will be reCalculated if needed
@@ -274,6 +276,11 @@ export default class scripts{
274276
const targetLineOffSet = parseInt(targetOffSet / this.lineCharNum[targetClassName]);
275277
const targetLine = parseInt(targetText.length / this.lineCharNum[targetClassName]) + 1;
276278

279+
/* ------------------------------------------------------
280+
Set focus false
281+
------------------------------------------------------ */
282+
this.paragraphs[index].focus = false;
283+
277284
const paragraphLengthOld = this.paragraphs.length;
278285
const paragraphHeightOld = this.paragraphs[index].height;
279286

@@ -383,7 +390,6 @@ export default class scripts{
383390
// show selectbox
384391
this.selectbox.index = index;
385392
this.selectbox.display = 'block';
386-
this.paragraphs[index].focus = false;
387393
}else{
388394

389395
/* ------------------------------------------------------
@@ -396,7 +402,6 @@ export default class scripts{
396402
newPara.selectionStart = {line:0,offset:1}
397403
}
398404
this.paragraphs.splice(index + 1, 0, newPara);
399-
this.paragraphs[index].focus = false;
400405

401406
// console.log(this.paragraphs[index].type);
402407
}
@@ -433,7 +438,6 @@ export default class scripts{
433438
// show selectbox
434439
this.selectbox.index = index;
435440
this.selectbox.display = 'block';
436-
this.paragraphs[index].focus = false;
437441
}
438442

439443
/* ------------------------------------------------------
@@ -446,42 +450,34 @@ export default class scripts{
446450
case 'para-fadein':
447451
newPara = {type: 'para-scene', focus: true, height: 16 + this.Hdata['para-scene'], key: Math.random(), line: 1, selectionStart: {line:0,offset:0}, innerHTML: '', text: ''};
448452
this.paragraphs.splice(index + 1, 0, newPara);
449-
this.paragraphs[index].focus = false;
450453
break;
451454
case 'para-action':
452455
newPara = {type: 'para-action', focus: true, height: 16 + this.Hdata['para-action'], key: Math.random(), line: 1, selectionStart: {line:0,offset:0}, innerHTML: '', text: ''};
453456
this.paragraphs.splice(index + 1, 0, newPara);
454-
this.paragraphs[index].focus = false;
455457
break;
456458
case 'para-scene':
457459
newPara = {type: 'para-action', focus: true, height: 16 + this.Hdata['para-action'], key: Math.random(), line: 1, selectionStart: {line:0,offset:0}, innerHTML: '', text: ''};
458460
this.paragraphs.splice(index + 1, 0, newPara);
459-
this.paragraphs[index].focus = false;
460461
break;
461462
case 'para-character':
462463
newPara = {type: 'para-dialogue', focus: true, height: 16 + this.Hdata['para-dialogue'], key: Math.random(), line: 1, selectionStart: {line:0,offset:0}, innerHTML: '', text: ''};
463464
this.paragraphs.splice(index + 1, 0, newPara);
464-
this.paragraphs[index].focus = false;
465465
break;
466466
case 'para-parenthetical':
467467
newPara = {type: 'para-dialogue', focus: true, height: 16 + this.Hdata['para-dialogue'], key: Math.random(), line: 1, selectionStart: {line:0,offset:0}, innerHTML: '', text: ''};
468468
this.paragraphs.splice(index + 1, 0, newPara);
469-
this.paragraphs[index].focus = false;
470469
break;
471470
case 'para-dialogue':
472471
newPara = {type: 'para-action', focus: true, height: 16 + this.Hdata['para-action'], key: Math.random(), line: 1, selectionStart: {line:0,offset:0}, innerHTML: '', text: ''};
473472
this.paragraphs.splice(index + 1, 0, newPara);
474-
this.paragraphs[index].focus = false;
475473
break;
476474
case 'para-transition':
477475
newPara = {type: 'para-scene', focus: true, height: 16 + this.Hdata['para-scene'], key: Math.random(), line: 1, selectionStart: {line:0,offset:0}, innerHTML: '', text: ''};
478476
this.paragraphs.splice(index + 1, 0, newPara);
479-
this.paragraphs[index].focus = false;
480477
break;
481478
case 'para-shot':
482479
newPara = {type: 'para-action', focus: true, height: 16 + this.Hdata['para-action'], key: Math.random(), line: 1, selectionStart: {line:0,offset:0}, innerHTML: '', text: ''};
483480
this.paragraphs.splice(index + 1, 0, newPara);
484-
this.paragraphs[index].focus = false;
485481
break;
486482
}
487483
}
@@ -515,7 +511,6 @@ export default class scripts{
515511
if(util.isSelected()){
516512
util.deleteContent();
517513
}else{
518-
this.paragraphs[index].focus = false;
519514
this.paragraphs[index - 1].focus = true;
520515
this.paragraphs[index - 1].selectionStart = {line: this.paragraphs[index - 1].line - 1, offset: this.paragraphs[index - 1].text.length};
521516
}
@@ -527,7 +522,6 @@ export default class scripts{
527522
else if(e.keyCode === 37 && targetOffSet === 0){
528523
if(index != 0){
529524
e.preventDefault();
530-
this.paragraphs[index].focus = false;
531525
this.paragraphs[index - 1].focus = true;
532526
this.paragraphs[index - 1].selectionStart = {line: this.paragraphs[index - 1].line - 1, offset: this.paragraphs[index - 1].text.length};
533527
}
@@ -539,7 +533,6 @@ export default class scripts{
539533
else if(e.keyCode === 39 && targetOffSet === targetText.length){
540534
if(index != this.paragraphs.length - 1){
541535
e.preventDefault();
542-
this.paragraphs[index].focus = false;
543536
this.paragraphs[index + 1].focus = true;
544537
this.paragraphs[index + 1].selectionStart = {line: 0, offset: 0};
545538
}
@@ -551,7 +544,6 @@ export default class scripts{
551544
else if(e.keyCode === 38 && targetLineOffSet === 0){
552545
if(index != 0){
553546
e.preventDefault();
554-
this.paragraphs[index].focus = false;
555547
this.paragraphs[index - 1].focus = true;
556548
// set cursor of prev paragraph relative to the first line of current paragraph
557549
this.paragraphs[index - 1].selectionStart = {line: this.paragraphs[index - 1].line - 1, offset: 0}
@@ -564,7 +556,6 @@ export default class scripts{
564556
else if(e.keyCode === 40 && targetLineOffSet === targetLine - 1){
565557
if(index != this.paragraphs.length - 1){
566558
e.preventDefault();
567-
this.paragraphs[index].focus = false;
568559
this.paragraphs[index + 1].focus = true;
569560
// set cursor of next paragraph relative to the last line of current paragraph
570561
this.paragraphs[index + 1].selectionStart = {line: 0, offset: 0}

src/styles/style.styl

+16-18
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@
2323
}
2424

2525

26-
@font-face
27-
font-family 'courier final draft bold italic'
28-
font-style normal
29-
src url('./font-courier/Courier Final Draft Bold Italic.ttf')
26+
// @font-face
27+
// font-family 'courier final draft bold italic'
28+
// font-style normal
29+
// src url('./font-courier/Courier Final Draft Bold Italic.ttf')
3030

3131
@font-face
3232
font-family 'courier final draft bold'
@@ -38,10 +38,10 @@
3838
font-style normal
3939
src url('./font-courier/Courier Final Draft Regular.ttf')
4040

41-
@font-face
42-
font-family 'courier final draft italic'
43-
font-style normal
44-
src url('./font-courier/Courier Final Draft Italic.ttf')
41+
// @font-face
42+
// font-family 'courier final draft italic'
43+
// font-style normal
44+
// src url('./font-courier/Courier Final Draft Italic.ttf')
4545

4646
// @font-face
4747
// font-family 'courier new'
@@ -238,21 +238,19 @@ body
238238
// font: 12pt "courier final draft"
239239
display: block
240240
padding: 0
241+
&:focus
242+
outline: none !important
243+
border: none
244+
box-shadow: 0 0 10px #719ECE
241245
&:empty:focus:before
242246
content: attr(data-placeholder)
243247
color: rgba(0,0,0,0.2)
248+
&:hover:not(:focus)
249+
outline: none !important
250+
border: none
251+
box-shadow: 0 0 10px #d3d3d3
244252

245253

246-
#paragraph:focus
247-
outline: none !important
248-
border: none
249-
box-shadow: 0 0 10px #719ECE
250-
251-
// #paragraph
252-
// font: 12pt "courier final draft"
253-
// b
254-
// font: 12pt "courier final draft bold"
255-
256254
.para-fadein
257255
width: 6.1in
258256
text-transform: uppercase

0 commit comments

Comments
 (0)