Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (27.44 KB)

1
/*
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
//do not execute pagemod in iframes
22
if (window.location == window.parent.location) {
23

    
24

    
25
        /*
26
        *        Append the DOM Observer to listen for new elements that are being attached
27
        */
28
        var observer = new MutationObserver(function (mutations) {
29
            
30
            mutations.forEach(function (mutation) {
31
              
32
              if (mutation.type == "childList"){                      
33
                      for (var c = 0;c< mutation.addedNodes.length;c++){                                      
34
                              if ($(mutation.addedNodes.item(c)).data("gaze") !== undefined){
35

    
36
                                      /*
37
                                      *        if a dom change is observed and the change is of type 'childlist'
38
                                      *        send all the new nodes to the gazeEvent appender
39
                                      */
40
                                      appendGazeEvents(mutation.addedNodes.item(c));
41
                              }
42
                        }
43
              }
44
              //console.log("MutationType: "+mutation.type);
45
                });
46
        });
47

    
48
        /*
49
        *        Set some observer options
50
        */  
51
        observer.observe(document.body, {
52
            attributes: true,
53
            childList:true,
54
            characterData: true,
55
            characterDataOldValue: true,
56
            subtree: true
57
        });
58

    
59
                
60
 
61

    
62
                /*
63
                *        Append gaze-gesture divs to the body (4 point gaze)
64
                */        
65
                var gesturedata = "{\"gazeEnter\": {\"funcType\":\"dynamic\",\"func\":\" $(\\\"#gestureTopLeft\\\").css(\\\"backgroundColor\\\",\\\"#053e46\\\"); gestureTimer = Date.now(); if (lastGesture != \\\"1\\\" ) {gestureString += \\\"1\\\"; lastGesture=\\\"1\\\"; }  \"},\"gazeLeave\": {\"funcType\":\"dynamic\",\"func\":\"  $(\\\"#gestureTopLeft\\\").css(\\\"backgroundColor\\\",\\\"#13D1EB\\\");  \"}}";
66
                $("body").prepend("<div data-gaze='" + gesturedata + "' id='gestureTopLeft'         class='gazeGestures'></div>");
67
                gesturedata = "{\"gazeEnter\": {\"funcType\":\"dynamic\",\"func\":\" $(\\\"#gestureTopRight\\\").css(\\\"backgroundColor\\\",\\\"#053e46\\\"); gestureTimer = Date.now(); if (lastGesture != \\\"2\\\" ) {gestureString += \\\"2\\\"; lastGesture=\\\"2\\\";}  \"},\"gazeLeave\": {\"funcType\":\"dynamic\",\"func\":\"  $(\\\"#gestureTopRight\\\").css(\\\"backgroundColor\\\",\\\"#13D1EB\\\");  \"}}";
68
                $("body").prepend("<div data-gaze='" + gesturedata + "' id='gestureTopRight'         class='gazeGestures'></div>");
69
                gesturedata = "{\"gazeEnter\": {\"funcType\":\"dynamic\",\"func\":\" $(\\\"#gestureBottomLeft\\\").css(\\\"backgroundColor\\\",\\\"#053e46\\\"); gestureTimer = Date.now(); if (lastGesture != \\\"3\\\" ) {gestureString += \\\"3\\\"; lastGesture=\\\"3\\\";}   \"},\"gazeLeave\": {\"funcType\":\"dynamic\",\"func\":\"  $(\\\"#gestureBottomLeft\\\").css(\\\"backgroundColor\\\",\\\"#13D1EB\\\");  \"}}";
70
                $("body").prepend("<div data-gaze='" + gesturedata + "' id='gestureBottomLeft'         class='gazeGestures'></div>");
71
                gesturedata = "{\"gazeEnter\": {\"funcType\":\"dynamic\",\"func\":\" $(\\\"#gestureBottomRight\\\").css(\\\"backgroundColor\\\",\\\"#053e46\\\"); gestureTimer = Date.now(); if (lastGesture != \\\"4\\\" ) {gestureString += \\\"4\\\"; lastGesture=\\\"4\\\";}  \"},\"gazeLeave\": {\"funcType\":\"dynamic\",\"func\":\"  $(\\\"#gestureBottomRight\\\").css(\\\"backgroundColor\\\",\\\"#13D1EB\\\");  \"}}";
72
                $("body").prepend("<div data-gaze='" + gesturedata + "'  id='gestureBottomRight' class='gazeGestures'></div>");
73

    
74
 
75
                
76
                /*
77
                *        Append gazeLinks Div to the body links that are found by a linkFinding algorithm are put into this div
78
                */        
