GithubHelp home page GithubHelp logo

aurajs / aura Goto Github PK

View Code? Open in Web Editor NEW
2.9K 2.9K 256.0 2.31 MB

A scalable, event-driven JavaScript architecture for developing component-based applications.

License: MIT License

JavaScript 99.28% HTML 0.72%

aura's People

Contributors

addyosmani avatar asciidisco avatar atesgoral avatar bobholt avatar bolshchikov avatar buritica avatar c4milo avatar dcherman avatar dotcypress avatar drewzboto avatar dustinboston avatar eliperelman avatar gersongoulart avatar hkjorgensen avatar hmac avatar joelhooks avatar julien avatar karlwestin avatar oliger avatar peterudo avatar pickachu avatar robertd avatar robertusvt avatar rumpl avatar sbellity avatar sindresorhus avatar steffenmllr avatar tony avatar virtueme avatar xcambar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aura's Issues

Stopping a widget not freeing memory/script?

I don't know if this is an issue with aura, requirejs, or chrome - but, it appears that scripts do not delete when you stop a widget. Worse yet, when you start the widget the script is duplicated. This duplication doesn't seem to show in the "Network" section in Chrome's Developer Tools, but it does show in "Scripts." Also, if you stop/start each widget multiple times while in the "Timeline" section (with record on), you'll see the memory climb.

For reference, memory seems to be at about 10mb after everything loads, but after stopping and starting each widget about 10 times the memory goes to about 30mb.

I'm not totally sure what it all means, but in the "Timeline" section, with the "Memory" option active, it appears that "listener" events fluctuates appropriately when stopping/starting widgets, but "nodes" climb each time a widget is started. I'd guess that means that event listeners are being removed correctly, but it seems like DOM elements aren't removed (aren't scripts DOM elements?). Makes me think that require.undef either doesn't work right or it's not be fired?

I checked and require.undef(key) is running when it should, but maybe the key is wrong? Or require.undef() just doesn't work like I would expect it to (I haven't it tested it on any of my projects, yet). I'll play with requirejs a bit and see if I can figure anything out.

Shared models/collections

Hi,

I post here my question because I think your answers will surely help someone else one day. It is a basic workflow which could be taken as an example for beginners I guess. Let's expose my question.

The example

Say, I've got a list of cars on my page. And when I click on a car, I see the information about the car displayed in an other part of my page and I can edit this information. Then, imagine I changed the name, so I want the row corresponding to the car being updated to display its new name.

My thought and the issue

First thought, it's easy when I update a model his own view is re-rendered! Issuer: Which architecture for this example... What I thought first was to develop two separate widgets:

  • The first one representing the list of cars
  • The second one to display the car details and edit it
    I wanted to build it like this because I read in the backbone preview written by addy osmani that each model should be in charge for a well defined job.

The first widget listen on the click and publish a message to the second one by passing in parameters the model "Car". But, here is the problem, the second widget doesn't know the model "Car" because it is defined in the first widget. And require this model by passing a weird reference such as "../my-first-widget/models/car" isn't good, because each widget should be able to live by his own.

Some other thoughts

I don't know which good architecture I should set up in this case:
1 - Set the whole first widget as a dependence of the second one?

2 - Make two widgets having both a model Car but the first one having (for instance), the name, and the second one, the name, the year, the constructor, the owner name. And when a car is edited, tell the first widget to refresh its whole list of cars.

3 - Make only one widget, and the second widget should only be another view of Car that I should display on my page when a car is clicked.

What are your advices?

ps: I really agree with @addyosmani and @dustinboston to say that the Todo example is too simple. It is good too understand the links between the scripts and the communication intra-widget, but not enough complex to being able to set up an architecture for a big project.

How to share collection

If i have one collection that uses many widgets, how correctly share this collection.

Sample:

Task menu (Wdiget?):

Review
In Progress
Done

Task list(Widget)
#1 Task name
#2 Task name
#3 Task name

Detailed view(Widget)

  • Task name
  • Description
  • created at

When in task list i click on "#2 Task name", i must render detailed view widget.
How correctly organize this code.

Thx.

Integrating the DOM-library (jquery, zepto, etc)

One way to make jquery more easily replaceable, is to reference jquery with a more generic name, like dom or something similar.
This is the approach I'm currently using in my app, to be able to switch between jquery and zepto more easily.

First the config can be changed to something like this:

require.config({
    paths: {
        dom: 'aura/lib/jquery'
    }
});

You could then replace:

