version update
[4Free-FSE.git] / src / character-inserter.ts
blobef02d9c7788f8c46ddafcddd5668c7a17af0511c
1 class CharacterInserter extends FeatureInterface{
2         
3         use_kita:boolean;
4         use_yen:boolean;
5         
6                 kita_character:string = "キタ━━━(゚∀゚)━━━!!";
7 kita_hash_color:string = "#444444"
8                 yen_character:string = "¥";
9 yen_hash_color:string = "#9370DB";
10         constructor(use_kita:boolean, use_yen:boolean){
11                 super();
12                 this.use_yen = use_yen;
13                 this.use_kita = use_kita;
14                 
15                 this.retrieveStates();
16                 this.init();
17                 this.activate();
18         }
19         
20         init():void{
21                 this.addStyle();
22                 this.hotkeyListeners();
23         }
24         activate():void{                        
25                 console.log("4F-FSE: CharacterInserter Active - " + (this.use_kita ? "Character Coloring+" : "") + (this.use_yen ?" Line Coloring" : ""));
26         }
27         decideAction(node:any):void{
28                 if(node.tagName == "BLOCKQUOTE")
29                         this.colorCharacters(node);
30         }
31         retrieveStates():void{
32                 if (localStorage.getItem("Yen_Character") === undefined || localStorage.getItem("Yen_Character") === null) this.yen_character = "¥";
33                 else this.yen_character = localStorage.getItem("Yen_Character");
34                                 if (localStorage.getItem("Yen_Color") === undefined || localStorage.getItem("Yen_Color")  === null) this.yen_hash_color = "#9370DB";
35                 else this.yen_hash_color = localStorage.getItem("Yen_Color");
36                                 if (localStorage.getItem("Kita_Character") === undefined || localStorage.getItem("Kita_Character") === null) this.kita_character = "キタ━━━(゚∀゚)━━━!!";
37                 else this.kita_character = localStorage.getItem("Kita_Character");
38                                 if (localStorage.getItem("Kita_Color") === undefined || localStorage.getItem("Kita_Color") === null)this.kita_hash_color = "#444444";
39                 else this.kita_hash_color = localStorage.getItem("Kita_Color");
40         }
41         storeStates(...items:any[]):void{}
43         
44         //color styling
45         addStyle():void{
46                 var style = document.createElement("STYLE");
47                 style.innerHTML = ".the_m_word{color:" + this.yen_hash_color + "} \n.the_k_word{color:" + this.kita_hash_color + "}";
48                 document.head.appendChild(style);
49         }
51         //hotkeys for kita and yen
52          hotkeyListeners():void{
53                 var listener_obj = {};
54                 
55                 window.addEventListener("keydown", (e)=>{
56                         listener_obj[e.keyCode] = true;
58                         var node = document.activeElement;
59                         if ((listener_obj[17] || listener_obj[91]) && listener_obj[75]){
60                                 e.preventDefault();
61                                 this.insertAtPos(node, this.kita_character);
62                         }
63                         if ((listener_obj[17] || listener_obj[91]) && listener_obj[220]){
64                                 e.preventDefault();
65                                 this.insertAtPos(node, this.yen_character);
66                         }
67                 }, {passive:false, capture:false, once:false});
69                 window.addEventListener("keyup", (e) => {
70                         listener_obj[e.keyCode] = false;
71                 }, {passive:false, capture:false, once:false});
72         }
74         insertAtPos(node, buzzwords):void{
75                 var sel_start = node.selectionStart;
76                 var sel_end = node.selectionEnd;
78                 var node_text = node.value;
79                 node.value = node_text.substr(0, sel_start) + buzzwords + node_text.substr(sel_end);
81                 node.selectionStart = sel_start + buzzwords.length;
82                 node.selectionEnd = sel_end + buzzwords.length;
83         }
84         
85 //insertion logic
86         colorCharacters(root){
87                 if(root.nodeType !== Node.ELEMENT_NODE){
88                         return;
89                 }       
90                         if(root.textContent.indexOf(this.yen_character) <= -1 && root.textContent.indexOf(this.kita_character) <= -1){
91                                 return;
92                         }
93                         
94                 var wbr = root.getElementsByTagName('WBR');
95         var wbr_len = wbr.length;
96         var wbr_indices = Array();
97         function previousIndex(len){
98             if(len > 0) return wbr_indices[len-1];
99             else return 0;
100         }
101         for(var wbr_item = 0;wbr_item < wbr_len; wbr_item++){
102             wbr_indices.push(wbr[wbr_item].previousSibling.length + previousIndex(wbr_item));
103         }
104         while(wbr.length){
105             root.removeChild(wbr[wbr.length-1]);
106         }
107         root.normalize();
108                 
109                 var txtItterator = document.createNodeIterator(root, NodeFilter.SHOW_TEXT);
110                 var text_node;
111                 while((text_node = txtItterator.nextNode())){
112                         //disregard text inside of A tag links and already colored text
113                         if(text_node.parentNode.tagName == "A" || /the_[a-z]_word/g.test(text_node.parentNode.className)) continue;
114                         this.setColor(text_node, txtItterator);
115                 }
116                 
117         //restart and add back the wbr
118         var txtItterator = document.createNodeIterator(root, NodeFilter.SHOW_TEXT);
119         var text_node;
120         while ((text_node = txtItterator.nextNode())) {
121             //disregard text inside of A tag links and already colored text
122             if (text_node.parentNode.tagName == "A")
123                 continue;
124             wbr_indices = this.addWBR(text_node, txtItterator, wbr_indices);
125         }
127         }
128         
129         //reinsert <wbr>
130          addWBR(text_node, txtItterator, wbr_indices){
131         wbr_indices[0] = wbr_indices[0] - text_node.length;
132         if(wbr_indices[0] <= 0){
133             var split_node = text_node.splitText(text_node.length + wbr_indices[0]);
134             var wbr = document.createElement("WBR");
135             split_node.parentNode.insertBefore(wbr, text_node.nextSibling);
136             wbr_indices.shift();
137         }
138         return wbr_indices;
139     }
141         //give color to text inside of nodes.
142         // first scan for yen symbols and then check the front of the text for not nested kita.
143         setColor(text_node, txtItterator):void{
144                 var start_text_node = text_node;
145                 var result;
146                 var yen_node:boolean = this.use_kita ? this.searchYen(text_node) : false;
147                 if(yen_node != false){
148                         //jump to internal node
149                         text_node = txtItterator.nextNode();
150                         //scan for nested kita
151                         do{
152                                 result = this.use_kita ? this.searchKita(text_node) : false;
153                                 if(result != false){
154                                         //jump foreward to point after kita inserted
155                                         text_node = txtItterator.nextNode();
156                                         text_node = txtItterator.nextNode();
157                                 }
158                         } while(result != false);
159                 }
160                 //scan for outside kita from start
161                 do{
162                         result = this.use_kita ? this.searchKita(start_text_node) : false;
163                         start_text_node = result.nextSibling;
164                 }while(result != false && start_text_node !== undefined);
166         }
168         //find the location of a yen, split the text from above that position, create a span element and place split into this span.
169         //Then take the initial text node and insert into it from after the text node.
170         searchYen (text_node):any{
171                 var yenIndex = text_node.textContent.indexOf(this.yen_character);
172                 if(yenIndex > -1){
173                         var splitNode = text_node.splitText(yenIndex);
175                         var span = document.createElement('span');
176                         span.className = "the_m_word";
178                         span.appendChild(splitNode);
179                         text_node.parentNode.insertBefore(span, text_node.nextSibling);
181                         return span;
182                 }
183                 return false;
184         }
186         //find the location of a kita, isolate it by splitting from the point where the kita ends and the point where it begins.
187         //Now that there are 3 text nodes, take the middle one from the start position index split, add the text which goes to the point of the rightmost split,
188         //then refer back to the parent and place it after the leftmost string.
189         searchKita (text_node):any{
190                 var kIndex = text_node.textContent.indexOf(this.kita_character);
191                 if(kIndex > -1){
192                         var far_split_note =  text_node.splitText(kIndex + this.kita_character.length);
193                         var splitNode = text_node.splitText(kIndex);
195                         var span = document.createElement('span');
196                         span.className = "the_k_word";
198                         span.appendChild(splitNode);
199                         text_node.parentNode.insertBefore(span, text_node.nextSibling);
200                         return span;
201                 }
202                 return false;
203         }