(function ($) {
/**
* Attaches sticky table headers.
*/
Drupal.behaviors.tableHeader = {
attach: function (context, settings) {
if (!$.support.positionFixed) {
return;
}
$('table.sticky-enabled', context).once('tableheader', function () {
$(this).data("drupal-tableheader", new Drupal.tableHeader(this));
});
}
};
/**
* Constructor for the tableHeader object. Provides sticky table headers.
*
* @param table
* DOM object for the table to add a sticky header to.
*/
Drupal.tableHeader = function (table) {
var self = this;
this.originalTable = $(table);
this.originalHeader = $(table).children('thead');
this.originalHeaderCells = this.originalHeader.find('> tr > th');
this.displayWeight = null;
// React to columns change to avoid making checks in the scroll callback.
this.originalTable.bind('columnschange', function (e, display) {
// This will force header size to be calculated on scroll.
self.widthCalculated = (self.displayWeight !== null && self.displayWeight === display);
self.displayWeight = display;
});
// Clone the table header so it inherits original jQuery properties. Hide
// the table to avoid a flash of the header clone upon page load.
this.stickyTable = $('
')
.insertBefore(this.originalTable)
.css({ position: 'fixed', top: '0px' });
this.stickyHeader = this.originalHeader.clone(true)
.hide()
.appendTo(this.stickyTable);
this.stickyHeaderCells = this.stickyHeader.find('> tr > th');
this.originalTable.addClass('sticky-table');
$(window)
.bind('scroll.drupal-tableheader', $.proxy(this, 'eventhandlerRecalculateStickyHeader'))
.bind('resize.drupal-tableheader', { calculateWidth: true }, $.proxy(this, 'eventhandlerRecalculateStickyHeader'))
// Make sure the anchor being scrolled into view is not hidden beneath the
// sticky table header. Adjust the scrollTop if it does.
.bind('drupalDisplaceAnchor.drupal-tableheader', function () {
window.scrollBy(0, -self.stickyTable.outerHeight());
})
// Make sure the element being focused is not hidden beneath the sticky
// table header. Adjust the scrollTop if it does.
.bind('drupalDisplaceFocus.drupal-tableheader', function (event) {
if (self.stickyVisible && event.clientY < (self.stickyOffsetTop + self.stickyTable.outerHeight()) && event.$target.closest('sticky-header').length === 0) {
window.scrollBy(0, -self.stickyTable.outerHeight());
}
})
.triggerHandler('resize.drupal-tableheader');
// We hid the header to avoid it showing up erroneously on page load;
// we need to unhide it now so that it will show up when expected.
this.stickyHeader.show();
};
/**
* Event handler: recalculates position of the sticky table header.
*
* @param event
* Event being triggered.
*/
Drupal.tableHeader.prototype.eventhandlerRecalculateStickyHeader = function (event) {
var self = this;
var calculateWidth = event.data && event.data.calculateWidth;
// Reset top position of sticky table headers to the current top offset.
this.stickyOffsetTop = Drupal.settings.tableHeaderOffset ? eval(Drupal.settings.tableHeaderOffset + '()') : 0;
this.stickyTable.css('top', this.stickyOffsetTop + 'px');
// Save positioning data.
var viewHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
if (calculateWidth || this.viewHeight !== viewHeight) {
this.viewHeight = viewHeight;
this.vPosition = this.originalTable.offset().top - 4 - this.stickyOffsetTop;
this.hPosition = this.originalTable.offset().left;
this.vLength = this.originalTable[0].clientHeight - 100;
calculateWidth = true;
}
// Track horizontal positioning relative to the viewport and set visibility.
var hScroll = document.documentElement.scrollLeft || document.body.scrollLeft;
var vOffset = (document.documentElement.scrollTop || document.body.scrollTop) - this.vPosition;
this.stickyVisible = vOffset > 0 && vOffset < this.vLength;
this.stickyTable.css({ left: (-hScroll + this.hPosition) + 'px', visibility: this.stickyVisible ? 'visible' : 'hidden' });
// Only perform expensive calculations if the sticky header is actually
// visible or when forced.
if (this.stickyVisible && (calculateWidth || !this.widthCalculated)) {
this.widthCalculated = true;
var $that = null;
var $stickyCell = null;
var display = null;
var cellWidth = null;
// Resize header and its cell widths.
// Only apply width to visible table cells. This prevents the header from
// displaying incorrectly when the sticky header is no longer visible.
for (var i = 0, il = this.originalHeaderCells.length; i < il; i += 1) {
$that = $(this.originalHeaderCells[i]);
$stickyCell = this.stickyHeaderCells.eq($that.index());
display = $that.css('display');
if (display !== 'none') {
cellWidth = $that.css('width');
// Exception for IE7.
if (cellWidth === 'auto') {
cellWidth = $that[0].clientWidth + 'px';
}
$stickyCell.css({'width': cellWidth, 'display': display});
}
else {
$stickyCell.css('display', 'none');
}
}
this.stickyTable.css('width', this.originalTable.outerWidth());
}
};
})(jQuery);
;
(function ($) {
Drupal.googleanalytics = {};
$(document).ready(function() {
// Attach mousedown, keyup, touchstart events to document only and catch
// clicks on all elements.
$(document.body).bind("mousedown keyup touchstart", function(event) {
// Catch the closest surrounding link of a clicked element.
$(event.target).closest("a,area").each(function() {
// Is the clicked URL internal?
if (Drupal.googleanalytics.isInternal(this.href)) {
// Skip 'click' tracking, if custom tracking events are bound.
if ($(this).is('.colorbox') && (Drupal.settings.googleanalytics.trackColorbox)) {
// Do nothing here. The custom event will handle all tracking.
//console.info("Click on .colorbox item has been detected.");
}
// Is download tracking activated and the file extension configured for download tracking?
else if (Drupal.settings.googleanalytics.trackDownload && Drupal.googleanalytics.isDownload(this.href)) {
// Download link clicked.
ga("send", {
"hitType": "event",
"eventCategory": "Downloads",
"eventAction": Drupal.googleanalytics.getDownloadExtension(this.href).toUpperCase(),
"eventLabel": Drupal.googleanalytics.getPageUrl(this.href),
"transport": "beacon"
});
}
else if (Drupal.googleanalytics.isInternalSpecial(this.href)) {
// Keep the internal URL for Google Analytics website overlay intact.
ga("send", {
"hitType": "pageview",
"page": Drupal.googleanalytics.getPageUrl(this.href),
"transport": "beacon"
});
}
}
else {
if (Drupal.settings.googleanalytics.trackMailto && $(this).is("a[href^='mailto:'],area[href^='mailto:']")) {
// Mailto link clicked.
ga("send", {
"hitType": "event",
"eventCategory": "Mails",
"eventAction": "Click",
"eventLabel": this.href.substring(7),
"transport": "beacon"
});
}
else if (Drupal.settings.googleanalytics.trackOutbound && this.href.match(/^\w+:\/\//i)) {
if (Drupal.settings.googleanalytics.trackDomainMode !== 2 || (Drupal.settings.googleanalytics.trackDomainMode === 2 && !Drupal.googleanalytics.isCrossDomain(this.hostname, Drupal.settings.googleanalytics.trackCrossDomains))) {
// External link clicked / No top-level cross domain clicked.
ga("send", {
"hitType": "event",
"eventCategory": "Outbound links",
"eventAction": "Click",
"eventLabel": this.href,
"transport": "beacon"
});
}
}
}
});
});
// Track hash changes as unique pageviews, if this option has been enabled.
if (Drupal.settings.googleanalytics.trackUrlFragments) {
window.onhashchange = function() {
ga("send", {
"hitType": "pageview",
"page": location.pathname + location.search + location.hash
});
};
}
// Colorbox: This event triggers when the transition has completed and the
// newly loaded content has been revealed.
if (Drupal.settings.googleanalytics.trackColorbox) {
$(document).bind("cbox_complete", function () {
var href = $.colorbox.element().attr("href");
if (href) {
ga("send", {
"hitType": "pageview",
"page": Drupal.googleanalytics.getPageUrl(href)
});
}
});
}
});
/**
* Check whether the hostname is part of the cross domains or not.
*
* @param string hostname
* The hostname of the clicked URL.
* @param array crossDomains
* All cross domain hostnames as JS array.
*
* @return boolean
*/
Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) {
/**
* jQuery < 1.6.3 bug: $.inArray crushes IE6 and Chrome if second argument is
* `null` or `undefined`, http://bugs.jquery.com/ticket/10076,
* https://github.com/jquery/jquery/commit/a839af034db2bd934e4d4fa6758a3fed8de74174
*
* @todo: Remove/Refactor in D8
*/
if (!crossDomains) {
return false;
}
else {
return $.inArray(hostname, crossDomains) > -1 ? true : false;
}
};
/**
* Check whether this is a download URL or not.
*
* @param string url
* The web url to check.
*
* @return boolean
*/
Drupal.googleanalytics.isDownload = function (url) {
var isDownload = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
return isDownload.test(url);
};
/**
* Check whether this is an absolute internal URL or not.
*
* @param string url
* The web url to check.
*
* @return boolean
*/
Drupal.googleanalytics.isInternal = function (url) {
var isInternal = new RegExp("^(https?):\/\/" + window.location.host, "i");
return isInternal.test(url);
};
/**
* Check whether this is a special URL or not.
*
* URL types:
* - gotwo.module /go/* links.
*
* @param string url
* The web url to check.
*
* @return boolean
*/
Drupal.googleanalytics.isInternalSpecial = function (url) {
var isInternalSpecial = new RegExp("(\/go\/.*)$", "i");
return isInternalSpecial.test(url);
};
/**
* Extract the relative internal URL from an absolute internal URL.
*
* Examples:
* - http://mydomain.com/node/1 -> /node/1
* - http://example.com/foo/bar -> http://example.com/foo/bar
*
* @param string url
* The web url to check.
*
* @return string
* Internal website URL
*/
Drupal.googleanalytics.getPageUrl = function (url) {
var extractInternalUrl = new RegExp("^(https?):\/\/" + window.location.host, "i");
return url.replace(extractInternalUrl, '');
};
/**
* Extract the download file extension from the URL.
*
* @param string url
* The web url to check.
*
* @return string
* The file extension of the passed url. e.g. "zip", "txt"
*/
Drupal.googleanalytics.getDownloadExtension = function (url) {
var extractDownloadextension = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
var extension = extractDownloadextension.exec(url);
return (extension === null) ? '' : extension[1];
};
})(jQuery);
;