knockout.mapping & Require.js bug - requirejs

So I am trying to integrate knockout.mapping.js with require.js. I have tried following this example.
Unfortunately, I keep on getting this error:
GET http://[url]/Scripts/app/contractor/ko.js 404 (Not Found)
Uncaught Error: Script error for: ko
I have set up following files:
app.index.js
requirejs.config({
"baseUrl": "../Scripts/app/contractor",
"paths": {
"app.index": "app.index",
"knockout": "//cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min",
"mapping": "//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.3.5/knockout.mapping",
"knockout.bindings": "../../lib/knockout.bindings",
"fu": "../../lib/jquery.fineuploader-3.8.0",
"s2": "../../lib/select2",
"jquery": "//code.jquery.com/jquery-latest.min",
"jqueryui": "//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min",
"moment": "../../lib/moment.min",
"toastr": "../../lib/toastr"
},
"shim": {
'mapping': {
deps: ['knockout'],
exports: 'mapping'
}
}
});
// Load the main app module to start the app
require(['knockout', 'mapping', "main.index"], function (ko, mapping, bs) {
ko.mapping = mapping;
alert('ko: ' + ko + ', mapping: ' + ko.mapping);
bs.run();
});
main.index.js
define(['knockout',
'mapping',
'indexViewModel'],
function (ko, mapping, indexViewModel) {
var
run = function () {
var vm = new indexViewModel();
ko.applyBindings(vm, document.getElementById('#contractor-home-view'));
};
return {
run: run
};
});
main.index.js is irrelevant at this point because the mapping is not loading properly. What am I doing wrong here?

Try making this in your .config
"shim": {
'knockout': {
exports: 'ko'
},
'mapping': {
deps: ['knockout'],
exports: 'mapping'
}
}

Related

riotjs route not working in requirejs