define(['jquery', 'underscore'], function ($, _) {
    // ...
});

With this:

define(['dom', 'underscore'], function ($, _) {
    // ...
});

Of course, this is a compile-time step, thus it's not adding the ability to change the dom-library in the runtime, which would be another feature.
Just thought I'd share the idea.

mediator publish function question

Hi there!

I was wondering about the publish function in mediator component.
This function iterates over the event's subsribers callbacks and executes them in sequence. My point is, if there are several subscribers for a single event and the first one's callback raises an error, I guess the rest of them won't be executed.
Is this so or am I missing something?

Thanks a lot for this brilliant work.

Idea: Media events

From the discussion with @dustinboston

  • Publish events on media change
  • E.g. when device is below 400px wide, trigger an even that tells the calendar to go into agenda mode
  • Could be based on matchMedia.js

What is the software license which covers Aura ?

Hello,

i want to use some of this library in another project, but i need to make sure the license agreement is in alignment. What is the software license you are using to cover this project ?

Cheers,
David

Logging capability

Hi,

I think it would be very nice if we can see what module publish/listens what events. Since Aura uses facade in between module and mediator, I think it is possible to make this happen.

I know that we can simply open each js files then check source codes, but it's just painful, especially working in a team environment with a lot of modules.

I've been using my own mediator in the following way.

Mediator.getOwnerOf("event name"); // returns owner of the event
Mediator.getListenersOf("event name") // returns listeners (modules) who listerns $eventanem
Mediator.getEventMapOf("module") // returns what $module listens and publishes.

Is there a plan for such feature?

Overextended modules

So I've really been having a problem with the models and collections in the aura-example. Circular dependencies, deferred hell, overly complex code, etc. It prompted me to go back and re-watch Nicholas Zakas' Scalable JavaScript Application Architecture presentation yet again. A couple of key points really stood out to me this time around:

  • Data is generally owned by a specific module. If another module needs that data the owner can send it to the mediator and then the mediator can distribute it out as needed.
  • If there is some data that is more general it can come from the application core and be exposed through a sandbox. I'm guessing something like user data, session info, and configs.

That combined with the principle that "any single module should be able to live on its own" got me re-thinking the way aura-example is structured.

I'm wondering if our example really isn't big enough. Everything we're doing currently centers around Todos. Sounds kind of like a single module. @addyosmani, you mentioned this sometime ago, and now I think I'm coming into agreement with you. Nicholas cites weather, stocks, and more. All very different types of data which correspond to different types of modules.

If we assume that Todos are just one Aura module, what would the mediator look like? I think pretty much the same. Same with the facade except that each module could possibly have its own instance of it. So then each AMD module within the Aura module includes the sandbox to get the functionality it needs like DOM manipulation, event handling, and AJAX. There is most likely a single entry point into that Aura module which, I think, would also be the one responsible for registering the Aura module with the core (mediator).

Just a side note: I think I get confusing because of the mixed terminology. To set the record straight, I'm proposing that we use many AMD modules to construct a single Aura module. I am using sandbox/facade interchangeably. Also I am using mediator/core interchangeably.

Seems a hell of a lot simpler to implement than my current approach. It also looks a lot like ender.js, but better because it provides an abstraction layer for all of the different APIs. Thoughts?

De-fuglify with Bootstrap

Update HTML/CSS to use Bootstrap. @addyosmani Shall we integrate LESS and use the build step to generate the .css files? Or do you just want to stick with the pre-baked versions from le Twitter?

facade.extend

Is there a facade.extend function example available that alters variables inside the module?

I'm not entirely sure if it is possible, but in my opinion you could respond to a channel inside a module with the facade.extend right?

I would love to start/stop/filter the module with this facade.extend but I can't seem to get this to work. A little code example would be dearly appreciated!

(im working with the new-version -- version)

Undefinded error when channel is missing in permissions

TypeError: rules[channel] is undefined

In https://github.com/addyosmani/backbone-aura/blob/master/src/aura/permissions.js#L26
var test = rules[channel][subscriber];

It happens when widget name is not added to permissions config and widget tries to subscribe to any event using sandbox.subscribe method. Of course we can add empty object just to avoid issue. In my opinion this could be simplified by returning false when there is no channel declaration in permissions config.

Hard time to build

Hey @addyosmani!

I got some errors while trying to build aura, not sure if everyone is going through the exact same, that's why I'm not trying to patch anything.

