@teachinglab/omd 0.7.13 → 0.7.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/canvas/core/omdCanvas.js +76 -5
- package/canvas/tools/PointerTool.js +1280 -29
- package/jsvg/jsvg.js +272 -36
- package/jsvg/package.json +13 -0
- package/package.json +1 -1
package/jsvg/jsvg.js
CHANGED
|
@@ -725,84 +725,320 @@ export class jsvgTextLine extends jsvgObject
|
|
|
725
725
|
}
|
|
726
726
|
|
|
727
727
|
|
|
728
|
-
// ================ jsvgTextBox
|
|
728
|
+
// ================ jsvgTextBox ================================= //
|
|
729
729
|
|
|
730
730
|
export class jsvgTextBox extends jsvgGroup
|
|
731
731
|
{
|
|
732
|
-
constructor()
|
|
732
|
+
constructor( options = {} )
|
|
733
733
|
{
|
|
734
734
|
super();
|
|
735
735
|
|
|
736
736
|
this.text = "";
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
this.
|
|
740
|
-
|
|
741
|
-
this.
|
|
742
|
-
this.
|
|
737
|
+
this._useForeignObject = options.useForeignObject === true;
|
|
738
|
+
this._textAlign = "left";
|
|
739
|
+
this._verticalCenter = false;
|
|
740
|
+
this._lineHeight = null;
|
|
741
|
+
this._fontSize = 16;
|
|
742
|
+
this._fontFamily = "Arial, Helvetica, sans-serif";
|
|
743
|
+
this._fontWeight = "normal";
|
|
744
|
+
this._fontColor = "black";
|
|
745
|
+
|
|
746
|
+
const ns = 'http://www.w3.org/2000/svg';
|
|
747
|
+
|
|
748
|
+
if ( this._useForeignObject )
|
|
749
|
+
{
|
|
750
|
+
this.foreignObject = document.createElementNS( ns, 'foreignObject');
|
|
751
|
+
this.foreignObject.style.backgroundColor = 'none';
|
|
752
|
+
this.svgObject.appendChild( this.foreignObject );
|
|
743
753
|
|
|
744
|
-
|
|
745
|
-
|
|
754
|
+
this.div = document.createElement('div');
|
|
755
|
+
this.foreignObject.appendChild( this.div );
|
|
756
|
+
}
|
|
757
|
+
else
|
|
758
|
+
{
|
|
759
|
+
this.textElement = document.createElementNS( ns, 'text');
|
|
760
|
+
this.textElement.setAttribute('x', '0');
|
|
761
|
+
this.textElement.setAttribute('y', '0');
|
|
762
|
+
this.textElement.setAttribute('fill', this._fontColor);
|
|
763
|
+
this.textElement.setAttribute('xml:space', 'preserve');
|
|
764
|
+
this.textElement.style.fontFamily = this._fontFamily;
|
|
765
|
+
this.textElement.style.fontSize = this._fontSize.toString() + "px";
|
|
766
|
+
this.svgObject.appendChild( this.textElement );
|
|
767
|
+
}
|
|
746
768
|
|
|
747
769
|
this.setWidthAndHeight( 200,100 );
|
|
748
770
|
}
|
|
749
771
|
|
|
750
|
-
|
|
772
|
+
_getLineHeight()
|
|
773
|
+
{
|
|
774
|
+
return this._lineHeight || this._fontSize;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
_getTextX()
|
|
778
|
+
{
|
|
779
|
+
if ( this._textAlign === "center" )
|
|
780
|
+
return this.width / 2;
|
|
781
|
+
if ( this._textAlign === "right" || this._textAlign === "end" )
|
|
782
|
+
return this.width;
|
|
783
|
+
return 0;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
_applyTextAnchor()
|
|
787
|
+
{
|
|
788
|
+
if ( !this.textElement ) return;
|
|
789
|
+
if ( this._textAlign === "center" )
|
|
790
|
+
this.textElement.setAttribute("text-anchor", "middle");
|
|
791
|
+
else if ( this._textAlign === "right" || this._textAlign === "end" )
|
|
792
|
+
this.textElement.setAttribute("text-anchor", "end");
|
|
793
|
+
else
|
|
794
|
+
this.textElement.setAttribute("text-anchor", "start");
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
_parseHtmlToLines( html )
|
|
798
|
+
{
|
|
799
|
+
const hasMarkup = /<\s*(sup|sub|br)\b/i.test( html || "" );
|
|
800
|
+
if ( !hasMarkup )
|
|
801
|
+
return [ [ { text: html || "", mode: null } ] ];
|
|
802
|
+
|
|
803
|
+
const container = document.createElement('div');
|
|
804
|
+
container.innerHTML = html || "";
|
|
805
|
+
const lines = [ [] ];
|
|
806
|
+
|
|
807
|
+
const walk = (node, mode) => {
|
|
808
|
+
if ( node.nodeType === 3 )
|
|
809
|
+
{
|
|
810
|
+
const value = node.nodeValue || "";
|
|
811
|
+
if ( value.length > 0 )
|
|
812
|
+
lines[ lines.length - 1 ].push({ text: value, mode: mode });
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
if ( node.nodeType !== 1 ) return;
|
|
816
|
+
const tag = node.tagName.toLowerCase();
|
|
817
|
+
if ( tag === "br" )
|
|
818
|
+
{
|
|
819
|
+
lines.push([]);
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
let nextMode = mode;
|
|
823
|
+
if ( tag === "sup" ) nextMode = "sup";
|
|
824
|
+
if ( tag === "sub" ) nextMode = "sub";
|
|
825
|
+
for ( let i = 0; i < node.childNodes.length; i++ )
|
|
826
|
+
walk( node.childNodes[i], nextMode );
|
|
827
|
+
};
|
|
828
|
+
|
|
829
|
+
for ( let i = 0; i < container.childNodes.length; i++ )
|
|
830
|
+
walk( container.childNodes[i], null );
|
|
831
|
+
|
|
832
|
+
if ( lines.length > 1 && lines[ lines.length - 1 ].length === 0 )
|
|
833
|
+
lines.pop();
|
|
834
|
+
|
|
835
|
+
return lines;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
_renderSvgText( html )
|
|
839
|
+
{
|
|
840
|
+
if ( !this.textElement ) return;
|
|
841
|
+
|
|
842
|
+
const ns = 'http://www.w3.org/2000/svg';
|
|
843
|
+
const lines = this._parseHtmlToLines( html );
|
|
844
|
+
const lineHeight = this._getLineHeight();
|
|
845
|
+
const blockHeight = lineHeight * lines.length;
|
|
846
|
+
const startY = this._verticalCenter ? Math.max(0, (this.height - blockHeight) / 2) : 0;
|
|
847
|
+
const startX = this._getTextX();
|
|
848
|
+
|
|
849
|
+
while ( this.textElement.firstChild )
|
|
850
|
+
this.textElement.removeChild( this.textElement.firstChild );
|
|
851
|
+
|
|
852
|
+
this._applyTextAnchor();
|
|
853
|
+
this.textElement.setAttribute('dominant-baseline', 'hanging');
|
|
854
|
+
|
|
855
|
+
for ( let lineIndex = 0; lineIndex < lines.length; lineIndex++ )
|
|
856
|
+
{
|
|
857
|
+
const line = lines[lineIndex];
|
|
858
|
+
if ( line.length === 0 )
|
|
859
|
+
line.push({ text: "", mode: null });
|
|
860
|
+
|
|
861
|
+
for ( let segIndex = 0; segIndex < line.length; segIndex++ )
|
|
862
|
+
{
|
|
863
|
+
const seg = line[segIndex];
|
|
864
|
+
const tspan = document.createElementNS( ns, 'tspan' );
|
|
865
|
+
tspan.textContent = seg.text;
|
|
866
|
+
|
|
867
|
+
if ( seg.mode === "sup" )
|
|
868
|
+
{
|
|
869
|
+
tspan.setAttribute("baseline-shift", "super");
|
|
870
|
+
tspan.setAttribute("font-size", "0.7em");
|
|
871
|
+
}
|
|
872
|
+
else if ( seg.mode === "sub" )
|
|
873
|
+
{
|
|
874
|
+
tspan.setAttribute("baseline-shift", "sub");
|
|
875
|
+
tspan.setAttribute("font-size", "0.7em");
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
if ( segIndex === 0 )
|
|
879
|
+
{
|
|
880
|
+
tspan.setAttribute("x", startX);
|
|
881
|
+
if ( lineIndex === 0 )
|
|
882
|
+
tspan.setAttribute("y", startY);
|
|
883
|
+
else
|
|
884
|
+
tspan.setAttribute("dy", lineHeight);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
this.textElement.appendChild( tspan );
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
_updateSvgLayout()
|
|
893
|
+
{
|
|
894
|
+
if ( this.textElement )
|
|
895
|
+
this._renderSvgText( this.text );
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
setText( T )
|
|
899
|
+
{
|
|
900
|
+
this.text = T || "";
|
|
901
|
+
if ( this._useForeignObject )
|
|
902
|
+
this.div.innerHTML = this.text;
|
|
903
|
+
else
|
|
904
|
+
this._renderSvgText( this.text );
|
|
905
|
+
}
|
|
751
906
|
|
|
752
907
|
getText() { return this.text; }
|
|
753
908
|
|
|
754
909
|
setStyle( S ) // for style setting with CSS
|
|
755
910
|
{
|
|
756
|
-
this.
|
|
757
|
-
|
|
911
|
+
if ( this._useForeignObject )
|
|
912
|
+
{
|
|
913
|
+
this.div.className = S;
|
|
914
|
+
this.div.style.position = 'fixed'; // for safari
|
|
915
|
+
}
|
|
916
|
+
else if ( this.textElement )
|
|
917
|
+
{
|
|
918
|
+
this.textElement.setAttribute('class', S);
|
|
919
|
+
}
|
|
758
920
|
};
|
|
759
921
|
|
|
760
|
-
setFontFamily( F )
|
|
922
|
+
setFontFamily( F )
|
|
923
|
+
{
|
|
924
|
+
this._fontFamily = F;
|
|
925
|
+
if ( this._useForeignObject )
|
|
926
|
+
this.div.style.fontFamily = F;
|
|
927
|
+
else if ( this.textElement )
|
|
928
|
+
this.textElement.style.fontFamily = F;
|
|
929
|
+
}
|
|
761
930
|
|
|
762
|
-
setFontSize( S )
|
|
931
|
+
setFontSize( S )
|
|
932
|
+
{
|
|
933
|
+
this._fontSize = S;
|
|
934
|
+
if ( this._useForeignObject )
|
|
935
|
+
this.div.style.fontSize = S.toString() + "px";
|
|
936
|
+
else if ( this.textElement )
|
|
937
|
+
{
|
|
938
|
+
this.textElement.style.fontSize = S.toString() + "px";
|
|
939
|
+
this._updateSvgLayout();
|
|
940
|
+
}
|
|
941
|
+
}
|
|
763
942
|
|
|
764
|
-
setLineHeight( H )
|
|
943
|
+
setLineHeight( H )
|
|
944
|
+
{
|
|
945
|
+
this._lineHeight = H;
|
|
946
|
+
if ( this._useForeignObject )
|
|
947
|
+
this.div.style.lineHeight = H + 'px';
|
|
948
|
+
else
|
|
949
|
+
this._updateSvgLayout();
|
|
950
|
+
}
|
|
765
951
|
|
|
766
|
-
setFontWeight( W )
|
|
952
|
+
setFontWeight( W )
|
|
953
|
+
{
|
|
954
|
+
this._fontWeight = W;
|
|
955
|
+
if ( this._useForeignObject )
|
|
956
|
+
this.div.style.fontWeight = W;
|
|
957
|
+
else if ( this.textElement )
|
|
958
|
+
this.textElement.style.fontWeight = W;
|
|
959
|
+
}
|
|
767
960
|
|
|
768
|
-
setFontColor( C )
|
|
961
|
+
setFontColor( C )
|
|
962
|
+
{
|
|
963
|
+
this._fontColor = C;
|
|
964
|
+
if ( this._useForeignObject )
|
|
965
|
+
this.div.style.color = C;
|
|
966
|
+
else if ( this.textElement )
|
|
967
|
+
this.textElement.setAttribute('fill', C);
|
|
968
|
+
}
|
|
769
969
|
|
|
770
|
-
setAlignment( A )
|
|
970
|
+
setAlignment( A )
|
|
971
|
+
{
|
|
972
|
+
this._textAlign = A;
|
|
973
|
+
if ( this._useForeignObject )
|
|
974
|
+
this.div.style.textAlign = A;
|
|
975
|
+
else
|
|
976
|
+
this._updateSvgLayout();
|
|
977
|
+
}
|
|
771
978
|
|
|
772
979
|
setVerticalCentering()
|
|
773
980
|
{
|
|
774
|
-
this.
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
981
|
+
if ( this._useForeignObject )
|
|
982
|
+
{
|
|
983
|
+
this.div.style.display = "flex";
|
|
984
|
+
this.div.style.flexFlow = "column"
|
|
985
|
+
this.div.style.justifyContent = "center";
|
|
986
|
+
this.div.style.alignItems = "center";
|
|
987
|
+
}
|
|
988
|
+
else
|
|
989
|
+
{
|
|
990
|
+
this._verticalCenter = true;
|
|
991
|
+
this._updateSvgLayout();
|
|
992
|
+
}
|
|
778
993
|
}
|
|
779
994
|
|
|
780
995
|
makeEditable()
|
|
781
996
|
{
|
|
782
|
-
this.
|
|
783
|
-
|
|
997
|
+
if ( this._useForeignObject )
|
|
998
|
+
{
|
|
999
|
+
this.div.style.contentEditable = 'true';
|
|
1000
|
+
this.div.onclick = function() { console.log("here"); this.focus(); };
|
|
1001
|
+
}
|
|
784
1002
|
}
|
|
785
1003
|
|
|
786
|
-
setBorderWidthAndColor( width, color )
|
|
1004
|
+
setBorderWidthAndColor( width, color )
|
|
1005
|
+
{
|
|
1006
|
+
if ( this._useForeignObject )
|
|
1007
|
+
this.div.style.border = width + "px solid " + color;
|
|
1008
|
+
}
|
|
787
1009
|
|
|
788
1010
|
setWidth( W )
|
|
789
1011
|
{
|
|
790
1012
|
this.width = W;
|
|
791
|
-
if ( this.
|
|
792
|
-
|
|
1013
|
+
if ( this._useForeignObject )
|
|
1014
|
+
{
|
|
1015
|
+
if ( this.div )
|
|
1016
|
+
this.div.style.width = W + 'px';
|
|
793
1017
|
|
|
794
|
-
|
|
795
|
-
|
|
1018
|
+
if ( this.foreignObject )
|
|
1019
|
+
this.foreignObject.setAttribute('width', W );
|
|
1020
|
+
}
|
|
1021
|
+
else
|
|
1022
|
+
{
|
|
1023
|
+
this._updateSvgLayout();
|
|
1024
|
+
}
|
|
796
1025
|
}
|
|
797
1026
|
|
|
798
1027
|
setHeight( H )
|
|
799
1028
|
{
|
|
800
1029
|
this.height = H;
|
|
801
|
-
if ( this.
|
|
802
|
-
|
|
1030
|
+
if ( this._useForeignObject )
|
|
1031
|
+
{
|
|
1032
|
+
if ( this.div )
|
|
1033
|
+
this.div.style.height = H + 'px';
|
|
803
1034
|
|
|
804
|
-
|
|
805
|
-
|
|
1035
|
+
if ( this.foreignObject )
|
|
1036
|
+
this.foreignObject.setAttribute('height', H );
|
|
1037
|
+
}
|
|
1038
|
+
else
|
|
1039
|
+
{
|
|
1040
|
+
this._updateSvgLayout();
|
|
1041
|
+
}
|
|
806
1042
|
}
|
|
807
1043
|
}
|
|
808
1044
|
|
|
@@ -814,7 +1050,7 @@ export class jsvgTextInput extends jsvgTextBox
|
|
|
814
1050
|
{
|
|
815
1051
|
constructor()
|
|
816
1052
|
{
|
|
817
|
-
super();
|
|
1053
|
+
super({ useForeignObject: true });
|
|
818
1054
|
|
|
819
1055
|
this.callback = null;
|
|
820
1056
|
|
|
@@ -861,7 +1097,7 @@ export class jsvgTextArea extends jsvgTextBox
|
|
|
861
1097
|
{
|
|
862
1098
|
constructor()
|
|
863
1099
|
{
|
|
864
|
-
super();
|
|
1100
|
+
super({ useForeignObject: true });
|
|
865
1101
|
|
|
866
1102
|
this.callback = null;
|
|
867
1103
|
|