1Drupal.TBMegaMenu = Drupal.TBMegaMenu || {}; 2 3(function ($) { 4 Drupal.TBMegaMenu.oldWindowWidth = 0; 5 Drupal.TBMegaMenu.displayedMenuMobile = false; 6 Drupal.TBMegaMenu.supportedScreens = [980]; 7 Drupal.TBMegaMenu.menuResponsive = function () { 8 var windowWidth = window.innerWidth ? window.innerWidth : $(window).width(); 9 var navCollapse = $('.tb-megamenu').children('.nav-collapse'); 10 if (windowWidth < Drupal.TBMegaMenu.supportedScreens[0]) { 11 navCollapse.addClass('collapse'); 12 if (Drupal.TBMegaMenu.displayedMenuMobile) { 13 navCollapse.css({height: 'auto', overflow: 'visible'}); 14 } else { 15 navCollapse.css({height: 0, overflow: 'hidden'}); 16 } 17 } else { 18 // If width of window is greater than 980 (supported screen). 19 navCollapse.removeClass('collapse'); 20 if (navCollapse.height() <= 0) { 21 navCollapse.css({height: 'auto', overflow: 'visible'}); 22 } 23 } 24 }; 25 26 Drupal.behaviors.tbMegaMenuAction = { 27 attach: function(context) { 28 $('.tb-megamenu-button', context).once('menuIstance', function () { 29 var This = this; 30 $(This).click(function() { 31 if(parseInt($(this).parent().children('.nav-collapse').height())) { 32 $(this).parent().children('.nav-collapse').css({height: 0, overflow: 'hidden'}); 33 Drupal.TBMegaMenu.displayedMenuMobile = false; 34 } 35 else { 36 $(this).parent().children('.nav-collapse').css({height: 'auto', overflow: 'visible'}); 37 Drupal.TBMegaMenu.displayedMenuMobile = true; 38 } 39 }); 40 }); 41 42 43 var isTouch = 'ontouchstart' in window && !(/hp-tablet/gi).test(navigator.appVersion); 44 if(!isTouch){ 45 $(document).ready(function($){ 46 var mm_duration = 0; 47 $('.tb-megamenu').each (function(){ 48 if ($(this).data('duration')) { 49 mm_duration = $(this).data('duration'); 50 } 51 }); 52 var mm_timeout = mm_duration ? 100 + mm_duration : 500; 53 $('.nav > li, li.mega').hover(function(event) { 54 var $this = $(this); 55 if ($this.hasClass ('mega')) { 56 $this.addClass ('animating'); 57 clearTimeout ($this.data('animatingTimeout')); 58 $this.data('animatingTimeout', setTimeout(function(){$this.removeClass ('animating')}, mm_timeout)); 59 clearTimeout ($this.data('hoverTimeout')); 60 $this.data('hoverTimeout', setTimeout(function(){$this.addClass ('open')}, 100)); 61 } else { 62 clearTimeout ($this.data('hoverTimeout')); 63 $this.data('hoverTimeout', 64 setTimeout(function(){$this.addClass ('open')}, 100)); 65 } 66 }, 67 function(event) { 68 var $this = $(this); 69 if ($this.hasClass ('mega')) { 70 $this.addClass ('animating'); 71 clearTimeout ($this.data('animatingTimeout')); 72 $this.data('animatingTimeout', 73 setTimeout(function(){$this.removeClass ('animating')}, mm_timeout)); 74 clearTimeout ($this.data('hoverTimeout')); 75 $this.data('hoverTimeout', setTimeout(function(){$this.removeClass ('open')}, 100)); 76 } else { 77 clearTimeout ($this.data('hoverTimeout')); 78 $this.data('hoverTimeout', 79 setTimeout(function(){$this.removeClass ('open')}, 100)); 80 } 81 }); 82 }); 83 } 84 85 $(window).resize(function() { 86 var windowWidth = window.innerWidth ? window.innerWidth : $(window).width(); 87 if(windowWidth != Drupal.TBMegaMenu.oldWindowWidth){ 88 Drupal.TBMegaMenu.oldWindowWidth = windowWidth; 89 Drupal.TBMegaMenu.menuResponsive(); 90 } 91 }); 92 }, 93 } 94})(jQuery); 95 96; 97Drupal.TBMegaMenu = Drupal.TBMegaMenu || {}; 98 99(function ($) { 100 Drupal.TBMegaMenu.createTouchMenu = function(items) { 101 items.children('a').each( function() { 102 var $item = $(this); 103 var tbitem = $(this).parent(); 104 $item.click( function(event){ 105 if ($item.hasClass('tb-megamenu-clicked')) { 106 var $uri = $item.attr('href'); 107 window.location.href = $uri; 108 } 109 else { 110 event.preventDefault(); 111 $item.addClass('tb-megamenu-clicked'); 112 if(!tbitem.hasClass('open')){ 113 tbitem.addClass('open'); 114 } 115 } 116 }).closest('li').mouseleave( function(){ 117 $item.removeClass('tb-megamenu-clicked'); 118 tbitem.removeClass('open'); 119 }); 120 }); 121 /* 122 items.children('a').children('span.caret').each( function() { 123 var $item = $(this).parent(); 124 $item.click(function(event){ 125 tbitem = $item.parent(); 126 if ($item.hasClass('tb-megamenu-clicked')) { 127 Drupal.TBMegaMenu.eventStopPropagation(event); 128 if(tbitem.hasClass('open')){ 129 tbitem.removeClass('open'); 130 $item.removeClass('tb-megamenu-clicked'); 131 } 132 } 133 else { 134 Drupal.TBMegaMenu.eventStopPropagation(event); 135 $item.addClass('tb-megamenu-clicked'); 136 if(!tbitem.hasClass('open')){ 137 tbitem.addClass('open'); 138 $item.removeClass('tb-megamenu-clicked'); 139 } 140 } 141 }); 142 }); 143 */ 144 } 145 146 Drupal.TBMegaMenu.eventStopPropagation = function(event) { 147 if (event.stopPropagation) { 148 event.stopPropagation(); 149 } 150 else if (window.event) { 151 window.event.cancelBubble = true; 152 } 153 } 154 Drupal.behaviors.tbMegaMenuTouchAction = { 155 attach: function(context) { 156 var isTouch = 'ontouchstart' in window && !(/hp-tablet/gi).test(navigator.appVersion); 157 if(isTouch){ 158 $('html').addClass('touch'); 159 Drupal.TBMegaMenu.createTouchMenu($('.tb-megamenu ul.nav li.mega').has('.dropdown-menu')); 160 } 161 } 162 } 163})(jQuery); 164; 165(function ($) { 166 167 Drupal.behaviors.captcha = { 168 attach: function (context) { 169 170 // Turn off autocompletion for the CAPTCHA response field. 171 // We do it here with JavaScript (instead of directly in the markup) 172 // because this autocomplete attribute is not standard and 173 // it would break (X)HTML compliance. 174 $("#edit-captcha-response").attr("autocomplete", "off"); 175 176 } 177 }; 178 179 Drupal.behaviors.captchaAdmin = { 180 attach: function (context) {
181 // Add onclick handler to checkbox for adding a CAPTCHA description 182 // so that the textfields for the CAPTCHA description are hidden 183 // when no description should be added. 184 // @todo: div.form-item-captcha-description depends on theming, maybe 185 // it's better to add our own wrapper with id (instead of a class). 186 $("#edit-captcha-add-captcha-description").click(function() { 187 if ($("#edit-captcha-add-captcha-description").is(":checked")) { 188 // Show the CAPTCHA description textfield(s). 189 $("div.form-item-captcha-description").show('slow'); 190 } 191 else { 192 // Hide the CAPTCHA description textfield(s). 193 $("div.form-item-captcha-description").hide('slow'); 194 } 195 }); 196 // Hide the CAPTCHA description textfields if option is disabled on page load. 197 if (!$("#edit-captcha-add-captcha-description").is(":checked")) { 198 $("div.form-item-captcha-description").hide(); 199 } 200 } 201 202 }; 203 204})(jQuery); 205; 206/** 207 * @file 208 * Some basic behaviors and utility functions for Views. 209 */ 210(function ($) { 211 212 Drupal.Views = {}; 213 214 /** 215 * JQuery UI tabs, Views integration component. 216 */ 217 Drupal.behaviors.viewsTabs = { 218 attach: function (context) { 219 if ($.viewsUi && $.viewsUi.tabs) { 220 $('#views-tabset').once('views-processed').viewsTabs({ 221 selectedClass: 'active' 222 }); 223 } 224 225 $('a.views-remove-link').once('views-processed').click(function(event) { 226 var id = $(this).attr('id').replace('views-remove-link-', ''); 227 $('#views-row-' + id).hide(); 228 $('#views-removed-' + id).attr('checked', true); 229 event.preventDefault(); 230 }); 231 /** 232 * Here is to handle display deletion 233 * (checking in the hidden checkbox and hiding out the row). 234 */ 235 $('a.display-remove-link') 236 .addClass('display-processed') 237 .click(function() { 238 var id = $(this).attr('id').replace('display-remove-link-', ''); 239 $('#display-row-' + id).hide(); 240 $('#display-removed-' + id).attr('checked', true); 241 return false; 242 }); 243 } 244 }; 245 246 /** 247 * Helper function to parse a querystring. 248 */ 249 Drupal.Views.parseQueryString = function (query) { 250 var args = {}; 251 var pos = query.indexOf('?'); 252 if (pos != -1) { 253 query = query.substring(pos + 1); 254 } 255 var pairs = query.split('&'); 256 for (var i in pairs) { 257 if (typeof(pairs[i]) == 'string') { 258 var pair = pairs[i].split('='); 259 // Ignore the 'q' path argument, if present. 260 if (pair[0] != 'q' && pair[1]) { 261 args[decodeURIComponent(pair[0].replace(/\+/g, ' '))] = decodeURIComponent(pair[1].replace(/\+/g, ' ')); 262 } 263 } 264 } 265 return args; 266 }; 267 268 /** 269 * Helper function to return a view's arguments based on a path. 270 */ 271 Drupal.Views.parseViewArgs = function (href, viewPath) { 272 273 // Provide language prefix. 274 if (Drupal.settings.pathPrefix) { 275 var viewPath = Drupal.settings.pathPrefix + viewPath; 276 } 277 var returnObj = {}; 278 var path = Drupal.Views.getPath(href); 279 // Ensure we have a correct path. 280 if (viewPath && path.substring(0, viewPath.length + 1) == viewPath + '/') { 281 var args = decodeURIComponent(path.substring(viewPath.length + 1, path.length)); 282 returnObj.view_args = args; 283 returnObj.view_path = path; 284 } 285 return returnObj; 286 }; 287 288 /** 289 * Strip off the protocol plus domain from an href. 290 */ 291 Drupal.Views.pathPortion = function (href) { 292 // Remove e.g. http://example.com if present. 293 var protocol = window.location.protocol; 294 if (href.substring(0, protocol.length) == protocol) { 295 // 2 is the length of the '//' that normally follows the protocol. 296 href = href.substring(href.indexOf('/', protocol.length + 2)); 297 } 298 return href; 299 }; 300 301 /** 302 * Return the Drupal path portion of an href. 303 */ 304 Drupal.Views.getPath = function (href) { 305 href = Drupal.Views.pathPortion(href); 306 href = href.substring(Drupal.settings.basePath.length, href.length); 307 // 3 is the length of the '?q=' added to the url without clean urls. 308 if (href.substring(0, 3) == '?q=') { 309 href = href.substring(3, href.length); 310 } 311 var chars = ['#', '?', '&']; 312 for (var i in chars) { 313 if (href.indexOf(chars[i]) > -1) { 314 href = href.substr(0, href.indexOf(chars[i])); 315 } 316 } 317 return href; 318 }; 319 320})(jQuery); 321; 322(function ($) { 323 324/** 325 * A progressbar object. Initialized with the given id. Must be inserted into 326 * the DOM afterwards through progressBar.element. 327 * 328 * method is the function which will perform the HTTP request to get the 329 * progress bar state. Either "GET" or "POST". 330 * 331 * e.g. pb = new progressBar('myProgressBar'); 332 * some_element.appendChild(pb.element); 333 */ 334Drupal.progressBar = function (id, updateCallback, method, errorCallback) { 335 var pb = this; 336 this.id = id; 337 this.method = method || 'GET'; 338 this.updateCallback = updateCallback; 339 this.errorCallback = errorCallback; 340
341 // The WAI-ARIA setting aria-live="polite" will announce changes after users 342 // have completed their current activity and not interrupt the screen reader. 343 this.element = $('<div class="progress-wrapper" aria-live="polite"></div>'); 344 this.element.html('<div id ="' + id + '" class="progress progress-striped active">' + 345 '<div class="progress-bar" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">' + 346 '<div class="percentage sr-only"></div>' + 347 '</div></div>' + 348 '</div><div class="percentage pull-right"></div>' + 349 '<div class="message"> </div>'); 350}; 351 352/** 353 * Set the percentage and status message for the progressbar. 354 */ 355Drupal.progressBar.prototype.setProgress = function (percentage, message) { 356 if (percentage >= 0 && percentage <= 100) { 357 $('div.progress-bar', this.element).css('width', percentage + '%'); 358 $('div.progress-bar', this.element).attr('aria-valuenow', percentage); 359 $('div.percentage', this.element).html(percentage + '%'); 360 } 361 $('div.message', this.element).html(message); 362 if (this.updateCallback) { 363 this.updateCallback(percentage, message, this); 364 } 365}; 366 367/** 368 * Start monitoring progress via Ajax. 369 */ 370Drupal.progressBar.prototype.startMonitoring = function (uri, delay) { 371 this.delay = delay; 372 this.uri = uri; 373 this.sendPing(); 374}; 375 376/** 377 * Stop monitoring progress via Ajax. 378 */ 379Drupal.progressBar.prototype.stopMonitoring = function () { 380 clearTimeout(this.timer); 381 // This allows monitoring to be stopped from within the callback. 382 this.uri = null; 383}; 384 385/** 386 * Request progress data from server. 387 */ 388Drupal.progressBar.prototype.sendPing = function () { 389 if (this.timer) { 390 clearTimeout(this.timer); 391 } 392 if (this.uri) { 393 var pb = this; 394 // When doing a post request, you need non-null data. Otherwise a 395 // HTTP 411 or HTTP 406 (with Apache mod_security) error may result. 396 $.ajax({ 397 type: this.method, 398 url: this.uri, 399 data: '', 400 dataType: 'json', 401 success: function (progress) { 402 // Display errors. 403 if (progress.status == 0) { 404 pb.displayError(progress.data); 405 return; 406 } 407 // Update display. 408 pb.setProgress(progress.percentage, progress.message); 409 // Schedule next timer. 410 pb.timer = setTimeout(function () { pb.sendPing(); }, pb.delay); 411 }, 412 error: function (xmlhttp) { 413 pb.displayError(Drupal.ajaxError(xmlhttp, pb.uri)); 414 } 415 }); 416 } 417}; 418 419/** 420 * Display errors on the page. 421 */ 422Drupal.progressBar.prototype.displayError = function (string) { 423 var error = $('<div class="alert alert-block alert-error"><a class="close" data-dismiss="alert" href="#">×</a><h4>Error message</h4></div>').append(string); 424 $(this.element).before(error).hide(); 425 426 if (this.errorCallback) { 427 this.errorCallback(this); 428 } 429}; 430 431})(jQuery); 432; 433/** 434 * @file 435 * Handles AJAX fetching of views, including filter submission and response. 436 */ 437(function ($) { 438 439 /** 440 * Attaches the AJAX behavior to exposed filter forms and key views links. 441 */ 442 Drupal.behaviors.ViewsAjaxView = {}; 443 Drupal.behaviors.ViewsAjaxView.attach = function() { 444 if (Drupal.settings && Drupal.settings.views && Drupal.settings.views.ajaxViews) { 445 $.each(Drupal.settings.views.ajaxViews, function(i, settings) { 446 Drupal.views.instances[i] = new Drupal.views.ajaxView(settings); 447 }); 448 } 449 }; 450 451 Drupal.views = {}; 452 Drupal.views.instances = {}; 453 454 /** 455 * JavaScript object for a certain view. 456 */ 457 Drupal.views.ajaxView = function(settings) { 458 var selector = '.view-dom-id-' + settings.view_dom_id; 459 this.$view = $(selector); 460 461 // Retrieve the path to use for views' ajax. 462 var ajax_path = Drupal.settings.views.ajax_path; 463 464 // If there are multiple views this might've ended up showing up multiple 465 // times. 466 if (ajax_path.constructor.toString().indexOf("Array") != -1) { 467 ajax_path = ajax_path[0]; 468 } 469 470 // Check if there are any GET parameters to send to views. 471 var queryString = window.location.search || ''; 472 if (queryString !== '') { 473 // Remove the question mark and Drupal path component if any. 474 var queryString = queryString.slice(1).replace(/q=[^&]+&?|&?render=[^&]+/, ''); 475 if (queryString !== '') { 476 // If there is a '?' in ajax_path, clean url are on and & should be 477 // used to add parameters. 478 queryString = ((/\?/.test(ajax_path)) ? '&' : '?') + queryString; 479 } 480 } 481 482 this.element_settings = { 483 url: ajax_path + queryString, 484 submit: settings, 485 setClick: true, 486 event: 'click', 487 selector: selector, 488 progress: { 489 type: 'throbber' 490 } 491 }; 492 493 this.settings = settings; 494
495 // Add the ajax to exposed forms. 496 this.$exposed_form = $('#views-exposed-form-' + settings.view_name.replace(/_/g, '-') + '-' + settings.view_display_id.replace(/_/g, '-')); 497 this.$exposed_form.once(jQuery.proxy(this.attachExposedFormAjax, this)); 498 499 // Store Drupal.ajax objects here for all pager links. 500 this.links = []; 501 502 // Add the ajax to pagers. 503 this.$view 504 .once(jQuery.proxy(this.attachPagerAjax, this)); 505 506 // Add a trigger to update this view specifically. In order to trigger a 507 // refresh use the following code. 508 // 509 // @code 510 // jQuery('.view-name').trigger('RefreshView'); 511 // @endcode 512 // Add a trigger to update this view specifically. 513 var self_settings = this.element_settings; 514 self_settings.event = 'RefreshView'; 515 this.refreshViewAjax = new Drupal.ajax(this.selector, this.$view, self_settings); 516 }; 517 518 Drupal.views.ajaxView.prototype.attachExposedFormAjax = function() { 519 var button = $('input[type=submit], button[type=submit], input[type=image]', this.$exposed_form); 520 button = button[0]; 521 522 // Call the autocomplete submit before doing AJAX. 523 $(button).click(function () { 524 if (Drupal.autocompleteSubmit) { 525 Drupal.autocompleteSubmit(); 526 } 527 }); 528 529 this.exposedFormAjax = new Drupal.ajax($(button).attr('id'), button, this.element_settings); 530 }; 531 532 /** 533 * Attach the ajax behavior to each link. 534 */ 535 Drupal.views.ajaxView.prototype.attachPagerAjax = function() { 536 this.$view.find('ul.pager > li > a, th.views-field a, .attachment .views-summary a') 537 .each(jQuery.proxy(this.attachPagerLinkAjax, this)); 538 }; 539 540 /** 541 * Attach the ajax behavior to a singe link. 542 */ 543 Drupal.views.ajaxView.prototype.attachPagerLinkAjax = function(id, link) { 544 var $link = $(link); 545 // Don't attach to pagers inside nested views. 546 if ($link.closest('.view')[0] !== this.$view[0]) { 547 return; 548 } 549 var viewData = {}; 550 var href = $link.attr('href'); 551 552 // Provide a default page if none has been set. This must be done 553 // prior to merging with settings to avoid accidentally using the 554 // page landed on instead of page 1. 555 if (typeof(viewData.page) === 'undefined') { 556 viewData.page = 0; 557 } 558 559 // Construct an object using the settings defaults and then overriding 560 // with data specific to the link. 561 $.extend( 562 viewData, 563 this.settings, 564 Drupal.Views.parseQueryString(href), 565 // Extract argument data from the URL. 566 Drupal.Views.parseViewArgs(href, this.settings.view_base_path) 567 ); 568 569 // For anchor tags, these will go to the target of the anchor rather 570 // than the usual location. 571 $.extend(viewData, Drupal.Views.parseViewArgs(href, this.settings.view_base_path)); 572 573 this.element_settings.submit = viewData; 574 this.pagerAjax = new Drupal.ajax(false, $link, this.element_settings); 575 this.links.push(this.pagerAjax); 576 }; 577 578 Drupal.ajax.prototype.commands.viewsScrollTop = function (ajax, response, status) { 579 // Scroll to the top of the view. This will allow users 580 // to browse newly loaded content after e.g. clicking a pager 581 // link. 582 var offset = $(response.selector).offset(); 583 // We can't guarantee that the scrollable object should be 584 // the body, as the view could be embedded in something 585 // more complex such as a modal popup. Recurse up the DOM 586 // and scroll the first element that has a non-zero top. 587 var scrollTarget = response.selector; 588 while ($(scrollTarget).scrollTop() == 0 && $(scrollTarget).parent()) { 589 scrollTarget = $(scrollTarget).parent(); 590 } 591 // Only scroll upward. 592 if (offset.top - 10 < $(scrollTarget).scrollTop()) { 593 $(scrollTarget).animate({scrollTop: (offset.top - 10)}, 500); 594 } 595 }; 596 597})(jQuery); 598; 599(function ($) { 600 601Drupal.googleanalytics = {}; 602 603$(document).ready(function() { 604 605 // Attach mousedown, keyup, touchstart events to document only and catch 606 // clicks on all elements. 607 $(document.body).bind("mousedown keyup touchstart", function(event) { 608 609 // Catch the closest surrounding link of a clicked element. 610 $(event.target).closest("a,area").each(function() { 611 612 // Is the clicked URL internal? 613 if (Drupal.googleanalytics.isInternal(this.href)) { 614 // Skip 'click' tracking, if custom tracking events are bound. 615 if ($(this).is('.colorbox') && (Drupal.settings.googleanalytics.trackColorbox)) {
616 // Do nothing here. The custom event will handle all tracking. 617 //console.info("Click on .colorbox item has been detected."); 618 } 619 // Is download tracking activated and the file extension configured for download tracking? 620 else if (Drupal.settings.googleanalytics.trackDownload && Drupal.googleanalytics.isDownload(this.href)) { 621 // Download link clicked. 622 ga("send", { 623 "hitType": "event", 624 "eventCategory": "Downloads", 625 "eventAction": Drupal.googleanalytics.getDownloadExtension(this.href).toUpperCase(), 626 "eventLabel": Drupal.googleanalytics.getPageUrl(this.href), 627 "transport": "beacon" 628 }); 629 } 630 else if (Drupal.googleanalytics.isInternalSpecial(this.href)) { 631 // Keep the internal URL for Google Analytics website overlay intact. 632 ga("send", { 633 "hitType": "pageview", 634 "page": Drupal.googleanalytics.getPageUrl(this.href), 635 "transport": "beacon" 636 }); 637 } 638 } 639 else { 640 if (Drupal.settings.googleanalytics.trackMailto && $(this).is("a[href^='mailto:'],area[href^='mailto:']")) { 641 // Mailto link clicked. 642 ga("send", { 643 "hitType": "event", 644 "eventCategory": "Mails", 645 "eventAction": "Click", 646 "eventLabel": this.href.substring(7), 647 "transport": "beacon" 648 }); 649 } 650 else if (Drupal.settings.googleanalytics.trackOutbound && this.href.match(/^\w+:\/\//i)) { 651 if (Drupal.settings.googleanalytics.trackDomainMode !== 2 || (Drupal.settings.googleanalytics.trackDomainMode === 2 && !Drupal.googleanalytics.isCrossDomain(this.hostname, Drupal.settings.googleanalytics.trackCrossDomains))) { 652 // External link clicked / No top-level cross domain clicked. 653 ga("send", { 654 "hitType": "event", 655 "eventCategory": "Outbound links", 656 "eventAction": "Click", 657 "eventLabel": this.href, 658 "transport": "beacon" 659 }); 660 } 661 } 662 } 663 }); 664 }); 665 666 // Track hash changes as unique pageviews, if this option has been enabled. 667 if (Drupal.settings.googleanalytics.trackUrlFragments) { 668 window.onhashchange = function() { 669 ga("send", { 670 "hitType": "pageview", 671 "page": location.pathname + location.search + location.hash 672 }); 673 }; 674 } 675 676 // Colorbox: This event triggers when the transition has completed and the 677 // newly loaded content has been revealed. 678 if (Drupal.settings.googleanalytics.trackColorbox) { 679 $(document).bind("cbox_complete", function () { 680 var href = $.colorbox.element().attr("href"); 681 if (href) { 682 ga("send", { 683 "hitType": "pageview", 684 "page": Drupal.googleanalytics.getPageUrl(href) 685 }); 686 } 687 }); 688 } 689 690}); 691 692/** 693 * Check whether the hostname is part of the cross domains or not. 694 * 695 * @param string hostname 696 * The hostname of the clicked URL. 697 * @param array crossDomains 698 * All cross domain hostnames as JS array. 699 * 700 * @return boolean 701 */ 702Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) { 703 /** 704 * jQuery < 1.6.3 bug: $.inArray crushes IE6 and Chrome if second argument is 705 * `null` or `undefined`, https://bugs.jquery.com/ticket/10076, 706 * https://github.com/jquery/jquery/commit/a839af034db2bd934e4d4fa6758a3fed8de74174 707 * 708 * @todo: Remove/Refactor in D8 709 */ 710 if (!crossDomains) { 711 return false; 712 } 713 else { 714 return $.inArray(hostname, crossDomains) > -1 ? true : false; 715 } 716}; 717 718/** 719 * Check whether this is a download URL or not. 720 * 721 * @param string url 722 * The web url to check. 723 * 724 * @return boolean 725 */ 726Drupal.googleanalytics.isDownload = function (url) { 727 var isDownload = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i"); 728 return isDownload.test(url); 729}; 730 731/** 732 * Check whether this is an absolute internal URL or not. 733 * 734 * @param string url 735 * The web url to check. 736 * 737 * @return boolean 738 */ 739Drupal.googleanalytics.isInternal = function (url) { 740 var isInternal = new RegExp("^(https?):\/\/" + window.location.host, "i"); 741 return isInternal.test(url); 742}; 743 744/** 745 * Check whether this is a special URL or not. 746 * 747 * URL types: 748 * - gotwo.module /go/* links. 749 * 750 * @param string url 751 * The web url to check. 752 * 753 * @return boolean 754 */ 755Drupal.googleanalytics.isInternalSpecial = function (url) { 756 var isInternalSpecial = new RegExp("(\/go\/.*)$", "i"); 757 return isInternalSpecial.test(url); 758}; 759 760/** 761 * Extract the relative internal URL from an absolute internal URL. 762 * 763 * Examples: 764 * - https://mydomain.com/node/1 -> /node/1 765 * - https://example.com/foo/bar -> https://example.com/foo/bar 766 * 767 * @param string url 768 * The web url to check. 769 * 770 * @return string 771 * Internal website URL 772 */ 773Drupal.googleanalytics.getPageUrl = function (url) { 774 var extractInternalUrl = new RegExp("^(https?):\/\/" + window.location.host, "i"); 775 return url.replace(extractInternalUrl, ''); 776}; 777 778/** 779 * Extract the download file extension from the URL. 780 * 781 * @param string url 782 * The web url to check. 783 * 784 * @return string 785 * The file extension of the passed url. e.g. "zip", "txt" 786 */ 787Drupal.googleanalytics.getDownloadExtension = function (url) { 788 var extractDownloadextension = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i"); 789 var extension = extractDownloadextension.exec(url); 790 return (extension === null) ? '' : extension[1]; 791}; 792 793})(jQuery); 794;
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.