79
                $("body").prepend("<div id='gazeLinks'></div>");
80
                
81
                /*
82
                *        Append the wheelselector to the body
83
                */        
84
                $("body").prepend("<div id='wheelSelector'></div>");
85

    
86
                /*
87
                *        Append the calibration_blackout div to the body to darken the background in calibration mode
88
                */
89
                $("body").prepend("<div id='calibration_blackout'></div>");
90

    
91
                /*
92
                *        Needed for calibration checking when adjusting gaze position offset
93
                */
94
                $("body").prepend("<div id='calibration_check'></div>");                
95
                
96

    
97
                /*
98
                *        Needed for BlickBrowser's own Notification
99
                */
100
                var dstr = "{\"gazeEnter\": {\"funcType\":\"dynamic\",\"func\":\" $(\\\"#notification\\\").stop();$(\\\"#notification\\\").fadeIn(10);  \"},\"gazeLeave\": {\"funcType\":\"dynamic\",\"func\":\" $(\\\"#notification\\\").fadeOut(3000);  \"}}";
101
                $("body").prepend("<div id='notification' data-gaze='" + dstr + "' ></div>");
102

    
103

    
104
                /*
105
                *        Needed for the progress circle
106
                */
107
                $("body").prepend('<div id="gazeProgress"><input type="text" class="dial"></div>');
108

    
109

    
110
                $("body").prepend("<div id='status'></div>");
111
                //$("body").prepend("<div id='fixatedA'></div>");
112
                $("body").prepend("<div id='controlBar' class='controlBar'></div>");
113

    
114

    
115

    
116
                $("body").prepend("<canvas id='findLinkArea'>Your browser does not support the HTML5 canvas tag.</canvas>");
117

    
118

    
119
                /*
120
                *        Needed for the crosshair
121
                */
122
                $("body").prepend("<canvas id='crosshairTop' width='1' height='15'>Your browser does not support the HTML5 canvas tag.</canvas>");
123
                $("body").prepend("<canvas id='crosshairBottom' width='1' height='15'>Your browser does not support the HTML5 canvas tag.</canvas>");
124
                $("body").prepend("<canvas id='crosshairLeft' width='15' height='1'>Your browser does not support the HTML5 canvas tag.</canvas>");
125
                $("body").prepend("<canvas id='crosshairRight' width='15' height='1'>Your browser does not support the HTML5 canvas tag.</canvas>");
126

    
127
                /*
128
                * Hide browser screen when it's not active
129
                */
130
                $("body").prepend("<div id='noFocusHider' ></div>");
131

    
132

    
133
                /*
134
                *        Styling the newly appended elements
135
                */
136
                $("#fixatedA").css("backgroundColor", "#FFFFFF");
137
                $("#fixatedA").css("display", "none");
138
                $("#fixatedA").css("position", "fixed");
139
                $("#fixatedA").css("padding", "10");
140
                $("#fixatedA").css("border", "2px solid");
141
                $("#fixatedA").css("border-bottom-color", "#000000");
142
                $("#fixatedA").css("border-top-color", "#000000");
143
                $("#fixatedA").css("border-left-color", "#000000");
144
                $("#fixatedA").css("border-right-color", "#000000");
145
                $("#fixatedA").css("border-radius", "10px");
146
                $("#fixatedA").css("box-shadow", "5px 5px 2px");
147
                $("#fixatedA").css("zIndex", 100000);
148

    
149
                $("#wheelSelector").css("display", "none");
150
                $("#wheelSelector").css("backgroundColor", "#13D1EB");
151
                $("#wheelSelector").css("position", "absolute");
152
                $("#wheelSelector").css("left", ((window.innerWidth / 2) - 250) + "px");
153
                $("#wheelSelector").css("zIndex", 120000);
154
                $("#wheelSelector").css("width", "500px");
155
                $("#wheelSelector").css("height", "500px");
156
                $("#wheelSelector").css("top", "10%");
157
                $("#wheelSelector").css("border", "2px solid #FFFFFF");
158
                $("#wheelSelector").css("border-radius", "250px");
159

    
160
                $("#gazeLinks").css("display", "none");
161
                $("#gazeLinks").css("position", "absolute");
162
                $("#gazeLinks").css("zIndex", 100000);
163

    
164
                $("#noFocusHider").css("display", "none");
165

    
166
                $("#controlBar").css("display", "none");
167

    
168
                $("#status").css("position", "absolute");
169
                $("#status").css("left", "0px");
170
                $("#status").css("top", "0px");
171
                $("#status").css("zIndex", 16777269);
