$(function () { // $('#button').click(function (event) { alert(this.innerHTML); }); $('#list').uberScrollerPluginStart({ "theme": "red" }); $('#lazy_thing').click(function () { $.get('/lazy/thing/body.html', doLazyLoad.bind(this)); }); /* */ });
var Module1 = { "someAction": function () { Module2.getSomeValue(); } }; var Module2 = { "getSomeValue": function () { return 'data'; } };
getSomeValue()
method. If we remove module 2, then everything will break. // var Module1 = { "init": function ($) { $.on('event', function (e) { // $ - jQuery, sandbox console.log(e.data); }); } }; var Module2 = { "someAction": function ($) { // $ - jQuery $.trigger('event', 'data'); } };
// var Storage = { "read": function (key) { return localStorage[key]; } }; var data = Storage.read('key'), pData = process(data); $.trigger('data', pData);
localStorage
, work with it synchronously and everything is fine. Well, as long as we did not want to keep the same data on the server, the probability that we decide to change something is very high. Translation of synchronous code to asynchronous can be a big problem, even with an event model. // var Storage = { "read": function (key, cb) { $.get('/read/' + key, cb); } }; Storage.read('key',function(data) { var pData = processData(data); $.trigger('data', pData); }.bind(this));
/app /css - /blocks /b-module-name /b-module-name.css ... ... /pages /index.css ... /descriptors - /ModuleName.json ... /locales - /ModuleName.json ... /modules - /ModuleName.js ... /templates - /ModuleName.html ... /views - /ModuleName.html ... /build - /lib - /Core.js /test - /lib /qunit.css /qunit.js /ModuleName - ModuleName /index.html /index.js /TestData.js - /vendors - /Script.js /jQuery.js ... /index.html - /index.js - js , /index.json - ...
(function(global){ "use strict"; var intervalId; var DataGenerator = { init: function (sandbox) { intervalId = setInterval(function () { sandbox.trigger('newData', Math.random()); }, sandbox.getResource('interval')); }, destroy: function () { clearInterval(intervalId); } }; // if (!global) { return DataGenerator; } if (!global.exports) { global.exports = {}; } global.exports.DataGenerator = DataGenerator; }(this)) // ; !
{ "name": "DataGenerator", "acl": { "trigger:newData": true // newData }, "resources": { "interval": 1000 } }
{ "text_label": { "ru": " : ", "en": "He said: " } }
<div class="b-message-view"> <span class="b-message-view__label">{%=label%}</span> <span class="b-message-view__value">{%=value%}</span> </div>
var loaderFactory = function (cacheObject, method, format, methodOwner, type) { return function (name) { var dfd = $.Deferred(), self = this; if (cacheObject[name]) { dfd.resolve(); return dfd.promise(); } function successOrFail(object) { var camelCasedType = type.slice(0, 1).toUpperCase() + type.slice(1); self['push' + camelCasedType](name, object); dfd.resolve(); if (object) { // if fail EventManager.trigger(type + ':loaded', {name: name}); EventManager.trigger(type + ':' + name + ':loaded'); } } var path = Core.descriptor.path[type] + format.replace('$0', name); if (type === 'module') { method.call(methodOwner, path, successOrFail); } else if (type === 'template') { method.call(methodOwner, path, successOrFail, 'html').error(successOrFail); } else { method.call(methodOwner, path, successOrFail).error(successOrFail); } return dfd.promise(); } };
var ModuleManager = { modules: {}, descriptors: {}, locales: {}, templates: {}, pushModule: function (name, module) {}, pushDescriptor: function (name, descriptor) {}, pushLocale: function (name, locale) {}, pushTemplate: function (name, template) {}, load: function (name) {} }; ModuleManager.getModule = loaderFactory(ModuleManager.modules, require, '$0.js', this, 'module'); ModuleManager.getDescriptor = loaderFactory(ModuleManager.descriptors, $.getJSON, '$0.json', $, 'descriptor'); ModuleManager.getLocale = loaderFactory(ModuleManager.locales, $.getJSON, '$0.json', $, 'locale'); ModuleManager.getTemplate = loaderFactory(ModuleManager.templates, $.get, '$0.html', $, 'template');
var templateFactory = function(str, data) {}
jQuery.bind jQuery.trigger jQuery.unbind
besides the standard methods it will have an interesting method - hook
, which hooks the hook function to the event. The hook function can change the contents of the event parameters, it can also prevent the event from being triggered. var EventManager = { $: $('<div/>'), hooks: {}, trigger: function (event, data) { if (this.hooks[event]) { // Update event data var result = this.hooks[event](data); // Don't trigger event if (result === false) { return this; } // Trigger with new data data = result || data; } this.$.trigger.apply(this.$, [event, data]); return this; }, bind: function () {}, unbind: function () {}, hook: function (event, hookFunction) { // One hook for example this.hooks[event] = hookFunction; return this; }, unhook: function (event) { delete this.hooks[event]; return this; } };
var Core = { descriptor: {}, runningModules: {}, // , init: function (descriptorOrFileName, callback) {}, // _initModules: function (callback) {}, // initModule: function (name, callback) {}, // destroyModule: function (name) {}, // HTMLElement getBox: function (name) {}, // getTemplateFunction: function (moduleName, templateSelector) {} };
var CorePublic = { trigger: $.proxy(EventManager.trigger, EventManager), bind: $.proxy(EventManager.bind, EventManager), unbind: $.proxy(EventManager.trigger, EventManager), on: $.proxy(EventManager.bind, EventManager), getModule: $.proxy(ModuleManager.getModule, ModuleManager), getDescriptor: $.proxy(ModuleManager.getDescriptor, ModuleManager), getLocale: $.proxy(ModuleManager.getLocale, ModuleManager), getTemplate: $.proxy(ModuleManager.getTemplate, ModuleManager), pushModule: $.proxy(ModuleManager.pushModule, ModuleManager), pushDescriptor: $.proxy(ModuleManager.pushDescriptor, ModuleManager), pushLocale: $.proxy(ModuleManager.pushLocale, ModuleManager), pushTemplate: $.proxy(ModuleManager.pushTemplate, ModuleManager), init: $.proxy(Core.init, Core), destroyModule: $.proxy(Core.destroyModule, Core), initModule: $.proxy(Core.initModule, Core), getTemplateFunction: $.proxy(Core.getTemplateFunction, Core) };
var Sandbox = function (descriptor) { this.descriptor = descriptor || {}; }; Sandbox.prototype.getBox = function () {}; // - Sandbox.prototype.is = function (role) {}; Sandbox.prototype.bind = function (event, callback) {}; Sandbox.prototype.unbind = function (event, callback) {}; Sandbox.prototype.trigger = function (event, data) {}; Sandbox.prototype.hook = function (event, hookFunction) {}; Sandbox.prototype.unhook = function (event) {}; Sandbox.prototype.getText = function (message) {}; Sandbox.prototype.getResource = function (resource) {}; Sandbox.prototype.getTemplate = function (templateSelector) {};
bind, trigger, hook,
...) that can affect other objects, the sandbox checks whether this function can be performed on this module (using the module descriptor). (function(global, $, require, undefined){ "use strict"; var templateFactory = function(str, data){}; var loaderFactory = function (cacheObject, method, format, self, type) {}; var ModuleManager = {}; var Sandbox = function (descriptor) {}; var EventManager = {}; var Core = {}; var CorePublic = {}; if (!global) { return CorePublic; } if (!global.exports) { global.exports = {}; } global.exports.Core = CorePublic; }(this, jQuery, $script));
{ "modules": ["MessageView", "DataGenerator", "Logger", "Hook"], "layout": { "MessageView": ".b-message-view" }, "locale": "ru", "path": { "descriptor": "./app/descriptors/", "module": "./app/modules/", "locale": "./app/locales/", "template": "./app/templates/" } }
Math.random()
index.json
. /*$require: ./lib/Core.js */ (function (Core) { "use strict"; /*$buildFrom ./index.json */ Core.on('ready', function () { Core.trigger('newData', 'Pewpew'); }); Core.init(/*$require*/'./index.json'/*$*/); }(this.exports.Core))
// Core.js (function (Core) { "use strict"; // + descriptors/Logger.json Core.pushDescriptor("Logger", { "name": "Logger", "acl": { "listen:newData": true, "listen:ready": true } }); // - descriptors/Logger.json // + modules/Logger.js Core.pushModule("Logger", (function(global){ // ... }(this))); // - modules/Logger.js // + locales/Logger.js Core.pushLocale("Logger", {}); // - locales/Logger.js // ... - .... Core.on('ready', function () { Core.trigger('newData', 'Pewpew'); }); Core.init({ "modules": ["MessageView", "DataGenerator", "Logger", "Hook"], "layout": { "MessageView": ".b-message-view" }, "locale": "ru", "path": { "descriptor": "./app/descriptors/", "module": "./app/modules/", "locale": "./app/locales/", "template": "./app/templates/" } }); }(this.exports.Core))
require
, buildFrom
. . Logger
( - ). buildFrom
( "en": "He said: "
), . /*$buildFrom: ../../index.json */ /* app/css/blocks/b-message-view/b-message-view.css */ .b-message-view { color: green; font-family: monospace; }
buildFrom
css
: layout , b-message-view
β . , , . , json .index.css
index.js
. index.html
<!DOCTYPE HTML> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title></title> <!--$require: index.css--> <link rel="stylesheet" href="app/css/pages/index.css" /> <!--$--> </head> <body> <!--$buildFrom: index.json--> <div class="b-message-view"></div> <!--$--> <script type="text/javascript" src="http://yandex.st/jquery/1.6.1/jquery.js"></script> <!--$require: index.js--> <script type="text/javascript" src="./vendors/Script.js"></script> <script type="text/javascript" src="./lib/Core.js"></script> <script type="text/javascript" src="./index.js"></script> <!--$--> </body> </html>
buildFrom
html ( css): layout div b-message-view
. , . xslt, . <!DOCTYPE HTML> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title></title> <link rel="stylesheet" href="/index.css" /> </head> <body> <div class="b-message-view"></div> <script type="text/javascript" src="http://yandex.st/jquery/1.6.1/jquery.js"></script> <script type="text/javascript" src="/index.js"></script> </body> </html>
var TestData = { "newData": function () { var data = [NaN, Infinity, window, Error, 'pewpewpew', '<b>Pewpew</b>', '"', '\'', new Date, Date, Math, 42, 8, -1, 0, false, true]; return data; } };
// MessageView test (function (Core, $, TestData, ok, test, module, equals, expect, asyncTest, start, stop) { "use strict"; // var ApplicationEnvironment = { "modules": ["MessageView"], "layout": { "MessageView": ".b-message-view" }, "locale": "ru", "path": { "descriptor": "../../app/descriptors/", "module": "../../app/modules/", "locale": "../../app/locales/", "template": "../../app/templates/" } }; Core.on('ready', function () { module("MessageView"); // 1 test("listen:newData", function() { var testItems = TestData["newData"](), $MessageView = Core.getBox("MessageView"), template = Core.getTemplateFunction("MessageView", '.b-message-view'), label = Core.getText("MessageView", "text_label"); expect(testItems.length); // >>> put your code $.each(testItems, function (index, text) { Core.trigger("newData", [text]); // >>> put your code var expected = template({label: label, value: text}); // <<< equals(expected, $MessageView.html(), 'Should be "text_label: value"'); // <<< }); }); // 2 test("trigger:newData:display", function() { var testItems = TestData["newData"](), $MessageView = Core.getBox("MessageView"), template = Core.getTemplateFunction("MessageView", '.b-message-view'); expect(testItems.length); // >>> put your code Core.on("newData:display", function () { // <<< ok(true); // <<< }); // <<< $.each(testItems, function (index, item) { Core.trigger("newData", [item]); // >>> put your code }); }); }); Core.init(ApplicationEnvironment); }(this.exports.Core, jQuery, TestData, ok, test, module, equals, expect, asyncTest, start, stop))
<<<
".$textarea.val($textarea.val())
Source: https://habr.com/ru/post/123635/
All Articles