less-plugin-autoprefix plugin with Gulp showing error - less

The less-plugin-autoprefixer plugin README says that, to use the plugin, you include this in your gulpfile.js:
var LessPluginAutoPrefix = require('less-plugin-autoprefix'),
autoprefixPlugin = new LessPluginAutoPrefix({browsers: ["last 2 versions"]});
less.render(lessString, { plugins: [autoprefixPlugin] })
.then(
Do they want me to put an open ended callback function here? I'm confused. I tried including just the first part:
var LessPluginAutoPrefix = require('less-plugin-autoprefix'),
autoprefixPlugin = new LessPluginAutoPrefix({browsers: ["last 2 versions"]});
and then called the plugin like this:
gulp.task('less', ['clean'], function() {
return gulp.src('app.less')
.pipe(less({
includePaths: ['less'],
plugins: [autoprefixPlugin] //***//
}))
.pipe(cssmin({keepSpecialComments: 0}))
.pipe(rename('app.full.min.css'))
.pipe(gulp.dest('../server/dist/'))
.pipe(filter('../server/dist/**/*.css'))
.pipe(reload({stream:true}));
});
But I receive the following error:
TypeError: Object #<Autoprefixer> has no method 'on'
at DestroyableTransform.Stream.pipe (stream.js:65:8)
at Gulp.<anonymous> (/Users/himmel/Sites/matt-mcdaniel.com/client/gulpfile.js:131:10)
I've included the necessary dependency, autoprefixer-core, what am I missing here?

The error was thrown for an unknown reason due to inclusion of:
var autoprefixer = require('autoprefixer-core');
After removing this, no error was thrown.
Additionally, including:
var LessPluginAutoPrefix = require('less-plugin-autoprefix'),
autoprefixPlugin = new LessPluginAutoPrefix({browsers: ["last 2 versions"]});
and
gulp.task('less', ['clean'], function() {
return gulp.src('app.less')
.pipe(less({
includePaths: ['less'],
plugins: [autoprefixPlugin] //***//
}))
.pipe(cssmin({keepSpecialComments: 0}))
.pipe(rename('app.full.min.css'))
.pipe(gulp.dest('../server/dist/'))
.pipe(filter('../server/dist/**/*.css'))
.pipe(reload({stream:true}));
});
was sufficient for my gulpfile to autoprefix on build, but did not autoprefix via BrowserSync during development.

Related

"orion" is undefined when integrating orion editor in dojo

I am new to dojo and I am trying to integrate orion editor(build downloaded from http://download.eclipse.org/orion/) in dojo but I get the error "orion" is undefined.
The code looks like below:
HTML file for placing editor
<div data-dojo-attach-point="embeddedEditor"></div>
A JS file
require([
"dojo/_base/declare",
"dijit/_WidgetBase",
"editorBuild/code_edit/built-codeEdit-amd",
"dijit/_TemplatedMixin",
"dojo/text!orionEditor.html"
], function(declare,_WidgetBase,
codeEditorAmd, _TemplatedMixin,template){
declare("orionEditor", [_WidgetBase,
_TemplatedMixin], {
templateString: template,
postCreate: function(){
var codeEdit = new orion.codeEdit();
var contents = '';
codeEdit.create({parent: this.embeddedEditor, contentType: "application/javascript", contents: contents}).
then(function(editorViewer) {
if (editorViewer.settings) {
editorViewer.settings.contentAssistAutoTrigger = true;
editorViewer.settings.showOccurrences = true;
}
});
}
});
});
The orion editor build is placed in editorBuild folder.
Standalone orion works fine - http://libingw.github.io/OrionCodeEdit/
When integrating with dojo I am not sure why orion is undefined.
Any help would be much appreciated.
If you want using orion name in amd module then it has to be defined as parameter in function passed as require's callback.
Check this guide - it has 2 solutions for using orion with amd modules.
Option 1 - define bundles once and use shorter name in all modules you need them:
require.config({
bundles: {
"editorBuild/code_edit/built-codeEdit-amd": ["orion/codeEdit", "orion/Deferred"]
}
});
require(
["orion/codeEdit", "orion/Deferred"],
function(mCodeEdit, Deferred) {
var codeEdit = new mCodeEdit();
var contents = 'var foo = "bar";';
codeEdit.create({parent: "embeddedEditor"/*editor parent node id*/})
.then(function(editorViewer) {
editorViewer.setContents(contents, "application/javascript");
});
});
Option 2 - nested require:
require(["editorBuild/code_edit/built-codeEdit-amd"], function() {
require(["orion/codeEdit", "orion/Deferred"], function(mCodeEdit, Deferred) {
var codeEdit = new mCodeEdit();
var contents = 'var foo = "bar";';
codeEdit.create({parent: "embeddedEditor"/*editor parent node id*/})
.then(function(editorViewer) {
editorViewer.setContents(contents, "application/javascript");
});
});
});
Note: you can replace mCodeEdit with any unique name (That wouldn't shadow other objects/modules)

Trying to get gulp notify to work and tell me things are running and updating

I am currently struggling to get gulp notify to display a success notification when I run my gulp watch command from terminal so that I know the command is running and the files have been compiled to the dist directory I have created.
I am very new to gulp and reading the docs on notify isn't 100% easy for me to understand or clear to me what I am doing wrong.
currently the code looks a bit like this...
var gulp = require('gulp'),
gutil = require('gulp-util'),
jshint = require('gulp-jshint'),
uglify = require('gulp-uglify'),
sass = require('gulp-sass'),
concat = require('gulp-concat'),
sourcemaps = require('gulp-sourcemaps'),
pump = require('pump'),
notify = require('gulp-notify'),
plumber = require('gulp-plumber'),
growl = require('growl'),
input = {
'sass': 'scss/**/*.scss',
'javascript': 'js/**/*.js'
},
output = {
'stylesheets': 'dist/styles',
'javascript': 'dist/javascript'
};
gulp.task('build-js', function() {
return gulp.src(input.javascript)
.pipe(sourcemaps.init())
.pipe(concat('test.js'))
//only uglify if gulp is ran with '--type production'
.pipe(gutil.env.type === 'production' ? uglify() : gutil.noop())
.pipe(sourcemaps.write())
.pipe(gulp.dest(output.javascript));
});
gulp.task('build-css', function() {
return gulp.src('scss/**/*.scss')
.pipe(sourcemaps.init())
.pipe(sass())
.pipe(sourcemaps.write())
.pipe(gulp.dest(output.stylesheets));
});
gulp.task('watch', function() {
notify("Watching for changes...").write('');
gulp.watch(input.javascript, ['jshint', 'build-js']);
gulp.watch(input.sass, ['build-css']);
.pipe(notify({
message: "Generated file: <%= file.relative %> # <%= options.date %>",
templateOptions: {
date: new Date()
}
}))
});
I've managed to get it working by changing the watch task to the following
gulp.task('watch', function() {
notify("Watching for changes...").write('');
gulp.watch(input.javascript, ['jshint', 'build-js']);
gulp.watch(input.sass, ['build-css']);
gulp.watch([
'dist/**/*'
]).on('change', function () {
notify("Files updated").write('');
});
});

How do I integrate PostCSS into Broccoli angular-cli Build?

It seems like this build script is running but the CSS that is output is not minified or auto prefixed. I am attempting to compile SASS, then run the output through Post CSS with Broccoli and the angular-cli. I figure maybe some ember-cli folks could help as well. What am I doing wrong?
The build outputs this in terminal:
Slowest Trees | Total
----------------------------------------------+---------------------
BroccoliTypeScriptCompiler | 1274ms
vendor | 502ms
PostcssFilter | 465ms
but the CSS is the same as if it were output from SASS, not Post CSS.
Here is my angular-cli-build.js:
'use strict';
/* global require, module */
const Angular2App = require('angular-cli/lib/broccoli/angular2-app');
const compileSass = require('broccoli-sass');
const compileCSS = require('broccoli-postcss');
const cssnext = require('postcss-cssnext');
const cssnano = require('cssnano');
const mergeTrees = require('broccoli-merge-trees');
const Funnel = require('broccoli-funnel');
const _ = require('lodash');
const glob = require('glob');
var options = {
plugins: [
{
module: cssnext,
options: {
browsers: ['> 1%'],
warnForDuplicates: false
}
},
{
module: cssnano,
options: {
safe: true,
sourcemap: true
}
}
]
};
module.exports = function(defaults) {
let sourceDir = 'src';
let appTree = new Angular2App(defaults, {
sourceDir: sourceDir,
sassCompiler: {
includePaths: [
'src/style'
]
},
vendorNpmFiles: [
'systemjs/dist/system-polyfills.js',
'systemjs/dist/system.src.js',
'zone.js/dist/*.js',
'es6-shim/es6-shim.js',
'reflect-metadata/*.js',
'reflect-metadata/*.js.map',
'rxjs/**/*.js',
'#angular/**/*.js',
'rxjs/**/*.js.map',
'#angular/**/*.js.map',
'd3/d3.js',
'three/build/three.js',
'three/examples/js/postprocessing/*.js',
'three/examples/js/shaders/*.js'
]
});
let sass = mergeTrees(_.map(glob.sync('src/**/*.scss'), function(sassFile) {
sassFile = sassFile.replace('src/', '');
return compileSass(['src'], sassFile, sassFile.replace(/.scss$/, '.css'));
}));
let css = compileCSS(sass, options);
return mergeTrees([sass, css, appTree], { overwrite: true });
};
It was the order of operations, my trees were not overwriting appTree!
This works!
return mergeTrees([appTree, sass, css], { overwrite: true });

Dojo AMD module changes reference of "this"

I'm really confused as to some behavior I'm seeing in trying to learn the AMD style of Dojo. When I instantiate my module/object, "this" refers to the object in my constructor. I make a call to an internal function, and "this" inside that internal function refers to the Window object. So when I get to this.attachMapEventHandlers I get a "Object [object global] has no method 'attachMapEventHandlers'" error. What am I doing wrong? UPDATE: I found lang.hitch, which seems to indicate that the async nature is what's tripping me up, but I'm confused on how to implement a solution.
my script inside index.html:
require(["javascript/layout", "dijit/layout/ContentPane", "dijit/layout/BorderContainer", "dijit/layout/AccordionContainer",
"dojo/dom", "dojo/dom-attr", "dijit/Toolbar", "dijit/form/Button", "dijit/Dialog","dijit/ProgressBar", "dojo/domReady!"],
function (layout, dom, domAttr) {
mapControl = new layout();
layout.js:
define(["dojo/_base/declare"], function(declare) {
return declare(null, {
action:"pan",
activeMeasureTool:"",
aerialLayer:"",
legendLayers:"",
loadedServices:"",
popup:"",
resizeId:0,
constructor: function() {
this.init();
},
init: function() {
require(["esri/map", "esri/config", "esri/SpatialReference", "esri/geometry/Extent"],
function(Map, config, SpatialReference, Extent) {
//custom map requires a proxy to function properly.
esri.config.defaults.io.proxyUrl = "../sdc_devdata/proxy.php";
var spatRef = new SpatialReference(2276);
var startExtent = new Extent(2481416.32087491, 6963246.42495962, 2501196.36936991, 6980267.92469462, spatRef);
var appFullExtent = new Extent(2396699.46935379, 6872369.60195443, 2607745.94404633, 7107335.22319087, spatRef);
map = new Map("map", {extent: startExtent, isZoomSlider:true, logo:false, sliderStyle:"large"});
this.attachMapEventHandlers();
this.createLayers();
this.handleLayerVisibilityChange();
});
},
There are a couple of things that you could do to resolve this.
Firstly, you could add your required dependency to the define array so you don't need to do an asynchronous require within the constructor of the class.
That would look like:
define(["dojo/_base/declare", "esri/map", "esri/config", "esri/SpatialReference", "esri/geometry/Extent"], function (declare, Map, config, SpatialReference, Extent) {
return declare(null, {
action: "pan",
activeMeasureTool: "",
aerialLayer: "",
legendLayers: "",
loadedServices: "",
popup: "",
resizeId: 0,
constructor: function () {
this.init();
},
init: function () {
//custom map requires a proxy to function properly.
esri.config.defaults.io.proxyUrl = "../sdc_devdata/proxy.php";
var spatRef = new SpatialReference(2276);
var startExtent = new Extent(2481416.32087491, 6963246.42495962, 2501196.36936991, 6980267.92469462, spatRef);
var appFullExtent = new Extent(2396699.46935379, 6872369.60195443, 2607745.94404633, 7107335.22319087, spatRef);
map = new Map("map", {
extent: startExtent,
isZoomSlider: true,
logo: false,
sliderStyle: "large"
});
this.attachMapEventHandlers();
this.createLayers();
this.handleLayerVisibilityChange();
}
});
});
OR you could save the current scope of this to something in the closure when doing the require
init: function () {
var that = this;
require(["esri/map", "esri/config", "esri/SpatialReference", "esri/geometry/Extent"],
function (Map, config, SpatialReference, Extent) {
//custom map requires a proxy to function properly.
esri.config.defaults.io.proxyUrl = "../sdc_devdata/proxy.php";
var spatRef = new SpatialReference(2276);
var startExtent = new Extent(2481416.32087491, 6963246.42495962, 2501196.36936991, 6980267.92469462, spatRef);
var appFullExtent = new Extent(2396699.46935379, 6872369.60195443, 2607745.94404633, 7107335.22319087, spatRef);
map = new Map("map", {
extent: startExtent,
isZoomSlider: true,
logo: false,
sliderStyle: "large"
});
that.attachMapEventHandlers();
that.createLayers();
that.handleLayerVisibilityChange();
});
},
EDIT: your third option would be using lang.hitch, which lets you specify the scope of this in the the callback function. To use it, you would add dojo/_base/lang to you define() dependency list, and wrap the require callback in lang.hitch(this, function(){});
define(["dojo/_base/declare", "dojo/_base/lang"], function (declare, lang) {
return declare(null, {
//...
init: function () {
require(["esri/map", "esri/config", "esri/SpatialReference", "esri/geometry/Extent"],
lang.hitch(this, function (Map, config, SpatialReference, Extent) {
//this now refers to the instance of the class
}));
}
});
});
I would strongly suggest going with the first option, since it is consistent with the entire use of AMD (declaring what dependencies a module needs before it executes, rather than loading it on the fly).
You can put 'this' in another variable, like _this, and use _this in your internal function,like
init: function() {
var _this= this;
require(["esri/map", "esri/config", "esri/SpatialReference", "esri/geometry/Extent"],
function(Map, config, SpatialReference, Extent) {
...
_this.attachMapEventHandlers();
_this.createLayers();
_this.handleLayerVisibilityChange();

How to test AngularJS Directive with scrolling

I have an infinite scroll directive that I am trying to unit test. Currently I have this:
describe('Infinite Scroll', function(){
var $compile, $scope;
beforeEach(module('nag.infiniteScroll'));
beforeEach(inject(function($injector) {
$scope = $injector.get('$rootScope');
$compile = $injector.get('$compile');
$scope.scrolled = false;
$scope.test = function() {
$scope.scrolled = true;
};
}));
var setupElement = function(scope) {
var element = $compile('<div><div id="test" style="height:50px; width: 50px;overflow: auto" nag-infinite-scroll="test()">a<br><br><br>c<br><br><br><br>e<br><br>v<br><br>f<br><br>g<br><br>m<br>f<br><br>y<br></div></div>')(scope);
scope.$digest();
return element;
}
it('should have proper initial structure', function() {
var element = setupElement($scope);
element.find('#test').scrollTop(10000);
expect($scope.scrolled).toBe(true);
});
});
However the .scrollTop(10000); does not seem to trigger anything.
Is there anyway to unit test this type of functionality (I am able to unit test other directives with similar interactions like clicking on elements)?
In case it is relative, this is the infinite scroll code:
angular.module('nag.infiniteScroll', [])
.directive('nagInfiniteScroll', [
function() {
return function(scope, elm, attr) {
var raw = elm[0];
elm.bind('scroll', function() {
if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
scope.$apply(attr.nagInfiniteScroll);
}
});
};
}
]);
You have to trigger the scroll event on your element manually in your test:
element.find('#test').scrollTop(10000);
element.find('#test').triggerHandler('scroll');
Had the same issue recently. For the scrolling to work, you will need to set some dimensions on the body tag, so the window can be scrolled.
var scrollEvent = document.createEvent( 'CustomEvent' ); // MUST be 'CustomEvent'
scrollEvent.initCustomEvent( 'scroll', false, false, null );
var expectedLeft = 123;
var expectedTop = 456;
mockWindow.document.body.style.minHeight = '9000px';
mockWindow.document.body.style.minWidth = '9000px';
mockWindow.scrollTo( expectedLeft, expectedTop );
mockWindow.dispatchEvent( scrollEvent );
Unfortunately this does not work in PhantomJS.
If you are running your tests on Travis CI, you can also use Chrome by adding the following to your .travis.yml
before_install:
- export CHROME_BIN=chromium-browser
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
And a custom Chrome launcher in your karma config:
module.exports = function(config) {
var configuration = {
// ... your default content
// This is the new content for your travis-ci configuration test
// Custom launcher for Travis-CI
customLaunchers: {
Chrome_travis_ci: {
base: 'Chrome',
flags: ['--no-sandbox']
}
},
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: true
};
if(process.env.TRAVIS){
configuration.browsers = ['Chrome_travis_ci'];
}
config.set( configuration );
};