172

    
173
                $("#calibration_blackout").css("backgroundColor", "#000000");
174
                $("#calibration_blackout").css("width", "100%");
175
                $("#calibration_blackout").css("height", "100%");
176
                $("#calibration_blackout").css("overflow", "hidden");
177
                $("#calibration_blackout").css("zIndex", 2147483640);
178
                $("#calibration_blackout").css("display", "none");
179
                $("#calibration_blackout").css("position", "fixed");
180
                $("#calibration_blackout").css("left", "0px");
181
                $("#calibration_blackout").css("top", "0px");
182

    
183
                $("#calibration_check").css("backgroundColor", "#000000");
184
                $("#calibration_check").css("width", "100%");
185
                $("#calibration_check").css("height", "100%");
186
                $("#calibration_check").css("overflow", "hidden");
187
                $("#calibration_check").css("zIndex", 2147483646);
188
                $("#calibration_check").css("display", "none");
189
                $("#calibration_check").css("position", "fixed");
190
                $("#calibration_check").css("left", "0px");
191
                $("#calibration_check").css("top", "0px");
192

    
193
                
194
                //activate indicator
195
                $("#gazeProgress").css("position", "absolute");
196
                $("#gazeProgress").css("display", "none");
197
                $("#gazeProgress").css("zIndex", 2147483645);
198

    
199
                $("#findLinkArea").css("width", "300px");
200
                $("#findLinkArea").css("height", "300px");
201
                $("#findLinkArea").css("display", "none");
202
                $("#findLinkArea").css("position", "absolute");
203
                $("#findLinkArea").css("zIndex", 160000);
204

    
205

    
206
                /*
207
                *        Creating and positioning the crosshair
208
                */
209
                var ctx = $("#crosshairTop")[0].getContext('2d');
210
                ctx.rect(0, 0, 1, 15);
211
                ctx.fillStyle = "black";
212
                ctx.fill();
213

    
214
                ctx = $("#crosshairBottom")[0].getContext('2d');
215
                ctx.rect(0, 0, 1, 15);
216
                ctx.fillStyle = "black";
217
                ctx.fill();
218

    
219
                ctx = $("#crosshairLeft")[0].getContext('2d');
220
                ctx.rect(0, 0, 15, 1);
221
                ctx.fillStyle = "black";
222
                ctx.fill();
223

    
224
                ctx = $("#crosshairRight")[0].getContext('2d');
225
                ctx.rect(0, 0, 15, 1);
226
                ctx.fillStyle = "black";
227
                ctx.fill();
228

    
229

    
230
                $("#crosshairTop").css("left", (100) + "px");
231
                $("#crosshairTop").css("top", (100 - 16) + "px");
232
                $("#crosshairTop").css("position", "absolute");
233
                $("#crosshairTop").css("zIndex", 16777270);
234

    
235
                $("#crosshairBottom").css("left", (100) + "px");
236
                $("#crosshairBottom").css("top", (100 + 1) + "px");
237
                $("#crosshairBottom").css("position", "absolute");
238
                $("#crosshairBottom").css("zIndex", 16777270);
239

    
240
                $("#crosshairLeft").css("left", (100 - 16) + "px");
241
                $("#crosshairLeft").css("top", (100) + "px");
242
                $("#crosshairLeft").css("position", "absolute");
243
                $("#crosshairLeft").css("zIndex", 16777270);
244

    
245
                $("#crosshairRight").css("left", (100 + 1) + "px");
246
                $("#crosshairRight").css("top", (100) + "px");
247
                $("#crosshairRight").css("position", "absolute");
248
                $("#crosshairRight").css("zIndex", 16777270);
249

    
250
                ctx = $("#findLinkArea")[0].getContext('2d');
251
                ctx.rect(0, 0, 300, 300);
252
                ctx.strokeStyle = "red";
253
                ctx.lineWidth = "2";
254
                ctx.stroke();
255

    
256

    
257
                //################################## VARIABLES #################################
258

    
259
                //JQNOTIFY settings
260
                $.notify.defaults({position: "top center"});
261

    
262

    
263
                var blickBrowserSettings;
264

    
265
                /*
266
                *        Needed for gazeCorrection offset
267
                */
268
                var recordGazeData = false;
269
                var recordedGazeData = [];
270

    
271
                var gazeCorrectionMode = false;
272
                var gazeCorrectionData = [];
273
                var gazeCorrection = { x: 0, y: 0 };
274
                var gazeCorrectionTimerStart;
275
                var gazeCorrectionDuration = 1000;
276
                var gazeCorrectionValues = [];
277
                var gazeCorrectionPointNr = 0;
