Newer
Older
* Piwik - Web Analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
/**
* broadcast object is to help maintain a hash for link clicks and ajax calls
* so we can have back button and refresh button working.
*
* Other file that currently depending on this are:
* calendar.js
* period_select.tpl
* sites_selections.tpl
* menu.js, ...etc
*
* !! Load this once and only once. !!
var broadcast = {
/**
* Initialisation state
* @type {Boolean}
*/
_isInit: false,
/**
* Last known hash url without popover parameter
*/
currentHashUrl: false,
/**
* Last known popover parameter
*/
currentPopoverParameter: false,
/**
* Callbacks for popover parameter change
*/
popoverHandlers: [],
/**
* Suppress content update on hash changing
*/
updateHashOnly: false,
/**
* Initializes broadcast object
* @return {void}
*/
init: function() {
// Initialize history plugin.
// The callback is called at once by present location.hash
piwikHelper.showAjaxLoading();
},
/**
* ========== PageLoad function =================
* This function is called when:
* 1. after calling $.history.init();
* 2. after calling $.history.load(); //look at broadcast.changeParameter();
* 3. after pushing "Go Back" button of a browser
*
* * Note: the method is manipulated in Overlay/templates/index.js - keep this in mind when making changes.
*
* @param {string} hash to load page with
* @return {void}
*/
pageload: function( hash )
// Unbind any previously attached resize handlers
$(window).off('resize');
// do not update content if it should be suppressed
if (broadcast.updateHashOnly) {
broadcast.updateHashOnly = false;
return;
}
// hash doesn't contain the first # character.
if( hash ) {
var hashParts = hash.split('&popover=');
var hashUrl = hashParts[0];
var popoverParam = '';
if (hashParts.length > 1) {
popoverParam = hashParts[1];
// in case the $ was encoded (e.g. when using copy&paste on urls in some browsers)
popoverParam = decodeURIComponent(popoverParam);
// revert special encoding from broadcast.propagateNewPopoverParameter()
popoverParam = popoverParam.replace(/\$/g, '%');
popoverParam = decodeURIComponent(popoverParam);
}
var pageUrlUpdated = (popoverParam == '' ||
(broadcast.currentHashUrl !== false && broadcast.currentHashUrl != hashUrl));
var popoverParamUpdated = (popoverParam != '' && hashUrl == broadcast.currentHashUrl);
if (broadcast.currentHashUrl === false) {
// new page load
pageUrlUpdated = true;
popoverParamUpdated = (popoverParam != '');
}
if (pageUrlUpdated || broadcast.forceReload) {
Piwik_Popover.close();
if (hashUrl != broadcast.currentHashUrl || broadcast.forceReload) {
// restore ajax loaded state
broadcast.loadAjaxContent(hashUrl);
// make sure the "Widgets & Dashboard" is deleted on reload
$('#dashboardSettings').remove();
$('#dashboardWidgetsArea').dashboard('destroy');
}
}
broadcast.currentHashUrl = hashUrl;
broadcast.currentPopoverParameter = popoverParam;
if (popoverParamUpdated && popoverParam == '') {
Piwik_Popover.close();
} else if (popoverParamUpdated) {
var popoverParamParts = popoverParam.split(':');
var handlerName = popoverParamParts[0];
popoverParamParts.shift();
var param = popoverParamParts.join(':');
if (typeof broadcast.popoverHandlers[handlerName] != 'undefined') {
broadcast.popoverHandlers[handlerName](param);
}
}
} else {
// start page
$('#content').empty();
}
},
/**
* propagateAjax -- update hash values then make ajax calls.
* example :
* 1) <a href="javascript:broadcast.propagateAjax('module=Referers&action=getKeywords')">View keywords report</a>
* 2) Main menu li also goes through this function.
*
* Will propagate your new value into the current hash string and make ajax calls.
*
* NOTE: this method will only make ajax call and replacing main content.
*
* @param {string} ajaxUrl querystring with parameters to be updated
* @param {boolean} disableHistory the hash change won't be available in the browser history
sgiehl
a validé
globalAjaxQueue.abort();
var params_vals = ajaxUrl.split("&");
for( var i=0; i<params_vals.length; i++ )
{
currentHashStr = broadcast.updateParamValue(params_vals[i],currentHashStr);
// if the module is not 'Goals', we specifically unset the 'idGoal' parameter
// this is to ensure that the URLs are clean (and that clicks on graphs work as expected - they are broken with the extra parameter)
if( action != 'goalReport' && action != 'ecommerceReport')
{
currentHashStr = broadcast.updateParamValue('idGoal=', currentHashStr);
}
// unset idDashboard if use doesn't display a dashboard
currentHashStr = broadcast.updateParamValue('idDashboard=', currentHashStr);
if (disableHistory)
{
var newLocation = window.location.href.split('#')[0] + '#' + currentHashStr;
// window.location.replace changes the current url without pushing it on the browser's history stack
window.location.replace(newLocation);
}
else
{
// Let history know about this new Hash and load it.
broadcast.forceReload = true;
$.history.load(currentHashStr);
}
},
/**
* propagateNewPage() -- update url value and load new page,
* Example:
* 1) We want to update idSite to both search query and hash then reload the page,
* 2) update period to both search query and hash then reload page.
*
* ** If you'd like to make ajax call with new values then use propagateAjax ** *
*
* Expecting:
* str = "param1=newVal1¶m2=newVal2";
*
* Currently being use by:
*
* handlePeriodClick,
* calendar.js,
* sites_selection.tpl
*
* NOTE: This method will refresh the page with new values.
*
* @param {string} str url with parameters to be updated
benakamoorthi
a validé
* @param {bool} showAjaxLoading whether to show the ajax loading gif or not.
benakamoorthi
a validé
propagateNewPage: function (str, showAjaxLoading)
{
// abort all existing ajax requests
sgiehl
a validé
globalAjaxQueue.abort();
benakamoorthi
a validé
if (typeof showAjaxLoading === 'undefined' || showAjaxLoading)
{
piwikHelper.showAjaxLoading();
}
// available in global scope
var currentSearchStr = window.location.search;
var oldUrl = currentSearchStr + currentHashStr;
for( var i=0; i<params_vals.length; i++ ) {
// update both the current search query and hash string
currentSearchStr = broadcast.updateParamValue(params_vals[i],currentSearchStr);
currentHashStr = broadcast.updateParamValue(params_vals[i],currentHashStr);
// Now load the new page.
var newUrl = currentSearchStr + currentHashStr;
if(oldUrl == newUrl) {
window.location.reload();
} else {
window.location.href = newUrl;
}
return false;
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
},
/*************************************************
*
* Broadcast Supporter Methods:
*
*************************************************/
/**
* updateParamValue(newParamValue,urlStr) -- Helping propagate functions to update value to url string.
* eg. I want to update date value to search query or hash query
*
* Expecting:
* urlStr : A Hash or search query string. e.g: module=whatever&action=index=date=yesterday
* newParamValue : A param value pair: e.g: date=2009-05-02
*
* Return module=whatever&action=index&date=2009-05-02
*
* @param {string} newParamValue param to be updated
* @param {string} urlStr url to be updated
* @return {string} urlStr with updated param
*/
updateParamValue: function(newParamValue, urlStr)
{
var p_v = newParamValue.split("=");
var paramName = p_v[0];
// if set 'idGoal=' then we remove the parameter from the URL automatically (rather than passing an empty value)
var paramValue = p_v[1];
if(paramValue == '')
{
newParamValue = '';
}
if( valFromUrl != '') {
// replacing current param=value to newParamValue;
valFromUrl = valFromUrl.replace(/\$/g, '\\$');
valFromUrl = valFromUrl.replace(/\./g, '\\.');
var regToBeReplace = new RegExp(paramName + '=' + valFromUrl, 'ig');
if(newParamValue == '') {
// if new value is empty remove leading &, aswell
regToBeReplace = new RegExp('[\&]?' + paramName + '=' + valFromUrl, 'ig');
}
urlStr = urlStr.replace( regToBeReplace, newParamValue );
} else if(newParamValue != '') {
urlStr += (urlStr == '') ? newParamValue : '&' + newParamValue;
}
/**
* Update the part after the second hash
*/
propagateNewPopoverParameter: function(handlerName, value)
{
var hash = broadcast.getHashFromUrl(window.location.href);
var hashParts = hash.split('&popover=');
var newHash = hashParts[0];
if (handlerName) {
var popover = handlerName + ':' + value;
// between jquery.history and different browser bugs, it's impossible to ensure
// that the parameter is en- and decoded the same number of times. in order to
// make sure it doesn't change, we have to manipulate the url encoding a bit.
popover = encodeURIComponent(popover);
popover = popover.replace(/%/g, '\$');
newHash = hashParts[0] + '&popover=' + popover;
}
window.location.href = 'index.php' + window.location.search + newHash;
},
/**
* Add a handler for the popover parameter
*/
addPopoverHandler: function(handlerName, callback) {
this.popoverHandlers[handlerName] = callback;
},
/**
* Loads the given url with ajax and replaces the content
*
* Note: the method is replaced in Overlay/templates/index.js - keep this in mind when making changes.
*
* @param {string} urlAjax url to load
* @return {Boolean}
*/
loadAjaxContent: function(urlAjax)
{
piwikMenu.activateMenu(
broadcast.getParamValue('module', urlAjax),
broadcast.getParamValue('action', urlAjax),
broadcast.getParamValue('idGoal', urlAjax) || broadcast.getParamValue('idDashboard', urlAjax)
);
piwikHelper.hideAjaxError('loadingError');
piwikHelper.showAjaxLoading();
$('#content').hide();
$("object").remove();
urlAjax = urlAjax.match(/^\?/) ? urlAjax : "?" + urlAjax;
function sectionLoaded(content)
{
benakamoorthi
a validé
// if content is whole HTML document, do not show it, otherwise recursive page load could occur
var htmlDocType = '<!DOCTYPE';
if (content.substring(0, htmlDocType.length) == htmlDocType)
{
return;
}
$('#content').html( content ).show();
piwikHelper.hideAjaxLoading();
sgiehl
a validé
type: 'POST',
url: urlAjax,
dataType: 'html',
async: true,
error: broadcast.customAjaxHandleError, // Callback when the request fails
success: sectionLoaded, // Callback when the request succeeds
data: new Object
};
sgiehl
a validé
globalAjaxQueue.push( $.ajax(ajaxRequest) );
return false;
},
/**
* Method to handle ajax errors
* @param {XMLHttpRequest} deferred
* @param {string} status
* @return {void}
*/
customAjaxHandleError: function (deferred, status)
{
piwikHelper.ajaxHandleError(deferred, status);
},
/**
* Return hash string if hash exists on address bar.
* else return false;
*
* @return {string|false}
*/
isHashExists: function()
{
if ( hashStr != "" ) {
return hashStr;
} else {
return false;
}
},
/**
* Get Hash from given url or from current location.
* return empty string if no hash present.
*
* @param {string} url
* @return {string} the hash part of the given url
*/
getHashFromUrl: function(url)
{
var hashStr = "";
// If url provided, give back the hash from url, else get hash from current address.
if( url && url.match('#') ) {
hashStr = url.substring(url.indexOf("#"),url.length);
}
else {
hashStr = decodeURIComponent(location.hash);
}
return hashStr;
},
/**
* Get search query from given url or from current location.
* return empty string if no search query present.
*
* @param {string} url
* @return {string} the query part of the given url
*/
getSearchFromUrl: function(url)
{
var searchStr = "";
// If url provided, give back the query string from url, else get query string from current address.
if( url && url.match(/\?/) ) {
searchStr = url.substring(url.indexOf("?"),url.length);
} else {
searchStr = location.search;
}
benakamoorthi
a validé
/**
* Returns all key-value pairs in query string of url.
*
* @param {string} url url to check. if undefined, null or empty, current url is used.
* @return {object} key value pair describing query string parameters
*/
getValuesFromUrl: function(url)
{
var searchString = this._removeHashFromUrl(url).split('?')[1] || '',
pairs = searchString.split('&');
var result = {};
for (var i = 0; i != pairs.length; ++i)
{
var pair = pairs[i].split('=');
result[pair[0]] = pair[1];
}
return result;
},
/**
* help to get param value for any given url string with provided param name
* if no url is provided, it will get param from current address.
* return:
* Empty String if param is not found.
*
* @param {string} param parameter to search for
* @param {string} url url to check
* @return {string} value of the given param within the given url
*/
getValueFromUrl: function (param, url)
{
benakamoorthi
a validé
var searchString = this._removeHashFromUrl(url);
},
/**
* NOTE: you should probably be using broadcast.getValueFromUrl instead!
*
* @param {string} param parameter to search for
* @param {string} url url to check
* @return {string} value of the given param within the hash part of the given url
*/
getValueFromHash: function(param, url)
{
if (hashStr.substr(0, 1) == '#') {
hashStr = hashStr.substr(1);
}
hashStr = hashStr.split('#')[0];
return broadcast.getParamValue(param,hashStr);
},
/**
* return value for the requested param, will return the first match.
* out side of this class should use getValueFromHash() or getValueFromUrl() instead.
* return:
* Empty String if param is not found.
*
* @param {string} param parameter to search for
* @param {string} url url to check
* @return {string} value of the given param within the given url
*/
getParamValue: function (param, url)
{
var startStr = url.indexOf(param);
if( startStr >= 0 ) {
var endStr = url.indexOf("&", startStr);
if( endStr == -1 ) {
endStr = url.length;
}
var value = url.substring(startStr + param.length +1,endStr);
// sanitize values
return value;
} else {
return '';
},
/**
* Returns the hash without the starting #
* @return {string} hash part of the current url
*/
getHash: function ()
{
return broadcast.getHashFromUrl().replace(/^#/, '').split('#')[0];
benakamoorthi
a validé
},
/**
* Removes the hash portion of a URL and returns the rest.
*
* @param {string} url
* @return {string} url w/o hash
*/
_removeHashFromUrl: function(url)
{
var searchString = '';
if( url ) {
var urlParts = url.split('#');
searchString = urlParts[0];
} else {
searchString = location.search;
}
return searchString;
}
};