Utility class for checking header and footer positions relative to viewport
483140
function() {
            var $el = this.element,
                header = $el.hasClass( "ui-header" ),
                offset = Math.abs( $el.offset().top - this.window.scrollTop() );
            if ( !header ) {
                offset = Math.round( offset - this.window.height() + $el.outerHeight() ) - 60;
            }
            return offset;
        }
1015953
function isElementInViewport(el) {
    var eap;
    var rect = el.getBoundingClientRect();
    var docEl = document.documentElement;
    var vWidth = window.innerWidth || docEl.clientWidth;
    var vHeight = window.innerHeight || docEl.clientHeight;
    var efp = function (x, y) { return document.elementFromPoint(x, y); };
    var contains = el.contains ? (function (node) { return el.contains(node); }) : (function (node) { return el.compareDocumentPosition(node) == 0x10; });
    // Return false if it's not in the viewport
    if (rect.right < 0 || rect.bottom < 0
        || rect.left > vWidth || rect.top > vHeight)
        return false;
    // Return true if any of its four corners are visible
    return ((eap = efp(rect.left, rect.top)) == el || contains(eap)
        || (eap = efp(rect.right, rect.top)) == el || contains(eap)
        || (eap = efp(rect.right, rect.bottom)) == el || contains(eap)
        || (eap = efp(rect.left, rect.bottom)) == el || contains(eap));
}
1127048
function position(element) {
	let elemOffset = offset(element);
	let offsetParentBCR = {top: 0, left: 0};
	let offsetParentEl = parentOffsetEl(element);
	if (offsetParentEl !== document) {
		offsetParentBCR = offset(offsetParentEl);
		offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
		offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
	}

	return {
		width: Math.round(isNumber(elemOffset.width) ? elemOffset.width : element.offsetWidth),
		height: Math.round(isNumber(elemOffset.height) ? elemOffset.height : element.offsetHeight),
		top: Math.round(elemOffset.top - offsetParentBCR.top),
		left: Math.round(elemOffset.left - offsetParentBCR.left)
	};
}
88053
function inViewport(el, options = { tolerance: 0 }) {
    if (!el) {
        throw new Error('You should specify the element you want to test');
    }

    if (typeof el === 'string') {
        el = document.querySelector(el);
    }

    const elRect = el.getBoundingClientRect();

    return (
        // Check bottom boundary
        elRect.bottom - options.tolerance > 0 &&

        // Check right boundary
        elRect.right - options.tolerance > 0 &&

        // Check left boundary
        elRect.left + options.tolerance < (window.innerWidth ||
        document.documentElement.clientWidth) &&

        // Check top boundary
        elRect.top + options.tolerance < (window.innerHeight ||
        document.documentElement.clientHeight)
    );
}
405585
def _calc_scrollbars(self, viewer, whence):
        
        if self._scrolling or whence > 0:
            return

        # flag that suppresses a cyclical callback
        self._adjusting = True
        try:
            bd = self.viewer.get_bindings()
            res = bd.calc_pan_pct(self.viewer, pad=self.pad)
            if res is None:
                return

            hsb = self.horizontalScrollBar()
            vsb = self.verticalScrollBar()

            page_h, page_v = (int(round(res.thm_pct_x * self.range_h)),
                              int(round(res.thm_pct_y * self.range_v)))
            hsb.setPageStep(page_h)
            vsb.setPageStep(page_v)

            upper_h = max(1, self.range_h - page_h)
            upper_v = max(1, self.range_v - page_v)
            hsb.setRange(0, upper_h)
            vsb.setRange(0, upper_v)
            self.upper_h, self.upper_v = upper_h, upper_v

            val_h, val_v = (int(round(res.pan_pct_x * self.upper_h)),
                            int(round((1.0 - res.pan_pct_y) * self.upper_v)))
            hsb.setValue(val_h)
            vsb.setValue(val_v)

        finally:
            self._adjusting = False
