if (typeof(OfficeExcel) == 'undefined') OfficeExcel = {isOfficeExcel:true,type:'common'}; OfficeExcel.Registry = {}; OfficeExcel.Registry.store = []; OfficeExcel.Registry.store['chart.event.handlers'] = []; OfficeExcel.background = {}; OfficeExcel.objects = []; OfficeExcel.Resizing = {}; OfficeExcel.events = []; HALFPI = (Math.PI / 2); PI = Math.PI; TWOPI = PI * 2; /** * Returns five values which are used as a nice scale * * @param max int The maximum value of the graph * @param obj object The graph object * @return array An appropriate scale */ OfficeExcel.getScale = function (max, obj, minVal, maxVal,yminVal,ymaxVal) { /** * Special case for 0 */ /*if (max == 0 && obj != undefined && obj.type != 'scatter') { return ['0.2', '0.4', '0.6', '0.8', '1.0']; }*/ var original_max = max; /** * Manually do decimals */ var mainObj = obj; if(undefined == mainObj) mainObj = bar; if('auto' == mainObj._otherProps._ylabels_count) { if(( 'bar' == mainObj.type || 'line' == mainObj.type) && mainObj._otherProps._autoGrouping != undefined && mainObj._otherProps._autoGrouping == 'stackedPer') { var arrNew = mainObj.data; if(typeof(arrNew[0]) == 'object') { var arrMin = []; var arrMax = []; for (var j=0; j < arrNew.length; j++) { var newMax = 0; var newMin = 0; if('bar' == mainObj.type) { for (var i=0; i<arrNew[j].length; i++) { if(arrNew[j][i] > 0) newMax += arrNew[j][i] else newMin += arrNew[j][i] } arrMin[j] = newMin; arrMax[j] = newMax; } else { min = Math.min.apply(null, arrNew[j]); max = Math.max.apply(null, arrNew[j]); arrMin[j] = min; arrMax[j] = max; } } min = Math.min.apply(null, arrMin); max = Math.max.apply(null, arrMax); } else { //min = Math.min.apply(null, arrNew); //max = Math.max.apply(null, arrNew); min = minVal; max = maxVal; } var newMin = min; var newMax = max; //находим максимум после преобразования if('bar' != mainObj.type) { if(typeof(arrNew[0]) == 'object') { var arrMin = []; var arrMax = []; for (var j=0; j < arrNew.length; j++) { newMin = Math.min.apply(null, arrNew[j]); newMax = Math.max.apply(null, arrNew[j]); arrMin[j] = newMin; arrMax[j] = newMax; } newMin = Math.min.apply(null, arrMin); newMax = Math.max.apply(null, arrMax); } else { newMin = Math.min.apply(null, arrNew); newMax = Math.max.apply(null, arrNew); } } if(max <= 0 && min < 0) { var tempVal = Math.abs(newMax) newMax = Math.abs(newMin); newMin = tempVal; } var massRes = []; //шаг нужно высчитывать var step = 10; if(((newMax - newMin)/10) > 11 ) step = 20; if('bar' == mainObj.type && max > 0 && min < 0) step = 20; var maxValue = 100; //находим максимум for (var i=0; i < 11; i++) { if(newMax < 100 - step*i && newMax > 100 - step*(i+1)) maxValue = 100 - step*i; } if(maxValue > 100) maxValue = 100; //получаем массив if(max <= 0 && min < 0) { if('bar' == mainObj.type) { for (var j=0; j < 11; j++) { massRes[j] = (maxValue - step*j); if(massRes[j] == step) { break; } } mainObj._otherProps._xaxispos = 'top'; massRes = OfficeExcel.array_reverse(massRes); mainObj._otherProps._ymax = massRes[massRes.length - 1]; mainObj._otherProps._ymin = 0; /*massRes = [10,20,30,40,50,60,70,80,90,100]; mainObj._otherProps._ymax = 100; mainObj._otherProps._ymin = 0;*/ } else { for (var j=0; j < 11; j++) { massRes[j] = -(maxValue - step - step*j); if(massRes[j] == 0) { break; } } mainObj._otherProps._ymax = 0; mainObj._otherProps._ymin = OfficeExcel.array_exp(massRes[0] - step); } } else if(max > 0 && min > 0) { for (var j=0; j < 11; j++) { massRes[j] = maxValue - step*j; if(massRes[j] - step == 0) { massRes = OfficeExcel.array_reverse(massRes); break; } } mainObj._otherProps._ymax = OfficeExcel.array_exp(maxValue); mainObj._otherProps._ymin = OfficeExcel.array_exp(massRes[0] - step); } else { for (var j=0; j < 11; j++) { massRes[j] = maxValue - step*j; if(massRes[j] - step <= newMin) { massRes = OfficeExcel.array_reverse(massRes); break; } } mainObj._otherProps._ymax = OfficeExcel.array_exp(maxValue); mainObj._otherProps._ymin = massRes[0] - step; } return OfficeExcel.array_exp(massRes); /*} else if(min < 0 && max < 0) { }*/ } else if('scatter' == mainObj.type || 'hbar' == mainObj.type) { var max1; var arr = []; //находим минимальное значение var min; var trueOX = false; if('hbar' == mainObj.type) { trueOX = true; if(typeof(mainObj.data[0]) == 'object') { var arrMin = []; var arrMax = []; for (var j=0; j < mainObj.data.length; j++) { min = Math.min.apply(null, mainObj.data[j]); max = Math.max.apply(null, mainObj.data[j]); arrMin[j] = min; arrMax[j] = max; } min = Math.min.apply(null, arrMin); max = Math.max.apply(null, arrMax); } else { min = Math.min.apply(null, mainObj.data); max = Math.max.apply(null, mainObj.data); } //min = minVal; //max = maxVal; } if('scatter' == mainObj.type) { //в этом случае определяем значения для оси OX(max == true) if(mainObj._otherProps._type == 'burse2') { var arrTemp = [] var k = 0; for (var j=0; j < mainObj.data[0].length; j++) { for (var i=0; i<5; i++) { arrTemp[k] = mainObj.data[0][j][1][i]; k++; } } min = Math.min.apply(null, arrTemp); max = Math.max.apply(null, arrTemp); if(min == max && max == 0) { mainObj._otherProps._ymax = 1; mainObj._otherProps._ymin = 0; return [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1] } } else if(undefined != max && true == max) { /*var arrTemp = [] var k = 0; for (var j=0; j < mainObj.data.length; j++) { for (var i=0; i<mainObj.data[j].length; i++) { if(typeof(mainObj.data[j][i]) == 'object') { arrTemp[k] = mainObj.data[j][i][0]; k++; } } } min = Math.min.apply(null, arrTemp); max = Math.max.apply(null, arrTemp);*/ min = minVal; max = maxVal; trueOX = true; } else { /*var arrTemp = []; var k = 0; for (var j=0; j < mainObj.data.length; j++) { for (var i=0; i<mainObj.data[j].length; i++) { if(typeof(mainObj.data[j][i]) == 'object') { arrTemp[k] = mainObj.data[j][i][1]; k++; } } } min = Math.min.apply(null, arrTemp); max = Math.max.apply(null, arrTemp);*/ min = yminVal; max = ymaxVal; } if((min == 0 && max == 0) ||(isNaN(min) && isNaN(max))) return [0,0.2,0.4,0.6,0.8,1,1.2]; } var degreeNum = 1; var maxString = max.toExponential(); var minString = min.toExponential(); var floatKoff = 1000000000000; if(maxString.search('e-') != -1 || minString.search('e-') != -1) { var partMin = minString.split('e-'); var partMax = maxString.split('e-'); if(partMin[1] != undefined) degreeNum = Math.pow(10, partMin[1]) if(partMax[1] != undefined && ((parseFloat(partMin[1]) < parseFloat(partMax[1])) || partMin[1] == undefined)) degreeNum = Math.pow(10, partMax[1]) max = OfficeExcel.num_round(max*degreeNum); min = OfficeExcel.num_round(min*degreeNum); } var axisXMax; var axisXMin; var stepOY; var checkInput = false; var greaterNull; var chackBelowNull = false; var checkIsMaxMin = false; var arrForRealDiff = []; if((min == 0 && max == 0) ||(isNaN(min) && isNaN(max))) { if( mainObj._otherProps._autoGrouping == 'stackedPer') return [20,40,60,80,100]; else return [0.2,0.4,0.6,0.8,1,1.2]; } //подготовительная работы для дальнейшего вычисления шага if(max >= 0 && min >= 0) { if(max == min) { checkIsMaxMin = true; min = 0; } var diffPerMaxMin = ((max - min)/max)*100; axisXMax = max + 0.05 * (max - min); stepOY = (max-min)/4; if(16.667 > diffPerMaxMin) { if(trueOX) { axisXMin = min; greaterNull = (max - min)/4; arrForRealDiff = [1.59595959,3.18181818,7.954545454]; } else { axisXMin = min; greaterNull = (max - min)/6; arrForRealDiff = [1.51515151,3.03030303,7.57575757]; } } else { if(trueOX) { greaterNull = max/4; arrForRealDiff = [1.66666666,3.33333333,8.33333333]; axisXMin = 0; } else { axisXMin = 0; } } } else if(max <= 0 && min <= 0) { if(max == min) { checkIsMaxMin = true; max = 0; } var tempMax = max; if(!trueOX) mainObj._otherProps._xaxispos = 'top'; else mainObj._otherProps._yaxispos = 'right'; max = Math.abs(min); min = Math.abs(tempMax); checkInput = true; var diffPerMaxMin = Math.abs(((max - min)/max))*100; axisXMax = max; stepOY = (max-min)/4; chackBelowNull = true; if(16.667 > diffPerMaxMin) { axisXMin = min; greaterNull = Math.abs((Math.abs(max) - Math.abs(min)))/6; arrForRealDiff = [1.51515151,3.03030303,7.57575757]; } else { if(trueOX) { greaterNull = max/4; arrForRealDiff = [1.66666666,3.33333333,8.33333333]; axisXMin = 0; } else { axisXMin = 0; } } } else if(max > 0 && min < 0) { //mainObj._otherProps._xaxispos = 'center'; stepOY = (max + Math.abs(min))/4; axisXMax = max; axisXMin = min; if(trueOX) { greaterNull = (Math.abs(max) + Math.abs(min))/4; arrForRealDiff = [1.59090909,3.18181818,7.954545454] } else { greaterNull = Math.abs((Math.abs(max) + Math.abs(min)))/6; arrForRealDiff = [1.51515151,3.03030303,7.57575757] } //greaterNull = (max - min)/8; } //приводим к первому порядку для дальнейших вычислений var secPart = max.toString().split('.'); var numPow = 1; if(0 != secPart[0]) numPow = Math.pow(10, secPart[0].toString().length - 1) max = max/numPow; if(0 == max.toString().split('.')[0]) { var tempMax = max; var num = -1; while(0 == tempMax.toString().split('.')[0]) { tempMax = max; numPow = Math.pow(10, num); tempMax = tempMax/numPow; num--; } max = tempMax; } var stepOYPart = stepOY.toString().split('.'); var numPowOY; var tempVal; if(0 != stepOYPart[0]) numPowOY = Math.pow(10, stepOYPart[0].toString().length - 1) if(10 == stepOYPart[0]) numPowOY = 1; if(0 == stepOYPart[0]) { var tempMax = stepOY; var num = -1; while(0 == tempMax.toString().split('.')[0]) { tempMax = stepOY; numPowOY = Math.pow(10, num); tempMax = tempMax/numPowOY; num--; } } //поиск шага if(undefined != greaterNull) { var greaterNullTemp = greaterNull.toString().split('.'); if(0 != greaterNullTemp[0]) greaterNullNum = Math.pow(10, greaterNullTemp[0].toString().length - 1) if(0 == greaterNullTemp[0]) { var tempMax = greaterNull; var num = -1; while(0 == tempMax.toString().split('.')[0]) { tempMax = greaterNull; greaterNullNum = Math.pow(10, num); tempMax = tempMax/greaterNullNum; num--; } } greaterNull = greaterNull/greaterNullNum; //if(axisXMin == 0) //{ if(1 < greaterNull && arrForRealDiff[0] >= greaterNull) greaterNull = 1; else if(arrForRealDiff[0] < greaterNull && arrForRealDiff[1] >= greaterNull) greaterNull = 2; else if(arrForRealDiff[1] < greaterNull && arrForRealDiff[2] >= greaterNull) greaterNull = 5; else if(arrForRealDiff[2] < greaterNull && 10 >= greaterNull) greaterNull = 10; // } greaterNull = greaterNull*greaterNullNum; //console.log(greaterNull) stepOY = greaterNull; } arr[0] = 0;arr[1] = 1;arr[2] = 2;arr[3] = 5;arr[4] = 10; //если максимальное значение больше числа из данного массива, меняем диапазон по оси OY var arrMaxVal = [0,0.952380952,1.904761904,4.76190476,9.523809523] //массив диапазонов var arrDiffVal1 = [0,0.2,0.5,1,2] if(axisXMin == 0 && undefined == greaterNull)//если разница между min и max такая, что не нужно масштабировать { for (var i=0; i<arr.length; i++) { if( max >= arr[i] && max <= arr[i+1]) { var max1 = arr[i+1]; var trueMax; var diff = max1/10; var trueDiff = diff; var maxVal; //проверяем есть ли переход в следующий диапазон if(max > arrMaxVal[i+1]) { trueDiff = arrDiffVal1[i+1] } } } stepOY = trueDiff*numPow; } if('hbar' == mainObj.type && mainObj._otherProps._autoGrouping == 'stackedPer') { if(axisXMin < 0 && axisXMax > 0) { var summVal = Math.abs(axisXMin) + Math.abs(axisXMax) if(summVal <= 100) stepOY = 10; else if(summVal > 100 && summVal <= 139) stepOY = 20; else stepOY = 50; } else { stepOY = 20; } } //находим истинные min и max var testDiff; var axisXMinTest; if(axisXMin == 0) { testDiff = stepOY/numPow; axisXMinTest = axisXMin/numPow } else { testDiff = stepOY/numPowOY; axisXMinTest = axisXMin/numPowOY; } var tempNum; var countAfterPoint = 1; if(undefined != axisXMinTest.toString().split('.')[1]) { countAfterPoint = Math.pow(10, axisXMinTest.toString().split('.')[1].toString().length - 1) } if(1 == testDiff) tempNum = testDiff/4; else if(2 == testDiff) tempNum = testDiff/4; else if(5 == testDiff) tempNum = testDiff/10; else if(10 == testDiff) tempNum = testDiff/20; axisXMinTest = Math.floor(axisXMinTest); while(0 != axisXMinTest%testDiff) { axisXMinTest = axisXMinTest - tempNum; } //возвращаем массив var varMin = axisXMinTest*numPowOY; var massRes = []; var tempKoff = 100000000000; varMin = OfficeExcel.num_round(varMin); /*for (var k=0; k <= 11; k++) { massRes[k] = varMin + (k)*(stepOY); if(massRes[k] > axisXMax) { break; } }*/ var lengthNum; if(!trueOX) { if(chackBelowNull) { //varMin = varMin - stepOY; if(min == varMin && !checkIsMaxMin && min != 0 ) varMin = varMin - stepOY ; varMin = varMin/degreeNum; stepOY = stepOY/degreeNum; axisXMax = axisXMax/degreeNum; max = max/degreeNum; if(undefined != varMin.toString().split('.')[1]) lengthNum = varMin.toString().split('.')[1].length; for (var k=0; k <= 11; k++) { massRes[k] = OfficeExcel.num_round(varMin + (k)*(stepOY)); if(massRes[k] > axisXMax) { break; } } //if(massRes[0] == max) if(massRes[massRes.length - 1] == max && !checkIsMaxMin) massRes[massRes.length] = massRes[massRes.length - 1] + stepOY; mainObj._otherProps._ymax = -massRes[0]; mainObj._otherProps._ymin = -massRes[massRes.length - 1]; mainObj.max = -massRes[0]; } else { if(min == varMin && !checkIsMaxMin) varMin = varMin - stepOY ; if(undefined != varMin.toString().split('.')[1]) lengthNum = varMin.toString().split('.')[1].length; varMin = varMin/degreeNum; stepOY = stepOY/degreeNum; axisXMax = axisXMax/degreeNum; max = max/degreeNum; if(min == 0 && (mainObj._otherProps._type == 'burse2' || mainObj.type == 'scatter')) varMin = 0; if(max == 0 && mainObj._otherProps._type == 'burse2') axisXMax = 0 + stepOY; for (var k=0; k <= 11; k++) { massRes[k] = OfficeExcel.num_round(varMin + (k)*(stepOY)); if(massRes[k] > axisXMax) { break; } } if(massRes[massRes.length - 1] == max && !checkIsMaxMin) massRes[massRes.length] = massRes[massRes.length - 1] + stepOY; mainObj.max = massRes[massRes.length - 1]; mainObj._otherProps._ymax = massRes[massRes.length - 1]; mainObj._otherProps._ymin = massRes[0]; } } else { if(chackBelowNull) { //varMin = varMin - stepOY; if(min == varMin && !checkIsMaxMin && min != 0) varMin = varMin - stepOY ; if(undefined != varMin.toString().split('.')[1]) lengthNum = varMin.toString().split('.')[1].length; varMin = varMin/degreeNum; stepOY = stepOY/degreeNum; axisXMax = axisXMax/degreeNum; max = max/degreeNum; for (var k=0; k <= 11; k++) { massRes[k] = OfficeExcel.num_round(varMin + (k)*(stepOY)); if('hbar' == mainObj.type && mainObj._otherProps._autoGrouping == 'stackedPer') { if(massRes[k] >= original_max) { break; } } else { if(massRes[k] > axisXMax) { break; } } } if(massRes[massRes.length - 1] == max && !checkIsMaxMin) massRes[massRes.length] = massRes[massRes.length - 1] + stepOY; mainObj._otherProps._xmax = -massRes[0]; mainObj._otherProps._xmin = -massRes[massRes.length - 1]; //mainObj.max = -massRes[0]; } else { if(min == varMin && !checkIsMaxMin && 'hbar' != mainObj.type && mainObj._otherProps._autoGrouping != 'stackedPer') varMin = varMin - stepOY ; if(undefined != varMin.toString().split('.')[1]) lengthNum = varMin.toString().split('.')[1].length; varMin = varMin/degreeNum; stepOY = stepOY/degreeNum; axisXMax = axisXMax/degreeNum; max = max/degreeNum; for (var k=0; k <= 11; k++) { massRes[k] = OfficeExcel.num_round(parseFloat(varMin + (k)*(stepOY))); if('hbar' == mainObj.type && mainObj._otherProps._autoGrouping == 'stackedPer') { if(massRes[k] >= original_max) { break; } } else { if(massRes[k] > axisXMax) { break; } } } if(massRes[massRes.length - 1] == max && !checkIsMaxMin) massRes[massRes.length] = massRes[massRes.length - 1] + stepOY; mainObj._otherProps._xmax = massRes[massRes.length - 1]; mainObj._otherProps._xmin = massRes[0]; mainObj._otherProps._xmax = massRes[massRes.length - 1]; //this._otherProps._xmin = xScale[0] - (xScale[1]-xScale[0]); //this.xmin = this._otherProps._ymin; } //mainObj._otherProps._ymax = massRes[massRes.length - 1]; //mainObj._otherProps._ymin = massRes[0]; } if('hbar' == mainObj.type) { massRes.splice(0,1); } return OfficeExcel.array_exp(massRes); } else { var max1; var arr = []; //находим минимальное значение var min; var max; if('bar' == mainObj.type || 'hbar' == mainObj.type || 'radar' == mainObj.type) { if(mainObj._otherProps._type == 'accumulative') { //суммируем отрицательные и положительные значения if(typeof(mainObj.data[0]) == 'object') { var arrMin = []; var arrMax = []; for (var j=0; j < mainObj.data.length; j++) { var allHeightAbNull = 0; var allHeightLessNull = 0; for (var i=0; i < mainObj.data[j].length; i++) { if(mainObj.data[j][i] > 0) allHeightAbNull += mainObj.data[j][i]; else allHeightLessNull += mainObj.data[j][i]; } arrMin[j] = allHeightLessNull; arrMax[j] = allHeightAbNull; } min = Math.min.apply(null, arrMin); max = Math.max.apply(null, arrMax); } else { min = Math.min.apply(null, mainObj.data); max = Math.max.apply(null, mainObj.data); } } else { /*if(typeof(mainObj.data[0]) == 'object') { var arrMin = []; var arrMax = []; for (var j=0; j < mainObj.data.length; j++) { min = Math.min.apply(null, mainObj.data[j]); max = Math.max.apply(null, mainObj.data[j]); arrMin[j] = min; arrMax[j] = max; } min = Math.min.apply(null, arrMin); max = Math.max.apply(null, arrMax); } else { min = Math.min.apply(null, mainObj.data); max = Math.max.apply(null, mainObj.data); }*/ min = minVal; max = maxVal; } } else { if(('line' == mainObj.type && mainObj._otherProps._autoGrouping == 'stacked' ) || 'line' != mainObj.type ) { var arrMin = []; var arrMax = []; for (var j=0; j<mainObj.data.length; j++) { min = Math.min.apply(null, mainObj.data[j]); max = Math.max.apply(null, mainObj.data[j]); arrMin[j] = min; arrMax[j] = max; } min = Math.min.apply(null, arrMin); max = Math.max.apply(null, arrMax); } else { min = minVal; max = maxVal; } } if(max == min) { if(max > 0) min = 0; else if(max < 0) max = 0; } var degreeNum = 1; var maxString = max.toExponential(); var minString = min.toExponential(); var floatKoff = 10000000000; if(maxString.search('e-') != -1 || minString.search('e-') != -1) { var partMin = minString.split('e-'); var partMax = maxString.split('e-'); if(partMin[1] != undefined) degreeNum = Math.pow(10, partMin[1]) if(partMax[1] != undefined && (parseFloat(partMin[1]) < parseFloat(partMax[1]))) degreeNum = Math.pow(10, partMax[1]) max = OfficeExcel.num_round(max*degreeNum); min = OfficeExcel.num_round(min*degreeNum); } var axisXMax; var axisXMin; var stepOY; var checkInput = false; var greaterNull; var firstMax = max; var firstMin = min; var arrForRealDiff = []; if(max >= 0 && min >= 0) { var diffPerMaxMin = ((max - min)/max)*100; axisXMax = max + 0.05 * (max - min); stepOY = (max-min)/4; if(16.667 > diffPerMaxMin) { axisXMin = min - ((max - min) / 2); greaterNull = (max - min)/4; arrForRealDiff = [1.5873,3.1745,7.93651] } else { axisXMin = 0; } } else if(max <= 0 && min <= 0) { var tempMax = max; mainObj._otherProps._xaxispos = 'top'; max = Math.abs(min); min = Math.abs(tempMax); checkInput = true; var diffPerMaxMin = ((max - min)/max)*100; axisXMax = max + 0.05 * (max - min); stepOY = (max-min)/4; if(16.667 > diffPerMaxMin) { axisXMin = min - ((max - min) / 2); greaterNull = (max - min)/4; arrForRealDiff = [1.5873,3.1745,7.93651] } else { axisXMin = 0; } } else if(max > 0 && min < 0) { //mainObj._otherProps._xaxispos = 'center'; stepOY = (max + Math.abs(min))/4; axisXMax = max + 0.05 * (max - min); axisXMin = min + 0.05 * (min - max); greaterNull = (Math.abs(max) + Math.abs(min))/6; arrForRealDiff = [1.51515151,3.03030303,7.57575757] //greaterNull = (max - min)/8; } //приведение к первому порядку для дальнейших вычислений var secPart = max.toString().split('.'); var numPow = 1; if(0 != secPart[0]) numPow = Math.pow(10, secPart[0].toString().length - 1) max = max/numPow; if((min == 0 && max == 0) ||(isNaN(min) && isNaN(max))) return [0.2,0.4,0.6,0.8,1,1.2]; if(0 == max.toString().split('.')[0]) { var tempMax = max; var num = -1; while(0 == tempMax.toString().split('.')[0]) { tempMax = max; numPow = Math.pow(10, num); tempMax = tempMax/numPow; num--; } max = tempMax; } var stepOYPart = stepOY.toString().split('.'); var numPowOY; var tempVal; if(0 != stepOYPart[0]) numPowOY = Math.pow(10, stepOYPart[0].toString().length - 1) if(10 == stepOYPart[0]) numPowOY = 1; if(0 == stepOYPart[0]) { var tempMax = stepOY; var num = -1; while(0 == tempMax.toString().split('.')[0]) { tempMax = stepOY; numPowOY = Math.pow(10, num); tempMax = tempMax/numPowOY; num--; } } //поиск шага if(undefined != greaterNull) { var greaterNullTemp = greaterNull.toString().split('.'); if(0 != greaterNullTemp[0]) greaterNullNum = Math.pow(10, greaterNullTemp[0].toString().length - 1) if(0 == greaterNullTemp[0]) { var tempMax = greaterNull; var num = -1; while(0 == tempMax.toString().split('.')[0]) { tempMax = greaterNull; greaterNullNum = Math.pow(10, num); tempMax = tempMax/greaterNullNum; num--; } } greaterNull = greaterNull/greaterNullNum; if(1 < greaterNull && arrForRealDiff[0] >= greaterNull) greaterNull = 1; else if(arrForRealDiff[0] < greaterNull && arrForRealDiff[1] >= greaterNull) greaterNull = 2; else if(arrForRealDiff[1] < greaterNull && arrForRealDiff[2] >= greaterNull) greaterNull = 5; else if(arrForRealDiff[2] < greaterNull && 10 >= greaterNull) greaterNull = 10; greaterNull = greaterNull*greaterNullNum; stepOY = greaterNull; } arr[0] = 0;arr[1] = 1;arr[2] = 2;arr[3] = 5;arr[4] = 10; //если максимальное значение больше числа из данного массива, меняем диапазон по оси OY var arrMaxVal = [0,0.952380952,1.904761904,4.76190476,9.523809523] //массив диапазонов var arrDiffVal1 = [0,0.2,0.5,1,2] if(axisXMin == 0)//если разница между min и max такая, что не нужно масштабировать { for (var i=0; i<arr.length; i++) { if( max >= arr[i] && max <= arr[i+1]) { var max1 = arr[i+1]; var trueMax; var diff = max1/10; var trueDiff = diff; var maxVal; //проверяем есть ли переход в следующий диапазон if(max > arrMaxVal[i+1]) { trueDiff = arrDiffVal1[i+1] } } } stepOY = trueDiff*numPow; } //находим истинные min и max var testDiff; var axisXMinTest; if(axisXMin == 0) { testDiff = stepOY/numPow; axisXMinTest = axisXMin/numPow } else { testDiff = stepOY/numPowOY; axisXMinTest = axisXMin/numPowOY; } var tempNum; var countAfterPoint = 1; if(undefined != axisXMinTest.toString().split('.')[1]) { countAfterPoint = Math.pow(10, axisXMinTest.toString().split('.')[1].toString().length - 1) } var floatKoff = 10000000000; if(0.5 == testDiff) tempNum = testDiff/5; else if(1 == testDiff) tempNum = testDiff/4; else if(2 == testDiff) tempNum = testDiff/4; else if(5 == testDiff) tempNum = testDiff/10; else tempNum = testDiff/20; if(testDiff != 0.5) axisXMinTest = Math.floor(axisXMinTest); else { axisXMinTest = Math.round(axisXMinTest*100)/100; if(axisXMinTest.toString().split('.')[1] != undefined) { var lengthAfterPoint = axisXMinTest.toString().split('.')[1].length; var l = 0; while(axisXMinTest.toString().split('.')[1].length != 1) { axisXMinTest = axisXMinTest - Math.pow(10,-(lengthAfterPoint)); if(l > 9) { axisXMinTest = Math.floor(axisXMinTest); break; } l++; } } } while(0 != axisXMinTest%testDiff) { axisXMinTest = axisXMinTest - tempNum; if(testDiff == 0.5) { axisXMinTest = OfficeExcel.num_round(axisXMinTest); } } //возвращаем массив var varMin = axisXMinTest*numPowOY; var massRes = []; var tempKoff = 100000000000000; varMin = OfficeExcel.num_round(varMin); if(undefined != varMin.toString().split('.')[1]) lengthNum = varMin.toString().split('.')[1].length; if('radar' == mainObj.type) { for (var k=0; k <= 11; k++) { if(undefined != lengthNum) massRes[k] = (varMin + (k)*(stepOY)).toFixed(lengthNum); else massRes[k] = varMin + (k)*(stepOY); if(massRes[k] > axisXMax) { break; } } if(firstMax < 0 && firstMin < 0) { for (var k=0; k < massRes.length; k++) { massRes[k] = - massRes[k]; } var tempMax = firstMax; firstMax = firstMin; firstMin = tempMax; } if(firstMax == massRes[massRes.length - 2]) massRes.splice(massRes.length - 1,massRes.length - 1); if(firstMin == massRes[1]) massRes.splice(0,0); if(firstMin < 0 && firstMax > 0) { for (var i=0; i <= massRes.length; i++) { if(firstMin == massRes[i]) { massRes.splice(0,i); break; } } } if(firstMax < 0 && firstMin < 0) massRes = OfficeExcel.array_reverse(massRes); return [massRes,min,max]; } else if('line' == mainObj.type && max > 0 && min < 0) { //varMin = varMin + stepOY; varMin = varMin/degreeNum; stepOY = stepOY/degreeNum; axisXMax = axisXMax/degreeNum; for (var k=0; k <= 11; k++) { massRes[k] = OfficeExcel.num_round((parseFloat(varMin + (k+1)*(stepOY)))); if(massRes[k] > axisXMax) { break; } } } else { varMin = varMin/degreeNum; stepOY = stepOY/degreeNum; axisXMax = axisXMax/degreeNum; for (var k=0; k <= 11; k++) { massRes[k] = OfficeExcel.num_round((varMin + (k+1)*(stepOY))); if(massRes[k] > axisXMax) { break; } } } if('hbar' == mainObj.type) { mainObj._otherProps._xmin = massRes[0] - stepOY; mainObj._otherProps._xmax = massRes[massRes.length - 1]; } else if('line' == mainObj.type && max > 0 && min < 0) { mainObj._otherProps._ymax = massRes[massRes.length - 1]; mainObj._otherProps._ymin = OfficeExcel.num_round(OfficeExcel.array_exp(massRes[0] - stepOY)); } else { mainObj._otherProps._ymax = massRes[massRes.length - 1]; mainObj._otherProps._ymin = OfficeExcel.num_round(OfficeExcel.array_exp(massRes[0] - stepOY)); } return OfficeExcel.array_exp(massRes); } } if (max <= 1) { if (max > 0.5) { return [0.2,0.4,0.6,0.8, Number(1).toFixed(1)]; } else if (max >= 0.1) { return obj._otherProps._scale_round ? [0.2,0.4,0.6,0.8,1] : [0.1,0.2,0.3,0.4,0.5]; } else { var tmp = max; var exp = 0; while (tmp < 1.01) { exp += 1; tmp *= 10; } var ret = ['2e-' + exp, '4e-' + exp, '6e-' + exp, '8e-' + exp, '10e-' + exp]; if (max <= ('5e-' + exp)) { ret = ['1e-' + exp, '2e-' + exp, '3e-' + exp, '4e-' + exp, '5e-' + exp]; } return ret; } } // Take off any decimals if (String(max).indexOf('.') > 0) { max = String(max).replace(/\.\d+$/, ''); } var interval = Math.pow(10, Number(String(Number(max)).length - 1)); var topValue = interval; while (topValue < max) { topValue += (interval / 2); } // Handles cases where the max is (for example) 50.5 if (Number(original_max) > Number(topValue)) { topValue += (interval / 2); } // Custom if the max is greater than 5 and less than 10 if (max < 10) { topValue = (Number(original_max) <= 5 ? 5 : 10); } /** * Added 02/11/2010 to create "nicer" scales */ if (obj && typeof(obj._otherProps._scale_round) == 'boolean' && obj._otherProps._scale_round) { topValue = 10 * interval; } return [topValue * 0.2, topValue * 0.4, topValue * 0.6, topValue * 0.8, topValue]; } /** * Returns the maximum numeric value which is in an array * * @param array arr The array (can also be a number, in which case it's returned as-is) * @param int Whether to ignore signs (ie negative/positive) * @return int The maximum value in the array */ OfficeExcel.array_max = function (arr) { var max = null; if (typeof(arr) == 'number') { return arr; } for (var i=0; i<arr.length; ++i) { if (typeof(arr[i]) == 'number') { var val = arguments[1] ? Math.abs(arr[i]) : arr[i]; if (typeof(max) == 'number') { max = Math.max(max, val); } else { max = val; } } } return max; } OfficeExcel.array_exp = function (arr) { var maxDig = 1000000000; var minDig = 0.000000001; if(typeof(arr) == 'number') { if(arr < 0) maxDig = 100000000; if(Math.abs(arr) > maxDig) { var tmp = Math.abs(arr); var exp = 0; while (tmp > 9) { exp += 1; tmp /= 10; } if(arr < 0) tmp *= -1; arr = tmp + "E+" + exp; } /*else if(Math.abs(arr) < minDig && Math.abs(arr) > 0) { var tmp = Math.abs(arr); var exp = 0; while (tmp < 9) { exp += 1; tmp *= 10; } if(arr < 0) tmp *= -1; arr = tmp + "E-" + exp; }*/ } else { for (var i=0; i<arr.length; ++i) { maxDig = 1000000000 if(arr[i] < 0) maxDig = 100000000; if(Math.abs(arr[i]) > maxDig) { var tmp = Math.abs(arr[i]); var exp = 0; while (tmp > 9) { exp += 1; tmp /= 10; } if(arr[i] < 0) tmp *= -1; arr[i] = tmp + "E+" + exp; } /*else if(Math.abs(arr[i]) < minDig && Math.abs(arr[i]) > 0) { var tmp = Math.abs(arr[i]); var exp = 0; while (tmp < 9) { exp += 1; tmp *= 10; } if(arr[i] < 0) tmp *= -1; arr[i] = tmp + "E-" + exp; }*/ } } return arr; } OfficeExcel.num_round = function (num) { /*var partNum = num.toString().split('.'); var len; if(partNum == undefined || num.toString().split('e-')[1] != undefined) { partNum = num.toString().split('e-'); len = partNum[1] + 1; } if(partNum[1] != undefined && partNum[1]) { if(!len) len = partNum[1].length; if(len) { var floatKoff = Math.pow(10, (len - 1)) if(floatKoff > 1) num = Math.round(num*floatKoff)/floatKoff ; } }*/ var floatKoff = 100000000000; num = Math.round(num*floatKoff)/floatKoff ; return num; } /** * Returns the maximum value which is in an array * * @param array arr The array * @param int len The length to pad the array to * @param mixed The value to use to pad the array (optional) */ OfficeExcel.array_pad = function (arr, len) { if (arr.length < len) { var val = arguments[2] ? arguments[2] : null; for (var i=arr.length; i<len; ++i) { arr[i] = val; } } return arr; } /** * An array sum function * * @param array arr The array to calculate the total of * @return int The summed total of the arrays elements */ OfficeExcel.array_sum = function (arr) { // Allow integers if (typeof(arr) == 'number') { return arr; } var i, sum; var len = arr.length; for(i=0,sum=0;i<len;sum+=arr[i++]); return sum; } /** * A simple is_array() function * * @param mixed obj The object you want to check * @return bool Whether the object is an array or not */ OfficeExcel.is_array = function (obj) { return obj != null && obj.constructor.toString().indexOf('Array') != -1; } /** * Converts degrees to radians * * @param int degrees The number of degrees * @return float The number of radians */ OfficeExcel.degrees2Radians = function (degrees) { return degrees * (Math.PI / 180); } /** * This function draws an angled line. The angle is cosidered to be clockwise * * @param obj ctxt The context object * @param int x The X position * @param int y The Y position * @param int angle The angle in RADIANS * @param int length The length of the line */ OfficeExcel.lineByAngle = function (context, x, y, angle, length) { context.arc(x, y, length, angle, angle, false); context.lineTo(x, y); context.arc(x, y, length, angle, angle, false); } /** * This is a useful function which is basically a shortcut for drawing left, right, top and bottom alligned text. * * @param object context The context * @param string font The font * @param int size The size of the text * @param int x The X coordinate * @param int y The Y coordinate * @param string text The text to draw * @parm string The vertical alignment. Can be null. "center" gives center aligned text, "top" gives top aligned text. * Anything else produces bottom aligned text. Default is bottom. * @param string The horizontal alignment. Can be null. "center" gives center aligned text, "right" gives right aligned text. * Anything else produces left aligned text. Default is left. * @param bool Whether to show a bounding box around the text. Defaults not to * @param int The angle that the text should be rotate at (IN DEGREES) * @param string Background color for the text * @param bool Whether the text is bold or not * @param bool Whether the bounding box has a placement indicator */ OfficeExcel.Text = function (context, font, size, x, y, text) { var drwContext = OfficeExcel.drawingCtxCharts; if(drwContext) { drwContext.setCanvas(bar.canvas); context = drwContext; // Need these now the angle can be specified, ie defaults for the former two args if (typeof(arguments[6]) == null) arguments[6] = 'bottom'; // Vertical alignment. Default to bottom/baseline if (typeof(arguments[7]) == null) arguments[7] = 'left'; // Horizontal alignment. Default to left if (typeof(arguments[8]) == null) arguments[8] = null; // Show a bounding box. Useful for positioning during development. Defaults to false if (typeof(arguments[9]) == null) arguments[9] = 0; // Angle (IN DEGREES) that the text should be drawn at. 0 is middle right, and it goes clockwise if (typeof(arguments[12]) == null) arguments[12] = true; // Whether the bounding box has the placement indicator // The alignment is recorded here for purposes of Opera compatibility if (navigator.userAgent.indexOf('Opera') != -1) { context.canvas.__OfficeExcel_valign__ = arguments[6]; context.canvas.__OfficeExcel_halign__ = arguments[7]; } // First, translate to x/y coords context.save(); context.canvas.__OfficeExcel_originalx__ = x; context.canvas.__OfficeExcel_originaly__ = y; context.translate(x, y); var italic = arguments[13] && arguments[13].italic ? arguments[13].italic : false; var underline = arguments[13] && arguments[13].underline ? arguments[13].underline : false; var ascFont = new Asc.FontProperties(font, size, arguments[11], italic, underline); context.setFont(ascFont); var width; var textSize; if(typeof text != 'string') text = text.toString(); if(text != "") textSize = context.measureText(text,1); // Vertical alignment - defaults to bottom if (arguments[6]) { var vAlign = arguments[6]; if(textSize) size1 = textSize.height/0.75; else size1 = size; if (vAlign == 'center') { y = y + size1 / 2; //context.translate(0, size / 2); } else if (vAlign == 'top') { y = y + size1; //context.translate(0, size); } } // Hoeizontal alignment - defaults to left if (arguments[7] && textSize) { var hAlign = arguments[7]; width = textSize.width/0.75; if (hAlign) { if (hAlign == 'center') { //context.translate(-1 * (width / 2), 0) x = x - width/2; } else if (hAlign == 'right') { x = x - width; //context.translate(-1 * width, 0) } } } if(arguments[13] && arguments[13].color) context.setFillStyle(arguments[13].color); else context.setFillStyle("#000000"); x = x/(drwContext.scaleFactor); y = y/(drwContext.scaleFactor); // Rotate the canvas if need be if (arguments[9] && textSize) { var textOptions = { font: ascFont, width: textSize.width, height: textSize.height, x: x*0.75, y: y*0.75 }; OfficeExcel.drawTurnedText(context,textOptions, text, 90); } if(!arguments[9]) { context.fillText(text, x*0.75, y*0.75); context.lineWidth = 1; } context.restore(); } else { /** * This calls the text function recursively to accommodate multi-line text */ if (typeof(text) == 'string' && text.match(/\r\n/)) { var arr = text.split('\r\n'); text = arr[0]; arr = OfficeExcel.array_shift(arr); var nextline = arr.join('\r\n') OfficeExcel.Text(context, font, size, arguments[9] == -90 ? (x + (size * 1.5)) : x, y + (size * 1.5), nextline, arguments[6] ? arguments[6] : null, 'center', arguments[8], arguments[9], arguments[10], arguments[11], arguments[12]); } // Accommodate MSIE if (OfficeExcel.isOld()) { y += 2; } context.font = (arguments[11] ? 'Bold ': '') + size + 'pt ' + font; var i; var origX = x; var origY = y; var originalFillStyle = context.fillStyle; var originalLineWidth = context.lineWidth; // Need these now the angle can be specified, ie defaults for the former two args if (typeof(arguments[6]) == null) arguments[6] = 'bottom'; // Vertical alignment. Default to bottom/baseline if (typeof(arguments[7]) == null) arguments[7] = 'left'; // Horizontal alignment. Default to left if (typeof(arguments[8]) == null) arguments[8] = null; // Show a bounding box. Useful for positioning during development. Defaults to false if (typeof(arguments[9]) == null) arguments[9] = 0; // Angle (IN DEGREES) that the text should be drawn at. 0 is middle right, and it goes clockwise if (typeof(arguments[12]) == null) arguments[12] = true; // Whether the bounding box has the placement indicator // The alignment is recorded here for purposes of Opera compatibility if (navigator.userAgent.indexOf('Opera') != -1) { context.canvas.__OfficeExcel_valign__ = arguments[6]; context.canvas.__OfficeExcel_halign__ = arguments[7]; } // First, translate to x/y coords context.save(); context.canvas.__OfficeExcel_originalx__ = x; context.canvas.__OfficeExcel_originaly__ = y; context.translate(x, y); x = 0; y = 0; // Rotate the canvas if need be if (arguments[9]) { context.rotate(arguments[9] / 57.3); } // Vertical alignment - defaults to bottom if (arguments[6]) { var vAlign = arguments[6]; if (vAlign == 'center') { context.translate(0, size / 2); } else if (vAlign == 'top') { context.translate(0, size); } } // Hoeizontal alignment - defaults to left if (arguments[7]) { var hAlign = arguments[7]; var width = context.measureText(text).width; if (hAlign) { if (hAlign == 'center') { context.translate(-1 * (width / 2), 0) } else if (hAlign == 'right') { context.translate(-1 * width, 0) } } } context.fillStyle = originalFillStyle; /** * Draw a bounding box if requested */ context.save(); context.fillText(text,0,0); context.lineWidth = 1; if (arguments[8]) { var width = context.measureText(text).width; var ieOffset = OfficeExcel.isIE8() ? 2 : 0; context.translate(x, y); context.strokeRect(AA(context.canvas.__object__, - 3), AA(context.canvas.__object__, 0 - 3 - size - ieOffset), width + 6, 0 + size + 6); /** * If requested, draw a background for the text */ if (arguments[10]) { var offset = 3; var ieOffset = OfficeExcel.isIE8() ? 2 : 0; var width = context.measureText(text).width //context.strokeStyle = 'gray'; context.fillStyle = arguments[10]; context.fillRect(AA(context.canvas.__object__, x - offset), AA(context.canvas.__object__, y - size - offset - ieOffset), width + (2 * offset), size + (2 * offset)); //context.strokeRect(x - offset, y - size - offset - ieOffset, width + (2 * offset), size + (2 * offset)); } /** * Do the actual drawing of the text */ context.fillStyle = originalFillStyle; context.fillText(text,0,0); if (arguments[12]) { context.fillRect( arguments[7] == 'left' ? 0 : (arguments[7] == 'center' ? width / 2 : width ) - 2, arguments[6] == 'bottom' ? 0 : (arguments[6] == 'center' ? (0 - size) / 2 : 0 - size) - 2, 4, 4 ); } } context.restore(); // Reset the lineWidth context.lineWidth = originalLineWidth; context.restore(); } } OfficeExcel.drawTurnedText = function(drawingCtx,textOptions, text, angle) { var cx = textOptions.x; // center offset x var cy = textOptions.y; // center offset y var textWidth = textOptions.width; // NOTE: measure text (width * 0.5) var textHeight = textOptions.height; // NOTE: measure text (height * 0.5) var font = textOptions.font; var size = textOptions.size; var asc = Asc; if(!angle) angle = 90; var m = new asc.Matrix(); m.rotate(angle, 0); var mbt = new asc.Matrix(); mbt.translate(cx + textWidth, cy + textHeight); drawingCtx.setFont(font, angle); drawingCtx.setTextTransform(m.sx, m.shy, m.shx, m.sy, m.tx, m.ty); drawingCtx.setTransform(mbt.sx, mbt.shy, mbt.shx, mbt.sy, mbt.tx, mbt.ty); drawingCtx.updateTransforms(); drawingCtx.fillText(text, 0, 0, 0, 0, angle); drawingCtx.resetTransforms(); } OfficeExcel.TextWithoutFonts = function (context, font, size, x, y, text) { /** * This calls the text function recursively to accommodate multi-line text */ if (typeof(text) == 'string' && text.match(/\r\n/)) { var arr = text.split('\r\n'); text = arr[0]; arr = OfficeExcel.array_shift(arr); var nextline = arr.join('\r\n') OfficeExcel.Text(context, font, size, arguments[9] == -90 ? (x + (size * 1.5)) : x, y + (size * 1.5), nextline, arguments[6] ? arguments[6] : null, 'center', arguments[8], arguments[9], arguments[10], arguments[11], arguments[12]); } // Accommodate MSIE if (OfficeExcel.isOld()) { y += 2; } context.font = (arguments[11] ? 'Bold ': '') + size + 'pt ' + font; var i; var origX = x; var origY = y; var originalFillStyle = context.fillStyle; var originalLineWidth = context.lineWidth; // Need these now the angle can be specified, ie defaults for the former two args if (typeof(arguments[6]) == null) arguments[6] = 'bottom'; // Vertical alignment. Default to bottom/baseline if (typeof(arguments[7]) == null) arguments[7] = 'left'; // Horizontal alignment. Default to left if (typeof(arguments[8]) == null) arguments[8] = null; // Show a bounding box. Useful for positioning during development. Defaults to false if (typeof(arguments[9]) == null) arguments[9] = 0; // Angle (IN DEGREES) that the text should be drawn at. 0 is middle right, and it goes clockwise if (typeof(arguments[12]) == null) arguments[12] = true; // Whether the bounding box has the placement indicator // The alignment is recorded here for purposes of Opera compatibility if (navigator.userAgent.indexOf('Opera') != -1) { context.canvas.__OfficeExcel_valign__ = arguments[6]; context.canvas.__OfficeExcel_halign__ = arguments[7]; } // First, translate to x/y coords context.save(); context.canvas.__OfficeExcel_originalx__ = x; context.canvas.__OfficeExcel_originaly__ = y; context.translate(x, y); x = 0; y = 0; // Rotate the canvas if need be if (arguments[9]) { context.rotate(arguments[9] / 57.3); } // Vertical alignment - defaults to bottom if (arguments[6]) { var vAlign = arguments[6]; if (vAlign == 'center') { context.translate(0, size / 2); } else if (vAlign == 'top') { context.translate(0, size); } } // Hoeizontal alignment - defaults to left if (arguments[7]) { var hAlign = arguments[7]; var width = context.measureText(text).width; if (hAlign) { if (hAlign == 'center') { context.translate(-1 * (width / 2), 0) } else if (hAlign == 'right') { context.translate(-1 * width, 0) } } } context.fillStyle = originalFillStyle; /** * Draw a bounding box if requested */ context.save(); context.fillText(text,0,0); context.lineWidth = 1; if (arguments[8]) { var width = context.measureText(text).width; var ieOffset = OfficeExcel.isIE8() ? 2 : 0; context.translate(x, y); context.strokeRect(AA(context.canvas.__object__, - 3), AA(context.canvas.__object__, 0 - 3 - size - ieOffset), width + 6, 0 + size + 6); /** * If requested, draw a background for the text */ if (arguments[10]) { var offset = 3; var ieOffset = OfficeExcel.isIE8() ? 2 : 0; var width = context.measureText(text).width //context.strokeStyle = 'gray'; context.fillStyle = arguments[10]; context.fillRect(AA(context.canvas.__object__, x - offset), AA(context.canvas.__object__, y - size - offset - ieOffset), width + (2 * offset), size + (2 * offset)); //context.strokeRect(x - offset, y - size - offset - ieOffset, width + (2 * offset), size + (2 * offset)); } /** * Do the actual drawing of the text */ context.fillStyle = originalFillStyle; context.fillText(text,0,0); if (arguments[12]) { context.fillRect( arguments[7] == 'left' ? 0 : (arguments[7] == 'center' ? width / 2 : width ) - 2, arguments[6] == 'bottom' ? 0 : (arguments[6] == 'center' ? (0 - size) / 2 : 0 - size) - 2, 4, 4 ); } } context.restore(); // Reset the lineWidth context.lineWidth = originalLineWidth; context.restore(); } // Clear canvas settings and fill rect OfficeExcel.Clear = function (canvas, color) { var context = canvas.getContext('2d'); if (OfficeExcel.isIE8() && !color) color = 'white'; // Clear canvas if (!color || (color && color == 'transparent')) { context.clearRect(0, 0, canvas.width, canvas.height); // Reset the globalCompositeOperation context.globalCompositeOperation = 'source-over'; } else { context.fillStyle = color; context = canvas.getContext('2d'); context.beginPath(); if (OfficeExcel.isIE8()) context.fillRect(0, 0, canvas.width, canvas.height); else context.fillRect(-10, -10, canvas.width + 20, canvas.height + 20); context.fill(); } if (OfficeExcel.ClearAnnotations) OfficeExcel.ClearAnnotations(canvas.id); OfficeExcel.FireCustomEvent(canvas.__object__, 'onclear'); } /** * Draws the title of the graph * * @param object canvas The canvas object * @param string text The title to write * @param integer gutter The size of the gutter * @param integer The center X point (optional - if not given it will be generated from the canvas width) * @param integer Size of the text. If not given it will be 14 */ OfficeExcel.DrawTitle = function (canvas, text, gutterTop) { var obj = canvas.__object__; var context = canvas.getContext('2d'); var gutterLeft = obj._chartGutter._left; var gutterRight = obj._chartGutter._right; var gutterBottom = obj._chartGutter._bottom; var size = arguments[4] ? arguments[4] : 12; var bold = obj._chartTitle._bold; var centerx = (arguments[3] ? arguments[3] : ((obj.canvas.width - gutterLeft - gutterRight) / 2) + gutterLeft); var keypos = obj._otherProps._key_position; var vpos = obj._chartTitle._vpos; var hpos = obj._chartTitle._hpos; var bgcolor = obj._chartTitle._background; var textOptions = { color: obj._chartTitle._color, underline: obj._chartTitle._underline, italic: obj._chartTitle._italic } // Account for 3D effect by faking the key position if (obj.type == 'bar' && obj._otherProps._variant == '3d') { keypos = 'gutter'; } context.beginPath(); context.fillStyle = obj._otherProps._text_color ? obj._otherProps._text_color : 'black'; /** * Vertically center the text if the key is not present */ if (keypos && keypos != 'gutter') { var vCenter = 'center'; } else if (!keypos) { var vCenter = 'center'; } else { var vCenter = 'bottom'; } // if chart title vPos does not equal 0.5, use that if (typeof(vpos) == 'number') { if (obj._otherProps._xaxispos == 'top') vpos = vpos * gutterBottom + gutterTop + (obj.canvas.height - gutterTop - gutterBottom); else vpos = vpos * gutterTop; } else { vpos = gutterTop - size - 5; if (obj._otherProps._xaxispos == 'top') { vpos = obj.canvas.height - gutterBottom + size + 5; } } // if chart title hPos is a number, use that. It's multiplied with the (entire) canvas width if (typeof(hpos) == 'number') { centerx = hpos * canvas.width; } // Set the colour if (typeof(obj._chartTitle._color != null)) { var oldColor = context.fillStyle var newColor = obj._chartTitle._color; context.fillStyle = newColor ? newColor : 'black'; } /** * Default font is Verdana */ var font = obj._otherProps._text_font; // Get chat title font if (typeof(obj._chartTitle._font) == 'string') font = obj._chartTitle._font; /** * Draw the title itself */ if('auto' == obj._otherProps._ylabels_count) { vpos = obj._chartTitle._vpos; vCenter = 'bottom'; } OfficeExcel.Text(context, font, size, centerx, vpos, text, vCenter, 'center', bgcolor != null, null, bgcolor, bold, null, textOptions); // Reset the fill colour context.fillStyle = oldColor; } /** * This function returns the mouse position in relation to the canvas * * @param object e The event object. */ OfficeExcel.getMouseXY = function (e) { var obj = (OfficeExcel.isIE8() ? event.srcElement : e.target); var x; var y; if (OfficeExcel.isIE8()) e = event; // Browser with offsetX and offsetY if (typeof(e.offsetX) == 'number' && typeof(e.offsetY) == 'number') { x = e.offsetX; y = e.offsetY; // FF and other } else { x = 0; y = 0; while (obj != document.body && obj) { x += obj.offsetLeft; y += obj.offsetTop; obj = obj.offsetParent; } x = e.pageX - x; y = e.pageY - y; } return [x, y]; } /** * This function returns a two element array of the canvas x/y position in * relation to the page * * @param object canvas */ OfficeExcel.getCanvasXY = function (canvas) { var x = 0; var y = 0; var obj = canvas; do { x += obj.offsetLeft; y += obj.offsetTop; obj = obj.offsetParent; } while (obj && obj.tagName.toLowerCase() != 'body'); return [x, y]; } /** * Registers a graph object (used when the canvas is redrawn) * * @param object obj The object to be registered */ OfficeExcel.Register = function (obj) { var key = obj.id + '_' + obj.type; OfficeExcel.objects[key] = obj; } /** * Causes all registered objects to be redrawn * * @param string An optional string indicating which canvas is not to be redrawn * @param string An optional color to use to clear the canvas */ OfficeExcel.Redraw = function () { for (i in OfficeExcel.objects) { // TODO FIXME Maybe include more intense checking for whether the object is an OfficeExcel object, eg obj.isOfficeExcel == true ...? if ( typeof(i) == 'string' && typeof(OfficeExcel.objects[i]) == 'object' && typeof(OfficeExcel.objects[i].type) == 'string' && OfficeExcel.objects[i].isOfficeExcel) { if (!arguments[0] || arguments[0] != OfficeExcel.objects[i].id) { OfficeExcel.Clear(OfficeExcel.objects[i].canvas, arguments[1] ? arguments[1] : null); OfficeExcel.objects[i].Draw(); } } } } /** * Loosly mimicks the PHP function print_r(); */ OfficeExcel.pr = function (obj) { var str = ''; var indent = (arguments[2] ? arguments[2] : ''); switch (typeof(obj)) { case 'number': if (indent == '') { str+= 'Number: ' } str += String(obj); break; case 'string': if (indent == '') { str+= 'String (' + obj.length + '):' } str += '"' + String(obj) + '"'; break; case 'object': // In case of null if (obj == null) { str += 'null'; break; } str += 'Object\n' + indent + '(\n'; for (var i in obj) { if (typeof(i) == 'string' || typeof(i) == 'number') { str += indent + ' ' + i + ' => ' + OfficeExcel.pr(obj[i], true, indent + ' ') + '\n'; } } var str = str + indent + ')'; break; case 'function': str += obj; break; case 'boolean': str += 'Boolean: ' + (obj ? 'true' : 'false'); break; } /** * Finished, now either return if we're in a recursed call, or alert() * if we're not. */ if (arguments[1]) { return str; } else { alert(str); } } /** * The OfficeExcel registry Set() function * * @param string name The name of the key * @param mixed value The value to set * @return mixed Returns the same value as you pass it */ OfficeExcel.Registry.Set = function (name, value) { // Store the setting OfficeExcel.Registry.store[name] = value; // Don't really need to do this, but ho-hum return value; } /** * The OfficeExcel registry Get() function * * @param string name The name of the particular setting to fetch * @return mixed The value if exists, null otherwise */ OfficeExcel.Registry.Get = function (name) { //return OfficeExcel.Registry.store[name] == null ? null : OfficeExcel.Registry.store[name]; return OfficeExcel.Registry.store[name]; } /** * This function draws the background for the bar chart, line chart and scatter chart. * * @param object obj The graph object */ OfficeExcel.background.Draw = function (obj) { var canvas = obj.canvas; var context = obj.context; var height = 0; var gutterLeft = obj._chartGutter._left; var gutterRight = obj._chartGutter._right; var gutterTop = obj._chartGutter._top; var gutterBottom = obj._chartGutter._bottom; var variant = obj._otherProps._variant; context.fillStyle = obj._otherProps._text_color; // If it's a bar and 3D variant, translate if (variant == '3d') { context.save(); context.translate(10, -5); } // X axis title if (typeof(obj._xAxisTitle._text) == 'string' && obj._xAxisTitle._text.length) { var size = obj._otherProps._text_size + 2; var font = obj._otherProps._text_font; var bold = obj._xAxisTitle._bold; var textOptions = { color: obj._xAxisTitle._color, underline: obj._xAxisTitle._underline, italic: obj._xAxisTitle._italic } if (typeof(obj._xAxisTitle._size) == 'number') size = obj._xAxisTitle._size; if (typeof(obj._xAxisTitle._font) == 'string') font = obj._xAxisTitle._font; var hpos = ((obj.canvas.width - obj._chartGutter._left - obj._chartGutter._right) / 2) + obj._chartGutter._left; var vpos = obj.canvas.height - obj._chartGutter._bottom + 25; if (typeof(obj._xAxisTitle._vpos) == 'number') { vpos = obj.canvas.height - (gutterBottom * obj._xAxisTitle._vpos); } if (obj._xAxisTitle._vpos != 'null') vpos = obj._xAxisTitle._vpos if (obj._xAxisTitle._hpos != 'null') hpos = obj._xAxisTitle._hpos context.beginPath(); OfficeExcel.Text(context, font, size, hpos, vpos, obj._xAxisTitle._text, 'center', 'center', false, false, false, bold, null, textOptions); context.fill(); } // Y axis title if (typeof(obj._yAxisTitle._text) == 'string' && obj._yAxisTitle._text.length) { var size = obj._otherProps._text_size + 2; var font = obj._otherProps._text_font; var angle = 270; var bold = obj._yAxisTitle._bold; var textOptions = { color: obj._yAxisTitle._color, underline: obj._yAxisTitle._underline, italic: obj._yAxisTitle._italic } var hpos; var vpos = ((obj.canvas.height - obj._chartGutter._top - obj._chartGutter._bottom) / 2) + obj._chartGutter._top; if (typeof(obj._yAxisTitle._hpos) == 'number') { hpos = obj._yAxisTitle._hpos * obj._chartGutter._left; } else { hpos = ((obj._chartGutter._left - 25) / obj._chartGutter._left) * obj._chartGutter._left; } if (typeof(obj._yAxisTitle._size) == 'number') size = obj._yAxisTitle._size; if (typeof(obj._yAxisTitle._font) == 'string') font = obj._yAxisTitle._font; if (obj._otherProps._title_yaxis_align == 'right' || obj._otherProps._title_yaxis_position == 'right') { angle = 90; hpos = obj._yAxisTitle._hpos ? obj._yAxisTitle._hpos * obj._chartGutter._right : obj.canvas.width - obj._chartGutter._right + obj._otherProps._text_size + 5; } else hpos = hpos; if(obj._yAxisTitle._angle != 'null' && obj._yAxisTitle._angle != undefined) angle = obj._yAxisTitle._angle; if (obj._yAxisTitle._vpos != 'null') vpos = obj._yAxisTitle._vpos; if (obj._yAxisTitle._hpos != 'null') hpos = obj._yAxisTitle._hpos; context.beginPath(); OfficeExcel.Text(context, font, size, hpos, vpos, obj._yAxisTitle._text, 'center', 'right',//change with center false, angle, false, bold, null, textOptions); context.fill(); } obj.context.beginPath(); // Draw the horizontal bars context.fillStyle = obj._otherProps._background_barcolor1; height = (OfficeExcel.GetHeight(obj) - gutterBottom); for (var i=gutterTop; i < height ; i+=80) { obj.context.fillRect(gutterLeft, i, OfficeExcel.GetWidth(obj) - gutterLeft - gutterRight, Math.min(40, OfficeExcel.GetHeight(obj) - gutterBottom - i) ); } context.fillStyle = obj._otherProps._background_barcolor2; height = (OfficeExcel.GetHeight(obj) - gutterBottom); for (var i= (40 + gutterTop); i < height; i+=80) { obj.context.fillRect(gutterLeft, i, OfficeExcel.GetWidth(obj) - gutterLeft - gutterRight, i + 40 > (OfficeExcel.GetHeight(obj) - gutterBottom) ? OfficeExcel.GetHeight(obj) - (gutterBottom + i) : 40); } context.stroke(); // Draw the background grid if (obj._otherProps._background_grid) { // If autofit is specified, use the .numhlines and .numvlines along with the width to work // out the hsize and vsize if (obj._otherProps._background_grid_autofit) { /** * Align the grid to the tickmarks */ if (obj._otherProps._background_grid_autofit_align) { // Align the horizontal lines obj._otherProps._background_grid_autofit_numhlines = obj._otherProps._ylabels_count; // Align the vertical lines for the line if (obj.type == 'line') { if (obj._otherProps._labels && obj._otherProps._labels.length) { obj._otherProps._background_grid_autofit_numvlines = obj._otherProps._labels.length - 1; } else { obj._otherProps._background_grid_autofit_numvlines = obj.data[0].length - 1; } // Align the vertical lines for the bar } else if (obj.type == 'bar' && obj._otherProps._labels && obj._otherProps._labels.length) { obj._otherProps._background_grid_autofit_numvlines = obj._otherProps._labels.length; } } var vsize = ((obj.canvas.width - gutterLeft - gutterRight)) / obj._otherProps._background_grid_autofit_numvlines; var hsize = (obj.canvas.height - gutterTop - gutterBottom) / (obj._otherProps._background_grid_autofit_numhlines); if(vsize > -1 && vsize < 1) vsize = 1; if(hsize > -1 && hsize < 1) hsize = 1; obj._otherProps._background_grid_vsize = vsize; obj._otherProps._background_grid_hsize = hsize; } context.beginPath(); context.lineWidth = obj._otherProps._background_grid_width ? obj._otherProps._background_grid_width : 1; context.strokeStyle = obj._otherProps._background_grid_color; // Draw the horizontal lines if (obj._otherProps._background_grid_hlines) { height = (OfficeExcel.GetHeight(obj) - gutterBottom - gutterTop) //for (y = gutterTop; y <= (height + gutterTop); y+=obj._otherProps._background_grid_hsize) { /*for (n = y; n < y + obj._otherProps._background_grid_hsize; n+=(obj._otherProps._background_grid_hsize/5)) { context.moveTo(gutterLeft, AA(this, n)); context.lineTo(OfficeExcel.GetWidth(obj) - gutterRight, AA(this,n)); }*/ height = (OfficeExcel.GetHeight(obj) - gutterBottom - gutterTop) for (y = gutterTop; y <= height + gutterTop + 1; y+=obj._otherProps._background_grid_hsize) { if((y + obj._otherProps._background_grid_hsize) > (height + gutterTop + 1)) { y = height + gutterTop; context.moveTo(gutterLeft, AA(this, y)); context.lineTo(OfficeExcel.GetWidth(obj) - gutterRight, AA(this, y)); break; } else { context.moveTo(gutterLeft, AA(this, y)); context.lineTo(OfficeExcel.GetWidth(obj) - gutterRight, AA(this, y)); } } // } /*if (obj._otherProps._background_grid_hlines) { height = (OfficeExcel.GetHeight(obj) - gutterBottom) for (y=gutterTop; y<height; y+=obj._otherProps._background_grid_hsize) { context.moveTo(gutterLeft, AA(this, y)); context.lineTo(OfficeExcel.GetWidth(obj) - gutterRight, AA(this, y)); } }*/ } if (obj._otherProps._background_grid_vlines) { // Draw the vertical lines var width = (obj.canvas.width - gutterRight - gutterLeft) for (x=gutterLeft; x<=width + gutterLeft + 1; x+=obj._otherProps._background_grid_vsize) { if((x + obj._otherProps._background_grid_vsize) > width + gutterLeft + 1) { x = width + gutterLeft; context.moveTo(AA(this, x), gutterTop); context.lineTo(AA(this, x), obj.canvas.height - gutterBottom); context.stroke(); break; } context.moveTo(AA(this, x), gutterTop); context.lineTo(AA(this, x), obj.canvas.height - gutterBottom); context.stroke(); } } /*if (obj._otherProps._background_grid_border && obj._otherProps._background_grid_vlines) { // Make sure a rectangle, the same colour as the grid goes around the graph context.strokeStyle = obj._otherProps._background_grid_color; context.strokeRect(AA(this, gutterLeft), AA(this, gutterTop), OfficeExcel.GetWidth(obj) - gutterLeft - gutterRight, OfficeExcel.GetHeight(obj) - gutterTop - gutterBottom); }*/ context.stroke(); // If it's a bar and 3D variant, translate if (variant == '3d') { context.restore(); } // Draw the title if one is set if ( typeof(obj._chartTitle._text) == 'string') { if (obj.type == 'gantt') { gutterTop -= 10; } OfficeExcel.DrawTitle(canvas, obj._chartTitle._text, gutterTop, null, obj._chartTitle._size ? obj._chartTitle._size : obj._otherProps._text_size + 2); } context.stroke(); if(obj._otherProps._background_grid_hlines_interim) { var n = 0; context.strokeStyle = obj._otherProps._background_grid_hlines_interim_color; for (y = gutterTop; y < (height + gutterTop); y+=(obj._otherProps._background_grid_hsize/5)) { if(n%5 != 0 && n != 0) { context.moveTo(gutterLeft, AA(this, y)); context.lineTo(OfficeExcel.GetWidth(obj) - gutterRight, AA(this, y)); context.stroke(); } n++; } context.stroke(); } if(obj._otherProps._background_grid_vlines_interim) { var n = 0; context.strokeStyle = obj._otherProps._background_grid_vlines_interim_color; var width = (obj.canvas.width - gutterRight) for (x=gutterLeft; x < width + gutterLeft; x+=obj._otherProps._background_grid_vsize/2) { if(n%2 != 0 && n != 0) { context.moveTo(AA(this, x), gutterTop); context.lineTo(AA(this, x), obj.canvas.height - gutterBottom); } n++; } context.stroke(); } } } /** * Returns the day number for a particular date. Eg 1st February would be 32 * * @param object obj A date object * @return int The day number of the given date */ OfficeExcel.GetDays = function (obj) { var year = obj.getFullYear(); var days = obj.getDate(); var month = obj.getMonth(); if (month == 0) return days; if (month >= 1) days += 31; if (month >= 2) days += 28; // Leap years. Crude, but if this code is still being used // when it stops working, then you have my permission to shoot // me. Oh, you won't be able to - I'll be dead... if (year >= 2008 && year % 4 == 0) days += 1; if (month >= 3) days += 31; if (month >= 4) days += 30; if (month >= 5) days += 31; if (month >= 6) days += 30; if (month >= 7) days += 31; if (month >= 8) days += 31; if (month >= 9) days += 30; if (month >= 10) days += 31; if (month >= 11) days += 30; return days; } /** * Debug short name functions */ function pd(variable) {OfficeExcel.pr(variable);} function p(variable) {OfficeExcel.pr(variable);} function a(variable) {alert(variable);} /** * A shortcut for console.log - as used by Firebug and Chromes console */ function cl (variable) { return console.log(variable); } // Makes a clone of an array OfficeExcel.array_clone = function (obj) { if(obj == null || typeof(obj) != 'object') return obj; var temp = []; for (var i = 0;i < obj.length; ++i) { if (typeof(obj[i]) == 'number') temp[i] = (function (arg) {return Number(arg);})(obj[i]); else if (typeof(obj[i]) == 'string') temp[i] = (function (arg) {return String(arg);})(obj[i]); else if (typeof(obj[i]) == 'function') temp[i] = obj[i]; else temp[i] = OfficeExcel.array_clone(obj[i]); } return temp; } /** * This function reverses an array */ OfficeExcel.array_reverse = function (arr) { var newarr = []; for (var i=arr.length - 1; i>=0; i--) { newarr.push(arr[i]); } return newarr; } OfficeExcel.numToFormatText = function (value,format) { if(format == 'General') return value; var numFormat = oNumFormatCache.get(format); var aFormatedValue = numFormat.format(value, CellValueType.number, 15); if(aFormatedValue[0].t == '#') return ""; return aFormatedValue[0].text; } /** * Formats a number with thousand seperators so it's easier to read * * @param integer num The number to format * @param string The (optional) string to prepend to the string * @param string The (optional) string to ap * pend to the string * @return string The formatted number */ OfficeExcel.number_format = function (obj, num) { var i; var prepend = arguments[2] ? String(arguments[2]) : ''; var append = arguments[3] ? String(arguments[3]) : ''; var output = ''; var decimal = ''; var decimal_seperator = obj._otherProps._scale_point ? obj._otherProps._scale_point : '.'; var thousand_seperator = obj._otherProps._scale_thousand ? obj._otherProps._scale_thousand : ','; RegExp.$1 = ''; var i,j; if (typeof(obj._otherProps._scale_formatter) == 'function') { return obj._otherProps._scale_formatter(obj, num); } // Ignore the preformatted version of "1e-2" if (String(num).indexOf('e') > 0) { return String(prepend + String(num) + append); } // We need then number as a string num = String(num); // Take off the decimal part - we re-append it later if (num.indexOf('.') > 0) { num = num.replace(/\.(.*)/, ''); decimal = RegExp.$1; } // Thousand seperator //var seperator = arguments[1] ? String(arguments[1]) : ','; var seperator = thousand_seperator; /** * Work backwards adding the thousand seperators */ var foundPoint; for (i=(num.length - 1),j=0; i>=0; j++,i--) { var character = num.charAt(i); if ( j % 3 == 0 && j != 0) { output += seperator; } /** * Build the output */ output += character; } /** * Now need to reverse the string */ var rev = output; output = ''; for (i=(rev.length - 1); i>=0; i--) { output += rev.charAt(i); } // Tidy up //output = output.replace(/^-,/, '-'); if (output.indexOf('-' + obj._otherProps._scale_thousand) == 0) { output = '-' + output.substr(('-' + obj._otherProps._scale_thousand).length); } // Reappend the decimal if (decimal.length) { output = output + decimal_seperator + decimal; decimal = ''; RegExp.$1 = ''; } // Minor bugette if (output.charAt(0) == '-') { output = output.replace(/-/, ''); prepend = '-' + prepend; } return prepend + output + append; } /** * Draws horizontal coloured bars on something like the bar, line or scatter */ OfficeExcel.DrawBars = function (obj) { var hbars = obj._otherProps._background_hbars; /** * Draws a horizontal bar */ obj.context.beginPath(); for (i=0; i<hbars.length; ++i) { // If null is specified as the "height", set it to the upper max value if (hbars[i][1] == null) { hbars[i][1] = obj.max; // If the first index plus the second index is greater than the max value, adjust accordingly } else if (hbars[i][0] + hbars[i][1] > obj.max) { hbars[i][1] = obj.max - hbars[i][0]; } // If height is negative, and the abs() value is greater than .max, use a negative max instead if (Math.abs(hbars[i][1]) > obj.max) { hbars[i][1] = -1 * obj.max; } // If start point is greater than max, change it to max if (Math.abs(hbars[i][0]) > obj.max) { hbars[i][0] = obj.max; } // If start point plus height is less than negative max, use the negative max plus the start point if (hbars[i][0] + hbars[i][1] < (-1 * obj.max) ) { hbars[i][1] = -1 * (obj.max + hbars[i][0]); } // If the X axis is at the bottom, and a negative max is given, warn the user if (obj._otherProps._xaxispos == 'bottom' && (hbars[i][0] < 0 || (hbars[i][1] + hbars[i][1] < 0)) ) { alert('[' + obj.type.toUpperCase() + ' (ID: ' + obj.id + ') BACKGROUND HBARS] You have a negative value in one of your background hbars values, whilst the X axis is in the center'); } var ystart = (obj.grapharea - ((hbars[i][0] / obj.max) * obj.grapharea)); var height = (Math.min(hbars[i][1], obj.max - hbars[i][0]) / obj.max) * obj.grapharea; // Account for the X axis being in the center if (obj._otherProps._xaxispos == 'center') { ystart /= 2; height /= 2; } ystart += obj._chartGutter._top var x = obj._chartGutter._left; var y = ystart - height; var w = obj.canvas.width - obj._chartGutter._left - obj._chartGutter._right; var h = height; // Accommodate Opera :-/ if (navigator.userAgent.indexOf('Opera') != -1 && obj._otherProps._xaxispos == 'center' && h < 0) { h *= -1; y = y - h; } /** * Account for X axis at the top */ if (obj._otherProps._xaxispos == 'top') { y = obj.canvas.height - y; h *= -1; } obj.context.fillStyle = hbars[i][2]; obj.context.fillRect(x, y, w, h); } obj.context.fill(); } /** * Draws in-graph labels. * * @param object obj The graph object */ OfficeExcel.DrawInGraphLabels = function (obj) { var canvas = obj.canvas; var context = obj.context; var labels = obj._otherProps._labels_ingraph; var labels_processed = []; // Defaults var fgcolor = 'black'; var bgcolor = 'white'; var direction = 1; var bold = bar._otherProps._labels_above_bold; var textOptions = { color: bar._otherProps._labels_above_color, italic: bar._otherProps._labels_above_italic, underline: bar._otherProps._labels_above_underline } if (!labels) { return; } /** * Preprocess the labels array. Numbers are expanded */ for (var i=0; i<labels.length; ++i) { if (typeof(labels[i]) == 'number') { for (var j=0; j<labels[i]; ++j) { labels_processed.push(null); } } else if (typeof(labels[i]) == 'string' || typeof(labels[i]) == 'object') { labels_processed.push(labels[i]); } else { labels_processed.push(''); } } /** * Turn off any shadow */ OfficeExcel.NoShadow(obj); if (labels_processed && labels_processed.length > 0) { for (var i=0; i<labels_processed.length; ++i) { if (labels_processed[i]) { var coords = obj.coords[i]; if (coords && coords.length > 0) { var x = (obj.type == 'bar' ? coords[0] + (coords[2] / 2) : coords[0]); var y = (obj.type == 'bar' ? coords[1] + (coords[3] / 2) : coords[1]); var length = typeof(labels_processed[i][4]) == 'number' ? labels_processed[i][4] : 25; context.beginPath(); context.fillStyle = 'black'; context.strokeStyle = 'black'; if (obj.type == 'bar') { /** * X axis at the top */ if (obj._otherProps._xaxispos == 'top') { length *= -1; } if (obj._otherProps._variant == 'dot') { context.moveTo(x, obj.coords[i][1] - 5); context.lineTo(x, obj.coords[i][1] - 5 - length); var text_x = x; var text_y = obj.coords[i][1] - 5 - length; } else if (obj._otherProps._variant == 'arrow') { context.moveTo(x, obj.coords[i][1] - 5); context.lineTo(x, obj.coords[i][1] - 5 - length); var text_x = x; var text_y = obj.coords[i][1] - 5 - length; } else { context.arc(x, y, 2.5, 0, 6.28, 0); context.moveTo(x, y); context.lineTo(x, y - length); var text_x = x; var text_y = y - length; } context.stroke(); context.fill(); } else if (obj.type == 'line') { if ( typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][3]) == 'number' && labels_processed[i][3] == -1 ) { context.moveTo(x, y + 5); context.lineTo(x, y + 5 + length); context.stroke(); context.beginPath(); // This draws the arrow context.moveTo(x, y + 5); context.lineTo(x - 3, y + 10); context.lineTo(x + 3, y + 10); context.closePath(); var text_x = x; var text_y = y + 5 + length; } else { var text_x = x; var text_y = y - 5 - length; context.moveTo(x, y - 5); context.lineTo(x, y - 5 - length); context.stroke(); context.beginPath(); // This draws the arrow context.moveTo(x, y - 5); context.lineTo(x - 3, y - 10); context.lineTo(x + 3, y - 10); context.closePath(); } context.fill(); } // Taken out on the 10th Nov 2010 - unnecessary //var width = context.measureText(labels[i]).width; context.beginPath(); // Fore ground color context.fillStyle = (typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][1]) == 'string') ? labels_processed[i][1] : 'black'; OfficeExcel.Text(context, obj._otherProps._text_font, obj._otherProps._text_size, text_x, text_y, (typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][0]) == 'string') ? labels_processed[i][0] : labels_processed[i], 'bottom', 'center', true, null, (typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][2]) == 'string') ? labels_processed[i][2] : 'white', bold, null, textOptions); context.fill(); } } } } } /** * This function "fills in" key missing properties that various implementations lack * * @param object e The event object */ OfficeExcel.FixEventObject = function (e) { if (OfficeExcel.isIE8()) { var e = event; e.pageX = (event.clientX + document.body.scrollLeft); e.pageY = (event.clientY + document.body.scrollTop); e.target = event.srcElement; if (!document.body.scrollTop && document.documentElement.scrollTop) { e.pageX += parseInt(document.documentElement.scrollLeft); e.pageY += parseInt(document.documentElement.scrollTop); } } // This is mainly for FF which doesn't provide offsetX if (typeof(e.offsetX) == 'undefined' && typeof(e.offsetY) == 'undefined') { var coords = OfficeExcel.getMouseXY(e); e.offsetX = coords[0]; e.offsetY = coords[1]; } // Any browser that doesn't implement stopPropagation() (MSIE) if (!e.stopPropagation) { e.stopPropagation = function () {window.event.cancelBubble = true;} } return e; } /** * Draw crosshairs if enabled * * @param object obj The graph object (from which we can get the context and canvas as required) */ OfficeExcel.DrawCrosshairs = function (obj) { if (obj._otherProps._crosshairs) { var canvas = obj.canvas; var context = obj.context; //canvas.onmousemove = function (e) var crosshairs_mousemove = function (e) { var e = OfficeExcel.FixEventObject(e); var canvas = obj.canvas; var context = obj.context; var width = canvas.width; var height = canvas.height; var adjustments = obj._tooltip._coords_adjust; var gutterLeft = obj._chartGutter._left; var gutterRight = obj._chartGutter._right; var gutterTop = obj._chartGutter._top; var gutterBottom = obj._chartGutter._bottom; var mouseCoords = OfficeExcel.getMouseXY(e); var x = mouseCoords[0]; var y = mouseCoords[1]; if (typeof(adjustments) == 'object' && adjustments[0] && adjustments[1]) { x = x - adjustments[0]; y = y - adjustments[1]; } OfficeExcel.Clear(canvas); obj.Draw(); if ( x >= gutterLeft && y >= gutterTop && x <= (width - gutterRight) && y <= (height - gutterBottom) ) { var linewidth = obj._otherProps._crosshairs_linewidth; context.lineWidth = linewidth ? linewidth : 1; context.beginPath(); context.strokeStyle = obj._otherProps._crosshairs_color; // Draw a top vertical line if (obj._otherProps._crosshairs_vline) { context.moveTo(AA(this, x), AA(this, gutterTop)); context.lineTo(AA(this, x), AA(this, height - gutterBottom)); } // Draw a horizontal line if (obj._otherProps._crosshairs_hline) { context.moveTo(AA(this, gutterLeft), AA(this, y)); context.lineTo(AA(this, width - gutterRight), AA(this, y)); } context.stroke(); /** * Need to show the coords? */ if (obj._otherProps._crosshairs_coords) { if (obj.type == 'scatter') { var xCoord = (((x - obj._chartGutter._left) / (obj.canvas.width - gutterLeft - gutterRight)) * (obj._otherProps._xmax - obj._otherProps._xmin)) + obj._otherProps._xmin; xCoord = xCoord.toFixed(obj._otherProps._scale_decimals); var yCoord = obj.max - (((y - obj._chartGutter._top) / (obj.canvas.height - gutterTop - gutterBottom)) * obj.max); if (obj.type == 'scatter' && obj._otherProps._xaxispos == 'center') { yCoord = (yCoord - (obj.max / 2)) * 2; } yCoord = yCoord.toFixed(obj._otherProps._scale_decimals); var div = OfficeExcelExcel.Registry.Get('chart.coordinates.coords.div'); var mouseCoords = OfficeExcel.getMouseXY(e); var canvasXY = OfficeExcel.getCanvasXY(canvas); if (!div) { div = document.createElement('DIV'); div.__object__ = obj; div.style.position = 'absolute'; div.style.backgroundColor = 'white'; div.style.border = '1px solid black'; div.style.fontFamily = 'Arial, Verdana, sans-serif'; div.style.fontSize = '10pt' div.style.padding = '2px'; div.style.opacity = 1; div.style.WebkitBorderRadius = '3px'; div.style.borderRadius = '3px'; div.style.MozBorderRadius = '3px'; document.body.appendChild(div); OfficeExcel.Registry.Set('chart.coordinates.coords.div', div); } // Convert the X/Y pixel coords to correspond to the scale div.style.opacity = 1; div.style.display = 'inline'; if (!obj._otherProps._crosshairs_coords_fixed) { div.style.left = Math.max(2, (e.pageX - div.offsetWidth - 3)) + 'px'; div.style.top = Math.max(2, (e.pageY - div.offsetHeight - 3)) + 'px'; } else { div.style.left = canvasXY[0] + gutterLeft + 3 + 'px'; div.style.top = canvasXY[1] + gutterTop + 3 + 'px'; } div.innerHTML = '<span style="color: #666">' + obj._otherProps._crosshairs_coords_labels_x + ':</span> ' + xCoord + '<br><span style="color: #666">' + obj._otherProps._crosshairs_coords_labels_y + ':</span> ' + yCoord; canvas.addEventListener('mouseout', OfficeExcel.HideCrosshairCoords, false); obj.canvas.__crosshairs_labels__ = div; obj.canvas.__crosshairs_x__ = xCoord; obj.canvas.__crosshairs_y__ = yCoord; } else { alert('[OfficeExcel] Showing crosshair coordinates is only supported on the Scatter chart'); } } /** * Fire the oncrosshairs custom event */ OfficeExcel.FireCustomEvent(obj, 'oncrosshairs'); } else { OfficeExcel.HideCrosshairCoords(); } } canvas.addEventListener('mousemove', crosshairs_mousemove, false); OfficeExcel.AddEventListener(obj.id, 'mousemove', crosshairs_mousemove); } } /** * Thisz function hides the crosshairs coordinates */ OfficeExcel.HideCrosshairCoords = function () { var div = OfficeExcel.Registry.Get('chart.coordinates.coords.div'); if ( div && div.style.opacity == 1 && div.__object__._otherProps._crosshairs_coords_fadeout ) { setTimeout(function() {OfficeExcel.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.9;}, 50); setTimeout(function() {OfficeExcel.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.8;}, 100); setTimeout(function() {OfficeExcel.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.7;}, 150); setTimeout(function() {OfficeExcel.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.6;}, 200); setTimeout(function() {OfficeExcel.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.5;}, 250); setTimeout(function() {OfficeExcel.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.4;}, 300); setTimeout(function() {OfficeExcel.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.3;}, 350); setTimeout(function() {OfficeExcel.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.2;}, 400); setTimeout(function() {OfficeExcel.Registry.Get('chart.coordinates.coords.div').style.opacity = 0.1;}, 450); setTimeout(function() {OfficeExcel.Registry.Get('chart.coordinates.coords.div').style.opacity = 0;}, 500); setTimeout(function() {OfficeExcel.Registry.Get('chart.coordinates.coords.div').style.display = 'none';}, 550); } } /** * Trims the right hand side of a string. Removes SPACE, TAB * CR and LF. * * @param string str The string to trim */ OfficeExcel.rtrim = function (str) { return str.replace(/( |\n|\r|\t)+$/, ''); } /** * Draws the3D axes/background */ OfficeExcel.Draw3DAxes = function (obj) { var gutterLeft = obj._chartGutter._left; var gutterRight = obj._chartGutter._right; var gutterTop = obj._chartGutter._top; var gutterBottom = obj._chartGutter._bottom; var context = obj.context; var canvas = obj.canvas; context.strokeStyle = '#aaa'; context.fillStyle = '#ddd'; // Draw the vertical left side context.beginPath(); context.moveTo(gutterLeft, gutterTop); context.lineTo(gutterLeft + 10, gutterTop - 5); context.lineTo(gutterLeft + 10, canvas.height - gutterBottom - 5); context.lineTo(gutterLeft, canvas.height - gutterBottom); context.closePath(); context.stroke(); context.fill(); // Draw the bottom floor context.beginPath(); context.moveTo(gutterLeft, canvas.height - gutterBottom); context.lineTo(gutterLeft + 10, canvas.height - gutterBottom - 5); context.lineTo(canvas.width - gutterRight + 10, canvas.height - gutterBottom - 5); context.lineTo(canvas.width - gutterRight, canvas.height - gutterBottom); context.closePath(); context.stroke(); context.fill(); } // Turns off any shadow OfficeExcel.NoShadow = function (obj) { obj.context.shadowColor = 'rgba(0,0,0,0)'; obj.context.shadowBlur = 0; obj.context.shadowOffsetX = 0; obj.context.shadowOffsetY = 0; } /** * Sets the four shadow properties - a shortcut function * * @param object obj Your graph object * @param string color The shadow color * @param number offsetx The shadows X offset * @param number offsety The shadows Y offset * @param number blur The blurring effect applied to the shadow */ OfficeExcel.SetShadow = function (obj, color, offsetx, offsety, blur) { obj.context.shadowColor = color; obj.context.shadowOffsetX = offsetx; obj.context.shadowOffsetY = offsety; obj.context.shadowBlur = blur; } // Compatibility canvas browser OfficeExcel.CanvasBrowserCompat = function (context) { if (!context) { return; } if (!context.measureText) { // This emulates the measureText() function context.measureText = function (text) { var textObj = document.createElement('DIV'); textObj.innerHTML = text; textObj.style.backgroundColor = 'white'; textObj.style.position = 'absolute'; textObj.style.top = -100 textObj.style.left = 0; document.body.appendChild(textObj); var width = {width: textObj.offsetWidth}; textObj.style.display = 'none'; return width; } } if (!context.fillText) { // This emulates the fillText() method context.fillText = function (text, targetX, targetY) { return false; } } // If IE8, add addEventListener() if (!context.canvas.addEventListener) { window.addEventListener = function (ev, func, bubble) { return this.attachEvent('on' + ev, func); } context.canvas.addEventListener = function (ev, func, bubble) { return this.attachEvent('on' + ev, func); } } } /** * This is a function that can be used to run code asynchronously, which can * be used to speed up the loading of you pages. * * @param string func This is the code to run. It can also be a function pointer. * The front page graphs show this function in action. Basically * each graphs code is made in a function, and that function is * passed to this function to run asychronously. */ OfficeExcel.Async = function (func) { return setTimeout(func, arguments[1] ? arguments[1] : 1); } /** * A custom random number function * * @param number min The minimum that the number should be * @param number max The maximum that the number should be * @param number How many decimal places there should be. Default for this is 0 */ OfficeExcel.random = function (min, max) { var dp = arguments[2] ? arguments[2] : 0; var r = Math.random(); return Number((((max - min) * r) + min).toFixed(dp)); } OfficeExcel.degrees2Radians=function(degrees){return degrees*(PI/180);} /** * Draws a rectangle with curvy corners * * @param context object The context * @param x number The X coordinate (top left of the square) * @param y number The Y coordinate (top left of the square) * @param w number The width of the rectangle * @param h number The height of the rectangle * @param number The radius of the curved corners * @param boolean Whether the top left corner is curvy * @param boolean Whether the top right corner is curvy * @param boolean Whether the bottom right corner is curvy * @param boolean Whether the bottom left corner is curvy */ OfficeExcel.strokedCurvyRect = function (context, x, y, w, h) { // The corner radius var r = arguments[5] ? arguments[5] : 3; // The corners var corner_tl = (arguments[6] || arguments[6] == null) ? true : false; var corner_tr = (arguments[7] || arguments[7] == null) ? true : false; var corner_br = (arguments[8] || arguments[8] == null) ? true : false; var corner_bl = (arguments[9] || arguments[9] == null) ? true : false; context.beginPath(); // Top left side context.moveTo(x + (corner_tl ? r : 0), y); context.lineTo(x + w - (corner_tr ? r : 0), y); // Top right corner if (corner_tr) { context.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2, false); } // Top right side context.lineTo(x + w, y + h - (corner_br ? r : 0) ); // Bottom right corner if (corner_br) { context.arc(x + w - r, y - r + h, r, Math.PI * 2, Math.PI * 0.5, false); } // Bottom right side context.lineTo(x + (corner_bl ? r : 0), y + h); // Bottom left corner if (corner_bl) { context.arc(x + r, y - r + h, r, Math.PI * 0.5, Math.PI, false); } // Bottom left side context.lineTo(x, y + (corner_tl ? r : 0) ); // Top left corner if (corner_tl) { context.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5, false); } context.stroke(); } /** * Draws a filled rectangle with curvy corners * * @param context object The context * @param x number The X coordinate (top left of the square) * @param y number The Y coordinate (top left of the square) * @param w number The width of the rectangle * @param h number The height of the rectangle * @param number The radius of the curved corners * @param boolean Whether the top left corner is curvy * @param boolean Whether the top right corner is curvy * @param boolean Whether the bottom right corner is curvy * @param boolean Whether the bottom left corner is curvy */ OfficeExcel.filledCurvyRect = function (context, x, y, w, h) { // The corner radius var r = arguments[5] ? arguments[5] : 3; // The corners var corner_tl = (arguments[6] || arguments[6] == null) ? true : false; var corner_tr = (arguments[7] || arguments[7] == null) ? true : false; var corner_br = (arguments[8] || arguments[8] == null) ? true : false; var corner_bl = (arguments[9] || arguments[9] == null) ? true : false; context.beginPath(); // First draw the corners // Top left corner if (corner_tl) { context.moveTo(x + r, y + r); context.arc(x + r, y + r, r, Math.PI, 1.5 * Math.PI, false); } else { context.fillRect(x, y, r, r); } // Top right corner if (corner_tr) { context.moveTo(x + w - r, y + r); context.arc(x + w - r, y + r, r, 1.5 * Math.PI, 0, false); } else { context.moveTo(x + w - r, y); context.fillRect(x + w - r, y, r, r); } // Bottom right corner if (corner_br) { context.moveTo(x + w - r, y + h - r); context.arc(x + w - r, y - r + h, r, 0, Math.PI / 2, false); } else { context.moveTo(x + w - r, y + h - r); context.fillRect(x + w - r, y + h - r, r, r); } // Bottom left corner if (corner_bl) { context.moveTo(x + r, y + h - r); context.arc(x + r, y - r + h, r, Math.PI / 2, Math.PI, false); } else { context.moveTo(x, y + h - r); context.fillRect(x, y + h - r, r, r); } // Now fill it in context.fillRect(x + r, y, w - r - r, h); context.fillRect(x, y + r, r + 1, h - r - r); context.fillRect(x + w - r - 1, y + r, r + 1, h - r - r); context.fill(); } /** * A crude timing function * * @param string label The label to use for the time */ OfficeExcel.Timer = function (label) { var d = new Date(); // This uses the Firebug console console.log(label + ': ' + d.getSeconds() + '.' + d.getMilliseconds()); } /** * Hides the palette if it's visible */ OfficeExcel.HidePalette = function () { var div = OfficeExcel.Registry.Get('palette'); if (typeof(div) == 'object' && div) { div.style.visibility = 'hidden'; div.style.display = 'none'; OfficeExcel.Registry.Set('palette', null); } } /** * Hides the zoomed canvas */ OfficeExcel.HideZoomedCanvas = function () { var interval = 15; var frames = 10; if (typeof(__zoomedimage__) == 'object') { obj = __zoomedimage__.obj; } else { return; } if (obj._zoom._fade_out) { for (var i=frames,j=1; i>=0; --i, ++j) { if (typeof(__zoomedimage__) == 'object') { setTimeout("__zoomedimage__.style.opacity = " + String(i / 10), j * interval); } } if (typeof(__zoomedbackground__) == 'object') { setTimeout("__zoomedbackground__.style.opacity = " + String(i / frames), j * interval); } } if (typeof(__zoomedimage__) == 'object') { setTimeout("__zoomedimage__.style.display = 'none'", obj._zoom._fade_out ? (frames * interval) + 10 : 0); } if (typeof(__zoomedbackground__) == 'object') { setTimeout("__zoomedbackground__.style.display = 'none'", obj._zoom._fade_out ? (frames * interval) + 10 : 0); } } /** * Adds an event handler * * @param object obj The graph object * @param string event The name of the event, eg ontooltip * @param object func The callback function */ OfficeExcel.AddCustomEventListener = function (obj, name, func) { if (typeof(OfficeExcel.events[obj.id]) == 'undefined') { OfficeExcel.events[obj.id] = []; } OfficeExcel.events[obj.id].push([obj, name, func]); return OfficeExcel.events[obj.id].length - 1; } // Fire events OfficeExcel.FireCustomEvent = function (obj, name) { if (obj && obj.isOfficeExcel) { var id = obj.id; if ( typeof(id) == 'string' && typeof(OfficeExcel.events) == 'object' && typeof(OfficeExcel.events[id]) == 'object' && OfficeExcel.events[id].length > 0) { for(var j=0; j<OfficeExcel.events[id].length; ++j) { if (OfficeExcel.events[id][j] && OfficeExcel.events[id][j][1] == name) { OfficeExcel.events[id][j][2](obj); } } } } } // Checks the browser for traces of MSIE8 OfficeExcel.isIE8 = function () { return navigator.userAgent.indexOf('MSIE 8') > 0; } // Checks the browser for traces of MSIE7 OfficeExcel.isIE7 = function () { return navigator.userAgent.indexOf('MSIE 7') > 0; } // Checks the browser for traces of MSIE9 OfficeExcel.isIE9 = function () { return navigator.userAgent.indexOf('MSIE 9') > 0; } // Checks the browser for traces of MSIE9 OfficeExcel.isOld = function () { return OfficeExcel.isIE7() || OfficeExcel.isIE8(); } // Checks the browser for traces of MSIE9 OfficeExcel.isIE9up = function () { navigator.userAgent.match(/MSIE (\d+)/); return Number(RegExp.$1) >= 9; } //Clear all Listeners OfficeExcel.ClearEventListeners = function (id) { for (var i = 0; i < OfficeExcel.Registry.Get('chart.event.handlers').length; ++i) { var el = OfficeExcel.Registry.Get('chart.event.handlers')[i]; if (el && (el[0] == id || el[0] == ('window_' + id))) { if (el[0].substring(0, 7) == 'window_') window.removeEventListener(el[1], el[2], false); else { if (document.getElementById(id)) { document.getElementById(id).removeEventListener(el[1], el[2], false); } } OfficeExcel.Registry.Get('chart.event.handlers')[i] = null; } } } /** * */ OfficeExcel.AddEventListener = function (id, e, func) { var type = arguments[3] ? arguments[3] : 'unknown'; OfficeExcel.Registry.Get('chart.event.handlers').push([id, e, func, type]); } /** * This function suggests a gutter size based on the widest left label. Given that the bottom * labels may be longer, this may be a little out. * * @param object obj The graph object * @param array data An array of graph data * @return int A suggested gutter setting */ OfficeExcel.getGutterSuggest = function (obj, data) { var str = OfficeExcel.number_format(obj, OfficeExcel.array_max(OfficeExcel.getScale(OfficeExcel.array_max(data), obj)), obj._otherProps._units_pre, obj._otherProps._units_post); // Take into account the HBar if (obj.type == 'hbar') { var str = ''; var len = 0; for (var i=0; i<obj._otherProps._labels.length; ++i) { str = (obj._otherProps._labels.length > str.length ? obj._otherProps._labels[i] : str); } } obj.context.font = obj._otherProps._text_size + 'pt ' + obj._otherProps._text_font; len = obj.context.measureText(str).width + 5; return (obj.type == 'hbar' ? len / 3 : len); } /** * A basic Array shift gunction * * @param object The numerical array to work on * @return The new array */ OfficeExcel.array_shift = function (arr) { var ret = []; for (var i=1; i<arr.length; ++i) ret.push(arr[i]); return ret; } /** * If you prefer, you can use the SetConfig() method to set the configuration information * for your chart. You may find that setting the configuration this way eases reuse. * * @param object obj The graph object * @param object config The graph configuration information */ OfficeExcel.SetConfig = function (obj, c) { for (i in c) { if (typeof(i) == 'string') { obj.Set(i, c[i]); } } return obj; } /** * These are older functions that were used before the move to seperate gutter settings */ OfficeExcel.GetHeight=function(obj){return obj.canvas.height;} OfficeExcel.GetWidth=function(obj){return obj.canvas.width;} /** * Clears all the custom event listeners that have been registered * * @param string Limits the clearing to this object ID */ OfficeExcel.RemoveAllCustomEventListeners = function () { var id = arguments[0]; if (id && OfficeExcel.events[id]) { OfficeExcel.events[id] = []; } else { OfficeExcel.events = []; } } /** * Clears a particular custom event listener * * @param object obj The graph object * @param number i This is the index that is return by .AddCustomEventListener() */ OfficeExcel.RemoveCustomEventListener = function (obj, i) { if ( typeof(OfficeExcel.events) == 'object' && typeof(OfficeExcel.events[obj.id]) == 'object' && typeof(OfficeExcel.events[obj.id][i]) == 'object') { OfficeExcel.events[obj.id][i] = null; } } OfficeExcel.DrawBackgroundImage1 = function (obj) { var img = new Image(); img.__object__ = obj; img.__canvas__ = obj.canvas; img.__context__ = obj.context; img.src = obj._otherProps._background_image; img.onload = function () { var obj = this.__object__; obj.context.drawImage(this, 0, 0, obj.canvas.width, obj.canvas.height); obj.__background_image__ = true; obj.Draw(); } } // Draw the background OfficeExcel.DrawBackgroundImage = function (obj) { var img = new Image(); img.__object__ = obj; img.__canvas__ = obj.canvas; img.__context__ = obj.context; img.src = obj._otherProps._background_image; obj.__background_image__ = img; img.onload = function () { var obj = this.__object__; var gutterLeft = obj._chartGutter._left; var gutterRight = obj._chartGutter._right; var gutterTop = obj._chartGutter._top; var gutterBottom = obj._chartGutter._bottom; var stretch = obj._otherProps._background_image_stretch; var align = obj._otherProps._background_image_align; var x; var y; if (typeof(align) == 'string') { if (align.indexOf('right') != -1) x = obj.canvas.width - this.width - gutterRight; else x = gutterLeft; if (align.indexOf('bottom') != -1) y = obj.canvas.height - this.height - gutterBottom; else y = gutterTop; } else { x = gutterLeft; y = gutterTop; } // X/Y coords take precedence over the align x = typeof(obj._otherProps._background_image_x) == 'number' ? obj._otherProps._background_image_x : x; y = typeof(obj._otherProps._background_image_y) == 'number' ? obj._otherProps._background_image_y : y; var w = stretch ? obj.canvas.width - gutterLeft - gutterRight : this.width; var h = stretch ? obj.canvas.height - gutterTop - gutterBottom : this.height; OfficeExcel.Clear(obj.canvas); obj.context.drawImage(this, x, y, w, h); // Draw the graph obj.Draw(); } img.onerror = function () { var obj = this.__canvas__.__object__; // Show an error alert alert('[ERROR] There was an error with the background image that you specified: ' + img.src); // Draw the graph, because the onload doesn't fire obj.Draw(); } } /** * This resets the canvas. Keep in mind that any translate() that has been performed will also be reset. * * @param object canvas The canvas */ OfficeExcel.Reset=function(canvas){canvas.width = canvas.width;} /** * This function skirts the annoying canvas anti-aliasing * * @param object obj The object * @param number value The number to round */ function AA (obj, value) { var value = String(value).replace(/^(\d+)\.\d+/, '$1'); var newvalue = Number(value) + 0.5; return (newvalue - value) >= 0 ? newvalue : Math.floor(value); } OfficeExcel.InstallUserClickListener = function (obj, func) { if (typeof(func) == 'function') { function UserClickListener (e) { var obj = e.target.__object__; var shape = obj.getShape(e); if (shape) { func(e, shape); } } obj.canvas.addEventListener('click', UserClickListener, false); OfficeExcel.AddEventListener(obj.id, 'click', UserClickListener); } } OfficeExcel.InstallUserMousemoveListener = function (obj, func) { if (typeof(func) == 'function') { function UserMousemoveHandler (e) { var obj = e.target.__object__; var shape = obj.getShape(e); /** * This bit saves the current pointer style if there isn't one already saved */ if (shape && typeof(func) == 'function') { if (obj._otherProps._events_mousemove_revertto == null) { obj._otherProps._events_mousemove_revertto = e.target.style.cursor; } func(e, shape) } else if (typeof(obj._otherProps._events_mousemove_revertto) == 'string') { e.target.style.cursor = obj._otherProps._events_mousemove_revertto; obj._otherProps._events_mousemove_revertto = null; } } obj.canvas.addEventListener('mousemove', UserMousemoveHandler, false); OfficeExcel.AddEventListener(obj.id, 'mousemove', UserMousemoveHandler); } }