how can I use riot route with requirejs?
I know it has a js file for AMD that start with define but I can not use this in my project
requirejs.config({
baseUrl: '/static/front/js',
paths: {
jquery: [
'https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min',
'lib/jquery-3.2.1.min'
],
hammerjs: 'lib/hammerjs',
velocity: 'lib/materialize/velocity.min',
materialize: 'lib/materialize/materialize',
riot: 'lib/riot/riot',
route: 'lib/riot/route',
},
shim: {
'materialize': {
deps: ['jquery', 'hammerjs', 'velocity']
},
'riot': {
deps: ['materialize', 'route']
}
}
});
define([
'riot',
'route'
], function (riot, route) {
'use strict';
require(['view/all'], function () {
route.base("/"); // start router
route.start(true);
route('/..', function () {
alert('It Work!');
});
});
});
in require(['view/all'], function ()... I compile my tags by riot -w ./ ./all.js and edit that:
all.js:
define(['riot'], function (riot) {'use strict';
riot.tag2('component', '<h2>test</h2>', '', '', function(opts) {
this.on('mount', function(){
$('h2').html("change")
})
});
riot.tag2('mytag', '<h1>mytag</h1>', '', '', function(opts) {
});
});
and it work well, because when I call riot.mount('mytag') it works

require.js listener or callback

I am loading a 3rd party script that simply creates an overlay on a site it has been loaded onto. It works fine but sites using require.js seem to have intermittent issues I'm assuming with async loading some js files. Is there any type of callback or way to create a module in the DOM as sort of a listener to see if require.js is done loading?
I tried this but not even close:
define(function() {
alert('test');
return {};
});
and
define('myModule',
function () {
var myModule = {
doStuff:function(){
console.log('Yay! Stuff');
}
};
return myModule;
});
console.log(myModule);
I ended up just creating a secondary require.config file and loading the module with require if require is detected, seems to work fine.
if(typeof require === 'function') {
var base = 'http://' + someDomainVar;
function getJSTreeURL() {
var url = base + '/js/libs/jstree.min';
return url;
}
function getModuleURL() {
var url = base + '/module';
return url;
}
var reqTwo = require.config({
context: "instance2",
baseUrl: "instance2",
paths: {
'jq': 'http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min',
'jqTree': getJSTreeURL(),
'module': getModuleURL()
},
shim: {
'jq': {
exports: 'jq'
},
'jqTree': {
deps: ['jq'],
exports: 'jqTree'
},
'module': {
deps: ['jq', 'jqTree'],
exports: 'module'
}
}
});
reqTwo(['require', 'jq', 'jqTree'],
function(require, jq, jqTree) {
setTimeout(function() {
require(['module'],
function(module) {
console.log('loaded');
}
);
}, 0);
});

RequireJS - Manually bundling some libs together

I'm trying to migrate a site to use RequireJS to manage it's JS dependencies. Also I want to bundle some libs together.
Currently we are building a base.min.js that comprises underscore, jquery, bootstrap and backbone. They are used all over our site and thus it makes sense to serve them together.
Nevertheless, I think we should have logically the three libs separate by name, thus I have written the following require.config:
require.config({
baseUrl: '/s/js/libs',
paths: {
app: '../app', shims: '../shims'
},
map: {
'*' : {
// underscore, backbone, jquery and bootstrap are bundled
'underscore': '../base',
'backbone': '../base',
'jquery': '../base',
'bootstrap': '../base'
}
},
shim:{
'bootstrap': {
deps: ['jquery']
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'underscore': {
exports: '_'
},
'jquery': {exports: '$'}
}
});
I'm not using the data-main; but instead I'm requiring several things:
require(["jquery", "underscore", "backbone", "bootstrap", "../baseapp"],
function($){
// Next line fixes the bootstrap issue with double modals taken from:
// http://stackoverflow.com/questions/13649459/twitter-bootstrap-multiple-modal-error
$.fn.modal.Constructor.prototype.enforceFocus = function () {};
$('.modal').on('shown', function () {
$('input:text:visible:first, textarea:visible:first', this).focus();
});
$('#search').on('shown', function () {
$('#id_asf-text').focus();
})
require(['micro', 'csrf_xhr', 'locale']);
require(['app/routers']);
});
This however causes the error that $ is undefined.
The global window.$ is defined, but it seems that requirejs is not properly detecting it with the exports of my shims. Even if I do exports: 'window.jQuery' it does not work.
Is this a bug in RequireJS or there a bug in my code? Does map and shim play well together? Does RequireJS support my use case?
Update 2013-11-05
After a long debugging session, I have found that shims are recorded per "real" Module inside RequireJS; so if I just change my shim to be:
shim : {
'../base': {init: function() {return [$, _, Backbone]}}
}
I do get this array as the first argument to my callback. However I would like them to be exploded, i.e; have each of the returned values as arguments...
I thought that an internal map + paths would work. Like this:
var require = {
baseUrl: '/s/js/libs/',
paths: {
app: '../app',
shims: '../shims',
'base-underscore': '../base',
'base-backbone': '../base',
'base-jquery': '../base',
'base-bootstrap': '../base'
},
map: {
'*' : {
// underscore, backbone, jquery and bootstrap are bundled
'underscore': 'base-underscore',
'backbone': 'base-backbone',
'jquery': 'base-jquery',
'bootstrap': 'base-bootstrap',
}
},
shim:{
'base-bootstrap': {
deps: ['base-jquery'],
init: function() {return null}
},
'base-backbone': {
deps: ['base-underscore', 'base-jquery'],
init: function() {return window.Backbone;}
},
'base-underscore': {
init: function() {return window.Underscore;}
},
'base-jquery': {
init: function() {return $}
}
} // shims
};
Unfortunally, it does not. Now the error is: Uncaught Error: Load timeout for modules: base-underscore,base-backbone,base-bootstrap,../base... Notice base-jquery is not listed!
I have found a workaround, but involves a plugin. This is my current solution. On my HTML I have the following config (I changed to require = {...} idiom so that debugging would be easier):
var STATIC_URL = "/s/js/libs/";
var require = {
baseUrl: STATIC_URL,
paths: {
app: '../app',
shims: '../shims',
},
map: {
'*': {
'jquery': 'bundler!jQuery',
'bootstrap': 'bundler!',
'underscore': 'bundler!_',
'backbone': 'bundler!Backbone'
}
},
bundler: {url: '../base'}
};
The bundler.js plugin lies in my js/libs. This is the original CoffeeScript:
global = #
each = (ary, func) ->
if (ary)
i = 0
while i < ary.length and (what = ary[i]) and func(what, i, ary)
i += 1
getGlobal = (value) ->
if not value
value
g = global;
each value.split('.'), (part) ->
g = g[part]
g
define
load: (name, require, onload, config) ->
base = config.bundler?.url ? '../base'
require [base], () ->
if name? and name
value = getGlobal(name)
onload(value)
else
onload()
normalize: (name, norm) -> name
Probably there should be a way to do this without a bundler... I'll keep the question open for while, so that better answers might be provided.

RequireJS loading script file but the passed reference is undefined

I've got the following requireJS config. When trying to reference the package/ImagingX module I always get undefined even though I can see that the script has been loaded in firebug. If I move the js file in question into the baseUrl directory and remove package/ it works as expected.
What am I doing wrong?
window.requirejs.config(
{
baseUrl: '/Scripts',
paths: {
"jquery": "./jquery-1.7.1.min",
"jqx": "/Content/Plugins/jqWidgets",
"package" : "/Scripts/packages"
},
urlArgs: "bust=" + (new Date()).getTime(),
shim : {
'jqx/jqxcore': ['jquery'],
'jqx/jqxsplitter': ['jquery','jqx/jqxcore']
}
}
);
window.require(['jquery', 'layoutManager', 'container', 'package/ImagingX'],
function ($,lm,container,px) {
px.Focus();
$(document).ready(function () {
lm.Init(); // Sets up panes
container.Init(); //Set up the containers
});
});
Update 15/10/2012
I'm getting desperate to solve this issue now, I've stripped everything back to the basics so here is the new main file :
(function () {
requirejs.config({
paths: {
"packages": "packages"
}
});
require([
'packages/testmodule'
],
function (tm) {
alert(tm);
});
})();
And the module which is in a sub folder called packages.
define('testmodule',
function () {
alert("called");
return {
set : 'rar '
};
});
I can see the script loaded but it never gets executed, hence I never get a reference for it.
requirejs.config({
paths: {
//"jquery": "./jquery-1.8.2.min",
//"jqx": "/Content/Plugins/jqWidgets",
"templates": 'templates',
"text": "commonRequireJsModules/text",
"domReady": "commonRequireJsModules/domReady",
"packages" : 'packages/'
//'signalR': './jquery.signalR-0.5.3.min',
//'knockout': './knockout-2.1.0',
//'pubsub' : './pubsub'
}
//,urlArgs: "bust=" + (new Date()).getTime()
//,
//shim : {
// 'jqx/jqxcore': ['jquery'],
// 'jqx/jqxsplitter': ['jquery', 'jqx/jqxcore'],
// 'signalR': ['jquery'],
// 'pubsub' : ['jquery']
//}
});
The trailing slash on the packages path seems to have addressed the issue, in part with also removing the name in the define part of the module. So it now looks like
define(['deps'],function(deps){
});
Rather than
define('myMod',['deps'],function(deps){
});
Couple of things:
it seems strange to use window.require instead of just require
names in 'shim' must match names in 'paths', this is not the case, here
document.ready is done for free by require, no need to do it again
So: do you have any loading error in your JS console? Does it says a script is missing?
Here is a working require configuration, Router is in the same folder of this code:
require.config({
paths:{
'jquery':'lib/jquery.min',
'backbone':'lib/backbone.min',
'underscore':'lib/underscore.min',
'router':'Router'
},
shim:{
'backbone':{ deps:['jquery', 'underscore'] },
'router':{ deps:['backbone'] }
}
});
require(['router', 'jquery', 'underscore', 'backbone'],
function (Router) {
var router = new Router();
$('img').hide();
});
});
And the index.html:
<html>
<head>
<script data-main="assets/js/App.js" src="assets/js/lib/require.min.js"></script>
</head>
<body>...</body>
</html>

backbone.marionette + i18n + handlebars

Can some one post an example of combining these libraries together?
including the handler for the i18n and marionette.
Thanks
point backbone.marionette templates to compile hendlebars.
this can be done on your main.js:
Backbone.Marionette.TemplateCache.prototype.compileTemplate = function(rawTemplate) {
return Handlebars.compile(rawTemplate);
};
configure your app to use handlebars and i18n:
this can be done on your config.js:
require.config({
// Initialize the application with the main application file
deps: ["main"],
paths: {
libs: "../assets/js/libs",
plugins: "../assets/js/plugins",
// Libraries
jquery: "../assets/js/libs/jquery",
underscore: "../assets/js/libs/lodash",
backbone: "../assets/js/libs/backbone",
marionette: "../assets/js/libs/backbone.marionette",
handlebars: "../assets/js/libs/handlebars",
//plugins
text : "../assets/js/plugins/text",
i18n : "../assets/js/plugins/i18n",
},
config: {
//Set the config for the i18n
//module ID
i18n: {
locale: 'fr-fr'
}
},
shim: {
marionette: {
deps: ['backbone'],
exports: 'Backbone.Marionette'
},
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
handlebars: {
deps: [],
exports: "Handlebars"
}
}
});
use it on any of your modules:
define([
'jquery',
'underscore',
'backbone',
'marionette',
'handlebars',
'text!templates/template.html',
'i18n!nls/your_i18n_text'
],
function($, _, Backbone, Marionette, Handlebars, tmpl, msg) {
'use strict';
var mod = Backbone.Model.extend({
defaults: function() {
return {
feedUrl : "this is for test"
};
}
});
view = Backbone.Marionette.ItemView.extend({
template: Handlebars.compile(tmpl),
model: new mod(),
initialize: function() {
this.tmpl_data = msg;
if(msg && this.model)
this.tmpl_data = _.extend(this.model.toJSON(),msg);
},
render: function() {
var view = this;
$(this.el).html(this.template(view.tmpl_data));
return this;
}
});
});
this will fetch templates + i18n files and render
I use i18n-JS, which is everything-agnostic, so you can use it with any server-side framework (Ruby on Rails for me) and any Javascript template engine (Haml Coffee for me).
Here is an example:
%form.form-horizontal
.modal
.modal-header
%button{ class: 'close', data: { dismiss: 'modal' } } ×
%h3
= I18n.t(#property.get('name'), scope: 'data_sheets.properties')
.modal-body
- unless #property.get('editable')
%p= I18n.t('data_sheets.you_already_contributed_to_this_property')
So there is nothing to do about Backbone nor Marionette side.

Resources