]> BookStack Code Mirror - bookstack/blob - resources/assets/js/global.js
Standardised JS vars and imports/exports
[bookstack] / resources / assets / js / global.js
1 "use strict";
2
3 // AngularJS - Create application and load components
4 import angular from "angular";
5 import "angular-resource";
6 import "angular-animate";
7 import "angular-sanitize";
8 import "angular-ui-sortable";
9
10 // Url retrieval function
11 window.baseUrl = function(path) {
12     let basePath = document.querySelector('meta[name="base-url"]').getAttribute('content');
13     if (basePath[basePath.length-1] === '/') basePath = basePath.slice(0, basePath.length-1);
14     if (path[0] === '/') path = path.slice(1);
15     return basePath + '/' + path;
16 };
17
18 let ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize', 'ui.sortable']);
19
20 // Global Event System
21 class EventManager {
22     constructor() {
23         this.listeners = {};
24     }
25
26     emit(eventName, eventData) {
27         if (typeof this.listeners[eventName] === 'undefined') return this;
28         let eventsToStart = this.listeners[eventName];
29         for (let i = 0; i < eventsToStart.length; i++) {
30             let event = eventsToStart[i];
31             event(eventData);
32         }
33         return this;
34     }
35
36     listen(eventName, callback) {
37         if (typeof this.listeners[eventName] === 'undefined') this.listeners[eventName] = [];
38         this.listeners[eventName].push(callback);
39         return this;
40     }
41 }
42
43 window.Events = new EventManager();
44
45 // Load in angular specific items
46 import Services from './services';
47 import Directives from './directives';
48 import Controllers from './controllers';
49 Services(ngApp, window.Events);
50 Directives(ngApp, window.Events);
51 Controllers(ngApp, window.Events);
52
53 //Global jQuery Config & Extensions
54
55 // Smooth scrolling
56 jQuery.fn.smoothScrollTo = function () {
57     if (this.length === 0) return;
58     let scrollElem = document.documentElement.scrollTop === 0 ?  document.body : document.documentElement;
59     $(scrollElem).animate({
60         scrollTop: this.offset().top - 60 // Adjust to change final scroll position top margin
61     }, 800); // Adjust to change animations speed (ms)
62     return this;
63 };
64
65 // Making contains text expression not worry about casing
66 jQuery.expr[":"].contains = $.expr.createPseudo(function (arg) {
67     return function (elem) {
68         return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
69     };
70 });
71
72 // Global jQuery Elements
73 $(function () {
74
75     let notifications = $('.notification');
76     let successNotification = notifications.filter('.pos');
77     let errorNotification = notifications.filter('.neg');
78     let warningNotification = notifications.filter('.warning');
79     // Notification Events
80     window.Events.listen('success', function (text) {
81         successNotification.hide();
82         successNotification.find('span').text(text);
83         setTimeout(() => {
84             successNotification.show();
85         }, 1);
86     });
87     window.Events.listen('warning', function (text) {
88         warningNotification.find('span').text(text);
89         warningNotification.show();
90     });
91     window.Events.listen('error', function (text) {
92         errorNotification.find('span').text(text);
93         errorNotification.show();
94     });
95
96     // Notification hiding
97     notifications.click(function () {
98         $(this).fadeOut(100);
99     });
100
101     // Chapter page list toggles
102     $('.chapter-toggle').click(function (e) {
103         e.preventDefault();
104         $(this).toggleClass('open');
105         $(this).closest('.chapter').find('.inset-list').slideToggle(180);
106     });
107
108     // Back to top button
109     $('#back-to-top').click(function() {
110          $('#header').smoothScrollTo();
111     });
112     let scrollTopShowing = false;
113     let scrollTop = document.getElementById('back-to-top');
114     let scrollTopBreakpoint = 1200;
115     window.addEventListener('scroll', function() {
116         let scrollTopPos = document.documentElement.scrollTop || document.body.scrollTop || 0;
117         if (!scrollTopShowing && scrollTopPos > scrollTopBreakpoint) {
118             scrollTop.style.display = 'block';
119             scrollTopShowing = true;
120             setTimeout(() => {
121                 scrollTop.style.opacity = 0.4;
122             }, 1);
123         } else if (scrollTopShowing && scrollTopPos < scrollTopBreakpoint) {
124             scrollTop.style.opacity = 0;
125             scrollTopShowing = false;
126             setTimeout(() => {
127                 scrollTop.style.display = 'none';
128             }, 500);
129         }
130     });
131
132     // Common jQuery actions
133     $('[data-action="expand-entity-list-details"]').click(function() {
134         $('.entity-list.compact').find('p').not('.empty-text').slideToggle(240);
135     });
136
137     // Popup close
138     $('.popup-close').click(function() {
139         $(this).closest('.overlay').fadeOut(240);
140     });
141     $('.overlay').click(function(event) {
142         if (!$(event.target).hasClass('overlay')) return;
143         $(this).fadeOut(240);
144     });
145
146     // Prevent markdown display link click redirect
147     $('.markdown-display').on('click', 'a', function(event) {
148         event.preventDefault();
149         window.open($(this).attr('href'));
150     });
151
152     // Detect IE for css
153     if(navigator.userAgent.indexOf('MSIE')!==-1
154         || navigator.appVersion.indexOf('Trident/') > 0
155         || navigator.userAgent.indexOf('Safari') !== -1){
156         $('body').addClass('flexbox-support');
157     }
158
159 });
160
161 // Page specific items
162 import "./pages/page-show";