1277697
function(){
		var articleRect = this.article.getBoundingClientRect();

		var buttons = this.buttons;


		var positions = this.titles.map(function(header, i){
			return {
				header: header,
				rect: header.getBoundingClientRect(),
				button: buttons[i]
			};
		});
		// this simulates a header at the end of the page
		positions.push({
			rect: {
				top: articleRect.top + this.article.scrollHeight - this.article.scrollTop
			}
		});
		// loop through the actual headers and their positions
		positions.slice(0, positions.length - 1).forEach(function(position, index){

			position.button.classList.remove("completed","active");

			var curRect = position.rect;
			var curDistance = curRect.top - articleRect.top;

			var nextRect = positions[index+1].rect;
			var nextDistance = nextRect.top - articleRect.top;

			// =====[CUR=NEXT]===
			if( nextDistance >= 0 && nextDistance <= articleRect.height && curDistance >= 0 && curDistance <= articleRect.height ) {
				position.button.classList.add("active");
			}
			// =======CUR=====[=NEXT=|===]======
			// =======CUR=======NEXT=====[===|===]===
			else if( nextDistance < (articleRect.height / 2) ) {
				position.button.classList.add("completed");
			}
			// ======[=CUR=|=NEXT=]======
			// ======[=CUR=|===]=NEXT====
			// ====CUR=[===|=NEXT]=======
			// ====CUR=[===|===]=NEXT====
			else if( nextDistance >= (articleRect.height / 2) && curDistance < (articleRect.height / 2) ) {
				position.button.classList.add("active");
			}
		});
		var elementToScroll = this.outlineScrollElement;

		if(elementToScroll) {
			// find out where the midpoint is
			var distance = (this.article.scrollTop + this.article.offsetHeight / 2) / this.article.scrollHeight;
			elementToScroll.scrollTop = (elementToScroll.scrollHeight * distance) - (elementToScroll.offsetHeight / 2);
		}
	}
45292
function() {
		if ( !this[ 0 ] ) {
			return;
		}

		var offsetParent, offset, doc,
			elem = this[ 0 ],
			parentOffset = { top: 0, left: 0 };

		// position:fixed elements are offset from the viewport, which itself always has zero offset
		if ( jQuery.css( elem, "position" ) === "fixed" ) {

			// Assume position:fixed implies availability of getBoundingClientRect
			offset = elem.getBoundingClientRect();

		} else {
			offset = this.offset();

			// Account for the *real* offset parent, which can be the document or its root element
			// when a statically positioned element is identified
			doc = elem.ownerDocument;
			offsetParent = elem.offsetParent || doc.documentElement;
			while ( offsetParent &&
				( offsetParent === doc.body || offsetParent === doc.documentElement ) &&
				jQuery.css( offsetParent, "position" ) === "static" ) {

				offsetParent = offsetParent.parentNode;
			}
			if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {

				// Incorporate borders into its offset, since they are outside its content origin
				parentOffset = jQuery( offsetParent ).offset();
				parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );
				parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );
			}
		}

		// Subtract parent offsets and element margins
		return {
			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
		};
	}
268302
function getPageOffset ( ) {

        var supportPageOffset = window.pageXOffset !== undefined,
            isCSS1Compat = ((document.compatMode || "") === "CSS1Compat"),
            x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft,
            y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;

        return {
            x: x,
            y: y
        };
    }
282052
function() {
      if (this.isInline) {
        return;
      }
      var widgetWidth = this.$widget.outerWidth(), widgetHeight = this.$widget.outerHeight(), visualPadding = 10, windowWidth =
        $(window).width(), windowHeight = $(window).height(), scrollTop = $(window).scrollTop();

      var zIndex = parseInt(this.$element.parents().filter(function() { return $(this).css('z-index') !== 'auto'; }).first().css('z-index'), 10) + 10;
      var offset = this.component ? this.component.parent().offset() : this.$element.offset();
      var height = this.component ? this.component.outerHeight(true) : this.$element.outerHeight(false);
      var width = this.component ? this.component.outerWidth(true) : this.$element.outerWidth(false);
      var left = offset.left, top = offset.top;

      this.$widget.removeClass('timepicker-orient-top timepicker-orient-bottom timepicker-orient-right timepicker-orient-left');

      if (this.orientation.x !== 'auto') {
        this.$widget.addClass('timepicker-orient-' + this.orientation.x);
        if (this.orientation.x === 'right') {
          left -= widgetWidth - width;
        }
      } else{
        // auto x orientation is best-placement: if it crosses a window edge, fudge it sideways
        // Default to left
        this.$widget.addClass('timepicker-orient-left');
        if (offset.left < 0) {
          left -= offset.left - visualPadding;
        } else if (offset.left + widgetWidth > windowWidth) {
          left = windowWidth - widgetWidth - visualPadding;
        }
      }
      // auto y orientation is best-situation: top or bottom, no fudging, decision based on which shows more of the widget
      var yorient = this.orientation.y, topOverflow, bottomOverflow;
      if (yorient === 'auto') {
        topOverflow = -scrollTop + offset.top - widgetHeight;
        bottomOverflow = scrollTop + windowHeight - (offset.top + height + widgetHeight);
        if (Math.max(topOverflow, bottomOverflow) === bottomOverflow) {
          yorient = 'top';
        } else {
          yorient = 'bottom';
        }
      }
      this.$widget.addClass('timepicker-orient-' + yorient);
      if (yorient === 'top'){
        top += height;
      } else{
        top -= widgetHeight + parseInt(this.$widget.css('padding-top'), 10);
      }

      this.$widget.css({
        top : top,
        left : left,
        zIndex : zIndex
      });
    }
