PageSourceSearch

https://www.knowyouknowme.com/wp-content/plugins/simply-schedule-a…/assets/js/iframe-outer.js?ver=1.6.12.33

js knowyouknowme.com collected 2026-09-24 14:15:29 UTC 42,729 bytes, 1,615 lines download raw bytes

1/*
2 * File: iframeResizer.js
3 * Desc: Force iframes to size to content.
4 * Requires: iframeResizer.contentWindow.js to be loaded into the target frame.
5 * Doc: https://github.com/davidjbradshaw/iframe-resizer
6 * Author: David J. Bradshaw - [email protected]
7 * Contributor: Jure Mav - [email protected]
8 * Contributor: Reed Dadoune - [email protected]
9 */
10
11// eslint-disable-next-line sonarjs/cognitive-complexity, no-shadow-restricted-names
12;(function (undefined) {
13  if (typeof window === 'undefined') return // don't run for server side render
14
15  var count = 0,
16    logEnabled = false,
17    hiddenCheckEnabled = false,
18    msgHeader = 'message',
19    msgHeaderLen = msgHeader.length,
20    msgId = '[iFrameSizer]', // Must match iframe msg ID
21    msgIdLen = msgId.length,
22    pagePosition = null,
23    requestAnimationFrame = window.requestAnimationFrame,
24    resetRequiredMethods = {
25      max: 1,
26      scroll: 1,
27      bodyScroll: 1,
28      documentElementScroll: 1
29    },
30    settings = {},
31    timer = null,
32    defaults = {
33      autoResize: true,
34      bodyBackground: null,
35      bodyMargin: null,
36      bodyMarginV1: 8,
37      bodyPadding: null,
38      checkOrigin: true,
39      inPageLinks: false,
40      enablePublicMethods: true,
41      heightCalculationMethod: 'bodyOffset',
42      id: 'iFrameResizer',
43      interval: 32,
44      log: false,
45      maxHeight: Infinity,
46      maxWidth: Infinity,
47      minHeight: 0,
48      minWidth: 0,
49      mouseEvents: true,
50      resizeFrom: 'parent',
51      scrolling: false,
52      sizeHeight: true,
53      sizeWidth: false,
54      warningTimeout: 5000,
55      tolerance: 0,
56      widthCalculationMethod: 'scroll',
57      onClose: function () {
58        return true
59      },
60      onClosed: function () {},
61      onInit: function () {},
62      onMessage: function () {
63        warn('onMessage function not defined')
64      },
65      onMouseEnter: function () {},
66      onMouseLeave: function () {},
67      onResized: function () {},
68      onScroll: function () {
69        return true
70      }
71    }
72
73  function getMutationObserver() {
74    return (
75      window.MutationObserver ||
76      window.WebKitMutationObserver ||
77      window.MozMutationObserver
78    )
79  }
80
81  function addEventListener(el, evt, func) {
82    el.addEventListener(evt, func, false)
83  }
84
85  function removeEventListener(el, evt, func) {
86    el.removeEventListener(evt, func, false)
87  }
88
89  function setupRequestAnimationFrame() {
90    var vendors = ['moz', 'webkit', 'o', 'ms']
91    var x
92
93    // Remove vendor prefixing if prefixed and break early if not
94    for (x = 0; x < vendors.length && !requestAnimationFrame; x += 1) {
95      requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']
96    }
97
98    if (!requestAnimationFrame) {
99      log('setup', 'RequestAnimationFrame not supported')
100    } else {
101      // Firefox extension content-scripts have a globalThis object that is not the same as window.
102      // Binding `requestAnimationFrame` to window allows the function to work and prevents errors
103      // being thrown when run in that context, and should be a no-op in every other context.
104      requestAnimationFrame = requestAnimationFrame.bind(window)
105    }
106  }
107
108  function getMyID(iframeId) {
109    var retStr = 'Host page: ' + iframeId
110
111    if (window.top !== window.self) {
112      retStr =
113        window.parentIFrame && window.parentIFrame.getId
114          ? window.parentIFrame.getId() + ': ' + iframeId
115          : 'Nested host page: ' + iframeId
116    }
117
118    return retStr
119  }
120
121  function formatLogHeader(iframeId) {
122    return msgId + '[' + getMyID(iframeId) + ']'
123  }
124
125  function isLogEnabled(iframeId) {
126    return settings[iframeId] ? settings[iframeId].log : logEnabled
127  }
128
129  function log(iframeId, msg) {
130    output('log', iframeId, msg, isLogEnabled(iframeId))
131  }
132
133  function info(iframeId, msg) {
134    output('info', iframeId, msg, isLogEnabled(iframeId))
135  }
136
137  function warn(iframeId, msg) {
138    output('warn', iframeId, msg, true)
139  }
140
141  function output(type, iframeId, msg, enabled) {
142    if (true === enabled && 'object' === typeof window.console) {
143      // eslint-disable-next-line no-console
144      console[type](formatLogHeader(iframeId), msg)
145    }
146  }
147
148  function iFrameListener(event) {
149    function resizeIFrame() {
150      function resize() {
151        setSize(messageData)
152        setPagePosition(iframeId)
153        on('onResized', messageData)
154      }
155
156      ensureInRange('Height')
157      ensureInRange('Width')
158
159      syncResize(resize, messageData, 'init')
160    }
161
162    function processMsg() {
163      var data = msg.substr(msgIdLen).split(':')
164      var height = data[1] ? parseInt(data[1], 10) : 0
165      var iframe = settings[data[0]] && settings[data[0]].iframe
166      var compStyle = getComputedStyle(iframe)
167
168      return {
169        iframe: iframe,
170        id: data[0],
171        height: height + getPaddingEnds(compStyle) + getBorderEnds(compStyle),
172        width: data[2],
173        type: data[3]
174      }
175    }
176
177    function getPaddingEnds(compStyle) {
178      if (compStyle.boxSizing !== 'border-box') {
179        return 0
180      }
181      var top = compStyle.paddingTop ? parseInt(compStyle.paddingTop, 10) : 0
182      var bot = compStyle.paddingBottom
183        ? parseInt(compStyle.paddingBottom, 10)
184        : 0
185      return top + bot
186    }
187
188    function getBorderEnds(compStyle) {
189      if (compStyle.boxSizing !== 'border-box') {
190        return 0
191      }
192      var top = compStyle.borderTopWidth
193        ? parseInt(compStyle.borderTopWidth, 10)
194        : 0
195      var bot = compStyle.borderBottomWidth
196        ? parseInt(compStyle.borderBottomWidth, 10)
197        : 0
198      return top + bot
199    }
200
201    function ensureInRange(Dimension) {
202      var max = Number(settings[iframeId]['max' + Dimension]),
203        min = Number(settings[iframeId]['min' + Dimension]),
204        dimension = Dimension.toLowerCase(),
205        size = Number(messageData[dimension])
206
207      log(iframeId, 'Checking ' + dimension + ' is in range ' + min + '-' + max)
208
209      if (size < min) {
210        size = min
211        log(iframeId, 'Set ' + dimension + ' to min value')
212      }
213
214      if (size > max) {
215        size = max
216        log(iframeId, 'Set ' + dimension + ' to max value')
217      }
218
219      messageData[dimension] = '' + size
220    }
221
222    function isMessageFromIFrame() {
223      function checkAllowedOrigin() {
224        function checkList() {
225          var i = 0,
226            retCode = false
227
228          log(
229            iframeId,
230            'Checking connection is from allowed list of origins: ' +
231              checkOrigin
232          )
233
234          for (; i < checkOrigin.length; i++) {
235            if (checkOrigin[i] === origin) {
236              retCode = true
237              break
238            }
239          }
240          return retCode
241        }
242
243        function checkSingle() {
244          var remoteHost = settings[iframeId] && settings[iframeId].remoteHost
245          log(iframeId, 'Checking connection is from: ' + remoteHost)
246          return origin === remoteHost
247        }
248
249        return checkOrigin.constructor === Array ? checkList() : checkSingle()
250      }
251
252      var origin = event.origin,
253        checkOrigin = settings[iframeId] && settings[iframeId].checkOrigin
254
255      if (checkOrigin && '' + origin !== 'null' && !checkAllowedOrigin()) {
256        throw new Error(
257          'Unexpected message received from: ' +
258            origin +
259            ' for ' +
260            messageData.iframe.id +
261            '. Message was: ' +
262            event.data +
263            '. This error can be disabled by setting the checkOrigin: false option or by providing of array of trusted domains.'
264        )
265      }
266
267      return true
268    }
269
270    function isMessageForUs() {
271      return (
272        msgId === ('' + msg).substr(0, msgIdLen) &&
273        msg.substr(msgIdLen).split(':')[0] in settings
274      ) // ''+Protects against non-string msg
275    }
276
277    function isMessageFromMetaParent() {
278      // Test if this message is from a parent above us. This is an ugly test, however, updating
279      // the message format would break backwards compatibility.
280      var retCode = messageData.type in { true: 1, false: 1, undefined: 1 }
281
282      if (retCode) {
283        log(iframeId, 'Ignoring init message from meta parent page')
284      }
285
286      return retCode
287    }
288
289    function getMsgBody(offset) {
290      return msg.substr(msg.indexOf(':') + msgHeaderLen + offset)
291    }
292
293    function forwardMsgFromIFrame(msgBody) {
294      log(
295        iframeId,
296        'onMessage passed: {iframe: ' +
297          messageData.iframe.id +
298          ', message: ' +
299          msgBody +
300          '}'
301      )
302
303      on('onMessage', {
304        iframe: messageData.iframe,
305        message: JSON.parse(msgBody)
306      })
307
308      log(iframeId, '--')
309    }
310
311    function getPageInfo() {
312      var bodyPosition = document.body.getBoundingClientRect(),
313        iFramePosition = messageData.iframe.getBoundingClientRect()
314
315      return JSON.stringify({
316        iframeHeight: iFramePosition.height,
317        iframeWidth: iFramePosition.width,
318        clientHeight: Math.max(
319          document.documentElement.clientHeight,
320          window.innerHeight || 0
321        ),
322        clientWidth: Math.max(
323          document.documentElement.clientWidth,
324          window.innerWidth || 0
325        ),
326        offsetTop: parseInt(iFramePosition.top - bodyPosition.top, 10),
327        offsetLeft: parseInt(iFramePosition.left - bodyPosition.left, 10),
328        scrollTop: window.pageYOffset,
329        scrollLeft: window.pageXOffset,
330        documentHeight: document.documentElement.clientHeight,
331        documentWidth: document.documentElement.clientWidth,
332        windowHeight: window.innerHeight,
333        windowWidth: window.innerWidth
334      })
335    }
336
337    function sendPageInfoToIframe(iframe, iframeId) {
338      function debouncedTrigger() {
339        trigger('Send Page Info', 'pageInfo:' + getPageInfo(), iframe, iframeId)
340      }
341      debounceFrameEvents(debouncedTrigger, 32, iframeId)
342    }
343
344    function startPageInfoMonitor() {
345      function setListener(type, func) {
346        function sendPageInfo() {
347          if (settings[id]) {
348            sendPageInfoToIframe(settings[id].iframe, id)
349          } else {
350            stop()
351          }
352        }
353
354        ;['scroll', 'resize'].forEach(function (evt) {
355          log(id, type + evt + ' listener for sendPageInfo')
356          func(window, evt, sendPageInfo)
357        })
358      }
359
360      function stop() {
361        setListener('Remove ', removeEventListener)
362      }
363
364      function start() {
365        setListener('Add ', addEventListener)
366      }
367
368      var id = iframeId // Create locally scoped copy of iFrame ID
369
370      start()
371
372      if (settings[id]) {
373        settings[id].stopPageInfo = stop
374      }
375    }
376
377    function stopPageInfoMonitor() {
378      if (settings[iframeId] && settings[iframeId].stopPageInfo) {
379        settings[iframeId].stopPageInfo()
380        delete settings[iframeId].stopPageInfo
381      }
382    }
383
384    function checkIFrameExists() {
385      var retBool = true
386
387      if (null === messageData.iframe) {
388        warn(iframeId, 'IFrame (' + messageData.id + ') not found')
389        retBool = false
390      }
391      return retBool
392    }
393
394    function getElementPosition(target) {
395      var iFramePosition = target.getBoundingClientRect()
396
397      getPagePosition(iframeId)
398
399      return {
400        x: Math.floor(Number(iFramePosition.left) + Number(pagePosition.x)),
401        y: Math.floor(Number(iFramePosition.top) + Number(pagePosition.y))
402      }
403    }
404
405    function scrollRequestFromChild(addOffset) {
406      /* istanbul ignore next */ // Not testable in Karma
407      function reposition() {
408        pagePosition = newPosition
409        scrollTo()
410        log(iframeId, '--')
411      }
412
413      function calcOffset() {
414        return {
415          x: Number(messageData.width) + offset.x,
416          y: Number(messageData.height) + offset.y
417        }
418      }
419
420      function scrollParent() {
421        if (window.parentIFrame) {
422          window.parentIFrame['scrollTo' + (addOffset ? 'Offset' : '')](
423            newPosition.x,
424            newPosition.y
425          )
426        } else {
427          warn(
428            iframeId,
429            'Unable to scroll to requested position, window.parentIFrame not found'
430          )
431        }
432      }
433
434      var offset = addOffset
435          ? getElementPosition(messageData.iframe)
436          : { x: 0, y: 0 },
437        newPosition = calcOffset()
438
439      log(
440        iframeId,
441        'Reposition requested from iFrame (offset x:' +
442          offset.x +
443          ' y:' +
444          offset.y +
445          ')'
446      )
447
448      if (window.top !== window.self) {
449        scrollParent()
450      } else {
451        reposition()
452      }
453    }
454
455    function scrollTo() {
456      if (false !== on('onScroll', pagePosition)) {
457        setPagePosition(iframeId)
458      } else {
459        unsetPagePosition()
460      }
461    }
462
463    function findTarget(location) {
464      function jumpToTarget() {
465        var jumpPosition = getElementPosition(target)
466
467        log(
468          iframeId,
469          'Moving to in page link (#' +
470            hash +
471            ') at x: ' +
472            jumpPosition.x +
473            ' y: ' +
474            jumpPosition.y
475        )
476        pagePosition = {
477          x: jumpPosition.x,
478          y: jumpPosition.y
479        }
480
481        scrollTo()
482        log(iframeId, '--')
483      }
484
485      function jumpToParent() {
486        if (window.parentIFrame) {
487          window.parentIFrame.moveToAnchor(hash)
488        } else {
489          log(
490            iframeId,
491            'In page link #' +
492              hash +
493              ' not found and window.parentIFrame not found'
494          )
495        }
496      }
497
498      var hash = location.split('#')[1] || '',
499        hashData = decodeURIComponent(hash),
500        target =
501          document.getElementById(hashData) ||
502          document.getElementsByName(hashData)[0]
503
504      if (target) {
505        jumpToTarget()
506      } else if (window.top !== window.self) {
507        jumpToParent()
508      } else {
509        log(iframeId, 'In page link #' + hash + ' not found')
510      }
511    }
512
513    function onMouse(event) {
514      var mousePos = {}
515
516      if (Number(messageData.width) === 0 && Number(messageData.height) === 0) {
517        var data = getMsgBody(9).split(':')
518        mousePos = {
519          x: data[1],
520          y: data[0]
521        }
522      } else {
523        mousePos = {
524          x: messageData.width,
525          y: messageData.height
526        }
527      }
528
529      on(event, {
530        iframe: messageData.iframe,
531        screenX: Number(mousePos.x),
532        screenY: Number(mousePos.y),
533        type: messageData.type
534      })
535    }
536
537    function on(funcName, val) {
538      return chkEvent(iframeId, funcName, val)
539    }
540
541    function actionMsg() {
542      if (settings[iframeId] && settings[iframeId].firstRun) firstRun()
543
544      switch (messageData.type) {
545        case 'close':
546          closeIFrame(messageData.iframe)
547          break
548
549        case 'message':
550          forwardMsgFromIFrame(getMsgBody(6))
551          break
552
553        case 'mouseenter':
554          onMouse('onMouseEnter')
555          break
556
557        case 'mouseleave':
558          onMouse('onMouseLeave')
559          break
560
561        case 'autoResize':
562          settings[iframeId].autoResize = JSON.parse(getMsgBody(9))
563          break
564
565        case 'scrollTo':
566          scrollRequestFromChild(false)
567          break
568
569        case 'scrollToOffset':
570          scrollRequestFromChild(true)
571          break
572
573        case 'pageInfo':
574          sendPageInfoToIframe(
575            settings[iframeId] && settings[iframeId].iframe,
576            iframeId
577          )
578          startPageInfoMonitor()
579          break
580
581        case 'pageInfoStop':
582          stopPageInfoMonitor()
583          break
584
585        case 'inPageLink':
586          findTarget(getMsgBody(9))
587          break
588
589        case 'reset':
590          resetIFrame(messageData)
591          break
592
593		case 'stripeModalOpened':
594			ssaDebouncedScroll(messageData)
595
596        case 'init':
597          resizeIFrame()
598          on('onInit', messageData.iframe)
599          break
600
601        default:
602          if (
603            Number(messageData.width) === 0 &&
604            Number(messageData.height) === 0
605          ) {
606            warn(
607              'Unsupported message received (' +
608                messageData.type +
609                '), this is likely due to the iframe containing a later ' +
610                'version of iframe-resizer than the parent page'
611            )
612          } else {
613            resizeIFrame()
614          }
615      }
616    }
617
618    function hasSettings(iframeId) {
619      var retBool = true
620
621      if (!settings[iframeId]) {
622        retBool = false
623        warn(
624          messageData.type +
625            ' No settings for ' +
626            iframeId +
627            '. Message was: ' +
628            msg
629        )
630      }
631
632      return retBool
633    }
634
635    function iFrameReadyMsgReceived() {
636      // eslint-disable-next-line no-restricted-syntax, guard-for-in
637      for (var iframeId in settings) {
638        trigger(
639          'iFrame requested init',
640          createOutgoingMsg(iframeId),
641          settings[iframeId].iframe,
642          iframeId
643        )
644      }
645    }
646
647    function firstRun() {
648      if (settings[iframeId]) {
649        settings[iframeId].firstRun = false
650      }
651    }
652
653    var msg = event.data,
654      messageData = {},
655      iframeId = null
656
657    if ('[iFrameResizerChild]Ready' === msg) {
658      iFrameReadyMsgReceived()
659    } else if (isMessageForUs()) {
660      messageData = processMsg()
661      iframeId = messageData.id
662      if (settings[iframeId]) {
663        settings[iframeId].loaded = true
664      }
665
666      if (!isMessageFromMetaParent() && hasSettings(iframeId)) {
667        log(iframeId, 'Received: ' + msg)
668
669        if (checkIFrameExists() && isMessageFromIFrame()) {
670          actionMsg()
671        }
672      }
673    } else {
674      info(iframeId, 'Ignored: ' + msg)
675    }
676  }
677
678  function chkEvent(iframeId, funcName, val) {
679    var func = null,
680      retVal = null
681
682    if (settings[iframeId]) {
683      func = settings[iframeId][funcName]
684
685      if ('function' === typeof func) {
686        retVal = func(val)
687      } else {
688        throw new TypeError(
689          funcName + ' on iFrame[' + iframeId + '] is not a function'
690        )
691      }
692    }
693
694    return retVal
695  }
696
697  function removeIframeListeners(iframe) {
698    var iframeId = iframe.id
699    delete settings[iframeId]
700  }
701
702  function closeIFrame(iframe) {
703    var iframeId = iframe.id
704    if (chkEvent(iframeId, 'onClose', iframeId) === false) {
705      log(iframeId, 'Close iframe cancelled by onClose event')
706      return
707    }
708    log(iframeId, 'Removing iFrame: ' + iframeId)
709
710    try {
711      // Catch race condition error with React
712      if (iframe.parentNode) {
713        iframe.parentNode.removeChild(iframe)
714      }
715    } catch (error) {
716      warn(error)
717    }
718
719    chkEvent(iframeId, 'onClosed', iframeId)
720    log(iframeId, '--')
721    removeIframeListeners(iframe)
722  }
723
724  function getPagePosition(iframeId) {
725    if (null === pagePosition) {
726      pagePosition = {
727        x:
728          window.pageXOffset !== undefined
729            ? window.pageXOffset
730            : document.documentElement.scrollLeft,
731        y:
732          window.pageYOffset !== undefined
733            ? window.pageYOffset
734            : document.documentElement.scrollTop
735      }
736      log(
737        iframeId,
738        'Get page position: ' + pagePosition.x + ',' + pagePosition.y
739      )
740    }
741  }
742
743  function setPagePosition(iframeId) {
744    if (null !== pagePosition) {
745      window.scrollTo(pagePosition.x, pagePosition.y)
746      log(
747        iframeId,
748        'Set page position: ' + pagePosition.x + ',' + pagePosition.y
749      )
750      unsetPagePosition()
751    }
752  }
753
754  function unsetPagePosition() {
755    pagePosition = null
756  }
757
758  function resetIFrame(messageData) {
759    function reset() {
760      setSize(messageData)
761      trigger('reset', 'reset', messageData.iframe, messageData.id)
762    }
763
764    log(
765      messageData.id,
766      'Size reset requested by ' +
767        ('init' === messageData.type ? 'host page' : 'iFrame')
768    )
769    getPagePosition(messageData.id)
770    syncResize(reset, messageData, 'reset')
771  }
772
773  function setSize(messageData) {
774    function setDimension(dimension) {
775      if (!messageData.id) {
776        log('undefined', 'messageData id not set')
777        return
778      }
779      messageData.iframe.style[dimension] = messageData[dimension] + 'px'
780      log(
781        messageData.id,
782        'IFrame (' +
783          iframeId +
784          ') ' +
785          dimension +
786          ' set to ' +
787          messageData[dimension] +
788          'px'
789      )
790    }
791
792    function chkZero(dimension) {
793      // FireFox sets dimension of hidden iFrames to zero.
794      // So if we detect that set up an event to check for
795      // when iFrame becomes visible.
796
797      /* istanbul ignore next */ // Not testable in PhantomJS
798      if (!hiddenCheckEnabled && '0' === messageData[dimension]) {
799        hiddenCheckEnabled = true
800        log(iframeId, 'Hidden iFrame detected, creating visibility listener')
801        fixHiddenIFrames()
802      }
803    }
804
805    function processDimension(dimension) {
806      setDimension(dimension)
807      chkZero(dimension)
808    }
809
810    var iframeId = messageData.iframe.id
811
812    if (settings[iframeId]) {
813      if (settings[iframeId].sizeHeight) {
814        processDimension('height')
815      }
816      if (settings[iframeId].sizeWidth) {
817        processDimension('width')
818      }
819    }
820  }
821
822  function syncResize(func, messageData, doNotSync) {
823    /* istanbul ignore if */ // Not testable in PhantomJS
824    if (
825      doNotSync !== messageData.type &&
826      requestAnimationFrame &&
827      // including check for jasmine because had trouble getting spy to work in unit test using requestAnimationFrame
828      !window.jasmine
829    ) {
830      log(messageData.id, 'Requesting animation frame')
831      requestAnimationFrame(func)
832    } else {
833      func()
834    }
835  }
836
837  function trigger(calleeMsg, msg, iframe, id, noResponseWarning) {
838    function postMessageToIFrame() {
839      var target = settings[id] && settings[id].targetOrigin
840      log(
841        id,
842        '[' +
843          calleeMsg +
844          '] Sending msg to iframe[' +
845          id +
846          '] (' +
847          msg +
848          ') targetOrigin: ' +
849          target
850      )
851      iframe.contentWindow.postMessage(msgId + msg, target)
852    }
853
854    function iFrameNotFound() {
855      warn(id, '[' + calleeMsg + '] IFrame(' + id + ') not found')
856    }
857
858    function chkAndSend() {
859      if (
860        iframe &&
861        'contentWindow' in iframe &&
862        null !== iframe.contentWindow
863      ) {
864        // Null test for PhantomJS
865        postMessageToIFrame()
866      } else {
867        iFrameNotFound()
868      }
869    }
870
871    function warnOnNoResponse() {
872      function warning() {
873        if (settings[id] && !settings[id].loaded && !errorShown) {
874          errorShown = true
875          warn(
876            id,
877            'IFrame has not responded within ' +
878              settings[id].warningTimeout / 1000 +
879              ' seconds. Check iFrameResizer.contentWindow.js has been loaded in iFrame. This message can be ignored if everything is working, or you can set the warningTimeout option to a higher value or zero to suppress this warning.'
880          )
881        }
882      }
883
884      if (
885        !!noResponseWarning &&
886        settings[id] &&
887        !!settings[id].warningTimeout
888      ) {
889        settings[id].msgTimeout = setTimeout(
890          warning,
891          settings[id].warningTimeout
892        )
893      }
894    }
895
896    var errorShown = false
897
898    id = id || iframe.id
899
900    if (settings[id]) {
901      chkAndSend()
902      warnOnNoResponse()
903    }
904  }
905
906  function createOutgoingMsg(iframeId) {
907    return (
908      iframeId +
909      ':' +
910      settings[iframeId].bodyMarginV1 +
911      ':' +
912      settings[iframeId].sizeWidth +
913      ':' +
914      settings[iframeId].log +
915      ':' +
916      settings[iframeId].interval +
917      ':' +
918      settings[iframeId].enablePublicMethods +
919      ':' +
920      settings[iframeId].autoResize +
921      ':' +
922      settings[iframeId].bodyMargin +
923      ':' +
924      settings[iframeId].heightCalculationMethod +
925      ':' +
926      settings[iframeId].bodyBackground +
927      ':' +
928      settings[iframeId].bodyPadding +
929      ':' +
930      settings[iframeId].tolerance +
931      ':' +
932      settings[iframeId].inPageLinks +
933      ':' +
934      settings[iframeId].resizeFrom +
935      ':' +
936      settings[iframeId].widthCalculationMethod +
937      ':' +
938      settings[iframeId].mouseEvents
939    )
940  }
941
942  function isNumber(value) {
943    return typeof value === 'number'
944  }
945
946  function setupIFrame(iframe, options) {
947    function setLimits() {
948      function addStyle(style) {
949        var styleValue = settings[iframeId][style]
950        if (Infinity !== styleValue && 0 !== styleValue) {
951          iframe.style[style] = isNumber(styleValue)
952            ? styleValue + 'px'
953            : styleValue
954          log(iframeId, 'Set ' + style + ' = ' + iframe.style[style])
955        }
956      }
957
958      function chkMinMax(dimension) {
959        if (
960          settings[iframeId]['min' + dimension] >
961          settings[iframeId]['max' + dimension]
962        ) {
963          throw new Error(
964            'Value for min' +
965              dimension +
966              ' can not be greater than max' +
967              dimension
968          )
969        }
970      }
971
972      chkMinMax('Height')
973      chkMinMax('Width')
974
975      addStyle('maxHeight')
976      addStyle('minHeight')
977      addStyle('maxWidth')
978      addStyle('minWidth')
979    }
980
981    function newId() {
982      var id = (options && options.id) || defaults.id + count++
983      if (null !== document.getElementById(id)) {
984        id += count++
985      }
986      return id
987    }
988
989    function ensureHasId(iframeId) {
990      if ('' === iframeId) {
991        // eslint-disable-next-line no-multi-assign
992        iframe.id = iframeId = newId()
993        logEnabled = (options || {}).log
994        log(
995          iframeId,
996          'Added missing iframe ID: ' + iframeId + ' (' + iframe.src + ')'
997        )
998      }
999
1000      return iframeId
1001    }
1002
1003    function setScrolling() {
1004      log(
1005        iframeId,
1006        'IFrame scrolling ' +
1007          (settings[iframeId] && settings[iframeId].scrolling
1008            ? 'enabled'
1009            : 'disabled') +
1010          ' for ' +
1011          iframeId
1012      )
1013      iframe.style.overflow =
1014        false === (settings[iframeId] && settings[iframeId].scrolling)
1015          ? 'hidden'
1016          : 'auto'
1017      switch (settings[iframeId] && settings[iframeId].scrolling) {
1018        case 'omit':
1019          break
1020
1021        case true:
1022          iframe.scrolling = 'yes'
1023          break
1024
1025        case false:
1026          iframe.scrolling = 'no'
1027          break
1028
1029        default:
1030          iframe.scrolling = settings[iframeId]
1031            ? settings[iframeId].scrolling
1032            : 'no'
1033      }
1034    }
1035
1036    // The V1 iFrame script expects an int, where as in V2 expects a CSS
1037    // string value such as '1px 3em', so if we have an int for V2, set V1=V2
1038    // and then convert V2 to a string PX value.
1039    function setupBodyMarginValues() {
1040      if (
1041        'number' ===
1042          typeof (settings[iframeId] && settings[iframeId].bodyMargin) ||
1043        '0' === (settings[iframeId] && settings[iframeId].bodyMargin)
1044      ) {
1045        settings[iframeId].bodyMarginV1 = settings[iframeId].bodyMargin
1046        settings[iframeId].bodyMargin =
1047          '' + settings[iframeId].bodyMargin + 'px'
1048      }
1049    }
1050
1051    function checkReset() {
1052      // Reduce scope of firstRun to function, because IE8's JS execution
1053      // context stack is borked and this value gets externally
1054      // changed midway through running this function!!!
1055      var firstRun = settings[iframeId] && settings[iframeId].firstRun,
1056        resetRequertMethod =
1057          settings[iframeId] &&
1058          settings[iframeId].heightCalculationMethod in resetRequiredMethods
1059
1060      if (!firstRun && resetRequertMethod) {
1061        resetIFrame({ iframe: iframe, height: 0, width: 0, type: 'init' })
1062      }
1063    }
1064
1065    function setupIFrameObject() {
1066      if (settings[iframeId]) {
1067        settings[iframeId].iframe.iFrameResizer = {
1068          close: closeIFrame.bind(null, settings[iframeId].iframe),
1069
1070          removeListeners: removeIframeListeners.bind(
1071            null,
1072            settings[iframeId].iframe
1073          ),
1074
1075          resize: trigger.bind(
1076            null,
1077            'Window resize',
1078            'resize',
1079            settings[iframeId].iframe
1080          ),
1081
1082          moveToAnchor: function (anchor) {
1083            trigger(
1084              'Move to anchor',
1085              'moveToAnchor:' + anchor,
1086              settings[iframeId].iframe,
1087              iframeId
1088            )
1089          },
1090
1091          sendMessage: function (message) {
1092            message = JSON.stringify(message)
1093            trigger(
1094              'Send Message',
1095              'message:' + message,
1096              settings[iframeId].iframe,
1097              iframeId
1098            )
1099          }
1100        }
1101      }
1102    }
1103
1104    // We have to call trigger twice, as we can not be sure if all
1105    // iframes have completed loading when this code runs. The
1106    // event listener also catches the page changing in the iFrame.
1107    function init(msg) {
1108      function iFrameLoaded() {
1109        trigger('iFrame.onload', msg, iframe, undefined, true)
1110        checkReset()
1111      }
1112
1113      function createDestroyObserver(MutationObserver) {
1114        if (!iframe.parentNode) {
1115          return
1116        }
1117
1118        var destroyObserver = new MutationObserver(function (mutations) {
1119          mutations.forEach(function (mutation) {
1120            var removedNodes = Array.prototype.slice.call(mutation.removedNodes) // Transform NodeList into an Array
1121            removedNodes.forEach(function (removedNode) {
1122              if (removedNode === iframe) {
1123                closeIFrame(iframe)
1124              }
1125            })
1126          })
1127        })
1128        destroyObserver.observe(iframe.parentNode, {
1129          childList: true
1130        })
1131      }
1132
1133      var MutationObserver = getMutationObserver()
1134      if (MutationObserver) {
1135        createDestroyObserver(MutationObserver)
1136      }
1137
1138      addEventListener(iframe, 'load', iFrameLoaded)
1139      trigger('init', msg, iframe, undefined, true)
1140    }
1141
1142    function checkOptions(options) {
1143      if ('object' !== typeof options) {
1144        throw new TypeError('Options is not an object')
1145      }
1146    }
1147
1148    function copyOptions(options) {
1149      // eslint-disable-next-line no-restricted-syntax
1150      for (var option in defaults) {
1151        if (Object.prototype.hasOwnProperty.call(defaults, option)) {
1152          settings[iframeId][option] = Object.prototype.hasOwnProperty.call(
1153            options,
1154            option
1155          )
1156            ? options[option]
1157            : defaults[option]
1158        }
1159      }
1160    }
1161
1162    function getTargetOrigin(remoteHost) {
1163      return '' === remoteHost ||
1164        null !== remoteHost.match(/^(about:blank|javascript:|file:\/\/)/)
1165        ? '*'
1166        : remoteHost
1167    }
1168
1169    function depricate(key) {
1170      var splitName = key.split('Callback')
1171
1172      if (splitName.length === 2) {
1173        var name =
1174          'on' + splitName[0].charAt(0).toUpperCase() + splitName[0].slice(1)
1175        this[name] = this[key]
1176        delete this[key]
1177        warn(
1178          iframeId,
1179          "Deprecated: '" +
1180            key +
1181            "' has been renamed '" +
1182            name +
1183            "'. The old method will be removed in the next major version."
1184        )
1185      }
1186    }
1187
1188    function processOptions(options) {
1189      options = options || {}
1190      settings[iframeId] = {
1191        firstRun: true,
1192        iframe: iframe,
1193        remoteHost: iframe.src && iframe.src.split('/').slice(0, 3).join('/')
1194      }
1195
1196      checkOptions(options)
1197      Object.keys(options).forEach(depricate, options)
1198      copyOptions(options)
1199
1200      if (settings[iframeId]) {
1201        settings[iframeId].targetOrigin =
1202          true === settings[iframeId].checkOrigin
1203            ? getTargetOrigin(settings[iframeId].remoteHost)
1204            : '*'
1205      }
1206    }
1207
1208    function beenHere() {
1209      return iframeId in settings && 'iFrameResizer' in iframe
1210    }
1211
1212    var iframeId = ensureHasId(iframe.id)
1213
1214    if (!beenHere()) {
1215      processOptions(options)
1216      setScrolling()
1217      setLimits()
1218      setupBodyMarginValues()
1219      init(createOutgoingMsg(iframeId))
1220      setupIFrameObject()
1221    } else {
1222      warn(iframeId, 'Ignored iFrame, already setup.')
1223    }
1224  }
1225
1226  function debouce(fn, time) {
1227    if (null === timer) {
1228      timer = setTimeout(function () {
1229        timer = null
1230        fn()
1231      }, time)
1232    }
1233  }
1234
1235  var frameTimer = {}
1236  function debounceFrameEvents(fn, time, frameId) {
1237    if (!frameTimer[frameId]) {
1238      frameTimer[frameId] = setTimeout(function () {
1239        frameTimer[frameId] = null
1240        fn()
1241      }, time)
1242    }
1243  }
1244
1245  // Not testable in PhantomJS
1246  /* istanbul ignore next */
1247
1248  function fixHiddenIFrames() {
1249    function checkIFrames() {
1250      function checkIFrame(settingId) {
1251        function chkDimension(dimension) {
1252          return (
1253            '0px' ===
1254            (settings[settingId] && settings[settingId].iframe.style[dimension])
1255          )
1256        }
1257
1258        function isVisible(el) {
1259          return null !== el.offsetParent
1260        }
1261
1262        if (
1263          settings[settingId] &&
1264          isVisible(settings[settingId].iframe) &&
1265          (chkDimension('height') || chkDimension('width'))
1266        ) {
1267          trigger(
1268            'Visibility change',
1269            'resize',
1270            settings[settingId].iframe,
1271            settingId
1272          )
1273        }
1274      }
1275
1276      Object.keys(settings).forEach(function (key) {
1277        checkIFrame(key)
1278      })
1279    }
1280
1281    function mutationObserved(mutations) {
1282		// watch for changes in the inputs corresponding to the iframes
1283		mutations.forEach(mut=>{
1284			// make sure this executes only on pages with a formidable form
1285			if ( window.frmrules && mut.target.classList?.contains('ssa_appointment_form_field_appointment_id') && !mut.target.value){
1286				// scoped function to sync the iframe
1287				let syncIframe = () => {
1288					let src = jQuery(`#${mut.target.id}`).closest('div').find('iframe').attr('src')
1289					jQuery(`#${mut.target.id}`).closest('div').find('iframe').attr( 'src', '' )
1290					debouce(()=>{
1291						jQuery(`#${mut.target.id}`).closest('div').find('iframe').attr( 'src', src )
1292					}, 100 )
1293				}
1294				// debounce to space out the syncs and avoid crashing
1295				debouce(syncIframe, 16)
1296			}
1297		})
1298      log(
1299        'window',
1300        'Mutation observed: ' + mutations[0].target + ' ' + mutations[0].type
1301      )
1302      debouce(checkIFrames, 16)
1303    }
1304
1305    function createMutationObserver() {
1306      var target = document.querySelector('body'),
1307        config = {
1308          attributes: true,
1309          attributeOldValue: false,
1310          characterData: true,
1311          characterDataOldValue: false,
1312          childList: true,
1313          subtree: true
1314        },
1315        observer = new MutationObserver(mutationObserved)
1316
1317      observer.observe(target, config)
1318    }
1319
1320    var MutationObserver = getMutationObserver()
1321    if (MutationObserver) {
1322      createMutationObserver()
1323    }
1324  }
1325
1326  function resizeIFrames(event) {
1327    function resize() {
1328      sendTriggerMsg('Window ' + event, 'resize')
1329    }
1330
1331    log('window', 'Trigger event: ' + event)
1332    debouce(resize, 16)
1333  }
1334
1335  // Not testable in PhantomJS
1336  /* istanbul ignore next */
1337  function tabVisible() {
1338    function resize() {
1339      sendTriggerMsg('Tab Visible', 'resize')
1340    }
1341
1342    if ('hidden' !== document.visibilityState) {
1343      log('document', 'Trigger event: Visibility change')
1344      debouce(resize, 16)
1345    }
1346  }
1347
1348  function sendTriggerMsg(eventName, event) {
1349    function isIFrameResizeEnabled(iframeId) {
1350      return (
1351        settings[iframeId] &&
1352        'parent' === settings[iframeId].resizeFrom &&
1353        settings[iframeId].autoResize &&
1354        !settings[iframeId].firstRun
1355      )
1356    }
1357
1358    Object.keys(settings).forEach(function (iframeId) {
1359      if (isIFrameResizeEnabled(iframeId)) {
1360        trigger(eventName, event, settings[iframeId].iframe, iframeId)
1361      }
1362    })
1363  }
1364
1365  function setupEventListeners() {
1366    addEventListener(window, 'message', iFrameListener)
1367
1368    addEventListener(window, 'resize', function () {
1369      resizeIFrames('resize')
1370    })
1371
1372  }
1373
1374  function factory() {
1375    function init(options, element) {
1376      function chkType() {
1377        if (!element.tagName) {
1378          throw new TypeError('Object is not a valid DOM element')
1379        } else if ('IFRAME' !== element.tagName.toUpperCase()) {
1380          throw new TypeError(
1381            'Expected <IFRAME> tag, found <' + element.tagName + '>'
1382          )
1383        }
1384      }
1385
1386      if (element) {
1387        chkType()
1388        setupIFrame(element, options)
1389        iFrames.push(element)
1390      }
1391    }
1392
1393    function warnDeprecatedOptions(options) {
1394      if (options && options.enablePublicMethods) {
1395        warn(
1396          'enablePublicMethods option has been removed, public methods are now always available in the iFrame'
1397        )
1398      }
1399    }
1400
1401    var iFrames
1402
1403    setupRequestAnimationFrame()
1404    setupEventListeners()
1405
1406    return function iFrameResizeF(options, target) {
1407      iFrames = [] // Only return iFrames past in on this call
1408
1409      warnDeprecatedOptions(options)
1410
1411      switch (typeof target) {
1412        case 'undefined':
1413        case 'string':
1414          Array.prototype.forEach.call(
1415            document.querySelectorAll(target || 'iframe'),
1416            init.bind(undefined, options)
1417          )
1418          break
1419
1420        case 'object':
1421          init(options, target)
1422          break
1423
1424        default:
1425          throw new TypeError('Unexpected data type (' + typeof target + ')')
1426      }
1427
1428      return iFrames
1429    }
1430  }
1431
1432  function createJQueryPublicMethod($) {
1433    if (!$.fn) {
1434      info('', 'Unable to bind to jQuery, it is not fully loaded.')
1435    } else if (!$.fn.iFrameResize) {
1436      $.fn.iFrameResize = function $iFrameResizeF(options) {
1437        function init(index, element) {
1438          setupIFrame(element, options)
1439        }
1440
1441        return this.filter('iframe').each(init).end()
1442      }
1443    }
1444  }
1445
1446  if (window.jQuery) {
1447    createJQueryPublicMethod(window.jQuery)
1448  }
1449
1450  if (typeof define === 'function' && define.amd) {
1451    define([], factory)
1452  } else if (typeof module === 'object' && typeof module.exports === 'object') {
1453    // Node for browserfy
1454    module.exports = factory()
1455  }
1456  window.iFrameResize = window.iFrameResize || factory()
1457})()
1458
1459/* ----- SSA Code --------- */
1460
1461var bookingIframes = document.querySelectorAll('.ssa_booking_iframe');
1462var iframeInteraction = false; // Track if the iframe has been activated
1463
1464var ssaDebouncedScroll = debounce(function(e){ // Debouncing scroll event listener to improve performance
1465	ssaHandleScroll(e);
1466}, 300);
1467
1468// Detect any interactivity with iframe - focus moved to any element inside
1469window.addEventListener('blur', function(){
1470	let activeEl = document.activeElement;
1471
1472	if (activeEl.tagName === 'IFRAME' && activeEl.classList.contains('ssa_booking_iframe')) {
1473		iframeInteraction = true;
1474	}
1475});
1476
1477// helper function to initialize the IframeResizer
1478var ssaInitIframeResizer = function() {
1479	var ssaIframeSettings = {
1480		heightCalculationMethod: 'taggedElement',
1481		checkOrigin: false,
1482		warningTimeout: 20000,
1483		onResized: ssaDebouncedScroll,
1484		onScroll: false
1485	}
1486
1487	iFrameResize(ssaIframeSettings, '.ssa_booking_iframe')
1488}
1489
1490// call on page load if there are SSA iframes
1491if (bookingIframes) {
1492	ssaInitIframeResizer();
1493}
1494
1495// Only run Elementor and FF code if jQuery is on the page
1496if ( window.jQuery ) {
1497
1498	// Elementor integration
1499	jQuery( document ).on( 'elementor/popup/show', function(){
1500		ssaInitIframeResizer()
1501	});
1502
1503	jQuery( document ).ready(function($){
1504
1505		// Formidable Forms integration
1506		$(document).on( 'frmPageChanged', function( event, form, response ) {
1507			var $iframes = $( '.frm_forms .ssa_booking_iframe' );
1508
1509			// if form page has changed, and the current page contains an SSA iframe,
1510			// initialize IframeResizer
1511			if( $iframes.length ) {
1512				ssaInitIframeResizer();
1513			}
1514		});
1515
1516		// Gravity Forms integration
1517		$( document ).on( 'gform_page_loaded', function( event, form_id, current_page ) {
1518			var $iframes = $( '.gform_wrapper .ssa_booking_iframe' );
1519
1520			// if form page has changed, and the current page contains an SSA iframe,
1521			// initialize IframeResizer
1522			if( $iframes.length ) {
1523				ssaInitIframeResizer();
1524			}
1525		});
1526	});
1527
1528} // end jQuery check
1529
1530// Returns a function, that, as long as it continues to be invoked, will not
1531// be triggered. The function will be called after it stops being called for
1532// N milliseconds. If `immediate` is passed, trigger the function on the
1533// leading edge, instead of the trailing.
1534function debounce(func, wait, immediate) {
1535	var timeout;
1536	return function() {
1537		var context = this, args = arguments;
1538		var later = function() {
1539			timeout = null;
1540			if (!immediate) func.apply(context, args);
1541		};
1542		var callNow = immediate && !timeout;
1543		clearTimeout(timeout);
1544		timeout = setTimeout(later, wait);
1545		if (callNow) func.apply(context, args);
1546	};
1547};
1548
1549function ssaHandleScroll(e) {
1550	if (e.type === 'stripeModalOpened') {
1551		e.iframe.scrollIntoView({
1552		behavior: 'smooth',
1553		block: 'end'
1554		});
1555		return;
1556	}
1557
1558	// This is needed for a bug on mobile devices where events are constantly emitted from the iframe and not all of them are mutationObserver
1559	if (e.type !== 'mutationObserver' ) { // Only scroll if iframe DOM has mutated
1560		return;
1561	}
1562
1563	var rect = e.iframe.getBoundingClientRect();
1564	var windowHeight = window.innerHeight || document.documentElement.clientHeight;
1565
1566	// is in viewPort 
1567	var isInViewport = rect.bottom >= 0 && 
1568						rect.right >= 0 && 
1569						rect.top <= (window.innerHeight) && 
1570						rect.left <= (window.innerWidth);
1571
1572	// is top of the iframe visible
1573	var isTopVisible = rect.top >= 0 && rect.top <= windowHeight;
1574
1575	// is bottom of the iframe visible
1576	var isBottomVisible = rect.bottom >= 0 && rect.bottom <= windowHeight;
1577
1578	if ( !isInViewport ) {
1579		return;
1580	}
1581
1582	if ( !iframeInteraction ) {
1583		return;
1584	}
1585
1586	if (isBottomVisible && isTopVisible) {
1587		// whole iframe is visible, do nothing
1588		return
1589	}
1590
1591	if ( rect.height > windowHeight ) {
1592		// top of the iframe is visible, scroll to the top of the iframe, 
1593		if ( isTopVisible ) {
1594			e.iframe.scrollIntoView({
1595				behavior: 'smooth',
1596				block: 'start'
1597			});
1598
1599		// if the bottom of the iframe is visible, scroll to the bottom of the iframe
1600		} else if ( isBottomVisible ) {
1601			e.iframe.scrollIntoView({
1602				behavior: 'smooth',
1603				block: 'end'
1604			});
1605		}
1606	} else {
1607		// if the iframe is smaller than the viewport, scroll to the center of the iframe
1608		e.iframe.scrollIntoView({
1609			behavior: 'smooth',
1610			block: 'center'
1611		});
1612		return;
1613	}
1614}
1615

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.