PHP Classes

File: core/assets/plugins/ckeditor/plugins/chart/plugin.js

Recommend this page to a friend!
  Classes of No name   RT Adminlte   core/assets/plugins/ckeditor/plugins/chart/plugin.js   Download  
File: core/assets/plugins/ckeditor/plugins/chart/plugin.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: RT Adminlte
Generate layout and menus for Adminlte
Author: By
Last change:
Date: 7 years ago
Size: 19,926 bytes
 

Contents

Class file image Download
/** * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. * For licensing, see LICENSE.md or http://ckeditor.com/license */ /** * @fileOverview Charts for CKEditor using Chart.js. */ /* global alert:false, Chart:false */ 'use strict'; // TODO IE8 fallback to a table maybe? // TODO a11y http://www.w3.org/html/wg/wiki/Correct_Hidden_Attribute_Section_v4 ( function() { CKEDITOR.plugins.add( 'chart', { // Required plugins requires: 'widget,dialog', // Name of the file in the "icons" folder icons: 'chart', // Supported languages lang: 'en,es,pl', // Load library that renders charts inside CKEditor, if Chart object is not already available. afterInit: function() { var plugin = this; if ( typeof Chart === 'undefined' ) { // Chart library is loaded asynchronously, so we can draw anything only once it's loaded. CKEDITOR.scriptLoader.load( CKEDITOR.getUrl( plugin.path + 'lib/chart.min.js' ), function() { plugin.drawCharts(); } ); } }, // Function called on initialization of every editor instance created in the page. init: function( editor ) { var plugin = this; var chartDefaultHeight = editor.config.chart_height || 300; // Default hardcoded values used if config.chart_colors is not provided. var colors = editor.config.chart_colors || { // Colors for Bar/Line chart: http://www.chartjs.org/docs/#bar-chart-data-structure fillColor: 'rgba(151,187,205,0.5)', strokeColor: 'rgba(151,187,205,0.8)', highlightFill: 'rgba(151,187,205,0.75)', highlightStroke: 'rgba(151,187,205,1)', // Colors for Doughnut/Pie/PolarArea charts: http://www.chartjs.org/docs/#doughnut-pie-chart-data-structure data: [ '#B33131', '#B66F2D', '#B6B330', '#71B232', '#33B22D', '#31B272', '#2DB5B5', '#3172B6', '#3232B6', '#6E31B2', '#B434AF', '#B53071' ] }; var config = { Bar: editor.config.chart_configBar || { animation: false }, Doughnut: editor.config.chart_configDoughnut || { animateRotate: false }, Line: editor.config.chart_configLine || { animation: false }, Pie: editor.config.chart_configPie || { animateRotate: false }, PolarArea: editor.config.chart_configPolarArea || { animateRotate: false } }; // The number of rows in Edit Chart dialog window. var inputRows = editor.config.chart_maxItems || 8; // Inject required CSS stylesheet to classic editors because the <iframe> needs it. // Inline editors will ignore this, the developer is supposed to load chart.css directly on a page. // "this.path" is a path to the current plugin. editor.addContentsCss( CKEDITOR.getUrl( plugin.path + 'chart.css' ) ); // A little bit of magic to support "Preview" feature in CKEditor (in a popup). // In order to transform downcasted widgets into nice charts we need to: // 1. Pass color settings and charts configuration through JSON. // 2. Load the Chart.js library // 3. Load a helper script that will "upcast" widgets and initiate charts. editor.on( 'contentPreview', function( evt ) { evt.data.dataValue = evt.data.dataValue.replace( /<\/head>/, '<script>var chartjs_colors_json = "' + JSON.stringify( colors ).replace( /\"/g, '\\"' ) + '";<\/script>' + '<script>var chartjs_config_json = "' + JSON.stringify( config ).replace( /\"/g, '\\"' ) + '";<\/script>' + '<script src="' + CKEDITOR.getUrl( plugin.path + 'lib/chart.min.js' ) + '"><\/script>' + '<script src="' + CKEDITOR.getUrl( plugin.path + 'widget2chart.js' ) + '"><\/script><\/head>' ); } ); // The dialog window to insert / edit a chart. CKEDITOR.dialog.add( 'chart', function( editor ) { var dialog = { title: editor.lang.chart.dialogTitle, minWidth: 200, minHeight: 100, // Executed every time a dialog is shown. onShow: function() { var widget = editor.widgets.focused; if ( !widget ) return; // We edit an existing widget, so we have already some data and should set input values accordingly. // The dialog consists of multiple rows with two input elements each. // We could use "setup" callbacks for each UI element, but the we'd end up with lots of data properties. // So instead we merge all the values into a single object, ending with an array like: // [ {"value":45,"label":"Yes"}, {}, .... ] // to make it easier to pass it to Chart.js later. for ( var j = 0; j < inputRows; j++ ) { if ( widget.data.values[j] ) { // toString() is used here to set correctly zero values. this.setValueOf( 'data', 'value' + j, widget.data.values[j].value.toString() ); this.setValueOf( 'data', 'label' + j, widget.data.values[j].label ); } } }, // Executed every time a dialog is closed (OK is pressed). onOk: function() { // ATTENTION: this.widget is not available here in CKEditor by default. // We added this in the "init" function of a widget ("Pass the reference to this widget to the dialog."), var widget = this.widget, values = [], value; // We could use "commit" callbacks in every input element to set widget data. // But we decided to keep multiple values in a single object (see comment in "onShow" for more details). for ( var j = 0; j < inputRows; j++ ) { value = this.getValueOf( 'data', 'value' + j ); if ( value ) values.push( { value: parseFloat( this.getValueOf( 'data', 'value' + j ) ), label: this.getValueOf( 'data', 'label' + j ) } ); } widget.setData( 'values', values ); widget.setData( 'chart', this.getValueOf( 'data', 'chart' ) ); widget.setData( 'height', this.getValueOf( 'data', 'height' ) ); }, // Define elements in a dialog window. contents: [ { id: 'data', elements: [ { type: 'hbox', children: [ { id: 'chart', type: 'select', label: editor.lang.chart.chartType, labelLayout: 'horizontal', // Align vertically, otherwise labels are a bit misplaced. labelStyle: 'display:block;padding: 4px 6px;', items: [ [ editor.lang.chart.bar, 'bar' ], [ editor.lang.chart.line, 'line' ], [ editor.lang.chart.pie, 'pie' ], [ editor.lang.chart.polar, 'polar' ], [ editor.lang.chart.doughnut, 'doughnut' ] ], style: 'margin-bottom:10px', setup: function( widget ) { // Set radios to the correct value based on the widget type. this.setValue( widget.data.chart ); } }, { id: 'height', type: 'text', label: editor.lang.chart.height, labelLayout: 'horizontal', // Align vertically, otherwise labels are a bit misplaced. labelStyle: 'display:block;padding: 4px 6px;', width: '50px', setup: function( widget ) { this.setValue( widget.data.height ); }, validate: function() { var value = this.getValue(), pass = ( !value || !!( CKEDITOR.dialog.validate.number( value ) && value >= 0 ) ); if ( !pass ) { alert( editor.lang.common.validateNumberFailed ); this.select(); } return pass; } } ] } ] } ] }; // Rarely elements in dialog definitions are generated in loops. // Here we decided to make the number of "data" rows configurable, so a loop is handy. for ( var i = 0; i < inputRows; i++ ) { dialog.contents[0].elements.push( { type: 'hbox', children: [ { id: 'value' + i, type: 'text', labelLayout: 'horizontal', label: editor.lang.chart.value, // Align vertically, otherwise labels are a bit misplaced. labelStyle: 'display:block;padding: 4px 6px;', width: '50px', validate: function() { var value = this.getValue(), pass = ( !value || !!( CKEDITOR.dialog.validate.number( value ) && value >= 0 ) ); if ( !pass ) { alert( editor.lang.common.validateNumberFailed ); this.select(); } return pass; } }, { id: 'label' + i, type: 'text', label: editor.lang.chart.label, labelLayout: 'horizontal', // Align vertically, otherwise labels are a bit misplaced. labelStyle: 'display:block;padding: 4px 6px;', width: '200px' } ] } ); } return dialog; } ); // Helper function that we'd like to run in case Chart.js library was loaded asynchronously. this.drawCharts = function() { // All available widgets are stored in an object, not an array. for ( var id in editor.widgets.instances ) { // The name was provided in editor.widgets.add() if ( editor.widgets.instances[id].name == 'chart' ) { // Our "data" callback draws widgets, so let's call it. editor.widgets.instances[id].fire( 'data' ); } } }; function renderChart( canvas, data, legend ) { var values = data.values, chartType = data.chart; // The code below is the same as in widget2chart.js. // ########## RENDER CHART START ########## // Prepare canvas and chart instance. var i, ctx = canvas.getContext( '2d' ), chart = new Chart( ctx ); // jshint ignore:line // Set some extra required colors by Pie/Doughnut charts. // Ugly charts will be drawn if colors are not provided for each data. // http://www.chartjs.org/docs/#doughnut-pie-chart-data-structure if ( chartType != 'bar' ) { for ( i = 0; i < values.length; i++ ) { values[i].color = colors.data[i]; values[i].highlight = colors.data[i]; } } // Prepare data for bar/line charts. if ( chartType == 'bar' || chartType == 'line' ) { var data = { // Chart.js supports multiple datasets. // http://www.chartjs.org/docs/#bar-chart-data-structure // This plugin is simple, so it supports just one. // Need more features? Create a Pull Request :-) datasets: [ { label: '', fillColor: colors.fillColor, strokeColor: colors.strokeColor, highlightFill: colors.highlightFill, highlightStroke: colors.highlightStroke, data: [] } ], labels: [] }; // Bar charts accept different data format than Pie/Doughnut. // We need to pass values inside datasets[0].data. for ( i = 0; i < values.length; i++ ) { if ( values[i].value ) { data.labels.push( values[i].label ); data.datasets[0].data.push( values[i].value ); } } // Legend makes sense only with more than one dataset. legend.innerHTML = ''; } // Render Bar chart. if ( chartType == 'bar' ) { chart.Bar( data, config.Bar ); } // Render Line chart. else if ( chartType == 'line' ) { chart.Line( data, config.Line ); } // Render Line chart. else if ( chartType == 'polar' ) { //chart.PolarArea( values ); legend.innerHTML = chart.PolarArea( values, config.PolarArea ).generateLegend(); } // Render Pie chart and legend. else if ( chartType == 'pie' ) { legend.innerHTML = chart.Pie( values, config.Pie ).generateLegend(); } // Render Doughnut chart and legend. else { legend.innerHTML = chart.Doughnut( values, config.Doughnut ).generateLegend(); } // ########## RENDER CHART END ########## } // Here we define the widget itself. editor.widgets.add( 'chart', { // The *label* for the button. The button *name* is assigned automatically based on the widget name. button: editor.lang.chart.chart, // Connect widget with a dialog defined earlier. So our toolbar button will open a dialog window. dialog: 'chart', // Based on this template a widget will be created automatically once user exits the dialog window. template: '<div class="chartjs" data-chart="bar" data-chart-height="' + chartDefaultHeight + '"><canvas height="' + chartDefaultHeight + '"></canvas><div class="chartjs-legend"></div></div>', // In order to provide styles (classes) for this widget through config.stylesSet we need to explicitly define the stylable elements. styleableElements: 'div', // Name to be displayed in the elements path (at the bottom of CKEditor), pathName: 'chart', // Run when initializing widget (thank you, captain obvious!). // It is common to use the init method to populate widget data with information loaded from the DOM. init: function() { // When an empty widget is initialized after clicking a button in the toolbar, we do not have yet chart values. if ( this.element.data( 'chart-value' ) ) { this.setData( 'values', JSON.parse( this.element.data( 'chart-value' ) ) ); } // Chart is specified in a template, so it is available even in an empty widget. this.setData( 'chart', this.element.data( 'chart' ) ); // Height is specified in a template, so it is available even in an empty widget. this.setData( 'height', this.element.data( 'chart-height' ) ); // Pass the reference to this widget to the dialog. See "onOk" in the dialog definition, we needed widget there. this.on( 'dialog', function( evt ) { evt.data.widget = this; }, this ); }, // Run when widget data is changed (widget is rendered for the first time, inserted, changed). data: function() { // Just in case Chart.js was loaded asynchronously and is not available yet. if ( typeof Chart === 'undefined' ) return; // It's hard to draw a chart without numbers. if ( !this.data.values ) return; // It looks like Chart.js does not handle well updating charts. // When hovering over updated canvas old data is picked up sometimes, so we need to always replace an old canvas. var canvas = editor.document.createElement( 'canvas', { attributes: { height: this.data.height } } ); canvas.replace( this.element.getChild( 0 ) ); // Unify variable names with the one used in widget2chart.js. var legend = this.element.getChild( 1 ).$; canvas = canvas.$; // IE8 can't handle the next part (without the help of excanvas etc.). if ( !canvas.getContext ) return; var data = this.data; // Without timeout the chart does not render immediately after inserting into the editing area. setTimeout( function() { renderChart( canvas, data, legend ) }, 0 ); }, // ACF settings. Without allowing elements introduced by this plugin, CKEditor built-in filter would remove it. allowedContent: 'div(!chartjs)[data-*];', requiredContent: 'div(chartjs)[data-chart-value,data-chart,data-chart-height]', // Executed when CKEditor loads content, when switching from source to wysiwyg mode. Makes HTML content a widget. upcast: function( element ) { if ( element.name == 'div' && element.hasClass( 'chartjs' ) ) { // Downcasted <div> could have contained some text like "chart" or &nbsp; which was there just to prevent <div>s from being deleted. // Get rid of it when upcasting. element.setHtml( '' ); // Chart.js work on canvas elements, Prepare one. var canvas = new CKEDITOR.htmlParser.element( 'canvas', { height: element.attributes[ 'data-chart-height' ] } ); element.add( canvas ); // And make place for a legend. var div = new CKEDITOR.htmlParser.element( 'div', { 'class': 'chartjs-legend' } ); element.add( div ); return element; } }, // Executed when CKEditor returns content, when switching from wysiwyg to source mode. Transforms a widget back to a downcasted form. downcast: function( element ) { var data = []; // Should not happen unless someone has accidentally messed up ACF rules. if ( !this.data.values ) return; for ( var i = 0; i < this.data.values.length; i++ ) { // Get data from widget into an object in order to save it as data-chart-value attribute. // We could simply save this.data.values, but it contains some additional temporary data which we want to skip (like colors). data.push( { value: this.data.values[i].value, label: this.data.values[i].label } ); } // Create the downcasted form of a widget (a simple <div>). var el = new CKEDITOR.htmlParser.element( 'div', { // We could pass here hardcoded "chartjs" class, but this way we would lose here all the classes applied through the Styles dropdown. // (In case someone defined his own styles for the chart widget) 'class': element.attributes['class'], 'data-chart': this.data.chart, 'data-chart-height': this.data.height, // Feature detection (editor.getSelectedHtml) to check if CKEditor 4.5+ is used. // CKEditor < 4.5 and CKEditor 4.5+ require different code due to https://dev.ckeditor.com/ticket/13105 'data-chart-value': editor.getSelectedHtml ? JSON.stringify( data ) : CKEDITOR.tools.htmlEncodeAttr( JSON.stringify( data ) ) } ); return el; } } ); } } ); } )(); /** * The default chart height (in pixels) in the Edit Chart dialog window. * * // Set default height to 400px. * config.chart_height = 400; * * @cfg {Integer} [chart_height=300] * @member CKEDITOR.config */ /** * The number of rows (items to enter) in the Edit Chart dialog window. * * // Set number of rows to 12. * config.chart_maxItems = 12; * * @cfg {Integer} [chart_maxItems=12] * @member CKEDITOR.config */ /** * Colors used to draw charts. See <a href="http://www.chartjs.org/docs/#bar-chart-data-structure">Bar chart data structure</a> and * <a href="http://www.chartjs.org/docs/#doughnut-pie-chart-data-structure">Pie chart data structure</a>. * * config.chart_colors = * { * // Colors for Bar/Line chart. * fillColor: 'rgba(151,187,205,0.5)', * strokeColor: 'rgba(151,187,205,0.8)', * highlightFill: 'rgba(151,187,205,0.75)', * highlightStroke: 'rgba(151,187,205,1)', * // Colors for Doughnut/Pie/PolarArea charts. * data: [ '#B33131', '#B66F2D', '#B6B330', '#71B232', '#33B22D', '#31B272', '#2DB5B5', '#3172B6', '#3232B6', '#6E31B2', '#B434AF', '#B53071' ] * } * * @cfg {Array} chart_colors * @member CKEDITOR.config */ /** * Chart.js configuration to use for Bar charts. * * @cfg {Object} [chart_configBar={ animation: false }] * @member CKEDITOR.config */ /** * Chart.js configuration to use for Doughnut charts. * * @cfg {Object} [chart_configDoughnut={ animateRotate: false }] * @member CKEDITOR.config */ /** * Chart.js configuration to use for Line charts. * * @cfg {Object} [chart_configLine={ animation: false }] * @member CKEDITOR.config */ /** * Chart.js configuration to use for Pie charts. * * @cfg {Object} [chart_configPie={ animateRotate: false }] * @member CKEDITOR.config */ /** * Chart.js configuration to use for PolarArea charts. * * @cfg {Object} [chart_configPolarArea={ animateRotate: false }] * @member CKEDITOR.config */