278
                var gazeCorrectionQuantity = 4;
279
                var gazeCorrectionPoints = [];
280
                var gazeCorrectionX = 0;
281
                var gazeCorrectionY = 0;
282
                var gc_left, gc_right, gc_top, gc_bottom = 0;
283

    
284

    
285
                /*
286
                *        Notify the user, that the browser has to be in full screen mode to start calibrating
287
                */
288
            var showFullscreenMessageForCalibration = true;
289

    
290
            /*
291
            *        Prevent sending multiple calibration requests when waiting for the first one
292
            */
293
            var calibrationRequestSent = false;
294

    
295
            /*
296
            *        The calibration results are saved here when requesting the EYETRIBE status on page load / activate
297
            */
298
                var calibrationResult;
299

    
300

    
301
                /*
302
                *        point counter in calibration array 
303
                */
304
                var calibrationStart = 0;
305

    
306

    
307
                /*
308
                *        4 point gaze gesture variables
309
                */
310
                var gestureTimer = Date.now();
311
                var gestureString = "";
312
                var gestureMode = false;
313
                var lastGesture = "";
314

    
315

    
316
                /*
317
                *        prevents toggling reading / browsing mode more than 1 time per second
318
                */
319
                var modeToggleCounter = 0;
320

    
321
                //wheter gazeLinks are showing
322
                var gazeLinksShowing = false;
323
                var gazeLinkOptionsShowing = false;
324

    
325
                //wheter controlBar is showing
326
                var controlBarShowing = false;
327

    
328
                //wheter wheelselector is showing
329
                var wheelSelectorShowing = false;
330

    
331
                //whether eyetracker has been set up while initializing - False if it's set up.
332
                var firstRun = true;
333

    
334
                //if a message has been sent to the tracker and a request is awaited
335
                var waitingForResponse = false;
336

    
337
                //show the follow me message when calibration is run and the crosshair is shown
338
                var showFollowMeMessageAtCalibration = true;
339

    
340
                //take average values from EYETRIBE eyetracking data?
341
                var average = true;
342

    
343

    
344
                //####################### INSIDE WINDOW OFFSET CALCULATION #####################
345

    
346
                var xOffset = 0;
347
                var yOffset = 0;
348

    
349
                var browserDecorationThickness = (window.outerWidth - window.innerWidth) / 2;
350
                console.log("browserDecorationThickness: "+browserDecorationThickness);
351
                var browserTopBarsHeight = window.outerHeight - browserDecorationThickness - window.innerHeight;
352
                console.log("browserTopBarsHeight: "+browserTopBarsHeight);
353
                //################################# SMI #####################################
354
                var iViewXAPI = null;
355

    
356
                //##################### CALIBRATION VARIABLES #####################
357
                //the array where the recalibration points will be put
358
                var calibrationArray = [];
359

    
360
                var overflowXBeforeCalibration;
361
                var overflowYBeforeCalibration;
362
                //32 is half of calibrationImage
363
                var calibrationIconSizeHalf = 32;
364

    
365
                //distance of calibrationImage from borders (in pixel)
366
                var distanceFromBorder = 100;
367

    
368
                //the calibration grid for 3 x 3 calibration
369
                var topRow, midRow, bottomRow = 0;
370
                var leftCol, midCol, rightCol = 0;
371
                var recalibrationArray = [];
372
                var calibrationPointNumber = 1;
373

    
374

    
375
                var gazeTimer = 0;
376
                var linkCheckRunning = false;
377
                eyeTribe.setCalibrationParameters();
378

    
379
                //initiate calibration timer
380
                var calibrationTimer = "null";
381

    
382
                //variable for checking what should be parsed from the eyetracking frame data
383
                var calibrationRunning = false;
384
                var eyeTrackerIsCalibrated = false;
385
                var eyeTrackerIsCalibrating = false;
386
                var pushMode = "notSet";
387

    
388
                /*
389
                *        Asynchronous toggling of the linkFinding algorithms every 1000ms 
390
                *        (or more if algorithm is still running after 1000ms)
391
                */
392
                var checkForLinksInterval;                
393
                checkForLinksInterval = setInterval(function() {                
394
                        if (document.hasFocus()) {
395
                                gazeFunctions.checkForLinks();
396
                        }
397
                }, 1000);
398

    
399
                //move the status div with the mouse
400
                window.onmousemove = mousemoved;
401

    
402
                //needed for collecting gazePositions for smoothing
403
                var gazeCollection = [];
404

    
405
                //###################### GAZE INFORMATION JSON VARIABLE ###################