First error was on the lint task (on events.js, app.js and todos.js). But that's just a matter of minor adjustments in the files, so I didn't worry about it โ€” just removed the lint task from the grunt build and ran it again. Than I got:

Error: Cannot find module 'jsdom'

So I ran npm install jsdom in the same folder and ran grunt build again. Than I got:

Error: Cannot find module 'xmlhttprequest'

So I ran npm install xmlhttprequest in the same folder and ran grunt build again. Than I got:

RequireJS optimizer started

node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Error: ENOENT, no such file or directory '/Users/gerson/Dropbox/Sites/backbone-aura/demo-build/js/ext/mediator.js' In module tree:

The app seem to be working just fine, but I don't understand this error. I wish I could help better and give a solution, but it will take me a while until I wrap my mind around all the RequireJS thing...

some questions and comments

I have some questions and comments about backbone-aura 0.8 developer preview.

  1. You placed every library in the lib directory expect require and require.text - is there a reason for that?
  2. I assume you used the name widgets because it fits your example but in a different use case this directory would not only contain widgets. You and Nicholas C. Zakas always talk about modules not widgets. I think it would be more understandable if you'd use the name modules instead of widgets.
  3. The same applies to facade and sandbox - the file is named facade.js and the alias sandbox.
  4. At the moment the example application is part of the whole project. It would be nice to have two parts: aura + example
  5. In the readme it says: "Widgets represent a complete unit of a page" - In my opinion the stylesheet should also be a part of that unit.
  6. What are the benefits of the permission-layer?
  7. The permissions get extended by simply using the extend function. Why not having the same ability on the mediator and facade? You could also get rid of the Object.create function in app.js.
  8. Why is there an alias for facade.start / -stop for the widget (facade.widget.start / -stop)?
  9. It's probably a bit early but it would be nice to have the ability to configure and customize aura with a configuration.
  10. There might be commonly used or inter-module models, collections, views, etc. in a project. How would you solve that?

That's it for now.
Thanks for the nice work and keep it up :-)

inter module communication

The major confusing point to me is between module communication. My previous understanding was - there are modules, that are absolutely independent each of other. The only one way to notify about something is to publish an event. They can subscribe to / publish on through mediator object.

Say, I have 2 modules - chat and message hub. Chat is basically backbone view, that is reposible for rendering messages. Message hub is module responsible for receiving and sending events.

Previously, I thought that mediator is responsible for providing functionality of Pub / Sub in aura architecture. With the latest changes, I can see it's not.

Some very simplified code,

// Chat
define(['core'], function (core) {
core.subscribe('chat', function () {
// create view here etc..

     // somewhere inside the view..
     core.subscribe('message/recieved', function () { });

});
});

// Message Hub

define(['core'], function (core) {
core.subscribe('hub', function () {
// somewhere is message recieve handler
core.publish('message/recieved', { messsage: data } );
});
});

But now, Mediator (or it's wrapper Facade) publish and subscribe methods has a different meaning. Publish is starting up widget and call it's subsriber function. The code like core.publish('message/recieved' ... ) will fail, since now it is expected 'widgets/message/recieved.js' module is expected. I think publish/subscribe loosing it's previous meaning.. now it's more like start / onStarted methods, as for me.

In my opinion aura now have a drawback that it does not demonstrate inter module communication which we can see in real life.

modified source files with requirejs2.0?

is there a good reason to use the modified source files (backbone,underscore) instead of the shim feature of requirejs2.0?

this makes it harder for anyone to use a different version of backbone (especially master)

Is there a way to compress all the js files into one file?

Hi,

I just tested out Aura and I really like it. One of my minor concerns is that requirejs optimizer simply compressed all the js files instead of generating one single js file.

Is this intended or is it going to be added in the near future?

Coding standard: Keep /* global */ jslint config in files?

Hi, was passing by and saw oppurtunity to make a pull, but wanted to step back and get a take on this.

Since we're using grunt configuration for handling jslint, we're set to allow for require, define, etc.

As a matter of consistency moving forward, should we include jslint comments at the top of backbone-aura files? It's missing on some, included on others, and outdated in other places.

Best
T

Project rename

We've discussed for a while the idea of renaming the project to Aura, eventually moving the Backbone-Aura extension part of it to a separate repo or just leaving it in the repo as a plugin of some sort.

As GitHub don't promise to handle redirects, renaming this repo would mean breaking links to articles pointing at backbone-aura, but otherwise should be okay. Anyone against this change?

missing var statement

Hi Addy,

First thanks for sharing this, nice work.
Just wondering, on line 130 of the aura/mediator.js file you are using a variable named 'key' without declaring it:

obj.unload = function(channel){
        var contextMap = requirejs.s.contexts._.urlMap;
        for (key in contextMap) {
            if (contextMap.hasOwnProperty(key) && key.indexOf(channel) !== -1) {
                require.undef(key);
            }
        }

    };

Shouldn't that be ?

obj.unload = function(channel){
        var contextMap = requirejs.s.contexts._.urlMap, key;
        for (key in contextMap) {
            if (contextMap.hasOwnProperty(key) && key.indexOf(channel) !== -1) {
                require.undef(key);
            }
        }

    };

Cheers

delete subscribers on aura mediator.stop?

Should the aura mediator.stop delete subscribers? - if you .start / .stop / .start the same widget it will have 2 duplicate subscribers.

    obj.stop = function(channel){

        var args = [].slice.call(arguments, 1),
            el = args[0],
            file = obj.util.decamelize(channel);

        // Remove all modules under a widget path (e.g widgets/todos)
        obj.unload("widgets/" + file);

        // Empty markup associated with the module
        $(el).html('');

    };

Shouldn't all subscribers be cleared aswell?

delete channels[channel]

maybe an prettier obj.unsubscribe fn instead :-)

