1<?xml version="1.0" encoding="UTF-8"?> 2<!DOCTYPE html> 3<html xmlns="http://www.w3.org/1999/xhtml"><head id="j_idt2"> 4 <link rel="SHORTCUT ICON" href="https://f.nordiskemedier.dk/favicon/rtforum2.ico" /> 5 <link rel="ICON" href="https://f.nordiskemedier.dk/favicon/rtforum2.ico" type="image/x-icon" /> 6 <title>Anmäl dig till vårt nyhetsbrev</title> 7 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> 9 <meta id="viewport" name="viewport" content="width=device-width, initial-scale=1" /> 10
10<script> 11 //<![CDATA[ 12 (function () { 13 var width = window.innerWidth || 14 document.documentElement.clientWidth || 15 document.body.clientWidth; 16 if (width >= 768) { 17 document.getElementById("viewport").setAttribute("content", "width=1344"); 18 } else { 19 document.getElementById("viewport").setAttribute("content", "width=device-width, initial-scale=1"); 20 } 21 })(); 22 //]]> 23 </script>
23 24 <meta http-equiv="content-script-type" content="text/javascript" /> 25 <meta http-equiv="cache-control" content="no-cache" /> 26 <meta http-equiv="expires" content="0" /> 27 <meta http-equiv="pragma" content="no-cache" /> 28
28<script src="/js/vars.js?t=1790253005902" type="text/javascript"></script>
28 29
29<script src="/js/access.js?t=1790253005902" type="text/javascript"></script>
29 30
30<script> 31 window.startupTimestamp = "1790253005902"; 32 window.contextPath = ""; 33 window.domain = "https://www.rt-forum.se"; 34 window.fileDomain = "https://f.nordiskemedier.dk"; 35 window.logoName = "54"; 36 window.hostId = 54; 37 window.visitor = {}; 38 window.cvrRestApiAddress = "https://cvr-api.nordiskemedier.dk/resources"; 39 window.metaObject = {"industryName":"","authorInitials":"","pageType":"","contentType":""}; 40 window.testMode = false; 41 42 window.googleAnalytics = false; 43 window.pendingScriptExecutions = []; 44 window.enableCookieBot = new function () {}; 45 46 window.trackerEnabled = true; // TODO: replace with JsVarsServlet after merge 47 </script>
47 48 49
49<script type="text/javascript" async="true"> 50 //<![CDATA[ 51 (function() { 52 var host = window.location.hostname; 53 var element = document.createElement('script'); 54 var firstScript = document.getElementsByTagName('script')[0]; 55 var url = 'https://cmp.inmobi.com' 56 .concat('/choice/', 'h8eTMmqFZF-_K', '/', host, '/choice.js?tag_version=V3'); 57 var uspTries = 0; 58 var uspTriesLimit = 3; 59 element.async = true; 60 element.type = 'text/javascript'; 61 element.src = url; 62 63 // Not default InMobi code - make sure there is a script present 64 // before inserting anything before it. 65 if (firstScript) { 66 firstScript.parentNode.insertBefore(element, firstScript); 67 } 68 69 function makeStub() { 70 var TCF_LOCATOR_NAME = '__tcfapiLocator'; 71 var queue = []; 72 var win = window; 73 var cmpFrame; 74 75 function addFrame() { 76 var doc = win.document; 77 var otherCMP = !!(win.frames[TCF_LOCATOR_NAME]); 78 79 if (!otherCMP) { 80 if (doc.body) { 81 var iframe = doc.createElement('iframe'); 82 83 iframe.style.cssText = 'display:none'; 84 iframe.name = TCF_LOCATOR_NAME; 85 doc.body.appendChild(iframe); 86 } else { 87 setTimeout(addFrame, 5); 88 } 89 } 90 return !otherCMP; 91 } 92 93 function tcfAPIHandler() { 94 var gdprApplies; 95 var args = arguments; 96 97 if (!args.length) { 98 return queue; 99 } else if (args[0] === 'setGdprApplies') { 100 if ( 101 args.length > 3 && 102 args[2] === 2 && 103 typeof args[3] === 'boolean' 104 ) { 105 gdprApplies = args[3]; 106 if (typeof args[2] === 'function') { 107 args[2]('set', true); 108 } 109 } 110 } else if (args[0] === 'ping') { 111 var retr = { 112 gdprApplies: gdprApplies, 113 cmpLoaded: false, 114 cmpStatus: 'stub' 115 }; 116 117 if (typeof args[2] === 'function') { 118 args[2](retr); 119 } 120 } else { 121 if(args[0] === 'init' && typeof args[3] === 'object') { 122 args[3] = Object.assign(args[3], { tag_version: 'V3' }); 123 } 124 queue.push(args); 125 } 126 } 127 128 function postMessageEventHandler(event) { 129 var msgIsString = typeof event.data === 'string'; 130 var json = {}; 131 132 try { 133 if (msgIsString) { 134 json = JSON.parse(event.data); 135 } else { 136 json = event.data; 137 } 138 } catch (ignore) {} 139 140 var payload = json.__tcfapiCall; 141 142 if (payload) { 143 window.__tcfapi( 144 payload.command, 145 payload.version, 146 function(retValue, success) { 147 var returnMsg = { 148 __tcfapiReturn: { 149 returnValue: retValue, 150 success: success, 151 callId: payload.callId 152 } 153 }; 154 if (msgIsString) { 155 returnMsg = JSON.stringify(returnMsg); 156 } 157 if (event && event.source && event.source.postMessage) { 158 event.source.postMessage(returnMsg, '*'); 159 } 160 }, 161 payload.parameter 162 ); 163 } 164 } 165 166 while (win) { 167 try { 168 if (win.frames[TCF_LOCATOR_NAME]) { 169 cmpFrame = win; 170 break; 171 } 172 } catch (ignore) {} 173 174 if (win === window.top) { 175 break; 176 } 177 win = win.parent; 178 } 179 if (!cmpFrame) { 180 addFrame(); 181 win.__tcfapi = tcfAPIHandler; 182 win.addEventListener('message', postMessageEventHandler, false); 183 } 184 }; 185 186 makeStub(); 187 188 function makeGppStub() { 189 const CMP_ID = 10; 190 const SUPPORTED_APIS = [ 191 '2:tcfeuv2', 192 '6:uspv1', 193 '7:usnatv1', 194 '8:usca', 195 '9:usvav1', 196 '10:uscov1', 197 '11:usutv1', 198 '12:usctv1' 199 ]; 200 201 window.__gpp_addFrame = function (n) { 202 if (!window.frames[n]) { 203 if (document.body) { 204 var i = document.createElement("iframe"); 205 i.style.cssText = "display:none"; 206 i.name = n; 207 document.body.appendChild(i); 208 } else { 209 window.setTimeout(window.__gpp_addFrame, 10, n); 210 } 211 } 212 }; 213 window.__gpp_stub = function () { 214 var b = arguments; 215 __gpp.queue = __gpp.queue || []; 216 __gpp.events = __gpp.events || []; 217 218 if (!b.length || (b.length == 1 && b[0] == "queue")) { 219 return __gpp.queue; 220 } 221 222 if (b.length == 1 && b[0] == "events") { 223 return __gpp.events; 224 } 225 226 var cmd = b[0]; 227 var clb = b.length > 1 ? b[1] : null; 228 var par = b.length > 2 ? b[2] : null; 229 if (cmd === "ping") { 230 clb( 231 { 232 gppVersion: "1.1", // must be âVersion.Subversionâ, current: â1.1â 233 cmpStatus: "stub", // possible values: stub, loading, loaded, error 234 cmpDisplayStatus: "hidden", // possible values: hidden, visible, disabled 235 signalStatus: "not ready", // possible values: not ready, ready 236 supportedAPIs: SUPPORTED_APIS, // list of supported APIs 237 cmpId: CMP_ID, // IAB assigned CMP ID, may be 0 during stub/loading 238 sectionList: [], 239 applicableSections: [-1], 240 gppString: "", 241 parsedSections: {}, 242 }, 243 true 244 ); 245 } else if (cmd === "addEventListener") { 246 if (!("lastId" in __gpp)) { 247 __gpp.lastId = 0; 248 } 249 __gpp.lastId++; 250 var lnr = __gpp.lastId; 251 __gpp.events.push({ 252 id: lnr, 253 callback: clb, 254 parameter: par, 255 }); 256 clb( 257 { 258 eventName: "listenerRegistered", 259 listenerId: lnr, // Registered ID of the listener 260 data: true, // positive signal 261 pingData: { 262 gppVersion: "1.1", // must be âVersion.Subversionâ, current: â1.1â 263 cmpStatus: "stub", // possible values: stub, loading, loaded, error 264 cmpDisplayStatus: "hidden", // possible values: hidden, visible, disabled 265 signalStatus: "not ready", // possible values: not ready, ready 266 supportedAPIs: SUPPORTED_APIS, // list of supported APIs 267 cmpId: CMP_ID, // list of supported APIs 268 sectionList: [], 269 applicableSections: [-1], 270 gppString: "", 271 parsedSections: {}, 272 }, 273 }, 274 true 275 ); 276 } else if (cmd === "removeEventListener") { 277 var success = false;
278 for (var i = 0; i < __gpp.events.length; i++) { 279 if (__gpp.events[i].id == par) { 280 __gpp.events.splice(i, 1); 281 success = true; 282 break; 283 } 284 } 285 clb( 286 { 287 eventName: "listenerRemoved", 288 listenerId: par, // Registered ID of the listener 289 data: success, // status info 290 pingData: { 291 gppVersion: "1.1", // must be âVersion.Subversionâ, current: â1.1â 292 cmpStatus: "stub", // possible values: stub, loading, loaded, error 293 cmpDisplayStatus: "hidden", // possible values: hidden, visible, disabled 294 signalStatus: "not ready", // possible values: not ready, ready 295 supportedAPIs: SUPPORTED_APIS, // list of supported APIs 296 cmpId: CMP_ID, // CMP ID 297 sectionList: [], 298 applicableSections: [-1], 299 gppString: "", 300 parsedSections: {}, 301 }, 302 }, 303 true 304 ); 305 } else if (cmd === "hasSection") { 306 clb(false, true); 307 } else if (cmd === "getSection" || cmd === "getField") { 308 clb(null, true); 309 } 310 //queue all other commands 311 else { 312 __gpp.queue.push([].slice.apply(b)); 313 } 314 }; 315 window.__gpp_msghandler = function (event) { 316 var msgIsString = typeof event.data === "string"; 317 try { 318 var json = msgIsString ? JSON.parse(event.data) : event.data; 319 } catch (e) { 320 var json = null; 321 } 322 if (typeof json === "object" && json !== null && "__gppCall" in json) { 323 var i = json.__gppCall; 324 window.__gpp( 325 i.command, 326 function (retValue, success) { 327 var returnMsg = { 328 __gppReturn: { 329 returnValue: retValue, 330 success: success, 331 callId: i.callId, 332 }, 333 }; 334 event.source.postMessage(msgIsString ? JSON.stringify(returnMsg) : returnMsg, "*"); 335 }, 336 "parameter" in i ? i.parameter : null, 337 "version" in i ? i.version : "1.1" 338 ); 339 } 340 }; 341 if (!("__gpp" in window) || typeof window.__gpp !== "function") { 342 window.__gpp = window.__gpp_stub; 343 window.addEventListener("message", window.__gpp_msghandler, false); 344 window.__gpp_addFrame("__gppLocator"); 345 } 346 }; 347 348 makeGppStub(); 349 350 var uspStubFunction = function() { 351 var arg = arguments; 352 if (typeof window.__uspapi !== uspStubFunction) { 353 setTimeout(function() { 354 if (typeof window.__uspapi !== 'undefined') { 355 window.__uspapi.apply(window.__uspapi, arg); 356 } 357 }, 500); 358 } 359 }; 360 361 var checkIfUspIsReady = function() { 362 uspTries++; 363 if (window.__uspapi === uspStubFunction && uspTries < uspTriesLimit) { 364 console.warn('USP is not accessible'); 365 } else { 366 clearInterval(uspInterval); 367 } 368 }; 369 370 if (typeof window.__uspapi === 'undefined') { 371 window.__uspapi = uspStubFunction; 372 var uspInterval = setInterval(checkIfUspIsReady, 6000); 373 } 374 })(); 375 //]]> 376 </script>
376 377
377<script type="application/ld+json"> 378 { 379 "@context":"http://schema.org", 380 "@type":"NewsMediaOrganization", 381 "name":"RT-Forum", 382 "logo":{ 383 "@type":"ImageObject", 384 "url":"https://f.nordiskemedier.dk/logo/portal/54.png" 385 }, 386 "url":"https://www.rt-forum.se", 387 "ethicsPolicy":"https://www.rt-forum.se/privacy", 388 "sameAs":["https://www.facebook.com/Trafikforum","https://www.linkedin.com/company/res-och-trafikforum/"] 389 } 390 </script>
390 391
391<script src="/js/notbot.js?t=1790253005902" type="text/javascript"></script>
391 392 393 <link href="https://f.nordiskemedier.dk/font/media.css" rel="stylesheet" /> 394 <link rel="stylesheet" href="https://f.nordiskemedier.dk/font-awesome/pro/6.6.0/css/all.min.css" /> 395 <link rel="stylesheet" href="https://f.nordiskemedier.dk/bootstrap/5.3.6/css/bootstrap.min.css" /> 396 <link rel="stylesheet" href="/css/default.css?t=1790253005902" type="text/css" /> 397
397<script src="https://f.nordiskemedier.dk/jquery/jquery-3.6.0.min.js"></script>
397 398 399
399<script src="/js/jquery-ui.min.js"></script>
399<script type="text/javascript" src="/javax.faces.resource/js/jquery.cookies.2.2.0.min.js.html?ln=portal-jsf&t=17902530"></script>
399 400
400<script src="https://f.nordiskemedier.dk/bootstrap/5.3.6/js/bootstrap.bundle.min.js"></script>
400 401
401<script src="/js/default.js?t=1790253005902" type="text/javascript"></script>
vendor: 138 bytes, lines 401-403
401 402 <script src="https://www.google.com/recaptcha/api.js?render=explicit&hl=sv" type="text/javascript"></script> 403
403<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
403 404
404<script src="/dist/vue-components.umd.min.js?t=1790253005902" type="text/javascript"></script>
404 405 406
406<script src="https://f.nordiskemedier.dk/turnjs4/lib/turn.min.js" type="text/javascript"></script>
406<!--[if lt IE 9]> 407
407<script src="https://f.nordiskemedier.dk/turnjs4/lib/turn.html4.min.js" type="text/javascript"></script>
407<![endif]--><!--[if lt IE 9]> 408
408<script type="text/javascript"> 409 window.location = "/browser-support.html"; 410 </script>
410<![endif]--> 411
411<script src="https://cdn.jsdelivr.net/npm/ua-parser-js@0/dist/ua-parser.min.js"></script>
411 412
412<script type="text/javascript"> 413 window.enableGTM = function() { 414 try {
vendor: 647 bytes, lines 414-427
414 415 (function (w, d, s, l, i) { 416 w[l] = w[l] || []; 417 w[l].push({ 418 'gtm.start': 419 new Date().getTime(), event: 'gtm.js' 420 }); 421 var f = d.getElementsByTagName(s)[0], 422 j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; 423 j.async = true; 424 j.src = 425 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; 426 f.parentNode.insertBefore(j, f); 427 })(window, document, 'script', 'dataLayer', '
427GTM-K3P2LSL
vendor: 16 bytes, lines 427-428
427'); 428
428} catch (err) { 429 console.log(err); 430 } 431 }; 432 </script>
432 433 434 435 436
436<script src="/js/cookie-utilities.js"></script>
436 437
437<script type="text/javascript"> 438 var gaPageType = 'misc'; 439 var gaContentType = 'misc'; 440 var gaPageAge = null; 441 var gaPageSize = null; 442 var gaIndustryName = 'null'; 443 444 </script>
444 445
445<script type="text/javascript"> 446 window.enableBanners = function () { 447 try { 448 window['banner-consent-is-ready'] = true; 449 EventBus.broadcast("banner-consent-is-ready"); 450 } catch (err) { 451 console.log(err); 452 } 453 }; 454 </script>
454 455
455<script type="text/javascript"> 456 //<![CDATA[ 457 (function () { 458 var salespanelModuleEnabled = false; 459 var quantCastModuleEnabled = true; 460 var salespanelResolve, salespanelReject; 461 window.salespanelPromise = new Promise((resolve, reject) => { 462 // Check if Salespanel and QuantCast module is enabled for this host and check if the tag has loaded. 463 if (!salespanelModuleEnabled || !quantCastModuleEnabled) { 464 resolve(false); 465 } 466 salespanelResolve = resolve; 467 salespanelReject = reject; 468 }); 469 470 // Reject just in case QuantCast module is enabled but variable is not initialized. 471 if (typeof window.__tcfapi == "undefined") { 472 salespanelReject("QuantCast error: __tcfapi is undefined"); 473 return; 474 } 475 476 // Listen for Quantcast events for changes to Salespanel consent. 477 window.__tcfapi('addEventListener', 2, async function (tcData, success) { 478 if (!success) { 479 salespanelReject("Salespanel error: Could not create event listener."); 480 return; 481 } 482 483 // the rest of this function is called when the page is loaded OR 484 // - the user accepts / rejects / updates the consent terms 485 // - the user dismisses the consent box by clicking the 'x' 486 if (tcData.eventStatus !== 'tcloaded' && tcData.eventStatus !== 'useractioncomplete') { 487 return; 488 } 489 490 // Salespanel is managed by Google Tag Manager and is not inserted if the relevant consent is not given. 491 // If consent is given, it returns true, otherwise false after 2,5 seconds. 492 var loops = 0; 493 while(!salespanelObjectLoaded() && loops < 5) { 494 await new Promise(resolve => setTimeout(resolve, 500)); 495 loops += 1; 496 } 497 498 if (salespanelObjectLoaded()) { 499 // Set cookie. 500 allowTracking(); 501 salespanelResolve(true); 502 } else { 503 // Remove cookie. 504 rejectTracking(); 505 // Salespanel did not load in time or was rejected by consent. 506 salespanelReject("Salespanel error: Not loaded."); 507 } 508 }); 509 510 function salespanelObjectLoaded() { 511 return typeof $salespanel !== "undefined" && $salespanel.hasOwnProperty("push"); 512 } 513 514 function allowTracking() { 515 // Check if Salespanel tracking has already been allowed. 516 if ($.cookies.get("track_uid") !== null) { 517 return; 518 } 519 520 try { 521 // Activate tracking when the visitor provides explicit consent. 522 // Place `track_uid` cookie. 523 $salespanel.push(["set", "tracking:allowTracking"]); 524 } catch (e) { 525 salespanelReject("Salespanel error: Allow tracking failed."); 526 } 527 } 528 529 function rejectTracking() { 530 // Remove cookie if user removed Salespanel consent. 531 // All created Salespanel events will now be un-identified. 532 if ($.cookies.get("track_uid")) { 533 $.cookies.del("track_uid", {domain: '.rt-forum.se'}); 534 } 535 } 536 })(); 537 //]]> 538 </script>
538 539
539<script type="text/javascript"> 540 //<![CDATA[ 541 window.paywallScripts = { 542 seenPaywall: async function (type) { 543 // Wait for salespanel promise to be fulfilled (either loaded or not). 544 const salespanelLoaded = await window.salespanelPromise.catch(() => { 545 // Salespanel didn't load if promise is rejected. 546 return false; 547 }); 548 if (!salespanelLoaded) return; 549 550 // Find previous amount of seen paywalls. 551 await this.seenPaywallPromise().then(seenPaywalls => { 552 // Increment amount of seen paywall on visitor attribute. 553 this.setPaywallsAttribute(seenPaywalls); 554 555 // Create Meta/Facebook Pixel event notifying of a seen paywall. 556 if (seenPaywalls > 3) { 557 fbq('trackCustom', "Set paywall +3 gange"); 558 } 559 }).catch((message) => { 560 console.error(message); 561 }); 562 563 // Create Salespanel event notifying of a seen paywall. 564 this.sendPaywallEvent(type); 565 }, 566 seenPaywallPromise: function () { 567 return new Promise((resolve, reject) => { 568 try { 569 $salespanel.push(["get", "qualify:visitor", function (data) { 570 data.visitor_attributes.paywalls !== null ? 571 resolve(data.visitor_attributes.paywalls) : 572 resolve(0); 573 }]); 574 } catch (e) { 575 reject("Salespanel error: Get details failed."); 576 } 577 }); 578 }, 579 setPaywallsAttribute: function (seenPaywalls) { 580 try { 581 $salespanel.push(["set", "attributes:visitor", { 582 "paywalls": seenPaywalls + 1 583 }]); 584 } catch (e) { 585 console.error("Salespanel error: Couldn't set attribute."); 586 } 587 }, 588 sendPaywallEvent: function (type) { 589 try { 590 $salespanel.push(["set", 591 "activity:customActivity", 592 "website", 593 "Saw paywall", 594 type 595 ]); 596 } catch (e) { 597 console.error("Salespanel error: Couldn't send custom activity."); 598 } 599 } 600 } 601 //]]> 602 </script>
602 603
603<script type="text/javascript"> 604 (function (){ 605 var is = []; 606 var impersonating = false; 607 if (!impersonating && window.visitor.person && window.visitor.person.id) { 608 is.push({ 609 name: "person", 610 ref: window.visitor.person.id 611 }); 612 } 613 if (!impersonating && window.visitor.recipient && window.visitor.recipient.id) { 614 is.push({ 615 name: "recipient", 616 ref: window.visitor.recipient.id 617 }); 618 } 619 620 var evtr; 621 var queue = []; 622 window.queueTrackerEvent = function (a, sn, sr, tn, tr) { 623 if (evtr) { 624 evtr(a, sn, sr, tn, tr, is); 625 } else { 626 queue.push({ 627 a: a, 628 sn: sn, 629 sr: sr, 630 tn: tn, 631 tr: tr 632 }) 633 } 634 }; 635 window.addEventListener("onTrackerLoaded", function () { 636 evtr = window.createTracker("https://api.evtr.nordiskemedier.dk", "evtr"); 637 while (queue.length) { 638 var ev = queue.splice(0, 1)[0]; 639 if (ev) { 640 evtr(ev.a, ev.sn, ev.sr, ev.tn, ev.tr, is); 641 } 642 } 643 }); 644 })(); 645 </script>
645 646
646<script async="async" src="https://js.evtr.nordiskemedier.dk/_.js?t=1790253005902" type="text/javascript"></script>
646 647 648
648<script type="text/javascript"> 649 $(function() { 650 $('.item').hover( 651 function() { $(this).css('background-color', '#efefef').css('cursor', 'pointer') }, 652 function() { $(this).css('background-color', 'transparent').css('cursor', 'normal') } 653 ); 654 $(".tt").tooltip(); 655 }); 656 function getTitle() { 657 return document.title; 658 } 659 function getLocation() { 660 return window.location; 661 } 662 function getUrl() { 663 return window.location.href; 664 } 665 function confirmDelete(p) { 666 var v = "\u00C4r du s\u00E4ker p\u00E5 att du vill radera \"{0}\"?"; 667 v = v.replace("{0}", p); 668 return confirm(v); 669 } 670 function getVisitorEmail() { 671 return ""; 672 } 673 function getVisitorRememberInfo() { 674 return true; 675 } 676 677 var ids = []; 678 function messageFade() { 679 $('.fade').fadeTo('slow', 0.3); 680 } 681 682 // Remove cookies that are no longer in use 683 $(document).ready(function () { 684 $.cookies.del("c1"); 685 $.cookies.del("c2"); 686 $.cookies.del("c3"); 687 }); 688 689 window.pushGTrackScript = function (f, cont) { 690 window.pendingScriptExecutions.push({ 691 callback: function () { 692 if (window.googleAnalytics) { 693 eval(f(cont)); 694 } 695 }, 696 context: cont 697 }); 698 699 } 700 $(window).on('load', function () { 701 // if subscription is suspended change paywall message. 702 if ($('#paywall-overlay') && window.visitor?.person?.suspended) { 703 $('#paywall-overlay .paywall-package').html("\u00C5tkomsten \u00E4r avst\u00E4ngd."); 704 $('#paywall-overlay .paywall-body-wrapper').html("Av s\u00E4kerhetssk\u00E4l \u00E4r ditt konto tillf\u00E4lligt avst\u00E4ngt.".replace('{0}', "[email protected]").replace('{1}', "[email protected]")); 705 $('.paywall-content-wrapper').addClass('warning'); 706 } 707 }); 708 </script>
708 709
709<script type="text/javascript"> 710 //<![CDATA[ 711 function center(element) { 712 var e=$(element); 713 var w=e.width(); 714 var h=e.height(); 715 e.css("position","fixed").css("z-index","50000").css("top","50%").css("left","50%").css("margin-left","-"+(w/2)+"px").css("margin-top","-"+(h/2)+"px"); 716 e.draggable({ 717 handle: $(element+"_handle") 718 }); 719 } 720 //]]> 721 </script>
721 722 723 724 <link rel="alternate" type="application/rss+xml" title="News RSS" href="https://www.rt-forum.se/xml/rss2/articles" /> 725 <link rel="alternate" type="application/rss+xml" title="Advertisements RSS" href="https://www.rt-forum.se/xml/rss2/advertisements?typeId=1&typeId=2" /> 726 <link rel="alternate" type="application/rss+xml" title="Competences RSS" href="https://www.rt-forum.se/xml/rss2/competences" /> 727 <link rel="alternate" type="application/rss+xml" title="Jobs RSS" href="https://www.rt-forum.se/xml/rss2/jobs" /> 728 <link rel="alternate" type="application/rss+xml" title="Courses RSS" href="https://www.rt-forum.se/xml/rss2/courses" /> 729 730
730<script> 731 window.adTracker = { 732 slots: {}, 733 adsMeta: {}, 734 hoverState: { 735 currentSlotId: null, 736 lastChangeTs: 0 737 }, 738 clickState: { 739 lastPointerDown: null, // { slotId, ts } 740 clickHandled: false 741 } 742 }; 743 </script>
743<script async="async" src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"></script>
743<script>window.googletag = window.googletag || {cmd: []};if (!window.__gptGlobalsInit) { window.__gptGlobalsInit = true; window.slotFallbackData = new Map(); window.__inViewPct = window.__inViewPct || {}; window.__lastRefreshAt = new Map(); window.__slotCooldownMs = new Map(); function __canRefresh(slot){ const id = slot.getSlotElementId(); const last = window.__lastRefreshAt.get(id) || 0; const cd = window.__slotCooldownMs.get(id) || 30000; return Date.now() - last >= cd; } function __markRefreshed(slot){ window.__lastRefreshAt.set(slot.getSlotElementId(), Date.now()); } window.__refreshState = window.__refreshState || {}; function __getRefreshState(id){ return (window.__refreshState[id] = window.__refreshState[id] || { pending:false, nextAllowedTs:0 }); } function __tryRefresh(slot){ const id = slot.getSlotElementId(); const st = __getRefreshState(id); if (!st.pending) return; if (st.refreshScheduled) return; const now = Date.now(); const pct = (window.__inViewPct && window.__inViewPct[id]) || 0; if (now < st.nextAllowedTs){ __scheduleTryRefresh(slot, st.nextAllowedTs - now); return; } if (pct < 50){ __scheduleTryRefresh(slot, 3000); return; } if (!__canRefresh(slot)){ __scheduleTryRefresh(slot, 3000); return; } st.refreshScheduled = true; const ranInt = Math.floor(Math.random() * (2000 - 100 + 1)) + 100; setTimeout(function(){ googletag.pubads().refresh([slot]); __markRefreshed(slot); st.pending = false; st.refreshScheduled = false; }, ranInt); }function handleSlotRender(slotElementId) { var labelId = 'label-' + slotElementId; var labelEl = document.getElementById(labelId); if (!labelEl) { return; } labelEl.style.display = 'block';}function registerAdSlot(slotId) { const slotEl = document.getElementById(slotId); if (!slotEl) return; const wrapper = slotEl; wrapper.dataset.adSlotId = slotId; if (!wrapper.style.position) { wrapper.style.position = 'relative'; } window.adTracker = window.adTracker || {}; window.adTracker.slots = window.adTracker.slots || {}; window.adTracker.slotListeners = window.adTracker.slotListeners || {}; const existing = window.adTracker.slotListeners[slotId]; if (existing && existing.wrapper) { existing.wrapper.removeEventListener('mouseenter', existing.mouseenter); existing.wrapper.removeEventListener('mouseleave', existing.mouseleave); } const mouseenter = function () { window.adTracker.hoverState.currentSlotId = slotId; window.adTracker.hoverState.lastChangeTs = Date.now(); }; const mouseleave = function () { if (window.adTracker.hoverState.currentSlotId === slotId) { window.adTracker.hoverState.currentSlotId = null; window.adTracker.hoverState.lastChangeTs = Date.now(); } }; wrapper.addEventListener('mouseenter', mouseenter); wrapper.addEventListener('mouseleave', mouseleave); window.adTracker.slotListeners[slotId] = { wrapper: wrapper, mouseenter: mouseenter, mouseleave: mouseleave }; window.adTracker.slots[slotId] = wrapper;} function __scheduleTryRefresh(slot, delayMs){ const id = slot.getSlotElementId(); const st = __getRefreshState(id); if (st.tryTimer) clearTimeout(st.tryTimer); st.tryTimer = setTimeout(function(){ st.tryTimer = null; __tryRefresh(slot); }, Math.max(0, delayMs || 0)); } googletag.cmd.push(function(){ googletag.pubads().addEventListener('slotVisibilityChanged', function(e){ const slot = e.slot; const id = slot.getSlotElementId(); window.__inViewPct[id] = e.inViewPercentage || 0; __scheduleTryRefresh(slot, 250); }); googletag.pubads().addEventListener('impressionViewable', function(e){ const slot = e.slot; const id = slot.getSlotElementId(); const cd = window.__slotCooldownMs.get(id) || 30000; const st = __getRefreshState(id); st.pending = true; st.nextAllowedTs = Date.now() + cd; __scheduleTryRefresh(slot, cd); }); }); window.fireWindowResizeEvent = window.fireWindowResizeEvent || function(){ try { window.dispatchEvent(new Event('resize')); } catch(e){} };}googletag.cmd.push(function(){ window.__fallbackHandled = window.__fallbackHandled || new Set(); googletag.pubads().addEventListener('slotRenderEnded', function(event){ const adslotId = event.slot.getSlotElementId(); if (!event.isEmpty) { fireWindowResizeEvent(); handleSlotRender(adslotId); window.adTracker.adsMeta[adslotId] = { creativeId: event.creativeId, lineItemId: event.lineItemId, campaignId: event.campaignId, size: event.size, adUnitPath: event.slot.getAdUnitPath(), }; registerAdSlot(adslotId); return; } if (!window.slotFallbackData || !window.slotFallbackData.has(adslotId)) { fireWindowResizeEvent(); return; } if (window.__fallbackHandled.has(adslotId)) { fireWindowResizeEvent(); return; } window.__fallbackHandled.add(adslotId); const cfg = window.slotFallbackData.get(adslotId); try { googletag.destroySlots([event.slot]); } catch(e) {} requestAnimationFrame(function(){ const toArr = s => s.split('],').map(x=>JSON.parse(x.replace(/\s/g,'') + (x.endsWith(']')?'':']'))); const sizeArrayLarge = cfg.sizesLarge ? toArr(cfg.sizesLarge) : []; const sizeArraySmall = cfg.sizesSmall ? toArr(cfg.sizesSmall) : []; const sizeArrayMobile = cfg.sizesMobile ? toArr(cfg.sizesMobile) : []; var mapping = googletag.sizeMapping() .addSize([1588,0], sizeArrayLarge) .addSize([768,0], sizeArraySmall) .addSize([0,0], sizeArrayMobile).build(); var already = googletag.pubads().getSlots().some(s => s.getSlotElementId() === adslotId); if (!already) { var fb = googletag.defineSlot(cfg.fallbackAdUnitPath, cfg.sizes, adslotId) .defineSizeMapping(mapping) .addService(googletag.pubads()); if (cfg.refreshAdSlot === 'true') { window.__slotCooldownMs && window.__slotCooldownMs.set(adslotId, Number(cfg.refreshInterval)||30000); } else { window.__slotCooldownMs && window.__slotCooldownMs.set(adslotId, 1440000); } } setTimeout(function(){ try { googletag.display(adslotId); } catch(e) { console.warn('fallback display failed:', e); } fireWindowResizeEvent(); }, 0); }); });});googletag.cmd.push(function(){googletag.setConfig({singleRequest: true});googletag.setConfig({ collapseDiv: "ON_NO_FILL" }); googletag.enableServices();});</script>
743 744 745 746
746<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
746</head><body> 747
747<script src="/js/cookie-consent.js"></script>
747 748 749 <div style="display:none;"> 750 <a href="/void/index.html" rel="nofollow">23948sdkhjf</a> 751 </div> 752 <i id="media-width-detection" style="display: none"> 753 754 <i class="d-md-none xs"></i> 755 <i class="d-none d-md-inline lg"></i> 756 </i>
vendor: 93 bytes, lines 756-758
756 757 758 <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
758GTM-K3P2LSL
vendor: 91 bytes, lines 758-759
758" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> 759
759<div class="remodal-bg"> 760 <header id="main-header" v-cloak="" class="unprintable"> 761 <nav> 762 <div> 763 <global-search-icon></global-search-icon> 764 </div> 765 <div> 766 <a href="/" class="logo"> 767 <img src="https://f.nordiskemedier.dk/logo/portal/54.png" alt="RT-Forum" /> 768 </a> 769 </div> 770 <div> 771 <button v-if="window.visitor.person" v-on:click.prevent="open(personMenu)" class="btn btn-link btn-log-in px-0" style="position: relative;"> 772 <i class="fa-light fa-user d-sm-none"></i> 773 <span class="d-none d-sm-inline">Mitt konto</span> 774 <span class="badge bg-danger rounded-pill translate-middle notification-badge notification-badge--account" v-if="unreadNotifications > 0 && 10 > unreadNotifications">{{ unreadNotifications }}</span> 775 <span class="badge bg-danger rounded-pill translate-middle notification-badge notification-badge--account" v-else-if="unreadNotifications > 0 && unreadNotifications >= 10"> 9+ </span> 776 </button> 777 <button v-else="" v-on:click.prevent="open(topMenu)" class="btn btn-link btn-log-in px-0"> 778 <i class="fa-light fa-user d-sm-none"></i> 779 <span class="d-none d-sm-inline">Logga in</span> 780 </button> 781 <button v-if="(window.visitor.ipAccess && !window.visitor.ipAccess.disable && window.visitor.ipAccess.corporateClient) || (window.visitor.person && window.visitor.corporateClient)" v-on:click.prevent="open(ipAccessMenu)" class="btn btn-link btn-ip-access px-0"> 782 <span class="d-flex" v-if="window.visitor.corporateClient && window.visitor.person && window.visitor.person.companiesWhereAdmin && window.visitor.person.companiesWhereAdmin.length == 1"> 783 <i class="fa-light fa-lock-open me-1"></i><span class="short-name">{{ truncateString(window.visitor.corporateClient.name, 12) }}</span><span class="long-name">{{ truncateString(window.visitor.corporateClient.name, 20) }}</span> 784 </span> 785 <span class="d-flex" v-else-if="window.visitor.corporateClient && window.visitor.person && window.visitor.person.companiesWhereAdmin && window.visitor.person.companiesWhereAdmin.length > 1"> 786 <i class="fa-light fa-lock-open me-1"></i><span class="short-name">{{ truncateString("Företagslösning", 12) }}</span><span class="long-name">{{ truncateString("Företagslösning", 20) }}</span> 787 </span> 788 <span class="d-flex" v-else-if="window.visitor.ipAccess && !window.visitor.ipAccess.disable && window.visitor.ipAccess.corporateClient"> 789 <i class="fa-light fa-lock-open me-1"></i><span class="short-name">{{ truncateString(window.visitor.ipAccess.corporateClient.name, 12) }}</span><span class="long-name">{{ truncateString(window.visitor.ipAccess.corporateClient.name, 20) }}</span> 790 </span> 791 <span class="d-flex" v-else=""> 792 <i class="fa-light fa-lock-open me-1"></i><span class="short-name">{{ truncateString(window.visitor.corporateClient.name, 12) }}</span><span class="long-name">{{ truncateString(window.visitor.corporateClient.name, 20) }}</span> 793 </span> 794 </button> 795 <template v-else=""><a id="j_idt109:j_idt111" href="/products/subscription.html" style="" class="btn btn-primary" target=""> 796 <span class="d-inline d-sm-none">Köp</span> 797 <span class="d-none d-sm-inline">Köp åtkomst</span></a> 798 </template> 799 <button v-on:click.prevent="open(rightMenu)" class="btn btn-link btn-bars px-0 d-inline-flex"> 800 <i class="fa-light fa-bars-staggered"></i> 801 </button> 802 </div> 803 </nav> 804 <div v-on:click.self="close" class="menu-container menu-top" v-bind:class="getStyleClass(topMenu)"> 805 <div>
806 <menu-log-in v-bind:sign-up-link="signUpLink" v-on:close="close"></menu-log-in> 807 </div> 808 </div> 809 <div v-on:click.self="close" class="menu-container menu-right" v-bind:class="getStyleClass(rightMenu)"> 810 <div> 811 <div style="align-items: center;" class="d-flex justify-content-end"> 812 <button v-if="window.visitor.person" v-on:click.prevent="open(personMenu)" class="btn btn-link btn-log-in px-0"> 813 Mitt konto 814 </button> 815 <button v-else="" v-on:click.prevent="open(topMenu)" class="btn btn-link btn-log-in px-0"> 816 <i class="fa-light fa-user d-sm-none"></i> 817 <span class="d-none d-sm-inline">Logga in</span> 818 </button> 819 <button v-if="(window.visitor.ipAccess && !window.visitor.ipAccess.disable && window.visitor.ipAccess.corporateClient) || (window.visitor.person && window.visitor.corporateClient)" v-on:click.prevent="open(ipAccessMenu)" class="btn btn-link btn-ip-access px-0 mx-4"> 820 <span class="d-flex" v-if="window.visitor.corporateClient && window.visitor.person && window.visitor.person.companiesWhereAdmin && window.visitor.person.companiesWhereAdmin.length == 1"> 821 <i class="fa-light fa-lock-open me-1"></i><span class="short-name">{{ truncateString(window.visitor.corporateClient.name, 12) }}</span><span class="long-name">{{ truncateString(window.visitor.corporateClient.name, 20) }}</span> 822 </span> 823 <span class="d-flex" v-else-if="window.visitor.corporateClient && window.visitor.person && window.visitor.person.companiesWhereAdmin && window.visitor.person.companiesWhereAdmin.length > 1"> 824 <i class="fa-light fa-lock-open me-1"></i><span class="short-name">{{ truncateString("Företagslösning", 12) }}</span><span class="long-name">{{ truncateString("Företagslösning", 20) }}</span> 825 </span> 826 <span class="d-flex" v-else-if="window.visitor.ipAccess && !window.visitor.ipAccess.disable && window.visitor.ipAccess.corporateClient"> 827 <i class="fa-light fa-lock-open me-1"></i><span class="short-name">{{ truncateString(window.visitor.ipAccess.corporateClient.name, 12) }}</span><span class="long-name">{{ truncateString(window.visitor.ipAccess.corporateClient.name, 20) }}</span> 828 </span> 829 <span class="d-flex" v-else=""> 830 <i class="fa-light fa-lock-open me-1"></i><span class="short-name">{{ truncateString(window.visitor.corporateClient.name, 12) }}</span><span class="long-name">{{ truncateString(window.visitor.corporateClient.name, 20) }}</span> 831 </span> 832 </button> 833 <template v-else=""><a id="j_idt113:j_idt115" href="/products/subscription.html" style="" class="btn btn-primary mx-4" target=""> 834 <span class="d-inline d-sm-none">Köp</span> 835 <span class="d-none d-sm-inline">Köp åtkomst</span></a> 836 </template> 837 <button v-on:click.prevent="close" class="btn btn-link btn-x px-0 d-inline-flex"> 838 <i class="fa-light fa-xmark-large"></i> 839 </button> 840 </div> 841 <div class="mt-5 mb-4"> 842 <global-search-input></global-search-input> 843 </div> 844 <ul class="primary-menu"> 845 <li v-for="(option, i) in mainOptions" v-bind:key="i" v-bind:class="{'open': unfolded == i}"> 846 <a v-if="option.target" v-bind:href="option.target" v-bind:target="option.external ? '_blank' : ''">{{ option.name }}</a> 847 <template v-else-if="option.children"> 848 <a href="#" v-on:click.prevent="unfolded = unfolded != i ? i : null">{{ option.name }}<i class="fa-light" v-bind:class="{'fa-chevron-down': unfolded != i, 'fa-chevron-up': unfolded == i}"></i></a> 849 <ul> 850 <li v-for="(child, j) in option.children" v-bind:key="j"> 851 <a v-bind:href="child.target" v-bind:target="child.external ? '_blank' : ''">{{ child.name }}</a> 852 </li> 853 </ul> 854 </template> 855 </li> 856 </ul> 857 <ul class="secondary-menu"> 858 <li> 859 <a href="/epages/archive.html"> 860 <i class="fa-light fa-newspaper"></i>E-tidning 861 </a> 862 </li> 863 <li> 864 <a href="/newsletter/subscribe.html"><i class="fa-light fa-envelope"></i>Registrera nyhetsbrev</a> 865 </li> 866 <li> 867 <a href="/bookmark"><i class="fa-light fa-bookmark"></i>Min läslista</a> 868 </li> 869 </ul> 870 <ul v-if="mainSecondaryOptions && mainSecondaryOptions.length" class="secondary-menu"> 871 <li v-for="(option, i) in mainSecondaryOptions" v-bind:key="i"> 872 <a v-if="option.target" v-bind:href="option.target" v-bind:target="option.external ? '_blank' : ''">{{ option.name }}</a> 873 <template v-else-if="option.children">
874 <span>{{ option.name }}</span> 875 <ul> 876 <li v-for="(child, j) in option.children" v-bind:key="j"> 877 <a v-bind:href="child.target" v-bind:target="child.external ? '_blank' : ''">{{ child.name }}</a> 878 </li> 879 </ul> 880 </template> 881 </li> 882 </ul> 883 <div class="extra"> 884 <ip-access-toggle></ip-access-toggle> 885 </div> 886 </div> 887 </div> 888 <div v-if="window.visitor.person" v-on:click.self="close" class="menu-container menu-right" v-bind:class="getStyleClass(personMenu)"> 889 <div> 890 <div class="d-flex"> 891 <div class="d-flex w-50 align-items-center"> 892 </div> 893 894 <div style="align-items: center;" class="d-flex justify-content-end w-50"> 895 <button v-on:click.prevent="close" class="btn btn-link btn-x px-0 d-inline-flex"> 896 <i class="fa-light fa-xmark-large"></i> 897 </button> 898 </div> 899 </div> 900 <ul class="primary-menu mt-4"> 901 <li v-bind:class="{'open': unfolded == -1}"> 902 <a href="#" v-on:click.prevent="unfolded = unfolded != -1 ? -1 : null" class="border-top-0"> 903 <span class="d-block"> 904 <span class="d-block">{{ window.visitor.person.name }}</span> 905 <small v-if="window.visitor.member" class="d-block text-muted"> 906 <span class="me-2">{{ window.visitor.member.name }}</span> 907 <span v-if="window.visitor.person.members && window.visitor.person.members.length > 1" class="border rounded px-1">+{{ window.visitor.person.members.length - 1 }}</span> 908 </small> 909 </span> 910 <i class="fa-light" v-bind:class="{'fa-chevron-down': unfolded != -1, 'fa-chevron-up': unfolded == -1}"></i> 911 </a> 912 <ul> 913 <li v-if="window.visitor.person.members && window.visitor.person.members.length > 1" v-for="member in window.visitor.person.members"> 914 <a href="#" v-on:click="switchMember(member.id)"> 915 {{ member.name }} 916 <small class="d-block text-muted">Företagsprofil<i v-if="window.visitor.member && member.id === window.visitor.member.id" class="text-success ms-2 fa-solid fa-check-circle"></i></small> 917 </a> 918 </li> 919 <li> 920 <a href="/user/update.html">Inställningar</a> 921 </li> 922 <li> 923 <a href="/member/log-out.html">Logga ut</a> 924 </li> 925 </ul> 926 </li> 927 <li v-for="(option, i) in personOptions" v-bind:key="i" v-bind:class="{'open': unfolded == i}"> 928 <a v-if="option.target" v-bind:href="option.target" v-bind:target="option.external ? '_blank' : ''">{{ option.name }}</a> 929 <template v-else-if="option.children"> 930 <a href="#" v-on:click.prevent="unfolded = unfolded != i ? i : null">{{ option.name }}<i class="fa-light" v-bind:class="{'fa-chevron-down': unfolded != i, 'fa-chevron-up': unfolded == i}"></i></a> 931 <ul> 932 <li v-for="(child, j) in option.children" v-bind:key="j"> 933 <a v-bind:href="child.target" v-bind:target="child.external ? '_blank' : ''">{{ child.name }}</a> 934 </li> 935 </ul> 936 </template> 937 </li> 938 </ul> 939 <ul class="secondary-menu"> 940 <li> 941 <a href="/epages/archive.html"> 942 <i class="fa-light fa-newspaper"></i>E-tidning 943 </a> 944 </li> 945 <li> 946 <a href="/newsletter/subscribe.html"><i class="fa-light fa-envelope"></i>Registrera nyhetsbrev</a> 947 </li> 948 <li> 949 <a href="/bookmark"><i class="fa-light fa-bookmark"></i>Min läslista</a> 950 </li> 951 </ul> 952 <ul v-if="mainSecondaryOptions && mainSecondaryOptions.length" class="secondary-menu"> 953 <li v-for="(option, i) in mainSecondaryOptions" v-bind:key="i"> 954 <a v-if="option.target" v-bind:href="option.target" v-bind:target="option.external ? '_blank' : ''">{{ option.name }}</a> 955 <template v-else-if="option.children">
956 <span>{{ option.name }}</span> 957 <ul> 958 <li v-for="(child, j) in option.children" v-bind:key="j"> 959 <a v-bind:href="child.target" v-bind:target="child.external ? '_blank' : ''">{{ child.name }}</a> 960 </li> 961 </ul> 962 </template> 963 </li> 964 </ul> 965 <div class="extra"> 966 <ip-access-toggle></ip-access-toggle> 967 </div> 968 </div> 969 </div> 970 <div v-if="(window.visitor.ipAccess && !window.visitor.ipAccess.disable && window.visitor.ipAccess.corporateClient) || (window.visitor.person && window.visitor.corporateClient)" v-on:click.self="close" class="menu-container menu-right" v-bind:class="getStyleClass(ipAccessMenu)"> 971 <div> 972 <div style="align-items: center;" class="d-flex justify-content-end"> 973 <button v-on:click.prevent="close" class="btn btn-link btn-x px-0 d-inline-flex"> 974 <i class="fa-light fa-xmark-large"></i> 975 </button> 976 </div> 977 <ul class="ip-menu"> 978 <li> 979 <h5 v-if="window.visitor.corporateClient && window.visitor.person && window.visitor.person.companiesWhereAdmin && window.visitor.person.companiesWhereAdmin.length == 1" class="m-0">{{ window.visitor.corporateClient.name }}</h5> 980 <h5 v-else-if="window.visitor.corporateClient && window.visitor.person && window.visitor.person.companiesWhereAdmin && window.visitor.person.companiesWhereAdmin.length > 1" class="m-0">Företagslösning</h5> 981 <h5 v-else-if="window.visitor.ipAccess && !window.visitor.ipAccess.disable && window.visitor.ipAccess.corporateClient" class="m-0">{{ window.visitor.ipAccess.corporateClient.name }}</h5> 982 <h5 v-else="" class="m-0">{{ window.visitor.corporateClient.name }}</h5> 983 </li> 984 <li v-if="window.visitor.corporateClient && window.visitor.person && window.visitor.person.companiesWhereAdmin && window.visitor.person.companiesWhereAdmin.length >= 1"><p><b>Välkommen till vår företagslösning</b></p> 985<p>Här kan du administrera användarna i din företagslösning.</p> 986 </li> 987 <li v-else-if="window.visitor.corporateClient && window.visitor.person && window.visitor.corporateClient && !window.visitor.ipAccess">Välkommen till din prenumeration för RT-Forum. 988 </li> 989 <li v-else=""><p><b>Welcome to our Corporate client solution</b></p> 990<p>Your IP is registered with the company mentioned above and provides access to RT-Forum.</p> 991 </li> 992 <template v-if="window.visitor.person && window.visitor.person.companiesWhereAdmin && window.visitor.person.companiesWhereAdmin.length >= 1"> 993 <li v-for="company in window.visitor.person.companiesWhereAdmin" class="subscription-menu-company-link"> 994 <a v-bind:href="company.link"> 995 <span class="d-block"> 996 <span class="d-block"> 997 Hantera företagsprenumeration 998 </span> 999 <small v-if="window.visitor.person.companiesWhereAdmin.length >= 1" class="d-block text-muted">{{company.name}}</small> 1000 </span> 1001 </a> 1002 </li> 1003 </template> 1004 <li v-if="window.visitor.ipAccess && window.visitor.ipAccess.corporateClient && window.visitor.ipAccess.corporateClient.type != 3 && window.visitor.ipAccess.corporateClient.type != 2 && !window.visitor.person"> 1005 <a v-bind:href="'/corporate-client/index.html?token='+window.visitor.ipAccess.corporateClient.token" class="btn btn-link p-0"> 1006 Click here to go to sign-up<i class="fa-light fa-arrow-right ms-2"></i> 1007 </a> 1008 </li> 1009 </ul> 1010 <div class="extra"> 1011 <ip-access-toggle></ip-access-toggle> 1012 </div> 1013 </div> 1014 </div> 1015 </header> 1016
1016<script type="application/javascript"> 1017 //<![CDATA[ 1018 window.mainMenu = new Vue({ 1019 el: "#main-header", 1020 data: { 1021 topMenu: { 1022 transitioning: false, 1023 open: false 1024 }, 1025 rightMenu: { 1026 transitioning: false, 1027 open: false 1028 }, 1029 personMenu: { 1030 transitioning: false, 1031 open: false 1032 }, 1033 ipAccessMenu: { 1034 transitioning: false, 1035 open: false 1036 }, 1037 notificationsMenu: { 1038 transitioning: false, 1039 open: false 1040 }, 1041 personNotifications: [], 1042 unreadNotifications: 0, 1043 hasMore: true, 1044 stack: [], 1045 unfolded: null, 1046 mainOptions: [{"children":[{"external":false,"name":"Senaste nytt","target":"/article/latest.html"},{"name":"Bokslut","target":"/topic/view/1263/bokslut"},{"name":"Bussförar-SM","target":"/topic/view/1128/bussforarsm"},{"name":"Infrastruktur","target":"/topic/view/1159/infrastruktur"},{"name":"Kartläggning","target":"/topic/view/1177/kartlaggning"},{"name":"Kvartalsrapport ","target":"/topic/view/1079/kvartalsrapport"},{"name":"Tunga Bussligan","target":"/topic/view/1126/tunga_bussligan"},{"name":"Upphandling & avtal","target":"/topic/view/686/upphandling_avtal"}],"name":"Nyheter"},{"children":[{"external":false,"name":"Företagsnyheter","target":"/announcement"},{"external":false,"name":"Medlemsföretag","target":"/company"}],"name":"Branschinsikt"},{"children":[{"external":false,"name":"Maskiner","target":"/machine"},{"external":false,"name":"Produkter","target":"/product"},{"external":false,"name":"Tjänster","target":"/competence"}],"name":"Köp & Sälj"},{"external":false,"name":"Kalender","target":"/event/search"},{"external":false,"name":"Jobb","target":"/job"}], 1047 mainSecondaryOptions: [{"children":[{"external":false,"name":"Bli prenumerant","target":"/products/subscription.html"}
1047,{"external":true,"name":"Bli medlem","target":"https://nordiskemediehus.dk/se/produkt/medlemskab/"},{"external":true,"name":"Annonsera","target":"https://nordiskemediehus.dk/se/rt-forum/"},{"external":true,"name":"Se alla produkter","target":"https://nordiskemediehus.dk/se/produkter/"}],"name":"Produkter"}], 1048 createSubscriptionLink: {"external":false,"name":"Bli prenumerant","target":"/products/subscription.html"}, 1049 createMembershipLink: {"external":true,"name":"Bli medlem","target":"https://nordiskemediehus.dk/se/produkt/medlemskab/"}, 1050 }, 1051 computed: { 1052 personOptions: function () { 1053 const options = []; 1054 1055 const add = (list, name, target) => { 1056 const option = { 1057 name 1058 }; 1059 if (target) { 1060 option.target = target; 1061 } else { 1062 option.children = []; 1063 } 1064 list.push(option); 1065 return option.children; 1066 } 1067 1068 if (!window.visitor.member) { 1069 add(options, "Market overview", "/watch"); 1070 } else { 1071 add(options, "Aktiviteter", "/member"); 1072 1073 if (window.visitor.member.state.type.announcements || window.visitor.member.state.type.posts) { 1074 const createItems = add(options, "Skapa ett inlägg"); 1075 if (window.visitor.member.state.type.announcements) { 1076 add(createItems, "Nyhet", "/post/announcement"); 1077 } 1078 if (window.visitor.member.state.type.posts) { 1079 if (true) { 1080 add(createItems, "Maskin eller produkt", "/post/machine-or-product"); 1081 } 1082 if (true) { 1083 add(createItems, "Tj\u00E4nst", "/post/competence"); 1084 } 1085 if (true) { 1086 add(createItems, "Jobb", "/post/job"); 1087 } 1088 if (false) { 1089 add(createItems, "Kurs", "/post/course"); 1090 } 1091 } 1092 1093 if (window.visitor.member.state.type.posts && true && (true)) { 1094 const crawlingItems = add(options, "Importlagring"); 1095 add(crawlingItems, "Import overview", "/post/overview?imported=true"); 1096 add(crawlingItems, "Crawling status", "/import/status.html"); 1097 } 1098 1099 add(options, "Sammanst\u00E4llning", "/post/overview"); 1100 } 1101 // if (window.visitor.member.misc.banners || window.visitor.member.misc.newsletterBanners) { 1102 // const bannerItems = add(options, "Annonsering"); 1103 // if (window.visitor.member.misc.banners) { 1104 // add(bannerItems, "\u00D6versikt", "/banner/index.html"); 1105 // } 1106 // if (window.visitor.member.misc.newsletterBanners) { 1107 // add(bannerItems, "Annonsering i nyhetsbrevet", "/newsletter/banner/index.html"); 1108 // } 1109 // // Member-specifik kode... virker ikke med cache 1110 // // const saleEmail = "N\/A"; 1111 // // if (saleEmail.indexOf("@") != -1) { 1112 // // add(bannerItems, "Kontakta oss f\u00F6r ett kostnadsf\u00F6rslag", "mailto:" + saleEmail + "?subject=N\u00E4r det g\u00E4ller annonsering"); 1113 // // } 1114 // } 1115 1116 if (false) { 1117 add(options, "Market overview", "/watch"); 1118 } 1119 1120 const profileItems = add(options, "F\u00F6retagsprofil"); 1121 add(profileItems, "Se profilen", "/company/view/" + window.visitor.member.id + "/" + window.visitor.member.slug); 1122 if (window.visitor.member.state.type.profile) { 1123 add(profileItems, "Redigera profil", "/company/profile.html"); 1124 } 1125 add(profileItems, "Kontakter", "/member-contact/overview"); 1126 if (window.visitor.member.state.type.supplements) { 1127 add(profileItems, "F\u00F6retagsportf\u00F6lj", "/supplement/management"); 1128 } 1129 add(profileItems, "Inst\u00E4llningar f\u00F6r administrat\u00F6rer", "/company/administrators.html"); 1130 1131 add(options, "Hj\u00E4lp", "/member/help.html"); 1132 } 1133 1134 return options; 1135 // var addContacts = function (items, text, contacts) { 1136 // if (contacts) { 1137 // var contactItems = []; 1138 // for (var i = 0; i < contacts.length; i++) { 1139 // var contact = contacts[i]; 1140 // contactItems.push({ 1141 // text: contact.name, 1142 // portrait: contact.portrait, 1143 // phonePrefix: "Tel: ", 1144 // phone: contact.phone, 1145 // email: contact.email 1146 // }); 1147 // } 1148 // items.push({ 1149 // text: text, 1150 // items: contactItems, 1151 // }); 1152 // } 1153 // }; 1154 // 1155 // var contactItems = []; 1156 // for (var contact in this.visitor.contacts) { 1157 // addContacts(contactItems, this.visitor.contacts[contact].title, this.visitor.contacts[contact].contacts); 1158 // } 1159 // 1160 // items.push({ 1161 // icon: "fa-light fa-phone-alt", 1162 // text: "Kontakt", 1163 // href: "#", 1164 // items: contactItems, 1165 // }); 1166 // 1167 // return { 1168 // items: items 1169 // }; 1170 // } 1171 }, 1172 signUpLink: function () { 1173 if (window.access.module.subscriptions && this.createSubscriptionLink) { 1174 this.createSubscriptionLink.name = "Prenumerera"; 1175 return this.createSubscriptionLink; 1176 } else if (this.createMembershipLink) { 1177 this.createMembershipLink.name = "Bli medlem"; 1178 return this.createMembershipLink; 1179 } else { 1180 return null; 1181 } 1182 } 1183 }, 1184 watch: { 1185 stack: function (newValue) { 1186 if (newValue && newValue.length > 0) { 1187 document.body.classList.add("menu-open"); 1188 } else { 1189 document.body.classList.remove("menu-open"); 1190 } 1191 } 1192 }, 1193 mounted: function () { 1194 document.addEventListener("keyup", this.keyupListener); 1195 }, 1196 unmounted: function () { 1197 window.removeEventListener("keyup", this.keyupListener); 1198 }, 1199 created: function () { 1200 this.loadUnreadNotificationCount(); 1201 }, 1202 updated: function () { 1203 if(this.notificationsMenu.open) { 1204 this.$nextTick(() => { 1205 this.markNotificationsSeen(); 1206 }); 1207 } 1208 }, 1209 methods: { 1210 truncateString(str, maxLength) { 1211 if (!str || typeof str !== 'string') return ''; 1212 const ellipsis = 'â¦'; 1213 1214 if (str.length > maxLength) { 1215 let trimmed = str.slice(0, maxLength); 1216 trimmed = trimmed.replace(/\s+$/, ''); 1217 if ((trimmed + ellipsis).length < str.length) { 1218 return trimmed + ellipsis; 1219 } 1220 } 1221 1222 return str; 1223 }, 1224 keyupListener: function (event) { 1225 if (event.keyCode == 27) { 1226 this.close(); 1227 } 1228 }, 1229 open: function (menu) { 1230 this.stack.push(menu); 1231 menu.transitioning = true; 1232 this.$nextTick(() => { 1233 menu.open = true; 1234 }) 1235 }, 1236 openNotificationsMenu: function () { 1237 if(false) { 1238 this.open(this.notificationsMenu); 1239 this.loadNotifications(); 1240 } 1241 }, 1242 close: function () { 1243 const menu = this.stack.length ? this.stack.splice(this.stack.length - 1, 1)[0] : null; 1244 if (menu) { 1245 menu.open = false;
1246 setTimeout(() => { 1247 menu.transitioning = false; 1248 }, 250) 1249 } 1250 }, 1251 closeNotificationsMenu: function () { 1252 this.$nextTick(() => { 1253 this.loadUnreadNotificationCount(); 1254 }); 1255 this.close(this.notificationsMenu); 1256 }, 1257 getStyleClass: function (menu) { 1258 return { 1259 "transitioning": menu.transitioning || menu.open, 1260 "open": menu.open 1261 }; 1262 }, 1263 switchMember: function (memberId) { 1264 this.$services.personSecureService.switchMember(memberId) 1265 .then(() => window.location.reload()) 1266 .catch(err => console.error(err)); 1267 }, 1268 openLogIn: function () { 1269 Vue.$hashUtil.remove("paywall"); 1270 this.open(this.topMenu); 1271 }, 1272 loadNotifications: function () { 1273 if (window.visitor.person && false) { 1274 this.$services.notificationSecureService.loadByPerson() 1275 .then(data => { 1276 this.personNotifications = data; 1277 }).catch(err => { 1278 console.error(err); 1279 }); 1280 } 1281 }, 1282 loadUnreadNotificationCount: function () { 1283 if (window.visitor.person && false) { 1284 this.$services.notificationSecureService.loadUnreadCount() 1285 .then(data => { 1286 this.unreadNotifications = data; 1287 }).catch(err => { 1288 console.error(err); 1289 }); 1290 } 1291 }, 1292 async markNotificationsSeen() { 1293 if (this.personNotifications.length > 0) { 1294 const personNotificationIds = this.personNotifications 1295 .filter(n => !n.seen) 1296 .map(n => n.id); 1297 if (personNotificationIds.length > 0) { 1298 this.$services.notificationSecureService.seen(personNotificationIds); 1299 } 1300 } 1301 }, 1302 async handleClick(personNotification) { 1303 this.$services.notificationSecureService.clicked(personNotification.id); 1304 window.location.href = personNotification.notification.link; 1305 }, 1306 async loadMore() { 1307 min = Math.max(this.personNotifications.length, 0); 1308 this.loadNotifications(min, 15); 1309 }, 1310 timeAgo(dateString) { 1311 const created = new Date(dateString); 1312 const now = new Date(); 1313 1314 const seconds = Math.floor((now - created) / 1000); 1315 1316 if (seconds < 60) return seconds + ' sekunder sedan'; 1317 1318 const minutes = Math.floor(seconds / 60); 1319 if (minutes < 60) return minutes + ' minuter sedan'; 1320 1321 const hours = Math.floor(minutes / 60); 1322 if (hours < 60) return hours + ' timmar sedan'; 1323 1324 const days = Math.floor(hours / 24); 1325 if (days < 7) return days + ' dagar sedan'; 1326 1327 const dd = ("0" + created.getDate()).slice(0-2); 1328 const mm = ("0" + (created.getMonth() + 1)).slice(0-2); 1329 const yyyy = created.getFullYear(); 1330 return dd + "-" + mm + "-" + yyyy; 1331 } 1332 } 1333 }); 1334 //]]> 1335 </script>
1335 1336 <header id="extra-header" class="unprintable"> 1337 <nav></nav> 1338 <nav> 1339 <featured-links v-bind:value="featuredOptions"></featured-links> 1340 </nav> 1341 </header> 1342
1342<script type="application/javascript"> 1343 //<![CDATA[ 1344 new Vue({ 1345 el: "#extra-header", 1346 data: { 1347 featuredOptions: [{"external":false,"name":"Nyheter","target":"/"},{"external":false,"name":"Resforum","target":"/topic/view/693/resforum"},{"external":false,"name":"Företagsnyheter","target":"/announcement"},{"external":false,"name":"Medlemsföretag","target":"/company"},{"external":false,"name":"Annonsera","target":"/page/view.html?id=18020"},{"external":false,"name":"Jobb","target":"/job"}], 1348 articles: [] 1349 } 1350 }); 1351 //]]> 1352 </script>
1352 1353 <hash-modal id="paywall-modal" v-cloak="" v-on:opened="opened" hash="paywall" class="paywall paywall-modal "> 1354 <div class="paywall-message">Logga in eller skapa en prenumeration för att spara artiklar 1355 </div> 1356 <div class="paywall-body-wrapper"> 1357 <div class="paywall-gain"> 1358 FÃ¥ tillgÃ¥ng till allt innehÃ¥ll pÃ¥ RT-Forum 1359 </div> 1360 <div class="paywall-binding"> 1361 Ingen bindningstid eller kortinformation krävs 1362 </div> 1363 <div class="paywall-action"><a id="j_idt145:j_idt147:j_idt158:j_idt162" href="/products/subscription.html?product=105&campaign_code=paywall" style="" class="btn btn-primary" target=""> 1364 Prova RT-Forum nu 1365 </a> 1366 </div> 1367 <div class="paywall-log-in"> 1368 Redan prenumerant? <a href="#" v-on:click.prevent="window.mainMenu.openLogIn()">Logga in</a> 1369 </div> 1370 <div class="paywall-conditions"> 1371 <div> 1372 Gäller endast personlig prenumeration. 1373 </div> 1374 <div>Kontakta oss för en <a id="j_idt145:j_idt147:j_idt166:0:j_idt168" href="/products/subscription.html?product=109&campaign_code=paywall">företagslösning</a>. 1375 </div> 1376 </div> 1377 </div> 1378 </hash-modal> 1379
1379<script type="text/javascript"> 1380 //<![CDATA[ 1381 new Vue({ 1382 el: "#paywall-modal", 1383 methods: { 1384 opened: function () { 1385 window.paywallScripts.seenPaywall("unknown"); 1386 } 1387 } 1388 }); 1389 //]]> 1390 </script>
1390 1391 1392 <div class="super-container"> 1393 <div class="main-container"> 1394 <div> 1395 </div> 1396 <main> 1397 <div> 1398 1399 <div class="row news-subs"> 1400 <div class="col-sm-5"> 1401 <div id="newsletter-box" class="newsletter-box"> 1402 <h1>Anmäl dig till vårt nyhetsbrev</h1> 1403 <form> 1404 <div class="form-group"> 1405 <input type="text" name="name" required="required" class="form-control" placeholder="Ditt namn" /> 1406 </div> 1407 <div class="form-group"> 1408 <input type="text" name="email" required="required" class="form-control" placeholder="Din e-post" /> 1409 </div> 1410 1411 1412 <div class="form-group"> 1413 <div class="form-check form-check-xs"> 1414 <input id="dailySignup" name="dailySignup" class="form-check-input" type="checkbox" /> 1415 <label for="dailySignup" class="form-check-label">Ja tack, jag vill gärna få RT-Forums nyhetsbrev <a href="/privacy">Läs cookie- och datapolicy.</a> 1416 </label> 1417 </div> 1418 </div> 1419 <div class="form-group"> 1420 <div class="form-check form-check-xs"> 1421 <input id="acceptMarketing" name="acceptMarketing" class="form-check-input" type="checkbox" /> 1422 <label for="acceptMarketing" class="form-check-label">Ja tack, jag vill gärna ta emot marknadsföring, erbjudanden, undersökningar m.m. från RT-Forum. <a href="/privacy" target="_blank">Läs cookie- och datapolicy.</a> 1423 </label> 1424 </div> 1425 </div> 1426 <div class="form-group"> 1427 <h5 class="mb-2">Nyhetsbrev 1428 </h5> 1429 <div class="mb-2"> 1430 <div class="form-check form-check-sm"> 1431 <input id="newsletter204" name="mailingLists" type="checkbox" data-type="array" value="204" class="form-check-input" /> 1432 <label for="newsletter204" class="form-check-label"> 1433 RT-Forum Breaking/Extra 1434 </label> 1435 </div> 1436 </div> 1437 <div class="mb-2"> 1438 <div class="form-check form-check-sm"> 1439 <input id="newsletter207" name="mailingLists" type="checkbox" data-type="array" value="207" class="form-check-input" /> 1440 <label for="newsletter207" class="form-check-label"> 1441 RT-Forum Eventnyheter 1442 </label> 1443 </div> 1444 </div> 1445 </div> 1446 1447 <div class="form-buttons"> 1448 <input type="submit" value="Registrera nyhetsbrev" class="btn btn-light" /> 1449 </div> 1450 1451 <div class="mt-5"> 1452 <p>
1452Nyhetsbrevet skickas ut tre gånger i veckan (måndag, tisdag och torsdag). 1453 </p> 1454 <p><a id="j_idt211" href="/newsletter">Se det senaste nyhetsbrevet.</a> 1455 </p> 1456 </div> 1457 </form> 1458
1458<script type="text/javascript"> 1459 //<![CDATA[ 1460 $("#newsletter-box").mailingListForm({ 1461 container: $("#newsletter-box form"), 1462 source: 'standalone' 1463 }); 1464 //]]> 1465 </script>
1465 1466 </div> 1467 </div> 1468 <div class="col-sm-6"> 1469 <h1>Prenumerera pÃ¥ RT-Forums nyhetsbrev! 1470 </h1> 1471 <p>Anmäl dig till vårt nyhetsbrev och följ med i allt som händer i kollektivtrafik- och beställningstrafikbranschen! <br/><br/>Få den skarpaste branschanalysen och de senaste nyheterna levererade direkt till din inkorg. Håll dig uppdaterad med de viktigaste nyheterna inom all slags persontrafik utom flyg. RT-Forum synar allt från lokal och regional kollektivtrafik till långväga trafik med både buss, tåg och taxi samt bussturism. Hela Sverige bevakas och vi genomför även relevant internationell bevakning. <br/><br/>Och följ med jobbannonser från företag som letar efter kvalificerade anställda med precis dina färdigheter. 1472 </p>Det är enkelt att avsluta nyhetsbrev som du inte längre vill ta emot. Du avslutar genom att klicka på länken som finns längst ner i nyhetsbrevet, eller <a class="bb" href="/newsletter/unsubscribe.html">avsluta nyhetsbrev här</a>. 1473 </div> 1474 </div> 1475 1476 </div> 1477 </main> 1478 <div> 1479 </div> 1480 </div> 1481 </div> 1482 <footer id="main-footer" v-cloak="" class="unprintable"> 1483 <nav> 1484 <div class="row text-center text-md-start"> 1485 <div class="col-12 col-md-3 mb-5 mb-md-0"> 1486 <a href="/"> 1487 <img src="https://f.nordiskemedier.dk/logo/inverted/54.png" alt="RT-Forum" loading="lazy" class="logo" /> 1488 </a> 1489 </div> 1490 <div class="col-12 col-md-6"> 1491 <div class="row"> 1492 <div v-for="(option, i) in footerOptions" v-bind:key="i" class="col-12 mb-4" v-bind:class="footerOptionClass"> 1493 <h6>{{ option.name }}</h6> 1494 <ul> 1495 <li v-for="(child, j) in option.children" v-bind:key="j"> 1496 <a v-bind:href="child.target" v-bind:target="child.external ? '_blank' : ''">{{ child.name }}</a> 1497 </li> 1498 </ul> 1499 </div> 1500 </div> 1501 </div> 1502 </div> 1503 </nav> 1504 <nav> 1505 <div> 1506 <div> 1507 <div class="row"> 1508 <div class="col-12 col-md-8 order-1 order-md-2 mb-4 text-center address"><div>Trafikforum - Nordens ledande facktidning för persontrafik</div> 1509 </div> 1510 <div class="col-6 col-md-2 order-2 order-md-1 mb-4"> 1511 </div> 1512 <div class="col-6 col-md-2 order-3 mb-4 text-end"> 1513 <ip-access-toggle></ip-access-toggle> 1514 </div> 1515 </div> 1516 </div> 1517 </div> 1518 </nav> 1519 </footer> 1520
1520<script type="application/javascript"> 1521 //<![CDATA[ 1522 new Vue({ 1523 el: "#main-footer", 1524 data: { 1525 footerOptions: [{"children":[{"external":false,"name":"Bli prenumerant","target":"/products/subscription.html"},{"external":true,"name":"Bli medlem","target":"https://nordiskemediehus.dk/se/produkt/medlemskab/"},{"external":true,"name":"Annonsera","target":"https://nordiskemediehus.dk/se/rt-forum/"},{"external":true,"name":"Se alla produkter","target":"https://nordiskemediehus.dk/se/produkter/"}],"name":"Produkter"},{"children":[{"external":false,"name":"Cookies och personuppgiftspolicy","target":"/privacy"},{"external":false,"name":"Juridik och upphovsrätt","target":"/page/view.html?id=17921"},{"external":false,"name":"KlagomÃ¥l","target":"/page/view.html?id=17919"},{"external":false,"name":"Sponsrat innehÃ¥ll","target":"/lb-article"}],"name":"Ãvrigt"},{"children":[{"external":false,"name":"Kontakta redaktionen","target":"mailto:[email protected]"},{"external":false,"name":"Kontakta oss","target":"/page/view.html?id=18019"},{"external":true,"name":"Jobba hos oss","target":"https://nordiskemediehus.dk/se/om-os/karriere/"},{"external":true,"name":"Om RT-Forum","target":"https://nordiskemediehus.dk/se/rt-forum/"}],"name":"Kontakt"}] 1526 }, 1527 computed: { 1528 footerOptionClass: function () { 1529 const len = this.footerOptions.length; 1530 if (len <= 1) { 1531 return "col-sm-12"; 1532 } else if (len == 2) { 1533 return "col-sm-6"; 1534 } else if (len == 3) { 1535 return "col-sm-4"; 1536 } else if (len == 4) { 1537 return "col-sm-3"; 1538 } else if (len >= 5 && len <= 6) { 1539 return "col-sm-4"; 1540 } else if (len >= 7 && len <= 8) { 1541 return "col-sm-3"; 1542 } else if (len == 9) { 1543 return "col-sm-4"; 1544 } else { 1545 return "col-sm-3"; 1546 } 1547 } 1548 } 1549 }); 1550 //]]> 1551 </script>
1551 1552 <div id="breaking-news-app" v-cloak="" v-if="article" class="breaking-news unprintable"> 1553 <div> 1554 <img src="/binary/breaking-black.svg" loading="lazy" />BREAKING 1555 </div> 1556 <div> 1557 <a v-bind:href="article.link" ref="headlineRef" v-bind:style="styleStr">{{ article.headline }}</a> 1558 </div> 1559 </div> 1560
1560<script type="application/javascript"> 1561 //<![CDATA[ 1562 new Vue({ 1563 el: "#breaking-news-app", 1564 data: { 1565 articles: [], 1566 intervalId: null, 1567 isTabActive: true, 1568 isWindowFocused: true, 1569 currentOffset: 0, 1570 currentTransitionTime: 2000 1571 }, 1572 computed: { 1573 article: function () { 1574 if (this.articles && this.articles.length) { 1575 return this.articles[0]; 1576 } 1577 return null; 1578 }, 1579 shouldFetch: function () { 1580 return this.isTabActive && this.isWindowFocused; 1581 }, 1582 styleStr: function () { 1583 return "margin-left: " + this.currentOffset + "px; transition: margin-left " + this.currentTransitionTime + "ms linear;"; 1584 } 1585 }, 1586 mounted: function () { 1587 this.load(); 1588 1589 document.addEventListener("visibilitychange", this.handleVisibilityChange); 1590 1591 window.addEventListener("focus", this.handleFocus); 1592 window.addEventListener("blur", this.handleBlur); 1593 1594 this.intervalId = setInterval(() => { 1595 if (this.shouldFetch) { 1596 this.load(); 1597 } 1598 }, 60000); 1599 }, 1600 beforeDestroy: function () { 1601 clearInterval(this.intervalId); 1602 document.removeEventListener("visibilitychange", this.handleVisibilityChange); 1603 window.removeEventListener("focus", this.handleFocus); 1604 window.removeEventListener("blur", this.handleBlur); 1605 }, 1606 watch: { 1607 article: function (newValue, oldValue) { 1608 if (newValue?.id !== oldValue?.id) { 1609 const defaultTransitionTime = 2000; 1610 const transitionPause = 1000; 1611 1612 const check = () => { 1613 const overflowAmount = this.getOverflowAmount(); 1614 if (overflowAmount !== 0) { 1615 this.currentOffset = this.currentOffset === 0 ? overflowAmount : 0; 1616 this.currentTransitionTime = -1000 * overflowAmount / 25; 1617 } else { 1618 this.currentOffset = 0; 1619 this.currentTransitionTime = defaultTransitionTime; 1620 } 1621 1622 this.currentTransitionTime = Math.max(this.currentTransitionTime, defaultTransitionTime); 1623 setTimeout(check, this.currentTransitionTime + transitionPause); 1624 } 1625 1626 check(); 1627 } 1628 } 1629 }, 1630 methods: { 1631 load: function () { 1632 this.$services.articleService.loadBreaking().then((data) => { 1633 this.articles = data; 1634 }).catch((err) => { 1635 console.error(err); 1636 }) 1637 }, 1638 handleVisibilityChange: function () { 1639 this.isTabActive = !document.hidden; 1640 }, 1641 handleFocus: function () { 1642 this.isWindowFocused = true; 1643 }, 1644 handleBlur: function () { 1645 this.isWindowFocused = false; 1646 }, 1647 getOverflowAmount: function () { 1648 const ref = this.$refs?.headlineRef; 1649 if (ref && ref.parentElement) { 1650 const elementWidth = ref.offsetWidth; 1651 let parentWidth = ref.parentElement.offsetWidth; 1652 1653 const parentStyle = window.getComputedStyle(ref.parentElement); 1654 const parentPaddingLeft = parseFloat(parentStyle.paddingLeft) || 0; 1655 const parentPaddingRight = parseFloat(parentStyle.paddingRight) || 0; 1656 parentWidth -= parentPaddingLeft; 1657 parentWidth -= parentPaddingRight; 1658 1659 if (elementWidth > parentWidth) { 1660 return parentWidth - elementWidth; 1661 } else { 1662 return 0; 1663 } 1664 } 1665 } 1666 } 1667 }); 1668 //]]> 1669 </script>
1669 1670 <form id="sendToColleagueForm"> 1671 <hash-modal hash="sendtocolleague" title="Sänd till en kollega"> 1672 <input-text id="sendToColleagueForm:yourEmail" v-model="formData.yourEmail" v-bind:errors="formErrors.yourEmail" label="Din e-post" required="true" maxlength="254"></input-text> 1673 <input-text id="sendToColleagueForm:yourName" v-model="formData.yourName" v-bind:errors="formErrors.yourName" label="Ditt namn" required="true" maxlength="100"></input-text> 1674 <input-text id="sendToColleagueForm:recipients" v-model="formData.recipients" v-bind:errors="formErrors.recipients" label="Kollegans e-post (Använd kommatecken för att separera e-postadresserna, om de är fler än en.)" required="true" maxlength="1000"></input-text> 1675 <input-textarea id="sendToColleagueForm:message" v-model="formData.message" v-bind:errors="formErrors.message" label="Meddelande" optional="Valfri" rows="5" maxlength="50000"></input-textarea> 1676 <template v-if="!person"> 1677 <select-boolean-checkbox id="sendToColleagueForm:remember" v-model="formData.remember" v-bind:errors="formErrors.remember" option-label="Kom ihåg mitt namn och e-post på den här datorn."></select-boolean-checkbox> 1678 <recaptcha id="sendToColleagueForm:recaptcha" sitekey="6LdasRwUAAAAAOAWkvok94EmD1GjREqoghAriL9L" v-bind:errors="formErrors.captcha"></recaptcha> 1679 </template> 1680 <button v-on:click.prevent="ok()" class="btn btn-success" v-bind:class="{'disabled': loading}"><i v-if="loading" style="margin-right: 5px;" class="fa-light fa-loading-white-12"></i>Skicka 1681 </button> 1682 <button v-on:click.prevent="cancel()" class="btn btn-outline-success">Stäng</button> 1683 </hash-modal> 1684 </form> 1685
1685<script> 1686 //<![CDATA[ 1687 $(function () { 1688 new Vue({ 1689 el: "#sendToColleagueForm", 1690 data: { 1691 person: false, 1692 loading: false, 1693 formData: { 1694 title: getTitle(), 1695 href: getUrl(), 1696 yourEmail: "", 1697 yourName: "", 1698 recipients: "", 1699 message: "", 1700 remember: true, 1701 captcha: null 1702 }, 1703 formErrors: {} 1704 }, 1705 methods: { 1706 reset: function () { 1707 this.formData.recipients = ""; 1708 this.formData.message = ""; 1709 }, 1710 submitForm: function () { 1711 var instance = this; 1712 instance.loading = true; 1713 $.ajax("/rest/sharedPages", { 1714 cache: false, 1715 method: "post", 1716 data: instance.formData, 1717 success: function (data) { 1718 instance.$clearFormErrors(instance.formErrors); 1719 if (data.status === "ok") { 1720 instance.reset(); 1721 closeSendToColleague(); 1722 } else { 1723 if (data.errors.remember || data.errors.captcha) { 1724 instance.person = false; 1725 } 1726 instance.$showFormErrors(instance.formErrors, data.errors); 1727 } 1728 }, 1729 complete: function () { 1730 instance.loading = false; 1731 } 1732 }); 1733 }, 1734 ok: function () { 1735 if (!this.loading) { 1736 this.formData.captcha = $("#sendToColleagueForm textarea[name=g-recaptcha-response]").val(); 1737 this.submitForm(); 1738 } 1739 }, 1740 cancel: function () { 1741 history.back(); 1742 } 1743 } 1744 }); 1745 }); 1746 //]]> 1747 </script>
1747 1748 </div> 1749 <div class="render-time unprintable">0.062<span class="mx-1">|</span> 1750 </div></body> 1751</html>
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.