406

    
407
                var gazeInformation = {
408
                        "x": 0, //the actual x value
409
                        "y": 0, //the actual y value
410
                        "previousX": 0, //last x value
411
                        "previousY": 0, //last y value
412
                        "isFixation": false, //eyetribe built in fixation algorithm
413
                        "fixationStart": 0, //unix time when actual fixation started
414
                        "fixationPositionAtStart": { 
415
                                x: 0,
416
                                y: 0
417
                        }, // x|y of gaze position when fixation started
418
                        "elementBelow": null, //actual element under gaze at x/y
419
                        "fixatedElement": null, //actually fixated object
420
                        "lastElementBelow": null, //last fixated object
421
                        "currentElementFixatedAt": Date.now(), //unix time when fixation started
422
                        "fixatedOptionsDialogPosition": {
423
                                x: 0,
424
                                y: 0
425
                        }, //for calculating the distance of mouse - optionsDiv
426
                        "gazeLinksPosition": {
427
                                x: 0,
428
                                y: 0
429
                        }, //position of link list
430
                        "gazeLinks": [], //array of all links
431
                        "gazeLinkName": null,
432
                        "gazeLinkSource": null,
433
                        "selectedGazeLink": null,
434
                        "gazeMoveStartPoint": {"x": 0,"y":0}, // auto readingmode reference point
435
                        "gazeMoveStartTime": Date.now(), // auto readingmode duration
436
                };
437

    
438
                
439

    
440
                //##################### EVENT CREATION AND APPENDING #####################
441

    
442
                var gazeEnter = new Event('gazeEnter');
443
                var gazeLeave = new Event('gazeLeave');
444
                var gazeOver = new Event('gazeOver');
445
                var isFixated = new Event('isFixated');
446

    
447

    
448

    
449

    
450

    
451
                
452

    
453

    
454
                //################### COMMUNICATION WITH ADDON ###################
455

    
456

    
457
                /*
458
                *        Listen for the calibrationImage being transmitted
459
                */
460
                self.port.on("calibrationImage", function(imgurl) {
461
                        $("body").prepend("<img id='calibrationImage' src='" + imgurl + "' />");
462
                        $("#calibrationImage").css("position", "absolute");
463
                        $("#calibrationImage").css("left", "50%");
464
                        $("#calibrationImage").css("top", "50%");
465
                        $("#calibrationImage").css("display", "none");
466
                        $("#calibrationImage").css("zIndex", 2147483647); //1 level above calibration_blackout
467

    
468
                });
469
        
470

    
471
                /*
472
                *        Listen for the privateMode image being transmitted
473
                */
474
                self.port.on("holeImage", function(imgurl) {                        
475
                        $("body").prepend("<img id='holeImageFile' src='" + imgurl + "' />");
476
                        $("#holeImageFile").hide();
477
                        $("body").prepend("<div id='holeImage'></div>");
478
                        $("#holeImage").css("display", "none");
479
                        $("#holeImage").css("background-image", "url(" + $("#holeImageFile").attr('src') + ")");
480
                        $("#holeImage").css("position", "fixed");
481
                        $("#holeImage").css("width", "100%");
482
                        $("#holeImage").css("height", "100%");
483
                        $("#holeImage").css("zIndex", 16777272); //2 level above calibration_blackout
484

    
485
                });
486

    
487
                /*
488
                *        Listen for external calibration initialization
489
                */
490
                self.port.on("startCalibration", function(message) {
491
                        //console.log("initiate calibration");
492
                        eyeTribe.initiateCalibration();
493

    
494
                });
495

    
496

    
497
                /*
498
                *        Listen for external gaze offset calibration initialization
499
                */
500
                self.port.on("checkCalibration", function(message) {
501
                        //console.log("initiate calibration");
502
                        checkCalibration();
503

    
504
                });
505

    
506

    
507
                /*
508
                *        initialize eyetribe calibration parameters
509
                */
510
                self.port.on("initializeEyeTribe", function(message) {
511
                        //console.log("abort running calibration");
512
                        //abortRunningCalibration();
513
                        //console.log("get tracker status");
514
                        //initializeEyeTracker();
515
                        eyeTribe.getTrackerStatus();
516

    
517
                });
518

    
519

    
520
                /*
521
                *        ##########################################################################################
522
                *        Listen for gazeData Messages and call the proper handler accordingly to current eyetracker
523
                *        ##########################################################################################
524
                */
525

    
526

    
527
                /*
528
                *        If eyetracker is eyetribe - send gazeData to eyetribe handler
529
                */
