cujojs / wire Goto Github PK
View Code? Open in Web Editor NEWA light, fast, flexible Javascript IOC container
License: Other
A light, fast, flexible Javascript IOC container
License: Other
This is trivial to add, but seems extremely powerful. It will allow, among other things, functions in pipelines like "doThis | thenThat | thenTheOther" to return promises.
They probably need to be refactored to make them fit better with the new doc structure as well.
Even though the use cases are more limited, sometimes injecting the wire function itself can be very useful.
Adding RingoJS support should be relatively simple since it uses a CommonJS module loader, and wire doesn't really need any additional APIs.
Hi,
first of all great job putting this module together, it really does open up lots of cool scenarios and possibilities.
I was wondering if you could suggest what is your idea for integrating wire.js to be run within Node.js. Do you plan on using the requirejs for Node?
It would be awesome to be able to use wire.js in node!
Thanks
create a new transform function that combines replaceClasses with mapTokenList.
create (or modify existing) transform that allows the node to be passed at run time instead of new css state
Hi,
I apologize in advance for filing a bug to ask a question. But is there a way I can prevent caching of modules with wire.js + curl.js? The specific case I have is this:
templateText: {
create: {
module: 'text!/template.html'
}
}
This templateText module loads my Backbone templates up, which then other components use. I've found that this template.html file gets cached in chrome. Is there an easy way to prevent caching of all resources during development?
Thanks,
Noah
It seems like we end up writing this a lot, and the most common use case is probably fetching the first match
{ $ref: 'dom.query!.whatever', i:0 }
So let's add dom.first!
that automatically resolves to the first match, rather than to a nodelist of 1 item. It can take advantage of any selector-specific optimizations, such as :first
, too.
As a nice parallel, let's add dom.all!
which will be a synonym for dom.query!
... and maybe we should deprecate dom.query!
When using the create
factory to beget instances from objects (aka "constructor-less components"), you tend to end up with components whose type is Object
, which is not helpful during debugging, since you typically have to expand the object and visually duck-type it to know what it is. After some quick tests in modern WebKit and FF, it is possible to set constructor
to a function with a useful name on those objects that don't already have a constructor
. We could make when/debug do this in a "reasonably safe" way to help with debugging.
Just wondering if it makes sense to add clone() functionality to the proxies. This would allow us to create a "standard" clone factory to wire. For the node proxy, the clone method would call node.cloneNode(true). I imagine we'd need to provide a way for a dev to use cloneNode(false), although I've never seen a use case for this.
I have not thought much about cloning javascript objects. If I were to write this, I'd check out dojo.clone to see what they do! :)
Hello, I'm also trying to use AMD/DI in our production system and ran into an issue wiring two specs together and the passing of the object. Details of the project are we are using backbone, underscore, jquery, and now wire. I have an application spec which wires itself to another spec much like what happens in PirateScript for the ResultsView.
the child spec looks like this:
define({
plugins: [
{ module: 'wire/jquery'}
],
detailContainer: { $ref: '$!#var_detail' },
detailViewModel : {
create : "viewmodels/detail"
},
detailView: {
create: {
module: 'views/detail',
args: {
el: {$ref: 'detailContainer' },
viewModel: {$ref: 'detailViewModel'}
}
},
init: {
render: { $ref: 'data' }
}
}
});
And the is the parent spec that wires it (snippet):
cardsView : {
create : {
module: "views/cards",
args: {
el : {$ref: "$!#var_results"},
model : {$ref: "cardsCollection"}
}
},
properties : {
filterPanelModel : {$ref: "filterPanelModel"},
pageView : {$ref: "pageView"},
controller : {$ref: "controller"},
apiDog : {$ref: "apiDog"},
showCard: { wire: { spec: 'specs/detailspec', defer: true } }
}
},
So, the method in the cardsView object creates a backbone model, and is passed like this:
this.showCard({
data: model
});
Which works, and passes it fine... However, beforehand it is a backbone object but then the detail method render that receives it gets a different object, one without the proto attribute, chain. Backbone puts the methods you define in your Model.extend({ methods}) in that proto chain, so I'm basically losing those methods. I'm basically needing to find out how to pass this object and keep it exactly the same as it was passed from the client. I'm also wondering why it's being changed. Any help you can provide would be great! Thanks as well for this project, so much potential to change how people write their JS apps (coming from a Java, DI world, and really wanting DI in JS).
Thanks,
Chris
See the discussion in #15 about some of the pros and cons of relying on the AMD loader's domReady!
plugin, versus a domReady
module (if it provides one). Here's a summary:
domReady!
plugin can cause module loading to fail if DOMReady doesn't fire before the AMD loaders failure timeout (specifically, RequireJS, not sure if other loaders have an explicit failure timeout). Using domReady
as a module doesn't have this problem.domReady
module requires an AMD loader path config in every loader I've tried, unless you move it directly into baseUrl. Some loaders (e.g. curl) can automatically locate their domReady!
plugin without additional configuration.So, we need to figure out which is best for wire/domReady
RequireJS provides this - http://requirejs.org/docs/api.html#config-urlArgs
Being realistic, wire's design is based around component modularity, and currently to use wire's full functionality, you need a module environment like AMD or CommonJS. It's possible to use wire via a browser script tag right now, but it's extremely limited, and seems like a dead end.
We should consider removing support for browser script tag and just requiring AMD or CommonJS, and other module systems such as Harmony in the future.
But I want to open this discussion up in case there are wire users out there who are currently using it via script tag, to make sure we consider all the angles, and those folks have a chance to be heard.
Let's say I've got parent context containing a module M, and 2 child contexts c1 and c2 either of which is wired dynamically at runtime. Each of c1/c2 has its own decorator implementation d1/d2.
Not sure if I'm missing something but It would be nice if M could be decorated with the appropriate d1 or d2 depending on which of c1 or c2 got wired.
Ta!
Andy.
I'm trying to put together a project using wire.js at the moment, and I'm at the situation where I need to be able to pass some literals (mainly DOM IDs) into the loaded spec.
The scenario is that the JS app being constructed by Wire.js is an application that can be embedded on other people's sites. As such, the name of DOM elements be referenced will be different each time.
I'd like to keep my application code clean and not include any global variable references, I'd like to pass everything in via the proxy wrapper that sits between the site and the application code (and which sets up Curl, calls wire.js, etc)
The code for retrieving the IDs of the DOM elements already exists in the wrapper code, I just need some way of getting that into the spec.
Any way of constructing a child context and passing it in as a string rather than having it loaded by the AMD loader?
I just tried to upgrade to the latest version of wire.js, and I get a load timeout on my wire spec (context-common in my example). The context-common.js file is indeed being loaded by the browser according to chrome's network tab. Swapping in the old wire.js fixes the issue. Any ideas on what I may be missing with the new version of wire.js?
In chrome:
Uncaught Error: Load timeout for modules: wire!/a/context-common
http://requirejs.org/docs/errors.html#timeout
req.onErrorrequire.js:1524
checkLoadedrequire.js:958
(anonymous function)
Because of the order of promise resolution, the child's "Context ready" is output before the parent's. The actual order in which things happen seems to be correct, but the output seems backwards.
The reason is that the parent can't finish until all it's components have resolved. Given that the child spec is one of the components, it makes sense that the child's promise would resolve first. On the other hand, a child can't be wired until its parent has finished!
This is definitely a tricky situation, but need to figure out if it it's actually happening, and if it causes any problems.
The root node passed to W3C querySelector
and querySelectorAll
will never be matched by the selector
. This has tripped up one user already, so we should document it.
Given something like the following in a wire spec using the Dojo pubsub plugin:
thing1: {
create: "test/pubsub1/Thing",
properties: {
name: "Thing 1",
logger: { $ref: 'logger' }
},
publish: {
"doSomething": "thing/did-something",
"doSomethingElse": "thing/did-something-else"
}
}
Invocations of both the doSomething
and doSomethingElse
methods result in publishing to the thing/did-something-else
topic. This is due to a subtle closure error in the pubsub plugin here:
https://github.com/cujojs/wire/blob/dev-080/dojo/pubsub.js#L38
Relative module ids are a big problem in general, but an even bigger problem in node, since there's no path or package re-mapping (as there is in AMD). We need a way to allow a wire spec to be wired using the require()
that is relative to the wire spec itself. Ideally, we can come up with something that works in both node and AMD.
Here's one possible thought--explicitly providing the local require()
in a wire spec via a special component name, such as $require
:
// UMD
(function(define) {
define(function(require) {
return {
$require: require
// ... more components
}
});
})(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); });
While the AMD loader plugin (e.g. require(['wire!my/spec'])
) works with curl, requirejs, dojo, etc. loaders, the builder plugin currently only works with cram. Need to make that obvious. See also this requirejs issue
Need make the compose factory section simply point over to the composing functions section
It's only in dev right now, but proving to be very useful, and somewhat parallel to object creation/composition. It's also pretty tiny, so makes sense to move it to the core.
Add info to dom docs about the ability to get a reference to dom selector functions by using { $ref: 'dom.first!' }
, etc.
I am getting errors in my code with collections, sometimes when I go to populate collections with models the second time, for instance after a reset, the models can't be instantiated correctly. This bug has been challenging to track down, I've tested other code, but this happens about one time out of 20.
TypeError: '[object Object]' is not a constructor (evaluating 'new this.model(attrs, options)')
// Prepare a model or hash of attributes to be added to this collection.
_prepareModel: function(model, options) {
options || (options = {});
if (!(model instanceof Model)) {
var attrs = model;
options.collection = this;
model = new this.model(attrs, options);
if (!model._validate(model.attributes, options)) model = false;
} else if (!model.collection) {
model.collection = this;
}
return model;
},
activation~ 15:12:36:26 [FATAL] Error in (http://beta.inhbogo.com/activate/js/libs/requirejs_107/require.js) on line 1633 with message (Uncaught Error: Load timeout for modules: wire!specs/applicationContext
http://requirejs.org/docs/errors.html#timeout)
require.js:1633Uncaught Error: Load timeout for modules: wire!specs/applicationContext
although the spec is loaded by wire, and build it still complains, not sure if this goes here or at the require repo
Right now, it reports the error as if a component failed. Also, it may be good to reset the timeout each time the plugin receives a progress event--i.e. it still looks like wiring is making progress.
It'd be easy to make the standard create
syntax support what the prototype
factory does now, i.e. create
would just "Do the right thing". That'd be one fewer keyword in the core DSL, and one fewer to learn.
We were able to get this to fail with an exception on one machine, but not another, when there was a call to wire inside a domReady callback inside a factory plugin. The wire()
function given to plugins is special and operates within the current context. It's possible that the delay could cause the call to wire()
to happen after the context thinks it's done and frees some internal state that's needed by the delayed wire()
call.
The exception was that moduleLoadPromises
was null inside getModule()
, and moduleLoadPromises
is indeed set to null when the context thinks it is done wiring, so that seems like a smoking gun.
The workaround for now is to rely on wire's own domReady handling (e.g. if you need to resolve a dom reference) inside of plugins, rather than using a domReady module directly.
Right now, function pipelines are composed using compose()
in lib/functional, which is not promise-aware. We could (fairly easily) create a promise-aware version based on when.reduce()
. That'd allow any function in a pipeline to return a promise, and the pipeline would still work out.
This change would also allow the compose
factory to compose functions that return promises.
There would be a small perf hit, of course. The tradeoff is probably that all synchronous pipelines will be slightly slower (probably only noticeable if the pipeline is used in a tight loop), but async pipelines become possible.
Performance in async pipelines is likely to be completely dominated by the time of the async operations themselves, so I don't see any perf concerns there.
Seem like a good idea to me, and fits with wire's general "we handle the async for you" model, but want to see what others think.
I have an error in tv.js line 292. It's called from an init facet in my wire spec.
Here's a screenshot of my chrome console after the error is thrown (you'll want to zoom in).
You can see the first error is the one that was automatically generated by wire. Not helpful in this situation as it says nothing about line 292 in tv.js, and actually doesn't even print the error message.
Looking at the code in debug.js:
// TODO: Consider using stacktrace.js
// https://github.com/eriwen/javascript-stacktrace
// For now, quick and dirty, based on how stacktrace.js chooses the appropriate field
// If console.trace exists, use it, otherwise use console.error
logStack = typeof console.trace == 'function'
? function (e) { console.trace(e); }
: function (e) { console.error(e.stack || e.stacktrace || e.message || e); };
In my screenshot I manually executed both options for comparison. You can see that unhelpful option 1 is being chosen based on my chrome environment. In my case I really want e.stack to be called so I get a pointer to tv.js line 292.
We've found a few in the 0.9.0 docs, so can fix for 0.9.1
wire/aop
provides standard mixin functionality via introduce
, but that name isn't very Javascripty. Also, mixins are a common JS idiom for object composition, so it should probably just be in the core, rather than having to pull in wire/aop
.
Users who may be using ids on elements in templates (not recommended) may need to wait for those templates to be inserted into the dom before trying to access those elements.
The current implementation of $ref:"dom!id" doesn't allow the dev to specify a dependency. If we add support for the at
option, the dev could use that to specify a dependency.
This would also make it consistent with $ref:"dom.first!" and $ref:"dom.all!".
When I enable debug trace the wiring fails with error 'WIRING FAILED at created controller_app' for the following wire spec:
define
plugins: [ { module: 'wire/debug', trace:true } ]
controller_app: { module:'controller/app' }
I've tried different combinations of debug flags with no success and it's not obvious what I'm doing wrong, so any help is much appreciated.
Using wire v0.7.5 and correct debug.js AFAIK (there's no version number in the file).
Cheers!
For example, to load a child wire spec hosted at http://foo.bar/plugin/bop.wire
Ideally I'd be able to determine the child wire spec url at runtime rather than having to hardcode it in the parent wire spec.
The motivation is to allow my host app to dynamically load and run 3rd party plugins published on the internet, but without prior knowledge of them.
Currently, wire/base provides init
for running initializer methods on a component, but sometimes you need to run a method even later in the cycle. For example, after connect
is applied. Adding a ready facet that does the same thing as init
, only later, would be useful
Spurred on by info from @neonstalwart in this thread, we should revisit all the dojo plugins and update the dependencies to take advantage of the new finer grained modules in dojo 1.7.
The wire! plugin works great at load time, but does not help the build tool determine which modules to load. Actually, it does for cram.js, but not for other AMD tools such as RequireJS or dojo. Unfortunately, cram.js is several revs old and needs to be updated to work with curl.js 0.6.x.
This ticket is to track progress of cram-wire integration and/o any updates about wire working with other AMD build tools.
cc @lightsblue
Since the use of css as identity and state is a core theme in cujojs, and there is lots of useful stuff in wire/dom/transform, we should create a css plugin that makes it super-easy. As usual, the main hurdle will be designing the DSL.
Let me start by saying I'm very new to AMD and especially wire.js. So this may not be an issue at all, or may be more related to AMD loaders.
It seems that when I define a module, and it's loaded by wire.js and AMD loader, it's not possible to see when something goes wrong in the module code (e.g. an error in chrome or firebug console).
This can be reproduced by checking out the hello-wired.js project, and modifying js/hello-wired.js as follows:
...
HelloWired.prototype = {
// The sayHello method takes a message String and renders it to
// the DOM Node that was supplied to the constructor.
sayHello: function(message) {
nonExistantVar++; // I would hope to see a console or firebug error from this, or some other indication of the problem
this._node.innerHTML = "Hello! " + message;
}
};
...
See curl issues cujojs/curl#81 and cujojs/curl#82. There is no AMD standard for propagating module loading errors in a plugin, but curl.js has a require.reject(ex) method that can be used. If this isn't too hard to implement, we should make this work for curl.js users.
[update] AMD is adding a standard way to do this so this fix should apply to all conforming AMD loaders.
When 1.3.0 seems to be breaking wire 0.8, rolling back to When 1.2.0 fixes the problem.
wire( './context' )
Is giving me wire.js line:131 cannot call 'wire' on undefined
, it seems wireContext(rootSpec)
is returning a promise with the value of undefined for the root
object.
Hi,
I'm a senior developer with HBO and would like to follow up on an issue that was posted by a colleague of mine a while back in issue #33.
The application can be accessed here:
http://www.hbogo.com/activate/
We're puzzled why the application works on all other browsers but the 64bit version of IE8. The error message we're getting has been reported on Issue #33 here. Do you guys have any ideas what's preventing the application from functioning properly?
Thanks.
Regards,
Chin S. Huang
Senior Developer
HBO
wire/on breaks when given compose pipelines (e.g. func1 | func2 | handler). Needs to be fixed to bring it in line with all the other connectors.
@scothis and I both got tripped up by this. It seems that the wire/dojo/dom and wire/jquery/dom plugins should also support dom! resolution. This also makes it easier to switch.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.