PageSourceSearch

https://dance-pandect.gr/wp-content/themes/pandect/inc/vanilla/res…/js/responsiville.main.js?ver=7.1.1

js dance-pandect.gr collected 2026-09-25 01:42:28 UTC 22,902 bytes, 898 lines download raw bytes

1/**
2 * Creates and initialises the main Responsiville object. 
3 * 
4 * @class
5 * @extends   Responsiville.Debug
6 * @extends   Responsiville.Events
7 * 
8 * @author    Nevma, [email protected]
9 * @license   Nevma Copyright (c) http://www.nevma.gr
10 * 
11 * @fires     Responsiville.Main#init
12 * 
13 * @classdesc This is the main object of the Responsiville framework. The whole 
14 *            Responsiville framework depends on this object to function and so
15 *            do all the plugins that belong to the framework as well. It 
16 *            contains core functions that handle the breakpoints and the 
17 *            responsiveness of the web page in development.
18 *
19 * @param {Object} options The initialisation options of the module.
20 *
21 * @property {Object}  options             The options that define the object
22 *                                         behaviour.
23 * @property {boolean} options.debug       Whether to print debug messages in 
24 *                                         the browser console.
25 * @property {boolean} options.debugUI     Whether to show the debug panel at 
26 *                                         the edge of the screen.
27 * @property {string}  options.debugPos    Where to position the debug panel (br
28 *                                         means bottom-right, tl means top-left
29 *                                         and so on).
30 * @property {int}     options.throttle    Time delay to throttle expensive 
31 *                                         function calls as a result of 
32 *                                         repeated operations like the browser 
33 *                                         resize event.
34 * @property {Array}   options.breakpoints Array of extra breakpoints to include
35 *                                         to the framework. Each breakpoint is 
36 *                                         an associative array like { name: 
37 *                                         'small', width: 320, icon: 'uE800' }.
38 *                                         One might need to add breakpoints to 
39 *                                         this array but they probably should
40 *                                         not remove any beacuse this might
41 *                                         break behaviour of other code that
42 *                                         depends on them.
43 */
44
45Responsiville.Main = function ( options ) {
46
47    // Responsiville is a singleton.
48
49    if ( ! Responsiville.Main.instance ) {
50
51        Responsiville.Main.instance = this;
52        
53    } else {
54
55        throw new Error( 'Responsiville instantiation error: the framework has already been initialised, new Responsiville.Main is a singleton.' );
56
57    }
58
59
60
61    // General settings setup.
62    
63    this.options  = {};
64    this.options  = jQuery.extend( this.options, Responsiville.Main.defaults, options );
65    this.codeName = 'responsiville.main';
66
67
68
69    // Cache important DOM elements (note that it might be too early for the body here).
70
71    this.$window = jQuery( window );
72    this.$html   = jQuery( 'html' );
73
74    
75
76    // Flag which checks whether the resize callbacks have been called. 
77    
78    this.adjustCallbacksCalled = false;
79
80    // The previous and current breakpoint of the page.
81    
82    this.previousBreakpoint = null;
83    this.currentBreakpoint  = null;
84
85    
86
87    // Log some crap.
88    
89    var toLog = 
90        '\n' +
91        '    ____                                   _       _ ____\n' +
92        '   / __ \\___  _________  ____  ____  _____(_)   __(_) / /__\n' +
93        '  / /_/ / _ \\/ ___/ __ \\/ __ \\/ __ \\/ ___/ / | / / / / / _ \\\n' +
94        ' / _, _/  __(__  ) /_/ / /_/ / / / (__  ) /| |/ / / / /  __/\n' +
95        '/_/ |_|\\___/____/ .___/\\____/_/ /_/____/_/ |___/_/_/_/\\___/\n' +
96        '               /_/\n' +
97        '                                               version ' + Responsiville.VERSION + '\n\n';
98
99    toLog += 'breakpoints:\n';
100
101    for ( var k = 0, length = this.options.breakpoints.length; k < length; k++ ) {
102
103        var breakpoint = this.options.breakpoints[k];
104        toLog += breakpoint.name + '\t' + breakpoint.width + 'px' + ( k < length-1 ? '\n' : '' );
105
106    }
107
108    this.log( toLog );
109
110
111    
112    this.$debugControls    = null;
113    this.$debugPerformance = null;
114    this.$debugToggle      = null;
115
116
117
118    // Adjust to the current viewport and device characteristics for the first time.
119
120    this.adjust();
121
122};
123
124
125
126// Extend with logging functions.
127
128Responsiville.extend( Responsiville.Main, Responsiville.Debug.Extensions );
129
130// Extend with event handling mechanism.
131
132Responsiville.extend( Responsiville.Main, Responsiville.Events );
133
134
135
136/**
137 * @property {boolean} AUTO_RUN Controls whether this module should run by 
138 *                              default, without the developer calling it, using
139 *                              its default settings. Defaults to true.
140 */
141
142Responsiville.Main.AUTO_RUN = typeof RESPONSIVILLE_AUTO_INIT !== 'undefined' ? RESPONSIVILLE_AUTO_INIT : true;
143
144
145
146/**
147 * @property {Object} defaults Default values for this module settings.
148 */
149
150Responsiville.Main.defaults = {
151    debug       : false,
152    debugUI     : false,
153    debugPos    : 'br',
154    throttle    : 250,
155    breakpoints : [
156        { name: 'small',   width:   320, icon: '\uE800' }, // Screens    0 -  320
157        { name: 'mobile',  width:   599, icon: '\uE801' }, // Screens  321 -  599
158        { name: 'tablet',  width:  1023, icon: '\uE802' }
158, // Screens  600 - 1023
159        { name: 'laptop',  width:  1279, icon: '\uE803' }, // Screens 1024 - 1279
160        { name: 'desktop', width:  1439, icon: '\uE804' }, // Screens 1280 - 1439
161        { name: 'large',   width:  1679, icon: '\uE804' }, // Screens 1440 - 1679
162        { name: 'xlarge',  width: 99999, icon: '\uE804' }  // Screens 1601 - infinity
163    ]
164};
165
166
167
168/**
169 * Automatically initialises the Responsiville framework. It is dependendent on
170 * the fact that the jQuery and the main Responsiville scripts (not the modules)
171 * have loaded. It is activated via the global RESPONSIVILLE_AUTO_INIT and it 
172 * uses the global RESPONSIVILLE_DEBUG.
173 *
174 * @function
175 * @static
176 * 
177 * @return {void}
178 */
179
180Responsiville.Main.autoRun = function () {
181
182    // Create, but not yet initialise the Responsiville framework main singleton instance.
183
184    var responsiville = new Responsiville.Main({
185        debug   : RESPONSIVILLE_DEBUG,
186        debugUI : RESPONSIVILLE_DEBUG
187    });
188
189
190
191    // On DOMContentLoaded fully initialise the instance.
192
193    jQuery( (function () {
194
195        this.init();
196
197    }).bind( responsiville ) );
198
199};
200
201
202
203/**
204 * Get the singleton responsiville instance. Oh, did we mention? Responsiville
205 * is a singleton, because in a browser you only get one responsive web page at
206 * a time.
207 * 
208 * @function
209 * @static
210 *
211 * @return {Responsiville.Main} The singleton Responsiville object instance
212 *                              which is responsible for the current page.
213 */
214
215Responsiville.Main.getInstance = function () {
216
217    return Responsiville.Main.instance;
218
219};
220
221
222
223/**
224 * Initilalises the responsive magic. Sets up the necessary event handlers on 
225 * browser window resize that assist in controlling the desired responsive
226 * behaviour. Runs exactly once.
227 * 
228 * @return {void}
229 */
230
231Responsiville.Main.prototype.init = function () {
232
233    // In the case the framework was initialised automatically in the HEAD before the BODY was created.
234
235    var bodyElementNotCreated = typeof this.$body === 'undefined' || this.$body.length === 0;
236
237    if ( bodyElementNotCreated ) {
238        this.$body = jQuery( 'body' );
239    }
240
241
242
243    // Setup the debugging tools of the framework.
244
245    Responsiville.Debug.setupDebug();
246
247
248
249    // General debounced resize handler so that the rest of the code hooks to it instead of directly on window resize.
250
251    this.$window.on( 'resize', Responsiville.debounce( this.windowResize, this.options.throttle, this ) );
252
253
254
255
256    // Run responsive adjustments once immediately.
257
258    this.adjust();
259
260    
261
262    /**
263     * Called after the module has been initialised.
264     * 
265     * @event Responsiville.Main#init
266     */
267
268    this.fireEvent( 'init' );
269
270
271
272    // A de facto breakpoint has occured after init, so run the breakpoint change callbacks.
273
274    this.runBreakpointChangeCallbacks();
275
276
277
278    this.log( 'framework Responsiville has initialised' );
279
280};
281
282
283
284/**
285 * Registers a new, non-default, breakpoint in the system.
286 *
287 * @param {string} breakpointName  The code name of the new breakpoint.
288 * @param {int}    breakpointWidth The window width of the new breakpoint.
289 * 
290 * @return {void}
291 */
292
293Responsiville.Main.prototype.registerBreakpoint = function ( breakpointName, breakpointWidth ) {
294
295    var index = 0;
296
297    for ( var k = 0, length = this.options.breakpoints.length; k < length; k++ ) {
298
299        // Breakpoints have to be sorted by ascending screen width.
300
301        var breakpoint = this.options.breakpoints[k];
302
303        if ( breakpointWidth < breakpoint.width ) {
304            
305            index = k;
306            break;
307
308        }
309
310    }
311
312    this.options.breakpoints.splice( k, 0, { name: breakpointName, width: breakpointWidth } );
313
314    this.dir( 'breakpoint registered:', { name: breakpointName, width: breakpointWidth }, 'breakpoints:', this.options.breakpoints );
315
316};
317
318
319
320/**
321 * Deregisters an existing breakpoint.
322 *
323 * @param {string} breakpointName The code name of the breakpoint to deregister.
324 * 
325 * @return {void}
326 */
327
328Responsiville.Main.prototype.deregisterBreakpoint = function ( breakpointName ) {
329
330    for ( var k = 0, length = this.options.breakpoints.length; k < length; k++ ) {
331
332        var breakpoint = this.options.breakpoints[k];
333
334        if ( breakpointName == breakpoint.name ) {
335            
336            this.options.breakpoints.splice( k+1, 1 );
337            break;
338
339        }
340
341    }
342
343    this.dir( 'breakpoint deregistered: ' + breakpointName, 'new breakpoints: ', this.options.breakpoints );
344
345};
346
347
348
349/**
350 * Window resize event handler which takes care of manipulating the breakpoints, 
351 * setting and unsetting them accordingly.
352 * 
353 * @return {void}
354 */
355
356Responsiville.Main.prototype.adjust = function () {
357
358    this.log( 'adjusting to viewport' );
359
360
361
362    // Calculate the classes to remove from the HTML element based on the current breakpoint.
363
364    var removeClasses = '';
365
366    var k;
367    var breakpoint;
368
369    for ( k = this.options.breakpoints.length - 1; k >= 0; k-- ) {
370
371        breakpoint = this.options.breakpoints[k];
372        removeClasses += breakpoint.name + ' ';
373
374    }
375
376
377
378    // Calculate the classes to add to the HTML element based on the current breakpoint.
379
380    var addClasses = '';
381
382    for ( k = 0, length = this.options.breakpoints.length; k < length; k++ ) {
383
384        breakpoint = this.options.breakpoints[k];
385
386        if ( window.innerWidth > breakpoint.width ) {
387            addClasses += breakpoint.name + ' ';
388        } else {
389            break;
390        }
391
392    }
393
394    if ( window.innerWidth <= breakpoint.width ) {
395        addClasses += breakpoint.name + ' ';
396    }
397
398
399
400    // Add a class that indicates whether we are on a touch device or not.
401    
402    if ( this.isDevice() ) {
403        addClasses += 'device ';
404    } else {
405        removeClasses += 'device ';
406    }
407
408
409
410    // Adds a class that indicates the current browser orientation.
411    
412    if ( window.innerWidth >= window.innerHeight ) {
413        addClasses    += 'landscape ';
414        removeClasses += 'portrait ';
415    } else {
416        addClasses    += 'portrait ';
417        removeClasses += 'landscape ';
418    }
419
420
421
422    // Adds a class that indicates whether the current device is a PC or phone/tablet.
423    
424    if ( this.isDevice() ) {
425        addClasses    += 'device ';
426        removeClasses += 'pc ';
427    } else {
428        addClasses    += 'pc ';
429        removeClasses += 'device ';
430    }
431
432    this.$html.removeClass( removeClasses );
433    this.$html.addClass( addClasses );
434
435
436
437    // Sets up current breakpoint the first time the framework runs.
438    
439    var firstRun = false;
440
441    if ( ! this.currentBreakpoint ) {
442
443        firstRun = true;
444        this.currentBreakpoint = this.calculateCurrentBreakpoint();
445
446    }
447
448
449
450    // Checks if and what kind of breakpoint change has occured.
451
452    var newBreakpoint = this.calculateCurrentBreakpoint();
453    var oldBreakpoint = this.currentBreakpoint;
454
455    var breakpointChanged = 
456        firstRun ||
457        oldBreakpoint.name != newBreakpoint.name || 
458        ! this.adjustCallbacksCalled;
459
460    if ( breakpointChanged ) {
461
462        this.previousBreakpoint = this.currentBreakpoint;
463        this.currentBreakpoint = newBreakpoint;
464
465    }
466
467
468
469    // Calls event handlers that run on breakpoint changes.
470
471    if ( breakpointChanged ) {
472        
473        // Run the breakpoint change callbacks.
474        
475        this.runBreakpointChangeCallbacks();
476
477
478        
479        /**
480         * Called after a breakpoint change has occured.
481         * 
482         * @event Responsiville.Main#change
483         */
484
485        this.fireEvent( 'change' );
486        
487        this.adjustCallbacksCalled = true;
488
489    }
490
491
492
493    this.log( 
494        'window resized', 'window width: ' + window.innerWidth, 
495        ( breakpointChanged ? 'breakpoint changed from: ' + this.previousBreakpoint.name + '' : 'no breakpoint change' ),
496        'current breakpoint: ' + this.currentBreakpoint.name
497    );
498
499};
500
501
502
503/**
504 * Runs all callbacks registered on breakpoint change events (either entering or
505 * leaving a breakpoint).
506 * 
507 * @return {void}
508 */
509
510Responsiville.Main.prototype.runBreakpointChangeCallbacks = function () {
511
512    // Run all callbacks set on leaving the previous breakpoint.
513
514    this.fireEvent( 'leave.' + this.previousBreakpoint.name );
515
516    // Run all callbacks set on entering the current breakpoint.
517    
518    this.fireEvent( 'enter.' + this.currentBreakpoint.name );
519
520};
521
522
523
524/**
525 * Runs all the function callbacks which are attached to the Responsiville Main
526 * object's resize event. The call to this function has been registered as
527 * throttled to begin with, so that the browser is protected from repeated calls
528 * of the same callbacks.
529 *
530 * @fires Responsiville.Main#resize
531 * 
532 * @return void
533 */
534
535Responsiville.Main.prototype.windowResize = function () {
536
537    this.adjust();
538
539    /**
540     * Called after a breakpoint change has occured.
541     * 
542     * @event Responsiville.Main#resize
543     */
544    
545    this.fireEvent( 'resize' );
546
547};
548
549
550
551/**
552 * Checks whether the current screen has a high devide pixel ratio, that is 
553 * greater than 1 (HiDPI, retina, etc).
554 *
555 * @return {boolean} Whether the current screen has a high device pixel ratio.
556 */
557
558Responsiville.Main.prototype.isHiDPI = function () {
559
560    if ( window.devicePixelRatio > 1 ) {
561    
562        return true;
563
564    }
565
566    // High resolution screen check regular expression.
567
568    var mediaQuery = '(-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-resolution: 1.5dppx)';
569
570    if ( window.matchMedia && window.matchMedia( mediaQuery ).matches ) {
571
572        return true;
573
574    }
575
576    return false;
577
578};
579
580
581
582/**
583 * Checks whether the current device is a mobile and not a desktop one based on
584 * the user agent of the browser.
585 * 
586 * @return {boolean} Whether the current device is a mobile one.
587 */
588
589Responsiville.Main.prototype.isDevice = function () {
590
591    var deviceAgentQuery = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
592
593    return deviceAgentQuery.test( navigator.userAgent );
594
595};
596
597
598
599/**
600 * Checks whether the current browser window size is currently at the given 
601 * breakpoint(s). Useful in order to check if we are inside the range of a 
602 * specific breakpoint.
603 *
604 * @param {Array<string>|string} breakpointNames The breakpoint name(s) against
605 *                                               which to check. Can be just a
606 *                                               single breakpoint name or a 
607 *                                               comma separated list of 
608 *                                               breakpoint names or an array of
609 *                                               breakpoint names.
610 * 
611 * @return {boolean} Whether the browser window is at the given breakpoint(s).
612 */
613
614Responsiville.Main.prototype.is = function ( breakpointNames ) {
615
616    var k;
617    var testBreakpointName;
618    var breakpointNamesArray = Responsiville.splitAndTrim( breakpointNames );
619
620    for ( k in breakpointNamesArray ) {
621
622        testBreakpointName = breakpointNamesArray[k];
623
624        if ( this.currentBreakpoint && this.currentBreakpoint.name == testBreakpointName ) {
625            return true;
626        }
627        
628    }
629
630    return false;
631
632};
633
634
635
636/**
637 * Checks whether the current window is at a size smaller than the given 
638 * breakpoint. Remember that we are checking mobile first.
639 * 
640 * @param {string} testBreakpointName The breakpoint name against which to 
641 *                                    check. 
642 * 
643 * @return {boolean} Whether the browser window is at a smaller breakpoint.
644 */
645
646Responsiville.Main.prototype.isSmallerThan = function ( testBreakpointName ) {
647
648    for ( var k = 0, length = this.options.breakpoints.length; k < length; k++ ) {
649
650        var breakpoint = this.options.breakpoints[k];
651
652        if ( breakpoint.name == testBreakpointName ) {
653            return window.innerWidth < breakpoint.width;
654        }
655
656    }
657
658};
659
660
661
662/**
663 * Checks whether the current window is at a size equal or smaller than the 
664 * given breakpoint.
665 *
666 * @param {string} testBreakpointName The breakpoint name against which to 
667 *                                    check. 
668 * 
669 * @return {boolean} Whether the browser window is at an equal or smaller 
670 *                   breakpoint.
671 */
672
673Responsiville.Main.prototype.isEqualOrSmallerThan = function ( testBreakpointName ) {
674
675    return this.is( testBreakpointName ) || this.isSmallerThan( testBreakpointName );
676
677};
678
679
680
681/**
682 * Checks whether the current window is at a size bigger than the given 
683 * breakpoint.
684 * 
685 * @param {string} testBreakpointName The breakpoint name against which to 
686 *                                    check. 
687 *                                    
688 * @return {boolean} Whether the browser window is at bigger breakpoint. 
689 */
690
691Responsiville.Main.prototype.isBiggerThan = function ( testBreakpointName ) {
692
693    for ( var k = this.options.breakpoints.length-1; k >= 0; k-- ) {
694
695        var breakpoint = this.options.breakpoints[k];
696
697        if ( breakpoint.name == testBreakpointName ) {
698            return window.innerWidth > breakpoint.width;
699        }
700
701    }
702
703};
704
705
706
707/**
708 * Checks whether the current window is at a size equal or bigger than the given
709 * breakpoint.
710 *
711 * @param {string} testBreakpointName The breakpoint name against which to 
712 *                                    check. 
713 *                                    
714 * @return {boolean} Whether the browser window is at an equal or bigger
715 *                   breakpoint. 
716 */
717
718Responsiville.Main.prototype.isEqualOrBiggerThan = function ( testBreakpointName ) {
719
720    return this.is( testBreakpointName ) || this.isBiggerThan( testBreakpointName );
721
722};
723
724
725
726/**
727 * Checks whether the last breakpoint change was towards a bigger screen.
728 * 
729 * @return {boolean} Whether the last breakpoint change was towards a bigger 
730 *                   screen.
731 */
732
733Responsiville.Main.prototype.hasGrown = function () {
734
735    if ( this.currentBreakpoint.name == this.previousBreakpoint.name ) {
736        return false;
737    }
738
739
740
741    // Calculate the current and previous breakpoint widths.
742
743    var currentBreakpointWidth  = 0;
744    var previousBreakpointWidth = 0;
745
746    for ( var k = 0, length = this.options.breakpoints.length; k < length; k++ ) {
747
748        var breakpoint = this.options.breakpoints[k];
749
750        if ( this.currentBreakpoint.name == breakpoint.name ) {
751            currentBreakpointWidth = breakpoint.width;
752        } else if ( this.previousBreakpoint.name == breakpoint.name ) {
753            previousBreakpointWidth = breakpoint.width;
754        }
755
756    }
757
758
759
760    // In case of the first load of the page.
761
762    if ( previousBreakpointWidth === 0 ) {
763        return true;
764    }
765
766
767    // All other usual cases. 
768
769    return currentBreakpointWidth > previousBreakpointWidth;
770
771};
772
773
774
775/**
776 * Calculate the current breakpoint according to the current browser window 
777 * size.
778 *
779 * @return {Object} The current breakpoint.
780 */
781
782Responsiville.Main.prototype.calculateCurrentBreakpoint = function () {
783
784    var tempBreakpoint;
785
786    for ( var k = 0, length = this.options.breakpoints.length; k < length; k++ ) {
787
788        var breakpoint = this.options.breakpoints[k];
789        
790        // The current breakpoint is the one closest but bigger than the window width.
791
792        if ( window.innerWidth <= breakpoint.width ) {
793
794            tempBreakpoint = breakpoint;
795            break;
796
797        }
798
799    }
800
801    return tempBreakpoint;
802
803};
804
805
806
807/**
808 * Gets a property from the browser local storage.
809 *
810 * @param {string} name The key name of the property to retrieve from the
811 *                      browser local storage.
812 *
813 * @return {Object} The value that corresponds to the given property from the
814 *                  browser local storage.
815 */
816
817Responsiville.Main.prototype.getProperty = function ( name ) {
818
819    var localStorage = window.localStorage;
820
821    var settings = localStorage.getItem( this.codeName );
822
823    if ( settings ) {
824
825        settings = JSON.parse( settings );
826        return settings[name];
827
828    }
829
830};
831
832
833
834/**
835 * Sets a property in the browser local storage.
836 *
837 * @param {string} name  The key name of the property to set in the browser 
838 *                       local storage.
839 * @param {Object} value The value that is to be set for the given property code
840 *                       name in the browser local storage.
841 *                       
842 * @return {void}
843 */
844
845Responsiville.Main.prototype.setProperty = function ( name, value ) {
846
847    var localStorage = window.localStorage;
848
849    var settings = localStorage.getItem( this.codeName );
850
851    
852    
853    // Makes sure the settings object is created.
854
855    if ( ! settings ) {
856        settings = {};
857    } else {
858        settings = JSON.parse( settings );
859    }
860
861    settings[name] = value;
862
863
864
865    // Stores one big settings object in local storage.
866
867    localStorage.setItem( this.codeName, JSON.stringify( settings ) );
868
869};
870
871
872
873/**
874 * Prints the current registered breakpoints in the browser console.
875 *                       
876 * @return {void}
877 */
878
879Responsiville.Main.prototype.printBreakpoints = function () {
880
881    var debug = this.options.debug;
882
883    this.options.debug = true;
884
885    var toLog = [ 'Breakpoints' ];
886
887    for ( var k = 0, length = this.options.breakpoints.length; k < length; k++ ) {
888
889        var breakpoint = this.options.breakpoints[k];
890        toLog.push( breakpoint.name + ' - ' + breakpoint.width );
891        
892    }
893
894    this.log.apply( this, toLog );
895
896    this.options.debug = debug;
897
898};

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.