add icons for Character groups

This commit is contained in:
coderkun 2014-04-29 14:18:04 +02:00
commit 2d9a41a5fe
3461 changed files with 594457 additions and 0 deletions

View file

@ -0,0 +1,450 @@
/*!
* Piwik - Web Analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
/**
* global ajax queue
*
* @type {Array} array holding XhrRequests with automatic cleanup
*/
var globalAjaxQueue = [];
globalAjaxQueue.active = 0;
/**
* Removes all finished requests from the queue.
*
* @return {void}
*/
globalAjaxQueue.clean = function () {
for (var i = this.length; i--;) {
if (!this[i] || this[i].readyState == 4) {
this.splice(i, 1);
}
}
};
/**
* Extend Array.push with automatic cleanup for finished requests
*
* @return {Object}
*/
globalAjaxQueue.push = function () {
this.active += arguments.length;
// cleanup ajax queue
this.clean();
// call original array push
return Array.prototype.push.apply(this, arguments);
};
/**
* Extend with abort function to abort all queued requests
*
* @return {void}
*/
globalAjaxQueue.abort = function () {
// abort all queued requests
for (var i = this.length; i--;) {
this[i] && this[i].abort && this[i].abort(); // abort if possible
}
// remove all elements from array
this.splice(0, this.length);
this.active = 0;
};
/**
* Global ajax helper to handle requests within piwik
*
* @type {Object}
* @constructor
*/
function ajaxHelper() {
/**
* Format of response
* @type {String}
*/
this.format = 'json';
/**
* Should ajax request be asynchronous
* @type {Boolean}
*/
this.async = true;
/**
* Callback function to be executed on success
*/
this.callback = function () {};
/**
* Use this.callback if an error is returned
* @type {Boolean}
*/
this.useRegularCallbackInCaseOfError = false;
/**
* Callback function to be executed on error
*/
this.errorCallback = this.defaultErrorCallback;
/**
* Params to be passed as GET params
* @type {Object}
* @see ajaxHelper._mixinDefaultGetParams
*/
this.getParams = {};
/**
* Base URL used in the AJAX request. Can be set by setUrl.
* @type {String}
* @see ajaxHelper.setUrl
*/
this.getUrl = 'index.php?';
/**
* Params to be passed as GET params
* @type {Object}
* @see ajaxHelper._mixinDefaultPostParams
*/
this.postParams = {};
/**
* Element to be displayed while loading
* @type {String}
*/
this.loadingElement = null;
/**
* Element to be displayed on error
* @type {String}
*/
this.errorElement = '#ajaxError';
/**
* Handle for current request
* @type {XMLHttpRequest}
*/
this.requestHandle = null;
/**
* Adds params to the request.
* If params are given more then once, the latest given value is used for the request
*
* @param {object} params
* @param {string} type type of given parameters (POST or GET)
* @return {void}
*/
this.addParams = function (params, type) {
if (typeof params == 'string') {
params = broadcast.getValuesFromUrl(params);
}
for (var key in params) {
if(type.toLowerCase() == 'get') {
this.getParams[key] = params[key];
} else if(type.toLowerCase() == 'post') {
this.postParams[key] = params[key];
}
}
};
/**
* Sets the base URL to use in the AJAX request.
*
* @param {string} url
*/
this.setUrl = function (url) {
this.addParams(broadcast.getValuesFromUrl(url), 'GET');
};
/**
* Gets this helper instance ready to send a bulk request. Each argument to this
* function is a single request to use.
*/
this.setBulkRequests = function () {
var urls = [];
for (var i = 0; i != arguments.length; ++i) {
urls.push($.param(arguments[i]));
}
this.addParams({
module: 'API',
method: 'API.getBulkRequest',
urls: urls,
format: 'json'
}, 'post');
};
/**
* Sets the callback called after the request finishes
*
* @param {function} callback Callback function
* @return {void}
*/
this.setCallback = function (callback) {
this.callback = callback;
};
/**
* Set that the callback passed to setCallback() should be used if an application error (i.e. an
* Exception in PHP) is returned.
*/
this.useCallbackInCaseOfError = function () {
this.useRegularCallbackInCaseOfError = true;
};
/**
* Set callback to redirect on success handler
* &update=1(+x) will be appended to the current url
*
* @param {object} [params] to modify in redirect url
* @return {void}
*/
this.redirectOnSuccess = function (params) {
this.setCallback(function() {
piwikHelper.redirect(params);
});
};
/**
* Sets the callback called in case of an error within the request
*
* @param {function} callback Callback function
* @return {void}
*/
this.setErrorCallback = function (callback) {
this.errorCallback = callback;
};
/**
* error callback to use by default
*
* @param deferred
* @param status
*/
this.defaultErrorCallback = function(deferred, status)
{
// do not display error message if request was aborted
if(status == 'abort') {
return;
}
$('#loadingError').show();
setTimeout( function(){
$('#loadingError').fadeOut('slow');
}, 2000);
};
/**
* Sets the response format for the request
*
* @param {string} format response format (e.g. json, html, ...)
* @return {void}
*/
this.setFormat = function (format) {
this.format = format;
};
/**
* Set the div element to show while request is loading
*
* @param {String} [element] selector for the loading element
*/
this.setLoadingElement = function (element) {
if (!element) {
element = '#ajaxLoadingDiv';
}
this.loadingElement = element;
};
/**
* Set the div element to show on error
*
* @param {String} element selector for the error element
*/
this.setErrorElement = function (element) {
if (!element) {
return;
}
this.errorElement = element;
};
/**
* Send the request
* @param {Boolean} [sync] indicates if the request should be synchronous (defaults to false)
* @return {void}
*/
this.send = function (sync) {
if (sync === true) {
this.async = false;
}
if ($(this.errorElement).length) {
$(this.errorElement).hide();
}
if (this.loadingElement) {
$(this.loadingElement).fadeIn();
}
this.requestHandle = this._buildAjaxCall();
globalAjaxQueue.push(this.requestHandle);
};
/**
* Aborts the current request if it is (still) running
* @return {void}
*/
this.abort = function () {
if (this.requestHandle && typeof this.requestHandle.abort == 'function') {
this.requestHandle.abort();
this.requestHandle = null;
}
};
/**
* Builds and sends the ajax requests
* @return {XMLHttpRequest}
* @private
*/
this._buildAjaxCall = function () {
var that = this;
var parameters = this._mixinDefaultGetParams(this.getParams);
var url = this.getUrl;
if (url[url.length - 1] != '?') {
url += '&';
}
// we took care of encoding &segment properly already, so we don't use $.param for it ($.param URL encodes the values)
if(parameters['segment']) {
url += 'segment=' + parameters['segment'] + '&';
delete parameters['segment'];
}
if(parameters['date']) {
url += 'date=' + decodeURIComponent(parameters['date']) + '&';
delete parameters['date'];
}
url += $.param(parameters);
var ajaxCall = {
type: 'POST',
async: this.async !== false,
url: url,
dataType: this.format || 'json',
error: this.errorCallback,
success: function (response) {
if (that.loadingElement) {
$(that.loadingElement).hide();
}
if (response && response.result == 'error' && !that.useRegularCallbackInCaseOfError) {
var placeAt = null;
var type = 'toast';
if ($(that.errorElement).length && response.message) {
$(that.errorElement).show();
placeAt = that.errorElement;
type = null;
}
if (response.message) {
var UI = require('piwik/UI');
var notification = new UI.Notification();
notification.show(response.message, {
placeat: placeAt,
context: 'error',
type: type,
id: 'ajaxHelper'
});
notification.scrollToNotification();
}
} else {
that.callback(response);
}
--globalAjaxQueue.active;
var piwik = window.piwik;
if (piwik
&& piwik.ajaxRequestFinished
) {
piwik.ajaxRequestFinished();
}
},
data: this._mixinDefaultPostParams(this.postParams)
};
return $.ajax(ajaxCall);
};
/**
* Mixin the default parameters to send as POST
*
* @param {object} params parameter object
* @return {object}
* @private
*/
this._mixinDefaultPostParams = function (params) {
var defaultParams = {
token_auth: piwik.token_auth
};
for (var index in defaultParams) {
if (!params[index]) {
params[index] = defaultParams[index];
}
}
return params;
};
/**
* Mixin the default parameters to send as GET
*
* @param {object} params parameter object
* @return {object}
* @private
*/
this._mixinDefaultGetParams = function (params) {
var defaultParams = {
idSite: piwik.idSite || broadcast.getValueFromUrl('idSite'),
period: piwik.period || broadcast.getValueFromUrl('period'),
segment: broadcast.getValueFromHash('segment', window.location.href.split('#')[1])
};
// never append token_auth to url
if (params.token_auth) {
params.token_auth = null;
delete params.token_auth;
}
for (var key in defaultParams) {
if (!params[key] && !this.postParams[key] && defaultParams[key]) {
params[key] = defaultParams[key];
}
}
// handle default date & period if not already set
if (!params.date && !this.postParams.date) {
params.date = piwik.currentDateString || broadcast.getValueFromUrl('date');
if (params.period == 'range' && piwik.currentDateString) {
params.date = piwik.startDateString + ',' + params.date;
}
}
return params;
};
return this;
}