Widget disposal

Is this enough for disposing a widget?

// Remove all modules under a widget path (e.g widgets/todos)
obj.unload("widgets/" + file);

// Empty markup associated with the module
$(el).html('');

what about unbinding events? Why is better to use $(el).html('') instead of $(el).remove() to remove the DOM nodes?
I've seen other frameworks, such as Chaplin or Marionette, having more sophisticated object disposal techniques.
Maybe I'm not understanding the full framework workflow here.

Esteban.

Aura heavily bound with RequireJS + others... why?

As title says... why aura is so tight bound with RequireJS and jQuery and Underscore?

For example, the pup/sub technique that mediator uses shouldn't be bound so tight with RequireJS module autoloading and DOM selection as it is now, of course these are very useful, but only for those who use jquery + requirejs but thing is that not everyone uses (at least the second...).

I prefer to keep the following as the very basic example of mediator/facade pattern with permissions intermediate:

//==== Mediator Pattern
var channels = {};
var mediator = {};

mediator.subscribe = function (channel, subscription) {
  if (!channels[channel]) channels[channel] = [];
  channels[channel].push(subscription);
};

mediator.publish = function (channel) {
  if (!channels[channel]) return;
  var args = [].slice.call(arguments, 1);
  for (var i = 0, l = channels[channel].length; i < l; i++) {
    channels[channel][i].apply(this, args);
  }
};

//=== Permissions 
var permissions = {
  endContentEditing:{
    todoSaver:true,
    testing : true
  }
};

permissions.validate = function(subscriber, channel){
  var test = permissions[channel][subscriber];
  return test===undefined? false: test;
};

//=== Facade Pattern
var facade = facade || {};

facade.subscribe = function(subscriber, channel, callback){

  if(permissions.validate(subscriber, channel)){
    mediator.subscribe( channel, callback );
  }
}

facade.publish = function() {
  args = [].slice.apply(arguments, [0, 2]); // first two arguments for mediator
  arguments = [].slice.call(arguments, 2); // Rest for facade

  mediator.publish.apply(mediator, args);
}


//=== Application Use Case
facade.subscribe('todoSaver','endContentEditing', function (context) {
  try {
    console.loger('todoSaver');
  } catch (e) {
    console.log('todoSaver f**** up!');
  }
});

facade.subscribe('testing','endContentEditing', function (context) {
  console.log('testing');
});

facade.publish('endContentEditing', {
  test : 'test!'
});

Sharing Widget Data

Howdy,

Apologies if "Issues" isn't the right place for a question. If there's a better place to post, please let me know.

If two Aura widgets require same data, how should widget2 get widget1's data?

For example, let's say that the example project has a fourth "Feed" widget that displays a list of todos.

In Aura, how should the feed widget get the todos data?

  • Via mediator message?
  • Via separate collections defined in /widgets/feed/collections/ and /widgets/todos/collections/ ?
  • Via define(['sandbox', '../todos/collections/todos.js'], function(sandbox,Todos){})?
  • Something else?

Thanks!

Adam

Language file

@addyosmani Just wanted to see what your thoughts regarding i18n are. It's not currently needed for our Aura because we're just throwing errors, but I think it would be great to expose a single nls file through the mediator/facade.

AMD+Opera