530
                self.port.on("eyeTrackerData", function(message) {
531

    
532
                        var messages;
533

    
534
                        // for debugging the gaze history can be set to 12345 to stop listening to the gazedata and stop 
535
                        if (blickBrowserSettings.gazeSmoothingHistory !== 12345) {
536
                                if (message.search(/}\n{/) > -1) {
537
                                        //split multiple messages from eyetribe server and send them on by one at a time
538
                                        messages = message.split(/\n/);
539

    
540
                                        for (var v = 0; v < messages.length; v++) {
541
                                                
542
                                                if (messages[v].length > 5) {
543
                                                        
544
                                                        eyeTribe.parseMessage(messages[v]);
545

    
546
                                                        
547
                                                }
548
                                        }
549

    
550
                                } else {
551

    
552
                                        eyeTribe.parseMessage(message);
553

    
554
                                }
555
                        }
556

    
557

    
558
                        if (!document.hasFocus()) {
559
                                //console.log("no focus.");
560
                                if (blickBrowserSettings.hideOnFocusLost === true) {
561
                                        $("#noFocusHider").css("display", "block");
562
                                }
563
                        } else {
564
                                $("#noFocusHider").css("display", "none");
565
                        }
566

    
567
                });
568

    
569

    
570
                /*
571
                *        if message comes from REDm, route it directly to gazeCalculation
572
                */
573
                self.port.on("smiData", function(message) {
574
                        calcGazePosition(message);
575
                });
576

    
577
                /*
578
                *        if message comes from MyGaze, route it directly to gazeCalculation
579
                */
580
                self.port.on("myGazeData", function(message) {                        
581
                        calcGazePosition(message);
582
                });
583
        
584

    
585
                /*
586
                *        Listen for external settings changes
587
                */
588
                self.port.on("blickBrowserSettings", function(settings) {
589
                        blickBrowserSettings = eval(settings);
590
                        $(function() {
591
                                $(".dial").knob({
592
                                        'min': 0,
593
                                        'max': blickBrowserSettings.fixationThreshold,
594
                                        'readOnly': true,
595
                                        'displayInput': false,
596
                                        'fgColor': '#13D1EB',
597
                                        'bgColor': '#000000',
598
                                        'width': 30
599
                                });
600
                        });
601
                        $.notify("Settings updated","success");
602

    
603
                        if (blickBrowserSettings.eyeTracker === "eyetribe"){
604
                                window.onresize = eyeTribe.setCalibrationParameters();
605
                        }        
606
                        //show all settings in console
607
                        console.log(JSON.stringify(blickBrowserSettings, undefined, 4));
608
                });
609

    
610

    
611

    
612
                /*
613
                *        Put all '<a>' Elements into an array to parse it
614
                */
615
                var aArray = [];
616
                var allAs = document.getElementsByTagName("a");
617
                //console.log("Found "+ allAs.length +" Links");
618

    
619
                for (var b = 0; b < allAs.length; b++) {
620
                        var pos = getPosition(allAs[b]);
621

    
622
                        aArray[b] = [];
623
                        aArray[b].url = allAs[b].getAttribute("href");
624
                        aArray[b].text = allAs[b].innerHTML;
625
                        aArray[b].x = $(allAs[b]).offset().left;
626
                        aArray[b].y = $(allAs[b]).offset().top;
627

    
628
                }
629

    
630

    
631

    
632

    
633
                /*
634
                *        Calculate the size of the linkparsing grid
635
                */
636

    
637

    
638
/*
639
        DOCUMENT Grid:
640
                                 __ __ __ __
641
                                |__|__|__|__|
642
                                |__|__|__|__|
643
                                |__|__|__|__|
644
                                |__|__|__|__|
645
                                |__|__|__|__|
646
                                |__|__|__|__|
647
                                |__|__|__|__|
648

649
*/
650

    
651

    
652
                var documentHeight = $(document).height();
653
                var documentWidth = $(document).height();
654

    
655
                var colCount = 4;
656
                var fieldWidth = documentWidth / colCount;
657
                var fieldHeight = fieldWidth;
658
                var rowCount = Math.ceil(documentHeight / fieldHeight);
659
                /*console.log("colcount: "+colCount);
660
                console.log("fieldWidth: "+fieldWidth);
661
                console.log("fieldHeight: "+fieldHeight);
662
                console.log("rowCount: "+rowCount);*/
663

    
664

    
665

    
666
                var fields = [];
667

    
668
                //console.log("Found "+ allAs.length +" Links");
