The question is how do I fix the path issue for module1 as noted by the console log?
basic info - most recent versions of requirejs, underscore and jquery and are located in library
dir layout
library
templates
-default
--js
---lib.js
---module1.js
-scripts
--calendar
---module2.js
--jquery.alpha.js
--jquery.beta.js
-main.js
index.php
within index.php
<script>var Template="default/"</script> //todo convert to session
<script>var Domain="mygsd"</script> //todo convert to session
<script src="library/require.js/require.js" data-main="templates/main">
main.js
var templatejs = Template+'js/';
var scripts = 'scripts/';
require.config({
baseUrl:"templates/",
catchError: true,
paths: {
jquery: '//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min',
underscore: 'library/underscore',
libs:templatejs+'lib',
scripts: scripts,
},
shim: {
'jQuery': {
exports: '$'
},
'underscore': {
exports: '_'
}
}
});
require(['libs']);
define(["jquery", "scripts/jquery.alpha", "scripts/jquery.beta"], function($) {
$(function() {
$('body').alpha().beta();
});
});
libs.js
define([templatejs+'module1', scripts+"calendar/module2"], function(module1ref, module2ref){
var module1 = new module1ref(),
module2 = new module2ref();
console.log(module1.getName() === module2.getModule1Name());
});
module1.js
define([], function () {
var returnedModule = function () {
var _name = 'module1 name';
this.getName = function () {
return _name;
};
};
return returnedModule;
});
module2.js
define(['module1'], function (module1ref) {
var module1 = new module1ref();
var returnedModule = function () {
this.getModule1Name = function () {
return module1.getName();
};
};
return returnedModule;
});
console log
Completed load of main require.js (line 1531)
Loading jquery from //ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js require.js (line 1650)
Loading scripts/jquery.alpha from templates/scripts//jquery.alpha.js require.js (line 1650)
Loading scripts/jquery.beta from templates/scripts//jquery.beta.js require.js (line 1650)
Loading libs from templates/default/js/lib.js require.js (line 1650)
Completed load of scripts/jquery.alpha require.js (line 1531)
Completed load of scripts/jquery.beta require.js (line 1531)
Completed load of libs require.js (line 1531)
Loading default/js/module1 from templates/default/js/module1.js require.js (line 1650)
Loading scripts/calendar/module2 from templates/scripts//calendar/module2.js require.js (line 1650)
Completed load of default/js/module1 require.js (line 1531)
Initializing default/js/module1 require.js (line 1662)
Completed load of scripts/calendar/module2 require.js (line 1531)
Loading module1 from templates/module1.js require.js (line 1650)
Completed load of jquery require.js (line 1531)
Initializing jquery require.js (line 1662)
Initializing scripts/jquery.alpha require.js (line 1662)
Initializing scripts/jquery.beta require.js (line 1662)
Initializing main require.js (line 1662)
"NetworkError: 404 Not Found - http://local:81/mygsd/templates/module1.js" module1.js
Since module1's path is not correct in module2, I got the default/backup path.
It should have been:
define([templatejs + 'module1'], function (module1ref){
var module1 = new module1ref();
var returnedModule = function (){
this.getModule1Name = function (){
return module1.getName();
};
};
return returnedModule;
});
BTW Thanks to the bonehead who took the time to -1 the question instead of answering it.
Related
I try to implement ActionTest with old way asset pipeline (without Webpack) on rails 6
Almost all is good, except loading of #rails/actiontext
in my application.js I've
//= require trix
//= require #rails/actiontext
The riche editor appear, I can change bold/italic text, but can't add image (not uploaded)
I've an JS error : Uncaught SyntaxError: Cannot use import statement outside a module
on line : import { AttachmentUpload } from "./attachment_upload" from attachment_uplaod.js in actiontext.
Any way to achieve this without webpack?
thanks
I don't know what will be the official way, but I did it this way as I'm waiting for an updated install generator:
Prerequisites
hotwire-rails
CSS
Copy the CSS file in your asset pipeline (https://github.com/basecamp/trix/tree/main/dist)
JS Libraries
In app/assets/javascripts/libraries create these two files
Updated content may be found on https://www.skypack.dev
// app/assets/javascripts/libraries/actiontext#6.1.4.js
export * from 'https://cdn.skypack.dev/pin/#rails/actiontext#v6.1.4-znF92tREya92yxvegJvq/mode=imports/optimized/#rails/actiontext.js';
export { default } from 'https://cdn.skypack.dev/pin/#rails/actiontext#v6.1.4-znF92tREya92yxvegJvq/mode=imports,min/optimized/#rails/actiontext.js';
// app/assets/javascripts/libraries/trix#1.3.1.js
export * from 'https://cdn.skypack.dev/pin/trix#v1.3.1-EGGvto9zyvcAYsikgQxN/mode=imports/optimized/trix.js';
export { default } from 'https://cdn.skypack.dev/pin/trix#v1.3.1-EGGvto9zyvcAYsikgQxN/mode=imports,min/optimized/trix.js';
Import through Stimulus
In app/assets/javascripts/controllers create this file
//app/assets/javascripts/controllers/trix_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
connect() {
import("actiontext").catch(err => null)
import("trix").catch(err => null)
}
}
On pages where trix/action_text should be loaded, add a data-controller="trix" to the relevant div
And voilĂ !
https://github.com/rails/rails/issues/41221#issuecomment-871853505
Got Action Text working by copying the actiontext scripts into a custom file, and removing the imports and exports.
And second, you will need to require activestorage in your application.js to make use of DirectUpload.
application.js
//= require trix
//=# require #rails/actiontext
//= require activestorage
//= require actiontext
actiontext.js
// Copied from node_modules/#rails/actiontext/app/javascript/actiontext/attachment_upload.js
class AttachmentUpload {
constructor(attachment, element) {
this.attachment = attachment;
this.element = element;
// Requires `require activestorage` in application.js
this.directUpload = new ActiveStorage.DirectUpload(
attachment.file,
this.directUploadUrl,
this
);
}
start() {
this.directUpload.create(this.directUploadDidComplete.bind(this));
}
directUploadWillStoreFileWithXHR(xhr) {
xhr.upload.addEventListener("progress", event => {
const progress = (event.loaded / event.total) * 100;
this.attachment.setUploadProgress(progress);
});
}
directUploadDidComplete(error, attributes) {
if (error) {
throw new Error(`Direct upload failed: ${error}`);
}
this.attachment.setAttributes({
sgid: attributes.attachable_sgid,
url: this.createBlobUrl(attributes.signed_id, attributes.filename)
});
}
createBlobUrl(signedId, filename) {
return this.blobUrlTemplate
.replace(":signed_id", signedId)
.replace(":filename", encodeURIComponent(filename));
}
get directUploadUrl() {
return this.element.dataset.directUploadUrl;
}
get blobUrlTemplate() {
return this.element.dataset.blobUrlTemplate;
}
}
// Copied from node_modules/#rails/actiontext/app/javascript/actiontext/index.js
addEventListener("trix-attachment-add", event => {
const { attachment, target } = event;
if (attachment.file) {
const upload = new AttachmentUpload(attachment, target);
upload.start();
}
});
This still uses ES6 syntax, so if you want to support older browsers and aren't using Babel, you might want to rewrite or transpile this to ES5.
I am using Webpack 2 in my project to transpile and bundle ReactJS files along with a few other tasks. Here's what my config looks like:
var webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
var config = {
module: {
loaders: [
{
exclude: /(node_modules)/,
loader: "babel-loader",
query: {
presets: ["es2015", "react"]
}
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ["css-loader", "sass-loader"]
})
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({ mangle: false, sourcemap: false }),
new ExtractTextPlugin({
filename: "../../public/dist/main.css"
})
],
};
var indexConfig = Object.assign({}, config, {
name: "index",
entry: "./public/javascripts/build/index.js",
output: {
path: __dirname + "/public/dist",
filename: "index.min.js",
},
});
var aboutConfig = Object.assign({}, config, {
name: "about",
entry: "./public/javascripts/build/about.js",
output: {
path: __dirname + "/public/dist",
filename: "about.min.js"
},
});
// Return Array of Configurations
module.exports = [
indexConfig, aboutConfig
];
As evident, I am using multiple build configurations for JS, one for each page. Now, I need to add some Bootstrap JS to the mix for which I also need JQuery and Tether. Thus, I have the following 3 files in my library folder:
jquery-3.2.1.min.js
tether.min.js
bootstrap.min.js
I need these 3 files to be concatenated and bundled along with the main JS files being emitted by Webpack (e.g., index.min.js, etc.). To do so, I modified my entry item thus:
entry: {
a: "./public/javascripts/lib/jquery-3.2.1.min.js",
b: "./public/javascripts/lib/tether.min.js",
b: "./public/javascripts/lib/bootstrap.min.js",
c: "./public/javascripts/build/index.js"
}
However, doing so throws the following error:
ERROR in chunk a [entry]
index.min.js
Conflict: Multiple assets emit to the same filename index.min.js
ERROR in chunk b [entry]
index.min.js
Conflict: Multiple assets emit to the same filename index.min.js
ERROR in chunk c [entry]
index.min.js
Conflict: Multiple assets emit to the same filename index.min.js
Obviously this is because Webpack is expecting multiple output files for multiple entry items. Is there any way to overcome this problem? An existing question illustrating a similar problem doesn't seem to have any acceptable answer at the moment.
UPDATE:
Tried using the Commons chunk plugin as suggested by terales, but Webpack threw the following error this time:
ERROR in multi jquery tether bootstrap
Module not found: Error: Can't resolve 'jquery' in '/home/ubuntu/panda'
# multi jquery tether bootstrap
ERROR in multi jquery tether bootstrap
Module not found: Error: Can't resolve 'tether' in '/home/ubuntu/panda'
# multi jquery tether bootstrap
ERROR in multi jquery tether bootstrap
Module not found: Error: Can't resolve 'bootstrap' in '/home/ubuntu/panda'
# multi jquery tether bootstrap
ERROR in chunk vendor [entry]
index.min.js
Conflict: Multiple assets emit to the same filename index.min.js
Your libs shouldn't be entries. They called "vendors" in Webpack's terms.
See minimum working example repo.
In your code you should implicitly extract common vendor chunk:
var config = {
entry: { // <-- you could make two entries
index: './index.js', // in a more Webpack's way,
about: './about.js' // instead of providing array of confings
},
output: {
filename: '[name].min.js',
path: __dirname + '/dist'
},
module: {
loaders: [
// Fix error 'JQuery is not defined' if any
{ test: require.resolve("jquery"), loader: "expose-loader?$!expose-loader?jQuery" },
]
},
plugins: [
// this assumes your vendor imports exist in the node_modules directory
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
return module.context && module.context.indexOf('node_modules') !== -1;
}
})
]
};
I am working with the yo meanjs boilerplate from here :yo meanjs.
I know I can create my own module using $ yo meanjs:angular-module <module-name> .
Is it possible to install and inject into my controller ng-flow using yo from the command line?
Something like : $ yo meanjs:ng-flow <module-name>
In the documentation it states found here meanjs modules: So unless there are any better suggestions I might try this route.
To add third-party modules use the public/config.js file where we added an array property called applicationModuleVendorDependencies. When you add a new third-party module you should add it to this array so the main module can load it as a depenedency.
'use strict';
// Init the application configuration module for AngularJS application
var ApplicationConfiguration = (function() {
// Init module configuration options
var applicationModuleName = 'theconnect';
var applicationModuleVendorDependencies = ['ngResource', 'ngCookies', 'ngAnimate', 'ngTouch', 'ngSanitize', 'ui.router', 'ui.bootstrap', 'ui.utils'];
// Add a new vertical module
var registerModule = function(moduleName, dependencies) {
// Create angular module
angular.module(moduleName, dependencies || []);
// Add the module to the AngularJS configuration file
angular.module(applicationModuleName).requires.push(moduleName);
};
return {
applicationModuleName: applicationModuleName,
applicationModuleVendorDependencies: applicationModuleVendorDependencies,
registerModule: registerModule
};
})();
After adding module via cmd line using :
bower install "ng-flow#~2" --save
grunt bower-install
I added it as as dependency to public/config.js :
var applicationModuleVendorDependencies = ['ngResource', 'ngCookies', 'ngAnimate', 'ngTouch', 'ngSanitize', 'ui.router', 'ui.bootstrap', 'ui.utils','flow'];
then added the module path to the all the JS files under the /config/env directory.
module.exports = {
db: process.env.MONGOHQ_URL || process.env.MONGOLAB_URI || 'mongodb://' + (process.env.DB_1_PORT_27017_TCP_ADDR || 'localhost') + '/theconnect',
assets: {
lib: {
css: [
'public/lib/bootstrap/dist/css/bootstrap.min.css',
'public/lib/bootstrap/dist/css/bootstrap-theme.min.css',
],
js: [
'public/lib/angular/angular.min.js',
'public/lib/angular-resource/angular-resource.js',
'public/lib/angular-cookies/angular-cookies.js',
'public/lib/angular-animate/angular-animate.js',
'public/lib/angular-touch/angular-touch.js',
'public/lib/angular-sanitize/angular-sanitize.js',
'public/lib/angular-ui-router/release/angular-ui-router.min.js',
'public/lib/angular-ui-utils/ui-utils.min.js',
'public/lib/angular-bootstrap/ui-bootstrap-tpls.min.js',
'public/lib/ng-flow/dist/ng-flow.js'
]
},
css: 'public/dist/application.min.css',
js: 'public/dist/application.min.js'
},
......
...
}
Fabii's answer is helpful. To add to it...
I had to make 2 entries in the "all.js" file Fabii mentioned (which is located at /config/env/all.js
'public/lib/flow.js/dist/flow.min.js',
'public/lib/ng-flow/dist/ng-flow.js'
I am trying to write a gulp task that does a few things
Install the Bower dependencies
Concat those dependencies into one file in the order of the dependencies
I was hoping to do this without having to specify the paths to those dependencies. I know there is the command bower list --paths but I am unsure of if it is possible to tie it together.
Any thoughts?
Edit
So I am trying to use the gulp-bower-files and I am getting an eaccess error and its not generating the concatenated file.
gulpfile.js
var gulp = require('gulp');
var bower = require('bower');
var concat = require('gulp-concat');
var bower_files = require('gulp-bower-files');
gulp.task("libs", function(){
bower_files()
.pipe(concat('./libs.js'))
.pipe(gulp.dest("/"));
});
bower.json
{
"name": "ember-boilerplate",
"version": "0.0.0",
"dependencies": {
"ember": "1.6.0-beta.1",
"ember-data": "1.0.0-beta.7"
}
}
and I keep coming across this error
events.js:72
throw er; // Unhandled 'error' event
^
Error: EACCES, open '/libs.js'
Use main-bower-files
It grabs all production (main) files of your Bower packages defined in your project's bower.json and use them as your gulp src for your task.
integrate it in your gulpfile:
var mainBowerFiles = require('main-bower-files');
I made this task that grabs all production files, filters css/js/fonts and outputs them in the public folder in their respective subfolders (css/js/fonts).
Here's an example:
var gulp = require('gulp');
// define plug-ins
var flatten = require('gulp-flatten');
var gulpFilter = require('gulp-filter'); // 4.0.0+
var uglify = require('gulp-uglify');
var minifycss = require('gulp-minify-css');
var rename = require('gulp-rename');
var mainBowerFiles = require('main-bower-files');
// Define paths variables
var dest_path = 'www';
// grab libraries files from bower_components, minify and push in /public
gulp.task('publish-components', function() {
var jsFilter = gulpFilter('**/*.js');
var cssFilter = gulpFilter('**/*.css');
var fontFilter = gulpFilter(['**/*.eot', '**/*.woff', '**/*.svg', '**/*.ttf']);
return gulp.src(mainBowerFiles())
// grab vendor js files from bower_components, minify and push in /public
.pipe(jsFilter)
.pipe(gulp.dest(dest_path + '/js/'))
.pipe(uglify())
.pipe(rename({
suffix: ".min"
}))
.pipe(gulp.dest(dest_path + '/js/'))
.pipe(jsFilter.restore())
// grab vendor css files from bower_components, minify and push in /public
.pipe(cssFilter)
.pipe(gulp.dest(dest_path + '/css'))
.pipe(minifycss())
.pipe(rename({
suffix: ".min"
}))
.pipe(gulp.dest(dest_path + '/css'))
.pipe(cssFilter.restore())
// grab vendor font files from bower_components and push in /public
.pipe(fontFilter)
.pipe(flatten())
.pipe(gulp.dest(dest_path + '/fonts'));
});
I was attempting to run the listed gulpfile and ran into a couple errors. First gulpFilter.restore is not a function, and secondly if you plan on restoring the filtered files you need to pass {restore: true} when you define your filters.
Like so:
// gulpfile.js
var mainBowerFiles = require('main-bower-files');
var gulp = require('gulp');
// define plug-ins
var flatten = require('gulp-flatten'),
gulpFilter = require('gulp-filter'),
uglify = require('gulp-uglify'),
minifycss = require('gulp-minify-css'),
rename = require('gulp-rename'),
mainBowerFiles = require('main-bower-files');
// Define paths variables
var dest_path = 'www';
// grab libraries files from bower_components, minify and push in /public
gulp.task('publish-components', function() {
var jsFilter = gulpFilter('*.js', {restore: true}),
cssFilter = gulpFilter('*.css', {restore: true}),
fontFilter = gulpFilter(['*.eot', '*.woff', '*.svg', '*.ttf'], {restore: true});
return gulp.src(mainBowerFiles())
// grab vendor js files from bower_components, minify and push in /public
.pipe(jsFilter)
.pipe(gulp.dest(dest_path + '/js/'))
.pipe(uglify())
.pipe(rename({
suffix: ".min"
}))
.pipe(gulp.dest(dest_path + '/js/'))
.pipe(jsFilter.restore)
// grab vendor css files from bower_components, minify and push in /public
.pipe(cssFilter)
.pipe(gulp.dest(dest_path + '/css'))
.pipe(minifycss())
.pipe(rename({
suffix: ".min"
}))
.pipe(gulp.dest(dest_path + '/css'))
.pipe(cssFilter.restore)
// grab vendor font files from bower_components and push in /public
.pipe(fontFilter)
.pipe(flatten())
.pipe(gulp.dest(dest_path + '/fonts'));
});
After the changes mentioned it ran perfectly. :)
I'm using AngularJS in a Ruby on Rails 3.2.8 project with assets.
When I load up my form which is using AngularJS on my development machine I don't have a problem. However when I load the same form up on my production server I get this error in the Javascript console:
Error: Unknown provider: aProvider <- a
I've tracked it back to my coffeescript file where I setup AngularJS for use within a form:
$ (event) ->
$("#timesheet_description").autocomplete({source: '/autocomplete/work_descs'})
# Create AngularJS module
app = angular.module 'timesheetApp', []
# Create a AngularJS controller
app.controller "TimesheetCtrl", ($scope) ->
$scope.costed_amount = 0
# Bind my module to the global variables so I can use it.
angular.bootstrap document, ["timesheetApp"]
If I comment all this out the page will load without errors and without AngularJS abilities.
Is the problem due to Rails assets compiling and minify?
Is there a way to fix this and still use coffeescript and Rails assets?
AngularJS, when using the style you're using right now (called pretotyping), uses the function argument names to do dependency injection. So yes, minification does break this completely.
The fix is simple, though. In every case where you need injection (are using '$xxx') variables, do this:
app.controller "TimesheetCtrl", ['$scope', ($scope) ->
$scope.costed_amount = 0
]
Basically, replace all function definitions with an array. The last element should be the function definition itself, and the first ones are the $names of the objects you want injected.
There's some more (albeit not clear enough) info on the docs.
If you miss the array notation somewhere , to locate this we need to modify the angular code little bit, but its very quick solution.
change is console.log("Array Notation is Missing",fn); ( line no 11 from function start)
Find out annotate function in angular.js (non-minified)
function annotate(fn) {
var $inject,
fnText,
argDecl,
last;
if (typeof fn == 'function') {
if (!($inject = fn.$inject)) {
$inject = [];
if (fn.length) {
console.log("Array Notation is Missing",fn);
fnText = fn.toString().replace(STRIP_COMMENTS, '');
argDecl = fnText.match(FN_ARGS);
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
arg.replace(FN_ARG, function(all, underscore, name){
$inject.push(name);
});
});
}
fn.$inject = $inject;
}
} else if (isArray(fn)) {
last = fn.length - 1;
assertArgFn(fn[last], 'fn');
$inject = fn.slice(0, last);
} else {
assertArgFn(fn, 'fn', true);
}
return $inject;
}
To minify angular all you need is to do is to change your declaration to the "array" declaration "mode" for example:
From:
var demoApp= angular.module('demoApp', []);
demoApp.controller(function demoCtrl($scope) {
} );
To
var demoApp= angular.module('demoApp', []);
demoApp.controller(["$scope",function demoCtrl($scope) {
}]);
How to declare factory services?
demoApp.factory('demoFactory', ['$q', '$http', function ($q, $http) {
return {
//some object
};
}]);