conflict dojo.require and Socket.io client - javascript

I use dojo 1.8.6 and socket.io 0.9.16, after I load socket.io.js client, dojo.require conflict is happened and no more dojo module can load.
require([ 'socket.io/socket.io' ]) cause error.
TypeError: Cannot read property 'push' of undefined
I can't use "dojox/socket" for some reason.
Anybody have any idea?

As of dojo 1.11 the following is working fine:
packages: [
"dojo",
{name: "socketio", location: "/socket.io", main: "socket.io"}
]
with module loading:
define([
"socketio"
], function (socketio) {
var socket = socketio();
});
I assume its working in prior versions as well but i have not tested it.
Alternatively you could directly refer to the socket.io module as it is AMD compliant.
define([
"/socket.io/socket.io.js"
], function (socketio) {
var socket = socketio();
});
Unfortunately the builder does still report an 311 error (missing dependency) hence not breaking the build. Can't work around this as there is no package.js where to mark as copy only...

The require statement needs to be a valid AMD mid (module identifier).
Usually, people will add the package to their config, e.g.:
var dojoConfig = {
packages: [
{name: 'socketio', location: 'path/to/socket.io/socket.io'}
]
}
and then require it:
require(['socketio'], function (socketio) {
// do something with socketio
});
As far as why you cannot use dojox/socket, I don't see any code to comment on. You might also want to check out https://github.com/bryanforbes/tube , which is a draft of a replacement for dojox/socket.

Related

Magento 2: moment is not defined

I'm trying to use the Shipping Time JS plugin on my Magento 2 website, it requires both moment.js and jQuery in order to work however it's not working. I'm getting a ReferenceError: moment is not defined in shiptime.js on line 49 which is the following:
try {
if (moment === undefined || $ === undefined ) throw Error("please include jquery & moment.js");
} catch (e) {
console.log(e);
}
==============
My require.js
This is what my requirejs-config.js looks like, it's sitting in app/design/frontend/##/##/requirejs-config.js:
var config = { // eslint-disable-line no-unused-vars
packages: [{
name: 'momentjs',
location: 'js/',
main: 'moment'
}],
map: {
'*': {
'menu': 'Magento_Theme/js/disable-menu',
'shippingtime': 'js/shiptime'
}
},
shim: {
'momentjs': {
deps: ['jquery']
},
'shippingtime': {
deps: ['jquery',',momentjs']
}
}
};
jQuery is loaded elsewhere and is definitely being loaded (I have various other jQuery libraries which are all working).
==============
Debugging
I initially thought the moment.js/shiptime.js files weren't being loaded in however they are when I check both the source and the network panel. To further test this, I did the following to see if moment.js would output anything:
require(['momentjs'], function (moment) {
console.log(moment().format('LLLL'));
});
This does output the date in the console so moment.js is definitely loading, this is my code for the shiptime.js file which isn't working and gives me the error I mentioned above:
require(['jquery', 'shippingtime', 'momentjs'], function (moment) {
jQuery(document).ready(function () {
jQuery(function($) {
jQuery('.shipping-time').shipTime();
});
});
});
Any advice would be greatly appreciated!
It's been a while since I've worked with requirejs but since no one smarter has chimed in yet I'm happy to help you keep troubleshooting. Using jQuery with requirejs can be tricky, especially with a large and complex platform like Magento.
Without being able to see all of your code I would consider and investigate the following:
Are you initializing jQuery properly in a no-conflict way if necessary
Are you using require() vs. define() where and as intended
Are you versed in the challenges unique to Magento when using requirejs
Have you reviewed and followed the recommendations regarding the complexities of using moment with requirejs
Here is some corresponding reading on each:
On No-Conflict
require() vs define() plus other good insights
On Magento 2 with RequireJS
On complexities of Moment and RequireJS
https://momentjs.com/docs/#/use-it/require-js/
https://github.com/requirejs/requirejs/issues/1554#issuecomment-226269905
One last thing to try:
In your final code example you pass moment to the function but not jQuery. Have you tried something along these lines:
require(['jquery', 'momentjs', 'shippingtime'], function($, moment) {
$(document).ready(function() {
$('.shipping-time').shipTime();
});
});

require.js require a module with index.js