669
                for (var b = 0; b < allAs.length; b++) {
670
                        var foundPoint = [];
671
                        foundPoint.url = allAs[b].getAttribute("href");
672
                        foundPoint.text = allAs[b].innerHTML;
673
                        foundPoint.x = $(allAs[b]).offset().left;
674
                        //console.log("FIRSTX: "+foundPoint.x);
675
                        foundPoint.y = $(allAs[b]).offset().top;
676

    
677

    
678
                        var fieldX = Math.floor(foundPoint.x / fieldWidth);
679
                        //console.log("1_FieldX: "+fieldX);
680
                        var fieldY = Math.floor(foundPoint.y / fieldHeight);
681
                        //console.log("1_FieldY: "+fieldY);
682
                        if (fields[fieldX] !== undefined) {
683
                                if (fields[fieldX][fieldY] !== undefined) {
684
                                        fields[fieldX][fieldY].push(foundPoint);
685
                                        //console.log("addpoint_1");
686
                                } else {
687
                                        fields[fieldX][fieldY] = [];
688
                                        fields[fieldX][fieldY].push(foundPoint);
689
                                        //console.log("addpoint_2");
690
                                }
691
                        } else {
692
                                fields[fieldX] = [];
693
                                if (fields[fieldX][fieldY] !== undefined) {
694
                                        fields[fieldX][fieldY].push(foundPoint);
695
                                        //console.log("addpoint_3");
696
                                } else {
697
                                        fields[fieldX][fieldY] = [];
698
                                        fields[fieldX][fieldY].push(foundPoint);
699
                                        //console.log("addpoint_4");
700
                                }
701
                        }
702
                }
703

    
704

    
705

    
706
        }
707

    
708
        /*
709
        *        Run appendGazeEvents over all elements on page load
710
        */
711
        var allGazeObjects = document.querySelectorAll('[data-gaze]');
712
                for (var g = 0; g < allGazeObjects.length; g++) {
713
                        appendGazeEvents(allGazeObjects[g]);
714
                }
715

    
716

    
717

    
718
        /*
719
        *        Append gazeEvents to a given element (if it has any appended)
720
        *        
721
        *        @sourceElement : HTML Node Element to parse for gazeEvents
722
        */