851073
function _determineAutoPosition(targetElement, tooltipLayer, desiredTooltipPosition) {
    // Take a clone of position precedence. These will be the available
    var possiblePositions = this._options.positionPrecedence.slice();

    var windowSize = _getWinSize();
    var tooltipHeight = _getOffset(tooltipLayer).height + 10;
    var tooltipWidth = _getOffset(tooltipLayer).width + 20;
    var targetOffset = _getOffset(targetElement);

    // If we check all the possible areas, and there are no valid places for the tooltip, the element
    // must take up most of the screen real estate. Show the tooltip floating in the middle of the screen.
    var calculatedPosition = 'floating';

    // TODO Update by joyer
    // Check if the width of the tooltip + the starting point would spill off the right side of the screen
    // If no, neither bottom or top are valid
    // if (targetOffset.left + tooltipWidth > windowSize.width || ((targetOffset.left + (targetOffset.width / 2)) - tooltipWidth) < 0) {
    //   _removeEntry(possiblePositions, "bottom");
    //   _removeEntry(possiblePositions, "top");
    // } else {
    // Check for space below
    if (targetOffset.height + targetOffset.top + tooltipHeight > windowSize.height) {
        _removeEntry(possiblePositions, 'bottom');
    }

    // Check for space above
    if (targetOffset.top - tooltipHeight < 0) {
        _removeEntry(possiblePositions, 'top');
    }
    // }

    // Check for space to the right
    if (targetOffset.width + targetOffset.left + tooltipWidth > windowSize.width) {
        _removeEntry(possiblePositions, 'right');
    }

    // Check for space to the left
    if (targetOffset.left - tooltipWidth < 0) {
        _removeEntry(possiblePositions, 'left');
    }

    // At this point, our array only has positions that are valid. Pick the first one, as it remains in order
    if (possiblePositions.length > 0) {
        calculatedPosition = possiblePositions[0];
    }

    // If the requested position is in the list, replace our calculated choice with that
    if (desiredTooltipPosition && desiredTooltipPosition != 'auto') {
        if (possiblePositions.indexOf(desiredTooltipPosition) > -1) {
            calculatedPosition = desiredTooltipPosition;
        }
    }

    return calculatedPosition;
}
1158172
function updateViewportAboveIO() {
    io.viewportAbove = stepEl.map((el, i) => {
      const marginTop = pageH - stepOffsetTop[i];
      const marginBottom = offsetMargin - viewH - stepOffsetHeight[i];
      const rootMargin = `${marginTop}px 0px ${marginBottom}px 0px`;
      const options = { rootMargin };
      // console.log(options);
      const obs = new IntersectionObserver(intersectViewportAbove, options);
      obs.observe(el);
      return obs;
    });
  }
1298938
function createViewportDeterminer(props) {
  const { viewportRect, panelRect, actionRect } = props;

  return function isInViewport({ containerPosition }) {
    const containerTop = actionRect.top + containerPosition.top;
    const containerLeft = actionRect.left + containerPosition.left;
    const containerRight = containerLeft + panelRect.width;
    const containerBottom = containerTop + panelRect.height;
    const result =
      containerLeft >= viewportRect.left &&
      containerTop >= viewportRect.top &&
      containerRight <= viewportRect.right &&
      containerBottom <= viewportRect.bottom;

    return result;
  };
}
342444
function FooterView(vm, app, key, opts) {
	function filtItem(name) {
		var upper = name[0].toUpperCase() + name.slice(1);

		return el("li", [
			el("a", {class: opts.filter == name ? "selected" : null, href: "#/"+name}, upper),
		]);
	}

	return () => {
		var notDone = app.items.filter(item => !item.done).length;

		return el("footer#footer", [
			el("span#todo-count", [
				el("strong", notDone),
				" item" + (notDone == 1 ? "" : "s") + " left"
			]),
			el("ul#filters", ["all","active","completed"].map(
				filtItem
			)),
			app.items.length > notDone && el("button#clear-completed", {onclick: app.clearDone}, "Clear completed")
		])
	}
}
1091143
function () {
        this.top = document.body.scrollTop;
        this.left = document.body.scrollLeft;
        this.bottom = this.top + docElement.clientHeight;
        this.right = this.left + docElement.clientWidth;
    }
