PageSourceSearch

https://pajak.go.id/themes/custom/livechatdjp/js/vendor/cobrowse/coBrowseUI.js

js pajak.go.id collected 2026-10-02 02:50:51 UTC 51,334 bytes, 1,456 lines download raw bytes

1/* global coBrowse */
2
3/**
4 * @license coBrowse.js<br>
5 *          Copyright 2018 Avaya Inc. All Rights Reserved.<br>
6 *          <br>
7 *          Usage of this source is bound to the terms described in
8 *          licences/License.txt<br>
9 *          <br>
10 *          Avaya - Confidential & Proprietary. <br>
11 *          Use pursuant to your signed agreement or Avaya Policy
12 */
13
14/**
15 * Sample user interface implemented using jQuery UI that subscribes to the 
16 * coBrowse object for notifications.
17 * 
18 * @type Object
19 */
20var coBrowseUI = {
21
22    // Store the listeners interested in UI events.
23    listeners: [],
24
25    targetDocument: null,
26    targetDiv: null,
27
28    isIframed: false,
29
30    // UI element IDs.
31    proactiveJoinDialogId: '#proactiveJoinDialog',
32    proactiveJoinTextId: 'proactiveJoinText',
33    proactiveJoinNameInputId: 'proactiveJoinNameInput',
34    proactiveJoinSessionKeyInputId: 'proactiveJoinSessionKeyInput',
35
36    requestControlDialogId: '#requestControlDialog',
37    requestControlTextId: 'requestControlText',
38
39    coBrowseDialogId: '#coBrowseDialog',
40    coBrowseTextId: 'coBrowseText',
41
42    errorDialogId: '#errorDialog',
43    errorTextId: 'errorText',
44    
45    hiddenPostFix: 'Hidden',
46    hiddenElements: [
47        'proactiveJoinDialogHidden',
48        'requestControlDialogHidden',
49        'coBrowseDialogHidden',
50        'errorDialogHidden'
51    ],
52
53    // Button IDs used on the dialogs.
54    joinButtonId: 'join-button',
55    pauseButtonId: 'pause-button',
56    stopButtonId: 'stop-button',
57    inactiveStopId: 'inactive-stop-button',
58    inactiveContinueId: 'inactive-continue-button',
59    closeButtonId: 'close-button',
60    grantButtonId: 'grant-button',
61    denyButtonId: 'deny-button',
62    revokeButtonId: 'revoke-button',
63    
64    // various text entries for customisation/localisation
65    textEntries: {
66        proactiveJoin: {
67            title : "Join Co-Browse",
68            text : "",
69            nameLabel: "Your Name",
70            sessionKey : "SESSION KEY",
71            joinButtonText : "Join"
72        },
73        pauseStopDialog : {
74            title : "Connected to Co-Browse",
75            text : "Co-Browsing is in progress",
76            pauseText : "Pause",
77            stopText : "Stop"
78        },
79        requestControlDialog: {
80            title : "Co-Browse Control Request",
81            text : "The Agent would like to control your web page",
82            grantText : "Grant",
83            denyText : "Deny"
84        },
85        revokeControlDialog: {
86            title : "Co-Browse Control",
87            text : "The agent is currently in control of the co-browse session",
88            revokeText : "Revoke"
89        },
90        joinRequestDialog : {
91            noNameSpecified : "Please enter a name to join the Co-Browse session with",
92            noKeySpecified : "Please enter a Co-Browse Session Key",
93            invalidKeyEntered : "Please enter a valid Co-Browse Session Key (e.g. \"XXXX XXXX\")"
94        },
95        connectionFailureDialog: {
96            title : "Co-Browse Connection",
97            text : "Connection interrupted, attempting to reconnect"
98        },
99        sessionRebuildDialog: {
100            title : "Co-Browse Status",
101            text : "Reconnection in progress"
102        },
103        inactivityCloseDialog : {
104            title : "Co-Browse Idle Timeout",
105            text : "The Co-Browse session has been closed"
106        },
107        inactivityDialog : {
108            title : "Co-Browse Inactive",
109            text : "Do you wish to continue?",
110            confirmButton : "Yes",
111            rejectButton: "No"
112        },
113        joinFailureText : "Join Failed",
114        closeDialogButtonText : "Close",
115        pauseButtonText : "Pause",
116        resumeButtonText : "Resume",
117        invalidInputText: "Invalid Input",
118        grantControlFailed : "Grant Control Failed",
119        denyControlFailed : "Deny Control Failed",
120        revokeControlFailed : "Revoke Control Failed",
121        pauseFailed : "Pause Failed",
122        resumeFailed : "Resuming Session Failed",
123        stopFailed : "Stopping Session Failed"
124    },
125
126    // Image IDs used on the dialogs.
127    statusImageId: '#statusImage',
128    statusImage: '<img src="img/cobrowse/green.png" id="statusImage" class="status-image" />',
129    redStatus: 'img/cobrowse/red.png',
130    greenStatus: 'img/cobrowse/green.png',
131    orangeStatus: 'img/cobrowse/orange.png',
132
133    // iFrame associated IDs.
134    coBrowseIframeWrapper: '.AvayaCoBrowseWrapper',
135    coBrowseIframeId: '#cobrowse',
136
137    // Element ID associated with the "Show Co-Browse" link.
138    showCoBrowseLinkDivId: '#showCoBrowse',
139
140    // Inactivity timer settings.
141    inactiveCount: 0,
142    inactiveTimer: null,
143    inactiveLimit: 60,
144    isInactiveClose: false,
145    isInactiveContinueOpen: false,
146
147    /**
148     * Setups up the Co-Browse UI on page it is loaded from. If it is loaded in 
149     * an iFrame the UI controls will be displayed in the top most document.
150     * 
151     * If the required DIVs for the dialogs do not exist on the page they will
152     * be created by this function.
153     * 
154     * @returns {undefined}
155     */
156    setup: function () {
157        'use strict';
158        
159
160        // Get the top most document.
161        try {
162            coBrowseUI.targetDocument = window.top.document;
163            coBrowseUI.isIframed = window.top !== window.self;
164        } catch (e) { // May be thrown in an iFrame on some browsers if in an iFrame.
165            coBrowseUI.targetDocument = parent.document; // Assumes iFrame is one level deep.
166            coBrowseUI.isIframed = true;
167        }
168
169        // Solution for issue with jQuery getting unloaded from the 
170        // iFrame and leaving broken dialogs.
171        window.addEventListener('unload', coBrowseUI.closeHangingDialogs);
172
173        coBrowseUI.targetDiv = coBrowseUI.targetDocument.body;
174
175        // Check for the required DIVs on each page, if they exist already tear
176        // them down and recreate them to ensure we have a clean state.
177        try {
178
179            var element = $(coBrowseUI.proactiveJoinDialogId, coBrowseUI.targetDocument).length;
180			if (element === 1) {
181                // Already exists, tear it down and recreate.
182                $(coBrowseUI.proactiveJoinDialogId, coBrowseUI.targetDocument).remove();
183            }
184            coBrowseUI.addProactiveJoinDialog();
185
186            element = $(coBrowseUI.requestControlDialogId, coBrowseUI.targetDocument).length;
187            if (element === 1) {
188                // Already exists, tear it down and recreate.
189                $(coBrowseUI.requestControlDialogId, coBrowseUI.targetDocument).remove();
190            }
191            coBrowseUI.addRequestControlDialog();
192
193            element = $(coBrowseUI.coBrowseDialogId, coBrowseUI.targetDocument).length;
194            if (element === 1) {
195                // Already exists, tear it down and recreate.
196                $(coBrowseUI.coBrowseDialogId, coBrowseUI.targetDocument).remove();
197            }
198            coBrowseUI.addCoBrowseDialog();
199
200            element = $(coBrowseUI.errorDialogId, coBrowseUI.targetDocument).length;
201            if (element === 1) {
202                // Already exists, tear it down and recreate.
203                $(coBrowseUI.errorDialogId, coBrowseUI.targetDocument).remove();
204            }
205            coBrowseUI.addErrorDialog();
206            
207            // hide the JavaScript header
208            $('#cobrowseJavaScriptAlertHeader').hide();
209
210        } catch (err) {
211            console.error('Could not create the required dialogs.');
212            console.error(err);
213        }
214    },
215
216    /**
217     * Adds a listener that wishes to be notified of UI events.
218     * 
219     * @param {Object} listener - an object that wants to subscribe to events
220     * @returns {undefined}
221     */
222    addListener: function (listener) {
223        'use strict';
224
225        if (listener) {
226            coBrowseUI.listeners.push(listener);
227        }
228    },
229
230    /**
231     * Adds to the ProactiveJoinDialog used for Voice Co-Browse to the DOM.
232     * 
233     * @returns {undefined}
234     */
235    addProactiveJoinDialog: function () {
236        'use strict';
237
238        var proactiveJoinDialog = coBrowseUI.targetDocument
239                .createElement('div');
240        proactiveJoinDialog.id = coBrowseUI.proactiveJoinDialogId.substring(1);
241
242        var proactiveJoinText = coBrowseUI.targetDocument.createElement('div');
243        proactiveJoinText.id = coBrowseUI.proactiveJoinTextId;
244
245        proactiveJoinDialog.appendChild(proactiveJoinText);
246        coBrowseUI.targetDiv.appendChild(proactiveJoinDialog);
247    },
248
249    /**
250     * Adds the RequestControlDialog used for agent control requests to the DOM.
251     * 
252     * @returns {undefined}
253     */
254    addRequestControlDialog: function () {
255        'use strict';
256
257        var requestControlDialog = coBrowseUI.targetDocument
258                .createElement('div');
259        requestControlDialog.id = coBrowseUI.requestControlDialogId
260                .substring(1);
261
262        var requestControlText = coBrowseUI.targetDocument.createElement('div');
263        requestControlText.id = coBrowseUI.requestControlTextId;
264
265        requestControlDialog.appendChild(requestControlText);
266        coBrowseUI.targetDiv.appendChild(requestControlDialog);
267    },
268
269    /** 
270     * Adds the standard Pause/Stop dialog to the DOM.
271     * 
272     * @returns {undefined}
273     */
274    addCoBrowseDialog: function () {
275        'use strict';
276
277        var coBrowseDialog = coBrowseUI.targetDocument.createElement('div');
278        coBrowseDialog.id = coBrowseUI.coBrowseDialogId.substring(1);
279
280        var coBrowseText = coBrowseUI.targetDocument.createElement('div');
281        coBrowseText.id = coBrowseUI.coBrowseTextId;
282
283        coBrowseDialog.appendChild(coBrowseText);
284        coBrowseUI.targetDiv.appendChild(coBrowseDialog);
285    },
286
287    /**
288     * Adds the generic info/error dialog to the DOM.
289     * 
290     * @returns {undefined}
291     */
292    addErrorDialog: function () {
293        'use strict';
294
295        var errorDialog = coBrowseUI.targetDocument.createElement('div');
296        errorDialog.id = coBrowseUI.errorDialogId.substring(1);
297
298        var errorText = coBrowseUI.targetDocument.createElement('div');
299        errorText.id = coBrowseUI.coBrowseTextId;
300
301        errorDialog.appendChild(errorText);
302        coBrowseUI.targetDiv.appendChild(errorDialog);
303    },
304
305    /**
306     * Cleans up any remaining dialogs and informs any listeners of the event.
307     * 
308     * @returns {undefined}
309     */
310    cleanUp: function () {
311        'use strict';
312        
313        console.log('cleanUp');
314
315        // reset inactive close
316        coBrowseUI.isInactiveClose = false;
317
318        if (coBrowseUI.checkDialogOpen(coBrowseUI.requestControlDialogId) === true) {
319            coBrowseUI.destroyDialog(coBrowseUI.requestControlDialogId);
320        }
321
322        if (coBrowseUI.checkDialogOpen(coBrowseUI.coBrowseDialogId) === true) {
323            coBrowseUI.destroyDialog(coBrowseUI.coBrowseDialogId);
324        }
325
326        // Remove the dialog DIVs.
327        try {
328            console.log('Removing dialogs to ensure clean state.');
329            coBrowseUI.reenableLinks();
330
331            var element = $(coBrowseUI.requestControlDialogId, coBrowseUI.targetDocument).length;
332            if (element === 1) {
333                $(coBrowseUI.requestControlDialogId, coBrowseUI.targetDocument).remove();
334            }
335            element = $(coBrowseUI.coBrowseDialogId, coBrowseUI.targetDocument).length;
336            if (element === 1) {
337                $(coBrowseUI.coBrowseDialogId, coBrowseUI.targetDocument).remove();
338            }
339            element = $(coBrowseUI.errorDialogId, coBrowseUI.targetDocument).length;
340            if (element === 1) {
341                $(coBrowseUI.errorDialogId, coBrowseUI.targetDocument).remove();
342            }
343        } catch (err) {
344            console.error('Could not remove dialog DIVs!');
345            console.error(err);
346        }
347
348        coBrowseUI.fireCleanUp();
349    },
350
351    ////////////////////////////////////////////////////////////////////////////
352    // Co-Browse Event Triggers
353    ////////////////////////////////////////////////////////////////////////////
354
355    /**
356     * Fires the cleanup event notifiying any listeners.
357     * 
358     * @returns {undefined}
359     */
360    fireCleanUp: function () {
361        'use strict';
362        
363        console.log('fireCleanUp');
364
365        coBrowseUI.listeners.forEach(function (listener) {
366            if (listener.onCoBrowseUICleanUp !== undefined) {
367                listener.onCoBrowseUICleanUp(coBrowseUI);
368            }
369        });
370    },
371
372    /**
373     * Fires the JoinRequest event for Voice Co-Browse and notifies any listeners.
374     * 
375     * @returns {undefined}
376     */
377    fireJoinRequest: function () {
378        'use strict';
379        
380        console.log('fireJoinRequest');
381
382        var name = $('#' + coBrowseUI.proactiveJoinNameInputId,
383                coBrowseUI.targetDocument).val();
384        var coBrowseKey = $('#' + coBrowseUI.proactiveJoinSessionKeyInputId,
385                coBrowseUI.targetDocument).val();
386
387        // Basic check of input.
388        if (!name) {
389            coBrowseUI.createInfoDialog('Invalid Input',
390                    'Please enter a name to join the Co-Browse session with.',
391                    coBrowseUI.closeInfoDialog, true);
392            return;
393        }
394        if (!coBrowseKey) {
395            coBrowseUI.createInfoDialog('Invalid Input',
396                    'Please enter a Co-Browse Session Key.',
397                    coBrowseUI.closeInfoDialog, true);
398            return;
399        } else {
400            // Get rid of any white spaces to make matching easier.
401            coBrowseKey = coBrowseKey.replace(/\s+/g, '');
402
403            var regex = /\b\d{8}\b/;
404            var result = coBrowseKey.match(regex);
405
406            if (!result) {
407                coBrowseUI
408                        .createInfoDialog(
409                                'Invalid Input',
410                                'Please enter a valid Co-Browse Session Key (e.g. "XXXX XXXX").',
411                                coBrowseUI.closeInfoDialog, true);
412                return;
413            }
414
415            if (coBrowseKey[4] !== ' ') {
416                // They forgot the space in the key.
417                coBrowseKey = [coBrowseKey.slice(0, 4), ' ',
418                    coBrowseKey.slice(4)].join('');
419            }
420        }
421
422        coBrowseUI.listeners
423                .forEach(function (listener) {
424                    if (listener.onCoBrowseUIJoinRequest !== undefined) {
425                        listener.onCoBrowseUIJoinRequest(coBrowseUI, name,
426                                coBrowseKey);
427                    }
428                });
429    },
430
431    /**
432     * Fires the UIJoinFailure which tells any listeners that UI invoked join failed.
433     * 
434     * @returns {undefined}
435     */
436    fireCoBrowseUIJoinFailure: function () {
437        'use strict';
438        
439        console.log('fireCoBrowseUIJoinFailure');
440
441        coBrowseUI.closeDialog(coBrowseUI.errorDialogId);
442
443        coBrowseUI.listeners.forEach(function (listener) {
444            if (listener.onCoBrowseUIJoinFailure !== undefined) {
445                listener.onCoBrowseUIJoinFailure(coBrowseUI);
446            }
447        });
448    },
449
450    ////////////////////////////////////////////////////////////////////////////
451    // Subscribed Co-Browse Events
452    ////////////////////////////////////////////////////////////////////////////
453
454    /**
455     * Fired when the coBrowse object has loaded the required dependencies.
456     * 
457     * @param {Object} source - the object that generated this event
458     * @returns {undefined}
459     */
460    onCoBrowseReady: function (source) {
461        'use strict';
462        
463        console.log('onCoBrowseReady');
464    },
465
466    /**
467     * Fired when a connection to the Co-Browse session has been established.
468     * 
469     * @param {Object} source - the object that generated this event
470     * @returns {undefined}
471     */
472    onCoBrowseConnection: function (source) {
473        'use strict';
474
475        console.log('onCoBrowseConnection');
476
477        var data = source.coBrowseInstance.getCustomerData();
478        if (data.cobrowseState !== undefined) {
479            // Close all possible open dialogs.
480            coBrowseUI.closeDialog(coBrowseUI.errorDialogId);
481            coBrowseUI.closeDialog(coBrowseUI.coBrowseDialogId);
482            coBrowseUI.closeDialog(coBrowseUI.requestControlDialogId);
483
484            // Rebuild the user interface between pages.
485            if (data.agentControlState === "pending") {
486                coBrowseUI.createRequestControlDialog(true);
487            } else if (data.agentControlState === "true") {
488                coBrowseUI.createRevokeControlDialog(true);
489            } else if (data.cobrowseState === "Paused") {
490                coBrowseUI.onCoBrowsePauseSuccess(source);
491                coBrowseUI.openDialog(coBrowseUI.coBrowseDialogId);
492            } else { // Default state.
493                coBrowseUI.openDialog(coBrowseUI.coBrowseDialogId);
494            }
495        }
496
497        // TODO - test if fixed
498        /*	$(coBrowseUI.statusImageId, coBrowseUI.targetDocument).attr('src',
499         coBrowseUI.greenStatus);*/
500    },
501
502    onCoBrowseConnectionFailure: function (source, error) {
503        'use strict';
504
505        console.error('onCoBrowseConnectionFailure', error);
506
507        coBrowseUI.closeInfoDialog(); // Close it if already open, check performed in closeInfoDialog.
508
509        // Let the user know of the failure.
510        var dialogEntries = coBrowseUI.textEntries.connectionFailureDialog;
511        coBrowseUI.createInfoDialog(dialogEntries.title, dialogEntries.text, coBrowseUI.closeInfoDialog, true);
512    },
513
514    /**
515     * Fired when the coBrowse is rebuilding, normally this happens when moving 
516     * between pages.
517     * 
518     * @param {Object} source - the object that generated this event
519     * @returns {undefined}
520     */
521    onCoBrowseRebuild: function (source) {
522        'use strict';
523
524        console.log('onCoBrowseRebuild');
525
526        // Reset the state of these dialogs.
527        coBrowseUI.createPauseStopDialog(false);
528
529        var dialogEntries = coBrowseUI.textEntries.sessionRebuildDialog;
530        coBrowseUI.createInfoDialog(dialogEntries.title, dialogEntries.text, coBrowseUI.closeInfoDialog, true);
531    },
532
533    /**
534     * Fired when a Co-Browse session has been closed. Updates the UI to reflect
535     * this state.
536     * 
537     * @param {Object} source - the object that generated this event
538     * @param {string} title - title to be used on the closing dialog
539     * @param {string} text - text to be displayed on the closing dialog
540     * @returns {undefined}
541     */
542    onCoBrowseSessionClose: function (source, title, text) {
543        'use strict';
544        
545        console.log('onCoBrowseSessionClose');
546
547        coBrowseUI.closeHangingDialogs();
548
549        if (coBrowseUI.isInactiveContinueOpen) {
550            coBrowseUI.destroyDialog(coBrowseUI.errorDialogId);
551        }
552
553        coBrowseUI.closeDialog(coBrowseUI.coBrowseDialogId);
554        coBrowseUI.createCloseDialog(title, text, true);
555    },
556
557    /**
558     * Fired when a control request has been received.
559     * 
560     * @param {Object} source - the object that generated this event
561     * @returns {undefined}
562     */
563    onCoBrowseControlRequest: function (source) {
564        'use strict';
565
566	console.log('onCoBrowseControlRequest');
567
568        coBrowseUI.closeDialog(coBrowseUI.coBrowseDialogId);
569        coBrowseUI.createRequestControlDialog(true);
570    },
571
572    /**
573     * Fired when the other party has stopped controlling the session.
574     * 
575     * @param {Object} source - the object that generated this event
576     * @returns {undefined}
577     */
578    onCoBrowseControlRelease: function (source) {
579        'use strict';
580        
581        console.log('onCoBrowseControlRelease');
582
583		// when request control is received but neither of grant/deny is pressed, one of these remains true
584		// so don't hide the dialog in case there was no user response for request control
585		if (coBrowse.getSessionItem(coBrowse.inControlRequest) === "fal
585se" && coBrowse.getSessionItem(coBrowse.agentInControl) === "false") {
586			coBrowseUI.closeDialog(coBrowseUI.requestControlDialogId);
587			coBrowseUI.openDialog(coBrowseUI.coBrowseDialogId);
588        }
589    },
590
591    /**
592     * Fired when a succcessful join has taken place, makes the call to display
593     * the Pause/Stop dialog.
594     * 
595     * @param {Object} source - the object that generated this event
596     * @returns {undefined}
597     */
598    onCoBrowseJoinSuccess: function (source) {
599        'use strict';
600        
601        console.log('onCoBrowseJoinSuccess');
602        coBrowseUI.disableLinks();
603
604        if (!coBrowseUI.isIframed) {
605            coBrowseUI.closeDialog(coBrowseUI.proactiveJoinDialogId);
606        }
607
608        coBrowseUI.createPauseStopDialog(true);
609    },
610
611    /**
612     * Fired when a join request has failed.
613     * 
614     * @param {Object} source - the object that generated this event
615     * @param {Object} error - cause of the failure
616     * @returns {undefined}
617     */
618    onCoBrowseJoinFailure: function (source, error) {
619        'use strict';
620        
621        console.log('onCoBrowseJoinFailure');
622
623        var title = coBrowseUI.textEntries.joinFailureText;
624        coBrowseUI.createInfoDialog(title, error + '.',
625                coBrowseUI.fireCoBrowseUIJoinFailure, true);
626    },
627
628    /**
629     * Fired when control has been successfully granted to the other party.
630     * 
631     * @param {Object} source - the object that generated this event
632     * @returns {undefined}
633     */
634    onCoBrowseGrantControlSuccess: function (source) {
635        'use strict';
636        
637        console.log('onCoBrowseGrantControlSuccess');
638
639        coBrowseUI.closeDialog(coBrowseUI.requestControlDialogId);
640        coBrowseUI.createRevokeControlDialog(true);
641    },
642
643    /**
644     * Fired when a grant control request fails.
645     * 
646     * @param {Object} source - the object that generated this event
647     * @param {Object} error - cause of the failure
648     * @returns {undefined}
649     */
650    onCoBrowseGrantControlFailure: function (source, error) {
651        'use strict';
652        
653        console.log('onCoBrowseGrantControlFailure');
654
655        var title = coBrowseUI.textEntries.grantControlFailed;
656        coBrowseUI.createInfoDialog(title, error + '.',
657                coBrowseUI.closeInfoDialog, true);
658    },
659
660    /**
661     * Fired when a control request has been successfully denined.
662     * 
663     * @param {Object} source - the object that generated this event
664     * @returns {undefined}
665     */
666    onCoBrowseDenyControlSuccess: function (source) {
667        'use strict';
668        
669        console.log('onCoBrowseDenyControlSuccess');
670
671        coBrowseUI.closeDialog(coBrowseUI.requestControlDialogId);
672        coBrowseUI.openDialog(coBrowseUI.coBrowseDialogId);
673    },
674
675    /**
676     * Fired when a deny of control has failued.
677     * 
678     * @param {Object} source - the object that generated this event
679     * @param {Object} error - cause of the failure
680     * @returns {undefined}
681     */
682    onCoBrowseDenyControlFailure: function (source, error) {
683        'use strict';
684        
685        console.log('onCoBrowseDenyControlFailure');
686
687        var title = coBrowseUI.textEntries.denyControlFailed;
688        coBrowseUI.createInfoDialog(title, error + '.',
689                coBrowseUI.closeInfoDialog, true);
690    },
691
692    /**
693     * Fired when a revoke has been successful.
694     * 
695     * @param {Object} source - the object that generated this event
696     * @returns {undefined}
697     */
698    onCoBrowseRevokeControlSuccess: function (source) {
699        'use strict';
700        
701        console.log('onCoBrowseRevokeControlSuccess');
702
703        coBrowseUI.closeDialog(coBrowseUI.requestControlDialogId);
704        coBrowseUI.openDialog(coBrowseUI.coBrowseDialogId);
705    },
706
707    /**
708     * Fired when a request to revoke control has failed.
709     * 
710     * @param {Object} source - the object that generated this event
711     * @param {Object} error - cause of the failrue
712     * @returns {undefined}
713     */
714    onCoBrowseRevokeControlFailure: function (source, error) {
715        'use strict';
716        
717        console.log('onCoBrowseRevokeControlFailure');
718
719        var title = coBrowseUI.textEntries.revokeControlFailed;
720        coBrowseUI.createInfoDialog(title, error + '.',
721                coBrowseUI.closeInfoDialog, true);
722    },
723
724    /**
725     * Fired when the session has been successfully paused.
726     * 
727     * @param {Object} source - the object that generated this event
728     * @returns {undefined}
729     */
730    onCoBrowsePauseSuccess: function (source) {
731        'use strict';
732        
733        console.log('onCoBrowsePauseSuccess');
734
735        var label = coBrowseUI.textEntries.resumeButtonText;
736        $('#' + coBrowseUI.pauseButtonId, coBrowseUI.targetDocument).button(
737                'option', 'label', label);
738        $(coBrowseUI.statusImageId, coBrowseUI.targetDocument).attr('src',
739                coBrowseUI.orangeStatus);
740    },
741
742    /**
743     * Fired when a pause request has failed.
744     * 
745     * @param {Object} source - the object that generated this event
746     * @param {Object} error - cause of the error
747     * @returns {undefined}
748     */
749    onCoBrowsePauseFailure: function (source, error) {
750        'use strict';
751        
752        console.log('onCoBrowsePauseFailure');
753
754        var title = coBrowseUI.textEntries.pauseFailed;
755        coBrowseUI.createInfoDialog(title, error + '.',
756                coBrowseUI.closeInfoDialog, true);
757    },
758
759    /**
760     * Fired when a request to resume the session has been successful.
761     * 
762     * @param {Object} source - the object that generated this event
763     * @returns {undefined}
764     */
765    onCoBrowseResumeSuccess: function (source) {
766        'use strict';
767        
768        console.log('onCoBrowseResumeSuccess');
769
770        var label = coBrowseUI.textEntries.pauseButtonText;
771        $('#' + coBrowseUI.pauseButtonId, coBrowseUI.targetDocument).button(
772                'option', 'label', label);
773        $(coBrowseUI.statusImageId, coBrowseUI.targetDocument).attr('src',
774                coBrowseUI.greenStatus);
775    },
776
777    /**
778     * Fired when a request to resume the session has failed.
779     * 
780     * @param {Object} source - the object that generated this event
781     * @param {Object} error - cause of the failure
782     * @returns {undefined}
783     */
784    onCoBrowseResumeFailure: function (source, error) {
785        'use strict';
786        
787        console.log('onCoBrowseResumeFailure');
788
789        var title = coBrowseUI.textEntries.resumeFailed;
790        coBrowseUI.createInfoDialog(title, error + '.',
791                coBrowseUI.closeInfoDialog, true);
792    },
793
794    /**
795     * Fired when a request to stop the session has been successful.
796     * 
797     * @param {Object} source - the object that generated this event
798     * @returns {undefined}
799     */
800    onCoBrowseStopSuccess: function (source) {
801        'use strict';
802        
803        console.log('onCoBrowseStopSuccess');
804        
805        // timeout close button
806        if (!coBrowseUI.isInactiveClose) {
807            coBrowseUI.cleanUp();
808        }
809    },
810
811    /**
812     * Fired when a request to stop the session has failed.
813     * 
814     * @param {Object} source - the object that generated this event
815     * @param {Object} error - cause of the failure
816     * @returns {undefined}
817     */
818    onCoBrowseStopFailure: function (source, error) {
819        'use strict';
820        
821        console.log('onCoBrowseStopFailure');
822
823        var title = coBrowseUI.textEntries.stopFailed;
824        coBrowseUI.createInfoDialog(title, error + '.',
825                coBrowseUI.closeInfoDialog, true);
826    },
827
828    /**
829     * Fired when a the session has become inactive.
830     * 
831     * @param {Object} source - the object that generated this event
832     * @param {String} message - a message from the server
833     * @returns {undefined}
834     */
835    fireOnCoBrowseInactive: function (source, message) {
836        'use strict';
837        coBrowseUI.createInactivityDialog(true, message);
838        coBrowseUI.startInactivityLocalTimer();
839    },
840
841    ////////////////////////////////////////////////////////////////////////////
842    // Inactivity Functions
843    ////////////////////////////////////////////////////////////////////////////
844
845    /**
846     * Stops the Co-Browse inactive timer.
847     * 
848     * @param {Object} source - the object that generated this event
849     * @returns {undefined}
850     */
851    stopOnCoBrowseInactive: function (source) {
852        'use strict';
853
854        coBrowseUI.stopInactivityLocalTimer();
855    },
856
857    /**
858     * Stops the inactivity timer and clears the interval.
859     * 
860     * @returns {undefined}
861     */
862    stopInactivityLocalTimer: function () {
863        'use strict';
864
865        if (coBrowseUI.inactiveTimer !== null) {
866            clearInterval(coBrowseUI.inactiveTimer);
867        }
868
869        coBrowseUI.inactiveCount = 0;
870    },
871
872    /**
873     * Stops the session when the timeout has been reached an cleans up any
874     * open dialogs.
875     * 
876     * @param {Object} source - the object that generated this event
877     * @returns {undefined}
878     */
879    stopSessionWithTidyUp: function (source) {
880        'use strict';
881
882        coBrowseUI.isInactiveContinueOpen = false;
883        var reason = "inactive_timeout";
884        var dialog = coBrowseUI.errorDialogId;
885        coBrowse.updateIdleTimer(coBrowseUI.inactiveCount);
886        coBrowse.stopSessionWithReason(reason);
887        coBrowseUI.closeDialog(dialog);
888        coBrowseUI.stopInactivityLocalTimer();
889    },
890
891    /**
892     * Restarts the inactivity timer on the page.
893     * 
894     * @param {Object} source - the object that generated this event
895     * @returns {undefined}
896     */
897    restartInactivityTimer: function (source) {
898        'use strict';
899
900        coBrowseUI.isInactiveContinueOpen = false;
901
902        if (!coBrowseUI.checkDialogOpen(coBrowseUI.requestControlDialogId)) {
903            coBrowseUI.openDialog(coBrowseUI.coBrowseDialogId);
904        }
905
906        var dialog = coBrowseUI.errorDialogId;
907        coBrowse.updateIdleTimer(coBrowseUI.inactiveCount);
908        coBrowseUI.closeDialog(dialog);
909        coBrowseUI.stopInactivityLocalTimer();
910    },
911
912    /**
913     * Starts the Inactivity timer, if there is not activity on the session
914     * then the dialog will appear to the user.
915     * 
916     * Resets the timer if the there is already a value.
917     * 
918     * @returns {undefined}
919     */
920    startInactivityLocalTimer: function () {
921        'use strict';
922
923        if (coBrowseUI.inactiveTimer !== null) {
924            clearInterval(coBrowseUI.inactiveTimer);
925        }
926
927        coBrowseUI.inactiveTimer = setInterval(function () {
928            coBrowseUI.inactiveCount = coBrowseUI.inactiveCount + 1;
929            if (coBrowseUI.inactiveCount >= coBrowseUI.inactiveLimit) {
930                var dialogEntries = coBrowseUI.textEntries.inactivityCloseDialog;
931                coBrowseUI.isInactiveClose = true;
932                coBrowseUI.stopSessionWithTidyUp(coBrowseUI.errorDialogId);
933                coBrowseUI.createInfoDialog(dialogEntries.title,
934                        dialogEntries.text,
935                        coBrowseUI.closeInfoDialog, true);
936            }
937        }, 1000);
938    },
939
940    ///////////////////////////////////////////////////////////////////////////
941    // UI Dialog Functions
942    ////////////////////////////////////////////////////////////////////////////
943
944    /**
945     * Closes the generic info/error dialog.
946     * 
947     * @returns {undefined}
948     */
949    closeInfoDialog: function () {
950        'use strict';
951
952        coBrowseUI.closeDialog(coBrowseUI.errorDialogId);
953    },
954
955    /**
956     * Removes the inactive warning dialog.
957     * 
958     * @returns {undefined}
959     */
960    removeInactiveCloseDialog: function () {
961        "use strict";
962        coBrowseUI.destroyDialog(coBrowseUI.errorDialogId);
963        coBrowseUI.cleanUp();
964    },
965
966    /**
967     * Creates an instance of the Info dialog used for info and error notifications.
968     * 
969     * @param {string} title - title to display on the info dialog
970     * @param {string} text - text to display on the info dialog
971     * @param {Object} callback - function to invoke on close button click
972     * @param {boolean} autoOpen - should it open automatically
973     * @returns {undefined}
974     */
975    createInfoDialog: function (title, text, callback, autoOpen) {
976        'use strict';
977
978        if ($(coBrowseUI.errorDialogId, coBrowseUI.targetDocument).length === 0) {
979            coBrowseUI.addErrorDialog();
980        }
981
982        var isModal = true;
983        var buttons = [];
984        var closeButtonText = coBrowseUI.textEntries.closeDialogButtonText;
985
986        if (coBrowseUI.isInactiveClose) {
987            buttons.push(coBrowseUI.createButton(coBrowseUI.closeButtonId,
988                    closeButtonText, coBrowseUI.removeInactiveCloseDialog
989                    .bind(coBrowseUI)));
990        } else {
991            buttons.push(coBrowseUI.createButton(coBrowseUI.closeButtonId,
992                    closeButtonText, callback.bind(coBrowseUI)));
993        }
994
995        coBrowseUI.showDialog(coBrowseUI.errorDialogId, text, title, isModal, buttons, coBrowseUI.errorDialogId, null, null, false, autoOpen);
996    },
997
998    /**
999     * Creates a instance of the Inactivity dialog.
1000     * 
1001     * @param {boolean} autoOpen - should it open automatically
1002     * @param {String} alertMessage - a message to show in the panel. Defined in the SMGR attributes.
1003     * @returns {undefined}
1004     */
1005    createInactivityDialog: function (autoOpen, alertMessage) {
1006		'use strict';
1007		
1008	if ($(coBrowseUI.errorDialogId, coBrowseUI.targetDocument).length === 0) {
1009            coBrowseUI.addErrorDialog();
1010        }
1011
1012        //TODO - hide grant/deny dialog show later
1013        var dialogEntries = coBrowseUI.textEntries.inactivityDialog;
1014        var text = alertMessage;
1015        var title = dialogEntries.title;
1016        var isModal = true;
1017        var buttons = [];
1018        var dialog = coBrowseUI.errorDialogId;
1019        coBrowseUI.isInactiveContinueOpen = true;
1020        buttons.push(coBrowseUI.createButton(coBrowseUI.inactiveContinueId,
1021                dialogEntries.confirmButton, coBrowseUI.restartInactivityTimer.bind(coBrowseUI)));
1022
1023        buttons.push(coBrowseUI.createButton(coBrowseUI.inactiveStopId, dialogEntries.rejectButton,
1024                coBrowseUI.stopSessionWithTidyUp.bind(coBrowseUI)));
1025
1026        coBrowseUI.closeDialog(coBrowseUI.coBrowseDialogId);
1027
1028        coBrowseUI.showDialog(dialog, text, title, isModal, buttons, '', null,
1029                null, false, autoOpen);
1030    },
1031
1032    /**
1033     * Creates a instance of the ProactiveJoin dialog used for Voice.
1034     * 
1035     * @param {boolean} autoOpen - should it open automatically
1036     * @returns {undefined}
1037     */
1038    createProactiveJoinDialog: function (autoOpen) {
1039        'use strict';
1040
1041	if ($(coBrowseUI.proactiveJoinDialogId, coBrowseUI.targetDocument).length === 0) {
1042            coBrowseUI.addProactiveJoinDialog();
1043        }
1044        
1045        // get the configured buttons/labels for this div
1046        var dialogEntries = coBrowseUI.textEntries.proactiveJoin;
1047
1048        var text = dialogEntries.text;
1049        var title = dialogEntries.title;
1050        var isModal = false;
1051        var buttons = [];
1052        buttons.push(coBrowseUI.createButton(coBrowseUI.joinButtonId, dialogEntries.joinButtonText,
1053                coBrowseUI.fireJoinRequest.bind(coBrowseUI)));
1054
1055        var proactiveJoinNameInput = coBrowseUI.targetDocument
1056                .createElement('input');
1057        proactiveJoinNameInput.id = coBrowseUI.proactiveJoinNameInputId;
1058        proactiveJoinNameInput.type = 'text';
1059        proactiveJoinNameInput.size = 20;
1060        proactiveJoinNameInput.placeholder = dialogEntries.nameLabel;
1061        proactiveJoinNameInput.className = 'join-field';
1062
1063        var proactiveJoinSessionKeyInput = coBrowseUI.targetDocument
1064                .createElement('input');
1065        proactiveJoinSessionKeyInput.id = coBrowseUI.proactiveJoinSessionKeyInputId;
1066        proactiveJoinSessionKeyInput.type = 'text';
1067        proactiveJoinSessionKeyInput.size = 20;
1068        proactiveJoinSessionKeyInput.placeholder = dialogEntries.sessionKey;
1069        proactiveJoinSessionKeyInput.className = 'join-field';
1070
1071        var children = [proactiveJoinNameInput, proactiveJoinSessionKeyInput];
1072
1073        coBrowseUI.showDialog(coBrowseUI.proactiveJoinDialogId, text, title, isModal, buttons, coBrowseUI.proactiveJoinDialogId, null, children, true, autoOpen);
1074    },
1075
1076    /**
1077     * Creates an instance of the Pause/Stop dialog.
1078     * 
1079     * @param {boolean} autoOpen - should it open automatically
1080     * @returns {undefined}
1081     */
1082    createPauseStopDialog: function (autoOpen) {
1083        'use strict';
1084
1085        if ($(coBrowseUI.coBrowseDialogId, coBrowseUI.targetDocument).length === 0) {
1086            coBrowseUI.addCoBrowseDialog();
1087        }
1088        
1089        var dialogEntries = coBrowseUI.textEntries.pauseStopDialog;
1090
1091        var text = dialogEntries.text;
1092        var title = dialogEntries.title;
1093        var isModal = false;
1094        var buttons = [];
1095        buttons.push(coBrowseUI.createButton(coBrowseUI.pauseButtonId, dialogEntries.pauseText, coBrowse.togglePause.bind(coBrowse)));
1096        buttons.push(coBrowseUI.createButton(coBrowseUI.stopButtonId, dialogEntries.stopText, coBrowse.stopSession.bind(coBrowse)));
1097
1098        coBrowseUI.showDialog(coBrowseUI.coBrowseDialogId, text, title, isModal, buttons, coBrowseUI.coBrowseDialogId, coBrowseUI.statusImage, null, false, autoOpen);
1099
1100        $(coBrowseUI.statusImageId, coBrowseUI.targetDocument).attr('src',
1101                coBrowseUI.greenStatus);
1102    },
1103
1104    /**
1105     * Creates an instance of the close dialog.
1106     * 
1107     * @param {string} title - title to use on the close dialog
1108     * @param {string} text - text to use on the close dialog
1109     * @param {boolean} autoOpen - should it open automatically
1110     * @returns {undefined}
1111     */
1112    createCloseDialog: function (title, text, autoOpen) {
1113        'use strict';
1114
1115        if ($(coBrowseUI.coBrowseDialogId, coBrowseUI.targetDocument).length === 0) {
1116            coBrowseUI.addCoBrowseDialog();
1117        }
1118        
1119        var closeButtonText = coBrowseUI.textEntries.closeDialogButtonText;
1120        var isModal = true;
1121        var buttons = [];
1122        buttons.push(coBrowseUI.createButton(coBrowseUI.closeButtonId, closeButtonText,
1123                coBrowseUI.cleanUp.bind(coBrowseUI)));
1124
1125        coBrowseUI.showDialog(coBrowseUI.coBrowseDialogId, text, title, isModal, buttons, coBrowseUI.coBrowseDialogId, coBrowseUI.statusImage, null, false, autoOpen);
1126    },
1127
1128    /**
1129     * Creates an instance of the RequestControl.
1130     * 
1131     * @param {boolean} autoOpen - should it open automatically
1132     * @returns {undefined}
1133     */
1134    createRequestControlDialog: function (autoOpen) {
1135        'use strict';
1136
1137        if ($(coBrowseUI.requestControlDialogId, coBrowseUI.targetDocument).length === 0) {
1138            coBrowseUI.addRequestControlDialog();
1139        }
1140        
1141        // get the configured buttons/labels for this div
1142        var dialogEntries = coBrowseUI.textEntries.requestControlDialog;
1143
1144        var text = dialogEntries.text;
1145        var title = dialogEntries.title;
1146        var isModal = true;
1147        var buttons = [];
1148        buttons.push(coBrowseUI.createButton(coBrowseUI.grantButtonId, dialogEntries.grantText,
1149                coBrowse.grantControl.bind(coBrowse)));
1150        buttons.push(coBrowseUI.createButton(coBrowseUI.denyButtonId, dialogEntries.denyText,
1151                coBrowse.denyControl.bind(coBrowse)));
1152
1153        coBrowseUI.showDialog(coBrowseUI.requestControlDialogId, text, title, isModal, buttons, coBrowseUI.requestControlDialogId, null, null, false, autoOpen);
1154    },
1155
1156    /**
1157     * Creates an instance of the RevokeControl dialog.
1158     * 
1159     * @param {boolean} autoOpen - should it open automatically
1160     * @returns {undefined}
1161     */
1162    createRevokeControlDialog: function (autoOpen) {
1163        'use strict';
1164
1165        if ($(coBrowseUI.requestControlDialogId, coBrowseUI.targetDocument).length === 0) {
1166            coBrowseUI.addRequestControlDialog();
1167        }
1168        
1169        // get the configured buttons/labels for this div
1170        var dialogEntries = coBrowseUI.textEntries.revokeControlDialog;
1171
1172        var text = dialogEntries.text;
1173        var title = dialogEntries.title;
1174        var isModal = false;
1175        var buttons = [];
1176        buttons.push(coBrowseUI.createButton(coBrowseUI.revokeButtonId,
1177                dialogEntries.revokeText, coBrowse.revokeControl.bind(coBrowse)));
1178
1179        coBrowseUI.showDialog(coBrowseUI.requestControlDialogId, text, title, isModal, buttons, coBrowseUI.requestControlDialogId, null, null, false, autoOpen);
1180    },
1181
1182    /**
1183     * Shows a dialog to the user.
1184     * 
1185     * @param {string} dialog - element ID
1186     * @param {string} text - text message for the dialog
1187     * @param {string} title - title message for the dialog
1188     * @param {boolean} isModal - is this a modal dialog
1189     * @param {Object[]} buttons - collection of buttons on the dialog
1190     * @param {string} hiddenId - ID passed to coBrowse to hide this dialog
1191     * @param {string} statusImage - image to display in the top left corner
1192     * @param {Object[]} children - child DOM elements
1193     * @param {boolean} isCloseable - can this dialog be closed using the X button
1194     * @param {boolean} autoOpen - should it open automatically
1195     * @returns {undefined}
1196     */
1197    showDialog: function (dialog, text, title, isModal, buttons, hiddenId,
1198            statusImage, children, isCloseable, autoOpen) {
1199        'use strict';
1200
1201        var activeElement = coBrowseUI.targetDocument.activeElement;
1202
1203        var width = '250px';
1204        if (dialog === coBrowseUI.proactiveJoinDialogId) {
1205            width = 'auto';
1206        }
1207
1208        $(dialog, coBrowseUI.targetDocument).text(text);
1209        $(dialog, coBrowseUI.targetDocument)
1210                .dialog(
1211                        {
1212                            autoOpen: autoOpen,
1213                            width: width,
1214                            resizable: false,
1215                            dialogClass: 'cbe-container',
1216                            title: title,
1217                            modal: false,
1218                            closeOnEscape: false,
1219                            create: function () {
1220                                if (!isCloseable) {
1221                                    $(this, coBrowseUI.targetDocument).dialog(
1222                                            'widget').find(
1223                                            '.ui-dialog-titlebar-close')
1224                                            .remove();
1225                                }
1226
1227                                if (statusImage) {
1228                                    $(this, coBrowseUI.targetDocument).parent()
1229                                            .children(".ui-dialog-titlebar")
1230                                            .prepend(statusImage);
1231                                }
1232                                
1233                                hiddenId = (hiddenId + coBrowseUI.hiddenPostFix).replace('#', '');
1234                                $(this, coBrowseUI.targetDocument).dialog('widget').attr('id', hiddenId);
1235                            },
1236                            open: function () {
1237                                $(this).blur();
1238                                $(this, coBrowseUI.targetDocument).dialog(
1239                                        'widget').position({
1240                                    my: 'center',
1241                                    at: 'center',
1242                                    of: window
1243                                });
1244                                if (activeElement) {
1245                                    console.log('Resetting focus to: ' + activeElement.id);
1246   
1246                                 activeElement.focus();
1247                                }
1248                            },
1249                            buttons: buttons
1250                        });
1251
1252        if (children) {
1253            children.forEach(function (child) {
1254                $(dialog, coBrowseUI.targetDocument).append(child);
1255            });
1256        }
1257    },
1258
1259    /**
1260     * Checks if a dialog is open in the DOM.
1261     * 
1262     * @param {string} dialog - element ID
1263     * @returns {Boolean}
1264     */
1265    checkDialogOpen: function (dialog) {
1266        'use strict';
1267
1268        try {
1269            return $(dialog, coBrowseUI.targetDocument).hasClass("ui-dialog-content") && $(dialog, window.parent.document).dialog('isOpen') === true;
1270        } catch (ex) { // Thrown if the dialog hasn't been initialised for some reason.
1271            console.log('Dialog is not open: ' + dialog);
1272            return false;
1273        }
1274    },
1275
1276    /**
1277     * Opens a dialog displaying it to the user.
1278     * 
1279     * @param {string} dialog - element ID
1280     * @returns {undefined}
1281     */
1282    openDialog: function (dialog) {
1283        'use strict';
1284
1285        console.log('Opening dialog: ' + dialog);
1286
1287        if ($(dialog, coBrowseUI.targetDocument).length === 0) {
1288            if (dialog === coBrowseUI.coBrowseDialogId) {
1289                coBrowseUI.addCoBrowseDialog();
1290                coBrowseUI.createPauseStopDialog(true);
1291            } else if (dialog === coBrowseUI.requestControlDialogId) {
1292                coBrowseUI.addRequestControlDialog();
1293                coBrowseUI.createRequestControlDialog(true);
1294            }
1295        } else {
1296            if (coBrowseUI.checkDialogOpen(dialog)) {
1297                console.log('Dialog is already open: ' + dialog);
1298                return; // Already open.
1299            }
1300
1301            try {
1302                $(dialog, coBrowseUI.targetDocument).dialog('open');
1303            } catch (err) {
1304                // Looking for jQuery UI issues.
1305                console.error('Could not open dialog: ' + dialog);
1306                console.error(err);
1307            }
1308        }
1309    },
1310
1311    /**
1312     * Closes a dialog hiding it from a user.
1313     * 
1314     * @param {string} dialog - element ID
1315     * @returns {undefined}
1316     */
1317    closeDialog: function (dialog) {
1318        'use strict';
1319
1320        console.log('Closing dialog: ' + dialog);
1321
1322        // Completely remove the dialog from the DOM to work around the
1323        // breaking jQuery dialog issue.
1324        try {
1325            $(dialog, coBrowseUI.targetDocument).remove();
1326        } catch (err) {
1327            console.warn('Could not remove dialog from the DOM: ' + dialog);
1328        }
1329    },
1330
1331    /**
1332     * Completely destroys a dialog, used for cleanup routines.
1333     * 
1334     * @param {string} dialog - element ID
1335     * @returns {undefined}
1336     */
1337    destroyDialog: function (dialog) {
1338        'use strict';
1339
1340        console.log('Destroying dialog: ' + dialog);
1341
1342        // Completely remove the dialog from the DOM to work around the
1343        // breaking jQuery dialog issue.
1344        try {
1345            $(dialog, coBrowseUI.targetDocument).remove();
1346        } catch (err) {
1347            console.warn('Could not remove dialog from the DOM: ' + dialog);
1348        }
1349    },
1350
1351    /**
1352     * Creates a button for use with the Co-Browse dialogs.
1353     * 
1354     * @param {string} id
1355     * @param {string} text
1356     * @param {Object} click - callback function to execute on button click
1357     * @returns {coBrowseUI.createButton.coBrowseUIAnonym$3}
1358     */
1359    createButton: function (id, text, click) {
1360        'use strict';
1361
1362        return {
1363            id: id,
1364            text: text,
1365            click: click
1366        };
1367    },
1368
1369    /**
1370     * Shows the Co-browse iFrame.
1371     * 
1372     * @param {string} url - URL to open in the iFrame
1373     * @returns {undefined}
1374     */
1375    showCoBrowseIframe: function (url) {
1376        'use strict';
1377
1378        $(coBrowseUI.coBrowseIframeWrapper, coBrowseUI.targetDocument).hide();
1379        $(coBrowseUI.coBrowseIframeId, coBrowseUI.targetDocument).attr('src',
1380                url);
1381        $(coBrowseUI.coBrowseIframeId, coBrowseUI.targetDocument).show();
1382    },
1383
1384    /**
1385     * Closes any potentially hanging dialogs.
1386     * 
1387     * @returns {undefined}
1388     */
1389    closeHangingDialogs: function () {
1390        'use strict';
1391        
1392        console.log('closeHangingDialogs');
1393
1394        var dialogList = [
1395            coBrowseUI.errorDialogId,
1396            coBrowseUI.coBrowseDialogId,
1397            coBrowseUI.requestControlDialogId
1398        ];
1399
1400        var size = dialogList.length;
1401        for (var i = 0; i < size; i++) {
1402            coBrowseUI.destroyDialog(dialogList[i]);
1403        }
1404    },
1405
1406    /**
1407     * Hides the Co-Browsing iFrame.
1408     */
1409    hideCoBrowseIframe: function () {
1410        'use strict';
1411
1412        $(coBrowseUI.coBrowseIframeId, coBrowseUI.targetDocument).hide();
1413        $(coBrowseUI.coBrowseIframeId, coBrowseUI.targetDocument).attr('src',
1414                '');
1415        $(coBrowseUI.coBrowseIframeWrapper, coBrowseUI.targetDocument).show();
1416    },
1417
1418    /**
1419     * Shows the Co-Browse div link for toggling the proactive dialog.
1420     */
1421    showCoBrowseLinkDiv: function () {
1422        'use strict';
1423
1424        $(coBrowseUI.showCoBrowseLinkDivId, coBrowseUI.targetDocument).show();
1425    },
1426
1427    /**
1428     * Hides the Co-Browse div link for toggling the proactive dialog.
1429     */
1430    hideCoBrowseLinkDiv: function () {
1431        'use strict';
1432
1433        $(coBrowseUI.showCoBrowseLinkDivId, coBrowseUI.targetDocument).hide();
1434    },
1435    
1436    /**
1437     * Temporarily disable any links that are marked as "ignore cobrowse"
1438     */
1439    disableLinks: function() {
1440        'use strict';
1441        $(".ignoreCobrowse").click(function(event){
1442            event.preventDefault();
1443        });
1444    },
1445    
1446    reenableLinks: function() {
1447        'use strict';
1448        $(".ignoreCobrowse").unbind("click");
1449    }
1450
1451};
1452
1453$(function () {
1454    'use strict';
1455    coBrowseUI.setup();
1456});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.