mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #2875 from guerler/remote_chart_plugins
Link charts to external repo, adjust interface
This commit is contained in:
@@ -255,19 +255,13 @@ define(['utils/utils', 'utils/deferred', 'mvc/ui/ui-misc', 'mvc/form/form-view',
|
||||
title : 'Requirements',
|
||||
tooltip : 'Display tool requirements',
|
||||
onclick : function() {
|
||||
if (!this.visible || self.portlet.collapsed ) {
|
||||
this.visible = true;
|
||||
if ( !this.requirements_visible || self.portlet.collapsed ) {
|
||||
this.requirements_visible = true;
|
||||
self.portlet.expand();
|
||||
self.message.update({
|
||||
persistent : true,
|
||||
message : self._templateRequirements(options),
|
||||
status : 'info'
|
||||
});
|
||||
self.message.update( { persistent : true, message : self._templateRequirements( options ), status : 'info' } );
|
||||
} else {
|
||||
this.visible = false;
|
||||
self.message.update({
|
||||
message : ''
|
||||
});
|
||||
this.requirements_visible = false;
|
||||
self.message.update( { message : '' } );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -223,9 +223,11 @@ define( [ 'utils/utils' ], function( Utils ) {
|
||||
visible : true,
|
||||
tag : ''
|
||||
}).set( options );
|
||||
this.collection = new Backbone.Collection();
|
||||
this.setElement( $( '<div/>' ).append( this.$root = $( '<div/>' ).append( this.$icon = $( '<i/>' ) )
|
||||
.append( this.$title = $( '<span/>' ) ) ) );
|
||||
this.listenTo( this.model, 'change', this.render, this );
|
||||
this.listenTo( this.collection, 'change add remove reset', this.render, this );
|
||||
this.render();
|
||||
},
|
||||
|
||||
@@ -237,7 +239,7 @@ define( [ 'utils/utils' ], function( Utils ) {
|
||||
.addClass( options.cls )
|
||||
.attr( 'id', options.id )
|
||||
.css( { float : options.floating,
|
||||
display : options.visible ? 'block' : 'none' } );
|
||||
display : options.visible && this.collection.where( { visible: true } ).length > 0 ? 'block' : 'none' } );
|
||||
this.$root.addClass( 'root button dropdown-toggle' )
|
||||
.attr( 'data-toggle', 'dropdown' )
|
||||
.tooltip( { title: options.tooltip, placement: 'bottom' } )
|
||||
@@ -249,40 +251,46 @@ define( [ 'utils/utils' ], function( Utils ) {
|
||||
this.$icon.removeClass().addClass( 'icon fa' ).addClass( options.icon );
|
||||
this.$title.removeClass().addClass( 'title' ).html( options.title );
|
||||
options.icon && options.title && this.$icon.addClass( 'ui-margin-right' );
|
||||
this.$menu && this.$menu.remove();
|
||||
if ( this.collection.length > 0 ) {
|
||||
this.$menu = $( '<ul/>' ).addClass( 'menu dropdown-menu' )
|
||||
.addClass( 'pull-' + self.model.get( 'pull' ) )
|
||||
.attr( 'role', 'menu' );
|
||||
this.$el.append( this.$menu );
|
||||
}
|
||||
this.collection.each( function( submodel ) {
|
||||
var suboptions = submodel.attributes;
|
||||
if ( suboptions.visible ) {
|
||||
var $link = $( '<a/>' ).addClass( 'dropdown-item' )
|
||||
.attr( { href : suboptions.href, target : suboptions.target } )
|
||||
.append( $( '<i/>' ).addClass( 'fa' )
|
||||
.addClass( suboptions.icon )
|
||||
.css( 'display', suboptions.icon ? 'inline-block' : 'none' ) )
|
||||
.append( suboptions.title )
|
||||
.on( 'click', function( e ) {
|
||||
if ( suboptions.onclick ) {
|
||||
e.preventDefault();
|
||||
suboptions.onclick();
|
||||
}
|
||||
} );
|
||||
self.$menu.append( $( '<li/>' ).append( $link ) );
|
||||
suboptions.divider && self.$menu.append( $( '<li/>' ).addClass( 'divider' ) );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Add a new menu item */
|
||||
addMenu: function ( options ) {
|
||||
var options = Utils.merge( options, {
|
||||
this.collection.add( Utils.merge( options, {
|
||||
title : '',
|
||||
target : '',
|
||||
href : '',
|
||||
onclick : null,
|
||||
divider : false,
|
||||
visible : true,
|
||||
icon : null,
|
||||
cls : 'button-menu btn-group'
|
||||
});
|
||||
if ( !this.$menu ) {
|
||||
this.$menu = $( '<ul/>' ).addClass( 'menu dropdown-menu' )
|
||||
.addClass( 'pull-' + this.model.get( 'pull' ) )
|
||||
.attr( 'role', 'menu' );
|
||||
this.$el.append( this.$menu );
|
||||
}
|
||||
var $link = $( '<a/>' ).addClass( 'dropdown-item' )
|
||||
.attr( { href : options.href,
|
||||
target : options.target } )
|
||||
.append( $( '<i/>' ).addClass( 'fa' )
|
||||
.addClass( options.icon )
|
||||
.css( 'display', options.icon ? 'inline-block' : 'none' ) )
|
||||
.append( options.title )
|
||||
.on( 'click', function( e ) {
|
||||
if ( options.onclick ) {
|
||||
e.preventDefault();
|
||||
options.onclick();
|
||||
}
|
||||
} );
|
||||
this.$menu.append( $( '<li/>' ).append( $link ) );
|
||||
options.divider && this.$menu.append( $( '<li/>' ).addClass( 'divider' ) );
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -2,286 +2,297 @@
|
||||
* Galaxy utilities comprises small functions, which at this point
|
||||
* do not require their own classes/files
|
||||
*/
|
||||
define( [], function() {
|
||||
|
||||
// dependencies
|
||||
define([], function() {
|
||||
/** Builds a basic iframe */
|
||||
function iframe( src ) {
|
||||
return '<iframe src="' + src + '" frameborder="0" style="width: 100%; height: 100%;"/>';
|
||||
}
|
||||
|
||||
/** Builds a basic iframe
|
||||
*/
|
||||
function iframe( src ) {
|
||||
return '<iframe src="' + src + '" frameborder="0" style="width: 100%; height: 100%;"/>';
|
||||
}
|
||||
|
||||
/** Traverse through json
|
||||
*/
|
||||
function deepeach( dict, callback ) {
|
||||
for( var i in dict ) {
|
||||
var d = dict[ i ];
|
||||
if( _.isObject( d ) ) {
|
||||
var new_dict = callback( d );
|
||||
new_dict && ( dict[ i ] = new_dict );
|
||||
deepeach( d, callback );
|
||||
/** Traverse through json */
|
||||
function deepeach( dict, callback ) {
|
||||
for( var i in dict ) {
|
||||
var d = dict[ i ];
|
||||
if( _.isObject( d ) ) {
|
||||
var new_dict = callback( d );
|
||||
new_dict && ( dict[ i ] = new_dict );
|
||||
deepeach( d, callback );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Clone */
|
||||
function clone( obj ) {
|
||||
return JSON.parse( JSON.stringify( obj ) || null );
|
||||
}
|
||||
/** Identifies urls and replaces them with anchors */
|
||||
function linkify( inputText ) {
|
||||
var replacedText, replacePattern1, replacePattern2, replacePattern3;
|
||||
|
||||
/**
|
||||
* Check if a string is a json string
|
||||
* @param{String} text - Content to be validated
|
||||
*/
|
||||
function isJSON(text) {
|
||||
return /^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
|
||||
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
||||
replace(/(?:^|:|,)(?:\s*\[)+/g, ''));
|
||||
};
|
||||
// URLs starting with http://, https://, or ftp://
|
||||
replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
|
||||
replacedText = inputText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');
|
||||
|
||||
/**
|
||||
* Sanitize/escape a string
|
||||
* @param{String} content - Content to be sanitized
|
||||
*/
|
||||
function sanitize(content) {
|
||||
return $('<div/>').text(content).html();
|
||||
};
|
||||
// URLs starting with "www." (without // before it, or it'd re-link the ones done above).
|
||||
replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
|
||||
replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');
|
||||
|
||||
/**
|
||||
* Checks if a value or list of values is `empty`
|
||||
* usually used for selectable options
|
||||
* @param{String} value - Value or list to be validated
|
||||
*/
|
||||
function isEmpty ( value ) {
|
||||
if ( !( value instanceof Array ) ) {
|
||||
value = [ value ];
|
||||
// Change email addresses to mailto:: links.
|
||||
replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim;
|
||||
replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');
|
||||
|
||||
return replacedText;
|
||||
}
|
||||
if ( value.length === 0 ) {
|
||||
return true;
|
||||
|
||||
/** Clone */
|
||||
function clone( obj ) {
|
||||
return JSON.parse( JSON.stringify( obj ) || null );
|
||||
}
|
||||
for( var i in value ) {
|
||||
if ( [ '__null__', '__undefined__', null, undefined ].indexOf( value[ i ] ) > -1 ) {
|
||||
|
||||
/**
|
||||
* Check if a string is a json string
|
||||
* @param{String} text - Content to be validated
|
||||
*/
|
||||
function isJSON(text) {
|
||||
return /^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
|
||||
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
||||
replace(/(?:^|:|,)(?:\s*\[)+/g, ''));
|
||||
};
|
||||
|
||||
/**
|
||||
* Sanitize/escape a string
|
||||
* @param{String} content - Content to be sanitized
|
||||
*/
|
||||
function sanitize(content) {
|
||||
return $('<div/>').text(content).html();
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a value or list of values is `empty`
|
||||
* usually used for selectable options
|
||||
* @param{String} value - Value or list to be validated
|
||||
*/
|
||||
function isEmpty ( value ) {
|
||||
if ( !( value instanceof Array ) ) {
|
||||
value = [ value ];
|
||||
}
|
||||
if ( value.length === 0 ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert list to pretty string
|
||||
* @param{String} lst - List of strings to be converted in human readable list sentence
|
||||
*/
|
||||
function textify( lst ) {
|
||||
if ( $.isArray( lst ) ) {
|
||||
var lst = lst.toString().replace( /,/g, ', ' );
|
||||
var pos = lst.lastIndexOf( ', ' );
|
||||
if ( pos != -1 ) {
|
||||
lst = lst.substr( 0, pos ) + ' or ' + lst.substr( pos + 2 );
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Request handler for GET
|
||||
* @param{String} url - Url request is made to
|
||||
* @param{Function} success - Callback on success
|
||||
* @param{Function} error - Callback on error
|
||||
* @param{Boolean} cache - Use cached data if available
|
||||
*/
|
||||
function get (options) {
|
||||
top.__utils__get__ = top.__utils__get__ || {};
|
||||
var cache_key = JSON.stringify( options );
|
||||
if (options.cache && top.__utils__get__[cache_key]) {
|
||||
options.success && options.success(top.__utils__get__[cache_key]);
|
||||
window.console.debug('utils.js::get() - Fetching from cache [' + options.url + '].');
|
||||
} else {
|
||||
request({
|
||||
url : options.url,
|
||||
data : options.data,
|
||||
success : function(response) {
|
||||
top.__utils__get__[cache_key] = response;
|
||||
options.success && options.success(response);
|
||||
},
|
||||
error : function(response, status) {
|
||||
options.error && options.error(response, status);
|
||||
for( var i in value ) {
|
||||
if ( [ '__null__', '__undefined__', null, undefined ].indexOf( value[ i ] ) > -1 ) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Request handler
|
||||
* @param{String} method - Request method ['GET', 'POST', 'DELETE', 'PUT']
|
||||
* @param{String} url - Url request is made to
|
||||
* @param{Object} data - Data send to url
|
||||
* @param{Function} success - Callback on success
|
||||
* @param{Function} error - Callback on error
|
||||
*/
|
||||
function request (options) {
|
||||
// prepare ajax
|
||||
var ajaxConfig = {
|
||||
contentType : 'application/json',
|
||||
type : options.type || 'GET',
|
||||
data : options.data || {},
|
||||
url : options.url
|
||||
}
|
||||
// encode data into url
|
||||
if ( ajaxConfig.type == 'GET' || ajaxConfig.type == 'DELETE' ) {
|
||||
if ( !$.isEmptyObject(ajaxConfig.data) ) {
|
||||
ajaxConfig.url += ajaxConfig.url.indexOf('?') == -1 ? '?' : '&';
|
||||
ajaxConfig.url += $.param(ajaxConfig.data, true);
|
||||
}
|
||||
ajaxConfig.data = null;
|
||||
} else {
|
||||
ajaxConfig.dataType = 'json';
|
||||
ajaxConfig.url = ajaxConfig.url;
|
||||
ajaxConfig.data = JSON.stringify(ajaxConfig.data);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// make request
|
||||
$.ajax(ajaxConfig).done(function(response) {
|
||||
if (typeof response === 'string') {
|
||||
/**
|
||||
* Convert list to pretty string
|
||||
* @param{String} lst - List of strings to be converted in human readable list sentence
|
||||
*/
|
||||
function textify( lst ) {
|
||||
if ( $.isArray( lst ) ) {
|
||||
var lst = lst.toString().replace( /,/g, ', ' );
|
||||
var pos = lst.lastIndexOf( ', ' );
|
||||
if ( pos != -1 ) {
|
||||
lst = lst.substr( 0, pos ) + ' or ' + lst.substr( pos + 2 );
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Request handler for GET
|
||||
* @param{String} url - Url request is made to
|
||||
* @param{Function} success - Callback on success
|
||||
* @param{Function} error - Callback on error
|
||||
* @param{Boolean} cache - Use cached data if available
|
||||
*/
|
||||
function get (options) {
|
||||
top.__utils__get__ = top.__utils__get__ || {};
|
||||
var cache_key = JSON.stringify( options );
|
||||
if (options.cache && top.__utils__get__[cache_key]) {
|
||||
options.success && options.success(top.__utils__get__[cache_key]);
|
||||
window.console.debug('utils.js::get() - Fetching from cache [' + options.url + '].');
|
||||
} else {
|
||||
request({
|
||||
url : options.url,
|
||||
data : options.data,
|
||||
success : function(response) {
|
||||
top.__utils__get__[cache_key] = response;
|
||||
options.success && options.success(response);
|
||||
},
|
||||
error : function(response, status) {
|
||||
options.error && options.error(response, status);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Request handler
|
||||
* @param{String} method - Request method ['GET', 'POST', 'DELETE', 'PUT']
|
||||
* @param{String} url - Url request is made to
|
||||
* @param{Object} data - Data send to url
|
||||
* @param{Function} success - Callback on success
|
||||
* @param{Function} error - Callback on error
|
||||
*/
|
||||
function request (options) {
|
||||
// prepare ajax
|
||||
var ajaxConfig = {
|
||||
contentType : 'application/json',
|
||||
type : options.type || 'GET',
|
||||
data : options.data || {},
|
||||
url : options.url
|
||||
}
|
||||
// encode data into url
|
||||
if ( ajaxConfig.type == 'GET' || ajaxConfig.type == 'DELETE' ) {
|
||||
if ( !$.isEmptyObject(ajaxConfig.data) ) {
|
||||
ajaxConfig.url += ajaxConfig.url.indexOf('?') == -1 ? '?' : '&';
|
||||
ajaxConfig.url += $.param(ajaxConfig.data, true);
|
||||
}
|
||||
ajaxConfig.data = null;
|
||||
} else {
|
||||
ajaxConfig.dataType = 'json';
|
||||
ajaxConfig.url = ajaxConfig.url;
|
||||
ajaxConfig.data = JSON.stringify(ajaxConfig.data);
|
||||
}
|
||||
|
||||
// make request
|
||||
$.ajax(ajaxConfig).done(function(response) {
|
||||
if (typeof response === 'string') {
|
||||
try {
|
||||
response = response.replace('Infinity,', '"Infinity",');
|
||||
response = jQuery.parseJSON(response);
|
||||
} catch (e) {
|
||||
console.debug(e);
|
||||
}
|
||||
}
|
||||
options.success && options.success(response);
|
||||
}).fail(function(response) {
|
||||
var response_text = null;
|
||||
try {
|
||||
response = response.replace('Infinity,', '"Infinity",');
|
||||
response = jQuery.parseJSON(response);
|
||||
response_text = jQuery.parseJSON(response.responseText);
|
||||
} catch (e) {
|
||||
console.debug(e);
|
||||
response_text = response.responseText;
|
||||
}
|
||||
options.error && options.error(response_text, response.status);
|
||||
}).always(function() {
|
||||
options.complete && options.complete();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Read a property value from CSS
|
||||
* @param{String} classname - CSS class
|
||||
* @param{String} name - CSS property
|
||||
*/
|
||||
function cssGetAttribute (classname, name) {
|
||||
var el = $('<div class="' + classname + '"></div>');
|
||||
el.appendTo(':eq(0)');
|
||||
var value = el.css(name);
|
||||
el.remove();
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a CSS file
|
||||
* @param{String} url - Url of CSS file
|
||||
*/
|
||||
function cssLoadFile (url) {
|
||||
if (!$('link[href^="' + url + '"]').length) {
|
||||
$('<link href="' + Galaxy.root + url + '" rel="stylesheet">').appendTo('head');
|
||||
}
|
||||
options.success && options.success(response);
|
||||
}).fail(function(response) {
|
||||
var response_text = null;
|
||||
try {
|
||||
response_text = jQuery.parseJSON(response.responseText);
|
||||
} catch (e) {
|
||||
response_text = response.responseText;
|
||||
};
|
||||
|
||||
/**
|
||||
* Safely merge to dictionaries
|
||||
* @param{Object} options - Target dictionary
|
||||
* @param{Object} optionsDefault - Source dictionary
|
||||
*/
|
||||
function merge (options, optionsDefault) {
|
||||
if (options) {
|
||||
return _.defaults(options, optionsDefault);
|
||||
} else {
|
||||
return optionsDefault;
|
||||
}
|
||||
options.error && options.error(response_text, response.status);
|
||||
}).always(function() {
|
||||
options.complete && options.complete();
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Read a property value from CSS
|
||||
* @param{String} classname - CSS class
|
||||
* @param{String} name - CSS property
|
||||
*/
|
||||
function cssGetAttribute (classname, name) {
|
||||
var el = $('<div class="' + classname + '"></div>');
|
||||
el.appendTo(':eq(0)');
|
||||
var value = el.css(name);
|
||||
el.remove();
|
||||
return value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a CSS file
|
||||
* @param{String} url - Url of CSS file
|
||||
*/
|
||||
function cssLoadFile (url) {
|
||||
if (!$('link[href^="' + url + '"]').length) {
|
||||
$('<link href="' + Galaxy.root + url + '" rel="stylesheet">').appendTo('head');
|
||||
/**
|
||||
* Round floaing point 'number' to 'numPlaces' number of decimal places.
|
||||
* @param{Object} number a floaing point number
|
||||
* @param{Object} numPlaces number of decimal places
|
||||
*/
|
||||
function roundToDecimalPlaces( number, numPlaces ){
|
||||
var placesMultiplier = 1;
|
||||
for( var i=0; i<numPlaces; i++ ){
|
||||
placesMultiplier *= 10;
|
||||
}
|
||||
return Math.round( number * placesMultiplier ) / placesMultiplier;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Safely merge to dictionaries
|
||||
* @param{Object} options - Target dictionary
|
||||
* @param{Object} optionsDefault - Source dictionary
|
||||
*/
|
||||
function merge (options, optionsDefault) {
|
||||
if (options) {
|
||||
return _.defaults(options, optionsDefault);
|
||||
} else {
|
||||
return optionsDefault;
|
||||
}
|
||||
};
|
||||
// calculate on import
|
||||
var kb = 1024,
|
||||
mb = kb * kb,
|
||||
gb = mb * kb,
|
||||
tb = gb * kb;
|
||||
/**
|
||||
* Format byte size to string with units
|
||||
* @param{Integer} size - Size in bytes
|
||||
* @param{Boolean} normal_font - Switches font between normal and bold
|
||||
*/
|
||||
function bytesToString (size, normal_font, numberPlaces) {
|
||||
numberPlaces = numberPlaces !== undefined? numberPlaces: 1;
|
||||
// identify unit
|
||||
var unit = "";
|
||||
if (size >= tb){ size = size / tb; unit = 'TB'; } else
|
||||
if (size >= gb){ size = size / gb; unit = 'GB'; } else
|
||||
if (size >= mb){ size = size / mb; unit = 'MB'; } else
|
||||
if (size >= kb){ size = size / kb; unit = 'KB'; } else
|
||||
if (size > 0){ unit = 'b'; }
|
||||
else { return normal_font? '0 b': '<strong>-</strong>'; }
|
||||
// return formatted string
|
||||
var rounded = unit == 'b'? size: roundToDecimalPlaces( size, numberPlaces );
|
||||
if (normal_font) {
|
||||
return rounded + ' ' + unit;
|
||||
} else {
|
||||
return '<strong>' + rounded + '</strong> ' + unit;
|
||||
}
|
||||
};
|
||||
|
||||
/** Create a unique id */
|
||||
function uid(){
|
||||
top.__utils__uid__ = top.__utils__uid__ || 0;
|
||||
return 'uid-' + top.__utils__uid__++;
|
||||
};
|
||||
|
||||
/**
|
||||
* Round floaing point 'number' to 'numPlaces' number of decimal places.
|
||||
* @param{Object} number a floaing point number
|
||||
* @param{Object} numPlaces number of decimal places
|
||||
*/
|
||||
function roundToDecimalPlaces( number, numPlaces ){
|
||||
var placesMultiplier = 1;
|
||||
for( var i=0; i<numPlaces; i++ ){
|
||||
placesMultiplier *= 10;
|
||||
}
|
||||
return Math.round( number * placesMultiplier ) / placesMultiplier;
|
||||
}
|
||||
|
||||
// calculate on import
|
||||
var kb = 1024,
|
||||
mb = kb * kb,
|
||||
gb = mb * kb,
|
||||
tb = gb * kb;
|
||||
/**
|
||||
* Format byte size to string with units
|
||||
* @param{Integer} size - Size in bytes
|
||||
* @param{Boolean} normal_font - Switches font between normal and bold
|
||||
*/
|
||||
function bytesToString (size, normal_font, numberPlaces) {
|
||||
numberPlaces = numberPlaces !== undefined? numberPlaces: 1;
|
||||
// identify unit
|
||||
var unit = "";
|
||||
if (size >= tb){ size = size / tb; unit = 'TB'; } else
|
||||
if (size >= gb){ size = size / gb; unit = 'GB'; } else
|
||||
if (size >= mb){ size = size / mb; unit = 'MB'; } else
|
||||
if (size >= kb){ size = size / kb; unit = 'KB'; } else
|
||||
if (size > 0){ unit = 'b'; }
|
||||
else { return normal_font? '0 b': '<strong>-</strong>'; }
|
||||
// return formatted string
|
||||
var rounded = unit == 'b'? size: roundToDecimalPlaces( size, numberPlaces );
|
||||
if (normal_font) {
|
||||
return rounded + ' ' + unit;
|
||||
} else {
|
||||
return '<strong>' + rounded + '</strong> ' + unit;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a unique id
|
||||
*/
|
||||
function uid(){
|
||||
top.__utils__uid__ = top.__utils__uid__ || 0;
|
||||
return 'uid-' + top.__utils__uid__++;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a time stamp
|
||||
*/
|
||||
function time() {
|
||||
var d = new Date();
|
||||
var hours = (d.getHours() < 10 ? "0" : "") + d.getHours();
|
||||
var minutes = (d.getMinutes() < 10 ? "0" : "") + d.getMinutes()
|
||||
return datetime = d.getDate() + "/"
|
||||
+ (d.getMonth() + 1) + "/"
|
||||
+ d.getFullYear() + ", "
|
||||
+ hours + ":"
|
||||
+ minutes;
|
||||
};
|
||||
|
||||
return {
|
||||
cssLoadFile: cssLoadFile,
|
||||
cssGetAttribute: cssGetAttribute,
|
||||
get: get,
|
||||
merge: merge,
|
||||
iframe: iframe,
|
||||
bytesToString: bytesToString,
|
||||
uid: uid,
|
||||
time: time,
|
||||
request: request,
|
||||
sanitize: sanitize,
|
||||
textify: textify,
|
||||
isEmpty: isEmpty,
|
||||
deepeach: deepeach,
|
||||
isJSON: isJSON,
|
||||
clone: clone
|
||||
};
|
||||
/** Create a time stamp */
|
||||
function time() {
|
||||
var d = new Date();
|
||||
var hours = (d.getHours() < 10 ? "0" : "") + d.getHours();
|
||||
var minutes = (d.getMinutes() < 10 ? "0" : "") + d.getMinutes()
|
||||
return datetime = d.getDate() + "/"
|
||||
+ (d.getMonth() + 1) + "/"
|
||||
+ d.getFullYear() + ", "
|
||||
+ hours + ":"
|
||||
+ minutes;
|
||||
};
|
||||
|
||||
return {
|
||||
cssLoadFile: cssLoadFile,
|
||||
cssGetAttribute: cssGetAttribute,
|
||||
get: get,
|
||||
merge: merge,
|
||||
iframe: iframe,
|
||||
bytesToString: bytesToString,
|
||||
uid: uid,
|
||||
time: time,
|
||||
request: request,
|
||||
sanitize: sanitize,
|
||||
textify: textify,
|
||||
isEmpty: isEmpty,
|
||||
deepeach: deepeach,
|
||||
isJSON: isJSON,
|
||||
clone: clone,
|
||||
linkify: linkify
|
||||
};
|
||||
});
|
||||
@@ -1,24 +0,0 @@
|
||||
// NOTE: use 'sudo npm install .', then 'grunt' to use this file
|
||||
module.exports = function(grunt) {
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
requirejs: {
|
||||
compile: {
|
||||
options: {
|
||||
baseUrl : "../../../../static/scripts/",
|
||||
paths : {
|
||||
"plugin": "../../config/plugins/visualizations/charts/static"
|
||||
},
|
||||
shim : {
|
||||
"libs/underscore": { exports: "_" },
|
||||
"libs/backbone": { exports: "Backbone" }
|
||||
},
|
||||
name : "plugin/app",
|
||||
out : "static/build-app.js",
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
grunt.loadNpmTasks('grunt-contrib-requirejs');
|
||||
grunt.registerTask( 'default', [ 'requirejs' ]);
|
||||
};
|
||||
@@ -6,6 +6,7 @@
|
||||
<model_class>HistoryDatasetAssociation</model_class>
|
||||
<test type="isinstance" test_attr="datatype" result_type="datatype">tabular.Tabular</test>
|
||||
<test type="isinstance" test_attr="datatype" result_type="datatype">tabular.CSV</test>
|
||||
<test type="isinstance" test_attr="datatype" result_type="datatype">data.Text</test>
|
||||
<to_param param_attr="id">dataset_id</to_param>
|
||||
</data_source>
|
||||
</data_sources>
|
||||
@@ -13,4 +14,4 @@
|
||||
<param type="dataset" var_name_in_template="hda" required="true">dataset_id</param>
|
||||
</params>
|
||||
<entry_point entry_point_type="mako">charts.mako</entry_point>
|
||||
</visualization>
|
||||
</visualization>
|
||||
@@ -1,18 +1,41 @@
|
||||
{
|
||||
"name": "galaxy-charts",
|
||||
"version": "0.0.0",
|
||||
"description": "Charts visualization plugin for the Galaxy informatics framework",
|
||||
"main": " ",
|
||||
"name": "galaxy-charts-plugins",
|
||||
"version": "0.1.0",
|
||||
"description": "Charts visualization plugin.",
|
||||
"keywords": [
|
||||
"galaxy",
|
||||
"visualization",
|
||||
"d3"
|
||||
],
|
||||
"author": "Aysam Guerler",
|
||||
"license": "BSD",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guerler/galaxy-charts"
|
||||
},
|
||||
"license": "AFL-3.0",
|
||||
"dependencies": {
|
||||
"amdi18n-loader": "^0.2.0",
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-bower-install-simple": "^1.1.0",
|
||||
"grunt-check-modules": "^1.0.0",
|
||||
"grunt-cli": "^0.1.13",
|
||||
"grunt-contrib-clean": "^0.6.0",
|
||||
"grunt-contrib-copy": "^0.5.0",
|
||||
"grunt-contrib-less": "^1.1.0",
|
||||
"grunt-contrib-uglify": "^0.8.0",
|
||||
"grunt-contrib-watch": "^0.6.1",
|
||||
"grunt-exec": "^0.4.6",
|
||||
"grunt-spritesmith": "^4.7.1",
|
||||
"i18n-webpack-plugin": "^0.2.7",
|
||||
"webpack": "^1.10.1",
|
||||
"webpack-dev-server": "^1.7.0",
|
||||
"backbone": "^1.3.3",
|
||||
"bootstrap": "^3.3.7",
|
||||
"cytoscape": "^2.7.10",
|
||||
"jquery": "^3.1.1",
|
||||
"cytoscape-edgehandles": "^2.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt-contrib-requirejs": "~0.4.3"
|
||||
"css-loader": "^0.24.0",
|
||||
"style-loader": "^0.13.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
43 55 63 99 28 85 20 31 47 14
|
||||
1 63 94 83 94 74 7 73 51 7
|
||||
8 34 2 94 87 21 72 51 3 84
|
||||
5 50 40 30 59 43 19 77 30 80
|
||||
22 55 69 43 77 72 12 54 53 56
|
||||
36 34 81 28 59 64 54 29 57 69
|
||||
57 90 93 32 45 98 40 16 52 83
|
||||
6 17 39 86 10 11 38 69 19 50
|
||||
67 51 47 22 58 27 65 49 92 96
|
||||
@@ -1,54 +0,0 @@
|
||||
/**
|
||||
* Main application class.
|
||||
*/
|
||||
define( [ 'mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils', 'plugin/components/storage', 'plugin/components/model', 'utils/deferred', 'plugin/views/viewer', 'plugin/views/editor', 'plugin/charts/types' ],
|
||||
function( Modal, Portlet, Ui, Utils, Storage, Chart, Deferred, Viewer, Editor, Types ) {
|
||||
return Backbone.View.extend({
|
||||
initialize: function(options){
|
||||
this.options = options;
|
||||
this.modal = parent.Galaxy && parent.Galaxy.modal || new Modal.View();
|
||||
this.types = Types;
|
||||
this.chart = new Chart();
|
||||
this.storage = new Storage( this );
|
||||
this.deferred = new Deferred();
|
||||
|
||||
// views
|
||||
this.viewer = new Viewer( this );
|
||||
this.editor = new Editor( this );
|
||||
this.$el.append( this.viewer.$el );
|
||||
this.$el.append( this.editor.$el );
|
||||
|
||||
// pick start screen
|
||||
if ( !this.storage.load() ) {
|
||||
this.go( 'editor' );
|
||||
} else {
|
||||
this.go( 'viewer' );
|
||||
this.chart.trigger( 'redraw' );
|
||||
}
|
||||
},
|
||||
|
||||
/** Loads a view and makes sure that all others are hidden */
|
||||
go: function( view_id ) {
|
||||
$( '.tooltip' ).hide();
|
||||
this.viewer.hide();
|
||||
this.editor.hide();
|
||||
this[ view_id ].show();
|
||||
},
|
||||
|
||||
/** Message */
|
||||
showModal: function( title, body ) {
|
||||
var self = this;
|
||||
this.modal.show( { title: title, body: body, buttons: { 'Close': function() { self.modal.hide() } } } );
|
||||
},
|
||||
|
||||
/** Split chart type into path components */
|
||||
split: function( chart_type ) {
|
||||
var path = chart_type.split( /_(.+)/ );
|
||||
if ( path.length >= 2 ) {
|
||||
return path[ 0 ] + '/' + path[ 1 ];
|
||||
} else {
|
||||
return chart_type;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/components/jobs', 'plugin/charts/jqplot/common/wrapper' ], function( Utilities, Jobs, Plot ) {
|
||||
return Backbone.Model.extend({
|
||||
initialize: function( app, options ) {
|
||||
Jobs.request( app, Utilities.buildJobDictionary( 'histogramdiscrete', app.chart ), function( dataset ) {
|
||||
var request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id );
|
||||
var index = 1;
|
||||
var tmp_dict = { id : request_dictionary.id, groups : [] };
|
||||
_.each( request_dictionary.groups, function( group ) {
|
||||
tmp_dict.groups.push({
|
||||
key : group.key,
|
||||
columns : { x: { index : 0, is_label : true }, y: { index : index++ } }
|
||||
});
|
||||
});
|
||||
options.request_dictionary = tmp_dict;
|
||||
options.makeConfig = function( groups, plot_config ){
|
||||
$.extend( true, plot_config, {
|
||||
seriesDefaults: { renderer: $.jqplot.BarRenderer },
|
||||
axes: { xaxis: { min : -1 }, yaxis: { pad : 1.2 } }
|
||||
});
|
||||
};
|
||||
new Plot( app, options );
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
define( [ 'plugin/charts/jqplot/common/wrapper' ], function( Plot ) {
|
||||
return Backbone.Model.extend({
|
||||
initialize: function( app, options ) {
|
||||
new Plot( app, options );
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,8 +0,0 @@
|
||||
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
|
||||
return Backbone.Model.extend({
|
||||
initialize: function( app, options ) {
|
||||
options.type = 'multiBarChart';
|
||||
new NVD3( app, options );
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,8 +0,0 @@
|
||||
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
|
||||
return Backbone.Model.extend({
|
||||
initialize: function( app, options ) {
|
||||
options.type = 'multiBarHorizontalChart';
|
||||
new NVD3( app, options );
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,18 +0,0 @@
|
||||
define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/components/jobs', 'plugin/charts/nvd3/common/wrapper' ], function( Utilities, Jobs, NVD3 ) {
|
||||
return Backbone.Model.extend({
|
||||
initialize: function( app, options ) {
|
||||
Jobs.request( app, Utilities.buildJobDictionary( 'histogram', app.chart ), function( dataset ) {
|
||||
options.request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id );
|
||||
var index = 1;
|
||||
_.each( options.request_dictionary.groups, function( group ) {
|
||||
group.columns = { x : { index : 0, is_numeric : true }, y : { index : index++ } }
|
||||
});
|
||||
options.type = 'multiBarChart';
|
||||
options.makeConfig = function( nvd3_model ) {
|
||||
nvd3_model.options( { showControls: true } );
|
||||
};
|
||||
new NVD3( app, options );
|
||||
}, function() { options.process.reject() } );
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/components/jobs', 'plugin/charts/nvd3/common/wrapper' ], function( Utilities, Jobs, NVD3 ) {
|
||||
return Backbone.Model.extend({
|
||||
initialize: function( app, options ) {
|
||||
Jobs.request( app, Utilities.buildJobDictionary( 'histogramdiscrete', app.chart ), function( dataset ) {
|
||||
var request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id );
|
||||
var index = 1;
|
||||
var tmp_dict = { id : request_dictionary.id, groups : [] };
|
||||
_.each( request_dictionary.groups, function( group ) {
|
||||
tmp_dict.groups.push({
|
||||
key : group.key,
|
||||
columns : { x: { index : 0, is_label : true }, y: { index : index++ } }
|
||||
});
|
||||
});
|
||||
options.request_dictionary = tmp_dict;
|
||||
options.type = 'multiBarChart';
|
||||
options.makeConfig = function( nvd3_model ) {
|
||||
nvd3_model.options( { showControls: true } );
|
||||
};
|
||||
new NVD3( app, options );
|
||||
}, function() { options.process.reject() } );
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,8 +0,0 @@
|
||||
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
|
||||
return Backbone.Model.extend({
|
||||
initialize: function( app, options ) {
|
||||
options.type = 'lineChart';
|
||||
new NVD3( app, options );
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,8 +0,0 @@
|
||||
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
|
||||
return Backbone.Model.extend({
|
||||
initialize: function( app, options ) {
|
||||
options.type = 'lineWithFocusChart';
|
||||
new NVD3( app, options );
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,8 +0,0 @@
|
||||
define( [ 'plugin/charts/nvd3/common/wrapper' ], function( NVD3 ) {
|
||||
return Backbone.Model.extend({
|
||||
initialize: function( app, options ) {
|
||||
options.type = 'stackedAreaChart';
|
||||
new NVD3( app, options );
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,37 +0,0 @@
|
||||
define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/charts/utilities/tabular-datasets' ], function( Utilities, Datasets ) {
|
||||
return Backbone.View.extend({
|
||||
initialize: function( app, options ) {
|
||||
var chart = app.chart;
|
||||
var request_dictionary = Utilities.buildRequestDictionary( chart );
|
||||
var error = null;
|
||||
request_dictionary.success = function( result ) {
|
||||
var colors = d3.scale.category20();
|
||||
_.each( result.groups, function( group, group_index ) {
|
||||
try {
|
||||
var svg = d3.select( '#' + ( options.canvas_list[ group_index ] || options.canvas_list[ 0 ] ) );
|
||||
var height = parseInt( svg.style( 'height' ) );
|
||||
var width = parseInt( svg.style( 'width' ) );
|
||||
var maxValue = d3.max( group.values, function( d ) { return Math.max( d.x, d.y ) } );
|
||||
svg.selectAll( 'bubbles' )
|
||||
.data( group.values )
|
||||
.enter().append( 'circle' )
|
||||
.attr( 'r', function( d ) { return ( Math.abs( d.z ) * 20 ) / maxValue } )
|
||||
.attr( 'cy', function( d, i ) { return height * d.y / maxValue } )
|
||||
.attr( 'cx', function( d ) { return width * d.x / maxValue } )
|
||||
.style( 'stroke', colors( group_index ) )
|
||||
.style( 'fill', 'white' );
|
||||
} catch ( err ) {
|
||||
error = err;
|
||||
}
|
||||
});
|
||||
if ( error ) {
|
||||
chart.state( 'failed', error );
|
||||
} else {
|
||||
chart.state( 'ok', 'Workshop chart has been drawn.' );
|
||||
}
|
||||
options.process.resolve();
|
||||
}
|
||||
Datasets.request( request_dictionary );
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
define( [ 'plugin/charts/others/heatmap/config' ], function( default_config ) {
|
||||
return $.extend( true, {}, default_config, {
|
||||
title : 'Clustered Heatmap',
|
||||
category : 'Data processing (requires \'charts\' tool from Toolshed)',
|
||||
keywords : 'others default'
|
||||
});
|
||||
});
|
||||
@@ -1,40 +0,0 @@
|
||||
define( [ 'plugin/charts/utilities/tabular-utilities', 'plugin/components/jobs', 'plugin/charts/others/heatmap/heatmap-plugin' ], function( Utilities, Jobs, HeatMap ) {
|
||||
return Backbone.View.extend({
|
||||
initialize: function(app, options) {
|
||||
Jobs.request( app, Utilities.buildJobDictionary( 'heatmap', app.chart ), function( dataset ) {
|
||||
var request_dictionary = Utilities.buildRequestDictionary( app.chart, dataset.id );
|
||||
var index = 0;
|
||||
var tmp_dict = { id : request_dictionary.id, groups : [] };
|
||||
for ( var group_index in request_dictionary.groups ) {
|
||||
var group = request_dictionary.groups[ group_index ];
|
||||
tmp_dict.groups.push({
|
||||
key : group.key,
|
||||
columns : {
|
||||
x: {
|
||||
index : index++,
|
||||
is_label : true
|
||||
},
|
||||
y: {
|
||||
index : index++,
|
||||
is_label : true
|
||||
},
|
||||
z: {
|
||||
index : index++
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
options.request_dictionary = tmp_dict;
|
||||
options.render = function( canvas_id, groups ) {
|
||||
new HeatMap( app, {
|
||||
chart : options.chart,
|
||||
canvas_id : canvas_id,
|
||||
groups : groups
|
||||
});
|
||||
return true;
|
||||
};
|
||||
Utilities.panelHelper( options );
|
||||
}, function() { options.process.reject() } );
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
define( [], function() {
|
||||
return [
|
||||
{ label : 'Default', value: 'default',
|
||||
help : 'The visualizations below were curated from different libraries. Its a representative set covering most use cases. Use this selection by default.' },
|
||||
{ label : 'NVD3', value: 'nvd3',
|
||||
help : 'NVD3 is a popular d3-based library hosted at <a href="http://www.nvd3.org" target="_blank">www.nvd3.org<a/>. Most visualization types support intuitive drag-and-drop zooming and scaling. NVD3 generates high quality vector graphics. As with all vector based plugins, you may experience a slow down in browser responsiveness if visualizing thousands of data points.' },
|
||||
{ label : 'jqPlot', value: 'jqplot',
|
||||
help : 'jqPlot is a canvas-based library hosted at <a href="http://www.jqplot.com" target="_blank">www.jqplot.com<a/>. It is a plotting and charting plugin for the jQuery Javascript framework. Since based on canvas it is capable of rendering many thousand data points without adverse effects.' },
|
||||
{ label : 'Others', value: 'others',
|
||||
help : 'These visualizations were developed by the Galaxy team.'
|
||||
}
|
||||
];
|
||||
});
|
||||
@@ -1,66 +0,0 @@
|
||||
define(['plugin/charts/nvd3/bar/config',
|
||||
'plugin/charts/nvd3/bar_stacked/config',
|
||||
'plugin/charts/nvd3/bar_horizontal/config',
|
||||
'plugin/charts/nvd3/bar_horizontal_stacked/config',
|
||||
'plugin/charts/nvd3/line_focus/config',
|
||||
'plugin/charts/nvd3/pie/config',
|
||||
'plugin/charts/nvd3/stackedarea_full/config',
|
||||
'plugin/charts/nvd3/stackedarea_stream/config',
|
||||
'plugin/charts/nvd3/histogram/config',
|
||||
'plugin/charts/nvd3/histogram_discrete/config',
|
||||
'plugin/charts/nvd3/line/config',
|
||||
'plugin/charts/nvd3/scatter/config',
|
||||
'plugin/charts/nvd3/stackedarea/config',
|
||||
'plugin/charts/jqplot/bar/config',
|
||||
'plugin/charts/jqplot/line/config',
|
||||
'plugin/charts/jqplot/scatter/config',
|
||||
'plugin/charts/jqplot/boxplot/config',
|
||||
'plugin/charts/jqplot/histogram_discrete/config',
|
||||
'plugin/charts/others/heatmap/config',
|
||||
'plugin/charts/others/heatmap_cluster/config',
|
||||
'plugin/charts/others/example/config' ],
|
||||
function(nvd3_bar,
|
||||
nvd3_bar_stacked,
|
||||
nvd3_bar_horizontal,
|
||||
nvd3_bar_horizontal_stacked,
|
||||
nvd3_line_focus,
|
||||
nvd3_pie,
|
||||
nvd3_stackedarea_full,
|
||||
nvd3_stackedarea_stream,
|
||||
nvd3_histogram,
|
||||
nvd3_histogram_discrete,
|
||||
nvd3_line,
|
||||
nvd3_scatter,
|
||||
nvd3_stackedarea,
|
||||
jqplot_bar,
|
||||
jqplot_line,
|
||||
jqplot_scatter,
|
||||
jqplot_boxplot,
|
||||
jqplot_histogram_discrete,
|
||||
others_heatmap,
|
||||
others_heatmap_cluster,
|
||||
others_example) {
|
||||
return {
|
||||
'nvd3_bar' : nvd3_bar,
|
||||
'nvd3_bar_stacked' : nvd3_bar_stacked,
|
||||
'nvd3_bar_horizontal' : nvd3_bar_horizontal,
|
||||
'nvd3_bar_horizontal_stacked' : nvd3_bar_horizontal_stacked,
|
||||
'nvd3_line_focus' : nvd3_line_focus,
|
||||
'nvd3_stackedarea' : nvd3_stackedarea,
|
||||
'nvd3_stackedarea_full' : nvd3_stackedarea_full,
|
||||
'nvd3_stackedarea_stream' : nvd3_stackedarea_stream,
|
||||
'nvd3_pie' : nvd3_pie,
|
||||
'nvd3_line' : nvd3_line,
|
||||
'nvd3_scatter' : nvd3_scatter,
|
||||
'nvd3_histogram' : nvd3_histogram,
|
||||
'nvd3_histogram_discrete' : nvd3_histogram_discrete,
|
||||
'jqplot_bar' : jqplot_bar,
|
||||
'jqplot_histogram_discrete' : jqplot_histogram_discrete,
|
||||
'jqplot_line' : jqplot_line,
|
||||
'jqplot_scatter' : jqplot_scatter,
|
||||
'jqplot_boxplot' : jqplot_boxplot,
|
||||
'others_heatmap' : others_heatmap,
|
||||
'others_heatmap_cluster' : others_heatmap_cluster,
|
||||
'others_example' : others_example
|
||||
}
|
||||
});
|
||||
@@ -1,26 +0,0 @@
|
||||
define( [ 'plugin/charts/utilities/tabular-inputs' ], function( Inputs ) {
|
||||
return {
|
||||
title : '',
|
||||
category : '',
|
||||
library : '',
|
||||
tag : '',
|
||||
keywords : '',
|
||||
datatype : 'tabular',
|
||||
settings : {
|
||||
x_axis_label : Inputs.axisLabel( 'x_axis_label' ),
|
||||
x_axis_type : Inputs.axisType( 'x_axis_type' ),
|
||||
y_axis_label : Inputs.axisLabel( 'y_axis_label' ),
|
||||
y_axis_type : Inputs.axisType( 'y_axis_type' ),
|
||||
show_legend : Inputs.boolean( 'show_legend', { label: 'Show legend', help: 'Would you like to add a legend?' } ),
|
||||
use_panels : Inputs.boolean( 'use_panels', { label: 'Use multi-panels', help: 'Would you like to separate your data into individual panels?' } )
|
||||
},
|
||||
groups : {
|
||||
key: {
|
||||
label : 'Provide a label',
|
||||
type : 'text',
|
||||
placeholder : 'Data label',
|
||||
value : 'Data label'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,65 +0,0 @@
|
||||
define( [], function() {
|
||||
return {
|
||||
axisLabel : function( name, options ) {
|
||||
options = options || {};
|
||||
prefix = name.substr( 0, 1 );
|
||||
return {
|
||||
name : name,
|
||||
label : prefix.toUpperCase() + '-Axis label',
|
||||
help : 'Provide a label for the axis.',
|
||||
type : 'text',
|
||||
value : options.value || prefix.toUpperCase() + '-axis',
|
||||
placeholder : 'Axis label'
|
||||
}
|
||||
},
|
||||
axisType : function( name, options ) {
|
||||
options = options || {};
|
||||
prefix = name.substr( 0, 1 );
|
||||
var axisPrecision = function() {
|
||||
return { name : 'precision',
|
||||
label : 'Axis tick format',
|
||||
help : 'Select the tick format for the axis.',
|
||||
type : 'select',
|
||||
value : options.precision || 1,
|
||||
data : [ { label : '0.00001', value : '5' },
|
||||
{ label : '0.0001', value : '4' },
|
||||
{ label : '0.001', value : '3' },
|
||||
{ label : '0.01', value : '2' },
|
||||
{ label : '0.1', value : '1' },
|
||||
{ label : '1', value : '0' } ] }
|
||||
}
|
||||
return {
|
||||
name : prefix + '_axis_type',
|
||||
type : 'conditional',
|
||||
test_param : {
|
||||
name : 'type',
|
||||
label : prefix.toUpperCase() + '-Axis value type',
|
||||
type : 'select',
|
||||
value : options.value || 'auto',
|
||||
help : 'Select the value type of the axis.',
|
||||
data : [ { value : 'hide', label : '-- Do not show values --' },
|
||||
{ value : 'auto', label : 'Auto' },
|
||||
{ value : 'f', label : 'Float' },
|
||||
{ value : 'd', label : 'Integer' },
|
||||
{ value : 'e', label : 'Exponent' },
|
||||
{ value : 'p', label : 'Percent' },
|
||||
{ value : 's', label : 'SI-prefix' } ]
|
||||
},
|
||||
cases : [ { value : 'hide' },
|
||||
{ value : 'auto' },
|
||||
{ value : 'f', inputs: [ axisPrecision() ] },
|
||||
{ value : 'd' },
|
||||
{ value : 'e', inputs: [ axisPrecision() ] },
|
||||
{ value : 'p', inputs: [ axisPrecision() ] },
|
||||
{ value : 's' } ]
|
||||
}
|
||||
},
|
||||
boolean : function( name, options ) {
|
||||
options = options || {};
|
||||
return { name : name,
|
||||
label : options.label,
|
||||
help : options.help,
|
||||
type : 'boolean' }
|
||||
}
|
||||
}
|
||||
});
|
||||
+22
-15
@@ -1,3 +1,7 @@
|
||||
.charts-viewer {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.charts-viewer .ui-message {
|
||||
position: absolute;
|
||||
width: calc(100% - 20px);
|
||||
@@ -49,23 +53,12 @@
|
||||
.charts-grid .item {
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
border-radius:5px
|
||||
border-radius:5px;
|
||||
}
|
||||
|
||||
.charts-grid .current {
|
||||
border-color:#66afe9;
|
||||
background-color:#EEEEFF;
|
||||
outline:0;
|
||||
-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
}
|
||||
|
||||
.charts-grid .image {
|
||||
padding: 10px;
|
||||
width: 100px;
|
||||
height: 86px;
|
||||
.charts-grid .item-float {
|
||||
float: left;
|
||||
height: 140px;
|
||||
}
|
||||
|
||||
.charts-grid .title {
|
||||
@@ -83,6 +76,20 @@
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.charts-grid .current {
|
||||
border-color:#66afe9;
|
||||
background-color:#EEEEFF;
|
||||
outline:0;
|
||||
-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
}
|
||||
|
||||
.charts-grid .image {
|
||||
padding: 10px;
|
||||
width: 100px;
|
||||
height: 86px;
|
||||
}
|
||||
|
||||
.charts-viewport {
|
||||
height: inherit;
|
||||
min-height: 50px;
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Main application class.
|
||||
*/
|
||||
define( [ 'mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils', 'plugin/components/model', 'utils/deferred', 'plugin/views/viewer', 'plugin/views/editor' ],
|
||||
function( Modal, Portlet, Ui, Utils, Chart, Deferred, Viewer, Editor ) {
|
||||
return Backbone.View.extend({
|
||||
initialize: function( options ) {
|
||||
var self = this;
|
||||
require( [ 'repository/build/registry' ], function( Registry ) {
|
||||
console.debug( 'app::initialize() - Loaded Registry:' );
|
||||
console.debug( Registry );
|
||||
Utils.get({
|
||||
url : Galaxy.root + 'api/datasets/' + options.dataset_id,
|
||||
cache : true,
|
||||
success : function( dataset ) {
|
||||
self.dataset = dataset;
|
||||
self.types = {};
|
||||
_.each( Registry, function( type, type_id ) {
|
||||
if ( !type.datatypes || type.datatypes.indexOf( dataset.file_ext ) != -1 ) {
|
||||
self.types[ type_id ] = type;
|
||||
}
|
||||
});
|
||||
if ( _.size( self.types ) === 0 ) {
|
||||
self.$el.append( $( '<div/>' ).addClass( 'errormessagelarge' )
|
||||
.append( $( '<p/>' ).text( 'Unfortunately we could not identify a suitable plugin. Feel free to contact us if you are aware of visualizations for this datatype.' ) ) );
|
||||
} else {
|
||||
self._build( options );
|
||||
}
|
||||
}
|
||||
});
|
||||
}, function( err ) {
|
||||
self.$el.append( $( '<div/>' ).addClass( 'errormessagelarge' )
|
||||
.append( $( '<p/>' ).text( 'Unable to access the plugin repository:' ) )
|
||||
.append( $( '<pre/>' ).text( 'charts_repository_url = ' + repository_root ) )
|
||||
.append( $( '<p/>' ).html( 'Please verify that your internet connection works properly and that the above url is correct. Contact your admin if this error persists.' ) ) );
|
||||
});
|
||||
},
|
||||
|
||||
_build: function( options ) {
|
||||
this.options = options;
|
||||
this.modal = parent.Galaxy && parent.Galaxy.modal || new Modal.View();
|
||||
this.chart = new Chart( {}, options );
|
||||
this.deferred = new Deferred();
|
||||
this.viewer = new Viewer( this );
|
||||
this.editor = new Editor( this );
|
||||
this.$el.append( this.viewer.$el );
|
||||
this.$el.append( this.editor.$el );
|
||||
this.go( this.chart.load() ? 'viewer' : 'editor' );
|
||||
},
|
||||
|
||||
/** Loads a view and makes sure that all others are hidden */
|
||||
go: function( view_id ) {
|
||||
$( '.tooltip' ).hide();
|
||||
this.viewer.hide();
|
||||
this.editor.hide();
|
||||
this[ view_id ].show();
|
||||
},
|
||||
|
||||
/** Split chart type into path components */
|
||||
split: function( chart_type ) {
|
||||
var path = chart_type.split( /_(.+)/ );
|
||||
if ( path.length >= 2 ) {
|
||||
return path[ 0 ] + '/' + path[ 1 ];
|
||||
} else {
|
||||
return chart_type;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,98 @@
|
||||
define( [ 'utils/utils', 'mvc/visualization/visualization-model' ], function( Utils ) {
|
||||
return Backbone.Model.extend({
|
||||
defaults : {
|
||||
title : '',
|
||||
type : '',
|
||||
date : null,
|
||||
state : '',
|
||||
state_info : '',
|
||||
modified : false,
|
||||
dataset_id : '',
|
||||
dataset_id_job : ''
|
||||
},
|
||||
|
||||
initialize: function( options, viz_options ) {
|
||||
this.groups = new Backbone.Collection();
|
||||
this.settings = new Backbone.Model();
|
||||
this.definition = {};
|
||||
this.viz_options = viz_options;
|
||||
console.debug( 'model::initialize() - Initialized with configuration:' );
|
||||
console.debug( viz_options );
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this.clear().set({
|
||||
title : 'New Chart',
|
||||
type : '__first',
|
||||
dataset_id : this.viz_options.dataset_id
|
||||
});
|
||||
this.settings.clear();
|
||||
this.groups.reset();
|
||||
this.groups.add( { id : Utils.uid() } );
|
||||
},
|
||||
|
||||
state: function( value, info ) {
|
||||
this.set( { state : value, state_info : info } );
|
||||
this.trigger( 'set:state' );
|
||||
console.debug( 'model::state() - ' + info + ' (' + value + ')' );
|
||||
},
|
||||
|
||||
/** Pack and save nested chart model */
|
||||
save: function( options ) {
|
||||
var self = this;
|
||||
options = options || {};
|
||||
var chart_dict = {
|
||||
attributes : this.attributes,
|
||||
settings : this.settings.attributes,
|
||||
groups : []
|
||||
};
|
||||
this.groups.each( function( group ) {
|
||||
chart_dict.groups.push( group.attributes );
|
||||
});
|
||||
var viz = new Visualization({
|
||||
id : this.viz_options.visualization_id || undefined,
|
||||
type : 'charts',
|
||||
title : this.get( 'title' ) || '',
|
||||
config : {
|
||||
dataset_id : this.viz_options.dataset_id,
|
||||
chart_dict : this.viz_options.chart_dict = chart_dict
|
||||
}
|
||||
});
|
||||
viz.save().then( function( response ) {
|
||||
if ( response && response.id ) {
|
||||
self.viz_options.visualization_id = response.id;
|
||||
options.success && options.success();
|
||||
console.debug( 'model::save() - Received visualization id: ' + response.id );
|
||||
} else {
|
||||
options.error && options.error();
|
||||
console.debug( 'model::save() - Unrecognized response. Saving may have failed.' );
|
||||
}
|
||||
}).fail( function( response ) {
|
||||
options.error && options.error();
|
||||
console.debug( 'model::save() - Saving failed.' );
|
||||
});
|
||||
console.debug( 'model::save() - Saved with configuration:' );
|
||||
console.debug( this.viz_options );
|
||||
},
|
||||
|
||||
/** Load nested models/collections from packed dictionary */
|
||||
load: function() {
|
||||
console.debug( 'model::load() - Attempting to load with configuration:' );
|
||||
console.debug( this.viz_options );
|
||||
var chart_dict = this.viz_options.chart_dict;
|
||||
if ( chart_dict && chart_dict.attributes ) {
|
||||
this.set( chart_dict.attributes );
|
||||
this.state( 'ok', 'Loading saved visualization...' );
|
||||
this.settings.set( chart_dict.settings );
|
||||
this.groups.reset();
|
||||
this.groups.add( chart_dict.groups );
|
||||
this.set( 'modified', false );
|
||||
console.debug( 'model::load() - Loading chart model ' + chart_dict.attributes.type + '.' );
|
||||
this.trigger( 'redraw' );
|
||||
return true;
|
||||
}
|
||||
console.debug( 'model::load() - Visualization attributes unavailable.' );
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,169 @@
|
||||
/** This class enables users to export/download a chart as PNG, SVG or PDF. */
|
||||
define( [ 'libs/underscore' ], function( _ ) {
|
||||
/** PNG export */
|
||||
function createPNG (options) {
|
||||
if ( options.$el.find( 'svg' ).length > 0 ) {
|
||||
_svg2png( options );
|
||||
} else {
|
||||
_canvas2png( options.$el.find( '.charts-viewport-canvas' ) );
|
||||
}
|
||||
};
|
||||
|
||||
/** Convert canvas to png */
|
||||
function _canvas2png( $canvas ) {
|
||||
try {
|
||||
if ( $canvas.width() !== 0 && $canvas.height() !== 0) {
|
||||
var newCanvas = document.createElement( 'canvas' );
|
||||
newCanvas.width = $canvas.outerWidth( true );
|
||||
newCanvas.height = $canvas.outerHeight( true );
|
||||
var newContext = newCanvas.getContext( '2d' );
|
||||
newContext.save();
|
||||
newContext.fillStyle = 'rgb(255,255,255)';
|
||||
newContext.fillRect( 0,0, newCanvas.width, newCanvas.height );
|
||||
newContext.restore();
|
||||
newContext.translate( 0, 0 );
|
||||
newContext.textAlign = 'left';
|
||||
newContext.textBaseline = 'top';
|
||||
function _toImage( $el, x_offset, y_offset ) {
|
||||
var tagname = $el.prop( 'tagName' ).toLowerCase();
|
||||
var p = $el.position();
|
||||
var left = x_offset + p.left + parseInt( $el.css( 'marginLeft' ), 10 ) + parseInt( $el.css( 'borderLeftWidth' ), 10 ) + parseInt( $el.css( 'paddingLeft' ), 10 );
|
||||
var top = y_offset + p.top + parseInt( $el.css( 'marginTop' ), 10 ) + parseInt( $el.css( 'borderTopWidth' ), 10 ) + parseInt( $el.css( 'paddingTop' ), 10 );
|
||||
var w = newCanvas.width;
|
||||
if ( tagname == 'div' || tagname == 'span' ) {
|
||||
$el.children().each( function() { _toImage( $( this ), left, top ) } );
|
||||
} else if ( tagname == 'canvas' ) {
|
||||
newContext.drawImage( $el[ 0 ], left, top );
|
||||
}
|
||||
}
|
||||
$canvas.children().each( function() { _toImage( $( this ), 0, 0 ) } );
|
||||
imgData = newCanvas.toDataURL( 'image/png' );
|
||||
if ( imgData ) {
|
||||
window.location.href = imgData.replace( 'image/png', 'image/octet-stream' );
|
||||
}
|
||||
}
|
||||
} catch ( err ) {
|
||||
console.debug( 'FAILED - screenshot::_canvas2png() - ' + err );
|
||||
if (options.error) {
|
||||
options.error( 'Please reduce your visualization to a single panel and try again.' );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Convert svg to png */
|
||||
function _svg2png ( options ) {
|
||||
var scale = 5;
|
||||
var xml = toXML( options );
|
||||
var canvas = document.createElement( 'canvas' );
|
||||
var context = canvas.getContext( '2d' );
|
||||
var source = new Image();
|
||||
var $container = $( '<div style="display:none;"/>' ).append( $ ( canvas ) );
|
||||
$( 'body' ).append( $container );
|
||||
canvas.width = xml.width * scale;
|
||||
canvas.height = xml.height * scale;
|
||||
source.src = 'data:image/svg+xml;base64,' + btoa( xml.string );
|
||||
source.onload = function() {
|
||||
context.drawImage( source, 0, 0, canvas.width, canvas.height );
|
||||
window.location.href = canvas.toDataURL( 'image/png' ).replace( 'image/png', 'image/octet-stream' );
|
||||
$container.remove();
|
||||
}
|
||||
};
|
||||
|
||||
/** SVG export */
|
||||
function createSVG (options) {
|
||||
window.location.href = 'data:none/none;base64,' + btoa(toXML(options).string);
|
||||
};
|
||||
|
||||
/** PDF export */
|
||||
function createPDF( options ) {
|
||||
var xml = toXML( options );
|
||||
var data = {
|
||||
filename : 'visualization',
|
||||
type : 'application/pdf',
|
||||
height : xml.height,
|
||||
width : xml.width,
|
||||
scale : 2,
|
||||
svg : xml.string
|
||||
};
|
||||
var $el = $( 'body' );
|
||||
var form = $el.find( '#viewport-form' );
|
||||
if ( form.length === 0 ) {
|
||||
form = $( '<form>', {
|
||||
id : 'viewport-form',
|
||||
method : 'post',
|
||||
action : 'http://export.highcharts.com/',
|
||||
display : 'none'
|
||||
});
|
||||
$el.append( form );
|
||||
}
|
||||
form.empty();
|
||||
for ( name in data ) {
|
||||
var input = $( '<input/>', {
|
||||
type : 'hidden',
|
||||
name : name,
|
||||
value : data[ name ]
|
||||
});
|
||||
form.append( input );
|
||||
}
|
||||
try {
|
||||
form.submit();
|
||||
} catch( err ) {
|
||||
console.log( err );
|
||||
}
|
||||
};
|
||||
|
||||
/** XML export */
|
||||
function toXML( options ) {
|
||||
var $svg = options.$el.find( 'svg' );
|
||||
if ( $svg.length == 0 ) {
|
||||
if ( options.error ) {
|
||||
options.error( 'No SVG found. This visualization type does not support SVG/PDF export.' );
|
||||
return;
|
||||
}
|
||||
}
|
||||
var $el = options.$el;
|
||||
var nsvgs = $svg.length;
|
||||
var height = parseInt( $svg.first().css( 'height' ) );
|
||||
var width = parseInt( $svg.first().css( 'width' ) );
|
||||
var serializer = new XMLSerializer();
|
||||
var $composite = $( '<svg/>' ).attr( { version: '1.1', xmlns: 'http://www.w3.org/2000/svg', width: width * nsvgs, height: height } );
|
||||
var xmlString = '';
|
||||
var offsetX = 0;
|
||||
$svg.each(function() {
|
||||
var $svg = $( this ).clone();
|
||||
_inline( $svg );
|
||||
var $g = $( '<g transform="translate(' + offsetX + ', 0)">' ).attr( 'xmlns', 'http://www.w3.org/2000/svg' );
|
||||
$g.append( $svg.find( 'g' ).first() );
|
||||
$composite.append( $g );
|
||||
offsetX += width;
|
||||
});
|
||||
return {
|
||||
string : serializer.serializeToString( $composite[ 0 ] ),
|
||||
height : height,
|
||||
width : width
|
||||
}
|
||||
};
|
||||
|
||||
/** inlines CSS code */
|
||||
function _inline( $target ) {
|
||||
for ( var sheet_id in document.styleSheets ) {
|
||||
var sheet = document.styleSheets[ sheet_id ];
|
||||
var rules = sheet.cssRules;
|
||||
if ( rules ) {
|
||||
for ( var idx = 0, len = rules.length; idx < len; idx++ ) {
|
||||
try {
|
||||
$target.find( rules[ idx ].selectorText ).each( function ( i, elem ) {
|
||||
elem.style.cssText += rules[idx].style.cssText;
|
||||
});
|
||||
} catch( err ) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
createPNG: createPNG,
|
||||
createSVG: createSVG,
|
||||
createPDF: createPDF
|
||||
};
|
||||
});
|
||||
+9
-4
@@ -1,5 +1,5 @@
|
||||
/** This class renders the chart configuration form. */
|
||||
define( [], function() {
|
||||
define( [ 'utils/utils' ], function( Utils ) {
|
||||
return Backbone.View.extend({
|
||||
initialize: function( app, options ) {
|
||||
var self = this;
|
||||
@@ -13,9 +13,14 @@ define( [], function() {
|
||||
this.render();
|
||||
},
|
||||
render: function() {
|
||||
this.$image.attr( 'src', app_root + 'charts/' + this.app.split( this.chart.get( 'type' ) ) + '/logo.png' );
|
||||
this.$title.html( this.chart.definition.title + ' (' + this.chart.definition.library + ')' );
|
||||
this.$text.html( this.chart.definition.description || this.chart.definition.category );
|
||||
if ( this.chart.get( 'type' ) ) {
|
||||
this.$image.attr( 'src', repository_root + '/visualizations/' + this.app.split( this.chart.get( 'type' ) ) + '/logo.png' );
|
||||
this.$title.html( this.chart.definition.title + ' (' + this.chart.definition.library + ')' );
|
||||
this.$text.html( Utils.linkify( this.chart.definition.description || '' ) );
|
||||
this.$el.show();
|
||||
} else {
|
||||
this.$el.hide();
|
||||
}
|
||||
},
|
||||
_template: function() {
|
||||
return '<div class="charts-description">' +
|
||||
+36
-26
@@ -14,12 +14,12 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
|
||||
icon : 'fa-bar-chart-o',
|
||||
title: 'Editor',
|
||||
operations : {
|
||||
'save' : new Ui.ButtonIcon({
|
||||
icon : 'fa-save',
|
||||
tooltip : 'Draw Chart',
|
||||
title : 'Draw',
|
||||
'draw' : new Ui.ButtonIcon({
|
||||
icon : 'fa-line-chart',
|
||||
tooltip : 'Render Visualization',
|
||||
title : 'Visualize',
|
||||
onclick : function() {
|
||||
self._saveChart();
|
||||
self._drawChart();
|
||||
}
|
||||
}),
|
||||
'back' : new Ui.ButtonIcon({
|
||||
@@ -28,7 +28,7 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
|
||||
title : 'Cancel',
|
||||
onclick : function() {
|
||||
self.app.go( 'viewer' );
|
||||
self.app.storage.load();
|
||||
self.chart.load();
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -38,13 +38,24 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
|
||||
this.types = new TypesView( app, {
|
||||
onchange : function( chart_type ) {
|
||||
var chart_definition = self.app.types[ chart_type ];
|
||||
!chart_definition && console.debug( 'FAILED - Editor::onchange() - Chart type not supported.' );
|
||||
self.chart.definition = chart_definition;
|
||||
self.chart.set( { type : chart_type, modified : true } );
|
||||
console.debug( 'Editor::onchange() - Switched chart type.' );
|
||||
if ( !chart_definition ) {
|
||||
self.tabs.hideTab( 'settings' );
|
||||
self.tabs.hideTab( 'groups' );
|
||||
self.portlet.hideOperation( 'draw' );
|
||||
console.debug( 'editor::onchange() - Chart type not found.' );
|
||||
self.message.update( { message: 'The requested visualization type could not be found. Please select a new type from below or contact us.', status: 'danger', persistent: true } );
|
||||
} else {
|
||||
self.tabs.showTab( 'settings' );
|
||||
self.tabs.showTab( 'groups' );
|
||||
self.portlet.showOperation( 'draw' );
|
||||
self.chart.definition = chart_definition;
|
||||
self.chart.set( { type : chart_type, modified : true } );
|
||||
self.message.model.set( 'message', '' );
|
||||
console.debug( 'editor::onchange() - Switched visualization type.' );
|
||||
}
|
||||
},
|
||||
ondblclick : function( chart_id ) {
|
||||
self._saveChart();
|
||||
self._drawChart();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -62,25 +73,25 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
|
||||
id : 'main',
|
||||
title : 'Start',
|
||||
icon : 'fa fa-bars',
|
||||
tooltip : 'Start by selecting a chart type.',
|
||||
$el : $( '<div/>' ).append( ( new Ui.Label( { title : 'Provide a chart title:' } ).$el ) )
|
||||
tooltip : 'Start by selecting a visualization.',
|
||||
$el : $( '<div/>' ).append( ( new Ui.Label( { title : 'Provide a title:' } ).$el ) )
|
||||
.append( this.title.$el )
|
||||
.append( $( '<div/>' ).addClass( 'ui-form-info ui-margin-bottom' ).html( 'This title will appear in the list of \'Saved Visualizations\'. Charts are saved upon creation.' ) )
|
||||
.append( ( new Ui.Label( { title : 'Select a chart type:' } ).$el.addClass( 'ui-margin-top' ) ) )
|
||||
.append( $( '<div/>' ).addClass( 'ui-form-info ui-margin-bottom' ).html( 'This title will appear in the list of \'Saved Visualizations\'.' ) )
|
||||
.append( ( new Ui.Label( { title : 'Select a visualization:' } ).$el.addClass( 'ui-margin-top' ) ) )
|
||||
.append( this.types.$el )
|
||||
});
|
||||
this.tabs.add({
|
||||
id : 'settings',
|
||||
title : 'Customize',
|
||||
icon : 'fa-gear',
|
||||
tooltip : 'Customize charts options.',
|
||||
tooltip : 'Customize the visualization.',
|
||||
$el : ( new SettingsView( this.app ) ).$el
|
||||
});
|
||||
this.tabs.add({
|
||||
id : 'groups',
|
||||
title : 'Select data',
|
||||
icon : 'fa-database',
|
||||
tooltip : 'Specify your data options.',
|
||||
tooltip : 'Specify data options.',
|
||||
$el : ( new GroupsView( this.app ) ).$el
|
||||
});
|
||||
|
||||
@@ -92,10 +103,10 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
|
||||
this.tabs.hideOperation( 'back' );
|
||||
|
||||
// chart events
|
||||
this.chart.on( 'change:title', function( chart ) { self._refreshTitle() } );
|
||||
this.chart.on( 'change:type', function( chart ) { self.types.value( chart.get( 'type' ) ) } );
|
||||
this.chart.on( 'redraw', function( chart ) { self.portlet.showOperation( 'back' ) } );
|
||||
this.chart.reset( this.app.options );
|
||||
this.listenTo( this.chart, 'change:title', function( chart ) { self._refreshTitle() } );
|
||||
this.listenTo( this.chart, 'change:type', function( chart ) { self.types.value( chart.get( 'type' ) ) } );
|
||||
this.listenTo( this.chart, 'redraw', function( chart ) { self.portlet.showOperation( 'back' ) } );
|
||||
this.chart.reset();
|
||||
},
|
||||
|
||||
/** Show editor */
|
||||
@@ -115,8 +126,8 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
|
||||
this.title.value( title );
|
||||
},
|
||||
|
||||
/** Save chart data */
|
||||
_saveChart: function() {
|
||||
/** Draw chart data */
|
||||
_drawChart: function() {
|
||||
var self = this;
|
||||
this.chart.set({
|
||||
type : this.types.value(),
|
||||
@@ -124,7 +135,7 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
|
||||
date : Utils.time()
|
||||
});
|
||||
if ( this.chart.groups.length == 0 ) {
|
||||
this.message.update( { message: 'Please specify data options before drawing the chart.' } );
|
||||
this.message.update( { message: 'Please specify data options before rendering the visualization.', persistent: false } );
|
||||
this.tabs.show( 'groups' );
|
||||
return;
|
||||
}
|
||||
@@ -134,7 +145,7 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
|
||||
if ( valid ) {
|
||||
_.each( group.get( '__data_columns' ), function( data_columns, name ) {
|
||||
if ( group.attributes[ name ] === null ) {
|
||||
self.message.update( { status: 'danger', message: 'This chart type requires column types not found in your tabular file.' } );
|
||||
self.message.update( { status: 'danger', message: 'This visualization type requires column types not found in your tabular file.', persistent: false } );
|
||||
self.tabs.show( 'groups' );
|
||||
valid = false;
|
||||
}
|
||||
@@ -144,7 +155,6 @@ define( [ 'mvc/ui/ui-tabs', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'utils/utils'
|
||||
if ( valid ) {
|
||||
this.app.go( 'viewer' );
|
||||
this.app.deferred.execute( function() {
|
||||
self.app.storage.save();
|
||||
self.chart.trigger( 'redraw' );
|
||||
});
|
||||
}
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
/** This class renders the chart configuration form. */
|
||||
/** This class renders the chart data selection form with repeats. */
|
||||
define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-repeat', 'mvc/form/form-data', 'plugin/views/description' ],
|
||||
function( Utils, Ui, Form, Repeat, FormData, Description ) {
|
||||
var GroupView = Backbone.View.extend({
|
||||
@@ -14,7 +14,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
var inputs = this.chart.definition.groups ? Utils.clone( this.chart.definition.groups ) : [];
|
||||
var inputs = this.chart.definition.groups ? Utils.clone( this.chart.definition.groups ) : {};
|
||||
var dataset_id = this.chart.get( 'dataset_id' );
|
||||
var chart_type = this.chart.get( 'type' );
|
||||
var chart_definition = this.chart.definition;
|
||||
@@ -34,7 +34,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-
|
||||
input.is_zero && columns.push( { 'label' : 'Column: None', 'value' : 'zero' } );
|
||||
var meta = dataset.metadata_column_types;
|
||||
for ( var key in meta ) {
|
||||
var valid = ( [ 'int', 'float' ].indexOf( meta[ key ] ) != -1 && input.is_numeric ) || input.is_text || input.is_label;
|
||||
var valid = ( [ 'int', 'float' ].indexOf( meta[ key ] ) != -1 && input.is_numeric ) || input.is_label;
|
||||
valid && columns.push( { 'label' : 'Column: ' + ( parseInt( key ) + 1 ), 'value' : key } );
|
||||
}
|
||||
input.data = columns;
|
||||
@@ -74,7 +74,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-
|
||||
onnew : function() { self.chart.groups.add( { id : Utils.uid() } ) }
|
||||
});
|
||||
this.description = new Description( this.app );
|
||||
this.message = new Ui.Message( { message : 'There are no options for this chart type.', persistent : true, status : 'info' } );
|
||||
this.message = new Ui.Message( { message : 'There are no options for this visualization type.', persistent : true, status : 'info' } );
|
||||
this.setElement( $( '<div/>' ).append( this.description.$el )
|
||||
.append( this.repeat.$el.addClass( 'ui-margin-bottom' ) )
|
||||
.append( this.message.$el.addClass( 'ui-margin-bottom' ) ) );
|
||||
+15
-3
@@ -6,13 +6,25 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-
|
||||
this.app = app;
|
||||
this.chart = app.chart;
|
||||
this.description = new Description( this.app );
|
||||
this.message = new Ui.Message( { message: 'There are no options for this chart type.', persistent: true, status: 'info' } );
|
||||
this.setElement( $( '<div/>' ).append( this.description.$el ).append( this.message.$el ).append( this.$form = $( '<div/>' ) ) );
|
||||
this.message = new Ui.Message( { message: 'There are no options for this visualization type.', persistent: true, status: 'info' } );
|
||||
this.setElement( $( '<div/>' ).append( this.description.$el )
|
||||
.append( this.message.$el.addClass( 'ui-margin-bottom' ) )
|
||||
.append( this.$form = $( '<div/>' ).addClass( 'ui-margin-bottom' ) ) );
|
||||
this.listenTo( this.chart, 'change', function() { self.render() } );
|
||||
},
|
||||
render: function() {
|
||||
var self = this;
|
||||
var inputs = Utils.clone( this.chart.definition.settings );
|
||||
var inputs = Utils.clone( this.chart.definition.settings ) || {};
|
||||
var panel_option = this.chart.definition.use_panels;
|
||||
if ( panel_option == 'both' ) {
|
||||
inputs[ '__use_panels' ] = {
|
||||
type : 'boolean',
|
||||
label : 'Use multi-panels',
|
||||
help : 'Would you like to separate your data into individual panels?'
|
||||
};
|
||||
} else {
|
||||
this.chart.settings.set( '__use_panels', panel_option == 'yes' ? 'true' : 'false' );
|
||||
}
|
||||
if ( _.size( inputs ) > 0 ) {
|
||||
FormData.visitInputs( inputs, function( input, name ) {
|
||||
var model_value = self.chart.settings.get( name );
|
||||
@@ -0,0 +1,115 @@
|
||||
/** This class renders the chart type selection grid. */
|
||||
define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs' ], function( Utils, Ui, Tabs ) {
|
||||
return Backbone.View.extend({
|
||||
events : {
|
||||
'click .item' : '_onclick',
|
||||
'dblclick .item' : '_ondblclick'
|
||||
},
|
||||
|
||||
initialize : function( app, options ) {
|
||||
var self = this;
|
||||
this.app = app;
|
||||
this.options = Utils.merge( options, this.optionsDefault );
|
||||
this.tabs = new Tabs.View( {} );
|
||||
this.setElement( this.tabs.$el.addClass( 'charts-types' ) );
|
||||
this.render();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.first = null;
|
||||
this.tabs.delAll();
|
||||
this._renderDefault();
|
||||
this._renderList();
|
||||
},
|
||||
|
||||
_renderDefault: function() {
|
||||
var self = this;
|
||||
var index = [];
|
||||
var title_length = 20;
|
||||
var $el = $( '<div/>' ).addClass( 'charts-grid' );
|
||||
_.each( this.app.types, function( type, type_id ) {
|
||||
if ( type.keywords.indexOf( 'default' ) !== -1 ) {
|
||||
var title = type.title.length < title_length ? type.title : type.title.substr( 0, title_length ) + '...';
|
||||
$el.append( $( self._templateThumbnailItem( {
|
||||
id : type_id,
|
||||
title : ( type.zoomable ? '<span class="fa fa-search-plus"/>' : '' ) + title + ' (' + type.library + ')',
|
||||
url : repository_root + '/visualizations/' + self.app.split( type_id ) + '/logo.png'
|
||||
})).tooltip( { title: type.description, placement: 'bottom' } ) );
|
||||
}
|
||||
});
|
||||
if ( $el.children().length > 0 ) {
|
||||
this.tabs.add( { id: Utils.uid(), title: 'Suggested visualizations', $el: $el } );
|
||||
}
|
||||
},
|
||||
|
||||
_renderList: function() {
|
||||
var self = this;
|
||||
var index = [];
|
||||
_.each( this.app.types, function( type, type_id ) {
|
||||
index.push( {
|
||||
id : type_id,
|
||||
title : ( type.zoomable ? '<span class="fa fa-search-plus"/>' : '' ) + type.title + ' (' + type.library + ')',
|
||||
description : type.description || 'No description available.',
|
||||
url : repository_root + '/visualizations/' + self.app.split( type_id ) + '/logo.png'
|
||||
});
|
||||
});
|
||||
if ( index.length > 0 ) {
|
||||
this.first = this.first || index[ 0 ].id;
|
||||
var $el = $( '<div/>' ).addClass( 'charts-grid' );
|
||||
_.each( index, function( d, i ) {
|
||||
$el.append( self._templateRegularItem( d ) );
|
||||
});
|
||||
this.tabs.add( { id: Utils.uid(), title: 'List of available visualizations', $el: $el } );
|
||||
}
|
||||
},
|
||||
|
||||
/** Set/Get selected chart type */
|
||||
value: function( new_value ) {
|
||||
if ( new_value !== undefined ) {
|
||||
new_value = new_value == '__first' ? this.first : new_value;
|
||||
var before = this.$( '.current' ).attr( 'chart_id' );
|
||||
this.$( '.current' ).removeClass( 'current' );
|
||||
this.$( '[chart_id="' + new_value + '"]' ).addClass( 'current' );
|
||||
var after = this.$( '.current' ).attr( 'chart_id' );
|
||||
if ( after != before && this.options.onchange ) {
|
||||
this.options.onchange( after );
|
||||
}
|
||||
}
|
||||
return this.$( '.current' ).attr( 'chart_id' );
|
||||
},
|
||||
|
||||
/** Add click handler */
|
||||
_onclick: function( e ) {
|
||||
this.value( $( e.target ).closest( '.item' ).attr( 'chart_id' ) );
|
||||
},
|
||||
|
||||
/** Add double click handler */
|
||||
_ondblclick: function( e ) {
|
||||
this.options.ondblclick && this.options.ondblclick( this.value() );
|
||||
},
|
||||
|
||||
/* Chart type template with image */
|
||||
_templateThumbnailItem: function( options ) {
|
||||
return '<div class="item item-float" chart_id="' + options.id + '">' +
|
||||
'<img class="image" src="' + options.url + '">' +
|
||||
'<div class="title ui-form-info">' + options.title + '</div>' +
|
||||
'<div>';
|
||||
},
|
||||
|
||||
/* Chart type template with image */
|
||||
_templateRegularItem: function( options ) {
|
||||
return '<div class="item" chart_id="' + options.id + '">' +
|
||||
'<table>' +
|
||||
'<tr>' +
|
||||
'<td>' +
|
||||
'<img class="image" src="' + options.url + '">' +
|
||||
'</td>' +
|
||||
'<td>' +
|
||||
'<div class="charts-description-title ui-form-info">' + options.title + '</div>' +
|
||||
'<div class="charts-description-text ui-form-info">' + options.description + '</div>' +
|
||||
'</td>' +
|
||||
'</tr>' +
|
||||
'<div>';
|
||||
}
|
||||
});
|
||||
});
|
||||
+28
-29
@@ -8,17 +8,13 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'plugin/views/vi
|
||||
this.chart = this.app.chart;
|
||||
this.viewport = new Viewport( app );
|
||||
this.message = new Ui.Message();
|
||||
|
||||
// button menu
|
||||
var picture_button_menu = new Ui.ButtonMenu({
|
||||
this.export_button = new Ui.ButtonMenu({
|
||||
icon : 'fa-camera',
|
||||
title : 'Screenshot',
|
||||
tooltip : 'Download as PNG, SVG or PDF file'
|
||||
title : 'Export',
|
||||
tooltip : 'Export/Download Visualization'
|
||||
});
|
||||
|
||||
// add png option
|
||||
picture_button_menu.addMenu({
|
||||
id : 'button-png',
|
||||
this.export_button.addMenu({
|
||||
key : 'png',
|
||||
title : 'Save as PNG',
|
||||
icon : 'fa-file',
|
||||
onclick : function() {
|
||||
@@ -33,10 +29,8 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'plugin/views/vi
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// add svg option
|
||||
picture_button_menu.addMenu({
|
||||
id : 'button-svg',
|
||||
this.export_button.addMenu({
|
||||
key : 'svg',
|
||||
title : 'Save as SVG',
|
||||
icon : 'fa-file-text-o',
|
||||
onclick : function() {
|
||||
@@ -51,15 +45,13 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'plugin/views/vi
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// add pdf option
|
||||
picture_button_menu.addMenu({
|
||||
id : 'button-png',
|
||||
this.export_button.addMenu({
|
||||
key : 'pdf',
|
||||
title : 'Save as PDF',
|
||||
icon : 'fa-file-o',
|
||||
onclick : function() {
|
||||
self.app.modal.show({
|
||||
title : 'Send chart data for PDF creation',
|
||||
title : 'Send visualization data for PDF creation',
|
||||
body : 'Galaxy does not provide integrated PDF export scripts. You may click \'Continue\' to create the PDF by using a 3rd party service (https://export.highcharts.com).',
|
||||
buttons : {
|
||||
'Cancel' : function() { self.app.modal.hide() },
|
||||
@@ -79,8 +71,6 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'plugin/views/vi
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// create portlet
|
||||
this.portlet = new Portlet.View({
|
||||
icon : 'fa-bar-chart-o',
|
||||
title: 'Viewport',
|
||||
@@ -88,7 +78,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'plugin/views/vi
|
||||
operations: {
|
||||
edit_button: new Ui.ButtonIcon({
|
||||
icon : 'fa-edit',
|
||||
tooltip : 'Customize this chart',
|
||||
tooltip : 'Customize this Visualization',
|
||||
title : 'Editor',
|
||||
onclick : function() {
|
||||
self._wait( self.chart, function() {
|
||||
@@ -96,17 +86,22 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'plugin/views/vi
|
||||
});
|
||||
}
|
||||
}),
|
||||
picture_button_menu: picture_button_menu
|
||||
export_button: this.export_button,
|
||||
save_button: new Ui.ButtonIcon({
|
||||
icon : 'fa-save',
|
||||
tooltip : 'Save this Visualization',
|
||||
title : 'Save',
|
||||
onclick : function() {
|
||||
self.message.update( { message: 'Saving \'' + self.chart.get( 'title' ) + '\'. It will appear in the list of \'Saved Visualizations\'.', status: 'success' } );
|
||||
self.chart.save( { error : function() { self.message.update( { message: 'Could not save visualization.', status: 'danger' } ) } } );
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
// append elements
|
||||
this.portlet.append( this.message.$el );
|
||||
this.portlet.append( this.viewport.$el.addClass( 'ui-margin-top' ) );
|
||||
this.setElement( this.portlet.$el );
|
||||
|
||||
// events
|
||||
this.chart.on( 'change:title', function() { self._refreshTitle() } );
|
||||
this.listenTo( this.chart, 'change', function() { self.render() } );
|
||||
},
|
||||
|
||||
/** Show and refresh viewer */
|
||||
@@ -121,9 +116,13 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'plugin/views/vi
|
||||
},
|
||||
|
||||
/** Change title */
|
||||
_refreshTitle: function() {
|
||||
render: function() {
|
||||
var title = this.chart.get( 'title' );
|
||||
this.portlet.title( title );
|
||||
var exports = this.chart.definition && this.chart.definition.exports || [];
|
||||
this.export_button.collection.each( function( model ) {
|
||||
model.set( 'visible', exports.indexOf( model.get( 'key' ) ) !== -1 );
|
||||
});
|
||||
},
|
||||
|
||||
/** Check if chart is ready for export */
|
||||
@@ -131,7 +130,7 @@ define( [ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-portlet', 'plugin/views/vi
|
||||
if ( this.app.deferred.ready() ) {
|
||||
callback();
|
||||
} else {
|
||||
this.message.update( { message: 'Your chart is currently being processed. Please wait and try again.' } );
|
||||
this.message.update( { message: 'Your visualization is currently being processed. Please wait and try again.' } );
|
||||
}
|
||||
}
|
||||
});
|
||||
+13
-31
@@ -1,6 +1,5 @@
|
||||
/**
|
||||
* The viewport creates and manages the dom elements used by the visualization plugins to draw the chart.
|
||||
* Additionally, this class creates default request strings and request dictionaries parsed to the visualization plugins.
|
||||
* This is the last class of the charts core classes before handing control over to the visualization plugins.
|
||||
*/
|
||||
define( [ 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils' ], function( Portlet, Ui, Utils ) {
|
||||
@@ -17,32 +16,15 @@ define( [ 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils' ], function( Port
|
||||
this.$info = this.$( '.info' );
|
||||
this.$icon = this.$( '.icon' );
|
||||
this.$text = this.$( '.text' );
|
||||
|
||||
// use full screen for viewer
|
||||
this._fullscreen( this.$el, 55 );
|
||||
|
||||
// prevent window scrolling
|
||||
var initial_overflow = $( 'body' ).css( 'overflow' );
|
||||
this.$el.on( 'mouseover', function() {
|
||||
$( 'body' ).css( 'overflow', 'hidden' );
|
||||
}).on('mouseout', function() {
|
||||
$( 'body' ).css( 'overflow', initial_overflow );
|
||||
});
|
||||
|
||||
// create container element
|
||||
this._createContainer( 'div' );
|
||||
|
||||
// link redraw trigger
|
||||
var self = this;
|
||||
this.chart.on( 'redraw', function() {
|
||||
self.app.deferred.execute( function( process ) {
|
||||
self._draw( process, self.chart );
|
||||
});
|
||||
});
|
||||
|
||||
// link status handler
|
||||
this.chart.on( 'set:state', function() {
|
||||
var $container = self.$el.find( '.charts-viewport-container' );
|
||||
var $container = self.$( '.charts-viewport-container' );
|
||||
var $info = self.$info;
|
||||
var $icon = self.$icon;
|
||||
var $text = self.$text;
|
||||
@@ -86,33 +68,33 @@ define( [ 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'utils/utils' ], function( Port
|
||||
|
||||
/** A chart may contain multiple sub charts/containers which are created here */
|
||||
_createContainer: function( tag, n ) {
|
||||
tag = tag || 'div';
|
||||
n = n || 1;
|
||||
for ( var i in this.container_list ) {
|
||||
this.container_list[ i ].remove();
|
||||
}
|
||||
this.container_list = [];
|
||||
this.canvas_list = [];
|
||||
this.$( '.charts-viewport-container' ).remove();
|
||||
this.targets = [];
|
||||
for ( var i = 0; i < n; i++ ) {
|
||||
var container_id = Utils.uid();
|
||||
var container_el = $( '<div/>' ).addClass( 'charts-viewport-container' )
|
||||
.width( parseInt( 100 / n ) + '%' )
|
||||
.append( $( '<div/>' ).attr( 'id', 'menu' ) )
|
||||
.append( $( '<' + tag + ' class="charts-viewport-canvas" />' ).attr( 'id', container_id ) );
|
||||
this.$el.append( container_el );
|
||||
this.container_list[ i ] = container_el;
|
||||
this.canvas_list[ i ] = container_id;
|
||||
this.targets.push( container_id );
|
||||
}
|
||||
},
|
||||
|
||||
/** Draws a new chart by loading and executing the corresponding chart wrapper */
|
||||
_draw: function( process, chart ) {
|
||||
var self = this;
|
||||
var n_panels = chart.settings.get( 'use_panels' ) === 'true' ? chart.groups.length : 1;
|
||||
var n_panels = chart.settings.get( '__use_panels' ) == 'true' ? chart.groups.length : 1;
|
||||
this._createContainer( chart.definition.tag, n_panels );
|
||||
chart.state( 'wait', 'Please wait...' );
|
||||
require( [ 'plugin/charts/' + this.app.split( chart.get( 'type' ) ) + '/wrapper' ], function( ChartView ) {
|
||||
new ChartView( self.app, { process : process, chart : chart, canvas_list : self.canvas_list } );
|
||||
require( [ 'repository/build/' + chart.get( 'type' ) ], function( ChartView ) {
|
||||
new ChartView( { process: process, chart: chart, dataset: self.app.dataset, targets: self.targets } );
|
||||
}, function( err ) {
|
||||
chart.state( 'failed', 'Please verify that your internet connection works properly. This visualization could not be accessed in the repository. Please contact the Galaxy Team if this error persists.' );
|
||||
console.debug( err );
|
||||
process.resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,39 +0,0 @@
|
||||
define( [ 'utils/utils' ], function( Utils ) {
|
||||
return Backbone.Model.extend({
|
||||
defaults : {
|
||||
id : null,
|
||||
title : '',
|
||||
type : '',
|
||||
date : null,
|
||||
state : '',
|
||||
state_info : '',
|
||||
modified : false,
|
||||
dataset_id : '',
|
||||
dataset_id_job : ''
|
||||
},
|
||||
|
||||
initialize: function( options ) {
|
||||
this.groups = new Backbone.Collection();
|
||||
this.settings = new Backbone.Model();
|
||||
this.definition = {};
|
||||
},
|
||||
|
||||
reset: function( options ) {
|
||||
this.set({
|
||||
'id' : Utils.uid(),
|
||||
'type' : 'nvd3_bar',
|
||||
'dataset_id' : options.config.dataset_id,
|
||||
'title' : 'New Chart'
|
||||
});
|
||||
this.settings.clear();
|
||||
this.groups.reset();
|
||||
this.groups.add( { id : Utils.uid() } );
|
||||
},
|
||||
|
||||
state: function( value, info ) {
|
||||
this.set( { 'state': value, 'state_info': info } );
|
||||
this.trigger( 'set:state' );
|
||||
console.debug( 'Chart:state() - ' + info + ' (' + value + ')' );
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,279 +0,0 @@
|
||||
/**
|
||||
* This class enables users to export/download a chart as PNG, SVG or PDF.
|
||||
*/
|
||||
define(["libs/underscore"], function(_) {
|
||||
//
|
||||
// PNG export
|
||||
//
|
||||
function createPNG (options) {
|
||||
if (options.$el.find('svg').length > 0) {
|
||||
_fromSVGtoPNG (options);
|
||||
} else {
|
||||
_fromCanvas (options);
|
||||
}
|
||||
};
|
||||
|
||||
// from jqplot
|
||||
function _fromCanvas (options) {
|
||||
try {
|
||||
var $canvas = options.$el.find('.jqplot-target');
|
||||
var imgData = $canvas.jqplotToImageStr({});
|
||||
if (imgData) {
|
||||
window.location.href = imgData.replace('image/png', 'image/octet-stream');
|
||||
}
|
||||
} catch (err) {
|
||||
console.debug('FAILED - Screenshot::_fromCanvas() - ' + err);
|
||||
if (options.error) {
|
||||
options.error('Please reduce your chart to a single panel and try again.');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// from svg
|
||||
function _fromSVGtoPNG (options) {
|
||||
|
||||
// get parameters
|
||||
var $el = options.$el;
|
||||
var screenshot_url = options.url;
|
||||
var name = options.name;
|
||||
|
||||
// serialize svg
|
||||
var serializer = new XMLSerializer();
|
||||
|
||||
// create canvas
|
||||
var canvas = document.createElement('canvas');
|
||||
var $canvas = $(canvas);
|
||||
|
||||
// get svg dimensions
|
||||
var nsvgs = $el.find('svg').length;
|
||||
var first = $el.find('svg').first();
|
||||
var height = parseInt(first.css('height'));
|
||||
var width = parseInt(first.css('width'));
|
||||
|
||||
// set canvas dimensions
|
||||
$canvas.attr('width', width*nsvgs);
|
||||
$canvas.attr('height', height);
|
||||
|
||||
// check context support
|
||||
if (!canvas.getContext || !canvas.getContext('2d')) {
|
||||
alert ("Your browser doesn't support this feature, please use a modern browser");
|
||||
}
|
||||
|
||||
// context
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
// write all svgs
|
||||
var offsetX = 0;
|
||||
$el.find('svg').each(function() {
|
||||
// get svg element
|
||||
var $svg = $(this);
|
||||
|
||||
// configure svg
|
||||
$svg.attr({
|
||||
version : '1.1',
|
||||
xmlns : 'http://www.w3.org/2000/svg',
|
||||
width : width,
|
||||
height : height
|
||||
});
|
||||
|
||||
// create xml string
|
||||
var xmlString = serializer.serializeToString(this);
|
||||
|
||||
// draw into canvas
|
||||
ctx.drawSvg(xmlString, offsetX, 0, width, height)
|
||||
|
||||
// shift offset for multipanel charts
|
||||
offsetX += width;
|
||||
});
|
||||
|
||||
// post image
|
||||
window.location.href = _canvasToImage(canvas, canvas.getContext('2d'), 'white').replace('image/png', 'image/octet-stream');
|
||||
};
|
||||
|
||||
// create image
|
||||
function _canvasToImage(canvas, context, backgroundColor) {
|
||||
// cache height and width
|
||||
var w = canvas.width;
|
||||
var h = canvas.height;
|
||||
var data;
|
||||
|
||||
if(backgroundColor) {
|
||||
// get the current ImageData for the canvas.
|
||||
data = context.getImageData(0, 0, w, h);
|
||||
|
||||
// store the current globalCompositeOperation
|
||||
var compositeOperation = context.globalCompositeOperation;
|
||||
|
||||
// set to draw behind current content
|
||||
context.globalCompositeOperation = "destination-over";
|
||||
|
||||
// set background color
|
||||
context.fillStyle = backgroundColor;
|
||||
|
||||
// draw background / rect on entire canvas
|
||||
context.fillRect(0,0,w,h);
|
||||
}
|
||||
|
||||
// get the image data from the canvas
|
||||
var imageData = canvas.toDataURL("image/png");
|
||||
|
||||
if(backgroundColor) {
|
||||
// clear the canvas
|
||||
context.clearRect (0,0,w,h);
|
||||
|
||||
// restore it with original / cached ImageData
|
||||
context.putImageData(data, 0,0);
|
||||
|
||||
// reset the globalCompositeOperation to what it was
|
||||
context.globalCompositeOperation = compositeOperation;
|
||||
}
|
||||
|
||||
// return the Base64 encoded data url string
|
||||
return imageData;
|
||||
};
|
||||
|
||||
//
|
||||
// SVG export
|
||||
//
|
||||
function createSVG (options) {
|
||||
window.location.href = 'data:none/none;base64,' + btoa(createXML(options).string);
|
||||
};
|
||||
|
||||
// css inliner
|
||||
function _inline ($target) {
|
||||
for (var sheet_id in document.styleSheets) {
|
||||
var sheet = document.styleSheets[sheet_id];
|
||||
var rules = sheet.cssRules;
|
||||
if (rules) {
|
||||
for (var idx = 0, len = rules.length; idx < len; idx++) {
|
||||
try {
|
||||
$target.find(rules[idx].selectorText).each(function (i, elem) {
|
||||
elem.style.cssText += rules[idx].style.cssText;
|
||||
});
|
||||
} catch(err) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// PDF export
|
||||
//
|
||||
function createPDF (options) {
|
||||
|
||||
// do the post
|
||||
var xml = createXML(options);
|
||||
|
||||
// post data
|
||||
var data = {
|
||||
filename : name || 'chart',
|
||||
type : 'application/pdf',
|
||||
height : xml.height,
|
||||
width : xml.width,
|
||||
scale : 2,
|
||||
svg : xml.string
|
||||
};
|
||||
|
||||
|
||||
// create the form
|
||||
var $el = $('body');
|
||||
var form = $el.find('#viewport-form');
|
||||
if (form.length === 0) {
|
||||
form = $('<form>', {
|
||||
id : 'viewport-form',
|
||||
method : 'post',
|
||||
action : 'http://export.highcharts.com/',
|
||||
display : 'none'
|
||||
});
|
||||
$el.append(form);
|
||||
}
|
||||
|
||||
// reset form
|
||||
form.empty();
|
||||
|
||||
// add the data
|
||||
for (name in data) {
|
||||
var input = $('<input/>', {
|
||||
type : 'hidden',
|
||||
name : name,
|
||||
value : data[name]
|
||||
});
|
||||
form.append(input);
|
||||
}
|
||||
|
||||
// submit
|
||||
try {
|
||||
form.submit();
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// XML export
|
||||
//
|
||||
function createXML (options) {
|
||||
if (options.$el.find('svg').length == 0) {
|
||||
if (options.error) {
|
||||
options.error('No SVG found. This chart type does not support SVG/PDF export.');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// get parameters
|
||||
var $el = options.$el;
|
||||
|
||||
// get svg dimensions
|
||||
var nsvgs = $el.find('svg').length;
|
||||
var height = parseInt($el.find('svg').first().css('height'));
|
||||
var width = parseInt($el.find('svg').first().css('width'));
|
||||
|
||||
// serialize svg
|
||||
var serializer = new XMLSerializer();
|
||||
|
||||
// get svg element
|
||||
var $composite = $('<svg/>');
|
||||
|
||||
// configure svg
|
||||
$composite.attr({
|
||||
version : '1.1',
|
||||
xmlns : 'http://www.w3.org/2000/svg',
|
||||
width : width*nsvgs,
|
||||
height : height
|
||||
});
|
||||
|
||||
// write all svgs
|
||||
var xmlString = '';
|
||||
var offsetX = 0;
|
||||
$el.find('svg').each(function() {
|
||||
var $svg = $(this).clone();
|
||||
|
||||
// inline css
|
||||
_inline($svg);
|
||||
|
||||
// create group and append to composite svg
|
||||
var $g = $('<g transform="translate(' + offsetX + ', 0)">');
|
||||
$g.append($svg.find('g').first());
|
||||
$composite.append($g);
|
||||
|
||||
// shift offset for multipanel charts
|
||||
offsetX += width;
|
||||
});
|
||||
|
||||
// create xml string
|
||||
return {
|
||||
string : serializer.serializeToString($composite[0]),
|
||||
height : height,
|
||||
width : width
|
||||
}
|
||||
};
|
||||
|
||||
// return
|
||||
return {
|
||||
createPNG: createPNG,
|
||||
createSVG: createSVG,
|
||||
createPDF: createPDF
|
||||
};
|
||||
|
||||
});
|
||||
@@ -1,79 +0,0 @@
|
||||
/** This class saves and loads a chart through the api. */
|
||||
define( [ 'utils/utils', 'plugin/components/model', 'mvc/visualization/visualization-model' ], function( Utils, Chart ) {
|
||||
return Backbone.Model.extend({
|
||||
|
||||
initialize: function( app ) {
|
||||
this.app = app;
|
||||
this.chart = this.app.chart;
|
||||
this.options = this.app.options;
|
||||
this.id = this.options.id;
|
||||
this.vis = new Visualization({
|
||||
id : this.id,
|
||||
type : 'charts',
|
||||
config : {
|
||||
dataset_id : this.options.config.dataset_id,
|
||||
chart_dict : {}
|
||||
}
|
||||
});
|
||||
var chart_dict = this.options.config.chart_dict;
|
||||
if ( chart_dict ) {
|
||||
this.vis.get( 'config' ).chart_dict = chart_dict;
|
||||
}
|
||||
},
|
||||
|
||||
/** Pack and save nested chart model */
|
||||
save: function() {
|
||||
var self = this;
|
||||
var chart = this.app.chart;
|
||||
var chart_dict = {
|
||||
attributes : chart.attributes,
|
||||
settings : chart.settings.attributes,
|
||||
groups : []
|
||||
};
|
||||
chart.groups.each( function( group ) {
|
||||
chart_dict.groups.push( group.attributes );
|
||||
});
|
||||
this.vis.set( 'title', chart.get( 'title' ) || '' );
|
||||
this.vis.get( 'config' ).chart_dict = chart_dict;
|
||||
this.vis.save()
|
||||
.fail(function( xhr, status, message ) {
|
||||
self.app.showModal( 'Saving failed.', 'An attempt to save this chart to the server failed. Please try again and contact the administrator.' );
|
||||
})
|
||||
.then( function( response ) {
|
||||
if ( response && response.id ) {
|
||||
self.id = response.id;
|
||||
} else {
|
||||
console.debug( 'Storage::save() - Unrecognized response. Saving may have failed.' );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** Load nested models/collections from packed dictionary */
|
||||
load: function() {
|
||||
var chart_dict = this.vis.get( 'config' ).chart_dict;
|
||||
if ( !chart_dict.attributes ) {
|
||||
console.debug( 'Storage::load() - Chart attributes not found. Invalid format.' );
|
||||
return false;
|
||||
}
|
||||
var chart_type = chart_dict.attributes[ 'type' ];
|
||||
if ( !chart_type ) {
|
||||
console.debug( 'Storage::load() - Chart type not provided. Invalid format.' );
|
||||
return false;
|
||||
}
|
||||
var chart_definition = this.app.types[ chart_type ];
|
||||
if ( !chart_definition ) {
|
||||
console.debug( 'Storage::load() - Chart type not supported. Please re-configure the chart.' );
|
||||
return false;
|
||||
}
|
||||
this.chart.definition = chart_definition;
|
||||
this.chart.set( chart_dict.attributes );
|
||||
this.chart.state( 'ok', 'Loading saved visualization...' );
|
||||
this.chart.settings.set( chart_dict.settings );
|
||||
this.chart.groups.reset();
|
||||
this.chart.groups.add( chart_dict.groups );
|
||||
this.chart.set( 'modified', false );
|
||||
console.debug( 'Storage::load() - Loading chart type ' + chart_type + '.' );
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,287 +0,0 @@
|
||||
/**
|
||||
* A class to parse color values
|
||||
* @author Stoyan Stefanov <sstoo@gmail.com>
|
||||
* @link http://www.phpied.com/rgb-color-parser-in-javascript/
|
||||
* @license Use it if you like it
|
||||
*/
|
||||
function RGBColor(color_string)
|
||||
{
|
||||
this.ok = false;
|
||||
|
||||
// strip any leading #
|
||||
if (color_string.charAt(0) == '#') { // remove # if any
|
||||
color_string = color_string.substr(1,6);
|
||||
}
|
||||
|
||||
color_string = color_string.replace(/ /g,'');
|
||||
color_string = color_string.toLowerCase();
|
||||
|
||||
// before getting into regexps, try simple matches
|
||||
// and overwrite the input
|
||||
var simple_colors = {
|
||||
aliceblue: 'f0f8ff',
|
||||
antiquewhite: 'faebd7',
|
||||
aqua: '00ffff',
|
||||
aquamarine: '7fffd4',
|
||||
azure: 'f0ffff',
|
||||
beige: 'f5f5dc',
|
||||
bisque: 'ffe4c4',
|
||||
black: '000000',
|
||||
blanchedalmond: 'ffebcd',
|
||||
blue: '0000ff',
|
||||
blueviolet: '8a2be2',
|
||||
brown: 'a52a2a',
|
||||
burlywood: 'deb887',
|
||||
cadetblue: '5f9ea0',
|
||||
chartreuse: '7fff00',
|
||||
chocolate: 'd2691e',
|
||||
coral: 'ff7f50',
|
||||
cornflowerblue: '6495ed',
|
||||
cornsilk: 'fff8dc',
|
||||
crimson: 'dc143c',
|
||||
cyan: '00ffff',
|
||||
darkblue: '00008b',
|
||||
darkcyan: '008b8b',
|
||||
darkgoldenrod: 'b8860b',
|
||||
darkgray: 'a9a9a9',
|
||||
darkgreen: '006400',
|
||||
darkkhaki: 'bdb76b',
|
||||
darkmagenta: '8b008b',
|
||||
darkolivegreen: '556b2f',
|
||||
darkorange: 'ff8c00',
|
||||
darkorchid: '9932cc',
|
||||
darkred: '8b0000',
|
||||
darksalmon: 'e9967a',
|
||||
darkseagreen: '8fbc8f',
|
||||
darkslateblue: '483d8b',
|
||||
darkslategray: '2f4f4f',
|
||||
darkturquoise: '00ced1',
|
||||
darkviolet: '9400d3',
|
||||
deeppink: 'ff1493',
|
||||
deepskyblue: '00bfff',
|
||||
dimgray: '696969',
|
||||
dodgerblue: '1e90ff',
|
||||
feldspar: 'd19275',
|
||||
firebrick: 'b22222',
|
||||
floralwhite: 'fffaf0',
|
||||
forestgreen: '228b22',
|
||||
fuchsia: 'ff00ff',
|
||||
gainsboro: 'dcdcdc',
|
||||
ghostwhite: 'f8f8ff',
|
||||
gold: 'ffd700',
|
||||
goldenrod: 'daa520',
|
||||
gray: '808080',
|
||||
green: '008000',
|
||||
greenyellow: 'adff2f',
|
||||
honeydew: 'f0fff0',
|
||||
hotpink: 'ff69b4',
|
||||
indianred : 'cd5c5c',
|
||||
indigo : '4b0082',
|
||||
ivory: 'fffff0',
|
||||
khaki: 'f0e68c',
|
||||
lavender: 'e6e6fa',
|
||||
lavenderblush: 'fff0f5',
|
||||
lawngreen: '7cfc00',
|
||||
lemonchiffon: 'fffacd',
|
||||
lightblue: 'add8e6',
|
||||
lightcoral: 'f08080',
|
||||
lightcyan: 'e0ffff',
|
||||
lightgoldenrodyellow: 'fafad2',
|
||||
lightgrey: 'd3d3d3',
|
||||
lightgreen: '90ee90',
|
||||
lightpink: 'ffb6c1',
|
||||
lightsalmon: 'ffa07a',
|
||||
lightseagreen: '20b2aa',
|
||||
lightskyblue: '87cefa',
|
||||
lightslateblue: '8470ff',
|
||||
lightslategray: '778899',
|
||||
lightsteelblue: 'b0c4de',
|
||||
lightyellow: 'ffffe0',
|
||||
lime: '00ff00',
|
||||
limegreen: '32cd32',
|
||||
linen: 'faf0e6',
|
||||
magenta: 'ff00ff',
|
||||
maroon: '800000',
|
||||
mediumaquamarine: '66cdaa',
|
||||
mediumblue: '0000cd',
|
||||
mediumorchid: 'ba55d3',
|
||||
mediumpurple: '9370d8',
|
||||
mediumseagreen: '3cb371',
|
||||
mediumslateblue: '7b68ee',
|
||||
mediumspringgreen: '00fa9a',
|
||||
mediumturquoise: '48d1cc',
|
||||
mediumvioletred: 'c71585',
|
||||
midnightblue: '191970',
|
||||
mintcream: 'f5fffa',
|
||||
mistyrose: 'ffe4e1',
|
||||
moccasin: 'ffe4b5',
|
||||
navajowhite: 'ffdead',
|
||||
navy: '000080',
|
||||
oldlace: 'fdf5e6',
|
||||
olive: '808000',
|
||||
olivedrab: '6b8e23',
|
||||
orange: 'ffa500',
|
||||
orangered: 'ff4500',
|
||||
orchid: 'da70d6',
|
||||
palegoldenrod: 'eee8aa',
|
||||
palegreen: '98fb98',
|
||||
paleturquoise: 'afeeee',
|
||||
palevioletred: 'd87093',
|
||||
papayawhip: 'ffefd5',
|
||||
peachpuff: 'ffdab9',
|
||||
peru: 'cd853f',
|
||||
pink: 'ffc0cb',
|
||||
plum: 'dda0dd',
|
||||
powderblue: 'b0e0e6',
|
||||
purple: '800080',
|
||||
red: 'ff0000',
|
||||
rosybrown: 'bc8f8f',
|
||||
royalblue: '4169e1',
|
||||
saddlebrown: '8b4513',
|
||||
salmon: 'fa8072',
|
||||
sandybrown: 'f4a460',
|
||||
seagreen: '2e8b57',
|
||||
seashell: 'fff5ee',
|
||||
sienna: 'a0522d',
|
||||
silver: 'c0c0c0',
|
||||
skyblue: '87ceeb',
|
||||
slateblue: '6a5acd',
|
||||
slategray: '708090',
|
||||
snow: 'fffafa',
|
||||
springgreen: '00ff7f',
|
||||
steelblue: '4682b4',
|
||||
tan: 'd2b48c',
|
||||
teal: '008080',
|
||||
thistle: 'd8bfd8',
|
||||
tomato: 'ff6347',
|
||||
turquoise: '40e0d0',
|
||||
violet: 'ee82ee',
|
||||
violetred: 'd02090',
|
||||
wheat: 'f5deb3',
|
||||
white: 'ffffff',
|
||||
whitesmoke: 'f5f5f5',
|
||||
yellow: 'ffff00',
|
||||
yellowgreen: '9acd32'
|
||||
};
|
||||
for (var key in simple_colors) {
|
||||
if (color_string == key) {
|
||||
color_string = simple_colors[key];
|
||||
}
|
||||
}
|
||||
// emd of simple type-in colors
|
||||
|
||||
// array of color definition objects
|
||||
var color_defs = [
|
||||
{
|
||||
re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
|
||||
example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
|
||||
process: function (bits){
|
||||
return [
|
||||
parseInt(bits[1]),
|
||||
parseInt(bits[2]),
|
||||
parseInt(bits[3])
|
||||
];
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^(\w{2})(\w{2})(\w{2})$/,
|
||||
example: ['#00ff00', '336699'],
|
||||
process: function (bits){
|
||||
return [
|
||||
parseInt(bits[1], 16),
|
||||
parseInt(bits[2], 16),
|
||||
parseInt(bits[3], 16)
|
||||
];
|
||||
}
|
||||
},
|
||||
{
|
||||
re: /^(\w{1})(\w{1})(\w{1})$/,
|
||||
example: ['#fb0', 'f0f'],
|
||||
process: function (bits){
|
||||
return [
|
||||
parseInt(bits[1] + bits[1], 16),
|
||||
parseInt(bits[2] + bits[2], 16),
|
||||
parseInt(bits[3] + bits[3], 16)
|
||||
];
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// search through the definitions to find a match
|
||||
for (var i = 0; i < color_defs.length; i++) {
|
||||
var re = color_defs[i].re;
|
||||
var processor = color_defs[i].process;
|
||||
var bits = re.exec(color_string);
|
||||
if (bits) {
|
||||
channels = processor(bits);
|
||||
this.r = channels[0];
|
||||
this.g = channels[1];
|
||||
this.b = channels[2];
|
||||
this.ok = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// validate/cleanup values
|
||||
this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
|
||||
this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
|
||||
this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);
|
||||
|
||||
// some getters
|
||||
this.toRGB = function () {
|
||||
return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
|
||||
}
|
||||
this.toHex = function () {
|
||||
var r = this.r.toString(16);
|
||||
var g = this.g.toString(16);
|
||||
var b = this.b.toString(16);
|
||||
if (r.length == 1) r = '0' + r;
|
||||
if (g.length == 1) g = '0' + g;
|
||||
if (b.length == 1) b = '0' + b;
|
||||
return '#' + r + g + b;
|
||||
}
|
||||
|
||||
// help
|
||||
this.getHelpXML = function () {
|
||||
|
||||
var examples = new Array();
|
||||
// add regexps
|
||||
for (var i = 0; i < color_defs.length; i++) {
|
||||
var example = color_defs[i].example;
|
||||
for (var j = 0; j < example.length; j++) {
|
||||
examples[examples.length] = example[j];
|
||||
}
|
||||
}
|
||||
// add type-in colors
|
||||
for (var sc in simple_colors) {
|
||||
examples[examples.length] = sc;
|
||||
}
|
||||
|
||||
var xml = document.createElement('ul');
|
||||
xml.setAttribute('id', 'rgbcolor-examples');
|
||||
for (var i = 0; i < examples.length; i++) {
|
||||
try {
|
||||
var list_item = document.createElement('li');
|
||||
var list_color = new RGBColor(examples[i]);
|
||||
var example_div = document.createElement('div');
|
||||
example_div.style.cssText =
|
||||
'margin: 3px; '
|
||||
+ 'border: 1px solid black; '
|
||||
+ 'background:' + list_color.toHex() + '; '
|
||||
+ 'color:' + list_color.toHex()
|
||||
;
|
||||
example_div.appendChild(document.createTextNode('test'));
|
||||
var list_item_value = document.createTextNode(
|
||||
' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
|
||||
);
|
||||
list_item.appendChild(example_div);
|
||||
list_item.appendChild(list_item_value);
|
||||
xml.appendChild(list_item);
|
||||
|
||||
} catch(e){}
|
||||
}
|
||||
return xml;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Vendored
-3
File diff suppressed because one or more lines are too long
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com
|
||||
jsDate | (c) 2010-2013 Chris Leonello
|
||||
*/(function(a){a.jqplot.BlockRenderer=function(){a.jqplot.LineRenderer.call(this)};a.jqplot.BlockRenderer.prototype=new a.jqplot.LineRenderer();a.jqplot.BlockRenderer.prototype.constructor=a.jqplot.BlockRenderer;a.jqplot.BlockRenderer.prototype.init=function(b){this.css={padding:"2px",border:"1px solid #999",textAlign:"center"};this.escapeHtml=false;this.insertBreaks=true;this.varyBlockColors=false;a.extend(true,this,b);if(this.css.backgroundColor){this.color=this.css.backgroundColor}else{if(this.css.background){this.color=this.css.background}else{if(!this.varyBlockColors){this.css.background=this.color}}}this.canvas=new a.jqplot.BlockCanvas();this.shadowCanvas=new a.jqplot.BlockCanvas();this.canvas._plotDimensions=this._plotDimensions;this.shadowCanvas._plotDimensions=this._plotDimensions;this._type="block";this.moveBlock=function(l,j,i,e){var c=this.canvas._elem.children(":eq("+l+")");this.data[l][0]=j;this.data[l][1]=i;this._plotData[l][0]=j;this._plotData[l][1]=i;this._stackData[l][0]=j;this._stackData[l][1]=i;this.gridData[l][0]=this._xaxis.series_u2p(j);this.gridData[l][1]=this._yaxis.series_u2p(i);var k=c.outerWidth();var f=c.outerHeight();var d=this.gridData[l][0]-k/2+"px";var g=this.gridData[l][1]-f/2+"px";if(e){if(parseInt(e,10)){e=parseInt(e,10)}c.animate({left:d,top:g},e)}else{c.css({left:d,top:g})}c=null}};a.jqplot.BlockRenderer.prototype.draw=function(q,o,r){if(this.plugins.pointLabels){this.plugins.pointLabels.show=false}var f,c,l,o,p,k,n,g,e,m;var b=(r!=undefined)?r:{};var j=new a.jqplot.ColorGenerator(this.seriesColors);this.canvas._elem.empty();for(f=0;f<this.gridData.length;f++){l=this.data[f];o=this.gridData[f];p="";k={};if(typeof l[2]=="string"){p=l[2]}else{if(typeof l[2]=="object"){k=l[2]}}if(typeof l[3]=="object"){k=l[3]}if(this.insertBreaks){p=p.replace(/ /g,"<br />")}k=a.extend(true,{},this.css,k);c=a('<div style="position:absolute;margin-left:auto;margin-right:auto;"></div>');this.canvas._elem.append(c);this.escapeHtml?c.text(p):c.html(p);delete k.position;delete k.marginRight;delete k.marginLeft;if(!k.background&&!k.backgroundColor&&!k.backgroundImage){k.background=j.next()}c.css(k);n=c.outerWidth();g=c.outerHeight();e=o[0]-n/2+"px";m=o[1]-g/2+"px";c.css({left:e,top:m});c=null}};a.jqplot.BlockCanvas=function(){a.jqplot.ElemContainer.call(this);this._ctx};a.jqplot.BlockCanvas.prototype=new a.jqplot.ElemContainer();a.jqplot.BlockCanvas.prototype.constructor=a.jqplot.BlockCanvas;a.jqplot.BlockCanvas.prototype.createElement=function(i,e,c){this._offsets=i;var b="jqplot-blockCanvas";if(e!=undefined){b=e}var g;if(this._elem){g=this._elem.get(0)}else{g=document.createElement("div")}if(c!=undefined){this._plotDimensions=c}var d=this._plotDimensions.width-this._offsets.left-this._offsets.right+"px";var f=this._plotDimensions.height-this._offsets.top-this._offsets.bottom+"px";this._elem=a(g);this._elem.css({position:"absolute",width:d,height:f,left:this._offsets.left,top:this._offsets.top});this._elem.addClass(b);return this._elem};a.jqplot.BlockCanvas.prototype.setContext=function(){this._ctx={canvas:{width:0,height:0},clearRect:function(){return null}};return this._ctx}})(jQuery);
|
||||
Vendored
-129
@@ -1,129 +0,0 @@
|
||||
(function($) {
|
||||
/**
|
||||
* Class: $.jqplot.BoxplotRenderer
|
||||
* jqPlot Plugin to draw box plots <http://en.wikipedia.org/wiki/Box_plot>.
|
||||
*
|
||||
* To use this plugin, include the renderer js file in
|
||||
* your source:
|
||||
*
|
||||
* > <script type="text/javascript" src="plugins/jqplot.boxplotRenderer.js"></script>
|
||||
*
|
||||
* Then you set the renderer in the series options on your plot:
|
||||
*
|
||||
* > series: [{renderer:$.jqplot.BoxplotRenderer}]
|
||||
*
|
||||
* Data should be specified like so:
|
||||
*
|
||||
* > dat = [[sample_id, min, q1, median, q3, max], ...]
|
||||
*
|
||||
*/
|
||||
$.jqplot.BoxplotRenderer = function(){
|
||||
// subclass line renderer to make use of some of its methods.
|
||||
$.jqplot.LineRenderer.call(this);
|
||||
// prop: boxWidth
|
||||
// Default will auto calculate based on plot width and number
|
||||
// of boxes displayed.
|
||||
this.boxWidth = 'auto';
|
||||
this._boxMaxWidth = 100; // if 'auto', cap at this max
|
||||
// prop: lineWidth
|
||||
// The thickness of all lines drawn. Default is 1.5 pixels.
|
||||
this.lineWidth = 1.5;
|
||||
};
|
||||
|
||||
$.jqplot.BoxplotRenderer.prototype = new $.jqplot.LineRenderer();
|
||||
$.jqplot.BoxplotRenderer.prototype.constructor = $.jqplot.BoxplotRenderer;
|
||||
|
||||
// called with scope of series.
|
||||
$.jqplot.BoxplotRenderer.prototype.init = function(options, plot) {
|
||||
|
||||
plot.postDrawHooks.add($.jqplot.BoxplotRenderer.removePointerLabels);
|
||||
|
||||
this.lineWidth = options.lineWidth || this.renderer.lineWidth;
|
||||
$.jqplot.LineRenderer.prototype.init.call(this, options);
|
||||
// set the yaxis data bounds here to account for high and low values
|
||||
var db = {"min" : this._yaxis.min, "max" : this._yaxis.max};
|
||||
var d = this._plotData;
|
||||
for (var j=0, dj=d[j]; j<d.length; dj=d[++j]) {
|
||||
for (var k=1, dk=dj[k]; k<dj.length; dk=dj[++k]) {
|
||||
if (dk < db.min || db.min == null)
|
||||
db.min = dk;
|
||||
if (dk > db.max || db.max == null)
|
||||
db.max = dk;
|
||||
}
|
||||
}
|
||||
if(this._yaxis.min==null) {
|
||||
this._yaxis.min = db.min*this._yaxis.pad;
|
||||
}
|
||||
if(this._yaxis.max==null) {
|
||||
this._yaxis.max = db.max*this._yaxis.pad;
|
||||
}
|
||||
};
|
||||
|
||||
// called within scope of series.
|
||||
$.jqplot.BoxplotRenderer.prototype.draw = function(ctx, gd, options) {
|
||||
var d = this.data;
|
||||
var r = this.renderer;
|
||||
// set the shape renderer options
|
||||
var xp = this._xaxis.series_u2p;
|
||||
var yp = this._yaxis.series_u2p;
|
||||
if (!options)
|
||||
options = {};
|
||||
if (!('lineWidth' in options))
|
||||
$.extend(true, options, {lineWidth: this.lineWidth});
|
||||
var boxopts = $.extend(true, {}, options, {strokeRect: true});
|
||||
var boxW = options.boxWidth || r.boxWidth;
|
||||
if (boxW == 'auto')
|
||||
boxW = Math.min(r._boxMaxWidth, 0.6 * ctx.canvas.width/d.length);
|
||||
var endW = boxW / 2; // min and max ticks are half the box width
|
||||
boxW -= this.lineWidth*2;
|
||||
|
||||
var sctx = this.canvas._ctx;
|
||||
|
||||
ctx.save();
|
||||
if (this.show) {
|
||||
for (var i=0, di=d[i]; i<d.length; di=d[++i]) {
|
||||
var x = xp(di[0]),
|
||||
min = yp(di[7]),
|
||||
q1 = yp(di[6]),
|
||||
med = yp(di[5]),
|
||||
q3 = yp(di[4]),
|
||||
max = yp(di[3]);
|
||||
|
||||
var endL = x - endW/2; // start (left) x coord of min/max ticks
|
||||
var endR = x + endW/2; // end (right) x coord of min/max ticks
|
||||
var medL = x - boxW/2; // start (left) x coord of median tick
|
||||
var medR = x + boxW/2; // end (right) x coord of median tick
|
||||
|
||||
// median tick is full box width
|
||||
r.shapeRenderer.draw(ctx, [[medL, med], [medR, med]], options);
|
||||
|
||||
// draw whiskers
|
||||
r.shapeRenderer.draw(ctx, [[x, min], [x, q1]], options);
|
||||
r.shapeRenderer.draw(ctx, [[x, q3], [x, max]], options);
|
||||
|
||||
// draw min and max ticks
|
||||
r.shapeRenderer.draw(ctx, [[endL, min], [endR, min]], options);
|
||||
r.shapeRenderer.draw(ctx, [[endL, max], [endR, max]], options);
|
||||
|
||||
// draw box
|
||||
boxH = q1 - q3;
|
||||
boxpoints = [medL, q3, boxW, boxH];
|
||||
r.shapeRenderer.draw(ctx, boxpoints, boxopts);
|
||||
}
|
||||
}
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
$.jqplot.BoxplotRenderer.prototype.drawShadow = function(ctx, gd, options) {
|
||||
// This is a no-op, shadows drawn with lines.
|
||||
};
|
||||
|
||||
$.jqplot.BoxplotRenderer.removePointerLabels = function() {
|
||||
$(".jqplot-point-label").each(function() {
|
||||
$(this).hide();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
})(jQuery);
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com
|
||||
jsDate | (c) 2010-2013 Chris Leonello
|
||||
*/(function(a){a.jqplot.CanvasAxisLabelRenderer=function(b){this.angle=0;this.axis;this.show=true;this.showLabel=true;this.label="";this.fontFamily='"Trebuchet MS", Arial, Helvetica, sans-serif';this.fontSize="11pt";this.fontWeight="normal";this.fontStretch=1;this.textColor="#666666";this.enableFontSupport=true;this.pt2px=null;this._elem;this._ctx;this._plotWidth;this._plotHeight;this._plotDimensions={height:null,width:null};a.extend(true,this,b);if(b.angle==null&&this.axis!="xaxis"&&this.axis!="x2axis"){this.angle=-90}var c={fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily};if(this.pt2px){c.pt2px=this.pt2px}if(this.enableFontSupport){if(a.jqplot.support_canvas_text()){this._textRenderer=new a.jqplot.CanvasFontRenderer(c)}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}};a.jqplot.CanvasAxisLabelRenderer.prototype.init=function(b){a.extend(true,this,b);this._textRenderer.init({fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily})};a.jqplot.CanvasAxisLabelRenderer.prototype.getWidth=function(d){if(this._elem){return this._elem.outerWidth(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.sin(f.angle)*e)+Math.abs(Math.cos(f.angle)*c);return b}};a.jqplot.CanvasAxisLabelRenderer.prototype.getHeight=function(d){if(this._elem){return this._elem.outerHeight(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.cos(f.angle)*e)+Math.abs(Math.sin(f.angle)*c);return b}};a.jqplot.CanvasAxisLabelRenderer.prototype.getAngleRad=function(){var b=this.angle*Math.PI/180;return b};a.jqplot.CanvasAxisLabelRenderer.prototype.draw=function(c,f){if(this._elem){if(a.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==undefined){window.G_vmlCanvasManager.uninitElement(this._elem.get(0))}this._elem.emptyForce();this._elem=null}var e=f.canvasManager.getCanvas();this._textRenderer.setText(this.label,c);var b=this.getWidth(c);var d=this.getHeight(c);e.width=b;e.height=d;e.style.width=b;e.style.height=d;e=f.canvasManager.initCanvas(e);this._elem=a(e);this._elem.css({position:"absolute"});this._elem.addClass("jqplot-"+this.axis+"-label");e=null;return this._elem};a.jqplot.CanvasAxisLabelRenderer.prototype.pack=function(){this._textRenderer.draw(this._elem.get(0).getContext("2d"),this.label)}})(jQuery);
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com
|
||||
jsDate | (c) 2010-2013 Chris Leonello
|
||||
*/(function(a){a.jqplot.CanvasAxisTickRenderer=function(b){this.mark="outside";this.showMark=true;this.showGridline=true;this.isMinorTick=false;this.angle=0;this.markSize=4;this.show=true;this.showLabel=true;this.labelPosition="auto";this.label="";this.value=null;this._styles={};this.formatter=a.jqplot.DefaultTickFormatter;this.formatString="";this.prefix="";this.fontFamily='"Trebuchet MS", Arial, Helvetica, sans-serif';this.fontSize="10pt";this.fontWeight="normal";this.fontStretch=1;this.textColor="#666666";this.enableFontSupport=true;this.pt2px=null;this._elem;this._ctx;this._plotWidth;this._plotHeight;this._plotDimensions={height:null,width:null};a.extend(true,this,b);var c={fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily};if(this.pt2px){c.pt2px=this.pt2px}if(this.enableFontSupport){if(a.jqplot.support_canvas_text()){this._textRenderer=new a.jqplot.CanvasFontRenderer(c)}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}}else{this._textRenderer=new a.jqplot.CanvasTextRenderer(c)}};a.jqplot.CanvasAxisTickRenderer.prototype.init=function(b){a.extend(true,this,b);this._textRenderer.init({fontSize:this.fontSize,fontWeight:this.fontWeight,fontStretch:this.fontStretch,fillStyle:this.textColor,angle:this.getAngleRad(),fontFamily:this.fontFamily})};a.jqplot.CanvasAxisTickRenderer.prototype.getWidth=function(d){if(this._elem){return this._elem.outerWidth(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.sin(f.angle)*e)+Math.abs(Math.cos(f.angle)*c);return b}};a.jqplot.CanvasAxisTickRenderer.prototype.getHeight=function(d){if(this._elem){return this._elem.outerHeight(true)}else{var f=this._textRenderer;var c=f.getWidth(d);var e=f.getHeight(d);var b=Math.abs(Math.cos(f.angle)*e)+Math.abs(Math.sin(f.angle)*c);return b}};a.jqplot.CanvasAxisTickRenderer.prototype.getTop=function(b){if(this._elem){return this._elem.position().top}else{return null}};a.jqplot.CanvasAxisTickRenderer.prototype.getAngleRad=function(){var b=this.angle*Math.PI/180;return b};a.jqplot.CanvasAxisTickRenderer.prototype.setTick=function(b,d,c){this.value=b;if(c){this.isMinorTick=true}return this};a.jqplot.CanvasAxisTickRenderer.prototype.draw=function(c,f){if(!this.label){this.label=this.prefix+this.formatter(this.formatString,this.value)}if(this._elem){if(a.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==undefined){window.G_vmlCanvasManager.uninitElement(this._elem.get(0))}this._elem.emptyForce();this._elem=null}var e=f.canvasManager.getCanvas();this._textRenderer.setText(this.label,c);var b=this.getWidth(c);var d=this.getHeight(c);e.width=b;e.height=d;e.style.width=b;e.style.height=d;e.style.textAlign="left";e.style.position="absolute";e=f.canvasManager.initCanvas(e);this._elem=a(e);this._elem.css(this._styles);this._elem.addClass("jqplot-"+this.axis+"-tick");e=null;return this._elem};a.jqplot.CanvasAxisTickRenderer.prototype.pack=function(){this._textRenderer.draw(this._elem.get(0).getContext("2d"),this.label)}})(jQuery);
|
||||
Vendored
-3
File diff suppressed because one or more lines are too long
Vendored
-3
File diff suppressed because one or more lines are too long
-3
File diff suppressed because one or more lines are too long
-3
File diff suppressed because one or more lines are too long
-3
@@ -1,3 +0,0 @@
|
||||
/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com
|
||||
jsDate | (c) 2010-2013 Chris Leonello
|
||||
*/(function(c){c.jqplot.EnhancedLegendRenderer=function(){c.jqplot.TableLegendRenderer.call(this)};c.jqplot.EnhancedLegendRenderer.prototype=new c.jqplot.TableLegendRenderer();c.jqplot.EnhancedLegendRenderer.prototype.constructor=c.jqplot.EnhancedLegendRenderer;c.jqplot.EnhancedLegendRenderer.prototype.init=function(d){this.numberRows=null;this.numberColumns=null;this.seriesToggle="normal";this.seriesToggleReplot=false;this.disableIEFading=true;c.extend(true,this,d);if(this.seriesToggle){c.jqplot.postDrawHooks.push(b)}};c.jqplot.EnhancedLegendRenderer.prototype.draw=function(m,y){var f=this;if(this.show){var r=this._series;var u;var w="position:absolute;";w+=(this.background)?"background:"+this.background+";":"";w+=(this.border)?"border:"+this.border+";":"";w+=(this.fontSize)?"font-size:"+this.fontSize+";":"";w+=(this.fontFamily)?"font-family:"+this.fontFamily+";":"";w+=(this.textColor)?"color:"+this.textColor+";":"";w+=(this.marginTop!=null)?"margin-top:"+this.marginTop+";":"";w+=(this.marginBottom!=null)?"margin-bottom:"+this.marginBottom+";":"";w+=(this.marginLeft!=null)?"margin-left:"+this.marginLeft+";":"";w+=(this.marginRight!=null)?"margin-right:"+this.marginRight+";":"";this._elem=c('<table class="jqplot-table-legend" style="'+w+'"></table>');if(this.seriesToggle){this._elem.css("z-index","3")}var C=false,q=false,d,o;if(this.numberRows){d=this.numberRows;if(!this.numberColumns){o=Math.ceil(r.length/d)}else{o=this.numberColumns}}else{if(this.numberColumns){o=this.numberColumns;d=Math.ceil(r.length/this.numberColumns)}else{d=r.length;o=1}}var B,z,e,l,k,n,p,t,h,g;var v=0;for(B=r.length-1;B>=0;B--){if(o==1&&r[B]._stack||r[B].renderer.constructor==c.jqplot.BezierCurveRenderer){q=true}}for(B=0;B<d;B++){e=c(document.createElement("tr"));e.addClass("jqplot-table-legend");if(q){e.prependTo(this._elem)}else{e.appendTo(this._elem)}for(z=0;z<o;z++){if(v<r.length&&(r[v].show||r[v].showLabel)){u=r[v];n=this.labels[v]||u.label.toString();if(n){var x=u.color;if(!q){if(B>0){C=true}else{C=false}}else{if(B==d-1){C=false}else{C=true}}p=(C)?this.rowSpacing:"0";l=c(document.createElement("td"));l.addClass("jqplot-table-legend jqplot-table-legend-swatch");l.css({textAlign:"center",paddingTop:p});h=c(document.createElement("div"));h.addClass("jqplot-table-legend-swatch-outline");g=c(document.createElement("div"));g.addClass("jqplot-table-legend-swatch");g.css({backgroundColor:x,borderColor:x});l.append(h.append(g));k=c(document.createElement("td"));k.addClass("jqplot-table-legend jqplot-table-legend-label");k.css("paddingTop",p);if(this.escapeHtml){k.text(n)}else{k.html(n)}if(q){if(this.showLabels){k.prependTo(e)}if(this.showSwatches){l.prependTo(e)}}else{if(this.showSwatches){l.appendTo(e)}if(this.showLabels){k.appendTo(e)}}if(this.seriesToggle){var A;if(typeof(this.seriesToggle)==="string"||typeof(this.seriesToggle)==="number"){if(!c.jqplot.use_excanvas||!this.disableIEFading){A=this.seriesToggle}}if(this.showSwatches){l.bind("click",{series:u,speed:A,plot:y,replot:this.seriesToggleReplot},a);l.addClass("jqplot-seriesToggle")}if(this.showLabels){k.bind("click",{series:u,speed:A,plot:y,replot:this.seriesToggleReplot},a);k.addClass("jqplot-seriesToggle")}if(!u.show&&u.showLabel){l.addClass("jqplot-series-hidden");k.addClass("jqplot-series-hidden")}}C=true}}v++}l=k=h=g=null}}return this._elem};var a=function(j){var i=j.data,m=i.series,k=i.replot,h=i.plot,f=i.speed,l=m.index,g=false;if(m.canvas._elem.is(":hidden")||!m.show){g=true}var e=function(){if(k){var n={};if(c.isPlainObject(k)){c.extend(true,n,k)}h.replot(n);if(g&&f){var d=h.series[l];if(d.shadowCanvas._elem){d.shadowCanvas._elem.hide().fadeIn(f)}d.canvas._elem.hide().fadeIn(f);d.canvas._elem.nextAll(".jqplot-point-label.jqplot-series-"+d.index).hide().fadeIn(f)}}else{var d=h.series[l];if(d.canvas._elem.is(":hidden")||!d.show){if(typeof h.options.legend.showSwatches==="undefined"||h.options.legend.showSwatches===true){h.legend._elem.find("td").eq(l*2).addClass("jqplot-series-hidden")}if(typeof h.options.legend.showLabels==="undefined"||h.options.legend.showLabels===true){h.legend._elem.find("td").eq((l*2)+1).addClass("jqplot-series-hidden")}}else{if(typeof h.options.legend.showSwatches==="undefined"||h.options.legend.showSwatches===true){h.legend._elem.find("td").eq(l*2).removeClass("jqplot-series-hidden")}if(typeof h.options.legend.showLabels==="undefined"||h.options.legend.showLabels===true){h.legend._elem.find("td").eq((l*2)+1).removeClass("jqplot-series-hidden")}}}};m.toggleDisplay(j,e)};var b=function(){if(this.legend.renderer.constructor==c.jqplot.EnhancedLegendRenderer&&this.legend.seriesToggle){var d=this.legend._elem.detach();this.eventCanvas._elem.after(d)}}})(jQuery);
|
||||
Vendored
-3
File diff suppressed because one or more lines are too long
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
/* jqPlot 1.0.8r1250 | (c) 2009-2013 Chris Leonello | jplot.com
|
||||
jsDate | (c) 2010-2013 Chris Leonello
|
||||
*/(function(a){a.jqplot.OHLCRenderer=function(){a.jqplot.LineRenderer.call(this);this.candleStick=false;this.tickLength="auto";this.bodyWidth="auto";this.openColor=null;this.closeColor=null;this.wickColor=null;this.fillUpBody=false;this.fillDownBody=true;this.upBodyColor=null;this.downBodyColor=null;this.hlc=false;this.lineWidth=1.5;this._tickLength;this._bodyWidth};a.jqplot.OHLCRenderer.prototype=new a.jqplot.LineRenderer();a.jqplot.OHLCRenderer.prototype.constructor=a.jqplot.OHLCRenderer;a.jqplot.OHLCRenderer.prototype.init=function(e){e=e||{};this.lineWidth=e.lineWidth||1.5;a.jqplot.LineRenderer.prototype.init.call(this,e);this._type="ohlc";var b=this._yaxis._dataBounds;var f=this._plotData;if(f[0].length<5){this.renderer.hlc=true;for(var c=0;c<f.length;c++){if(f[c][2]<b.min||b.min==null){b.min=f[c][2]}if(f[c][1]>b.max||b.max==null){b.max=f[c][1]}}}else{for(var c=0;c<f.length;c++){if(f[c][3]<b.min||b.min==null){b.min=f[c][3]}if(f[c][2]>b.max||b.max==null){b.max=f[c][2]}}}};a.jqplot.OHLCRenderer.prototype.draw=function(A,N,j){var J=this.data;var v=this._xaxis.min;var z=this._xaxis.max;var l=0;var K=J.length;var p=this._xaxis.series_u2p;var G=this._yaxis.series_u2p;var D,E,f,M,F,n,O,C;var y;var u=this.renderer;var s=(j!=undefined)?j:{};var k=(s.shadow!=undefined)?s.shadow:this.shadow;var B=(s.fill!=undefined)?s.fill:this.fill;var c=(s.fillAndStroke!=undefined)?s.fillAndStroke:this.fillAndStroke;u.bodyWidth=(s.bodyWidth!=undefined)?s.bodyWidth:u.bodyWidth;u.tickLength=(s.tickLength!=undefined)?s.tickLength:u.tickLength;A.save();if(this.show){var m,q,g,Q,t;for(var D=0;D<J.length;D++){if(J[D][0]<v){l=D}else{if(J[D][0]<z){K=D+1}}}var I=this.gridData[K-1][0]-this.gridData[l][0];var L=K-l;try{var P=Math.abs(this._xaxis.series_u2p(parseInt(this._xaxis._intervalStats[0].sortedIntervals[0].interval,10))-this._xaxis.series_u2p(0))}catch(H){var P=I/L}if(u.candleStick){if(typeof(u.bodyWidth)=="number"){u._bodyWidth=u.bodyWidth}else{u._bodyWidth=Math.min(20,P/1.65)}}else{if(typeof(u.tickLength)=="number"){u._tickLength=u.tickLength}else{u._tickLength=Math.min(10,P/3.5)}}for(var D=l;D<K;D++){m=p(J[D][0]);if(u.hlc){q=null;g=G(J[D][1]);Q=G(J[D][2]);t=G(J[D][3])}else{q=G(J[D][1]);g=G(J[D][2]);Q=G(J[D][3]);t=G(J[D][4])}y={};if(u.candleStick&&!u.hlc){n=u._bodyWidth;O=m-n/2;if(t<q){if(u.wickColor){y.color=u.wickColor}else{if(u.downBodyColor){y.color=u.upBodyColor}}f=a.extend(true,{},s,y);u.shapeRenderer.draw(A,[[m,g],[m,t]],f);u.shapeRenderer.draw(A,[[m,q],[m,Q]],f);y={};M=t;F=q-t;if(u.fillUpBody){y.fillRect=true}else{y.strokeRect=true;n=n-this.lineWidth;O=m-n/2}if(u.upBodyColor){y.color=u.upBodyColor;y.fillStyle=u.upBodyColor}C=[O,M,n,F]}else{if(t>q){if(u.wickColor){y.color=u.wickColor}else{if(u.downBodyColor){y.color=u.downBodyColor}}f=a.extend(true,{},s,y);u.shapeRenderer.draw(A,[[m,g],[m,q]],f);u.shapeRenderer.draw(A,[[m,t],[m,Q]],f);y={};M=q;F=t-q;if(u.fillDownBody){y.fillRect=true}else{y.strokeRect=true;n=n-this.lineWidth;O=m-n/2}if(u.downBodyColor){y.color=u.downBodyColor;y.fillStyle=u.downBodyColor}C=[O,M,n,F]}else{if(u.wickColor){y.color=u.wickColor}f=a.extend(true,{},s,y);u.shapeRenderer.draw(A,[[m,g],[m,Q]],f);y={};y.fillRect=false;y.strokeRect=false;O=[m-n/2,q];M=[m+n/2,t];n=null;F=null;C=[O,M]}}f=a.extend(true,{},s,y);u.shapeRenderer.draw(A,C,f)}else{E=s.color;if(u.openColor){s.color=u.openColor}if(!u.hlc){u.shapeRenderer.draw(A,[[m-u._tickLength,q],[m,q]],s)}s.color=E;if(u.wickColor){s.color=u.wickColor}u.shapeRenderer.draw(A,[[m,g],[m,Q]],s);s.color=E;if(u.closeColor){s.color=u.closeColor}u.shapeRenderer.draw(A,[[m,t],[m+u._tickLength,t]],s);s.color=E}}}A.restore()};a.jqplot.OHLCRenderer.prototype.drawShadow=function(b,d,c){};a.jqplot.OHLCRenderer.checkOptions=function(d,c,b){if(!b.highlighter){b.highlighter={showMarker:false,tooltipAxes:"y",yvalues:4,formatString:'<table class="jqplot-highlighter"><tr><td>date:</td><td>%s</td></tr><tr><td>open:</td><td>%s</td></tr><tr><td>hi:</td><td>%s</td></tr><tr><td>low:</td><td>%s</td></tr><tr><td>close:</td><td>%s</td></tr></table>'}}}})(jQuery);
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+10
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+8
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+8
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+8
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user