From 81e19b432cabb3e8310b28e151a030003eb3e8bc Mon Sep 17 00:00:00 2001 From: chestozo Date: Fri, 2 May 2014 20:09:52 +0400 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D0=BD=D0=B4=D0=B5=D1=80=D0=B8?= =?UTF-8?q?=D0=BD=D0=B3=20=D0=BF=D1=80=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B2=20nodejs=20#264?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jshintrc | 2 +- package.json | 1 + src/index.js | 19 +++++++ src/ns.box.js | 3 + src/ns.consts.events.js | 2 + src/ns.consts.js | 2 + src/ns.dom.js | 2 + src/ns.js | 19 ++++--- src/ns.layout.js | 4 +- src/ns.log.js | 6 +- src/ns.model.js | 3 + src/ns.modelCollection.js | 3 + src/ns.object.js | 2 + src/ns.page.js | 3 + src/ns.request.js | 5 +- src/ns.router.js | 3 + src/ns.update.js | 116 ++++++++++++++++++++++---------------- src/ns.view.js | 22 +++++--- src/ns.viewCollection.js | 5 +- test/spec/combinations.js | 2 +- 20 files changed, 153 insertions(+), 71 deletions(-) create mode 100644 src/index.js diff --git a/.jshintrc b/.jshintrc index f80b9f7c..832e9948 100644 --- a/.jshintrc +++ b/.jshintrc @@ -4,7 +4,7 @@ "jquery": true, "node": true, "globals": { - "no": false, + "no": true, "ns": true, "DocumentTouch": false, "Vow": false, diff --git a/package.json b/package.json index 3be2566c..85324699 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "engines": { "node": "*" }, + "main": "src/index.js", "files": [ "css", "dist", diff --git a/src/index.js b/src/index.js new file mode 100644 index 00000000..c81929b6 --- /dev/null +++ b/src/index.js @@ -0,0 +1,19 @@ +var ns = require('./ns.js'); + +require('./ns.log.js'); +require('./ns.dom.js'); +require('./ns.consts.js'); +require('./ns.consts.events.js'); +require('./ns.object.js'); +require('./ns.router.js'); +require('./ns.layout.js'); +require('./ns.model.js'); +require('./ns.modelCollection.js'); +require('./ns.box.js'); +require('./ns.view.js'); +require('./ns.viewCollection.js'); +require('./ns.page.js'); +require('./ns.request.js'); +require('./ns.update.js'); + +module.exports = ns; diff --git a/src/ns.box.js b/src/ns.box.js index 87f2f7e0..53945d41 100644 --- a/src/ns.box.js +++ b/src/ns.box.js @@ -1,3 +1,6 @@ +var no = no || require('nommon'); +var ns = ns || require('./ns.js'); + /** * Это внутренний класс, который не должен использоваться приложением. * @classdesc Box - это тип View, который умеет выбирать какие View показывать. diff --git a/src/ns.consts.events.js b/src/ns.consts.events.js index 293ea6db..ec4efe6b 100644 --- a/src/ns.consts.events.js +++ b/src/ns.consts.events.js @@ -1,3 +1,5 @@ +var ns = ns || require('./ns.js'); + /** * Хеш событий для удобного биндинга touch/desktop * @type {object} diff --git a/src/ns.consts.js b/src/ns.consts.js index 6dbdc6eb..ba7be637 100644 --- a/src/ns.consts.js +++ b/src/ns.consts.js @@ -1,3 +1,5 @@ +var ns = ns || require('./ns.js'); + /** * Типы узлов ns.layout * @enum {string} diff --git a/src/ns.dom.js b/src/ns.dom.js index b3cb313c..60c21747 100644 --- a/src/ns.dom.js +++ b/src/ns.dom.js @@ -1,3 +1,5 @@ +var ns = ns || require('./ns.js'); + /** * Replaces oldNode with newNode * @param {Element} oldNode diff --git a/src/ns.js b/src/ns.js index 3973c009..e7905a64 100644 --- a/src/ns.js +++ b/src/ns.js @@ -1,3 +1,5 @@ +var no = no || require('nommon'); + /** * noscript MVC framework * @namespace @@ -6,7 +8,7 @@ */ var ns = {}; -if (typeof window === 'undefined') { +if (no.de) { module.exports = ns; } @@ -20,7 +22,7 @@ ns.events = no.extend( {}, no.Events ); * @const * @type {Boolean} */ -ns.IS_TOUCH = Boolean( +ns.IS_TOUCH = !no.de && Boolean( 'ontouchstart' in window || (window.DocumentTouch && document instanceof DocumentTouch) ); @@ -70,15 +72,14 @@ ns.parseQuery = function(s) { }; /** - * Performs json templating. - * @param {*} json - * @param {string} mode - * @param {string} [module='main'] - * @returns {Element} + * Генерация HTML по json дереву видов. + * @param {object} json Дерево видов. + * @param {string} mode Начальная мода: выполнить матчинг для шаблона с этой модой. + * @param {string} [module='main'] id Модуля yate. + * @returns {string} Отрендеренный HTML код. */ ns.tmpl = function(json, mode, module) { - var result = yr.run(module || 'main', json, mode); - return ns.html2node(result); + return yr.run(module || 'main', json, mode); }; /** diff --git a/src/ns.layout.js b/src/ns.layout.js index 6b83a21e..352047be 100644 --- a/src/ns.layout.js +++ b/src/ns.layout.js @@ -1,3 +1,6 @@ +var no = no || require('nommon'); +var ns = ns || require('./ns.js'); + (function() { /** @@ -189,5 +192,4 @@ } return key; } - })(); diff --git a/src/ns.log.js b/src/ns.log.js index fb554a5e..3758e7d4 100644 --- a/src/ns.log.js +++ b/src/ns.log.js @@ -1,4 +1,6 @@ -(function(ns) { +var ns = ns || require('./ns.js'); + +(function() { /** * Модуль логирования ошибок. @@ -44,4 +46,4 @@ /* jshint unused: false */ }; -})(ns); +})(); diff --git a/src/ns.model.js b/src/ns.model.js index 891d5a3f..f5623e4d 100644 --- a/src/ns.model.js +++ b/src/ns.model.js @@ -1,3 +1,6 @@ +var no = no || require('nommon'); +var ns = ns || require('./ns.js'); + (function() { /** diff --git a/src/ns.modelCollection.js b/src/ns.modelCollection.js index 2c950a22..f56be33d 100644 --- a/src/ns.modelCollection.js +++ b/src/ns.modelCollection.js @@ -1,3 +1,6 @@ +var no = no || require('nommon'); +var ns = ns || require('./ns.js'); + (function() { /** diff --git a/src/ns.object.js b/src/ns.object.js index 3512dd25..4e7ca812 100644 --- a/src/ns.object.js +++ b/src/ns.object.js @@ -1,3 +1,5 @@ +var ns = ns || require('./ns.js'); + /** * Хелперы для работы с объектами * @namespace diff --git a/src/ns.page.js b/src/ns.page.js index 93806c4e..280ccf84 100644 --- a/src/ns.page.js +++ b/src/ns.page.js @@ -1,3 +1,6 @@ +var no = no || require('nommon'); +var ns = ns || require('./ns.js'); + (function() { /** diff --git a/src/ns.request.js b/src/ns.request.js index 88b6b8bc..c0688b1a 100644 --- a/src/ns.request.js +++ b/src/ns.request.js @@ -1,3 +1,6 @@ +var no = no || require('nommon'); +var ns = ns || require('./ns.js'); + (function() { /** @@ -42,7 +45,7 @@ ns.request.models = function(models, options) { // Загрузка порционных данных. В этом случае грузим не саму модель, а порцию данных. - models = $.map(models, function(model) { + models = models.map(function(model) { return model.getRequest ? model.getRequest() : model; }); diff --git a/src/ns.router.js b/src/ns.router.js index 473a5071..fca0324c 100644 --- a/src/ns.router.js +++ b/src/ns.router.js @@ -1,3 +1,6 @@ +var no = no || require('nommon'); +var ns = ns || require('./ns.js'); + /** * Find best page for url. * @namespace diff --git a/src/ns.update.js b/src/ns.update.js index 0db17f92..e6841d53 100644 --- a/src/ns.update.js +++ b/src/ns.update.js @@ -1,13 +1,32 @@ +var no = no || require('nommon'); +var ns = ns || require('./ns.js'); + (function() { /** - * Создает ns.Update + * Id последнего созданного update-а. + * @type {number} + */ + var update_id = -1; + + /** + * Current ns.Updates. + * @type ns.Update[] + * @private + */ + var currentUpdates = []; + + /** + * Создает ns.Update. + * * @classdesc ns.Update * @param {ns.View} view Корневой view. - * @param {object} layout Layout для этого view, результат от ns.layout.page() - * @param {object} params Параметры, результат от ns.router() - * @param {object} [options] Options for ns.Update - * @param {ns.U.EXEC} [options.execFlag=ns.U.EXEC.GLOBAL] Options for ns.Update + * @param {object} layout Layout для этого view, результат от ns.layout.page(). + * @param {object} params Параметры, результат от ns.router(). + * @param {object} [options] Опции для ns.Update. + * @param {ns.U.EXEC} [options.execFlag=ns.U.EXEC.GLOBAL] Тип ns.Update (GLOBAL, PARALLEL, ASYNC). + * @param {boolean} [options.syncOnly=] Флаг "запросить данные только для синхронных видов". Нужен для генерации html на сервере. + * @param {boolean} [options.renderOnly=] Флаг "нужен только HTML код". Нужен для генерации html на сервере. * @constructor * @example * ```js @@ -39,28 +58,15 @@ this.id = ++update_id; - options = options || {}; + this.options = options = options || {}; /** * Execution flag * @type {ns.U.EXEC} */ - this.EXEC_FLAG = options.execFlag || ns.U.EXEC.GLOBAL; + this.execFlag = options.execFlag || ns.U.EXEC.GLOBAL; }; - /** - * Current ns.Updates. - * @type ns.Update[] - * @private - */ - var currentUpdates = []; - - /** - * Id последнего созданного update-а. - * @type {number} - */ - var update_id = -1; - /** * @see ns.U.STATUS * @type {ns.U.STATUS} @@ -131,11 +137,15 @@ return; } - that._update(async); - // resolve main promise and return promises for async views - that.done({ - async: asyncUpdaterPromises - }); + if (that.options.renderOnly) { + that.done(that._render()); + } else { + that._update(async); + // resolve main promise and return promises for async views + that.done({ + async: asyncUpdaterPromises + }); + } }, function(models) { // NOTE here we do not even try to handle the error. Or we should do it? that.error({ @@ -150,6 +160,10 @@ }); }); + if (this.options.syncOnly) { + return resultPromise; + } + // Для каждого async-view запрашиваем его модели. // Когда они приходят, запускаем точно такой же update. // Причем ждем отрисовку sync-view, чтобы точно запуститься после него. @@ -200,27 +214,13 @@ async_view: view, models: result[1] }); - }) - .fail(function(e) { - asyncUpdaterPromises[asyncViewId].reject({ - error: e, - async_view: view, - models: models - }); }); }); return resultPromise; }; - /** - * Обновляет DOM и триггерит нужные события - * @param {boolean} [async=false] Флаг асинхронного updater'а. - * @private - */ - ns.Update.prototype._update = function(async) { - // TODO: Проверить, что не начался уже более новый апдейт. - + ns.Update.prototype._render = function() { var params = this.params; var layout = this.layout; @@ -231,12 +231,32 @@ ns.log.debug('[ns.Update]', 'start()', this.id, 'updateTree', tree); - var node; // если пустое дерево, то ничего не реднерим, // но кидаем события и скрываем/открываем блоки + var html; if (!ns.object.isEmpty(tree.views)) { - node = this.render(tree, this.params, this.layout); - ns.log.debug('[ns.Update]', 'start()', this.id, 'new node', node.cloneNode(true)); + html = this.render(tree, params, layout); + ns.log.debug('[ns.Update]', 'start()', this.id, 'rendered html', html); + } + + return html; + }; + + /** + * Обновляет DOM и триггерит нужные события + * @param {boolean} [async=false] Флаг асинхронного updater'а. + * @private + */ + ns.Update.prototype._update = function(async) { + // TODO: Проверить, что не начался уже более новый апдейт. + + var params = this.params; + var layout = this.layout; + + var node; + var html = this._render(); + if (html) { + node = ns.html2node(html); } var viewEvents = { @@ -271,7 +291,7 @@ * @param {object} tree Дерево видов. * @param {object} params Параметры страницы. * @param {object} layout Раскладка страницы. - * @returns {HTMLElement} + * @returns {string} */ ns.Update.prototype.render = function(tree, params, layout) { /* jshint unused: false */ @@ -353,7 +373,7 @@ var FLAG_PARALLEL = FLAGS.PARALLEL; var FLAG_ASYNC = FLAGS.ASYNC; - var newRunExecutionFlag = newUpdate.EXEC_FLAG; + var newRunExecutionFlag = newUpdate.execFlag; var i; var j; @@ -368,7 +388,7 @@ var run = currentRuns[i]; // don't terminated paraller updates - if (run.EXEC_FLAG === FLAG_PARALLEL) { + if (run.execFlag === FLAG_PARALLEL) { survivedRuns.push(run); } else { @@ -382,7 +402,7 @@ // check whether we have one global update for (i = 0, j = currentRuns.length; i < j; i++) { - if (currentRuns[i].EXEC_FLAG === FLAG_GLOBAL) { + if (currentRuns[i].execFlag === FLAG_GLOBAL) { return false; } } @@ -399,7 +419,7 @@ * @returns Boolean. */ ns.Update.prototype.isGlobal = function() { - return this.EXEC_FLAG === ns.U.EXEC.GLOBAL; + return this.execFlag === ns.U.EXEC.GLOBAL; }; /** diff --git a/src/ns.view.js b/src/ns.view.js index da4c5c98..b68c351e 100644 --- a/src/ns.view.js +++ b/src/ns.view.js @@ -1,4 +1,7 @@ -(function() { +var no = no || require('nommon'); +var ns = ns || require('./ns.js'); + +(function($, win, doc) { /** * Uniq View ID counter @@ -28,14 +31,14 @@ * @type {jQuery} * @private */ - ns.View.prototype._$document = $(document); + ns.View.prototype._$document = $(doc); /** * Закешированный $(window) * @type {jQuery} * @private */ - ns.View.prototype._$window = $(window); + ns.View.prototype._$window = $(win); /** * Инициализирует экземпляр вида @@ -884,7 +887,8 @@ tree.extra = extra; } - return ns.tmpl(tree, mode); + var html = ns.tmpl(tree, mode); + return ns.html2node(html); }; /** @@ -1044,8 +1048,8 @@ this._saveModelsVersions(); } - // Если view валидный и не в async-режиме, то вызывается show и touch - // Для валидных view при втором проходе (когда отрисовываются asynс-view) не надо второй раз кидать touch + // Если view валидный и не в async-режиме, то вызывается show и touch + // Для валидных view при втором проходе (когда отрисовываются asynс-view) не надо второй раз кидать touch // Условие звучит так "(Если мы в синхнронном ns.Update и view стал валиден) или (view был не валиден и стал валиден)" // Второе условие относится как к перерисованным view, так и к async-view, которые полностью отрисовались @@ -1548,4 +1552,8 @@ return decl; }; -})(); +})( + no.de ? no.nop : jQuery, + no.de ? null : window, + no.de ? null : document +); diff --git a/src/ns.viewCollection.js b/src/ns.viewCollection.js index 7373cb7c..d02022f7 100644 --- a/src/ns.viewCollection.js +++ b/src/ns.viewCollection.js @@ -1,3 +1,6 @@ +var no = no || require('nommon'); +var ns = ns || require('./ns.js'); + /** * Создает коллекцию видов. * @classdesc Коллекция видов. @@ -409,7 +412,7 @@ ns.ViewCollection.prototype._updateHTML = function(node, layout, params, updateO } } - // Если view валидный и не в async-режиме, то вызывается show и touch + // Если view валидный и не в async-режиме, то вызывается show и touch // Для валидных view при втором проходе (когда отрисовываются asynс-view) не надо второй раз кидать touch // Условие звучит так "(Если мы в синхнронном ns.Update и view стал валиден) или (view был не валиден и стал валиден)" diff --git a/test/spec/combinations.js b/test/spec/combinations.js index 25d9cabd..6058922d 100644 --- a/test/spec/combinations.js +++ b/test/spec/combinations.js @@ -60,7 +60,7 @@ describe('Combinations of entities', function() { done(); }); }); - + }); afterEach(function() {