/app/scripts/components/VizabiPrototype.js
https://gitlab.com/Webxity/vizabi-prototypes · JavaScript · 370 lines · 273 code · 61 blank · 36 comment · 36 complexity · eec09407095d13340f1ef7aeffa7e9f6 MD5 · raw file
- (function(window, document) {'use strict';
- var noop = angular.noop;
- var tools = [
- 'bar-chart',
- 'bubble-chart',
- 'line-chart'
- ];
- var toolsObject = {
- 'bar-chart': 'BarChart',
- 'bubble-chart': 'BubbleChart',
- 'line-chart': 'LineChart'
- };
- /**
- * Tool decider
- * @param tool {String}
- * @exception error
- */
- var tool = function(tool) {
- if (tool) {
- if (tools.indexOf(tool) === -1) {
- error('No built-in tool provider found.');
- }
- return tool;
- }
- };
- /**
- * Throw error
- * @param msg {String}
- */
- var error = function(msg) {
- var err = new Error(msg);
- return err.stack;
- };
- /**
- * Safe function execution
- * @param fn {Function}
- */
- var safeExec = function(fn) {
- fn = fn || function() {};
- try {
- fn()
- } catch (e) {
- throw error(e);
- }
- };
- /**
- * Todo: Optimize and make it work
- * Create custom events
- * @param e {Object}
- * @param data {Object}
- * @returns {CustomEvent|Boolean}
- */
- var createEvent = function(e, data) {
- if (!angular.isObject(e) || !angular.isObject(data)) {
- return false;
- }
- window.addEventListener(e.name, function(e) { console.log(e.detail) });
- e.event = new CustomEvent(e.name, {
- detail: data
- });
- window.dispatchEvent(e.event);
- };
- var switchResponsiveDevices = function() {
- document.querySelector('#resize-portrait').addEventListener(
- 'click',
- function() {
- this.setScreenSize(this.PORTRAIT);
- }.bind(this));
- document.querySelector('#resize-landscape').addEventListener(
- 'click',
- function() {
- this.setScreenSize(this.LANDSCAPE)
- }.bind(this));
- document.querySelector('#resize-full').addEventListener(
- 'click',
- function() {
- this.setScreenSize(this.FULL);
- }.bind(this));
- document.querySelector('#enter-fullscreen').addEventListener(
- 'click',
- function() {
- if (!stageEl) {
- error('Stage is not yet drawn');
- }
- this.settings.fullscreen = true;
- this.setScreenSize(this.FULL);
- if (this.settings.fullscreen === true) {
- if (stageEl.requestFullscreen) {
- stageEl.requestFullscreen();
- } else if (stageEl.msRequestFullscreen) {
- stageEl.msRequestFullscreen();
- } else if (stageEl.mozRequestFullScreen) {
- stageEl.mozRequestFullScreen();
- } else if (stageEl.webkitRequestFullscreen) {
- stageEl.webkitRequestFullscreen();
- }
- }
- }.bind(this));
- var langEl = document.querySelector('#change-lang');
- langEl.addEventListener(
- 'click',
- function() {
- var title = langEl.getAttribute('data-original-title');
- var langIndex = this.langs.indexOf(title.toLowerCase());
- if (langIndex !== -1) {
- this.lang = (this.lang === 'pt') ? 'en' : 'pt';
- langEl.setAttribute(
- 'data-original-title',
- this.langs[langIndex].toUpperCase()
- );
- this.visualize();
- }
- }.bind(this));
- };
- var listenWindowResize = function() {
- window.addEventListener('resize', function(e) {
- if (this.screenType === this.PORTRAIT
- || this.screenType === this.LANDSCAPE) {
- return false;
- }
- // Todo: Uncomment when fix
- //this.newEvent(this.eventTypes.RESIZE, e);
- var fullScreen = document.mozFullscreenElement
- || document.webkitFullscreenElement
- || document.msFullscreenElement
- || document.fullscreenElement;
- if (!fullScreen) {
- this.settings.fullscreen = false;
- }
- this.setScreenSize(this.FULL);
- }.bind(this));
- };
- // Private var for short instance
- var VP;
- var htmlID;
- var containerID;
- var containerEl;
- var stageID;
- var stageEl;
- /**
- * VizabiPrototype constructor object
- * @param tool {String} bar-chart/bubble-chart/line-chart
- * @param id {String} html id attribute
- * @param options {Object}
- * @constructor
- */
- window.VizabiPrototype = VP = function VizabiPrototype(tool, id, options) {
- this.PORTRAIT = 'portrait';
- this.LANDSCAPE = 'landscape';
- this.FULL = 'full';
- this.tool = tool;
- this.htmlID = htmlID = id;
- this.sliderID = '#slider';
- this.optionsID = '#options';
- this.options = options;
- this.stateObj = {};
- this.screenType = 'portrait';
- this.screenSize = this.screenSizes.portrait;
- this.lang = options.language.id || 'en';
- this.langs = ['en', 'pt'];
- var eventPrefix = 'vp:';
- this.events = {
- RESIZE: []
- };
- this.eventTypes = {
- RESIZE: {
- name: eventPrefix + 'resize',
- event: noop
- }
- };
- switchResponsiveDevices.call(this);
- listenWindowResize.call(this);
- this.visualize();
- };
- VP.prototype.render = function() {
- tool(this.tool);
- //Todo: Find a proper place for this code to execute. Reason is because of Async call by Ajax causes delay in constructor.
- this.containerID = containerID = '#vp-bar-main';
- this.stageID = stageID = 'div#vp-bar-stage';
- this.containerEl = containerEl = document.querySelector(containerID);
- this.stageEl = stageEl = document.querySelector(stageID);
- this.stageEl.style.width = this.screenSize.width + 'px';
- this.stageEl.style.height = this.screenSize.height + 'px';
- this[toolsObject[this.tool]]();
- /*safeExec(function() {
- ;
- }.bind(this));*/
- return this;
- };
- VP.prototype.newEvent = function(name, data) {
- createEvent.apply(null, arguments);
- };
- VP.prototype.visualize = function() {
- async.waterfall([
- function(fn) {
- this.queryData(fn);
- }.bind(this),
- function(data, fn) {
- this.dataset = data;
- fn(null);
- }.bind(this)
- ], function(err) {
- if (err) {
- return error(err);
- }
- this.render();
- }.bind(this));
- return this;
- };
- VP.prototype.queryData = function(fn) {
- var options = this.options;
- var path = 'data/' + this.tool + '/query-en.json';
- var lang = this.lang;
- if (options.data.reader !== 'local-json') {
- // remote server
- } else {
- path = options.data.path;
- var ext = '-'+lang+'.json';
- if (path.indexOf(ext) !== -1) {
- path = path.replace(ext, '');
- }
- path = 'data/' + this.tool + '/' + path + ext;
- }
- d3.json(path, function(error, json) {
- if (error) return console.warn(error);
- fn.apply(null, arguments);
- }.bind(this));
- };
- VP.prototype.destroy = function() {
- var svgNode = document.querySelector(this.htmlID);
- var sliderNode = document.querySelector(this.sliderID);
- while (svgNode && svgNode.hasChildNodes()) {
- svgNode.removeChild(svgNode.lastChild);
- }
- while (sliderNode && sliderNode.hasChildNodes()) {
- sliderNode.removeChild(sliderNode.lastChild);
- }
- return this;
- };
- VP.prototype.reRender = function() {
- return this.destroy().render();
- };
- //Changes the OPTIONS sent to constructor obtained from textArea.
- VP.prototype.stateChanger = function (defaultObj){
- if (JSON.parse(document.getElementById("stateText").value != '')){
- try{
- this.stateObj = JSON.parse(document.getElementById("stateText").value);
- this.options = this.stateObj;
- this.reRender();
- }
- catch(e)
- {
- alert('Please Enter Valid JSON: ' + e);
- }
- }
- else{
- alert('No input detected, using default options');
- this.options = defaultObj;
- this.reRender();
- }
- };
- VP.prototype.dataset = [];
- VP.prototype.settings = {
- fullscreen: false
- };
- VP.prototype.screenSizes = {
- portrait: {
- width: 320,
- height: 512
- },
- landscape: {
- width: 568,
- height: 320
- },
- full: {}
- };
- Object.defineProperty(VP.prototype.screenSizes.full, 'width', {
- get: function() {
- var width = containerEl.offsetWidth;
- if (VP.prototype.settings.fullscreen === true) {
- width -= 70;
- }
- return width;
- },
- set: function(v) {
- return v;
- }
- });
- Object.defineProperty(VP.prototype.screenSizes.full, 'height', {
- get: function() {
- var c = VP.prototype.settings.fullscreen === true ? stageEl : containerEl;
- return c.offsetHeight - 110;
- },
- set: function(v) {
- return v;
- }
- });
- VP.prototype.setScreenSize = function(type) {
- var size = this.screenSizes[this.PORTRAIT];
- if (type && this.screenSizes[type]) {
- size = this.screenSizes[type];
- }
- this.screenSize = size;
- this.screenType = type;
- stageEl.style.width = size.width + 'px';
- stageEl.style.height = size.height + 'px';
- this.reRender();
- };
- })(window, document);