So I'm trying to set up Typescript and Chutzpah for testing purposes. Typescript is set up to output in this format:
define(['require', 'exports', './someModule'], function(require, exports, someModule) {
//examplecode
});
Which works fine, the problem occurs when someModule is actually a directory with an index.js.
/app
app.js
/someModule
index.js
require.js is unable to resolve someModule in this way and the test fails.
Is there any way to tell require.js that this is a module?
RequireJS won't automatically check for the presence of index.js and load that as your module. You need to tell RequireJS that when you want to load someModule, it should load someModule/index. I'd set a map in my call to require.config:
require.config({
[ ... ]
map: {
'*': {
someModule: 'someModule/index',
}
},
});
You have to adjust the name you give there so that it is a path relative to your baseUrl. It's not clear from the information you give in your question what it should be.
(For the record, there's also a packages setting that you could probably tweak to do what you want but putting something packages says "this is a package", which is not what you appear to have here. So I would not use it for what you are trying to do.)
I didn't like the configuration in map either. The most simple way I accomplished this was writing a plugin for require.
Let's name the plugin mod, where it is to be used as mod!module/someModule, you can also call it index as in index!module/someModule, whatever suits you best.
define(function(require, exports, module) {
// loading module/someModule/index.js with `mod!`
var someModule = require('mod!module/someModule');
// whatever this is about ..
module.exports = { .. };
});
So lets assume you have paths set in require's configuration with some sort of project structure:
- app
- modules
- someModule/index.js // the index we want to load
- someModule/..
- someModule/..
- etc
- plugins
- mod.js // plugin to load a module with index.js
Requires config:
require.config({
paths: {
'module': 'app/modules',
// the plugin we're going to use so
// require knows what mod! stands for
'mod': 'app/plugins/mod.js'
}
});
To read all the aspects of how to write a plugin, read the docs at requirejs.org. The simplest version would be to just rewrite the name of the requested "module" you are attempting to access and pass it back to load.
app/plugins/mod.js
(function() {
define(function () {
function parse(name, req) {
return req.toUrl(name + '/index.js');
}
return {
normalize: function(name, normalize) {
return normalize(name);
},
load:function (name, req, load) {
req([parse(name, req)], function(o) {
load(o);
});
}
};
});
})();
This is not production code, it's just a simple way to demonstrate that requires config wasn't meant to solve problems like this.

Loading: long, ByteBuffer and ProtoBuff with requirejs

Working on a project that gets its content with ProtoBuff. Made it work once with the loading of the JavaScripts in the HTML. Now refactoring to use requirejs to load the scripts. But when I try to use the scripts, it gives an error telling me the scripts are not loaded.
Require.js is loaded in the index.html
Bower is used to manage dependencies.
I am pretty sure I am missing a (simple) thing here, hope some one can help.
requirejs.config({
long : "long",
ByteBuffer : "ByteBuffer",
ProtoBuf : "ProtoBuf"
});
requirejs([ "long", "ByteBuffer", "ProtoBuf" ],
function( long, ByteBuffer, ProtoBuf ) {
}); ​
the files long.js, ByteBuffer.js and ProtoBuf.js are all in the same map as the App.js, where this is called.
*While this question about requirejs and ByteBuffer looks promising, I think I am missing something here.
This does work, the functions in those files are accessible within the rest of the scope:
requirejs([ "otherPage", "differentPage" ],
function( util ) {
});
You need to make sure you have requirejs hooked up correctly and that you have the relevant proto library loaded.
You can use bower to manage dependencies. Install bower and
bower install long byteBuffer protobuf requirejs-text requirejs-proto
The final code can then look something like this:
require.config({
paths: {
'Long': '../../bower_components/long/dist/Long',
'ByteBuffer': '../../bower_components/byteBuffer/dist/ByteBufferAB',
'ProtoBuf': '../../bower_components/protobuf/dist/ProtoBuf',
'text': '../../bower_components/requirejs-text/text',
'proto': '../../bower_components/requirejs-proto/proto'
},
proto: {
ext: 'proto',
convertFieldsToCamelCase: false,
populateAccessors: true
}
});
require(['proto!test'], function(builder) {
var pack = builder.build('pack');
var Message1 = builder.build('pack.Message1');
});
require(['proto!test::pack.Message1', 'proto!test::pack.Message2'], function(Message1, Message2) {
...
});
some code from https://www.npmjs.com/package/requirejs-proto

Why is Karma refusing to serve my JSON fixture (which I'd like to use in my jasmine / angularjs tests)

As indicated in this stackoverflow answer, it looks like Karma will serve JSON fixtures. However, I've spent too many hours trying to get it to work in my environment. Reason: I'm doing angular testing and need to load mock HTTP results into the test, as Jasmine doesn't support any global setup/teardown with mock servers and stuff.
In my karma config file, I'm defining a fixture as so:
files: [
// angular
'angular/angular.min.js',
'angular/angular-route.js',
'angular/mock/angular-mocks.js',
// jasmine jquery helper
'jquery-1.10.2.min.js',
'angular/jasmine-jquery.js',
// our app
'../public/js/FooApp.js',
// our tests
'angular/*-spec.js',
// fixtures
{ pattern: 'node/mock/factoryResults.json',
watched: 'true',
served: 'true',
included: 'false' }
]
Before I even attempt to use jasmine-jquery.js in my jasmine test to load the JSON, I see karma choking on trying to serve it:
...
DEBUG [web-server]: serving: /Users/XXX/FooApp/spec/node/mock/factoryResults.json
Firefox 25.0.0 (Mac OS X 10.8) ERROR
SyntaxError: missing ; before statement
at /Users/XXX/FooApp/spec/node/mock/factoryResults.json:1
...
Here's what factoryResults.json looks like:
{ "why": "WHY" }
Any idea what's going on here? I see plenty of examples on the web of folks successfully loading JSON into jasmine tests via karma fixtures. Karma can see the file; if I put the wrong path in my fixture block, I see an error stating that it couldn't find any files that match my fixture pattern. I've tried reformatting the .json file in different ways... Any ideas?
Your problem is that 'false' has to be a boolean, not a string.
There is already an issue to validate the config better and fix such a mistakes.
Also, you might write a simple "json" preprocessor (similar to karma-html2js) that would make it valid JS and put the JSON into some global namespace so that you can keep the tests synchronous...
I also needed json fixtures in my karma test suite.
I ended up just using the html2js preprocessor with json files as well as html.
karma.conf.js:
module.exports = function (config) {
config.set({
frameworks: ["jasmine"],
files: [
'**/*.js',
'**/*.html',
'**/*.json',
'**/*.spec.js'
],
plugins: [
'karma-html2js-preprocessor'
]
preprocessors: {
'**/*.html': ['html2js'],
'**/*.json': ['html2js']
}
});
};
Then it is just a matter of getting the json from the __html__ global.
e.g.
var exampleJson = __html__['example.json'];
var jsonObj = JSON.parse(exampleJson);
var exampleHtml = __html__['example.html'];
document.body.innerHTML = exampleHtml;
So, I had a lot of issues with jasmine-jquery and I got a pretty decent workaround.
It's a little hacky, but it works. Basically, I just create a function accessible on the window, then stack the JSON fixtures inside a little switch:
if (typeof(window.fixtures === "undefined")) {
window.fixtures = {};
}
window.setFixture = function(type) {
var json;
if (type == "catalog") {
json = { ... }
}
if (typeof(type) !== "undefined") {
window.fixtures[type] = json;
}
return json;
}
Then, I can just stub it inline in the view:
describe "App.Models.Catalog", ->
it "provides the 'App.Models.Catalog' function", ->
expect(App.Models.Catalog).toEqual(jasmine.any(Function))
it "sets up a fixture", ->
setFixture("catalog")
console.log(fixtures["catalog"])
expect(fixtures["catalog"]).toBeDefined()
Boom, tests pass, and the object comes out in the log:
{
catalog_id: '2212',
merchant_id: '114',
legacy_catalog_id: '2340',
name: 'Sample Catalog',
status: '1',
description: 'Catalog Description ',
}
Now, it's accessible within my test.
It's of course not perfect or ideal, but I kept hitting strange matchErrors and the like with the jasmine-jquery plugin, and it's simple enough (and fast) for me to paste in a couple of JSON blocks and get moving.
You also save yourself the time fiddling around with the configuration and making any changes to the files for Karma.
Anyone have any better suggestions or have any luck getting jasmine-jquery to work?

RequireJS plugin: load timeouts experienced when using plugin

Using RequireJS I'm building an app which make extensive use of widgets. For each widget I have at least 3 separate files:
request.js containing code for setting up request/response handlers to request a widget in another part of my application
controller.js containing handling between model and view
view.js containing handling between user and controller
Module definition in request.js:
define(['common/view/widget/entity/term/list/table/controller'],
function(WidgetController) { ... });
Module definition in controller.js:
define(['common/view/widget/entity/term/list/table/view'],
function(WidgetView) { ... });
Module definition of view.js is:
define(['module','require'],function(module,require) {
'use strict';
var WidgetView = <constructor definition>;
return WidgetView;
});
I have lots of these little situations as above in the case of widgets I have developed. What I dislike is using the full path every time when a module is requiring another module and both are located in the same folder. I'd like to simply specify as follows (assuming we have a RequireJS plugin which solves this for us):
define(['currentfolder!controller'],
function(WidgetController) { ... });
For this, I have written a small plugin, as I couldn't find it on the web:
define({
load: function (name, parentRequire, onload, config) {
var path = parentRequire.toUrl('.').substring(config.baseUrl.length) + '/' + name;
parentRequire([path], function (value) {
onload(value);
});
}
});
As you might notice, in its basic form it looks like the example of the RequireJS plugins documentation.
Now in some cases, the above works fine (e.g. from the request.js to the controller.js), but in other cases a load timeout occurs (from controller.js to view.js). When I look at the paths which are generated, all are proper RequireJS paths. Looking at the load timeouts, the following is logged:
Timestamp: 13-09-13 17:27:10
Error: Error: Load timeout for modules: currentfolder!view_unnormalized2,currentfolder!view
http://requirejs.org/docs/errors.html#timeout
Source File: http://localhost/app/vendor/requirejs/require.js?msv15z
Line: 159
The above log was from a test I did with only loading the view.js from controller.js using currentfolder!view in the list of modules in the define statement. Since I only requested currentfolder!view once, I'm confused as to why I both see currentfolder!view_unnormalized2 and currentfolder!view in the message.
Any idea as to why this might be happening?
My answer may not answer your primary questions, but it will help you achieve what you're trying to do with your plugin.
In fact, Require.js support relative paths for requiring modules when using CommonJS style. Like so:
define(function( require, exports, module ) {
var relativeModule = require("./subfolder/module");
module.exports = function() {
console.log( relativeModule );
};
});

Categories