View file

@ -0,0 +1,464 @@
/*!
* Piwik - Web Analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
function _pk_translate(translationStringId, values) {
function sprintf (translation, values) {
var index = 0;
return (translation+'').replace(/(%(.\$)?s+)/g, function(match, number) {
var replaced = match;
if (match != '%s') {
index = parseInt(match.substr(1, 1)) - 1;
}
if (typeof values[index] != 'undefined') {
replaced = values[index];
}
index++;
return replaced;
});
}
if( typeof(piwik_translations[translationStringId]) != 'undefined' ){
var translation = piwik_translations[translationStringId];
if (typeof values != 'undefined' && values && values.length) {
return sprintf(translation, values);
}
return translation;
}
return "The string "+translationStringId+" was not loaded in javascript. Make sure it is added in the Translate.getClientSideTranslationKeys hook.";
}
var piwikHelper = {
htmlDecode: function(value)
{
return $('<div/>').html(value).text();
},
/**
* a nice cross-browser logging function
*/
log: function() {
try {
console.log.apply(console, arguments); // Firefox, Chrome
} catch (e) {
try {
opera.postError.apply(opera, arguments); // Opera
} catch (f) {
// don't alert as log is not considered to be important enough
// (as opposed to piwikHelper.error)
//alert(Array.prototype.join.call(arguments, ' ')); // MSIE
}
}
},
error: function() {
try {
console.error.apply(console, arguments); // Firefox, Chrome
} catch (e) {
try {
opera.postError.apply(opera, arguments); // Opera
} catch (f) {
alert(Array.prototype.join.call(arguments, ' ')); // MSIE
}
}
},
htmlEntities: function(value)
{
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]];
for(var item in findReplace) {
value = value.replace(findReplace[item][0], findReplace[item][1]);
}
return value;
},
/**
* Add break points to a string so that it can be displayed more compactly
*/
addBreakpoints: function(text, breakpointMarkup)
{
return text.replace(/([\/&=?\.%#:_-])/g, '$1' +
(typeof breakpointMarkup == 'undefined' ? '<wbr>&#8203;' : breakpointMarkup));
// &#8203; is for internet explorer
},
/**
* Add breakpoints to a URL
* urldecodes and encodes htmlentities to display utf8 urls without XSS vulnerabilities
*/
addBreakpointsToUrl: function(url)
{
try {
url = decodeURIComponent(url);
} catch (e) {
// might throw "URI malformed"
}
url = piwikHelper.addBreakpoints(url, '|||');
url = $(document.createElement('p')).text(url).html();
url = url.replace(/\|\|\|/g, '<wbr />&#8203;'); // &#8203; is for internet explorer
return url;
},
/**
* As we still have a lot of old jQuery code and copy html from node to node we sometimes have to trigger the
* compiling of angular components manually.
*
* @param selector
*/
compileAngularComponents: function (selector) {
var $element = $(selector);
angular.element(document).injector().invoke(function($compile) {
var scope = angular.element($element).scope();
$compile($element)(scope);
});
},
/**
* Displays a Modal dialog. Text will be taken from the DOM node domSelector.
* Given callback handles will be mapped to the buttons having a role attriute
*
* Dialog will be closed when a button is clicked and callback handle will be
* called, if one was given for the clicked role
*
* @param {string} domSelector domSelector for modal window
* @param {object} handles callback functions for available roles
* @return {void}
*/
modalConfirm: function( domSelector, handles )
{
var domElem = $(domSelector);
var buttons = [];
$('[role]', domElem).each(function(){
var role = $(this).attr('role');
var title = $(this).attr('title');
var text = $(this).val();
var button = {text: text};
if(typeof handles[role] == 'function') {
button.click = function(){$(this).dialog("close"); handles[role].apply()};
} else {
button.click = function(){$(this).dialog("close");};
}
if (title) {
button.title = title;
}
buttons.push(button);
$(this).hide();
});
domElem.dialog({
resizable: false,
modal: true,
buttons: buttons,
width: 650,
position: ['center', 90]
});
},
getQueryStringWithParametersModified: function (queryString, newParameters) {
if (queryString != '') {
var r, i, keyvalue, keysvalues = newParameters.split('&');
var appendUrl = '';
for (i = 0; i < keysvalues.length; i++) {
keyvalue = keysvalues[i].split('=');
r = new RegExp('(^|[?&])' + keyvalue[0] + '=[^&]*');
queryString = queryString.replace(r, '');
// empty value, eg. &segment=, we remove the parameter from URL entirely
if (keyvalue[1].length == 0) {
continue;
}
appendUrl += '&' + keyvalue[0] + '=' + keyvalue[1];
}
queryString += appendUrl;
if (queryString[0] == '&') {
queryString = '?' + queryString.substring(1);
}
} else {
queryString = '?' + newParameters;
}
return queryString;
},
/**
* Returns the current query string with the given parameters modified
* @param {String} newparams parameters to be modified
* @return {String}
*/
getCurrentQueryStringWithParametersModified: function(newparams)
{
var queryString = String(window.location.search);
if (newparams) {
queryString = this.getQueryStringWithParametersModified(queryString, newparams);
}
return String(window.location.pathname) + queryString;
},
/**
* Given param1=v1&param2=k2
* returns: { "param1": "v1", "param2": "v2" }
*
* @param query string
* @return {Object}
*/
getArrayFromQueryString: function (query) {
var params = {};
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var keyValue = vars[i].split("=");
// Jquery will urlencode these, but we wish to keep the current raw value
// use case: &segment=visitorId%3D%3Dabc...
params[keyValue[0]] = decodeURIComponent(keyValue[1]);
}
return params;
},
/**
* Returns query string for an object of key,values
* Note: we don't use $.param from jquery as it doesn't return array values the PHP way (returns a=v1&a=v2 instead of a[]=v1&a[]=v2)
* Example:
* piwikHelper.getQueryStringFromParameters({"a":"va","b":["vb","vc"],"c":1})
* Returns:
* a=va&b[]=vb&b[]=vc&c=1
* @param {object} parameters
* @return {string}
*/
getQueryStringFromParameters: function(parameters)
{
var queryString = '';
if(!parameters || parameters.length==0) {
return queryString;
}
for(var name in parameters) {
var value = parameters[name];
if(typeof value == 'object') {
for(var i in value) {
queryString += name + '[]=' + value[i] + '&';
}
} else {
queryString += name + '=' + value + '&';
}
}
return queryString.substring(0, queryString.length-1);
},
/**
* Displays the given ajax error message within the given id element
* @param {string} message error message
* @param {string} errorDivID id of the domNode (defaults to ajaxError)
* @return {void}
*/
showAjaxError: function( message, errorDivID )
{
errorDivID = errorDivID || 'ajaxError';
$('#'+errorDivID).html(message).show();
},
/**
* Hides the error message with the given id
* @param {string} [errorDivID] id of the domNode (defaults to ajaxError)
* @return {void}
*/
hideAjaxError: function(errorDivID)
{
errorDivID = errorDivID || 'ajaxError';
$('#'+errorDivID).hide();
},
/**
* Shows the loading message with the given Id
* @param {string} [loadingDivID] id of the domNode (defaults to ajaxLoading)
* @return {void}
*/
showAjaxLoading: function(loadingDivID)
{
loadingDivID = loadingDivID || 'ajaxLoadingDiv';
$('#'+loadingDivID).show();
},
/**
* Hides the loading message with the given id
* @param {string} [loadingDivID] id of the domNode (defaults to ajaxLoading)
* @return {void}
*/
hideAjaxLoading: function(loadingDivID)
{
loadingDivID = loadingDivID || 'ajaxLoadingDiv';
$('#'+loadingDivID).hide();
},
/**
* Reloads the page after the given period
* @param {int} timeoutPeriod
* @return void
*/
refreshAfter: function(timeoutPeriod)
{
if(timeoutPeriod == 0) {
location.reload();
} else {
setTimeout("location.reload();",timeoutPeriod);
}
},
redirect: function (params) {
// add updated=X to the URL so that a "Your changes have been saved" message is displayed
if (typeof params == 'object') {
params = this.getQueryStringFromParameters(params);
}
var urlToRedirect = this.getCurrentQueryStringWithParametersModified(params);
var updatedUrl = new RegExp('&updated=([0-9]+)');
var updatedCounter = updatedUrl.exec(urlToRedirect);
if (!updatedCounter) {
urlToRedirect += '&updated=1';
} else {
updatedCounter = 1 + parseInt(updatedCounter[1]);
urlToRedirect = urlToRedirect.replace(new RegExp('(&updated=[0-9]+)'), '&updated=' + updatedCounter);
}
var currentHashStr = window.location.hash;
if(currentHashStr.length > 0) {
urlToRedirect += currentHashStr;
}
this.redirectToUrl(urlToRedirect);
},
/**
* Redirect to the given url
* @param {string} url
*/
redirectToUrl: function(url)
{
window.location = url;
},
/**
* Scrolls the window to the jquery element 'elem'
* if the top of the element is not currently visible on screen
* @param {string} elem Selector for the DOM node to scroll to, eg. '#myDiv'
* @param {int} [time] Specifies the duration of the animation in ms
* @param {boolean} [forceScroll] Whether to force scroll to an element.
* @return {void}
*/
lazyScrollTo: function(elem, time, forceScroll)
{
var elemTop = $(elem).offset().top;
// only scroll the page if the graph is not visible
if (elemTop < $(window).scrollTop()
|| elemTop > $(window).scrollTop()+$(window).height()
|| forceScroll
) {
// scroll the page smoothly to the graph
$.scrollTo(elem, time);
}
},
/**
* Returns the filtered/converted content of a textarea to be used for api requests
* @param {string} textareaContent
* @return {string}
*/
getApiFormatTextarea: function (textareaContent)
{
if(typeof textareaContent == 'undefined') {
return '';
}
return textareaContent.trim().split("\n").join(',');
}
};
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g,"");
};
/**
* Returns true if the event keypress passed in parameter is the ENTER key
* @param {Event} e current window event
* @return {boolean}
*/
function isEnterKey(e)
{
return (window.event?window.event.keyCode:e.which)==13;
}
// workarounds
(function($){
try {
// this code is not vital, so we make sure any errors are ignored
//--------------------------------------
//
// monkey patch that works around bug in arc function of some browsers where
// nothing gets drawn if angles are 2 * PI apart and in counter-clockwise direction.
// affects some versions of chrome & IE 8
//
//--------------------------------------
var oldArc = CanvasRenderingContext2D.prototype.arc;
CanvasRenderingContext2D.prototype.arc = function(x, y, r, sAngle, eAngle, clockwise) {
if (Math.abs(eAngle - sAngle - Math.PI * 2) < 0.000001 && !clockwise)
eAngle -= 0.000001;
oldArc.call(this, x, y, r, sAngle, eAngle, clockwise);
};
//--------------------------------------
//
// Array.reduce is not available in IE8 but used in Jqplot
//
//--------------------------------------
if ('function' !== typeof Array.prototype.reduce) {
Array.prototype.reduce = function(callback, opt_initialValue){
'use strict';
if (null === this || 'undefined' === typeof this) {
// At the moment all modern browsers, that support strict mode, have
// native implementation of Array.prototype.reduce. For instance, IE8
// does not support strict mode, so this check is actually useless.
throw new TypeError(
'Array.prototype.reduce called on null or undefined');
}
if ('function' !== typeof callback) {
throw new TypeError(callback + ' is not a function');
}
var index, value,
length = this.length >>> 0,
isValueSet = false;
if (1 < arguments.length) {
value = opt_initialValue;
isValueSet = true;
}
for (index = 0; length > index; ++index) {
if (this.hasOwnProperty(index)) {
if (isValueSet) {
value = callback(value, this[index], index, this);
}
else {
value = this[index];
isValueSet = true;
}
}
}
if (!isValueSet) {
throw new TypeError('Reduce of empty array with no initial value');
}
return value;
};
}
} catch (e) {}
}(jQuery));