1// Social share button. Native share for mobile devices and podium share for desktop. 2function socialShare() { 3 4 const shareButton = document.getElementById( 'share' ); 5 const shareBlock = document.querySelector( '.url-share .share-block' ); 6 7 if( navigator.share && isMobile() && typeof(shareButton) != 'undefined' && shareButton != null ) { 8 const fullShare = {}; 9 10 fullShare.url = document.location.href; 11 const canonicalshareUrl = document.querySelector( 'link[rel=canonical]' ); 12 if( canonicalshareUrl !== null ) { 13 fullShare.url = canonicalshareUrl.href; 14 } 15 let shareTitle = document.querySelector( 'meta[property="og:title"]' ); 16 if( shareTitle !== null ) { 17 fullShare.title = shareTitle.content; 18 } 19 let shareText = document.querySelector( 'meta[property="og:description"]' ); 20 if( shareText !== null ) { 21 fullShare.text = shareText.content; 22 } 23 24 shareButton.addEventListener( 'click', () => { 25 navigator.share( fullShare ) 26 .then( () => console.log( 'Successful web.share' ) ) 27 .catch( ( error ) => console.log( 'Error on web.sharing:', error ) ); 28 } 29 ); 30 31 } else { 32 if( typeof(shareButton) != 'undefined' && shareButton != null && typeof(shareBlock) != 'undefined' && shareBlock != null ) { 33 34 shareBlock.style.display = "none"; 35 let urlShareEl = document.getElementById( 'urlShare' ); 36 37 // Share button 38 shareButton.addEventListener( 'click', () => { 39 if (shareBlock.style.display === 'none'){ 40 shareBlock.style.display = 'block'; 41 window.addEventListener( 'click', hideShareBlock ); 42 } else { 43 shareBlock.style.display = "none"; 44 window.removeEventListener( "click", hideShareBlock ); 45 } 46 }); 47 48 // Copy url to clipboard 49 if( typeof(urlShareEl) != 'undefined' && urlShareEl != null ) { 50 urlShareEl.addEventListener( 'click', function (event) { 51 52 if(shareBlock.style.display === 'block' ) { 53 window.removeEventListener( "click", hideShareBlock ); 54 } 55 56 event.preventDefault(); 57 copyShareUrl(urlShareEl); 58 }); 59 } 60 } 61 62 function hideShareBlock(e){ 63 64 if( typeof(e.target.parentNode) != 'undefined' && e.target.parentNode != null) { 65 classList = e.target.parentNode.classList; 66 } 67 68 if( classList.contains( 'social-share' ) || e.target.id === 'share' 69 || classList.contains( 'url-share' ) || classList.contains( 'share-btn' ) ) { 70 shareBlock.style.display = 'block'; 71 } else { 72 shareBlock.style.display = 'none'; 73 window.removeEventListener( 'click', hideShareBlock ); 74 } 75 76 } 77 78 function copyShareUrl( e ) { 79 80 let url = e.getAttribute( 'data-href' ); 81 let tooltip = document.querySelector( '.social-share .tooltip' ); 82 let isOnPage = tooltip.classList.contains( 'is-on-page' ); 83 84 window.navigator.clipboard.writeText( url ); 85 86 tooltip.classList.add( 'is-on-page' ); 87 88 setTimeout( () => { 89 tooltip.classList.add( 'is-active' ); 90 }, 1); 91 92 setTimeout( function() { 93 setTimeout( function() { 94 tooltip.classList.remove( 'is-on-page' ); 95 window.addEventListener( 'click', hideShareBlock ); 96 },100) 97 tooltip.classList.remove( 'is-active' ); 98 },2000); 99 100 } 101 102 } 103 104} 105 106function isMobile() { 107 return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); 108} 109 110socialShare(); 111 112// Make it so we open all external links in new tabs 113( function( $ ) { 114 $.expr[':'].external = function( obj ) { 115 return ( obj.hostname != location.hostname ) && obj.href.startsWith( 'http' ); 116 }; 117 $( 'a:external' ).attr( 'target', '_blank' ); 118} )( jQuery ); 119 120jQuery( document ).ready( function( $ ) { 121 const observer = lozad( '.lazyload', { 122 threshold: 0, 123 rootMargin: '100px', 124 load: function(el) { 125 126 el.src=el.dataset.src; 127 128 if( el.dataset.srcset !== undefined ) 129 el.srcset = el.dataset.srcset; 130 if( el.dataset.sizes !== undefined ) 131 el.sizes = el.dataset.sizes; 132 133 el.onload = function() { 134 el.classList.add( 'fade' ); 135 } 136 137 } 138 }); 139 140 observer.observe(); 141 142 // set touchstart eventlistener passive false in order for preventDefault to work 143 $.event.special.touchstart = { 144 setup: function ( _, ns, handle ) { 145 this.addEventListener( "touchstart", handle, { passive: false } ); 146 } 147 }; 148 149 // div fade content with expanding + push/pull side menu or content below 150 $( document ).on( 'click', '.btn-fd a, .btn-fd-strip a', function( e ) { 151 e.stopPropagation(); 152 }); 153 154 $( document ).on( 'click', '.btn-fd, .btn-fd-strip', function( e ) { 155 // prevent same handler firing at the same time on the element (valuejackpot plugin) 156 e.stopImmediatePropagation(); 157 158 // change the trigger element class for on/off 159 if( $( this ).hasClass('btn-fd-on') || $( this ).hasClass( 'btn-fd-off' ) ) { 160 $( this ).toggleClass( 'btn-fd-on btn-fd-off' ); 161 } 162 // if trigger element is child of another trigger element change parent's class as well 163 if( $( this ).parents( '.btn-fd-strip' ) ) { 164 $( this ).parents( '.btn-fd-strip' ).toggleClass( 'btn-fd-on btn-fd-off' ); 165 } 166 167 // get target element and its parent 168 var id = $( this ).attr( 'data-id' ); 169 var container = $( '.fading-box.fd-' + id ); 170 171 //var parentHeight = 0; 172 var initialHeight = 0; 173 174 // RETRACT box code: if already expanded & has initial height value attribute 175 if (container.hasClass('active') && container.hasClass('allow-closing')) { 176 container.css({ "height": container.height(), "max-height": 9999 }).stop().animate({ "height": 0 }, 250); 177 178 // target element opened/closed class 179 container.toggleClass('active'); 180 181 return false;
182 183 // already opened, but not allowed to close back 184 } else if (container.hasClass('active') && !container.hasClass('allow-closing')) 185 return false; 186 187 // EXPAND box code 188 var totalHeight = 0; 189 var children = $('.fd-' + id + ' > *:not(.btn-fd)'); 190 191 // measure how tall inside should be by adding together heights of all inside paragraphs (except read-more paragraph) 192 children.each(function () { 193 // add height (including any paddings) 194 totalHeight += $(this).outerHeight(); 195 // add margins 196 totalHeight += parseInt($(this).css('margin-bottom')); 197 }); 198 199 // add padding of conatiner 200 totalHeight += parseInt(container.css('padding-top')); 201 totalHeight += parseInt(container.css('padding-bottom')); 202 203 // Set height to prevent instant jumpdown when max height is removed 204 container.css({ "height": initialHeight, "max-height": 9999 }).stop().animate({ "height": totalHeight }, 250); 205 206 // target element opened/closed class 207 container.toggleClass('active'); 208 209 // fade out button if allowed to fade out 210 if (!$(this).hasClass('no-fade-out')) 211 $(this).fadeOut(); 212 213 // prevent jump-down 214 return false; 215 }); 216 217 // main nav toggle in mobiles 218 function menuToggle(e, preventDefault = false) { 219 // We don't want to prevent default action when clicking #anchors 220 if( preventDefault ) e.preventDefault(); 221 222 $( '.main-nav-toggle-mobile').closest('.nav-item').toggleClass('active'); 223 // deactivate all submenus that might be opened 224 $( '.nav.d-nav .dropdown-menu.active' ).removeClass( 'active' ); 225 $( '.nav.d-nav .nav-item.active-submenu' ).removeClass( 'active-submenu' ); 226 $( '.nav.d-nav .dropdown-item.menu-item-has-children.active' ).removeClass( 'active' ); 227 // toggle the menu opened / closed 228 $( '.nav.d-nav' ).toggleClass( 'visible' ); 229 // toggle class in body and html 230 $( 'body, html' ).toggleClass( 'menu-opened' ); 231 } 232 $( '.nav .main-nav-toggle-mobile' ).on( 'click', (e) => { menuToggle( e, true ); } ); 233 //if( $('.nav.m-nav').css('display') !== 'none' ) $( '.dropdown-menu a[href*="#"]' ).on( 'click', (e) => { menuToggle(e); } ); 234 235 // toggle main nav submenus in mobiles 236 $( '.nav.d-nav .dropdown-toggle' ).on( 'click', function(e) { 237 // hide any submenus that could be opened 238 $(this).parent().siblings().find( '.active' ).removeClass( 'active' ); 239 $(this).parent().siblings().removeClass( 'active-submenu' ); 240 241 // open the requested submenu 242 $(this).parent().toggleClass( 'active-submenu' ); 243 $(this).parent().find( '.dropdown-menu' ).toggleClass( 'active' ); 244 }); 245 246 // toggle sub-submenus in mobiles 247 $( '.nav.d-nav .dropdown-item.menu-item-has-children > a .icon-chevron-right' ).on( 'click', function(e) { 248 e.preventDefault(); 249 250 $(this).parent().parent().parent().siblings( '.active' ).removeClass( 'active' ); 251 $(this).parent().parent().toggleClass( 'active' ); 252 }); 253 254 // tabs click 255 $( '.tabs li' ).on( 'click', function( e ) { 256 targetID = $(this).attr( 'data-target' ); 257 groupID = $(this).parent().attr( 'data-tabs-group-id' ); 258 259 // remove any active on other tabs and activate the tab button 260 $( this ).siblings().removeClass( 'active' ); 261 $( this ).addClass( 'active' ); 262 263 // hide the last shown tab content 264 $( '.tabs-group-' + groupID ).removeClass( 'active' ); 265 266 // and show the clicked tab 267 $( '#' + targetID ).addClass( 'active' ); 268 }); 269 270 // ajax for load more 271 $('.load-more-btn').on('click', function(e) { 272 var dataID = $(this).attr('data-id'), 273 dataURL = $(this).attr('data-url'), 274 dataAction = $(this).attr('data-action'), // ajax function to execute 275 dataActionIdentifier = $(this).attr('data-action-identifier'), // twig template loader identifier (which template) 276 dataLimit = parseInt( $(this).attr('data-limit'), 10 ), 277 dataOffset = parseInt( $(this).attr('data-offset'), 10 ) + dataLimit, 278 dataTag = $(this).attr('data-tag'), 279 dataCategory = $(this).attr('data-category'), 280 dataCategoryExclude = $(this).attr('data-category-exclude'), 281 dataViewType = $(this).attr('data-view-type'), 282 dataPageID = parseInt( $(this).attr('data-page-id'), 10 ), 283 dataAuthor = $(this).attr('data-author'), 284 dataPostType = $(this).attr('data-post-type'), 285 dataIsFrontPage = $(this).attr('data-is-front-page'), 286 dataShowAuthor = $(this).attr('data-show-author'), 287 dataShowCaterogry = $(this).attr('data-show-category'), 288 dataShowTime = $(this).attr('data-show-time'); 289 290 $.ajax({ 291 type: 'POST', 292 url: dataURL, 293 dataType: 'html', 294 data: { 295 action: dataAction, 296 action_id: dataActionIdentifier, 297 limit: dataLimit, 298 offset: dataOffset, 299 tag: dataTag, 300 category: dataCategory, 301 category_exclude: dataCategoryExclude, 302 view_type: dataViewType, 303 current_page_id: dataPageID, 304 author: dataAuthor, 305 post_type: dataPostType, 306 is_front_page: dataIsFrontPage, 307 show_author: dataShowAuthor, 308 show_category: dataShowCaterogry, 309 show_time: dataShowTime 310 }, 311 beforeSend: function(data) { 312 // show up loader 313 $('.loader[data-id="loader-' + dataID + '"]').show(); 314 $('.load-more-btn[data-id="' + dataID + '"]').hide(); 315 }, 316 success: function(response) { 317 // log debug 318 //console.log( response ); 319 //console.log( 'offset: ' + offset<?php //echo $dataID; ?>); 320 //console.log( 'total: ' + totalCount<?php //echo $dataID; ?>); 321 322 // output the result 323 $('[data-id="' + dataActionIdentifier + '-' + dataID + '"]').append(response); 324 325 // do lazyload for all images possibly loaded through ajax 326 observer.observe(); 327 328 // set new value for offset 329 $('.load-more-btn').attr('data-offset',dataOffset); 330 331 // if the next offset is higher than total count, then remove the button 332 /*if ( offset<?php echo $dataID; ?> + <?php echo $initialOffset; ?> > totalCount<?php echo $dataID; ?> ) 333 $('.show-more-anchor[data-id="<?php echo $dataID; ?>"]').remove(); */ 334 },
335 complete: function(response) { 336 // hide loader 337 $('.loader[data-id="loader-' + dataID + '"]').hide(); 338 $('.load-more-btn[data-id="' + dataID + '"]').show(); 339 } 340 }); 341 }); 342 343 // Script that goes through tables with the convert-ages class and changes "Age" column from birthdates to ages 344 function getAge( dateString ) { 345 var today = new Date(); 346 var birthDate = new Date( dateString ); 347 var age = today.getFullYear() - birthDate.getFullYear(); 348 var m = today.getMonth() - birthDate.getMonth(); 349 if( m < 0 ) age--; 350 if( m === 0 ) { 351 if( today.getDate() < birthDate.getDate() ) age--; 352 } 353 return age; 354 } 355 $('.convert-ages').each( function( i, el ) { 356 ageColumnIndex = $( el ).find( 'th:contains(Ikä)' )[0].cellIndex; 357 358 $( el ).find( 'tbody tr' ).each( function( i, row ) { 359 var bdayCell = $( row ).find( 'td:eq(' + ageColumnIndex + ')' )[0]; 360 var bday = getAge( $( bdayCell ).html().slice( 0, 10 ).split( '.' ).reverse().join( '/' ) ); 361 362 if( typeof tippy !== 'undefined' ) { 363 // Make tippy work with the dynamically created tooltips (if it's loaded) 364 $( bdayCell ).html( '<span class="age" data-tippy-content=' + $( bdayCell ).html() + '>' + bday + '</span>' ); 365 tippy.delegate( $( this )[0], { target: '.age' } ); 366 } else { 367 $( bdayCell ).html( bday ); 368 } 369 } ); 370 } ); 371 372 // Toggling "show more" fields 373 $('.show-more').on('click', function (e) { 374 e.preventDefault(); 375 376 var morediv = $( this ).attr( 'data-more' ); 377 var lesstext = $( this ).attr( 'data-less-text' ); 378 var moretext = $( this ).attr( 'data-more-text' ); 379 380 $( this ).html( $( this ).html() == lesstext ? moretext : lesstext); // toggle if there are different texts for showing more and less 381 $( '.' + morediv ).slideToggle( 'fast' ); 382 }); 383 384 if( $( '.theiaStickySidebar' ).length > 0 ) { 385 $( '.page-sidebar' ).theiaStickySidebar({ 386 'sidebarBehavior': 'stick-to-bottom', 387 'minWidth': 980, 388 'additionalMarginBottom': 15 389 }); 390 } 391});
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.