72028
function(o, blink) {
				if (! o.length) {
					return;
				}
				var ftop    = o.position().top,
					fheight = o.outerHeight(true),
					wtop    = wrapper.scrollTop(),
					wheight = wrapper.get(0).clientHeight,
					thheight = tableHeader? tableHeader.outerHeight(true) : 0;

				if (ftop + thheight + fheight > wtop + wheight) {
					wrapper.scrollTop(parseInt(ftop + thheight + fheight - wheight));
				} else if (ftop < wtop) {
					wrapper.scrollTop(ftop);
				}
				list && wrapper.scrollLeft(0);
				!!blink && fm.resources.blink(o, 'lookme');
			}
1184184
function getBoundingVisibleRect(el) {
    // Get the element bounding rect in the layout viewport.
    const rect = getBoundingRect(el);

    // Apply the visual viewport transform (i.e. pinch-zoom) to the bounding
    // rect. The viewportX|Y values are in CSS pixels so they don't change
    // with page scale. We first translate so that the viewport offset is
    // at the origin and then we apply the scaling factor.
    const scale = getPageScaleFactor();
    const visualViewportX = chrome.gpuBenchmarking.visualViewportX();
    const visualViewportY = chrome.gpuBenchmarking.visualViewportY();
    rect.top = (rect.top - visualViewportY) * scale;
    rect.left = (rect.left - visualViewportX) * scale;
    rect.width *= scale;
    rect.height *= scale;

    // Get the window dimensions.
    const windowHeight = getWindowHeight();
    const windowWidth = getWindowWidth();

    // Then clip the rect to the screen size.
    rect.top = clamp(0, rect.top, windowHeight);
    rect.left = clamp(0, rect.left, windowWidth);
    rect.height = clamp(0, rect.height, windowHeight - rect.top);
    rect.width = clamp(0, rect.width, windowWidth - rect.left);

    return rect;
  }
520001
function(inst) {
			var base = (inst.elem.is(':hidden') && inst.trigger ? inst.trigger : inst.elem);
			var offset = base.offset();
			var browserWidth = $(window).width();
			var browserHeight = $(window).height();
			if (browserWidth === 0) {
				return offset;
			}
			var isFixed = false;
			$(inst.elem).parents().each(function() {
				isFixed |= $(this).css('position') === 'fixed';
				return !isFixed;
			});
			var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
			var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
			var above = offset.top - (isFixed ? scrollY : 0) - inst.div.outerHeight();
			var below = offset.top - (isFixed ? scrollY : 0) + base.outerHeight();
			var alignL = offset.left - (isFixed ? scrollX : 0);
			var alignR = offset.left - (isFixed ? scrollX : 0) + base.outerWidth() - inst.div.outerWidth();
			var tooWide = (offset.left - scrollX + inst.div.outerWidth()) > browserWidth;
			var tooHigh = (offset.top - scrollY + inst.elem.outerHeight() +
				inst.div.outerHeight()) > browserHeight;
			inst.div.css('position', isFixed ? 'fixed' : 'absolute');
			var alignment = inst.options.alignment;
			if (alignment === 'topLeft') {
				offset = {left: alignL, top: above};
			}
			else if (alignment === 'topRight') {
				offset = {left: alignR, top: above};
			}
			else if (alignment === 'bottomLeft') {
				offset = {left: alignL, top: below};
			}
			else if (alignment === 'bottomRight') {
				offset = {left: alignR, top: below};
			}
			else if (alignment === 'top') {
				offset = {left: (inst.options.isRTL || tooWide ? alignR : alignL), top: above};
			}
			else { // bottom
				offset = {left: (inst.options.isRTL || tooWide ? alignR : alignL),
					top: (tooHigh ? above : below)};
			}
			offset.left = Math.max((isFixed ? 0 : scrollX), offset.left);
			offset.top = Math.max((isFixed ? 0 : scrollY), offset.top);
			return offset;
		}