@@ -462,15 +462,15 @@ MM.Item.prototype.clone = function() {
462
462
return this . constructor . fromJSON ( data ) ;
463
463
}
464
464
465
- MM . Item . prototype . focus = function ( ) {
466
- /* going to mode 2c */
465
+ MM . Item . prototype . select = function ( ) {
467
466
this . _dom . node . classList . add ( "current" ) ;
468
467
this . getMap ( ) . ensureItemVisibility ( this ) ;
469
- MM . publish ( "item-focus" , this ) ;
468
+ MM . Clipboard . focus ( ) ; /* going to mode 2c */
469
+ MM . publish ( "item-select" , this ) ;
470
470
}
471
471
472
- MM . Item . prototype . blur = function ( ) {
473
- /* we were in 2b; finish that via 4b */
472
+ MM . Item . prototype . deselect = function ( ) {
473
+ /* we were in 2b; finish that via 3b */
474
474
if ( MM . App . editing ) { MM . Command . Finish . execute ( ) ; }
475
475
this . _dom . node . classList . remove ( "current" ) ;
476
476
}
@@ -733,7 +733,7 @@ MM.Item.prototype.handleEvent = function(e) {
733
733
if ( e . keyCode == 9 ) { e . preventDefault ( ) ; } /* TAB has a special meaning in this app, do not use it to change focus */
734
734
break ;
735
735
736
- case "blur" : /* 4d */
736
+ case "blur" : /* 3d */
737
737
MM . Command . Finish . execute ( ) ;
738
738
break ;
739
739
@@ -1160,7 +1160,7 @@ MM.Keyboard.handleEvent = function(e) {
1160
1160
var keys = command . keys ;
1161
1161
for ( var j = 0 ; j < keys . length ; j ++ ) {
1162
1162
if ( this . _keyOK ( keys [ j ] , e ) ) {
1163
- e . preventDefault ( ) ;
1163
+ command . prevent && e . preventDefault ( ) ;
1164
1164
command . execute ( e ) ;
1165
1165
return ;
1166
1166
}
@@ -1409,14 +1409,33 @@ MM.Action.SetStatus.prototype.undo = function() {
1409
1409
}
1410
1410
MM . Clipboard = {
1411
1411
_data : null ,
1412
- _mode : ""
1412
+ _mode : "" ,
1413
+ _node : document . createElement ( "textarea" )
1413
1414
} ;
1414
1415
1416
+ MM . Clipboard . init = function ( ) {
1417
+ this . _node . style . position = "absolute" ;
1418
+ this . _node . style . width = 0 ;
1419
+ this . _node . style . height = 0 ;
1420
+ this . _node . style . left = "-100px" ;
1421
+ this . _node . style . top = "-100px" ;
1422
+ document . body . appendChild ( this . _node ) ;
1423
+ }
1424
+
1425
+ MM . Clipboard . focus = function ( ) {
1426
+ this . _node . focus ( ) ;
1427
+ }
1428
+
1415
1429
MM . Clipboard . copy = function ( sourceItem ) {
1416
1430
this . _endCut ( ) ;
1417
-
1418
1431
this . _data = sourceItem . clone ( ) ;
1419
1432
this . _mode = "copy" ;
1433
+
1434
+ var plaintext = this . _itemToPlaintext ( sourceItem ) ;
1435
+ this . _node . value = plaintext ;
1436
+ this . _node . selectionStart = 0 ;
1437
+ this . _node . selectionEnd = this . _node . value . length ;
1438
+ setTimeout ( function ( ) { this . _node . value = "" ; } . bind ( this ) , 0 ) ;
1420
1439
}
1421
1440
1422
1441
MM . Clipboard . paste = function ( targetItem ) {
@@ -1468,6 +1487,19 @@ MM.Clipboard._endCut = function() {
1468
1487
this . _data = null ;
1469
1488
this . _mode = "" ;
1470
1489
}
1490
+
1491
+ MM . Clipboard . _itemToPlaintext = function ( item , depth ) {
1492
+ depth = depth || 0 ;
1493
+
1494
+ var lines = item . getChildren ( ) . map ( function ( child ) {
1495
+ return this . _itemToPlaintext ( child , depth + 1 ) ;
1496
+ } , this ) ;
1497
+
1498
+ var prefix = new Array ( depth + 1 ) . join ( "\t" ) ;
1499
+ lines . unshift ( prefix + item . getText ( ) . replace ( / \n / g, "<br/>" ) )
1500
+
1501
+ return lines . join ( "\n" ) + ( depth ? "" : "\n" ) ;
1502
+ }
1471
1503
MM . Menu = {
1472
1504
_dom : { } ,
1473
1505
_port : null ,
@@ -1528,6 +1560,7 @@ MM.Menu = {
1528
1560
MM . Command = Object . create ( MM . Repo , {
1529
1561
keys : { value : [ ] } ,
1530
1562
editMode : { value : false } ,
1563
+ prevent : { value : true } , /* prevent default keyboard action? */
1531
1564
label : { value : "" }
1532
1565
} ) ;
1533
1566
@@ -1771,6 +1804,7 @@ MM.Command.Pan.handleEvent = function(e) {
1771
1804
1772
1805
MM . Command . Copy = Object . create ( MM . Command , {
1773
1806
label : { value : "Copy" } ,
1807
+ prevent : { value : false } ,
1774
1808
keys : { value : [ { keyCode : "C" . charCodeAt ( 0 ) , ctrlKey :true } ] }
1775
1809
} ) ;
1776
1810
MM . Command . Copy . execute = function ( ) {
@@ -1779,6 +1813,7 @@ MM.Command.Copy.execute = function() {
1779
1813
1780
1814
MM . Command . Cut = Object . create ( MM . Command , {
1781
1815
label : { value : "Cut" } ,
1816
+ prevent : { value : false } ,
1782
1817
keys : { value : [ { keyCode : "X" . charCodeAt ( 0 ) , ctrlKey :true } ] }
1783
1818
} ) ;
1784
1819
MM . Command . Cut . execute = function ( ) {
@@ -1787,6 +1822,7 @@ MM.Command.Cut.execute = function() {
1787
1822
1788
1823
MM . Command . Paste = Object . create ( MM . Command , {
1789
1824
label : { value : "Paste" } ,
1825
+ prevent : { value : false } ,
1790
1826
keys : { value : [ { keyCode : "V" . charCodeAt ( 0 ) , ctrlKey :true } ] }
1791
1827
} ) ;
1792
1828
MM . Command . Paste . execute = function ( ) {
@@ -3521,7 +3557,6 @@ MM.Backend.GDrive._auth = function(forceUI) {
3521
3557
}
3522
3558
MM . UI = function ( ) {
3523
3559
this . _node = document . querySelector ( ".ui" ) ;
3524
- this . _node . addEventListener ( "click" , this ) ;
3525
3560
3526
3561
this . _toggle = this . _node . querySelector ( "#toggle" ) ;
3527
3562
@@ -3531,15 +3566,18 @@ MM.UI = function() {
3531
3566
this . _value = new MM . UI . Value ( ) ;
3532
3567
this . _status = new MM . UI . Status ( ) ;
3533
3568
3534
- MM . subscribe ( "item-focus " , this ) ;
3569
+ MM . subscribe ( "item-select " , this ) ;
3535
3570
MM . subscribe ( "item-change" , this ) ;
3536
3571
3572
+ this . _node . addEventListener ( "click" , this ) ;
3573
+ this . _node . addEventListener ( "change" , this ) ;
3574
+
3537
3575
this . toggle ( ) ;
3538
3576
}
3539
3577
3540
3578
MM . UI . prototype . handleMessage = function ( message , publisher ) {
3541
3579
switch ( message ) {
3542
- case "item-focus " :
3580
+ case "item-select " :
3543
3581
this . _update ( ) ;
3544
3582
break ;
3545
3583
@@ -3550,23 +3588,29 @@ MM.UI.prototype.handleMessage = function(message, publisher) {
3550
3588
}
3551
3589
3552
3590
MM . UI . prototype . handleEvent = function ( e ) {
3553
- /* blur to return focus back to app commands (mode 2c) */
3554
- /* FIXME 1) re-select current node, 2) do it also after any select changes */
3555
- if ( e . target . nodeName . toLowerCase ( ) != "select" ) { e . target . blur ( ) ; }
3591
+ switch ( e . type ) {
3592
+ case "click" :
3593
+ if ( e . target . nodeName . toLowerCase ( ) != "select" ) { MM . Clipboard . focus ( ) ; } /* focus the clipboard (2c) */
3556
3594
3557
- if ( e . target == this . _toggle ) {
3558
- this . toggle ( ) ;
3559
- return ;
3560
- }
3561
-
3562
- var node = e . target ;
3563
- while ( node != document ) {
3564
- var command = node . getAttribute ( "data-command" ) ;
3565
- if ( command ) {
3566
- MM . Command [ command ] . execute ( ) ;
3567
- return ;
3568
- }
3569
- node = node . parentNode ;
3595
+ if ( e . target == this . _toggle ) {
3596
+ this . toggle ( ) ;
3597
+ return ;
3598
+ }
3599
+
3600
+ var node = e . target ;
3601
+ while ( node != document ) {
3602
+ var command = node . getAttribute ( "data-command" ) ;
3603
+ if ( command ) {
3604
+ MM . Command [ command ] . execute ( ) ;
3605
+ return ;
3606
+ }
3607
+ node = node . parentNode ;
3608
+ }
3609
+ break ;
3610
+
3611
+ case "change" :
3612
+ MM . Clipboard . focus ( ) ; /* focus the clipboard (2c) */
3613
+ break ;
3570
3614
}
3571
3615
}
3572
3616
@@ -3906,8 +3950,7 @@ MM.UI.IO.prototype.show = function(mode) {
3906
3950
MM . UI . IO . prototype . hide = function ( ) {
3907
3951
if ( ! this . _node . classList . contains ( "visible" ) ) { return ; }
3908
3952
this . _node . classList . remove ( "visible" ) ;
3909
- /* FIXME instead of blurring, just re-select current node => switch to 2c */
3910
- document . activeElement && document . activeElement . blur ( ) ;
3953
+ MM . Clipboard . focus ( ) ;
3911
3954
window . removeEventListener ( "keydown" , this ) ;
3912
3955
}
3913
3956
@@ -4838,6 +4881,12 @@ MM.Mouse._visualizeDragState = function(state) {
4838
4881
node . style . boxShadow = ( x * offset ) + "px " + ( y * offset ) + "px 2px " + spread + "px #000" ;
4839
4882
}
4840
4883
}
4884
+
4885
+ setInterval ( function ( ) {
4886
+ console . log ( document . activeElement ) ;
4887
+ } , 1000 ) ;
4888
+
4889
+
4841
4890
/*
4842
4891
* Notes regarding app state/modes, activeElements, focusing etc.
4843
4892
* ==============================================================
@@ -4850,23 +4899,20 @@ MM.Mouse._visualizeDragState = function(state) {
4850
4899
* Keyboard shortcuts are disabled.
4851
4900
* 2b) Current item is being edited. It is contentEditable and focused.
4852
4901
* Blurring ends the edit mode.
4853
- * 2c) ELSE the focus belongs the the currently selected item.
4902
+ * 2c) ELSE the Clipboard is focused (its invisible textarea)
4854
4903
*
4855
- * In 2a, we try to return focus (re-select, 2c) as soon as possible
4856
- * (after clicking, after changing select's value).
4904
+ * In 2a, we try to lose focus as soon as possible
4905
+ * (after clicking, after changing select's value), switching to 2c .
4857
4906
*
4858
- * 3) After selecting an item, we switch to 2c. In 2c, the current item
4859
- * focuses its invisible "paste" node to listen for ctrl+v data.
4860
- *
4861
- * 4) Editing mode (2b) can be ended by multiple ways:
4862
- * 4a) By calling current.stopEditing();
4907
+ * 3) Editing mode (2b) can be ended by multiple ways:
4908
+ * 3a) By calling current.stopEditing();
4863
4909
* this shall be followed by some resolution.
4864
- * 4b ) By executing MM.Command.{Finish,Cancel};
4865
- * these call 4a internally.
4866
- * 4c ) By blurring the item itself (by selecting another);
4867
- * this calls MM.Command.Finish (4b ).
4868
- * 4b ) By blurring the currentElement;
4869
- * this calls MM.Command.Finish (4b ).
4910
+ * 3b ) By executing MM.Command.{Finish,Cancel};
4911
+ * these call 3a internally.
4912
+ * 3c ) By blurring the item itself (by selecting another);
4913
+ * this calls MM.Command.Finish (3b ).
4914
+ * 3b ) By blurring the currentElement;
4915
+ * this calls MM.Command.Finish (3b ).
4870
4916
*
4871
4917
*/
4872
4918
MM . App = {
@@ -4912,11 +4958,11 @@ MM.App = {
4912
4958
} ,
4913
4959
4914
4960
select : function ( item ) {
4915
- if ( this . current && this . current != item ) { this . current . blur ( ) ; }
4961
+ if ( this . current && this . current != item ) { this . current . deselect ( ) ; }
4916
4962
this . current = item ;
4917
- this . current . focus ( ) ;
4963
+ this . current . select ( ) ;
4918
4964
} ,
4919
-
4965
+
4920
4966
adjustFontSize : function ( diff ) {
4921
4967
this . _fontSize = Math . max ( 30 , this . _fontSize + 10 * diff ) ;
4922
4968
this . _port . style . fontSize = this . _fontSize + "%" ;
@@ -4966,6 +5012,7 @@ MM.App = {
4966
5012
MM . Keyboard . init ( ) ;
4967
5013
MM . Menu . init ( this . _port ) ;
4968
5014
MM . Mouse . init ( this . _port ) ;
5015
+ MM . Clipboard . init ( ) ;
4969
5016
4970
5017
window . addEventListener ( "resize" , this ) ;
4971
5018
window . addEventListener ( "beforeunload" , this ) ;
0 commit comments