Statistics
| Branch: | Revision:

blinker / firefox.plugin / data / functions.js @ a03cd52e

History | View | Annotate | Download (63.492 KB)

1 a03cd52e Thies Pfeiffer
/*
2
 * Copyright 2015 Thies Pfeiffer and Dimitri Heil
3
 * Blinker is distributed under the terms of the GNU General Public License
4
 * 
5
 * This file is part of Blinker.
6
 * 
7
 * Blinker is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 * 
12
 * Blinker is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU General Public License for more details.
16
 * 
17
 * You should have received a copy of the GNU General Public License
18
 * along with Blinker. If not, see <http://www.gnu.org/licenses/>.
19
 */
20
 
21
var gazeFunctions = {
22
        /*
23
        *        open a given url in a given target (_self / _blank)
24
        */
25
        openURL: function(url, target) {
26
                //console.log("functions.js :: " + "gazeFunctions.openURL()" + ", url: " + url + ", target: " + target);
27
                $("#wheelSelector").css("display", "none");
28
                edgeFunctions.clearDivs();
29
                $("#wheelSelector").empty();
30
                wheelSelectorShowing = false;
31
                window.open(url, target);
32
        },
33
        /*
34
        *        Positions the gazeLinkOption-fields according to the number of gazeConfirmations-fileds and the gazeLinks-Div position
35
        *
36
        *        @gazeLinkNumber: the number of the gazeLink the gazeLinkOptions should be appended to
37
        */
38
        showGazeLinkOptions: function(gazeLinkNumber) {
39
                //console.log("functions.js :: " + "gazeFunctions.showGazeLinkOptions()" + ", gazeLinkNumber: " + gazeLinkNumber);
40
                gazeFunctions.hideGazeLinkOptions();
41
                //console.log("gazeLinkNumber: "+ gazeLinkNumber);
42
43
                var selectedDivOffset = $("#gazeLinkNum_" + gazeLinkNumber).offset();
44
                //console.log("selectedDivOffset X: "+selectedDivOffset.left);
45
                //console.log("selectedDivOffset Y: "+selectedDivOffset.top);
46
47
                if (blickBrowserSettings.gazeConfirmationSteps === 0) {
48
                        $("#leftGazeOption_" + gazeLinkNumber).css("left", (gazeInformation.gazeLinksPosition.x - $("#leftGazeOption_" + gazeLinkNumber).width() - window.scrollX) - 1 + "px");
49
                        $("#leftGazeOption_" + gazeLinkNumber).css("top", (gazeInformation.gazeLinksPosition.y + selectedDivOffset.top - $("#gazeLinks").offset().top) + "px");
50
                        $("#leftGazeOption_" + gazeLinkNumber).css("height", blickBrowserSettings.gazeConfirmationSize+"px");
51
                        $("#leftGazeOption_" + gazeLinkNumber).css("width", blickBrowserSettings.gazeConfirmationSize+"px");
52
53
54
55
56
                        $("#rightGazeOption_" + gazeLinkNumber).css("left", (gazeInformation.gazeLinksPosition.x + $("#gazeLinks").width() - window.scrollX) - 1 + "px");
57
                        $("#rightGazeOption_" + gazeLinkNumber).css("top", (gazeInformation.gazeLinksPosition.y + selectedDivOffset.top - $("#gazeLinks").offset().top) + "px");
58
                        $("#rightGazeOption_" + gazeLinkNumber).css("height", blickBrowserSettings.gazeConfirmationSize+"px");
59
                        $("#rightGazeOption_" + gazeLinkNumber).css("width", blickBrowserSettings.gazeConfirmationSize+"px");
60
61
62
                        $('.gazeLinkOption').stop();
63
                        $("#leftGazeOption_" + gazeLinkNumber).fadeIn();
64
                        $("#rightGazeOption_" + gazeLinkNumber).fadeIn();
65
                        //gazeInformation.gazeLinks[gazeLinkNumber]
66
                } else {
67
                        //console.log("GAZEPOS X: "+gazeInformation.gazeLinksPosition.x);
68
                        $("#leftGazeConfirmation_" + gazeLinkNumber + "_0").css("left", (gazeInformation.gazeLinksPosition.x - $("#leftGazeOption_" + gazeLinkNumber).width() - window.scrollX) - 1 + "px");
69
                        $("#leftGazeConfirmation_" + gazeLinkNumber + "_0").css("top", (gazeInformation.gazeLinksPosition.y + selectedDivOffset.top - $("#gazeLinks").offset().top) + "px");
70
                        $("#leftGazeConfirmation_" + gazeLinkNumber + "_0").css("height", blickBrowserSettings.gazeConfirmationSize+"px");
71
                        $("#leftGazeConfirmation_" + gazeLinkNumber + "_0").css("width", blickBrowserSettings.gazeConfirmationSize+"px");
72
73
74
                        $("#rightGazeConfirmation_" + gazeLinkNumber + "_0").css("left", (gazeInformation.gazeLinksPosition.x + $("#gazeLinks").width() - window.scrollX) - 1 + "px");
75
                        $("#rightGazeConfirmation_" + gazeLinkNumber + "_0").css("top", (gazeInformation.gazeLinksPosition.y + selectedDivOffset.top - $("#gazeLinks").offset().top) + "px");
76
                        $("#rightGazeConfirmation_" + gazeLinkNumber + "_0").css("height", blickBrowserSettings.gazeConfirmationSize+"px");
77
                        $("#rightGazeConfirmation_" + gazeLinkNumber + "_0").css("width", blickBrowserSettings.gazeConfirmationSize+"px");
78
79
80
                        $('.gazeLinkOption').stop();
81
                        $("#leftGazeConfirmation_" + gazeLinkNumber + "_0").fadeIn();
82
                        $("#rightGazeConfirmation_" + gazeLinkNumber + "_0").fadeIn();
83
                }
84
85
        },
86
        /*
87
        *        Hide all gazeLinkOption-fields
88
        */
89
        hideGazeLinkOptions: function() {
90
                //console.log("functions.js :: " + "gazeFunctions.hideGazeLinkOptions()");
91
92
                $(".gazeLinkOption").css("display", "none");
93
94
        },
95
        /*
96
        *        Check for links at the current gazePosition
97
        */
98
        checkForLinks: function() {
99
                /*if (!blickBrowserSettings.autoReadingMode) {*/
100
                        if (!blickBrowserSettings.explicitMode) {
101
                                if (!gazeCorrectionMode) {
102
                                        //console.log("functions.js :: "+"gazeFunctions.checkForLinks()" );
103
                                        if ($("#noFocusHider").css("display") == "none") {
104
                                                //console.log("functions.js :: "+"gazeFunctions.checkForLinks()"+" :: #noFocusHider is not displayed" );
105
                                                if (!linkCheckRunning) {
106
                                                        //console.log("functions.js :: "+"gazeFunctions.checkForLinks()"+" :: linkCheckRunning is false" );
107
                                                        if (!controlBarShowing) {
108
                                                                //console.log("functions.js :: "+"gazeFunctions.checkForLinks()"+" :: controlBarShowing is false" );
109
                                                                if (!wheelSelectorShowing) {
110
                                                                        //console.log("functions.js :: "+"gazeFunctions.checkForLinks()"+" :: wheelSelectorShowing is false" );
111
                                                                        if (!gazeLinksShowing) {
112
                                                                                //console.log("functions.js :: "+"gazeFunctions.checkForLinks()"+" :: gazeLinksShowing is false" );
113
114
                                                                                //console.log("Check for links initiated");
115
                                                                                
116
                                                                                $("#gazeLinks").css("display", "none");
117
                                                                                $("#closeGazeLinks").css("display", "none");
118
                                                                                $("#itemSelector").css("display", "none");
119
                                                                                $("#gazeLinks").empty();
120
121
122
                                                                                //getLinksFromElementBelow
123
                                                                                if (blickBrowserSettings.getLinksFromElementBelow === true) {
124
                                                                                        linkCheckRunning = true;
125
                                                                                        findLinksInElementBelow();
126
                                                                                        linkCheckRunning = false;
127
                                                                                
128
129
                                                                                }
130
131
                                                                                //getLinksFromArea
132
                                                                                if (blickBrowserSettings.getLinksFromArea === true) {
133
                                                                                        linkCheckRunning = true;                                                                                
134
                                                                                        findLinksInAreaFast();
135
                                                                                        linkCheckRunning = false;
136
                                                                                }
137
138
139
140
141
                                                                        } else {
142
                                                                                //console.log("functions.js :: " + "gazeFunctions.checkForLinks()" + " :: gazeLinksShowing: " + gazeLinksShowing);
143
                                                                        }
144
                                                                } else {
145
                                                                        //console.log("functions.js :: " + "gazeFunctions.checkForLinks()" + " :: wheelSelectorShowing: " + wheelSelectorShowing);
146
                                                                }
147
                                                        } else {
148
                                                                //console.log("functions.js :: " + "gazeFunctions.checkForLinks()" + " :: linkCheckRunning: " + linkCheckRunning);
149
                                                        }
150
                                                } else {
151
                                                        //console.log("functions.js :: " + "gazeFunctions.checkForLinks()" + " :: gazeCorrectionMode: " + gazeCorrectionMode);
152
                                                }
153
                                        }
154
                                } else {
155
                                        //console.log("functions.js :: " + "gazeFunctions.checkForLinks()" + " :: #noFocusHider: " + $("#noFocusHider").css("display"));
156
                                }
157
                        } else {
158
                                //console.log("functions.js :: " + "gazeFunctions.checkForLinks()" + " :: explicitMode: " + blickBrowserSettings.explicitMode);
159
                        /*}
160
                } else {*/
161
                        //console.log("functions.js :: " + "gazeFunctions.checkForLinks()" + " :: autoReadingMode: " + blickBrowserSettings.autoReadingMode);
162
                }
163
        },
164
165
        /*
166
        *        Show gazeConfirmations according to it's id and the selected gazeLink and gazeLink-Div position
167
        *
168
        *        @id: the id of the gazeOption or gazeConfirmation that should be positioned
169
        */
170
        showConfirmationDiv: function(id) {
171
                console.log("functions.js :: " + "gazeFunctionss.showConfirmationDiv() ID:" + id);
172
                var selectedDivOffset;
173
                var split;
174
                /*
175
                *        if it is a gazeOption
176
                */
177
                if (id.toLowerCase().indexOf("option") > -1) {
178
                        split = id.split("_");
179
                        selectedDivOffset = $("#gazeLinkNum_" + parseInt(split[1])).offset();
180
181
                        if (id.indexOf("left") > -1) {
182
        
183
                                $("#" + id).css("left", (gazeInformation.gazeLinksPosition.x - window.scrollX - ((blickBrowserSettings.gazeConfirmationSteps + 1) * blickBrowserSettings.gazeConfirmationSize)) - 2 + "px");
184
185
                        } else if (id.indexOf("right") > -1) {
186
187
                                $("#" + id).css("left", (gazeInformation.gazeLinksPosition.x + $("#gazeLinks").width() - window.scrollX + (blickBrowserSettings.gazeConfirmationSteps * blickBrowserSettings.gazeConfirmationSize)) - 2 + "px");
188
                        }
189
190
191
                /*
192
                *        if it is a gazeConfirmation
193
                */
194
                } else {
195
                        split = id.split("_");
196
                        selectedDivOffset = $("#gazeLinkNum_" + parseInt(split[1])).offset();
197
198
                        if (split[0].indexOf("left") > -1) {
199
                                $("#" + id).css("left", (gazeInformation.gazeLinksPosition.x - window.scrollX - ((parseInt(split[2]) + 1) * blickBrowserSettings.gazeConfirmationSize)) - 2 + "px");
200
                        } else if (split[0].indexOf("right") > -1) {
201
                                $("#" + id).css("left", (gazeInformation.gazeLinksPosition.x + $("#gazeLinks").width() - window.scrollX + (parseInt(split[2]) * blickBrowserSettings.gazeConfirmationSize)) - 2 + "px");
202
203
204
                        }
205
206
                }
207
                //set the size according to the value in settings (gazeConfirmationSize)
208
                $("#" + id).width(blickBrowserSettings.gazeConfirmationSize);
209
                $("#" + id).height(blickBrowserSettings.gazeConfirmationSize);
210
211
                $("#" + id).css("top", (selectedDivOffset.top) + "px");
212
                $("#" + id).css("display", "block");
213
214
215
        },
216
217
        /*
218
        *         Show wheelSelector for gazeLink with a certain gazeLinkNumber (position in gazeLink array)
219
        */
220
        showWheelSelector: function(gazeLinkNumber) {                
221
                //console.log("functions.js :: " + "gazeFunctions.showWheelSelector()" + " gazeLinkNumber: " + gazeLinkNumber);
222
                //console.log("gazeLinksCount: "+gazeInformation.gazeLinks.length);
223
                if (!controlBarShowing) {
224
                        if (!wheelSelectorShowing) {
225
                                gazeInformation.currentElementFixatedAt = Date.now();
226
227
                                //let top = $( "#wheelSelector" ).css("top")+window.scrollY;
228
                                $("#wheelSelector").css("top", window.scrollY + (window.innerHeight * 0.1) + "px");
229
230
                                $("#wheelSelector").fadeIn();
231
                                wheelSelectorShowing = true;
232
233
                                /*
234
                                * APPEND MORE ELEMENTS INSIDE OF THE WHEELSELECTOR HERE [START]
235
                                */
236
237
                                var dataGazeString = '';        
238
                                dataGazeString = "{\"isFixated\":{\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();gazeFunctions[\\\"openURL\\\"](\\\"" + gazeInformation.gazeLinks[gazeLinkNumber].url + "\\\",\\\"_self\\\")\"}}";
239
                                $("#wheelSelector").append("<div id='wheelSelectorOpenHere' data-gaze='" + dataGazeString + "' class='wheelSelector' target='_self'></div");
240
                                $("#wheelSelectorOpenHere").append("<i data-gaze='" + dataGazeString + "' class='wheelSelectorIcon fa fa-folder-open-o'></i><p class=\"subtitle\">Open</p>");
241
242
243
                                dataGazeString = "{\"isFixated\":{\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();gazeFunctions[\\\"openURL\\\"](\\\"" + gazeInformation.gazeLinks[gazeLinkNumber].url + "\\\",\\\"_blank\\\")\"}}";
244
                                $("#wheelSelector").append("<div id='wheelSelectorOpenNew' data-gaze='" + dataGazeString + "' class='wheelSelector' target='_blank'></div>");
245
                                $("#wheelSelectorOpenNew").append("<i data-gaze='" + dataGazeString + "' class='wheelSelectorIcon fa fa-external-link'></i><p class=\"subtitle\">Open in new Tab</p></div>");
246
247
                                dataGazeString = "{\"isFixated\":{\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();blickBrowserSettings.bookmarks += \\\"" + gazeInformation.gazeLinks[gazeLinkNumber].name+"|"+gazeInformation.gazeLinks[gazeLinkNumber].url + ";\\\"; writeSettings();\"}}";
248
                                $("#wheelSelector").append("<div id='wheelSelectorAddBookmark' data-gaze='" + dataGazeString + "' class='wheelSelector'></div");
249
                                $("#wheelSelectorAddBookmark").append("<i data-gaze='" + dataGazeString + "' class='wheelSelectorIcon fa fa-star'></i><p class=\"subtitle\">Bookmark</p>");
250
251
                                
252
                                /*
253
                                * APPEND MORE ELEMENTS INSIDE OF THE WHEELSELECTOR HERE [END]
254
                                */
255
256
257
                                //arrange the wheelelements in a circle
258
                                arrangeWheelElements();
259
260
                                $("#wheelSelector").append("<div class='wheelSelector gazeLinkName'><br />" + (shortenString(gazeInformation.gazeLinks[gazeLinkNumber].name, 25) || shortenString(gazeInformation.gazeLinks[gazeLinkNumber].url, 25)) + "</div>");
261
262
                        } else {
263
                                $("#wheelSelector").css("display", "none");
264
                                $("#wheelSelector").empty();
265
                                wheelSelectorShowing = false;
266
                                gazeFunctions.showWheelSelector();
267
                        }
268
                }
269
        }
270
};
271
/*
272
*        shorten a string to a given length and return the shortened string, if it has no node opening brackets inside of it like an " <img [...]> " or something
273
*/
274
function shortenString(str, length) {
275
        //console.log("functions.js :: "+"shortenString()" + ", str:" +str +", length: "+length);
276
        if (str !== null) {
277
278
                if (str.toLowerCase().indexOf("<") > -1) {
279
280
                        //console.log("'<' - node opening bracket found in the name of a gaze link - not shortening it, because it could be an html node");
281
282
                        return str;
283
284
                }
285
286
                if (str.length < length) {
287
288
                        return str;
289
290
                } else {
291
292
                        return str.substring(0, length) + "...";
293
294
                }
295
296
        }
297
298
}
299
300
301
/*
302
*        Find links in area and only the 4 surrounding districts around the current gazePosition and put the found links into the gazeLink array
303
*/
304
function findLinksInAreaFast() {
305
        //console.log("functions.js :: " + "findLinksInAreaFast()");
306
        var fieldX = Math.floor(gazeInformation.x / fieldWidth);
307
        //console.log("2_FieldX: " + fieldX);
308
        var fieldY = Math.floor(gazeInformation.y / fieldHeight);
309
        //console.log("2_FieldY: " + fieldY);
310
311
        //TODO PARSE FIELDTOCHECK
312
313
        var xRest = gazeInformation.x % fieldWidth;
314
        var yRest = gazeInformation.y % fieldHeight;
315
316
        var positionX;
317
        var positionY;
318
        if (xRest >= (fieldWidth / 2)) {
319
                positionX = "right";
320
        } else {
321
                positionX = "left";
322
        }
323
324
        if (yRest >= (fieldHeight / 2)) {
325
                positionY = "bottom";
326
        } else {
327
                positionY = "top";
328
        }
329
330
        gazeInformation.gazeLinks = [];
331
        if (fieldX >= 0 && fieldY >= 0) {
332
                if (positionY == "top" && positionX == "left") {
333
334
                        if (checkField(fields[fieldX]) && checkField(fields[fieldX][fieldY])) {
335
                                parseField(fields[fieldX][fieldY]);
336
                        }
337
                        if (checkField(fields[fieldX - 1]) && checkField(fields[fieldX - 1][fieldY - 1])) {
338
                                parseField(fields[fieldX - 1][fieldY - 1]);
339
                        }
340
341
                        if (checkField(fields[fieldX]) && checkField(fields[fieldX][fieldY - 1])) {
342
                                parseField(fields[fieldX][fieldY - 1]);
343
                        }
344
345
                        if (checkField(fields[fieldX - 1]) && checkField(fields[fieldX - 1][fieldY])) {
346
                                parseField(fields[fieldX - 1][fieldY]);
347
                        }
348
349
                } else if (positionY == "top" && positionX == "right") {
350
                        if (checkField(fields[fieldX]) && checkField(fields[fieldX][fieldY])) {
351
                                parseField(fields[fieldX][fieldY]);
352
                        }
353
354
                        if (checkField(fields[fieldX + 1]) && checkField(fields[fieldX + 1][fieldY - 1])) {
355
                                parseField(fields[fieldX + 1][fieldY - 1]);
356
                        }
357
358
                        if (checkField(fields[fieldX]) && checkField(fields[fieldX][fieldY - 1])) {
359
                                parseField(fields[fieldX][fieldY - 1]);
360
                        }
361
362
                        if (checkField(fields[fieldX + 1]) && checkField(fields[fieldX + 1][fieldY])) {
363
                                parseField(fields[fieldX + 1][fieldY]);
364
                        }
365
                } else if (positionY == "bottom" && positionX == "left") {
366
                        if (checkField(fields[fieldX]) && checkField(fields[fieldX][fieldY])) {
367
                                parseField(fields[fieldX][fieldY]);
368
                        }
369
370
                        if (checkField(fields[fieldX - 1]) && checkField(fields[fieldX - 1][fieldY + 1])) {
371
                                parseField(fields[fieldX - 1][fieldY + 1]);
372
                        }
373
374
                        if (checkField(fields[fieldX - 1]) && checkField(fields[fieldX - 1][fieldY + 1])) {
375
                                parseField(fields[fieldX - 1][fieldY + 1]);
376
                        }
377
                        if (checkField(fields[fieldX - 1]) && checkField(fields[fieldX - 1][fieldY])) {
378
                                parseField(fields[fieldX - 1][fieldY]);
379
                        }
380
                } else if (positionY == "bottom" && positionX == "right") {
381
                        if (checkField(fields[fieldX]) && checkField(fields[fieldX][fieldY])) {
382
                                parseField(fields[fieldX][fieldY]);
383
                        }
384
                        if (checkField(fields[fieldX + 1]) && checkField(fields[fieldX + 1][fieldY + 1])) {
385
                                parseField(fields[fieldX + 1][fieldY + 1]);
386
                        }
387
                        if (checkField(fields[fieldX + 1]) && checkField(fields[fieldX + 1][fieldY])) {
388
                                parseField(fields[fieldX + 1][fieldY]);
389
                        }
390
                        if (checkField(fields[fieldX + 1]) && checkField(fields[fieldX + 1][fieldY])) {
391
                                parseField(fields[fieldX + 1][fieldY]);
392
                        }
393
                }
394
        }
395
        appendGazeLinks();
396
}
397
398
/*
399
* Check if a given field has links inside of it at all
400
*/
401
function checkField(field) {
402
        console.log("functions.js :: " + "checkField()" + ", field: " + typeof field);
403
        //console.log("checking");
404
        if (field !== undefined) {
405
                return true;
406
        } else {
407
                return false;
408
        }
409
410
}
411
412
413
/*
414
*        Parse a given field for links that lie in the linkParsingArea 
415
*/
416
function parseField(fieldToParse) {
417
        //console.log("functions.js :: " + "parseField()" + ", fieldToParse: " + typeof fieldToParse);
418
        var topLeft_x = 0;
419
        topLeft_x = gazeInformation.x - (blickBrowserSettings.linkParsingAreaWidth / 2);
420
        var topLeft_y = 0;
421
        topLeft_y = gazeInformation.y - (blickBrowserSettings.linkParsingAreaHeight / 2);
422
423
424
        for (var s = 0; s < fieldToParse.length; s++) {
425
426
                if (fieldToParse[s].x > topLeft_x && fieldToParse[s].x < (topLeft_x + blickBrowserSettings.linkParsingAreaWidth)) {
427
428
                        if (fieldToParse[s].y > topLeft_y && fieldToParse[s].y < (topLeft_y + blickBrowserSettings.linkParsingAreaHeight)) {
429
430
                                gazeInformation.gazeLinks.push({
431
                                        "index": s,
432
                                        "name": fieldToParse[s].text,
433
                                        "url": fieldToParse[s].url
434
                                });
435
                                //console.log("GazeLink ADD index: "+s+" name: "+fieldToParse[s]['text']+" url: "+fieldToParse[s]['url']);
436
437
438
439
                        }
440
                }
441
        }
442
}
443
444
/*
445
*        Parse element below at current gazePosition for links and put them into the gazeLink Array
446
*/
447
function findLinksInElementBelow() {
448
        //console.log("functions.js :: " + "findLinksInElementBelow()");
449
        var sourceData = $(gazeInformation.elementBelow).find("a");
450
451
        gazeInformation.gazeLinks = [];
452
        for (var s = 0; s < sourceData.length; s++) {
453
                gazeInformation.gazeLinks.push({
454
                        "index": s,
455
                        "name": $(sourceData[s]).text(),
456
                        "url": $(sourceData[s]).attr("href")
457
                });
458
        }
459
        //console.log("Number of GazeLinksFound in elementBelow " + gazeInformation.gazeLinks.length);
460
        appendGazeLinks();
461
462
}
463
464
465
/*
466
*        Take the links from the gazeLink Array and arrange them in the gazeLink Div as a list
467
*        Also append all needed gazeConfirmations and gazeLinkOptions to them
468
*/
469
function appendGazeLinks() {
470
        //console.log("functions.js :: " + "appendGazeLinks()");
471
        $("#gazeLinks").empty();
472
        var dataGazeString = '{\"isFixated\":{\"funcType\":\"fixed\",\"func\":\"showWheelSelector\"}}';
473
474
        //console.log("gazelinksLength: "+gazeInformation.gazeLinks.length);
475
        if (gazeInformation.gazeLinks.length > 0) {
476
                for (var l = 0; l < gazeInformation.gazeLinks.length; l++) {
477
478
479
                        
480
                        if (blickBrowserSettings.selectionMode == "isFixated"){
481
                                //console.log("because selectionMode is 'isFixated' the gazeConfirmationSteps are set to 1");
482
                                blickBrowserSettings.gazeConfirmationSteps = 0;                                        
483
                        }                        
484
485
                        if (blickBrowserSettings.gazeConfirmationSteps === 0) {
486
                                
487
                                dataGazeString = '{\"gazeEnter\":{\"funcType\":\"dynamic\",\"func\":\"gazeInformation.selectedGazeLink=\\\"' + l + '\\\";gazeFunctions[\\\"showGazeLinkOptions\\\"](' + l + ');\"}}';
488
                                
489
                                if ($("#gazeLinkNum_" + l).length > 0) {
490
                                        $("#gazeLinkNum_" + l).remove();
491
                                }
492
                                $("#gazeLinks").append("<div id='gazeLinkNum_" + l + "' class='gazeLink' data-gaze='" + dataGazeString + "' ><strong class='gazeLinkName'>" + (shortenString(gazeInformation.gazeLinks[l].name, 25) || shortenString(gazeInformation.gazeLinks[l].url, 25)) + "</strong><br />" + shortenString(gazeInformation.gazeLinks[l].url, 60) + "</div>");
493
494
                                //dataGazeString = '{\"'+blickBrowserSettings.selectionMode+'\":{\"funcType\":\"dynamic\",\"func\":\"gazeInformation.selectedGazeLink=\\\"' + l + '\\\";gazeFunctions[\\\"showGazeLinkOptions\\\"](' + l + ');\"}}';
495
                                dataGazeString = "{\""+blickBrowserSettings.selectionMode+"\":{\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();gazeFunctions.showWheelSelector(" + l + ")\"}}";
496
                                
497
                                if (blickBrowserSettings.showLeftGazeLinkOption){
498
                                        if ($("#leftGazeOption_" + l).length > 0) {
499
                                                $("#leftGazeOption_" + l).remove();
500
                                        }
501
                                        $("#gazeLinks").parent().append("<div data-gaze='" + dataGazeString + "' id='leftGazeOption_" + l + "' class='gazeLinkOption'></div>");
502
                                        $("#leftGazeOption_" + l).append("<i id='gazeLinkOptionIcon_left' data-gaze='" + dataGazeString + "' class='gazeLinkOptionIcon fa fa-cogs'></i>");
503
                                        
504
                                        //appendGazeEvents($("#gazeLinkOptionIcon_left")[0]);
505
                                        $("#leftGazeOption_" + l).height(blickBrowserSettings.gazeConfirmationSize);
506
                                        $("#leftGazeOption_" + l).width(blickBrowserSettings.gazeConfirmationSize);
507
                                }
508
509
                                dataGazeString = "{\""+blickBrowserSettings.selectionMode+"\":{\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();gazeFunctions.openURL(\\\"" + gazeInformation.gazeLinks[l].url + "\\\",\\\"_self\\\")\"}}";
510
                                
511
                                if ($("#rightGazeOption_" + l).length > 0) {
512
                                        $("#rightGazeOption_" + l).remove();
513
                                }
514
                                $("#gazeLinks").parent().append("<div data-gaze='" + dataGazeString + "' id='rightGazeOption_" + l + "' class='gazeLinkOption'></div>");
515
                                $("#rightGazeOption_" + l).append("<i id='gazeLinkOptionIcon_right' data-gaze='" + dataGazeString + "' class='gazeLinkOptionIcon fa fa-external-link'></i>");
516
                                //appendGazeEvents($("#gazeLinkOptionIcon_right")[0]);
517
                                $("#rightGazeOption_" + l).height(blickBrowserSettings.gazeConfirmationSize);
518
                                $("#rightGazeOption_" + l).width(blickBrowserSettings.gazeConfirmationSize);
519
                        } else {
520
521
522
                                dataGazeString = '{\"'+blickBrowserSettings.selectionMode+'\":{\"funcType\":\"dynamic\",\"func\":\"gazeInformation.selectedGazeLink=\\\"' + l + '\\\";gazeFunctions.showGazeLinkOptions(' + l + ');\"}}';
523
                                dataGazeString = '{\"gazeEnter\":{\"funcType\":\"dynamic\",\"func\":\"gazeInformation.selectedGazeLink=\\\"' + l + '\\\";gazeFunctions.showGazeLinkOptions(' + l + ');\"}}';
524
                                
525
                                if ($("#gazeLinkNum_" + l).length > 0) {
526
                                        $("#gazeLinkNum_" + l).remove();
527
                                }
528
                                $("#gazeLinks").append("<div id='gazeLinkNum_" + l + "' class='gazeLink' data-gaze='" + dataGazeString + "' ><strong class='gazeLinkName'>" + (shortenString(gazeInformation.gazeLinks[l].name, 25) || shortenString(gazeInformation.gazeLinks[l].url, 25)) + "</strong><br />" + shortenString(gazeInformation.gazeLinks[l].url, 60) + "</div>");
529
530
                                
531
                                if (blickBrowserSettings.showLeftGazeLinkOption){
532
                                        dataGazeString = "{\""+blickBrowserSettings.selectionMode+"\":{\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();gazeFunctions.showWheelSelector(" + l + ")\"}}";
533
                                        if ($("#leftGazeOption_" + l).length > 0) {
534
                                                $("#leftGazeOption_" + l).remove();
535
                                        }
536
                                        $("#gazeLinks").parent().append("<div data-gaze='" + dataGazeString + "' id='leftGazeOption_" + l + "' class='gazeLinkOption'></div>");
537
                                        $("#leftGazeOption_" + l).append("<i data-gaze='" + dataGazeString + "' class='gazeLinkOptionIcon fa fa-cogs'></i>");
538
                                        $("#leftGazeOption_" + l).height(blickBrowserSettings.gazeConfirmationSize);
539
                                        $("#leftGazeOption_" + l).width(blickBrowserSettings.gazeConfirmationSize);
540
                                }
541
542
                                dataGazeString = "{\""+blickBrowserSettings.selectionMode+"\":{\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();gazeFunctions.openURL(\\\"" + gazeInformation.gazeLinks[l].url + "\\\",\\\"_self\\\")\"}}";
543
                                
544
545
                                if ($("#rightGazeOption_" + l).length > 0) {
546
                                        $("#rightGazeOption_" + l).remove();
547
                                }
548
                                $("#gazeLinks").parent().append("<div data-gaze='" + dataGazeString + "' id='rightGazeOption_" + l + "' class='gazeLinkOption'></div>");
549
                                $("#rightGazeOption_" + l).append("<i data-gaze='" + dataGazeString + "' class='gazeLinkOptionIcon fa fa-external-link'></i>");
550
                                
551
                                $("#rightGazeOption_" + l).height(blickBrowserSettings.gazeConfirmationSize);
552
                                $("#rightGazeOption_" + l).width(blickBrowserSettings.gazeConfirmationSize);
553
554
555
                                for (var confirmation = 0; confirmation < blickBrowserSettings.gazeConfirmationSteps; confirmation++) {
556
                                        if (confirmation == (blickBrowserSettings.gazeConfirmationSteps - 1)) {
557
                                                dataGazeString = "{\""+blickBrowserSettings.selectionMode+"\":{\"funcType\":\"dynamic\",\"func\":\"gazeFunctions.showConfirmationDiv(\\\"rightGazeOption_" + l + " \\\")\"}}";
558
                                                if ($("#rightGazeConfirmation_" + l + "_" + confirmation ).length > 0) {
559
                                                        $("#rightGazeConfirmation_" + l + "_" + confirmation).remove();
560
                                                }
561
                                                $("#gazeLinks").parent().append("<div data-gaze='" + dataGazeString + "' id='rightGazeConfirmation_" + l + "_" + confirmation + "' class='gazeLinkOption'></div>");
562
                                                $("#rightGazeConfirmation_" + l + "_" + confirmation).append("<span id='rightGazeConfirmation_" + l + "_" + confirmation+"_span' data-gaze='" + dataGazeString + "' class='gazeLinkOptionIcon gazeConfirmation'></span>");
563
                                                $("#rightGazeConfirmation_" + l + "_" + confirmation+"_span").append("<i data-gaze='" + dataGazeString + "' class='fa fa-external-link'></i><br />" + (confirmation + 1) + " / " + blickBrowserSettings.gazeConfirmationSteps);
564
        
565
566
567
                                                if (blickBrowserSettings.showLeftGazeLinkOption){
568
                                                dataGazeString = "{\""+blickBrowserSettings.selectionMode+"\":{\"funcType\":\"dynamic\",\"func\":\"gazeFunctions.showConfirmationDiv(\\\"leftGazeOption_" + l + " \\\")\"}}";
569
                                                
570
                                                if ($("#leftGazeConfirmation_" + l + "_" + confirmation ).length > 0) {
571
                                                        $("#leftGazeConfirmation_" + l + "_" + confirmation).remove();
572
                                                }
573
                                                $("#gazeLinks").parent().append("<div data-gaze='" + dataGazeString + "' id='leftGazeConfirmation_" + l + "_" + confirmation + "' class='gazeLinkOption'></div>");
574
                                                $("#leftGazeConfirmation_" + l + "_" + confirmation).append("<span id='leftGazeConfirmation_" + l + "_" + confirmation+"_span' data-gaze='" + dataGazeString + "' class='gazeLinkOptionIcon gazeConfirmation'></span>");
575
                                                $("#leftGazeConfirmation_" + l + "_" + confirmation+"_span").append("<i data-gaze='" + dataGazeString + "' class='fa fa-cogs'></i><br />" + (confirmation + 1) + " / " + blickBrowserSettings.gazeConfirmationSteps );
576
                                                }
577
578
                                        } else {
579
                                                dataGazeString = "{\""+blickBrowserSettings.selectionMode+"\":{\"funcType\":\"dynamic\",\"func\":\"gazeFunctions.showConfirmationDiv(\\\"rightGazeConfirmation_" + l + "_" + (confirmation + 1) + " \\\")\"}}";
580
                                                if ($("#rightGazeConfirmation_" + l + "_" + confirmation ).length > 0) {
581
                                                        $("#rightGazeConfirmation_" + l + "_" + confirmation).remove();
582
                                                }
583
                                                $("#gazeLinks").parent().append("<div data-gaze='" + dataGazeString + "' id='rightGazeConfirmation_" + l + "_" + confirmation + "' class='gazeLinkOption'><div>");
584
                                                $("#rightGazeConfirmation_" + l + "_" + confirmation).append("<span id='rightGazeConfirmation_" + l + "_" + confirmation+"_span' data-gaze='" + dataGazeString + "' class='gazeLinkOptionIcon gazeConfirmation'></span>");        
585
                                                $("#rightGazeConfirmation_" + l + "_" + confirmation+"_span").append("<i data-gaze='" + dataGazeString + "' class='fa fa-external-link'></i><br />" + (confirmation + 1) + " / " + blickBrowserSettings.gazeConfirmationSteps);
586
587
                                                if (blickBrowserSettings.showLeftGazeLinkOption){
588
                                                        dataGazeString = "{\""+blickBrowserSettings.selectionMode+"\":{\"funcType\":\"dynamic\",\"func\":\"gazeFunctions.showConfirmationDiv(\\\"leftGazeConfirmation_" + l + "_" + (confirmation + 1) + " \\\")\"}}";
589
                                                        if ($("#leftGazeConfirmation_" + l + "_" + confirmation ).length > 0) {
590
                                                                $("#leftGazeConfirmation_" + l + "_" + confirmation).remove();
591
                                                        }
592
593
                                                        $("#gazeLinks").parent().append("<div data-gaze='" + dataGazeString + "' id='leftGazeConfirmation_" + l + "_" + confirmation + "' class='gazeLinkOption'></div>");
594
                                                        $("#leftGazeConfirmation_" + l + "_" + confirmation).append("<span id='leftGazeConfirmation_" + l + "_" + confirmation +"_span' data-gaze='" + dataGazeString + "' class='gazeLinkOptionIcon gazeConfirmation'></span>");
595
                                                        $("#leftGazeConfirmation_" + l + "_" + confirmation +"_span").append("<i data-gaze='" + dataGazeString + "' class='fa fa-cogs'></i><br />" + (confirmation + 1) + " / " + blickBrowserSettings.gazeConfirmationSteps);
596
                                                }
597
                                        }
598
                                }
599
600
                        }
601
                }
602
603
                if (blickBrowserSettings.explicitMode === true){
604
                        //appendGazeEvents();
605
                }
606
607
                positionGazeLinks();
608
        }
609
610
}
611
612
/*
613
*        Position the gazeConfirmations, gazeLinkOptions and the gazeLink-DIV properly
614
*/
615
function positionGazeLinks() {
616
        //console.log("functions.js :: " + "positionGazeLinks()");
617
        
618
619
        if (blickBrowserSettings.explicitMode){
620
                if ($(gazeInformation.elementBelow).width() < 100){
621
                        $("#gazeLinks").width(312);
622
                        $("#gazeLinkNum_0").width(300);
623
                } else {
624
                        $("#gazeLinks").width($(gazeInformation.elementBelow).width()+12);
625
                        $("#gazeLinkNum_0").width($(gazeInformation.elementBelow).width());
626
                }
627
                
628
629
                if (blickBrowserSettings.showLeftGazeLinkOption){
630
                        if ($(gazeInformation.elementBelow).offset().left < ((blickBrowserSettings.gazeConfirmationSteps + 1) * blickBrowserSettings.gazeConfirmationSize)){
631
                                $("#gazeLinks").css("left", ((blickBrowserSettings.gazeConfirmationSteps + 1) * blickBrowserSettings.gazeConfirmationSize)+"px"  );
632
                        } else {
633
                                $("#gazeLinks").css("left", $(gazeInformation.elementBelow).offset().left + "px");
634
                        }
635
                } else {
636
                        $("#gazeLinks").css("left", $(gazeInformation.elementBelow).offset().left + "px");
637
                }
638
        
639
                if (($(window).width() - $("#gazeLinks").offset().left - $("#gazeLinks").width() ) < ((blickBrowserSettings.gazeConfirmationSteps + 1) * blickBrowserSettings.gazeConfirmationSize)){
640
                        console.log("too far right");                        
641
                        $("#gazeLinks").css("left", ( $(window).width() - ((blickBrowserSettings.gazeConfirmationSteps + 1) * blickBrowserSettings.gazeConfirmationSize) - $("#gazeLinks").width() )+"px"  );
642
                } 
643
644
645
646
647
                $("#gazeLinks").css("top", $(gazeInformation.elementBelow).offset().top + "px");
648
        } else {
649
650
                if ((gazeInformation.x - 150) < ((blickBrowserSettings.gazeConfirmationSteps + 1) * blickBrowserSettings.gazeConfirmationSize)){
651
                        console.log("too far left");
652
                        //$("#" + id).css("left", "0px");
653
                        $("#gazeLinks").css("left", ((blickBrowserSettings.gazeConfirmationSteps + 1) * blickBrowserSettings.gazeConfirmationSize)+"px"  );
654
                } else {
655
                        $("#gazeLinks").css("left", (gazeInformation.x - 150) + "px");
656
                }
657
658
                if (($(window).width() - (gazeInformation.x - 150) - $("#gazeLinks").width() ) < ((blickBrowserSettings.gazeConfirmationSteps + 1) * blickBrowserSettings.gazeConfirmationSize)){
659
                        console.log("too far right");                        
660
                        $("#gazeLinks").css("left", ( $(window).width() - ((blickBrowserSettings.gazeConfirmationSteps + 1) * blickBrowserSettings.gazeConfirmationSize) - $("#gazeLinks").width() )+"px"  );
661
                } 
662
663
                
664
                $("#gazeLinks").css("top", (gazeInformation.y - 20));        
665
        }
666
667
        
668
669
        $('.gazeLinkOption').stop();
670
        $(".gazeLinkOption").css("display", "none");
671
        
672
        $("#gazeLinks").fadeIn();
673
674
        var gazeLinksOffset = $("#gazeLinks").offset();
675
        gazeInformation.gazeLinksPosition.x = gazeLinksOffset.left;
676
        gazeInformation.gazeLinksPosition.y = gazeLinksOffset.top;
677
        gazeLinksShowing = true;
678
        //console.log("linkcheckrunning false");
679
        linkCheckRunning = false;
680
        //console.log("gazeLinkOffset x,y :"+ gazeInformation.gazeLinksPosition.x+ " , "+ gazeInformation.gazeLinksPosition.y);
681
682
683
}
684
685
/*
686
*        Arrange the elements inside the wheelSelector circled
687
*/
688
function arrangeWheelElements() {
689
        //console.log("functions.js :: " + "arrangeWheelElements()");
690
        var radius = 170;
691
        var fields = $('.wheelSelector'),
692
                container = $('#wheelSelector'),
693
                width = container.width(),
694
                height = container.height(),
695
                angle = 0,
696
                step = (2 * Math.PI) / fields.length;
697
        fields.each(function() {
698
                //alert($(this).width());
699
                var x = Math.round(width / 2 + radius * Math.cos(angle) - $(this).width() / 2);
700
                var y = Math.round(height / 2 + radius * Math.sin(angle) - $(this).height() / 2);
701
                if (window.console) {
702
                        //console.log($(this).text(), x, y);
703
                }
704
                $(this).css({
705
                        left: x + 'px',
706
                        top: y + 'px'
707
                });
708
                angle += step;
709
        });
710
}
711
712
/*
713
*        move the status div with the mouse 
714
*/
715
function mousemoved(e) {
716
        /*mouseX = e.clientX + window.scrollX;
717
        mouseY = e.clientY + window.scrollY*/
718
        $("#status").css("left", e.clientX + 30 + window.scrollX + "px");
719
        $("#status").css("top", e.clientY + window.scrollY + "px");
720
        
721
}
722
723
724
725
/*
726
*        Functions that can be used as edgeGazeGestures (looking left, top or right of the screen)
727
*/
728
var edgeFunctions = {
729
        /*
730
        *        clears all seen gaze elements 
731
        */
732
        clearDivs: function() {
733
                //console.log("clearGazeElements()");
734
735
                $('#gazeOption_single').css('display','none');
736
737
                $("#gazeLinks").css("display", "none");
738
                $("#closeGazeLinks").css("display", "none");
739
740
                //$('.gazeLinkOption').stop();
741
                //$(".gazeLinkOption").css("display", "none");
742
                $('.gazeLinkOption').remove();
743
744
                $("#gazeLinks").empty();
745
                gazeLinksShowing = false;
746
                $("#wheelSelector").css("display", "none");
747
                $("#wheelSelector").empty();
748
                wheelSelectorShowing = false;
749
                $("#controlBar").css("display", "none");
750
                controlBarShowing = false;
751
                $("#itemSelector").css("display", "none");
752
753
                $(".gazeGestures").css("display","none");
754
                gestureMode = false;
755
                if (!calibrationRunning){
756
                        $("#calibration_blackout").css("display", "none");
757
                }
758
759
        },
760
        /*
761
        *        initiate a 4 point gazeGesture
762
        */
763
        initiateGesture: function() {
764
                $("#calibration_blackout").css("display", "block");
765
                $(".gazeGestures").css("display", "block");
766
                gestureTimer = Date.now();
767
                lastGesture = "";
768
                gestureString = "";
769
                gestureMode = true;
770
        },
771
        /*
772
        *        shows the controlBar
773
        */
774
        showControlBar: function() {
775
776
                
777
                //console.log("showControlBar()");
778
                $("#controlBar").empty();
779
780
                if (blickBrowserSettings.eyeTracker == "eyetribe"){
781
                        if (blickBrowserSettings.controlBarCalibInfo){
782
                        $("#controlBar").append("<div id='controlBarCalibInfo' class='topBarItem' ><i class='topBarIcon fa fa-info'></i><p class=\"subtitle\">Accuracy: "+ calibrationResult.deg +"° </p></div>");                        
783
                        }
784
                }
785
786
                
787
788
                $("#controlBar").append("<div id='controlBarBack' data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();window.history.back()\"}}' class='topBarItem' ></div>");
789
                $("#controlBarBack").append("<i data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();window.history.back()\"}}' class='topBarIcon fa fa-mail-reply'></i><p class=\"subtitle\">Back</p>");
790
791
                $("#controlBar").append("<div id='controlBarForward' data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();window.history.forward()\"}}' class='topBarItem' ></div>");
792
                $("#controlBarForward").append("<i data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();window.history.forward()\"}}' class='topBarIcon fa fa-mail-forward'></i><p class=\"subtitle\">Forward</p>");
793
                
794
                $("#controlBar").append("<div id='controlBarReload' data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();location.reload()\"}}' class='topBarItem'></div>");
795
                $("#controlBarReload").append("<i data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();location.reload()\"}}' class='topBarIcon fa fa-refresh'></i><p class=\"subtitle\">Refresh</p>");
796
797
                $("#controlBar").append("<div id='controlBarToggleReading' data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();edgeFunctions.toggleReadingMode()\"}}' class='topBarItem'></div>");
798
                $("#controlBarToggleReading").append("<i data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();edgeFunctions.toggleReadingMode()\"}}' class='topBarIcon fa fa-book'></i><p class=\"subtitle\">"+(blickBrowserSettings.blickBrowserMode==="reading" ? "Disable Reading" : "Enable Reading")+"</p>");
799
800
                $("#controlBar").append("<div id='controlBarToggleAutoReading' data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();edgeFunctions.toggleAutoReadingMode()\"}}' class='topBarItem'></div>");
801
                $("#controlBarToggleAutoReading").append("<i data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();edgeFunctions.toggleAutoReadingMode()\"}}' class='topBarIcon fa fa-history'></i><p class=\"subtitle\">"+(blickBrowserSettings.autoReadingMode ? "Disable AutoRead" : "Enable AutoRead")+"</p>");
802
803
                $("#controlBar").append("<div id='toggleExplicitMode' data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();edgeFunctions.toggleExplicitMode()\"}}' class='topBarItem'></div>");
804
                $("#toggleExplicitMode").append("<i data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();edgeFunctions.toggleExplicitMode()\"}}' class='topBarIcon fa fa-dot-circle-o'></i><p class=\"subtitle\">"+ (blickBrowserSettings.explicitMode ? "Disable ExplicitMode" : "Enable ExplicitMode") +"</p>");
805
806
                $("#controlBar").append("<div id='controlBarToggleScrolling' data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();edgeFunctions.toggleScrolling()\"}}' class='topBarItem'></div>");
807
                $("#controlBarToggleScrolling").append("<i data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();edgeFunctions.toggleScrolling()\"}}' class='topBarIcon fa fa-arrows-v'></i><p class=\"subtitle\">"+ (blickBrowserSettings.scrollAtBorders ? "Disable Scrolling" : "Enable Scrolling") +"</p>");
808
809
                $("#controlBar").append("<div id='controlBarInitiateGesture' data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();edgeFunctions.initiateGesture();\"}}' class='topBarItem'></div>");
810
                $("#controlBarInitiateGesture").append("<i data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();edgeFunctions.initiateGesture();\"}}' class='topBarIcon fa fa-crosshairs'></i><p class=\"subtitle\">Initiate Gesture</p>");
811
                
812
813
814
                /*
815
                *        Put all available blickBrowser Bookmarks into controlbar
816
                */
817
                var myBookmarks = blickBrowserSettings.bookmarks.split(";");
818
                if (myBookmarks.length > 0){
819
                //console.log(myBookmarks);
820
                        for (var b = 0;b< myBookmarks.length; b++){
821
                                var splittedBookmark = myBookmarks[b].split("|");
822
                                var bookmarkName = splittedBookmark[0];
823
                                var bookmarkURL  = splittedBookmark[1];
824
                                if (bookmarkURL !== undefined){
825
                                        $("#controlBar").append("<div id='controlBarBookmark_"+b+"' data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();gazeFunctions[\\\"openURL\\\"](\\\"" + bookmarkURL + "\\\",\\\"_self\\\")\"}}' class='topBarItem'></div>");
826
                                        $("#controlBarBookmark_"+b).append("<i data-gaze='{\"isFixated\": {\"funcType\":\"dynamic\",\"func\":\"edgeFunctions.clearDivs();gazeFunctions[\\\"openURL\\\"](\\\"" + bookmarkURL + "\\\",\\\"_self\\\")\"}}' class='topBarIcon fa fa-star'></i><p class=\"subtitle\">"+ shortenString(bookmarkName, 12) +"</p>");
827
                                }
828
                        }
829
                }
830
831
                
832
833
                //appendGazeEvents($("#gazeLinkOptionIcon_right")[0]);
834
                //appendGazeEvents();
835
836
                if ($("#controlBar").children().length > 0) {
837
                        if (!controlBarShowing) {
838
                                //clearDivs();
839
                                controlBarShowing = true;
840
                                $("#controlBar").fadeIn();
841
842
                                /*var controlbar = document.getElementById('#controlBar');
843
                                var hasHorizontalScrollbar = controlbar.scrollWidth > div.clientWidth;
844
                                //document.getElementById("controlBar").scrollLeft+=100;
845
                                if (hasHorizontalScrollbar){
846
                                        alert("SCROLL!!!");
847
                                }*/
848
849
850
                        }
851
                }
852
        },
853
854
        /*
855
        *        toggle fixed reading mode for undisturbed reading of articles etc.
856
        */
857
        toggleReadingMode: function() {
858
859
                if (Date.now() - modeToggleCounter > blickBrowserSettings.modeToggleRefractionTime) {
860
                        //console.log("functions.js :: "+"toggleReadingMode()" );
861
                        if (blickBrowserSettings.blickBrowserMode == "reading") {
862
                                checkForLinksInterval = setInterval(gazeFunctions.checkForLinks, 1000);
863
                                self.port.emit("blickBrowserMode", "browse");
864
                                modeToggleCounter = Date.now();                                
865
                                $.notify("Switched to browse mode","success");
866
                                //showNotification('eye', 'Switched to browse mode');
867
                                //$("#notification").text("switched to browsing mode");
868
                                edgeFunctions.clearDivs();
869
                        } else if (blickBrowserSettings.blickBrowserMode == "browse") {
870
                                clearTimeout(checkForLinksInterval);
871
                                self.port.emit("blickBrowserMode", "reading");
872
                                modeToggleCounter = Date.now();                                
873
                                $.notify("Switched to reading mode","success");
874
                                //showNotification('book', 'Switched to reading mode');
875
                                //$("#notification").text("switched to reading mode");
876
                                edgeFunctions.clearDivs();
877
                        }
878
                }
879
        },
880
        toggleAutoReadingMode: function(){
881
                if (Date.now() - modeToggleCounter > blickBrowserSettings.modeToggleRefractionTime) {
882
                        //console.log("functions.js :: "+"toggleScrolling()" );
883
                                        
884
                        if (blickBrowserSettings.autoReadingMode === true){
885
                                blickBrowserSettings.autoReadingMode = false;                                
886
                        } else {
887
                                blickBrowserSettings.autoReadingMode = true;                                
888
                        }
889
                        
890
                        
891
                        
892
                        modeToggleCounter = Date.now();                                
893
                        $.notify("Switched autoReadingMode "+ ( blickBrowserSettings.scrollAtBorders ? "on" : "off"),"success");
894
                        writeSettings();
895
                        //showNotification('eye', 'Switched to browse mode');
896
                        //$("#notification").text("switched to browsing mode");
897
                        edgeFunctions.clearDivs();
898
                
899
                }
900
        },
901
        toggleExplicitMode: function(){
902
                if (Date.now() - modeToggleCounter > blickBrowserSettings.modeToggleRefractionTime) {
903
                        //console.log("functions.js :: "+"toggleScrolling()" );
904
                                        
905
                        if (blickBrowserSettings.explicitMode === true){
906
                                blickBrowserSettings.explicitMode = false;                                
907
                        } else {
908
                                blickBrowserSettings.explicitMode = true;                                
909
                        }
910
                        
911
                        
912
                        
913
                        modeToggleCounter = Date.now();                                
914
                        $.notify("Switched explicitMode "+ ( blickBrowserSettings.scrollAtBorders ? "on" : "off"),"success");
915
                        writeSettings();
916
                        //showNotification('eye', 'Switched to browse mode');
917
                        //$("#notification").text("switched to browsing mode");
918
                        edgeFunctions.clearDivs();
919
                
920
                }
921
        },
922
        /*
923
        *        enable / disable scrolling
924
        */
925
        toggleScrolling: function() {
926
                if (Date.now() - modeToggleCounter > blickBrowserSettings.modeToggleRefractionTime) {
927
                        //console.log("functions.js :: "+"toggleScrolling()" );
928
                                        
929
                        if (blickBrowserSettings.scrollAtBorders === true){
930
                                blickBrowserSettings.scrollAtBorders = false;                                
931
                        } else {
932
                                blickBrowserSettings.scrollAtBorders = true;                                
933
                        }
934
                        
935
                        
936
                        
937
                        modeToggleCounter = Date.now();                                
938
                        $.notify("Switched scrolling "+ ( blickBrowserSettings.scrollAtBorders ? "on" : "off"),"success");
939
                        writeSettings();
940
                        //showNotification('eye', 'Switched to browse mode');
941
                        //$("#notification").text("switched to browsing mode");
942
                        edgeFunctions.clearDivs();
943
                
944
                }
945
        },
946
        none: function(){
947
948
        }
949
950
};
951
952
953
//callable functions from the 4 point gaze gestures 
954
955
/*        ######################################################################################
956
*        ADD FUNCTIONS THAT SHOULD BE ENABLED FOR CALLING FROM THE 4-POINT-GESTURE MODE [START]
957
*        ######################################################################################
958
*/
959
960
var pageBack = function(){
961
        window.history.back();
962
};
963
964
var pageForward = function(){
965
        window.history.forward();
966
};
967
968
var pageReload = function(){
969
        location.reload();
970
};
971
972
/*        ####################################################################################
973
*        ADD FUNCTIONS THAT SHOULD BE ENABLED FOR CALLING FROM THE 4-POINT-GESTURE MODE [END]
974
*        ####################################################################################
975
*/
976
977
978
979
980
981
982
/*
983
*        Check for elements at position x,y that have gazeEvents bound to them and trigger those events
984
*/
985
function gazePosition(x, y) {
986
        //console.log("functions.js :: "+"gazePosition()" +", x: " + x +", y: "+y );
987
988
        //save current position into gazeInformation Object
989
        gazeInformation.x = x;
990
        gazeInformation.y = y;
991
992
        
993
994
995
        //check if gestureMode has been initiated and needs to be shown
996
        if (gestureMode) {
997
                if (gestureString.length == 4) {
998
                        $.notify("GestureString: " + gestureString, "success");
999
                        gestureMode = false;
1000
                        edgeFunctions.clearDivs();
1001
1002
                        var myGestures = blickBrowserSettings.gestures.split(";");
1003
                        if (myGestures.length > 0) {
1004
                                for (var gg = 0; gg < myGestures.length; gg++) {
1005
                                        var splittedGesture = myGestures[gg].split("|");
1006
                                        console.log(splittedGesture[1]);
1007
                                        if (splittedGesture[0] == gestureString) {
1008
                                                console.log("Calling Function: window."+splittedGesture[1]);
1009
                                                window[splittedGesture[1]]();
1010
                                        }
1011
                                }
1012
                        }
1013
                }
1014
1015
                if (Date.now() - gestureTimer >= 5000) {
1016
                        $.notify("gestureTimer ran out.", "success");
1017
                        gestureMode = false;
1018
                        edgeFunctions.clearDivs();
1019
                }
1020
1021
        }
1022
1023
1024
        //check if autoReadingMode is enabled and run the routine if needed
1025
        if (blickBrowserSettings.autoReadingMode){
1026
                clearTimeout(checkForLinksInterval);
1027
                if (Math.abs(gazeInformation.gazeMoveStartPoint.x - gazeInformation.x) > blickBrowserSettings.autoReadingModeDistance || 
1028
                        Math.abs(gazeInformation.gazeMoveStartPoint.y - gazeInformation.y) > blickBrowserSettings.autoReadingModeDistance){
1029
                        
1030
                        gazeInformation.gazeMoveStartTime = Date.now();
1031
                        gazeInformation.gazeMoveStartPoint = {"x": gazeInformation.x,"y":gazeInformation.y};
1032
1033
                } 
1034
1035
                if (Date.now() - gazeInformation.gazeMoveStartTime >= blickBrowserSettings.autoReadingModeThreshold){
1036
                        gazeInformation.gazeMoveStartTime = Date.now();
1037
                        gazeInformation.gazeMoveStartPoint = {"x": gazeInformation.x,"y":gazeInformation.y};
1038
                        gazeFunctions.checkForLinks();                        
1039
                        
1040
                }
1041
                
1042
        }
1043
1044
        // Compute gaze Correction
1045
        if (gazeCorrectionMode === true) {
1046
1047
                var gazeValues = {
1048
                        timestamp: Date.now(),
1049
                        gcPoint: gazeCorrectionPointNr,
1050
                        x: gazeInformation.x,
1051
                        y: gazeInformation.y
1052
                };        
1053
1054
                gazeCorrectionData.push(gazeValues);        
1055
        }
1056
        
1057
        //scroll if scrolling is enabled
1058
        if (blickBrowserSettings.scrollAtBorders === true) {
1059
1060
                
1061
1062
                if (gazeInformation.y > (window.innerHeight + window.scrollY) - (window.innerHeight * (blickBrowserSettings.scrollThreshold/100) )) {
1063
1064
                        window.scroll(window.scrollX, window.scrollY + blickBrowserSettings.scrollSpeed);
1065
1066
                } else if ((gazeInformation.y - window.scrollY) < (window.innerHeight * (blickBrowserSettings.scrollThreshold/100))) {
1067
1068
                        window.scroll(window.scrollX, window.scrollY - blickBrowserSettings.scrollSpeed);
1069
1070
                }
1071
1072
                if ((gazeInformation.x - window.scrollX) < (window.innerWidth * (blickBrowserSettings.scrollThreshold/100))) {
1073
                        window.scroll(window.scrollX - blickBrowserSettings.scrollSpeed, window.scrollY);
1074
                } else if (gazeInformation.x > (window.innerWidth + window.scrollX) - (window.innerWidth * (blickBrowserSettings.scrollThreshold/100))) {
1075
                        window.scroll(window.scrollX + blickBrowserSettings.scrollSpeed, window.scrollY);
1076
                }
1077
        
1078
1079
        }
1080
1081
        //position and show crosshair if enabled
1082
        if (blickBrowserSettings.gazeCrosshair === true) {
1083
1084
                $("#crosshairTop").css("left", (gazeInformation.x) + "px");
1085
                $("#crosshairTop").css("top", (gazeInformation.y - 16) + "px");
1086
1087
                $("#crosshairBottom").css("left", (gazeInformation.x) + "px");
1088
                $("#crosshairBottom").css("top", (gazeInformation.y + 1) + "px");
1089
1090
1091
                $("#crosshairLeft").css("left", (gazeInformation.x - 16) + "px");
1092
                $("#crosshairLeft").css("top", (gazeInformation.y) + "px");
1093
1094
                $("#crosshairRight").css("left", (gazeInformation.x + 1) + "px");
1095
                $("#crosshairRight").css("top", (gazeInformation.y) + "px");
1096
1097
                $("#crosshairTop").css("display", "block");
1098
                $("#crosshairBottom").css("display", "block");
1099
                $("#crosshairLeft").css("display", "block");
1100
                $("#crosshairRight").css("display", "block");
1101
                //$("#cross").css("display", "block");
1102
        } else {
1103
                $("#crosshairTop").css("display", "none");
1104
                $("#crosshairBottom").css("display", "none");
1105
                $("#crosshairLeft").css("display", "none");
1106
                $("#crosshairRight").css("display", "none");
1107
1108
                //$("#cross").css("display", "none");
1109
        }
1110
1111
1112
        //move findLinkArea with gazePosition
1113
        $("#findLinkArea").css("display", "none");
1114
        $("#findLinkArea").css("left", (gazeInformation.x - $(findLinkArea).width() / 2) + "px");
1115
        $("#findLinkArea").css("top", (gazeInformation.y - $(findLinkArea).height() / 2) + "px");
1116
1117
1118
1119
1120
        
1121
1122
        /*
1123
        *        Check current gazePosition for edgeGazeGestures
1124
        */
1125
1126
        if ( (x < ((-1 * blickBrowserSettings.leftEdgeTolerance) + window.scrollX) ) && (y > ( (window.innerHeight*0.1) + window.scrollY ) ) && (y < ((window.innerHeight*0.9)) + window.scrollY) ) {
1127
                //console.log("leftEdge!!!"+blickBrowserSettings['leftEdge']);
1128
                edgeFunctions[blickBrowserSettings.leftEdge]();
1129
        }
1130
        if ( (y < ((-1 * blickBrowserSettings.topEdgeTolerance) + window.scrollY) ) && (x > ((window.innerWidth*0.1) + window.scrollX ) && (x < ((window.innerWidth*0.9)+ window.scrollX ) ) ) )  {
1131
                //console.log("topEdge!!!");
1132
                edgeFunctions[blickBrowserSettings.topEdge]();
1133
        }
1134
        if ((x > (window.innerWidth + window.scrollX + blickBrowserSettings.rightEdgeTolerance)) && (y > ( (window.innerHeight*0.1) + window.scrollY ) ) && (y < ((window.innerHeight*0.9)) + window.scrollY) ) {
1135
                //console.log("rightEdge!!!");
1136
                edgeFunctions[blickBrowserSettings.rightEdge]();
1137
        }
1138
1139
        
1140
1141
1142
        //check if privacy mode is enabled and move the holeImage according to gazeposition
1143
        if (blickBrowserSettings.privacyMode === true) {
1144
                //console.log("privacy mode is true!!!!!");
1145
                $("#holeImage").css("display", "block");
1146
1147
                $("#holeImage").css('background-position', (gazeInformation.x - window.scrollX - 2500) + 'px ' + (gazeInformation.y - window.scrollY - 2500) + 'px');
1148
        } else {
1149
                $("#holeImage").css("display", "none");
1150
        }
1151
1152
1153
1154
        //Get elementAt gazePosition
1155
        var elementBelow = document.elementFromPoint(gazeInformation.x - scrollX, gazeInformation.y - scrollY);
1156
1157
1158
        
1159
        //document.getElementById("offsetLabel").innerHTML = "Offset: " + "x: " + (browserDecorationThickness + window.scrollX + window.screenX) + "px" + "|y: " + (browserTopBarsHeight + window.scrollY + window.screenY) + "px";
1160
1161
1162
1163
        //append debug information to mouse if enabled
1164
        if (blickBrowserSettings.debugInformation === true) {
1165
                $("#status").css("display", "block");
1166
        } else {
1167
                $("#status").css("display", "none");
1168
        }
1169
1170
        document.getElementById("status").innerHTML = "X: " + gazeInformation.x + "<br /> Y: " + gazeInformation.y + "<br /> fix: " + gazeInformation.isFixation + "<br /> dur:" + (Date.now() - gazeInformation.currentElementFixatedAt) + "ms" + "<br /> winsize:" + window.innerWidth + "px x " + innerHeight + "px" + "<br /> xOffset:" + (window.mozInnerScreenX + window.scrollX) + "px" + "<br /> yOffset:" + (window.mozInnerScreenY + window.scrollY) + "px";
1171
        if (elementBelow !== null) {
1172
                document.getElementById("status").innerHTML += ("<br />type:" + elementBelow.tagName);
1173
        }
1174
1175
1176
1177
1178
        //Fixated DISPATCHER
1179
        if (elementBelow !== null) {
1180
1181
                var dataGazeObject = $(elementBelow).data('gaze');
1182
                if (dataGazeObject !== undefined) {
1183
                        //does element below have an 'isFixated' event?
1184
                        if ($(dataGazeObject)[0].hasOwnProperty("isFixated")) {
1185
1186
                                //if user looks at that element more than 10% of fixationThreshold-time, then show the progressCircle
1187
                                if ((Date.now() - gazeInformation.currentElementFixatedAt) >= blickBrowserSettings.fixationThreshold * 0.1) {
1188
1189
1190
                                        $('.dial').val(Date.now() - gazeInformation.currentElementFixatedAt).trigger('change');
1191
                                        $("#gazeProgress").css("display", "block");
1192
1193
1194
1195
                                        if (distanceToGaze($("#gazeProgress")) < 10) {
1196
                                                $("#gazeProgress").css("left", ($("#gazeProgress").offset().left + 10));
1197
                                        }
1198
1199
1200
                                }
1201
1202
1203
                                //if user looks at that element longer that fixationThreshold-time, trigger isFixated event of that element
1204
                                if ((Date.now() - gazeInformation.currentElementFixatedAt) >= blickBrowserSettings.fixationThreshold) {
1205
                                        console.log("fixationTime: "+(Date.now() - gazeInformation.currentElementFixatedAt));
1206
                                        gazeInformation.currentElementFixatedAt = Date.now();
1207
                                        gazeInformation.fixatedElement = elementBelow;
1208
                                
1209
                                        //if ($(gazeInformation.fixatedElement).attr('data-gaze')) {
1210
                        
1211
                                                gazeInformation.fixatedElement.dispatchEvent(isFixated);
1212
                                        
1213
                                        //}
1214
                                        
1215
                                } 
1216
1217
                        } else {
1218
                                gazeInformation.currentElementFixatedAt = Date.now();        
1219
                                $("#gazeProgress").css("display", "none");
1220
                        }
1221
                } else {
1222
                        gazeInformation.currentElementFixatedAt = Date.now();
1223
                        $("#gazeProgress").css("display", "none");
1224
1225
1226
                }
1227
1228
1229
1230
        }
1231
1232
        //GAZE ENTER, GAZE LEAVE AND GAZE OVER DISPATCHER
1233
        if (elementBelow !== null) {
1234
1235
                //if current element has the gazeOver event bould to it, trigger it
1236
                var dataGazeObject = $(elementBelow).data('gaze');
1237
                if (dataGazeObject !== undefined) {
1238
                        if ($(dataGazeObject)[0].hasOwnProperty("gazeOver")) {
1239
                                $(gazeInformation.elementBelow).trigger("gazeOver");
1240
                        }
1241
                }
1242
                
1243
                
1244
                //if its a new element below gaze position 
1245
                if (gazeInformation.lastElementBelow != elementBelow) {
1246
1247
                        //if it's a new element - reset the fixated-timer 
1248
                        gazeInformation.currentElementFixatedAt = Date.now();
1249
                                $('#gazeProgress').css("left", ($(elementBelow).offset().left + $(elementBelow).width() + 10));
1250
                                $('#gazeProgress').css("top", ($(elementBelow).offset().top));
1251
                        gazeInformation.fixationPositionAtStart = {
1252
                                "x": gazeInformation.x,
1253
                                "y": gazeInformation.y
1254
                        };
1255
1256
                        //if (gazeInformation.lastElementBelow != gazeInformation.elementBelow){
1257
1258
                                //if last element has gazeLeave event bound to it, trigger it
1259
                                var dataGazeObject = $(gazeInformation.lastElementBelow).data('gaze');
1260
                                if (dataGazeObject !== undefined) {
1261
                                        if ($(dataGazeObject)[0].hasOwnProperty("gazeLeave")) {
1262
                                                $(gazeInformation.lastElementBelow).trigger("gazeLeave");
1263
                                        }
1264
                                }
1265
                                //$(gazeInformation.lastElementBelow).trigger("gazeLeave");
1266
1267
                        //}
1268
                        //save the element in the JSON object
1269
                        gazeInformation.lastElementBelow = gazeInformation.elementBelow;
1270
1271
                        //if the element was not null - dispatch event
1272
                        if (gazeInformation.lastElementBelow !== null) {
1273
1274
                                
1275
                                //unfade last gazed element
1276
                                var dataGazeObject = $(gazeInformation.lastElementBelow).data('gaze');
1277
                                if (dataGazeObject !== undefined) {                                        
1278
                                                $(gazeInformation.lastElementBelow).stop();
1279
                                                $(gazeInformation.lastElementBelow).fadeTo("fast", 1);                                        
1280
                                }
1281
                                                                
1282
                                gazeInformation.currentElementFixatedAt = Date.now();
1283
                                gazeLeaveFunc(gazeInformation.lastElementBelow);
1284
1285
                        }
1286
1287
                        //save current element to gazeInformation
1288
                        gazeInformation.elementBelow = elementBelow;
1289
1290
1291
                        //if last element has gazeEnter event bound to it, trigger it
1292
                var dataGazeObject = $(elementBelow).data('gaze');
1293
                if (dataGazeObject !== undefined) {
1294
                        if ($(dataGazeObject)[0].hasOwnProperty("gazeEnter")) {
1295
                                $(gazeInformation.elementBelow).trigger("gazeEnter");
1296
                                gazeInformation.currentElementFixatedAt = Date.now();
1297
                        }
1298
                }
1299
1300
                        
1301
                //if explicitMode is enabled, put the currently gazed elements name and url into the gazeLinks Array
1302
                        if (blickBrowserSettings.explicitMode === true) {
1303
                                if (!wheelSelectorShowing) {
1304
                                        if (!controlBarShowing) {
1305
                                                if (blickBrowserSettings.blickBrowserMode != 'reading') {
1306
                                                        if ($(gazeInformation.elementBelow).attr('href') !== undefined) {
1307
                                                                gazeInformation.gazeLinks = [];
1308
                                                                //console.log("NumOfGazeLinks: " + gazeInformation.gazeLinks.length);
1309
                                                                if (gazeInformation.gazeLinks.length < 1) {
1310
                                                                        gazeInformation.gazeLinks.push({
1311
                                                                                "object": $(gazeInformation.elementBelow),
1312
                                                                                "index": 0,
1313
                                                                                "name": $(gazeInformation.elementBelow).text(),
1314
                                                                                "url": $(gazeInformation.elementBelow).attr('href')
1315
                                                                        });
1316
1317
                                                                        appendGazeLinks();
1318
                                                                }
1319
                                                        }
1320
                                                }
1321
                                        }
1322
                                }
1323
                        }
1324
                        gazeInformation.currentElementFixatedAt = Date.now();
1325
                        gazeEnterFunc(gazeInformation.elementBelow);
1326
1327
1328
                        //fade gazed elements
1329
                        var dataGazeObject = $(gazeInformation.elementBelow).data('gaze');
1330
                        if (dataGazeObject !== undefined) {
1331
                                
1332
                                        $(gazeInformation.elementBelow).stop();
1333
                                        $(gazeInformation.elementBelow).fadeTo('fast', 0.3);
1334
                                
1335
                        }
1336
1337
                }
1338
        }
1339
1340
}
1341
1342
1343
1344
function gazeOverFunc(element) {
1345
1346
1347
}
1348
1349
function isFixationFunc(element) {
1350
1351
1352
}
1353
1354
function gazeEnterFunc(element) {
1355
        //console.log("functions.js :: "+"gazeEnterFunc()" + ", element: " + typeof element );
1356
1357
        if (blickBrowserSettings.borderGazedObjects === true) {
1358
                $(element).css("outline", "2px dashed #000000");
1359
                $(element).css("outline-offset", "-2px");
1360
        }
1361
1362
1363
}
1364
1365
function gazeLeaveFunc(element) {
1366
        //console.log("functions.js :: "+"gazeLeaveFunc()" +", element: "+typeof element );
1367
                if (blickBrowserSettings.borderGazedObjects === true) {
1368
                $(element).css("outline", "0px none");
1369
                }
1370
        
1371
1372
}
1373
1374
1375
//show a notification with a given font-awesome icon (http://fortawesome.github.io/Font-Awesome/icons/) and string
1376
function showNotification(faicon, str) {
1377
        //$("#notification").html("<div class='notif_icon'><i class='fa fa-"+faicon+"'></i></div><div class='notif_text'>"+str+"</div>");
1378
        console.log("Notification: " + str);
1379
        $("#notification").stop();        
1380
        $("#notification").html("<table><tr><td class='notif_icon'><i class='fa fa-" + faicon + "'></i></td><td class='notif_text'>" + str + "</td></tr></table>");
1381
        $("#notification").fadeIn("fast");
1382
        $('#notification').fadeOut(3000);
1383
1384
}
1385
//make the function visible from a page-script
1386
exportFunction(showNotification, unsafeWindow, {defineAs: "showNotification"});
1387
1388
1389
1390
1391
/*
1392
*        Copy current gazeInformationX/Y to unsafeWindow and make the function visible from a page-script
1393
*/
1394
function getGazeInformation(){
1395
        unsafeWindow.gazeInformationX = cloneInto(gazeInformation.x, unsafeWindow);
1396
        unsafeWindow.gazeInformationY = cloneInto(gazeInformation.y, unsafeWindow);
1397
        //return gazeInformation;
1398
}
1399
exportFunction(getGazeInformation, unsafeWindow, {defineAs: "getGazeInformation"});
1400
1401
1402
/*
1403
*        gazePosition adjusting before working with the gazePosition
1404
*/
1405
function calcGazePosition(message) {
1406
        //console.log(window.mozInnerScreenY);
1407
        //console.log("functions.js :: "+"calcGazePosition()" +", message: "+message );
1408
1409
1410
        //stop asyncronous checking for links if readingMode is active
1411
        if (blickBrowserSettings.blickBrowserMode == "reading") {
1412
                clearTimeout(checkForLinksInterval);
1413
        }
1414
1415
        
1416
        eyeTrackingData = JSON.parse(message);
1417
        var newX, newY;
1418
1419
1420
1421
        raw = eyeTrackingData;
1422
        if (raw.x == "0.0" && raw.y == "0.0") {
1423
                self.port.emit("setIconRed", "noop");
1424
        } else {
1425
                self.port.emit("setIconGreen", "noop");
1426
        }
1427
1428
        //remove current screen position from gazePosition
1429
        //add the current scrolling position from gazePosition
1430
        //add the manual offset to the gazePosition
1431
        raw.x = (raw.x / blickBrowserSettings.scaling) + window.scrollX - window.mozInnerScreenX + blickBrowserSettings.gazeOffsetX;
1432
        raw.y = (raw.y / blickBrowserSettings.scaling) + window.scrollY - window.mozInnerScreenY + blickBrowserSettings.gazeOffsetY;
1433
1434
1435
        //safe previous
1436
        gazeInformation.previousX = gazeInformation.x;
1437
        gazeInformation.previousY = gazeInformation.y;
1438
1439
1440
1441
        newX = raw.x;
1442
        newY = raw.y;
1443
1444
        //do gazeSmoothing if needed
1445
        if (blickBrowserSettings.gazeSmoothing === true) {
1446
                
1447
                
1448
                //empty gazeHistory if gaze just performed a saccade
1449
                //append the gazePosition to gazeHistory otherwise
1450
                if (Math.abs(gazeInformation.previousX - newX) > blickBrowserSettings.saccadeLength) {                                                
1451
                        gazeCollection = [];                        
1452
1453
                } else if (Math.abs(gazeInformation.previousY - newY) > blickBrowserSettings.saccadeLength) {
1454
                        gazeCollection = [];
1455
                } else {
1456
1457
                        //if gazeHistory is not full, append current gazePosition
1458
                        if (gazeCollection.length < blickBrowserSettings.gazeSmoothingHistory) {
1459
                                gazeCollection.push({
1460
                                        "x": newX,
1461
                                        "y": newY
1462
                                });
1463
                                //otherwise remove oldest element and append newest 
1464
                        } else {
1465
                                gazeCollection.splice(0, 1);
1466
                                gazeCollection.push({
1467
                                        "x": newX,
1468
                                        "y": newY
1469
                                });
1470
                        }
1471
1472
                        var sumX = 0;
1473
                        var sumY = 0;
1474
                        //calculate the average gazePosition from all positions in gazeHistory 
1475
                        for (var g = 0; g < gazeCollection.length; g++) {
1476
                                sumX += gazeCollection[g].x;
1477
                                sumY += gazeCollection[g].y;
1478
                        }
1479
                        //set newly calculated gazePosition 
1480
                        newX = sumX / gazeCollection.length;
1481
                        newY = sumY / gazeCollection.length;
1482
1483
1484
1485
                }
1486
        }
1487
1488
        try{
1489
                //run check for gazeEvents and options on newly calculated gazePosition 
1490
                gazePosition(newX, newY);
1491
        } catch (exc){
1492
                console.log("ERROR MESSAGE: "+exc.message);
1493
                console.log("ERROR NAME: "+exc.name);
1494
                console.log("ERROR LINENUMBER: "+exc.lineNumber);
1495
                console.log("ERROR LINENUMBER: "+exc.columnNumber);
1496
        }
1497
}
1498
1499
function checkCalibration() {
1500
                //console.log("check Calibration");
1501
                $("#calibration_check").css("display", "block");
1502
                $("#calibrationImage").css("display", "block");
1503
                var imageMovingSpeed = 1000;
1504
                
1505
                gazeCorrectionX = 0;
1506
                gazeCorrectionY = 0;
1507
1508
                gc_left = window.innerWidth * 0.2;
1509
                gc_right = window.innerWidth - gc_left;
1510
                gc_top =         window.innerHeight * 0.2;
1511
                gc_bottom = window.innerHeight - gc_top;
1512
                
1513
                switch(blickBrowserSettings.gazeCorrectionPoints){
1514
1515
                        case 4: gazeCorrectionPoints = [{x:gc_left,y:gc_top}, {x:gc_right,y:gc_bottom}, {x:gc_left,y:gc_bottom}, {x:gc_right,y:gc_top}]; break;
1516
                        case 1: gazeCorrectionPoints = [{x:(window.innerWidth/2),y:(window.innerHeight/2)}]; break;
1517
                        default: break;
1518
1519
                }
1520
                
1521
1522
                
1523
1524
                $("#calibrationImage").animate({
1525
                        left: "+" + (gazeCorrectionPoints[gazeCorrectionPointNr].x - calibrationIconSizeHalf),
1526
                        top: "+" + (gazeCorrectionPoints[gazeCorrectionPointNr].y - calibrationIconSizeHalf)
1527
                }, imageMovingSpeed);
1528
1529
                gazeCorrectionMode = true;
1530
1531
                setTimeout(function() {
1532
                        var gcSumX = 0;
1533
                        var gcSumY = 0;
1534
                        for (var gc = 0; gc < gazeCorrectionData.length; gc++) {
1535
                                gcSumX += gazeCorrectionData[gc].x;
1536
                                gcSumY += gazeCorrectionData[gc].y;
1537
1538
                        }
1539
                        //console.log("GC X: " + (gcSumX / gazeCorrectionData.length));
1540
                        //console.log("GC Y: " + (gcSumY / gazeCorrectionData.length));
1541
                        gazeCorrectionValues.push({
1542
                                x: gcSumX / gazeCorrectionData.length,
1543
                                y: gcSumY / gazeCorrectionData.length
1544
                        });
1545
                        gazeCorrectionX += (gazeCorrectionPoints[gazeCorrectionPointNr].x - gazeCorrectionValues[gazeCorrectionPointNr].x);
1546
                        gazeCorrectionY += (gazeCorrectionPoints[gazeCorrectionPointNr].y - gazeCorrectionValues[gazeCorrectionPointNr].y);
1547
                        //console.log("difference x:"+(gazeCorrectionPoints[gazeCorrectionPointNr].x - gazeCorrectionValues[gazeCorrectionPointNr].x));
1548
                        //console.log("difference y:"+(gazeCorrectionPoints[gazeCorrectionPointNr].y - gazeCorrectionValues[gazeCorrectionPointNr].y));
1549
                        gazeCorrectionData = [];
1550
                        gazeCorrectionPointNr++;
1551
1552
                        if (gazeCorrectionPointNr < gazeCorrectionPoints.length){
1553
                                gazeCorrectionValues = [];
1554
                                gazeCorrectionPoints = [];
1555
                                checkCalibration();
1556
                        } else {
1557
                                gazeCorrectionMode = false;
1558
                                
1559
                                gazeCorrectionX = (gazeCorrectionX/gazeCorrectionPointNr);
1560
                                gazeCorrectionY = (gazeCorrectionY/gazeCorrectionPointNr);
1561
1562
                                blickBrowserSettings.gazeOffsetX = Math.floor(gazeCorrectionX);
1563
                                blickBrowserSettings.gazeOffsetY = Math.floor(gazeCorrectionY);
1564
                                writeSettings();
1565
1566
                                console.log("gazeCorrectionX: "+gazeCorrectionX);
1567
                                console.log("gazeCorrectionY: "+gazeCorrectionY);
1568
                                $("#calibration_check").css("display", "none");
1569
                                $("#calibrationImage").css("display", "none");
1570
                                if (calibrationResult.deg < 0.5) {
1571
                        showNotification('star',"Calibration result: Very Good 5/5 stars.<br /><i class=\"fa fa-star\"></i><i class=\"fa fa-star\"></i><i class=\"fa fa-star\"></i><i class=\"fa fa-star\"></i><i class=\"fa fa-star\"></i>");
1572
1573
                } else if (calibrationResult.deg < 0.7) {
1574
                        showNotification('star',"Calibration result: Good 4/5 stars.<br /><i class=\"fa fa-star\"></i><i class=\"fa fa-star\"></i><i class=\"fa fa-star\"></i><i class=\"fa fa-star\"></i>");
1575
                    
1576
                } else if (calibrationResult.deg < 1) {
1577
                        showNotification('star',"Calibration result: Moderate 3/5 stars.<br /><i class=\"fa fa-star\"></i><i class=\"fa fa-star\"></i><i class=\"fa fa-star\"></i>");
1578
                    
1579
                } else if (calibrationResult.deg < 1.5) {
1580
                        showNotification('star',"Calibration result: Not good 2/5 stars.<br /><i class=\"fa fa-star\"></i><i class=\"fa fa-star\"></i>");
1581
                    
1582
                } else if (calibrationResult.deg >= 1.5) {
1583
                        showNotification('star',"Calibration result: Bad 1/5 stars.<br /><i class=\"fa fa-star\"></i>");
1584
                    
1585
                }
1586
                                gazeCorrectionPointNr = 0;
1587
                                /*for (var dp = 0;dp<gazeCorrectionValues.length;dp++){
1588
                                        console.log("Point "+gazeCorrectionPointNr+": "+gazeCorrectionValues[dp].x+"|"+gazeCorrectionValues[dp].y);
1589
                                        //console.log(": "+gazeCorrectionPoints[dp].x+"|"+gazeCorrectionPoints[dp].y);                                        
1590
                                        //gazeCorrectionX += 
1591
                                        console.log("difference x:"+(gazeCorrectionPoints[dp].x - gazeCorrectionValues[dp].x));
1592
                                        console.log("difference y:"+(gazeCorrectionPoints[dp].y - gazeCorrectionValues[dp].y));
1593
                                }*/
1594
                                
1595
                        }
1596
/*
1597
                        setTimeout(function() {
1598
                                
1599
                        },1000); */
1600
                }, imageMovingSpeed+300+3000);
1601
1602
1603
        }
1604
1605
function distanceToGaze(obj) {
1606
        //console.log("functions.js :: "+"distanceToGaze()" + ", obj: "+typeof obj );
1607
        var o1 = $(obj).offset();
1608
        var dx = o1.left - gazeInformation.x;
1609
        var dy = o1.top - gazeInformation.y;
1610
        return Math.sqrt(dx * dx + dy * dy);
1611
}