{"id":22678405,"url":"https://github.com/web2solutions/dhxmvp","last_synced_at":"2025-08-23T15:36:49.288Z","repository":{"id":68665153,"uuid":"63973559","full_name":"web2solutions/dhxMVP","owner":"web2solutions","description":"A complete boilerplate for building offline first MVP Single Page Applications leveraging DHTMLX","archived":false,"fork":false,"pushed_at":"2024-01-24T00:18:57.000Z","size":308950,"stargazers_count":7,"open_issues_count":0,"forks_count":2,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-08-09T04:36:46.380Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://web2solutions.github.io/dhxMVP","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/web2solutions.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-07-22T18:06:37.000Z","updated_at":"2024-01-23T22:51:47.000Z","dependencies_parsed_at":"2025-04-12T14:51:28.309Z","dependency_job_id":null,"html_url":"https://github.com/web2solutions/dhxMVP","commit_stats":{"total_commits":175,"total_committers":3,"mean_commits":"58.333333333333336","dds":0.28,"last_synced_commit":"67e7e9f4dd97d54018067d2ba205e3e5a36509ea"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/web2solutions/dhxMVP","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/web2solutions%2FdhxMVP","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/web2solutions%2FdhxMVP/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/web2solutions%2FdhxMVP/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/web2solutions%2FdhxMVP/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/web2solutions","download_url":"https://codeload.github.com/web2solutions/dhxMVP/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/web2solutions%2FdhxMVP/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271754863,"owners_count":24815304,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-23T02:00:09.327Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-09T18:15:09.531Z","updated_at":"2025-08-23T15:36:49.255Z","avatar_url":"https://github.com/web2solutions.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dhxMVP  \n\n[![NPM version](https://badge.fury.io/js/dhxmvp.png)](http://badge.fury.io/js/dhxmvp) [![Build Status](https://travis-ci.org/web2solutions/dhxMVP.svg?branch=master)](https://travis-ci.org/web2solutions/dhxMVP) ![Dependency Status](https://gemnasium.com/web2solutions/dhxMVP.png) [![License GPL-2.0](http://b.repl.ca/v1/License-GPL--2.0-brightgreen.png)](https://github.com/web2solutions/dhxMVP/blob/master/LICENSE) [![Join the chat at https://gitter.im/web2solutions/public](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/web2solutions/public?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\n[![NPM](https://nodei.co/npm/dhxmvp.png?compact=true)](https://nodei.co/npm/dhxmvp/)\n\n\n\ndhxMVP is a boilerplate system for building online, [offline](https://www.w3.org/TR/offline-webapps/) and [syncable](https://developer.mozilla.org/en-US/Apps/Fundamentals/Offline) Javascript [MVP](https://pt.wikipedia.org/wiki/Model-view-presenter) [Single Page Applications](https://en.wikipedia.org/wiki/Single-page_application) using [DHTMLX](http://dhtmlx.com/).\n\nDemo app:\n\n[https://web2solutions.github.io/dhxMVP](https://web2solutions.github.io/dhxMVP)\n\n\n- [Why another MV* implementation](#why-another-mv-implementation)\n- [Kit installation](#kit-installation)\n- [What the boilerplate provides?](#what-the-boilerplate-provides)\n- [Boilerplate architecture](#boilerplate-architecture)\n- [How to use the boilerplate to get my application done?](#how-to-use-the-boilerplate-to-get-my-application-done)\n    - [Setup development environment](#setup-development-environment)\n    - [The `application` html](#the-application-html)\n    - [The `application` script](#the-application-script)\n    - [The application `main` View](#the-application-main-view)\n    - [The application `main` Presenter](#the-application-main-presenter)\n    - [The application Model](#the-application-model)\n    - [Declaring routes](#declaring-routes)\n        - [Child Views](#child-views)\n        - [Child Presenters](#child-presenters)\n    - [Software validation and code automation](#software-validation-and-code-automation)\n        - [Code quality](#code-quality)\n            - [Run JSHint to check the code and look for error and bad pratices](#run-jshint-to-check-the-code-and-look-for-error-and-bad-pratices)\n        - [Unit Tests](#unit-tests)\n        - [Deploy](#deploy)\n            - [Creating minified version of the application javascript files](#creating-minified-version-of-the-application-javascript-files)\n            - [Build a distribution](#build-a-distribution)\n        - [Application distributing](#application-distributing)\n            - [Creating Mac installers](#creating-mac-installers)\n            - [Creating Windows installers](#creating-windows-installers)\n            - [Creating Linux installers](#creating-linux-installers)\n            - [Creating a Google Chrome Application](#creating-a-google-chrome-application)\n            - [Creating a Google Chrome Extension](#creating-a-google-chrome-extension)\n    - [Move to production](#move-to-production)\n\n- [License](#license)\n\n\n***Some print screens***\n\n[![print screen 1](http://i.imgur.com/oAHO2km.png)](http://i.imgur.com/oAHO2km.png)\n[![print screen 2](http://i.imgur.com/0P73aMq.png)](http://i.imgur.com/0P73aMq.png)\n[![print screen 3](http://i.imgur.com/ZsAIElz.png)](http://i.imgur.com/ZsAIElz.png)\n\n\n## Why another MV* implementation?\n\nThe [DHTMLX framework](http://www.dhtmlx.com), the main actor on the UI side of this project, does not implement any MV* model to create applications, or even implement any complex design pattern in their component calls. \n\nRather than the facade pattern used in several frameworks to init components, generally, DHTMLX pragmatically set up components `line by line`, by explicit calling component methods and passing the proper arguments on each call. That is their `default model`. Of course it also let you to set up your component using facade.\n\nIt makes DHTMLX simple and powerful. It let starters javascript programmers to build Enterprise Javascript applications.\n\nAnother reason is, actually there is no MV* framework or library which let you to build MV* aplications focused in DHTMLX components and `using the same paradigm`, or even similar in the way they were created. \n\nDHTMLX fits to a paradigm that is very similar to other frameworks like EXT JS (Senha actually), Dojo, Qooxdoo and others in term of how to implement applications using the `Component Driven Developmemnt` approach.\n\nFrameworks like DHTMLX provides mature and tested components API, rather the model where you create your own components.\n\nThere is no problem with the paradigm where you create your own components, it can be great for small applications or when you have sufficient time to start from the scratch to create components mature like the components which already exists in frameworks for Enterprise applications.\n\nFrameworks like Angular, React an others, render `views` by using `predefined` or `declarative` plain HTML templates.\n\nFrameworks like DHTMLX provides `built in` components where you can consume it APIs. The HTML, by itself, is generated in runtime, when the code which call the components is executed.\n\nFrameworks for Enterprise Applications keep the developer focus on the business logic, avoiding time wasting to create HTML, CSS, Cross Browser hacks and several other problems which already are solved by those solutions.\n\nYou may be wondering: \"What about concepts like `reaction` and data binding?\"\n\nDon't worry. Take a deep look into [DHTMLX documentation](http://docs.dhtmlx.com/datastore__index.html) and you will see those concepts are nothing new.\n\nFramerworks for Enterprise Javascript Applications are the first citizens of the `Javascript Development World`.\n\nThere is nothing you `can not do` with those frameworks, certainly they may not be the best choice for a small POC or small application, but they are the best choice in several scenarios which I will not discuss here.\n\nAs DHTMLX offers rich components through simple interfaces (API) with a great docs, it may be a right choice for small application too. Not only for Enterprise applications.\n\nAlthough, generally, a Enterprise application has it code increasing on it lifetime, resulting in a big codebase. In this scenario, you may see a lack in DHTMLX that is it does not encourage any pattern for development. Requiring from the developers to create their own application foundation.\n\nAnother common problems are:\n\n- Giant Javascript modules/classes\n\n    Are harder to maintain and get new people envolved on it development\n\n- `Load the whole app in just one file` methodology\n\n    Encouraged in top most several modern frameworks may not work for Enterprise applications, where you may have ` 2, 3, 4, 5 or even more` MB loading at the same time before application starts.\n\n- Keep clients data in sync and in realtime\n    \n    The succes of a online SPA directly rely on how and when data are displayed on the view\n\nThe dhxMVP boilerplate solves all those problems by using `dhx.ui.mvp`, a MVP framework.\n\n\n`dhx.ui.mvp` let you to declare your routes and it will call it proper `presenter` and `view` associated to it, automatically creating references to the model on each `child presenter`.\n\nFor each route, you declare (will use route as file name if not declared) a `view` and a `presenter`, but not least, you may also to attach any javascript file to the view scope.\n\nIn the view, you basically declare DHTMLX component settings and it calls.\n\nIn the presenter, you orchestrate your view, meanwhile you may implement and provide any required helper method.\n\nModels are `decoupled`, `completely independent` and `framework agnostic` Javascript Objects. Models are bound to the dhxMVP application through a `Engine\\Data Driver`.\n\n`Engines` or `Data Drivers`, are JavaScript Modules which defines certain logic of how about data is accessed, manipuled and stored.\n\nTo solve the problems regarding loading performance, `dhx.ui.mvp` implements a `on demand loading` model for loading your javascript views and presenters, let the end user to load it on their browsers only when they really need that file on their cache.\n\n\n\n\n\n## Kit installation\n\nList of the softwares you need to have installed in your computer to use the whole features of the development kit.\n\n - [Node.js](https://nodejs.org/en/download/)\n - [Gulp](https://github.com/gulpjs/gulp/blob/master/docs/getting-started.md)\n - [Git](https://desktop.github.com/) - `I'm using github`\n\nInstall process:\n\n### Via Github repo\n\nClone this repository to a given directory, lets assume: ***/Users/YourName/apps/***\n\n    $ cd /Users/YourName/apps/\n    $ git clone https://github.com/web2solutions/dhxMVP.git\n\nOr Download this repository as zip and uncompress it at /Users/YourName/apps/\n\n    $ cd dhxMVP\n    $ npm install --global gulp-cli\n    $ npm install\n\n\n\n\n\n## Boilerplate architecture\n\n\n***The File system for a properly fresh install version of dhxMVP should be something like:***\n\n    apps/\n    |---- dhxMVP/\n        |---- assets/\n        |---- cache/ -\u003e automatically created when creating Application installers\n        |---- coverage/ -\u003e Instabul coverage files\n        |---- deps/\n            |---- dhx\n            |---- thirdparty\n        |---- dist/ -\u003e automatically created when running $ gulp dist\n        |---- dist_chrome_app/ -\u003e automatically created when running $ gulp dist\n        |---- dist_chrome_extension/ -\u003e automatically created when running $ gulp dist\n        |---- dist_electron/ -\u003e automatically created when running `$ gulp dist`\n        |---- installers/ -\u003e automatically created when creating Application installers\n        |---- lib/\n            |---- model\n                |---- collections\n                    |---- questions.js\n                    |---- users.js\n                |---- engines\n                    |---- backboneIDB.js\n                |---- models\n                    |---- question.js\n                    |---- user.js\n            |---- presenter\n                |---- presenter.js\n            |---- view\n                |---- view.js\n        |---- node_modules/ -\u003e automatically created when installing the Boilerplate system\n        |---- test/\n        |---- .gitignore\n        |---- .travis.yml\n        |---- boilerplate_sidebar.html\n        |---- boilerplate_sidebar_chrome.html\n        |---- electron.js\n        |---- google_app_backgound.js\n        |---- google_app_manifest.json\n        |---- google_extension_manifest.json\n        |---- Gulpfile.js\n        |---- LICENSE\n        |---- package.json\n        |---- Readme.md\n\n\n\n## What the boilerplate provides?\n\nThis boilerplate provides:\n\n1. features to build full featured offline applications with powerful local database using [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API). \n\n2. features to build full featured syncable applications using a Message Mediator working over a `remote` provider.\n    [PubNub](https://www.pubnub.com/) is the first built in remote provider.\n\n\nFor future releases, this boilerplate will also provides a complete REST back end to be consumed by your client side application, in this way, letting you to build offline, online and syncable applications.\n\nThe currently implemented features are:\n\n- Foundation for Single Page Applications\n    - Application script\n    - Main View\n        - Initially Using DHTMLX Sidebar as application `wrapper and navigation`\n    - Main Presenter\n    - Demo Model\n        - Initially using [Backbone.js](http://backbonejs.org/) and [indexeddb-backbonejs-adapter](https://github.com/superfeedr/indexeddb-backbonejs-adapter)\n    - Demo routes\n        - #\n            - Main view\n            - Main presente\n        - /help\n            - view\n            - presenter\n    - Online Data sync\n\n- Code Validation and Automation Suite\n - gulp jshint - Run jsHint against application code\n - gulp dist \n    - Run jshint (_The dist will not be executed if is there any programmimng error reported by jshint_)\n    - Create minified version of the JavaScript files used by the application\n    - Create distributable web version\n    - Create distributable Google Chrome application version\n    - Create distributable Google Chrome extension version\n    - Create distributable Electron version\n\n - gulp test - Unit Tests\n - gulp git-init - init git on the repository\n - gulp git-add - prepare staged content to the next commit\n - sudo gulp git-add-commit-push - prepare staged content, commit and push to the repository\n - gulp git-push - push commit from Origin to Master branch\n - sudo gulp build - Build distribution. Performs several tasks over the code. If any task breaks, the upcoming task will not be executed. The tasks order is:\n    - dist\n    - test\n    - git-add-commit-push\n - gulp build-installer-mac - generate a Mac installer of the current build.\n - gulp build-installer-windows - generate a Windows installer of the current build.\n - gulp build-installer-linux - generate a Linux installer of the current build.\n\n\n\n***Note about `git` features:***\n\nYou will need `GIT LFS` to push large files to the repository.\nPlease install it. Check the doc at [Git-LFS repo at Github](https://github.com/github/git-lfs)\n\n\n\n\n\n## How to use the boilerplate to get my application done?\n\n\n### Setup development environment\n\n1. ***Give a name to your application.***\n\nOpen the file `./package.json` and alter the the following properties. \n\nExample:\n\n````javascript\n{\n  \"name\": \"MyApplicationName\",\n  \"version\": \"0.0.0\",\n  \"description\": \"Provide a description here.\",\n  \"keywords\": [\n    \"Your Keyword 1\"\n  ],\n  \"author\": {\n    \"name\": \"Your Name\",\n    \"email\": \"Your E-mail\"\n  }\n}\n````\n\n***_Note:_*** \n\nThe `version property` shall to be set to `0.0.0`. On every time you make a distribution of your application by running `gulp build`, the application version will be automatically incremented.\n\n\n\n\n2. ***Rename the Application directory***\n\nThe currently directory name is `dhxMVP`. Change it by providing your application name.\n\nFor example\n\n`dhxMVP/` ***--\u003e*** `MyApplicationName/`\n\n\n\n\n3. ***Start the development server***:\n\n    $ cd MyApplicationName/\n    $ gulp start-development-server\n\nNow open your browser and reach [http://localhost:9999/boilerplate_sidebar.html](http://localhost:9999/boilerplate_sidebar.html)\n\n***Note about _boilerplate_sidebar.html_***\n\nThis is the demo html file which uses DHTMLX Sidebar as the main `Application wrapper and navigation component`.\n\n_On a future version I will release a new demo example using `DHTMLX Layout` and `DHTMLX Toolbar` as the main `Application wrapper and navigation components`_\n\n\n\n\n4. ***Set up a new project on your prefered HTML5 and Javascript IDE***: \n\nI'm using [Sublime Text](https://www.sublimetext.com/) here and it provides a excellent plugin to run `gulp` directly from the IDE rather than requiring from you to run the `gulp commands` via `terminal`. Atom is a excellent choice too.\n\n\n\n\n\n5. ***Setup a new git repository for your application.***\n\nOn this step you will need a github account and it client installed locally.\n\nYou may use the Github client to setup the new repository.\n\nOr you may prefer to use `gulp` to init it:\n\n    $ cd MyApplicationName/\n    $ gulp git-init\n\n\n\n\n## The `application` html\n\nThe HTML code wich is reponsible for loading your dhxMVP application should looks like the following code:\n\n\n````html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003cmeta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\"\u003e\n    \u003ctitle\u003eMVP DHTMLX Demo app\u003c/title\u003e\n    \u003clink rel=\"icon\" href=\"assets/images/favicon.ico\"\u003e\n    \u003c!-- deps --\u003e\n    \u003cscript src='deps/dhx/min.shim.js'\u003e\u003c/script\u003e\n    \u003cscript src='deps/dhx/min.dhx.js'\u003e\u003c/script\u003e\n    \u003cscript src='deps/dhx/dhx.ui.mvp.js'\u003e\u003c/script\u003e\n    \u003c!-- app --\u003e\n    \u003clink rel=\"stylesheet\" type=\"text/css\" href=\"assets/css/app.css\"\u003e\n    \u003cscript src='boilerplate_sidebar.js'\u003e\u003c/script\u003e\n    \u003c!-- app --\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n````\n\n\n## The `application` script\n\nThe `application script` is the start point of you dhxMVP application. On that, you will declare your application and routes.\n\n\n````javascript\ndocument.addEventListener('DOMContentLoaded', function() {\n\n    //$dhx.environment = \"production\";\n\n    var dhx_application = $dhx.ui.mvp.application.extend({\n        initialize: function(options) {\n            //$dhx.debug.log('called initialize from factory');\n            //$dhx.debug.log('app initialized from ' + options.from );\n        }\n    }),\n        dhx_router = $dhx.ui.mvp.router.extend({ }),\n        router = new dhx_router({});\n\n    // lets use the events\n    dhx_application.on('before:start', function(options) {\n        console.log('fired app.onBeforeStart event 1');\n\n        //$dhx.debug.log('options ', options);\n        return true; // cancelable\n    });\n\n\n    dhx_application.on('start', function(options) {\n        console.log('fired app.onStart event');\n        //$dhx.debug.log('options ', options);\n    });\n\n    dhx_application.on('render', function(options) {\n        console.log('fired app.onRender event');\n        //app.main_view.dispatch( '/help' );\n        //$dhx.debug.log('options ', options);\n    });\n\n    // instantiate $dhx MVP application and router\n    var app = new dhx_application({\n            appId: \"MV* DHTMLX Demo app\",\n            container: document.body,\n            root: '',\n            //icons_path: '../assets/icons/64/', // not mandatory, default root + 'assets/icons/64/'\n            //deps_path: '../deps/', // not mandatory, default root + 'deps/'\n            //lib_path: '../lib/', // not mandatory, default root + 'lib/'\n            model:{\n                engine: 'backboneIDB',\n                models: [\n                    \"user\",\n                    \"question\",\n                    \"pet\"\n                ],\n                collections: [\n                    \"users\",\n                    \"questions\",\n                    \"pets\"\n                ]\n            }\n        });\n\n    /*\n        How to declare a route:\n\n        Properties:\n        url: Route address starting with \"/\". Mandatory\n        view: will assume url.replace(/\\//g,'') as view name if view not explicitly defined\n        presenter: will assume url.replace(/\\//g,'') as presenter name if presenter not explicitly defined\n        method: implicity call view.start() if not explicitly defined\n    \n        router.route({\n            url: '/route_name',\n            view: 'view_file_name',\n            presenter: 'presenter_file_name',\n            method: 'start_method_name', // implicity call presenter.start() if not explicitly defined\n            append_views: [\n                { \"chatter\" : 'chatter_view' }\n            ]\n        });\n\n     */\n\n    router.route({\n        url: 'help/:id:',\n        view: 'help',\n        presenter: 'help',\n    });\n\n\n    app.start({\n        backboneIDB: true, // require files used by backboneIDB engine\n        $dhx_form: true, // require dhx form helpers\n        $dhx_grid: true, // require dhx grid helpers\n        $dhx_crypt: true // require dhx crypt helpers\n    });\n});    \n````\n\n\n### The application `main` View\n\nThe `Main View` on a dhxMVP application is JavaScript Module that is reponsible to render all the components that are shared by all the `child views`.\n\nInitially, it need to provides a `wrapper` component which will be used as base to construct our entire application. All application componentes will be attached to the `wrapper component`.\n\nAs wrapper component, we may use DHTMLX Sidebar and DHTMLX Layout.\n\nStill yet initially, we also need a `navigation` component which is responsible to provide `navigation` feature to the end user meanwhile it `dispatchs routes` (inject child views and presenters) into the application.\n\nWhen using `DHTMLX Sidebar` as main `application wrapper component` we already have the `navigation component` included.\n\nWhen using `DHTMLX Layout` as main `application wrapper component` we will need to set up a `navigation component`, and for this case we may use:\n\n    - DHTMLX Toolbar\n    - DHTMLX Menu\n    - DHTMLX Ribbon\n\nAs a `Application Main View` you can assume it as `what the end user sees when application starts`, nothing more.\n\nThe application `Main View` shall to provide the following mandatory methods:\n\n- ***render***\n\n    Used call methods which calls DHTMLX components and render the View on browser.\n\n- ***onDispatch***\n\n    event function which is triggered always when a route is dispatched.\n\n- ***initialize***\n\n    Used to perform any task before rendering the view\n\nIt should looks like the following:\n\n````javascript\n$dhx.ui.mvp.views.declare({\n    \"view\": (function() {\n        'strict';\n        var route = '#',\n            main_view = $dhx.ui.mvp.main_view.extend({ }),\n            view = new main_view({\n                /**\n                 * [initialize view. Called before view is rendered]\n                 */\n                initialize: function(options) {\n                    console.log('VIEW:: called initialize from view.initialize');\n                    console.debug.log(this);\n                },\n\n                /**\n                 * [onDispatch event. Called each time a route is dispatched via main_view.dispatch() ]\n                 */\n                onDispatch:function( route ) {\n                    var self = this;\n\n                    self.sidebar.cells( route ).setActive();\n                },\n                \n                /**\n                 * [render the view. Called once application starts]\n                 */\n                render: function( render ) {\n                    var self = this;\n                    \n                }\n            });\n        return view;\n    }())\n});\n````\n\nA more complete `Main View` demo code may be [viewed here](https://gist.github.com/web2solutions/b5efa4546b9502396b1e3b007d51a465)\n\nThe `main view` is represented by the `#` route and it is executed `only one time` in the entire application lifetime when the same starts.\n\n\nThe application `main view` code resides in the following path: `MyApplicationName/lib/view/view.js`.\n\n***NOTE***\n\nThe name of the file is mandatory to be `view.js`. Don't change it.\n\n\n\n\n\n\n### The application `main` Presenter\n\nIn order to take advantage of the `MV*` development model, in the `Main Presenter` we orchestrate the `Main View` operations and tasks.\n\nIn the `Main Presenter` we could define `function event handlers` for the components defined in the 'Main View'.\n\nNot least, we could start the application database or provide any 'help method' to be used into the `Main View`.\n\nIn this way, we keep the code separated in accordance with it type of usage.\n\nThe application `Main Presenter` shall to provide the following mandatory methods:\n\n- ***start***\n\n    Called when the route code starts.\n\n- ***destroy***\n\n    Used to destroy components when unloading the entire application\n\n- ***subscriber***\n\n    Used to receive messages from Mediator.\n    Used to perform actions on presenter or view when requested by Mediator\n\n\nIt should looks like the following:\n\n````javascript\n$dhx.ui.mvp.presenters.declare({\n    \"presenter\": (function() {\n        'strict';\n        var API = {\n            start: function() {\n                var self = this,\n                    view = self.view;\n                $dhx.debug.log('MAIN:PRESENTER: start from MAIN:PRESENTER');\n            },\n            destroy: function() {\n                $dhx.debug.log('MAIN:PRESENTER: destroy from MAIN:PRESENTER');\n                //$dhx.debug.log(this._view);\n            },\n            subscriber: function( event, message ){\n                var self = $dhx.ui.mvp.presenters.get('presenter'),\n                    view = self.view;\n            }\n        }; // end API\n        return API;\n    }())\n});\n````\n\nA more complete `Main Presenter` demo code may be [viewed here](https://gist.github.com/web2solutions/3ffe4b181640c810d152cbd158693c78)\n\nThe `main presenter` is represented by the `#` route and it is executed `only one time` in the entire application lifetime when the same starts.\n\nThe application `main presenter` code resides in the following path: `MyApplicationName/lib/presenter/presenter.js`.\n\n***NOTE***\n\nThe name of the file is mandatory to be `presenter.js`. Don't change it.\n\n\n\n\n\n### The application Model\n\nThe client side data layer of a dhxMVP is basically divided in 3 parts:\n\n1. Models\n2. Collections\n3. Data driver or Engine\n\n#### Models\n\nModels are plain Javascript objects which:\n\n1. Maps to the data of a JSON document of a db collection.\n2. Define `Document Property` ***_names_***.\n3. Define ***_types_*** of a `Document Property`.\n4. Define ***_validation rules_*** of a `Document Property`\n5. Define ***_UI related features_*** of a `Document Property`.\n6. Define ***_Database (client) related features_*** of a `Document Property`.\n7. Define ***_Database (server) related features_*** of a `Document Property`.\n\nModels are saved into the following directory:\n\n***`./lib/model/models`***\n\nA Model shall to provide at least 2 properties:\n\n1. ***__v***\n    Integer property used to transparently set versions of a document.\n    NOTE: Don't set it directly when saving or updating a model.\n2. ***_id***\n    String property to provide sync support for Mongo on a future version of dhxMVP.\n    NOTE: Don't set it directly when saving or updating a model on a fully offline environment. Only set it when using online data fetched from a Mongo.\n\nLet's see a model which defines the JSON Document Schema for a `question` Document of a `collection of questions` to be used to implement a view of a `Frequent Asked Questions` section.\n\n````javascript\nvar question = {\n        /*\n        * mandatory, don't change it\n        */\n        __v: $dhx.ui.mvp.model.helpers.schema.defaults.__v,\n        /*\n        * mandatory, don't change it\n        */\n        _id: $dhx.ui.mvp.model.helpers.schema.defaults._id,\n        /*\n        * question property. Stores a question string.\n        */\n        question: {\n            /*\n            * Property type. Types are Javascript types. It may be:\n            * number, string, array, date\n            */\n            type: 'string',\n            /*\n            * Property default value.\n            * Value used for automatically associate to this property when inserting a \n            * document which does not explicity declare this property\n            */\n            default: '',\n            /*\n            * Property uniqueness.\n            * true or false. Define if the value stored on this property shall to be unique \n            * in the entire document collections\n            */\n            unique: false,\n            /*\n            * Property validation.\n            * Javascrip object which define validation aspects to be used when manipulating documents\n            * on client and server side.\n            */\n            validate: {\n                /*\n                * Is Property required?.\n                * Boolean value which defines if this property shall to have a associated value to it on every time\n                * you save or update this model.\n                */\n                required: true,\n                /*\n                * UI field masking.\n                * define a mask name to be applied to a field which represents this property on the UI.\n                * undefined or ('') for none.\n                * other values: \n                *       currency\n                *       integer, \n                *       credit_card, \n                *       number, \n                *       cpf (Brazilian SSN), \n                *       cnpj (Brazilian Cadasro nacional de Pessoas Jurídicas)\n                *       cep (Brazilian Zip Code)\n                *       us_phone\n                *       br_phone\n                *       expiration_date\n                *       ssn\n                *       time\n                */\n                mask_to_use: undefined,\n                /*\n                * Validation rules\n                * Are rules to test the property value against to, whenever you try to save or \n                * update the model (on client and server side) or submit a form.\n                * Separated comma list of rules\n                * Values may be: \n                *       Empty, NotEmpty, ValidEmail, ValidInteger, ValidFloat, ValidNumeric\n                *       ValidAplhaNumeric, ValidDatetime, ValidDate, ValidTime, ValidCurrency\n                *       ValidSSN, ValidExpirationdate\n                */\n                rules: 'NotEmpty,ValidNumeric'\n            },\n            /*\n            * Property UI related definitions.\n            * Javascrip object which define aspects related to this property on the User Interface\n            */\n            ui: {\n                /*\n                * Expose a explanatory text on UI side related to that document property.\n                * Adds a text tooltip to the control related to that document property on the UI side.\n                */\n                note: 'This is a user question',\n                /*\n                *  Define a maxlength property value to be effective in any control on UI side \n                *  related to that document property.\n                */\n                maxLength: 100,\n                /*\n                * Aspects of this property on a UI Form\n                */\n                form: {\n                    /*\n                    * Form text label\n                    */\n                    label: 'Question',\n                    /*\n                    * Form input type\n                    */\n                    type: 'input',\n                },\n                /*\n                * Aspects of this property on a UI Grid\n                */\n                grid: {\n                    /*\n                    * Header text value on a grid\n                    */\n                    header: 'Question',\n                    /*\n                    * Column alignment on a grid.\n                    * String: left, right, center.\n                    */\n                    align: 'left',\n                    /*\n                    * Column type on a grid.\n                    * It is a DHTMLX Grid column type.\n                    * Please refer to the DHTMLX docs for original types: \n                    *       -\u003e http://docs.dhtmlx.com/grid__columns_types.html\n                    * Another implemented column types are:\n                    *       UScurrency, ssn, USphone\n                    *       BRcurrency, BRphone, cep, cpf, cnpj\n                    *       integer, time\n                    *       moment_calendar, moment_to, moment_from, moment_fromNow, myprice\n                    */\n                    coltype: 'ro',\n                    /*\n                    * Column width on a grid\n                    * Integer values or * for automatically sizing\n                    */\n                    width: '*'\n                }\n            }\n        },\n        answer: {\n            type: 'string',\n            default: '',\n            unique: false,\n            validate: {\n                required: true,\n                mask_to_use: undefined,\n                rules: 'NotEmpty'\n            },\n            ui: {\n                note: 'This is answer for the question',\n                maxLength: 1000,\n                form: {\n                    label: 'Answer',\n                    type: 'input',\n                },\n                grid: {\n                    header: 'Answer',\n                    align: 'left',\n                    coltype: 'ro',\n                    width: '0'\n                }\n            }\n        }\n    };\n````\n\n#### Collections\n\nCollections are like a table on a RDBMS. Instead storing rows, it stores JSON documents.\n\nIn a dhxMVP application, a collection is a plain Javascript Object and it looks like the following code:\n\n````javascript\n    var questions = {\n        model: 'question'\n    };\n````\n\nCollections are saved into the following directory:\n\n***`./lib/model/collections`***\n\n#### Data driver - Engines\n\n\u003e Models are `decoupled`, `completely independent` and `framework agnostic` Javascript Objects. \n\u003e Models are bound to the dhxMVP application through a `Engine\\Data Driver`.\n\u003e \n\u003e `Engines` or `Data Drivers`, are JavaScript Modules which defines certain logic of how about data \n\u003e is accessed, manipuled and stored.\n\nActually, the unique `Engine` implemented uses Backbone to `Create` and `Handle`, `Models` and `Collections` using the predefined models. It also uses the `indexeddb-backbonejs-adapter` plugin to persist data on a local database powered by [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API).\n\nIf you are planning to implement a online and realtime Single Page Application, the currently implemented engined `backboneIDB` provides to you automatically sync data between connected clients. It transparently keep the local `IndexedDB` database of all connected clients in sync using a online Pub/Sub provider (currently implemented over PubNub only).\n\nIf you are planning in to build a offline application, the Pub/Sub will only provide local communication between application components.\n\nThe Engine automatically maps in runtime, the whole defined `Models` and `Collections`, and build a `input` and `output` CRUD style API to provide standardized data access and manipulation to the application. Rather than directly manipulate `Models` and `Collections`, you will count with a clear and well defined API which covers all your models and collections.\n\nThe advantage of implementing a `Data Driver` consist in providing proxyed data access to the models. In other words, you have total freedom to create a new Data Driver that defines a completely different data `access`, `manipulation` and `storage` rules and provide support to different environments and stacks.\n\nA public API of a `Engine` should looks like the following code:\n\nIt should looks like the following:\n\n````javascript\n$dhx.ui.mvp.model.engine.declare({\n    \"backboneIDB\": (function() {\n        'strict';\n        var API = {\n            database:{\n                description: '',\n                id: ''\n            },\n            subscriber: function( event, message ){\n\n            },\n            schema:{\n                add_all_records_from_server: function(){},\n                /*\n                * Namespace: module.schema.io\n                * Provide a CRUD like input and output API for each defined collection\n                */\n                 */\n                io:{\n                    questions:{\n                        create: function(){},\n                        destroy: function(){},\n                        read: function(){},\n                        update: function(){}\n                    },\n                    users: {\n                        create: function(){},\n                        destroy: function(){},\n                        read: function(){},\n                        update: function(){}\n                    },\n                    books: {\n                        create: function(){},\n                        destroy: function(){},\n                        read: function(){},\n                        update: function(){}\n                    },\n                },\n                start: function(){}\n            },\n            start: function(){}\n        }; // end API\n        return API;\n    }())\n});\n````\n\n***NOTE***\n\n_The above code is just a simple example of a Public API for a Engine. This example is not defining any `private` logic which implements that API._\n\nEngines are saved into the following directory:\n\n***`./lib/model/engines`***\n\nA more complete `engine` demo code may be [viewed here](https://gist.github.com/web2solutions/2c829ea0cd11660b10bda3504c8d26b3)\n\n\n\n### Declaring routes\n\nRoutes are declared inside the file `MyApplicationName/lib/app.js`.\n\nWhen you declare a route, you are defining 4 things inside a dhxMVP application:\n\n- a hash url to be dispatched\n- a `Child Presenter` file name to be injected when dispatching the route\n- a `Child View` file name to be injected when dispatching the route\n- A array of names of Javascript modules to be injected into the route scope. You may use the injected code inside your `Child view`.\n\nRoutes may be dispatched through 2 different ways:\n\n1. Calling the `dispatch()` method from the `Main View`. \n\nThis method is automatically created when you declare your `Main View`. Don't declare it again. Example:\n\n***On the Main Presenter***\n\n````javascript\n$dhx.ui.mvp.presenters.declare({\n    \"presenter\": (function() {\n        'strict';\n        var API = {\n            start: function() {\n                var self = this,\n                    view = self.view;\n                $dhx.debug.log('MAIN:PRESENTER: start from MAIN:PRESENTER');\n            },\n            destroy: function() {\n                $dhx.debug.log('MAIN:PRESENTER: destroy from MAIN:PRESENTER');\n                //$dhx.debug.log(this._view);\n            },\n\n            dispatch_help_route: function() {\n                var self = this,\n                    view = self.view;\n                \n                view.dispatch('/help');\n                \n            }\n            \n        }; // end API\n        return API;\n    }())\n});\n````\n\n***On a Child Presenter***\n\n````javascript\n$dhx.ui.mvp.presenters.declare({\n    \"help\": (function() {\n        'strict';\n        var API = {\n            start: function() {\n                var self = this,\n                    view = self.view;\n                $dhx.debug.log('MAIN:PRESENTER: start from MAIN:PRESENTER');\n            },\n            destroy: function() {\n                $dhx.debug.log('MAIN:PRESENTER: destroy from MAIN:PRESENTER');\n                //$dhx.debug.log(this._view);\n            },\n\n            dispatch_help_route: function() {\n                var self = this,\n                    main_view = $dhx.ui.mvp.views.get('view');\n                \n                main_view.dispatch('/help');\n            }\n            \n        }; // end API\n        return API;\n    }())\n});\n````\n\n\n2. Calling the `dispatch()` method from the `_router` Object from the `Main View`. \n\n\n***On the Main Presenter***\n\n````javascript\n$dhx.ui.mvp.presenters.declare({\n    \"presenter\": (function() {\n        'strict';\n        var API = {\n            start: function() {\n                var self = this,\n                    view = self.view;\n                $dhx.debug.log('MAIN:PRESENTER: start from MAIN:PRESENTER');\n            },\n            destroy: function() {\n                $dhx.debug.log('MAIN:PRESENTER: destroy from MAIN:PRESENTER');\n                //$dhx.debug.log(this._view);\n            },\n\n            dispatch_help_route: function() {\n                var self = this,\n                    view = self.view;\n                \n                view._router.dispatch('/help');\n                \n            }\n            \n        }; // end API\n        return API;\n    }())\n});\n````\n\n***On a Child Presenter***\n\n````javascript\n$dhx.ui.mvp.presenters.declare({\n    \"help\": (function() {\n        'strict';\n        var API = {\n            start: function() {\n                var self = this,\n                    view = self.view;\n                $dhx.debug.log('MAIN:PRESENTER: start from MAIN:PRESENTER');\n            },\n            destroy: function() {\n                $dhx.debug.log('MAIN:PRESENTER: destroy from MAIN:PRESENTER');\n                //$dhx.debug.log(this._view);\n            },\n\n            dispatch_help_route: function() {\n                var self = this,\n                    main_view = $dhx.ui.mvp.views.get('view');\n                \n                main_view._router.dispatch('/help');\n            }\n            \n        }; // end API\n        return API;\n    }())\n});\n````\n\n\nNow, let's see how to declare the routes:\n\n\n\n***Complete setup***\n\n\n````javascript\n        router.route({\n            url: '/help',\n            view: 'help_view_file_name',\n            presenter: 'help_presenter_file_name',\n            method: 'start_method_name', // implicity call presenter.start() if not explicitly defined\n            append_views: [\n                { \"chatter\" : 'chatter_view' } // \"name of the javascript object\": \"name of the javascript file\"\n            ]\n        });\n````\n\n\n***Minimal setup***\n\n````javascript\n    router.route({\n        url: 'help/:id:',\n        view: 'help',\n        presenter: 'help',\n    });\n````\n\nThe above declared route will inject the files 'MyApplicationName/lib/view/help.js' and 'MyApplicationName/lib/presenter/help.js' when the route `/help` is dispatched into the Application scope.\n\n\n\n\n\n\n\n#### Child Views\n\nChild Views are Javascript Modules/Object that are reponsible for rendering the view of a dispatched route.\n\nIt should looks like the following:\n\n````javascript\n$dhx.ui.mvp.views.declare({\n    \"help\": (function () {\n        'strict';\n        var route = 'help',\n            child_view = $dhx.ui.mvp.child_view.extend({ }),\n            view = new child_view({\n                /**\n                 * [_settings View's settings. Components' internal settings]\n                 * @type {Object}\n                 */\n                _settings: {\n                    \n                },\n\n                initialize: function(options) {\n                    $dhx.debug.log('CHILD:VIEW:: called initialize from help_view.initialize');\n                },\n                destroy: function() {\n\n                },\n                \n                \n                \n                /**\n                 * [render the view. Called once application starts]\n                 */\n                render: function() {\n                    var self = this;\n                    \n                }\n            });\n\n        return view;\n    }())\n});\n````\n\nA more complete `Child View` demo code may be [viewed here](https://gist.github.com/web2solutions/354b7f926d48ab0eb6e796834089d379)\n\nAs a example, we may consider a `Help` button on the `Main View` which dispatched the `/help` route when clicked.\n`$dhx.ui.mvp` will then inject the 'lib/view/help.js' and this recently injected module will render a interface displaying a list of `Frequent Asked Questions`\n\nOn a dhxMVP application, every route is associated to a `Child View`.\n\n\n\n\n\n#### Child Presenters\n\nChild Presenters are Javascript Modules/Object that are reponsible for orchestrating a `Child View`. of a dispatched route.\n\n\nIt should looks like the following:\n\n````javascript\n$dhx.ui.mvp.presenters.declare({\n    \"help\": (function() {\n        'strict';\n        var API = {\n            start: function() {\n                var self = this,\n                    view = self.view;\n            },\n            destroy: function() {\n                \n                \n            },\n            subscriber: function( event, message ){\n                var self = $dhx.ui.mvp.presenters.get('help'),\n                    view = self.view;\n                \n            },\n        }; // end API\n        return API;\n    }())\n});\n````\n\nA more complete `Child Presenter` demo code may be [viewed here](https://gist.github.com/web2solutions/15826fd72615da2a1b1eadcf2d45e3da)\n\n\nIn the `Child Presenter` we could define `function event handlers` for the components defined in the associated 'Child View'.\n\nNot least, provide any 'help method' to be used into the associated `Child View`.\n\n\nAs a example, we may consider a `Help` button on the `Main View` which dispatched the `/help` route when clicked.\n`$dhx.ui.mvp` will then inject the 'lib/presenter/help.js' and this recently injected module will orchestrate the interface displaying a list of `Frequent Asked Questions`.\n\n\nOn a dhxMVP application, every route is associated to a `Child Presenter`.\n\n\n\n***Resume***\n\nConsidering the Application Demo provided in this boilerplate, every time you want to add a new button on the left sidebar, you will need:\n\n1. Declare a new route into `./boilerplate_sidebar.js`\n2. Add a new sidebar button on the file `lib/presenter/presenter.js` inside add_sidebar_buttons() scope.\n3. Declare a new Child View and create it file inside `lib/view/` folder.\n4. Declare a new Child Presenter and create it file inside `lib/presenter/` folder.\n\n\n### Software validation and code automation\n\nWhen you finish the development process of your dhxMVP application, you may want to move it to production.\n\nNot least, you may want to create releases of your currently application version.\n\nYou may want too, to create `Desktop version` of your fresh created `Web Application`.\n\nAll those features are provided in this Boilerplate system. Although, you will not be able to produce new releases, or create installers for desktop version or even to create distributions of your application to run on a production server if one of the following 2 things occurs:\n\n1. programming error o bad pratice found in your codebase.\n2. Tests performed by the Testing Suite are failing.\n\nIt means you will not be able to delivery bad code to the end users.\n\n\n#### Code quality\n\nTo ensure code quality and best pratices we use [jsHint](http://jshint.com/), a code quality tool, against your codebase.\n\n##### Run JSHint to check the code and look for error and bad pratices.\n\nInside application directory, type:\n\n    $ gulp jshint\n\n\n\n\n#### Unit Tests\n\nInside application directory, type:\n\n    $ gulp test\n\n\n\n\n#### Deploy\n\n\n\n##### Creating minified version of the javascript files\n\nWhen working on localhost, the dhxMVP will generally load the non minified version of the javascript files. Although, the files used by the core are always loaded using the minified version.\n\nIn this case, on every time you change a file of the core (except views and presenters), you need to run the `dist` command to see the changes in action using a browser.\n\nIt is necessary too when putting the application on production due it will load only the minified version of the javascript files.\n\nTo make a dist, run:\n\n    $ gulp dist\n\n***Note***\n\nIt is a good pratice to run `$ gulp jshint` before `$ gulp dist` and check for programming error and bad pratices. Although, the `jshint` is automatically runned before `dist`\n\n\n\n\n\n##### Build a distribution\n\nBuilding a distribution will check the whole code reliability and push it to Git repository as a new version(release) of your application.\n\n    $ sudo gulp build\n\n_The above command will run the following tasks in order:_\n\n- gulp jshint\n- gulp dist\n- gulp test\n- gulp git-add-commit-push\n\n***Note***\n\nIf a error occurs on any of the above task, the upcoming deploy task will not be runned.\n\n\n\n\n\n\n#### Application distributing\n\n\n***Distributable Applications***\n\nDistributable applications are bundles of files automatically generated using the `dist` command in `gulp`.\n\n    $ gulp dist\n\nRunning `dist` will create 4 types of distributable applications:\n\n1. Web version\n\n    Stored in `./dist`\n    The content of the web version can be simple served by a HTTP server.\n\n2. Google Chrome Application Version\n\n    Stored in `./dist_chrome_app`\n    The content of the Google Chrome Application version can be directly imported using the `Google Chrome Extension Manager` or compacted as zip and uploaded in [`Chrome Web Store Control Panel`](https://chrome.google.com/webstore/developer/dashboard)\n\n3. Google Chrome Extension Version\n\n    Stored in `./dist_chrome_extension`\n    The content of the Google Chrome Extension version can be directly imported using the `Google Chrome Extension Manager` or compacted as zip and uploaded in [`Chrome Web Store Control Panel`](https://chrome.google.com/webstore/developer/dashboard)\n\n4. Electron Version\n\n    Stored in `./dist_electron`\n    The content of the Electron version will be used to create Windows, Linux and Mac installers of your application.\n\n\n***The File system of a distributable web version should be something like:***\n\n    |---- dist/\n        |---- assets/\n        |---- deps/\n            |---- dhx\n            |---- thirdparty\n        |---- lib/\n            |---- model\n                |---- collections\n                    |---- questions.js\n                    |---- min.questions.js\n                    |---- users.js\n                    |---- min.users.js\n                |---- engines\n                    |---- backboneIDB.js\n                    |---- min.backboneIDB.js\n                |---- models\n                    |---- min.question.js\n                    |---- min.question.js\n                    |---- min.user.js\n                    |---- min.user.js\n            |---- presenter\n                |---- presenter.js\n                |---- min.presenter.js\n                |---- help.js\n                |---- min.help.js\n            |---- view\n                |---- view.js\n                |---- min.view.js\n                |---- help.js\n                |---- min.help.js\n        |---- index.html\n\n\n***The File system of a distributable Google Chrome Application version should be something like:***\n\n    |---- dist_chrome_app/\n        |---- assets/\n        |---- deps/\n            |---- dhx\n            |---- thirdparty\n        |---- lib/\n            |---- model\n                |---- collections\n                    |---- questions.js\n                    |---- min.questions.js\n                    |---- users.js\n                    |---- min.users.js\n                |---- engines\n                    |---- backboneIDB.js\n                    |---- min.backboneIDB.js\n                |---- models\n                    |---- min.question.js\n                    |---- min.question.js\n                    |---- min.user.js\n                    |---- min.user.js\n            |---- presenter\n                |---- presenter.js\n                |---- min.presenter.js\n                |---- help.js\n                |---- min.help.js\n            |---- view\n                |---- view.js\n                |---- min.view.js\n                |---- help.js\n                |---- min.help.js\n        |---- boilerplate_sidebar.js\n        |---- google_app_background.js\n        |---- icon-128.png\n        |---- icon-16.png\n        |---- index.html\n        |---- manifest.json\n\n\n\n***The File system of a distributable Google Chrome Extension version should be something like:***\n\n    |---- dist_chrome_extension/\n        |---- assets/\n        |---- deps/\n            |---- dhx\n            |---- thirdparty\n        |---- lib/\n            |---- model\n                |---- collections\n                    |---- questions.js\n                    |---- min.questions.js\n                    |---- users.js\n                    |---- min.users.js\n                |---- engines\n                    |---- backboneIDB.js\n                    |---- min.backboneIDB.js\n                |---- models\n                    |---- min.question.js\n                    |---- min.question.js\n                    |---- min.user.js\n                    |---- min.user.js\n            |---- presenter\n                |---- presenter.js\n                |---- min.presenter.js\n                |---- help.js\n                |---- min.help.js\n            |---- view\n                |---- view.js\n                |---- min.view.js\n                |---- help.js\n                |---- min.help.js\n        |---- boilerplate_sidebar.js\n        |---- icon-128.png\n        |---- icon-16.png\n        |---- index.html\n        |---- manifest.json\n\n\n\n\n***The File system of a distributable Electron version should be something like:***\n\n    |---- dist_electron/\n        |---- public\n            |---- assets/\n            |---- deps/\n                |---- dhx\n                |---- thirdparty\n            |---- lib/\n                |---- model\n                    |---- collections\n                        |---- questions.js\n                        |---- min.questions.js\n                        |---- users.js\n                        |---- min.users.js\n                    |---- engines\n                        |---- backboneIDB.js\n                        |---- min.backboneIDB.js\n                    |---- models\n                        |---- min.question.js\n                        |---- min.question.js\n                        |---- min.user.js\n                        |---- min.user.js\n                |---- presenter\n                    |---- presenter.js\n                    |---- min.presenter.js\n                    |---- help.js\n                    |---- min.help.js\n                |---- view\n                    |---- view.js\n                    |---- min.view.js\n                    |---- help.js\n                    |---- min.help.js\n            |---- boilerplate_sidebar.js\n            |---- index.html\n        |---- index.js\n        |---- package.json\n\n\nIncluding the Web, Chrome Application and Chrome Extension versions, you may be interested in distributing your application as a `Desktop Application`. For this case, the Boilerplate system provides you a mechanism to create `executable versions` of your application with no efforts.\n\nYou can get the generated executables and distribute to your client.\n\nThe generated installers will be stored into `installers/`.\n\nTo make the installers, run the following commands:\n\n\n\n##### Creating Mac installers\n\n    $ gulp build-installer-mac\n\n\n\n\n##### Creating Windows installers\n\n    $ gulp build-installer-windows\n\n\n\n\n##### Creating Linux installers\n\n    $ gulp build-installer-windows\n\n\n\n##### Creating a Google Chrome Application\n\nA Google Chrome Application version of your app is automatically generated when you run `gulp dist`. The generated application is saved under the `./dist_chrome_app` directory.\n\n    $ gulp dist\n\n\n\n##### Creating a Google Chrome Extension\n\nA Google Chrome Extension version of your app is automatically generated when you run `gulp dist`. The generated application is saved under the `./dist_chrome_extension` directory.\n\n    $ gulp dist\n\n\n\n\n\n### Move to production\n\n\n\n## Release notes\n\nVersion: v0.0.94-alpha\n\n- Complete data sync between connected clients. Online usage.\n- Messaging Mediator\n    - Local Messaging Mediator\n        - Assynchronous Pub/Sub to provide local/offline communication between `isolated application pieces`.\n    - Remote Messaging Mediator\n        - Assynchronous Pub/Sub to provide remote/online communication/data sync between `connected clients`.\n            Currently using [PubNub](https://www.pubnub.com/) as communication stack. Easily replaced by your own stack with websocket and Redis for example.\n- Demo improvements\n    - New Pet model\n    - New Pets collection\n    - Main presenter subscriber\n        - Update Dashboard charts data when receives a message\n    - Help child presenter subscriber\n        - Insert data on view when receives a message\n        - Update data on view when receives a message\n        - Delete data on view when receives a message\n    - Help child view \n        - Insert data - UI - send message\n        - Update data - UI - send message\n        - Delete data - UI - send message\n- $dhx.ui.mvp improvements\n- $dhx.ui.session initial implementation\n- $dhx.component improvements\n- $dhx.getRandomColor\n- backboneIDB engine improvements\n    Create, Update and Destroy models when receiving proper messages from Mediator.\n    Notify Mediator when performed action was requested by local client. Notify other connected users.\n- New properties for model ui definition\n    - note\n        Expose a explanatory text on UI side related to that document property.\n        Adds a text tooltip to the control related to that document property on the UI side.\n    - maxLength\n        Define a maxlength property value to be effective in any control on UI side related to that document property.\n- navigator.geolocation shim\n\n## Todo\n\n- Generate Cordova distribution. Mobile application version.\n\n- Implement a `datastore` API\n    \n    Similar to [DHTMLX Datastore](http://docs.dhtmlx.com/datastore__index.html) to be used internally by all Engines.\n\n- Provide server sync for backboneIDB Engine\n    \n    Using Express, WS and Redis on Back End\n\n- Provide server storage for backboneIDB Engine\n    - Using Mongo on Back End\n    - Using Couchbase\n\n- Implement Pouch Engine and provide support to CouchBase\n\n- Implement Firebase Engine\n\n- REST API generator using defined models and collection\n    \n    Express\n    Mongoose\n    Mongo\n\n- Implement REST client\n\n\n\n\n\n## License\n\nThis software is distributed under [GPL-2.0](https://www.gnu.org/licenses/gpl-2.0.html) in accordance with [DHTMLX license](http://dhtmlx.com/docs/products/licenses.shtml).\n\n\n### DISCLAIMER OF WARRANTY\n\nBECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.\n\nIN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fweb2solutions%2Fdhxmvp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fweb2solutions%2Fdhxmvp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fweb2solutions%2Fdhxmvp/lists"}