723
        function appendGazeEvents(sourceElement) {
724
                //console.log("myscript.js :: " + "appendGazeEvents()" );
725
        
726
                
727
                        var gazeObject = $(sourceElement);
728
                        var jsonob = gazeObject.data("gaze");
729
                                
730
                        /*        
731
                        *        if element has an event bound to it, first check for function type, 
732
                        *        then append the event with that function to the 'sourceElement'
733
                        *
734
                        */
735

    
736

    
737
                        //if element has 'isFixated' event bound to it
738
                        if (jsonob.hasOwnProperty("isFixated")) {
739
                                //console.log("myscript.js :: " + "appendGazeEvents()" + " :: found isFixated data-gaze field in JSON: "+ JSON.stringify(jsonob));
740

    
741
                                if (jsonob.isFixated.funcType == "dynamic") {
742
                                        if (jsonob.isFixated.hasOwnProperty("func")) {
743
                                                gazeObject.off("isFixated");
744
                                                gazeObject.on("isFixated", new Function(jsonob.isFixated.func));
745
                                        } else {
746
                                                //console.log("myscript.js :: " + "appendGazeEvents()" + " :: function code is missing in JSON: " + JSON.stringify(jsonob));
747
                                                //console.log("function code is missing");
748
                                        }
749
                                } else if (jsonob.isFixated.funcType == "fixed") {
750
                                        if (jsonob.isFixated.hasOwnProperty("func")) {
751
                                                gazeObject.off("isFixated");
752
                                                gazeObject.on("isFixated", gazeFunctions[jsonob.isFixated.func]);
753
                                        } else {
754
                                                //console.log("myscript.js :: " + "appendGazeEvents()" + " :: function name is missing in JSON: " + JSON.stringify(jsonob));
755
                                                //console.log("function is missing");
756
                                        }
757
                                }
758
                        }
759

    
760
                        //if element has 'isFixated' event bound to it
761
                        if (jsonob.hasOwnProperty("gazeEnter")) {
762
                                //console.log("myscript.js :: " + "appendGazeEvents()" + " :: found gazeEnter data-gaze field in JSON: "+ JSON.stringify(jsonob));
763
                                if (jsonob.gazeEnter.funcType == "dynamic") {
764
                                        if (jsonob.gazeEnter.hasOwnProperty("func")) {
765

    
766
                                                gazeObject.off("gazeEnter");
767
                                                gazeObject.on("gazeEnter", new Function(jsonob.gazeEnter.func));
768
                                        } else {
769
                                                //console.log("myscript.js :: " + "appendGazeEvents()" + " :: function code is missing in JSON: " + JSON.stringify(jsonob));
770
                                                //console.log("function code is missing");
771
                                        }
772
                                } else if (jsonob.gazeEnter.funcType == "fixed") {
773
                                        if (jsonob.gazeEnter.hasOwnProperty("func")) {
774
                                                gazeObject.off("gazeEnter");
775
                                                gazeObject.on("gazeEnter", gazeFunctions[jsonob.gazeEnter.func]);
776
                                        } else {
777
                                                //console.log("myscript.js :: " + "appendGazeEvents()" + " :: function name is missing in JSON: " + JSON.stringify(jsonob));
778
                                                //console.log("function is missing");
779
                                        }
780
                                }
781
                        }
782

    
783
                        //if element has 'isFixated' event bound to it
784
                        if (jsonob.hasOwnProperty("gazeOver")) {
785
                                //console.log("myscript.js :: " + "appendGazeEvents()" + " :: found gazeOver data-gaze field in JSON: "+ JSON.stringify(jsonob));
786
                                if (jsonob.gazeOver.funcType == "dynamic") {
787
                                        if (jsonob.gazeOver.hasOwnProperty("func")) {
788

    
789
                                                gazeObject.off("gazeOver");
790
                                                gazeObject.on("gazeOver", new Function(jsonob.gazeOver.func));
791
                                        } else {
792
                                                //console.log("myscript.js :: " + "appendGazeEvents()" + " :: function code is missing in JSON: " + JSON.stringify(jsonob));
793
                                                //console.log("function code is missing");
794
                                        }
795
                                } else if (jsonob.gazeOver.funcType == "fixed") {
796
                                        if (jsonob.gazeOver.hasOwnProperty("func")) {
797
                                                gazeObject.off("gazeOver");
798
                                                gazeObject.on("gazeOver", gazeFunctions[jsonob.gazeOver.func]);
799
                                        } else {
800
                                                //console.log("myscript.js :: " + "appendGazeEvents()" + " :: function name is missing in JSON: " + JSON.stringify(jsonob));
801
                                                //console.log("function is missing");
802
                                        }
803
                                }
804
                        }
805

    
806

    
807
                        //if element has 'isFixated' event bound to it
808
                        if (jsonob.hasOwnProperty("gazeLeave")) {
809
                                //console.log("myscript.js :: " + "appendGazeEvents()" + " :: found gazeLeave data-gaze field in JSON: "+ JSON.stringify(jsonob));
810
                                if (jsonob.gazeLeave.funcType == "dynamic") {
811
                                        if (jsonob.gazeLeave.hasOwnProperty("func")) {
812
                                                gazeObject.off("gazeLeave");
813
                                                gazeObject.on("gazeLeave", new Function(jsonob.gazeLeave.func));
814
                                        } else {
815
                                                //console.log("myscript.js :: " + "appendGazeEvents()" + " :: function code is missing in JSON: " + JSON.stringify(jsonob));
816
                                        }
817
                                } else if (jsonob.gazeLeave.funcType == "fixed") {
818
                                        if (jsonob.gazeLeave.hasOwnProperty("func")) {
819
                                                gazeObject.off("gazeLeave");
820
                                                gazeObject.on("gazeLeave", gazeFunctions[jsonob.gazeLeave.func]);
821
                                        } else {
822
                                                //console.log("myscript.js :: " + "appendGazeEvents()" + " :: function name is missing in JSON: " + JSON.stringify(jsonob));
823
                                                //console.log("function is missing");
824
                                        }
825
                                }
826
                        }
827

    
828
                
829
        }
830

    
831
        /*
832
        *         Send changed blickBrowserSettings to addon
833
        */
834
        function writeSettings(){
835
                console.log("myscript.js :: " + "writeSettings()");
836
                self.port.emit('writeSettings',blickBrowserSettings);        
837
        }
838

    
839
        /*
840
        *        Request blickBrowserSettings from addon
841
        */
842
        function loadSettings() {
843
                self.port.emit("getAllSettings", "null");
844
        }
845

    
846
        /*
847
        *        retrieve absolute position of element
848
        *        @element: the element to get the position of
849
        */
850
        function getPosition(element) {
851
                //console.log("myscript.js :: "+"getPosition()" + ", element: "+ typeof element);
852
                var xPosition = 0;
853
                var yPosition = 0;
854

    
855
                while (element) {
856
                        xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
857
                        yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
858
                        element = element.offsetParent;
859
                }
860
                return {
861
                        x: xPosition,
862
                        y: yPosition
863
                };
864
}