From 47b0af98b0622ace4bbe7b0441370961677c2558 Mon Sep 17 00:00:00 2001 From: Catouse Date: Tue, 12 May 2015 11:20:13 +0800 Subject: [PATCH] + add Chart.Bar.js. --- docs/js/doc.js | 15 +- docs/js/doc.min.js | 4 +- docs/js/zui.js | 449 ++++++++++++++++++++++++++++++++++++++++++-- docs/js/zui.min.js | 15 +- package.json | 2 +- src/js/Chart.Bar.js | 373 ++++++++++++++++++++++++++++++++++++ 6 files changed, 824 insertions(+), 34 deletions(-) create mode 100644 src/js/Chart.Bar.js diff --git a/docs/js/doc.js b/docs/js/doc.js index 68500e47b..fe69aa0a3 100644 --- a/docs/js/doc.js +++ b/docs/js/doc.js @@ -1,5 +1,5 @@ /*! - * ZUI - v1.3.0 - 2015-05-06 + * ZUI - v1.3.0 - 2015-05-12 * http://zui.sexy * GitHub: https://github.com/easysoft/zui.git * Copyright (c) 2015 cnezsoft.com; Licensed MIT @@ -36,7 +36,7 @@ } var saveTraffic = false; - var debug = 1; + var debug = 2; if(debug) console.error("DEBUG ENABLED."); var chapters = { @@ -585,7 +585,7 @@ $body.addClass('query-enabled').attr('data-query', ''); // Send ga data - if($.isFunction(ga)) { + if(window['ga'] && $.isFunction(ga)) { if(queryGaCallback) clearTimeout(queryGaCallback); queryGaCallback = setTimeout(function(){ ga('send', 'pageview', window.location.pathname + '#search/' + keyString); @@ -966,7 +966,7 @@ if(topic) pageUrl += '/' + topic; window.document.title = section.chapterName + ' > ' + section.name + ' - ' + documentTitle; window.location.hash = pageUrl; - if($.isFunction(ga)) ga('send','pageview', window.location.pathname + pageUrl); + if(window['ga'] && $.isFunction(ga)) ga('send','pageview', window.location.pathname + pageUrl); $body.attr('data-page-accent', $section.data('accent')).attr('data-page', pageId); displaySectionIcon($pageHeader.find('.icon'), section); @@ -1391,7 +1391,7 @@ }); }; - $(function() { + var init = function(){ documentTitle = window.document.title; var stopPropagation = function(e) { @@ -1542,6 +1542,7 @@ var scrollHeight = $('#navbar').outerHeight(); var lastScrollTop; $window.on('scroll', function(e){ + if($body.hasClass('layout-classic')) return; var isScrollAnimating = $body.data('isScrollAnimating'); if(isScrollAnimating) { $window.scrollTop(1); @@ -1657,7 +1658,9 @@ }); $('[data-toggle="tooltip"]').tooltip({container: 'body'}); - }); + }; + + init(); $.doc = { query: query, diff --git a/docs/js/doc.min.js b/docs/js/doc.min.js index 5509b3b9f..7d95aef40 100644 --- a/docs/js/doc.min.js +++ b/docs/js/doc.min.js @@ -1,8 +1,8 @@ /*! - * ZUI - v1.3.0 - 2015-05-06 + * ZUI - v1.3.0 - 2015-05-12 * http://zui.sexy * GitHub: https://github.com/easysoft/zui.git * Copyright (c) 2015 cnezsoft.com; Licensed MIT */ -!function(a,b){"use strict";String.prototype.endsWith||(String.prototype.endsWith=function(a,b){var c=this.toString();(void 0===b||b>c.length)&&(b=c.length),b-=a.length;var d=c.indexOf(a,b);return-1!==d&&d===b}),String.prototype.startsWith||(String.prototype.startsWith=function(a,b){return b=b||0,this.lastIndexOf(a,b)===b}),String.prototype.includes||(String.prototype.includes=function(){return-1!==String.prototype.indexOf.apply(this,arguments)});var c=1;c&&console.error("DEBUG ENABLED.");var d,e,f={learn:{col:1},start:{col:1},basic:{col:1},control:{col:2},component:{col:2},javascript:{col:3},view:{col:3},promotion:{col:1,row:2},resource:{col:1,row:2},contribution:{col:1,row:2}},g="lastReloadAnimate",h="LAST_QUERY_ID",i="docs/index.json",j="docs/icons.json",k="package.json",l=void 0,m="page-show-full",n={};c&&(a.dataset=n);var o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L={standard:null,lite:null,separate:null},M="ZUI",N=-1,O=1120,P=function(a){return"string"==typeof a?(a=a.toLowerCase(),a.startsWith("http://")||a.startsWith("https://")):!1},Q=function(b){var c=new RegExp("(^|&)"+b+"=([^&]*)(&|$)","i"),d=a.location.search.substr(1).match(c);return null!=d?unescape(d[2]):null},R=function(){if(!(document.body.clientWidth>=a.innerWidth)){if(0>N){var b=document.createElement("div");b.className="modal-scrollbar-measure",q.append(b),N=b.offsetWidth-b.clientWidth,q[0].removeChild(b)}if(N){var c=parseInt(q.css("padding-right")||0,10);q.css("padding-right",c+N),F.css("padding-right",N)}}},S=function(){q.css("padding-right",""),F.css("padding-right","")},T=function(a,f){var g=n[a],h=g&&g.version,j=a===i;if(!h&&e){var k=b.zui.store.get("//"+a,null);if(null!==k){var l=b.zui.store.get("//"+a+"::V");l&&(g={data:k,version:l},n[a]=g,h=!0,c&&console.log("Load",a,"from storage:",g))}}if(!h||!j&&g.version!==d||(c&&console.log("Load",a,"from cache:",g),f(g.data),j||c)){var m=a.endsWith(".json")?"json":"html";b.get(a,function(e){null!==e?(j&&(d=e.version),g={data:e,version:d},n[a]=g,b.zui.store.set("//"+a,e),b.zui.store.set("//"+a+"::V",d),c&&console.log("Load",a,"from remote:",g),f(e)):h&&!j&&(c&&console.log("Failed load",a,"from remote, instead load cache:",g),f(g.data))},m).error(function(){c&&console.error("Ajax error:",a),h&&!j&&(c&&console.log("Failed load",a,"from remote with error, instead load cache:",g),f(g.data)),q.hasClass("page-open")&&E.children(".loader").addClass("with-error")})}},U=function(a,c){var d=n[i].data;return d?(b.each(f,function(e,f){if(d.chapters[e]){b.extend(f,d.chapters[e]);var g=f.sections,h=null;return c&&(h=c(f,g),h===!1)?!1:void b.each(g,function(b,c){return a(f,c,h)===!1?!1:void 0})}}),!0):(console.error("Document index is empty."),!1)},V=function(a,b){var c=b.icon;a.attr("class","icon").text("").css("background-image",""),(void 0===c||null===c||""===c)&&(c=b.name.substr(0,1).toUpperCase()),c.startsWith("icon-")?a.addClass(c):c.endsWith(".png")?a.css("background-image","url("+c+")").addClass("with-img"):a.addClass("text-icon").text(c)},W=function(){var a=0;U(function(b,c,d){var e=b.id;c.chapter=e,c.chapterName=b.name;var f=c.url;"undefined"==typeof f?(c.url="docs/part/"+c.chapter+"-"+c.id+".html",c.target="page"):P(f)?c.target="external":f&&f.endsWith(".md")?(c.target="page",c.targetType="markdown"):c.target="";var g=e+"-"+c.id,h=t.clone().data("section",c);h.attr({id:"section-"+g,"data-id":c.id,"data-chapter":e,"data-order":a++,"data-accent":b.accent,"data-target":c.target});var i=h.children(".card-heading"),j="#"+e+"/"+c.id;i.find(".name").text(c.name).attr("href",j),i.children(".desc").text(c.desc),V(i.children(".icon"),c);var k=h.find(".topics");if(c.topics&&c.topics.length){var l=0;for(var m in c.topics){var n=c.topics[m];"undefined"==typeof n.id&&(n.id=m);var p="undefined"==typeof n.url?j+"/"+l++:n.url;k.append('
  • "+n.name+"
  • ")}}else k.remove(".card-content"),h.addClass("without-topics");d.append(h.addClass("show"+(o?" in":"")))},function(a,b){a.$.attr("data-accent",a.accent);var c=a.$sections;return c.children().remove(),c})?(q.children(".loader").removeClass("loading"),J=s.find(".section"),o||(clearTimeout(s.data(g)),s.data(g,setTimeout(function(){J.addClass("in"),K.addClass("in")},100)),o=!0)):c&&console.error("Display sections failed.")},X=function(a,b,c){a===l&&(a=q),b===l||"down"===b?b=a.scrollTop()+.8*(r.height()-a.offset().top):"up"===b&&(b=a.scrollTop()-.8*(r.height()-a.offset().top)),a.animate({scrollTop:b},200,"swing",c)},Y=function(a){if(a){a.offset().top,a.outerHeight(),r.height(),q.scrollTop()}},Z=function(a){return a===l&&(a=y),a&&a.hasClass("choosed")&&a.hasClass("show")},$=function(a,b,c){if(J){if(Z(a||null)&&!c)return y=a.addClass("open"),void Y(a);var d=a&&a.hasClass("open");J.removeClass(b?"choosed":"choosed open"),a&&a.hasClass("section")&&(y=a.addClass(c&&!d?"choosed":"choosed open"),Y(a))}},_=function(){var a=J.filter(".show");if(Z()){for(var b=parseInt(y.data("order")),c=y;--b>-1;){var d=a.filter('[data-order="'+b+'"]');if(d.length){c=d;break}}$(c)}else $(a.first())},aa=function(){var a=J.filter(".show");if(Z()){for(var b=parseInt(y.data("order")),c=y,d=J.length;b++d)return void _();var e=c.top;d=c.left;var f=y,g=99999;a.each(function(){var a=b(this),c=a.offset();if(c.left+50h&&(f=a,g=h)}}),$(f)}else $(a.first())},da=function(){var a=J.filter(".show");if(Z()){var c=y.offset(),d=s.children(".container"),e=c.left-d.offset().left-10;if(e+20+y.outerWidth()+50>=d.outerWidth())return void aa();var f=c.top;e=c.left;var g=y,h=99999;a.each(function(){var a=b(this),c=a.offset();if(c.left>e){var d=ba(c.left,c.top,e,f);h>d&&(g=a,h=d)}}),$(g)}else $(a.first())},ea=function(){w.removeClass("hide"),v.removeClass("hide"),J.addClass("show"),K.addClass("show"),s.data(g,setTimeout(function(){J.addClass("in"),K.addClass("in")},20)),q.removeClass("query-enabled").attr("data-query","")},fa=function(a){var c=b("#section-control-icon");if(!a||!a.length)return void c.removeClass("section-preview-show").data("preview",null);c.addClass("open section-preview-show");var d=c.children(".section-preview"),e=c.data("preview");d.length||(d=b("#iconPreviewTemplate").clone().attr("id",""),c.children(".card-heading").after(d)),c.children(".section-search").find("li.active").removeClass("active"),a.addClass("active"),e&&d.find(".icon").removeClass("icon-"+e);var f=a.data("icon");c.data("preview",f.id);var g="icon-"+f.id;d.find(".icon").addClass(g),d.find(".name").text(g),d.find(".unicode").text(f.code),f.alias&&f.alias.length?d.find(".alias").removeClass("hide").find(".alias-values").text(f.alias.join(",")):d.find(".alias").addClass("hide")},ha=function(a){b.isArray(a)||!a&&!a.length||(a=[a]);var c=b("#section-control-icon");q.attr("data-query","icons");var d=c.children(".section-search");d.length||(d=b(''),c.children(".card-heading").after(d),d=c.children(".section-search")),T(j,function(c){var e=d.children("ul");if(e.length||(e=b('" + + }; + + + Chart.Type.extend( + { + name: "Bar", + defaults: defaultConfig, + initialize: function(data) + { + + //Expose options as a scope variable here so we can access it in the ScaleClass + var options = this.options; + + this.ScaleClass = Chart.Scale.extend( + { + offsetGridLines: true, + calculateBarX: function(datasetCount, datasetIndex, barIndex) + { + //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar + var xWidth = this.calculateBaseWidth(), + xAbsolute = this.calculateX(barIndex) - (xWidth / 2), + barWidth = this.calculateBarWidth(datasetCount); + + return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth / 2; + }, + calculateBaseWidth: function() + { + return (this.calculateX(1) - this.calculateX(0)) - (2 * options.barValueSpacing); + }, + calculateBarWidth: function(datasetCount) + { + //The padding between datasets is to the right of each bar, providing that there are more than 1 dataset + var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing); + + return (baseWidth / datasetCount); + } + }); + + this.datasets = []; + + //Set up tooltip events on the chart + if (this.options.showTooltips) + { + helpers.bindEvents(this, this.options.tooltipEvents, function(evt) + { + var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : []; + + this.eachBars(function(bar) + { + bar.restore(['fillColor', 'strokeColor']); + }); + helpers.each(activeBars, function(activeBar) + { + activeBar.fillColor = activeBar.highlightFill; + activeBar.strokeColor = activeBar.highlightStroke; + }); + this.showTooltip(activeBars); + }); + } + + //Declare the extension of the default point, to cater for the options passed in to the constructor + this.BarClass = Chart.Rectangle.extend( + { + strokeWidth: this.options.barStrokeWidth, + showStroke: this.options.barShowStroke, + ctx: this.chart.ctx + }); + + //Iterate through each of the datasets, and build this into a property of the chart + helpers.each(data.datasets, function(dataset, datasetIndex) + { + + var datasetObject = { + label: dataset.label || null, + fillColor: dataset.fillColor, + strokeColor: dataset.strokeColor, + bars: [] + }; + + this.datasets.push(datasetObject); + + helpers.each(dataset.data, function(dataPoint, index) + { + //Add a new point for each piece of data, passing any required data to draw. + datasetObject.bars.push(new this.BarClass( + { + value: dataPoint, + label: data.labels[index], + datasetLabel: dataset.label, + strokeColor: dataset.strokeColor, + fillColor: dataset.fillColor, + highlightFill: dataset.highlightFill || dataset.fillColor, + highlightStroke: dataset.highlightStroke || dataset.strokeColor + })); + }, this); + + }, this); + + this.buildScale(data.labels); + + this.BarClass.prototype.base = this.scale.endPoint; + + this.eachBars(function(bar, index, datasetIndex) + { + helpers.extend(bar, + { + width: this.scale.calculateBarWidth(this.datasets.length), + x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index), + y: this.scale.endPoint + }); + bar.save(); + }, this); + + this.render(); + }, + update: function() + { + this.scale.update(); + // Reset any highlight colours before updating. + helpers.each(this.activeElements, function(activeElement) + { + activeElement.restore(['fillColor', 'strokeColor']); + }); + + this.eachBars(function(bar) + { + bar.save(); + }); + this.render(); + }, + eachBars: function(callback) + { + helpers.each(this.datasets, function(dataset, datasetIndex) + { + helpers.each(dataset.bars, callback, this, datasetIndex); + }, this); + }, + getBarsAtEvent: function(e) + { + var barsArray = [], + eventPosition = helpers.getRelativePosition(e), + datasetIterator = function(dataset) + { + barsArray.push(dataset.bars[barIndex]); + }, + barIndex; + + for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) + { + for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) + { + if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x, eventPosition.y)) + { + helpers.each(this.datasets, datasetIterator); + return barsArray; + } + } + } + + return barsArray; + }, + buildScale: function(labels) + { + var self = this; + + var dataTotal = function() + { + var values = []; + self.eachBars(function(bar) + { + values.push(bar.value); + }); + return values; + }; + + var scaleOptions = { + templateString: this.options.scaleLabel, + height: this.chart.height, + width: this.chart.width, + ctx: this.chart.ctx, + textColor: this.options.scaleFontColor, + fontSize: this.options.scaleFontSize, + fontStyle: this.options.scaleFontStyle, + fontFamily: this.options.scaleFontFamily, + valuesCount: labels.length, + beginAtZero: this.options.scaleBeginAtZero, + integersOnly: this.options.scaleIntegersOnly, + calculateYRange: function(currentHeight) + { + var updatedRanges = helpers.calculateScaleRange( + dataTotal(), + currentHeight, + this.fontSize, + this.beginAtZero, + this.integersOnly + ); + helpers.extend(this, updatedRanges); + }, + xLabels: labels, + font: helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily), + lineWidth: this.options.scaleLineWidth, + lineColor: this.options.scaleLineColor, + showHorizontalLines: this.options.scaleShowHorizontalLines, + showVerticalLines: this.options.scaleShowVerticalLines, + gridLineWidth: (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0, + gridLineColor: (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)", + padding: (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0, + showLabels: this.options.scaleShowLabels, + display: this.options.showScale + }; + + if (this.options.scaleOverride) + { + helpers.extend(scaleOptions, + { + calculateYRange: helpers.noop, + steps: this.options.scaleSteps, + stepValue: this.options.scaleStepWidth, + min: this.options.scaleStartValue, + max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth) + }); + } + + this.scale = new this.ScaleClass(scaleOptions); + }, + addData: function(valuesArray, label) + { + //Map the values array for each of the datasets + helpers.each(valuesArray, function(value, datasetIndex) + { + //Add a new point for each piece of data, passing any required data to draw. + this.datasets[datasetIndex].bars.push(new this.BarClass( + { + value: value, + label: label, + x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount + 1), + y: this.scale.endPoint, + width: this.scale.calculateBarWidth(this.datasets.length), + base: this.scale.endPoint, + strokeColor: this.datasets[datasetIndex].strokeColor, + fillColor: this.datasets[datasetIndex].fillColor + })); + }, this); + + this.scale.addXLabel(label); + //Then re-render the chart. + this.update(); + }, + removeData: function() + { + this.scale.removeXLabel(); + //Then re-render the chart. + helpers.each(this.datasets, function(dataset) + { + dataset.bars.shift(); + }, this); + this.update(); + }, + reflow: function() + { + helpers.extend(this.BarClass.prototype, + { + y: this.scale.endPoint, + base: this.scale.endPoint + }); + var newScaleProps = helpers.extend( + { + height: this.chart.height, + width: this.chart.width + }); + this.scale.update(newScaleProps); + }, + draw: function(ease) + { + var easingDecimal = ease || 1; + this.clear(); + + var ctx = this.chart.ctx; + + this.scale.draw(easingDecimal); + + //Draw all the bars for each dataset + helpers.each(this.datasets, function(dataset, datasetIndex) + { + helpers.each(dataset.bars, function(bar, index) + { + if (bar.hasValue()) + { + bar.base = this.scale.endPoint; + //Transition then draw + bar.transition( + { + x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index), + y: this.scale.calculateY(bar.value), + width: this.scale.calculateBarWidth(this.datasets.length) + }, easingDecimal).draw(); + } + }, this); + + }, this); + } + }); + + /// ----- ZUI change begin ----- + /// Use jquery object to create Chart object + $.fn.barChart = function(data, options) + { + var barCharts = []; + this.each(function() + { + var $this = $(this); + barCharts.push(new Chart(this.getContext("2d")).Bar(data, $.extend($this.data(), options))); + }); + return barCharts.length === 1 ? barCharts[0] : barCharts; + } + + /// ----- ZUI change end ----- + + /// ----- ZUI change begin ----- + /// Add jquery object to namespace + + /// }).call(this); // Old code +}).call(this, jQuery); + +/// ----- ZUI change end ----- -- GitLab