PageSourceSearch

https://www.jimnortontoyotaokc.com/app/themes/dv-framework/shortcodes/shared/da-placement.js?ver=1.783.474

js jimnortontoyotaokc.com collected 2026-10-07 02:02:50 UTC 4,234 bytes, 131 lines download raw bytes

1/**
2 * DA Placement — shared frontend placement engine.
3 *
4 * Handles the selector-based injection mechanics used by data-driven UI
5 * features (translation switcher, sales event logos): device detection,
6 * injection relative to a target selector, fixed-corner floater positioning,
7 * and the retry watcher for targets that render late.
8 */
9window.DAPlacement = (function ($) {
10    var MOBILE_BREAKPOINT = 768; // Standard mobile breakpoint in this theme
11
12    function isMobile() {
13        return window.innerWidth <= MOBILE_BREAKPOINT;
14    }
15
16    function getDevice() {
17        return isMobile() ? 'mobile' : 'desktop';
18    }
19
20    function debounce(func, wait) {
21        var timeout;
22        return function () {
23            var context = this, args = arguments;
24            clearTimeout(timeout);
25            timeout = setTimeout(function () {
26                func.apply(context, args);
27            }, wait);
28        };
29    }
30
31    /**
32     * Move $el relative to the first element matching selector.
33     * injectionType: 'before' | 'after' | 'prepend' | 'append' (default 'after').
34     * Returns the target used, or null if the selector matched nothing.
35     */
36    function inject($el, selector, injectionType) {
37        if (!selector) {
38            return null;
39        }
40
41        var target = $(selector);
42        if (!target.length) {
43            return null;
44        }
45
46        // Prefer the first *visible* target — multi-selectors like
47        // '.ag-top-nav, .ag-top-nav-mobile' match both the desktop and mobile
48        // variants, and the right one depends on the current breakpoint.
49        // Fall back to the first match when none are visible.
50        var visible = target.filter(':visible');
51        var actualTarget = (visible.length ? visible : target).first();
52
53        switch (injectionType) {
54            case 'before': $el.insertBefore(actualTarget); break;
55            case 'prepend': $el.prependTo(actualTarget); break;
56            case 'append': $el.appendTo(actualTarget); break;
57            default: $el.insertAfter(actualTarget); break;
58        }
59
60        return actualTarget;
61    }
62
63    /**
64     * Pin $el to a viewport corner. floaterConfig: {corner: 'tl'|'tr'|'bl'|'br', offsetX, offsetY}.
65     */
66    function applyFloater($el, floaterConfig) {
67        var cfg = floaterConfig || { corner: 'br', offsetX: '20px', offsetY: '20px' };
68        var css = {
69            'position': 'fixed',
70            'z-index': '9999',
71            'bottom': 'auto',
72            'right': 'auto',
73            'top': 'auto',
74            'left': 'auto',
75            'margin': '0'
76        };
77
78        switch (cfg.corner) {
79            case 'tl': css.top = cfg.offsetY; css.left = cfg.offsetX; break;
80            case 'tr': css.top = cfg.offsetY; css.right = cfg.offsetX; break;
81            case 'bl': css.bottom = cfg.offsetY; css.left = cfg.offsetX; break;
82            case 'br': css.bottom = cfg.offsetY; css.right = cfg.offsetX; break;
83            default: css.bottom = '20px'; css.right = '20px';
84        }
85
86        $el.css(css).appendTo('body');
87    }
88
89    /**
90     * Reset positioning applied by applyFloater when moving back to an in-flow placement.
91     */
92    function clearFloater($el) {
93        $el.css({
94            'position': '',
95            'z-index': '',
96            'bottom': '',
97            'right': '',
98            'top': '',
99            'left': '',
100            'margin': ''
101        });
102    }
103
104    /**
105     * Call fn every `interval` ms until it returns true or maxAttempts is hit.
106     * Defaults match the translation switcher: every 100ms for up to 5s.
107     */
108    function watch(fn, interval, maxAttempts) {
109        interval = interval || 100;
110        maxAttempts = maxAttempts || 50;
111
112        var attempts = 0;
113        var timer = setInterval(function () {
114            attempts++;
115            if (fn() || attempts >= maxAttempts) {
116                clearInterval(timer);
117            }
118        }, interval);
119    }
120
121    return {
122        MOBILE_BREAKPOINT: MOBILE_BREAKPOINT,
123        isMobile: isMobile,
124        getDevice: getDevice,
125        debounce: debounce,
126        inject: inject,
127        applyFloater: applyFloater,
128        clearFloater: clearFloater,
129        watch: watch
130    };
131})(jQuery);

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.