Hi, Addy!

I tried to check if it works in Opera 11.60.. and it seems that it doesn't:-( Do you know why?

The best way to package an aura project

What would be the best way to package a large aura project with grunt?

  1. Optimize the "facade/core/dom/underscore/backbone" parts in an app-build.js file and then still require widgets (maybe also optimize each widgets deps to 1 main.js file).
  2. Same as (1) but wrap all widgets in one widgets-build.js file.
  3. One big app-build.js with both core and all widgets.

Any input is appreciated :-)

Aura V1

I think it would be useful to discuss what should land in V1. We of course need docs and some more complete tests, but I'd be interested in hearing whether there are more features Aura should come with.

Some ideas:

  • Better widget/module memory management. Are we sure we're clearing all event handlers, DOM elements etc and can we confirm these efforts actually reduce the memory required by the page/widgets?
  • Should Aura be framework agnostic? Now that we've split up the demo into Aura, a Backbone extension and the demo I'm wondering whether we should put effort into getting Aura working with other frameworks.
  • Remove AMD dependency for Aura itself? I'm wondering whether the core Aura library (mediator, facade etc) should be offered as a non-AMD script that contains all three components that can just be dropped into a project. We can continue demonstrating the demo project with AMD but would just have Aura pulled in once rather than in three parts. Thoughts?
  • It was suggested that we should support dynamic loading of the CSS of a widget so that all dependencies are separate from each other. There are of course some browser-quirks that could make this challenging. Should we explore this idea?.

Any other ideas or comments on the above?

@dustinboston @rudolfrck @gersongoulart

Write README.md files for sub-directories as applicable.

It is really nice to have sub-dir READMEs in a project. When browsing on Github, it makes for an excellent supplemental narrative documentation. Aura is already aiming to be documentation heavy, but it is also appropriate to heavily document a project like this for educational purposes.

Rename Aura Files

I think we should rename the aura files mediator.js to core.js and facade.js to sandbox.js as well as the main objects returned within these files (just like @addyosmani was going to do inside the single-file version). The reason is that, although it's important to know and understand which Js patters are being used (and that should still be explicit through the comments within the files), auras files (and objects returned) should be named after the functionality they're providing to the framework, not the technic adopted.

Idea: Prefetch/suspend

  • A widget can publish an event that will begin prefetching another widget
  • The widget will be loaded in a "suspended" state, meaning it's started but not displayed
  • A navigation widget could trigger an event to suspend several widgets and start others

@dustinboston when you get a chance would be great to get this idea expanded on :)

Idea: Route events

From the last catch-up @dustinboston and I had about the project:

  • Routes that publish events
  • For example, a navigation widget gets clicked, modifies URL, e.g. /about
  • Route responds to URL change by publishing an event

base lib abstraction

I'm not sure if you are aware of that:
If you want so switch the base lib, the interfaces of the sandbox (dom, utils, events, etc.) should be abstracted. I saw some cases where you referenced to the mediator which referenced the base lib's function directly (utils.extend = $.extend, etc.). Like that your widget code might not work if you switch the base library. But this can be avoided using proper abstraction in the sandbox.

Integrate Offline support

I'd like to integrate first class support for offline into Aura, something similar to:

https://github.com/Ask11/backbone.offline

At present, whilst offline isn't strictly a part of the originally planned architecture I strongly feel that there are advantages to giving developers the ability to use this out of the box.

To summarize: the way this works is that when a connection is no longer available we start syncing using local datastores (e.g localStorage), re-syncing with a server when a connection comes back.

Coding conventions

Coding conventions discussion based off #22, #81, #82. Making a stub for this.

We should make a wiki page to document decisions we have made throughout previous issues.

So far this includes:

  • Use of 2 spaces over tabs
  • Idiomatic.js concepts, unless objections in certain instances
  • Multiple var's in variable declarations
  • add anything else to a wiki page.

Some things to be discussed:

  • 'use strict'; vs "use strict"; per @sindresorhus on #82. 'use strict'; is valid and single quotes are clearer (see http://ecma262-5.com/ELS5_HTML.htm#Section_14.1).
  • Usage of new lines should be handled in context of the code at hand, but #82 does list a few newlines general approaches we can adhere to.
  • Not exhaustive, feel free to bring up anything else not listed here at anytime)

Uncaught TypeError: object is not a function

Hi. I have just downloaded aura and tried the new version in Google Chrome (it works in IE 9). Whenever I hit Eneter to create new todo item, I'm getting an error: Uncaught TypeError: object is not a function.
Here's the stack:

Uncaught TypeError: object is not a function
c.extend._prepareModelbackbone-optamd3-min.js:224
c.extend.createbackbone-optamd3-min.js:206
facade.subscribe.donemodules.js:75
obj.publishmediator.js:18
Backbone.View.extend.createOnEnterapp.js:72
f.event.dispatchjquery-min.js:1183
f.event.add.h.handle.ijquery-min.js:1103

Thank you.

Fix breaking build

Would you mind taking a look at this, @joelhooks ? I've been going through Travis CI trying to figure out where the build broke and everything seems to point to #71 and #72 being the culprits. Reverted those changes and applied some other minor changes but it still appears broken.

http://addyosmani.com/gyazo/0a8d.png

(It may be something very minor. I've been experiencing some npm issues this morning preventing me from running builds locally so any help would be appreciated)

example of facade.publish?

Just curious to see an example with facade.publish :)

EDIT:
I'm asking because I believe that facade.publish method should look more like this:

facade.publish = function() {
  mediator.publish.apply(mediator, arguments);
}

instead of this:

facade.publish = function(channel){
    mediator.publish( channel );
}

just want to confirm it :)

EDIT2:
Of-course we could also have something like this:

facade.publish = function() {
  args = [].slice.apply(arguments, [0, 2]); // first two arguments for mediator
  arguments = [].slice.call(arguments, 2); // rest for facade

  mediator.publish.apply(mediator, args);
}

since we expect mediator to get only two args we could pass first two args from facade and the rest will be used from facade if they needed.

In that way we will be using only Facade in our app and we won't call facade and mediator as it is now in the examples, so facade will invoke with mediator (since this is more logic as it is facade's role to invoke with private/hidden stuff).

Should publish call start and inter-module communication

The mediator has two sets of functions that do a completely different thing:

  • subscribe/publish for inter-module communication
  • start/stop for loading/unloading of modules

I don't think those two should have anything in common.

The way it is today, when you publish something, say 'todos' in the example application, the application will load the todos widget. Also, sandbox.publish('todos', '#todosapp'); has the same effect as sandbox.widgets.start('todos', '#todosapp');.

I tried to make the calendar widget publish an event to say to everyone that a new event was created and make the todo widget add a new todo when this happens and made it only by changing a lot of stuff. You can see it on my branch here. There is still one thing that is not working: if you stop a widget, all its callbacks for the events should be cleared.

I am not sure I am doing the right think here but I was unable to find a way for modules to communicate (publish events and others to receive that event).

Update to new RequireJS errbacks

We currently have an outstanding TODO in mediator.js to switch over to the new error callbacks (errbacks). Below is a sample from the RequireJS docs on how this would work.

Notice that the errbacks are used from within your config and seem to best work where you know explicitly where you want to define a fallback for locally loading something, unloading the module you previously tried loading if it failed for whatever reason.

requirejs.config({
    enforceDefine: true,
    paths: {
        jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min'
    }
});

//Later
require(['jquery'], function ($) {
    //Do something with $ here
}, function (err) {
    //The errback, error callback
    //The error has a list of modules that failed
    var failedId = err.requireModules && err.requireModules[0],
    if (failedId === 'jquery') {
        //undef is function only on the global requirejs object.
        //Use it to clear internal knowledge of jQuery. Any modules
        //that were dependent on jQuery and in the middle of loading
        //will not be loaded yet, they will wait until a valid jQuery
        //does load.
        requirejs.undef(failedId);

        //Set the path to jQuery to local path
        requirejs.config({
            paths: {
                jquery: 'local/jquery'
            }
        });

        //Try again. Note that the above require callback
        //with the "Do something with $ here" comment will
        //be called if this new attempt to load jQuery succeeds.
        require(['jquery'], function () {});
    } else {
        //Some other error. Maybe show message to the user.
    }
});

Here is our current custom variation of this:

    require.onError = function (err) {
        if (err.requireType === 'timeout') {
            console.warn('Could not load module ' + err.requireModules);
        } else {
            // If a timeout hasn't occurred and there was another module
            // related error, unload the module then throw an error
            var failedId = err.requireModules && err.requireModules[0];
            require.undef(failedId);
            throw err;
        }
    };

which simply unloads a module if it fails.

What benefits do we gain from switching to the proper form of errbacks? Its clearer to the user how to specify local fallbacks? Keep in mind that such fallbacks will have to be defined by widget authors.

//cc @dustinboston

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.