PageSourceSearch

https://www.newnordicfilms.no/assets/js/mars.js

js newnordicfilms.no collected 2026-10-02 12:18:51 UTC 16,652 bytes, 527 lines download raw bytes

1import 'https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js';
2import 'https://d1zibq5kp019rb.cloudfront.net/node_modules/vue/vue.js';
3// import 'https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js';
4
5window.getHeaders = () => ({ 'Token': getCookie('Token'), 'SubAppId': getCookie('SubAppId'), 'Content-Type': 'application/json;charset=UTF-8', 'Accept': 'application/json' });
6window.flatten = (arr) => { return arr.reduce((flat, toFlatten) => flat.concat(Array.isArray(toFlatten) ? window.flatten(toFlatten) : toFlatten), []); };
7window.AsyncFunction = Object.getPrototypeOf(async () => { }).constructor;
8window.deleteCookie = function (name) { setCookie(name, '', -1); };
9
10window.getCookie = function (cname) {
11  var name = cname + '=';
12  var decodedCookie = decodeURIComponent(document.cookie);
13  var ca = decodedCookie.split(';');
14  for (var i = 0; i < ca.length; i++) {
15    var c = ca[i];
16    while (c.charAt(0) == ' ') {
17      c = c.substring(1);
18    }
19
20    if (c.indexOf(name) == 0) {
21      return c.substring(name.length, c.length);
22    }
23  }
24
25  return '';
26};
27
28window.setCookie = function (name, value, days) {
29  const d = new Date();
30  d.setTime(d.getTime() + 24 * 60 * 60 * 1000 * (days || 18250));
31  document.cookie = name + "=" + value + ";path=/;expires=" + d.toGMTString();
32};
33
34window.postRequest = async function (url = '', data = {}, headers = { 'Content-Type': 'application/json;charset=UTF-8', 'Accept': 'application/json' }, cache = 'no-cache') {
35  const response = await fetch(url, {
36    method: 'POST',
37    headers,
38    cache,
39    body: JSON.stringify(data || {}),
40  });
41
42  const contentType = response.headers.get('content-type');
43  const responseData = await (contentType && contentType.includes('application/json') ? response.json() : response.text());
44  if (!response.ok) {
45    throw {
46      message: response.statusText,
47      response: {
48        status: response.status,
49        data: responseData,
50        headers: Object.fromEntries(response.headers.entries()),
51      },
52    };
53  }
54
55  return { data: responseData };
56};
57
58window.getRequest = async function (url = '', data = {}, headers = { 'Content-Type': 'application/json;charset=UTF-8', 'Accept': 'application/json' }) {
59  const response = await fetch(url, {
60    method: 'GET',
61    headers
62  });
63
64  const contentType = response.headers.get('content-type');
65  const responseData = await (contentType && contentType.includes('application/json') ? response.json() : response.text());
66  if (!response.ok) {
67    throw {
68      message: response.statusText,
69      response: {
70        status: response.status,
71        data: responseData,
72        headers: Object.fromEntries(response.headers.entries()),
73      },
74    };
75  }
76
77  return { data: responseData };
78};
79
80window.debounce = function debounce(func, wait, immediate) {
81  let timeout, args, context, timestamp, result;
82  if (wait == null) wait = 100;
83
84  function later() {
85    const last = Date.now() - timestamp;
86
87    if (last < wait && last >= 0) {
88      timeout = setTimeout(later, wait - last);
89    } else {
90      timeout = null;
91      if (!immediate) {
92        result = func.apply(context, args);
93        context = args = null;
94      }
95    }
96  };
97
98  const debounced = function () {
99    context = this;
100    args = arguments;
101    timestamp = Date.now();
102    const callNow = immediate && !timeout;
103    if (!timeout) timeout = setTimeout(later, wait);
104    if (callNow) {
105      result = func.apply(context, args);
106      context = args = null;
107    }
108
109    return result;
110  };
111
112  debounced.clear = function () {
113    if (timeout) {
114      clearTimeout(timeout);
115      timeout = null;
116    }
117  };
118
119  debounced.flush = function () {
120    if (timeout) {
121      result = func.apply(context, args);
122      context = args = null;
123
124      clearTimeout(timeout);
125      timeout = null;
126    }
127  };
128
129  return debounced;
130};
131
132window.to = async function (promise) {
133  return promise.then((data) => [null, data]).catch((err) => [err, null]);
134};
135
136class MarsBase {
137  constructor(id, serverData) {
138    this._marsId = id;
139    this._marsEl = document.getElementById(id);
140    this._marsData = serverData;
141
142    this.initApi();
143    this.initEvents();
144
145    window[this._marsId] = this;
146  }
147
148  initApi() {
149    this.api = {
150      _hidden: false,
151      hide: () => { this._marsEl.classList.add('d-none') },
152      show: () => { this._marsEl.classList.remove('d-none') },
153      get hidden() { return this._hidden; },
154      set hidden(val) {
155        val ? this.hide() : this.show();
156        this._hidden = val;
157      },
158    };
159
160    const defaultMethods = [{ name: 'reRender', block: 'MarsJs' }];
161    if (!this._marsData) { this._marsData = {}; }
162    if (!this._marsData.methods) { this._marsData.methods = []; }
163
164    [...this._marsData.methods, ...defaultMethods].forEach(i => {
165      this.api[i.name] = (...args) => {
166        return new Promise((resolve, reject) => {
167          window.postRequest(`/api/ExecuteApiMethod?blockName=${i.block}&methodName=${i.name}`, { "blockData": this._marsData, "methodData": args }, window.getHeaders())
168            .then((response) => {
169              resolve(response.data);
170            })
171            .catch((error) => {
172              reject(error);
173            });
174        });
175      }
176    });
177
178    this.api.reload = async (optionalData) => {
179      const r = await this.api.reRender(this._marsData._blockName, { Id: this._marsId, ...this._marsData, ...(optionalData || {}) });
180
181      // remove all children objects
182      delete window[this._marsId];
183      let children = document.querySelectorAll(`#${this._marsId} [id]`);
184      children.forEach(i => {
185        if (window[i.id]) {
186          delete window[i.id];
187        }
188      });
189
190      $(`#${this._marsId}`).replaceWith(r);
191      return r;
192    }
193  }
194
195  initEvents() {
196    this._marsEvents = {
197      initEvent: (eventName) => {
198        if (!this[eventName]) {
199          const eventHandlersKey = `${eventName}_Handlers`;
200          this._marsEvents[eventHandlersKey] = [];
201          Object.defineProperty(this, eventName, {
202            set: (handler) => {
203              if (!this._marsEvents[eventHandlersKey].find(t => t.toString() === handler.toString())) {
204                this._marsEvents[eventHandlersKey].push(handler);
205              }
206            },
207            // get: () => {
208            //   return this._marsEvents[eventHandlersKey];
209            // },
210          });
211        }
212      },
213      fireEvent: (eventName, ...eventData) => {
214        const eventHandlersKey = `${eventName}_Handlers`;
215        if (this._marsEvents[eventHandlersKey] && this._marsEvents[eventHandlersKey].length) {
216          this._marsEvents[eventHandlersKey].forEach(t => t(...eventData));
217        }
218      },
219    };
220
221    this.fire = {};
222    if (this._marsData.events) {
223      for (let eventName in this._marsData.events) {
224        this._marsEvents.initEvent(eventName);
225        this.fire[eventName] = (...eventData) => {
226          this._marsEvents.fireEvent(eventName, ...eventData);
227        };
228      }
229    }
230  }
231}
232
233class MarsBlock extends MarsBase {
234  constructor(id, serverData, app) {
235    super(id, { ...serverData, events: app.events });
236
237    Object.getOwnPropertyNames(app).map(property => {
238      const propertyDescriptor = Object.getOwnPropertyDescriptor(app, property);
239      Object.defineProperty(this, property, propertyDescriptor);
240    });
241
242    window.dispatchEvent(new CustomEvent(id, { detail: this }));
243  }
244}
245
246class MarsVue extends MarsBase {
247  constructor(id, serverData, app) {
248    if (!id) {
249      return;
250    }
251
252    super(id, { ...serverData, events: app.events });
253    const vue = new Vue(Object.assign(app, { el: `#${id}` }));
254
255    Object.getOwnPropertyNames(this).map(property => {
256      const propertyDescriptor = Object.getOwnPropertyDescriptor(this, property);
257      Object.defineProperty(vue, property, propertyDescriptor);
258    });
259
260    window[id] = vue;
261    this.vue = vue;
262    window.dispatchEvent(new CustomEvent(id, { detail: vue }));
263  }
264}
265
266/*
267class MarsAlpine extends MarsBase {
268  init() {
269    return this._marsData;
270  }
271
272  get data() {
273    return this._marsData.$el.__x.$data;
274  }
275
276  constructor(instanceId, serverData, app) {
277    if (!instanceId) {
278      return;
279    }
280
281    super(instanceId, { ...serverData, ...app });
282    this._marsData.fire = this.fire;
283
284    const el = document.getElementById(instanceId);
285    el.setAttribute('x-data', instanceId + '.init()');
286    Alpine.initializeComponent(el);
287  }
288}
289*/
290
291window['MarsBlock'] = MarsBlock;
292window['MarsVue'] = MarsVue;
293// window['MarsAlpine'] = MarsAlpine;
294
295const awaitForBlock = async function (blockId) {
296  const isMarsObject = (block) => (block && block.constructor && (block instanceof Vue || block instanceof MarsBlock || block.constructor.name === 'MarsBlock'));
297  return new Promise((resolve, reject) => {
298    const block = window[blockId];
299    if (isMarsObject(block)) {
300      resolve(block);
301      return;
302    }
303
304    window.addEventListener(blockId, (e) => {
305      if (isMarsObject(e.detail)) {
306        resolve(e.detail);
307      }
308    });
309  });
310};
311
312const awaitForDomNode = async function (selector) {
313  return new Promise((resolve, reject) => {
314    const node = document.querySelector(selector);
315    if (node) {
316      resolve(node);
317      return;
318    }
319
320    new MutationObserver((mutationRecords, observer) => {
321      const node = document.querySelector(selector);
322      if (node) {
323        resolve(node);
324        observer.disconnect();
325        return;
326      }
327    }).observe(document.documentElement, { childList: true, subtree: true });
328  });
329};
330
331window.executeAppBlock = async function executeAppBlock(f, props, ...children) {
332  // regular html tags
333  if (typeof (f) === 'string') {
334    const htmlProps = props ? Object.entries(props).map(([key, value]) => `${key}="${value}"`).join(' ') : null;
335    return `<${f} ${htmlProps || ''}>${(await Promise.all(flatten(children))).join('')}</${f}>`
336  }
337
338  // function block
339  if (children && children.length > 0) {
340    props = props || {};
341    props.children = await Promise.all(flatten(children));
342    /*props.children = await Promise.all(props.children.map(t => {
343        const r = t.render ? t.render() : t;
344        return r;
345    }));*/
346  }
347
348  return f.name === 'anonymous' ? f(Mars, props) : f(props);
349};
350
351
352function editData(name, objectId, path, options = {}) {
353  const editUrl = `/mars/edit-data/${name}/blocks?objectId=${objectId || ''}&path=${path || 'Config'}`;
354  console.log('editUrl', editUrl)
355  Modal.open(`/api/RenderFormByModel?Id=RenderDataByModel1&modelName=${name}&path=${path || 'Config'}&collectionName=blocks&objectId=${objectId || ''}&iframeUrl=${encodeURIComponent(editUrl)}`,
356    { ...{ width: '550px', noPadding: true, title: `Edit ${name}` }, ...options })
357}
358
359function editDataModel(name, objectId, options = {}) {
360  const editUrl = `/mars/edit-data-args/${name}`;
361  console.log('editUrl', editUrl)
362  Modal.open(`/api/RenderFormByModel?height=900px&Id=RenderDataByModel1&modelName=${name}&path=DataArgs&collectionName=blocks&objectId=${objectId || ''}&iframeUrl=${encodeURIComponent(editUrl)}`,
363    { ...{ width: '800px', height: '100%', noPadding: true, title: `Edit model: ${name}` }, ...options })
364}
365
366window.Mars = {
367  executeAppBlock,
368  editData,
369  editDataModel,
370  awaitForBlock,
371  awaitForDomNode,
372};
373
374// to create removeEventListeners - https://stackoverflow.com/a/47117084
375(function () {
376  const target = EventTarget.prototype;
377  const functionName = 'addEventListener';
378  const func = target[functionName];
379
380  const symbolHidden = Symbol('hidden');
381
382  function hidden(instance) {
383    if (instance[symbolHidden] === undefined) {
384      const area = {};
385      instance[symbolHidden] = area;
386      return area;
387    }
388
389    return instance[symbolHidden];
390  }
391
392  function listenersFrom(instance) {
393    const area = hidden(instance);
394    if (!area.listeners) { area.listeners = []; }
395    return area.listeners;
396  }
397
398  target[functionName] = function (type, listener) {
399    if (!this) {
400      return;
401    }
402
403    const listeners = listenersFrom(this);
404    listeners.push({ type, listener });
405    func.apply(this, [type, listener]);
406  };
407
408  target['removeEventListeners'] = function (targetType) {
409    if (!this) {
410      return;
411    }
412
413    const self = this;
414    const listeners = listenersFrom(this);
415    listeners.forEach(item => {
416      const type = item.type;
417      const listener = item.listener;
418      if (type == targetType) {
419        self.removeEventListener(type, listener);
420      }
421    });
422  };
423})();
424
425// to observe window.location.href changes
426let currentHref = document.location.href;
427window.onload = function () {
428  const observer = new MutationObserver(function (mutations) {
429    mutations.forEach(function (mutation) {
430      if (currentHref != document.location.href) {
431        currentHref = document.location.href;
432        window.dispatchEvent(new Event('onLocationChange'));
433      }
434    });
435  });
436
437  const body = document.querySelector('body');
438  observer.observe(body, { childList: true, subtree: true });
439};
440window.resizeIFrameToFitContent = (iFrame) => {
441  const height = iFrame.contentWindow.document.body.scrollHeight;
442  iFrame.width = iFrame.contentWindow.document.body.scrollWidth;
443  iFrame.height = height > 550 ? height : 550;
444}
445
446window.scrollToAnchor = (topOffset) => {
447  if (location.hash && location.hash.length > 1) {
448    $('html, body').animate({
449      scrollTop: $('h1,h2,h3,h4,h5,h6').filter(':contains("' + decodeURIComponent(location.hash.slice(1)) + '")').scroll().offset().top + (topOffset || 0)
450    })
451  }
452}
453
454window.marsAlert = (message, status) => {
455  Modal.open('/api/MessageTemplate', { center: true, hideModalHeader: true, width: '350px', noPadding: true, hideCloseButton: true }, null, { message, status })
456}
457/* load new page content when user clicks on an element with data-target-partial tag and prevent default navigation */
458$(document).on('click', '[data-target-partial]', function (e) {
459  e.preventDefault();
460  const targetUrl = $(this).attr('href');
461  if (targetUrl) {
462    targetUrl.startsWith('http') || targetUrl.startsWith('www.')
463      ? window.open(targetUrl)
464      : window.goTo(targetUrl);
465  }
466
467  return false;
468});
469
470window.history.replaceState(location.pathname, '', location.href);
471
472window.onpopstate = function (e) {
473  if (e.state != null) {
474    if (typeof (e.state) === 'string') window.goTo(e.state, true, null, true)
475    else window.goTo(e.state.targetUrl, true, e.state, true);
476  }
477}
478
479window.goTo = async (targetUrl, dontScroll, cachedData, goBack = false) => {
480  if (!targetUrl) targetUrl = location.href;
481  if (!goBack) { window.history.pushState(targetUrl, '', targetUrl); }
482  history.replaceState(targetUrl, null, targetUrl);
483  pageLoadSpinner.hidden = false;
484
485  function replaceHtmlOnPage(t) {
486    if (history.state !== targetUrl) return
487    
488    const namedSlot = $(`#${t.data.master}`);
489    const slot = $(`[data-master-content]:first`);
490
491    // if the target page master is nested, then we reload the page since we cannot do ajax in this case
492    if (!$(`[data-master-content]`).toArray().map(t => t.id).includes(t.data.master)) {
493      location.reload();
494      return;
495    }
496    window.dispatchEvent(new Event('locationchange'));
497
498    // if it is first level navigation we scroll to the top
499    if ($(`[data-master-content]`).length === 1 && !dontScroll) {
500      // console.log('scroll to top')
501      window.scrollTo(0, 0);
502    }
503
504    (namedSlot.length > 0 ? namedSlot : slot).html(typeof (t.data) === 'string' ? t.data : t.data.html);
505    pageLoadSpinner.hidden = true;
506
507    document.title = t.data.pageTitle;
508    // google analytics page view tracking
509    if (window.webMesurementId && gtag) {
510      window.gtag('event', 'page_view', {
511        page_title: document.title,
512        page_location: location.href,
513        page_path: location.pathname,
514        send_to: window.webMesurementId,
515      });
516    }
517
518    scrollToAnchor();
519    //history.pushState({ data: t.data, targetUrl: targetUrl }, null, targetUrl);
520  }
521
522  if (cachedData) {
523    replaceHtmlOnPage(cachedData);
524  } else {
525    return window.getRequest(targetUrl + (targetUrl.includes('?') ? '&' : '?') + 'noMaster=true').then(replaceHtmlOnPage).catch(function (reason) { console.error(reason); return reason; });
526  }
527}

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.