Using gulp-modernizr how do I specify feature options - javascript

My custom Moderniser build includes the following options which I am trying to inject into the gulp-modernizr tool as follows:
gulp.task('modernizr', function() {
allUISrcPlusSassSrc
.pipe(modernizr({
options: [
'backdropfilter',
'backgroundsize',
'bgpositionxy',
'bgrepeatspace_bgrepeatround',
'bgsizecover',
'borderradius',
'cssanimations',
'cssfilters',
'csspointerevents',
'csspseudoanimations',
'csspseudotransitions',
'cssremunit',
'csstransforms',
'csstransitions',
'customevent',
'devicemotion_deviceorientation',
'eventlistener',
'flexbox',
'fontface',
'json',
'nthchild',
'opacity',
'overflowscrolling',
'rgba',
'svg',
'svgasimg',
'svgfilters',
'touchevents',
'xhrresponsetypejson',
'domprefixes',
'setclasses',
'shiv'
]
}))
.pipe(gulp.dest("./output/js/vendor/"))
});
But running this leads to Building your customized Modernizr{ [Error: Error: ENOENT: no such file or directory, open '/Users/davesag/src/test-project/node_modules/modernizr/lib/../src/backgroundsize.js'
Looking in ./node_modules/modernizr/src I can't see any files that match these options. Am I just misunderstanding something? These feature names came straight from my custom-built modernizr file as downloaded previously from the moderniser website includes the following options which I am trying to inject into the gulp-modernizr.
Leaving out the options it builds okay but without the options I'm not getting any feature-classes injected into the HTML element of my page. The supposed auto-detect stuff does not seem to be working.
I checked the Customizr page as per the docs and it seems what I am doing is right. But clearly that's not the case.
How should I be doing this?

options refers to the options that are on the left hand side of the Modernizr builder page. These are typically APIs and convenience functions like Modernizr.mq, Modernizr.atRule, etc.
You want to use the tests option

#Patrick "it doesn't by default. you need to add options: ["setclasses"]"
Actually it's options: ["setClasses"]

Related

how to handle javascript that only runs on certain pages when bundled together

When working on small client sites, I often end up working with a main.js file that includes a bunch of jQuery plugins and small toggle functionality. Some of these code snippets are only relevant on certain pages, but ends up bundled together in one main.min.js file.
My question is, how do people write the individual code snippets in order to only execute that code when the correct page is being rendered?
Here's an example: Let's say I have a page with a search input field. This input is hooked up with jQuery autocomplete in order to show search suggestions as the user types. the code in main.js could look something like this:
var data = [
{
value: 'some value',
data: 'some data'
},
{...}
]
$('#autocomplete').autocomplete({
lookup: data,
lookupLimit: 10,
minChars: 3,
});
This code is only useful on the template that has that input field, but as main.js contains a bunch of other smaller bits like this that are useful globally and on other pages, the whole file is loaded on every pageview. What strategy should I use to only execute that piece of code when the page needs it?
I though of a few ways my self:
Check if the DOM-element (in this case #autocomplete) exists.
Check if the URL is == '/page-with-autocomplete'.
Use a class on , and check for that class i n order to run the script.
Other ideas? Any standard way to do this sort of thing? Anything considered a "best practice"?
Stick your JS in an if block and check for the unique DOM element on the page you want the script to run.
Although you can't just do:
if ( $('#my-el') ) {}
You have to check if the element has a length, like:
if ( $('#my-el').length ) {}

i18next best practice

I've successfully implemented i18next, which by the way is a great library! Though I'm still in search for the "best practice". This is the setup I have right now, which in general I like:
var userLanguage = 'en'; // set at runtime
i18n.init({
lng : userLanguage,
shortcutFunction : 'defaultValue',
fallbackLng : false,
load : 'unspecific',
resGetPath : 'locales/__lng__/__ns__.json'
});
In the DOM I do stuff like this:
<span data-i18n="demo.myFirstExample">My first example</span>
And in JS I do stuff like this:
return i18n.t('demo.mySecondExample', 'My second example');
This means I maintain the English translation within the code itself. I do however maintain other languages using separate translation.json files, using i18next-parser:
gulp.task('i18next', function()
{
gulp.src('app/**')
.pipe(i18next({
locales : ['nl','de'],
output : '../locales'
}))
.pipe(gulp.dest('locales'));
});
It all works great. The only problem is that when I've set 'en' as the userLanguage, i18next insists on fetching the /locales/en/translation.json file, even though it doesn't contain any translations. To prevent a 404, I currently serve an empty json object {} in that file.
Is there a way to prevent loading the empty .json file at all?
Maybe I'm missing something here but couldn't you simply do this:
if (userLanguage != 'en') {
i18n.init({
lng : userLanguage,
shortcutFunction : 'defaultValue',
fallbackLng : false,
load : 'unspecific',
resGetPath : 'locales/__lng__/__ns__.json'
});
}
That way your script i18n wouldn't be initialized unless you actually needed the translation service.
i18next-parser author here, I will explain how I use i18next and hopefully it will help:
1/ I do not use defaultTranslation in the code. The reason is that it doesn't belong in the code. I understand the benefit of having the actual text but the code can get bloated quickly. The difficult part consists in defining intelligible translation keys. If you do that, you don't really need the defaultTranslation text anymore. The translation keys are self-explainatory.
2/ If you have a 404 on the /locales/en/translation.json, then probably that you don't have the file in your public directory or something similar. With gulp you can have multiple destination and do dest('locales').dest('public/locales') for instance.
3/ If there is no translation in the catalog, make sure you run the gulp task first. Regarding populating the catalog with the defaultTranslation you have, it is a tricky problem to solve with regexes. Think of this case <div data-i18n="key">Default <div>translation</div></div>. It needs to be able to parse the inner html and extract all the content. I just never took the time to implement it as I don't use it.
See http://i18next.com/pages/doc_init.html under "whitelist languages to be allowed on init" (can't fragment link on those docs...):
i18n.init({ lngWhitelist: ['de-DE', 'de', 'fr'] });
Only specified languages will be allowed to load.
That should solve your problem. Though I suppose a blacklist would be even better.

How to Invalidate Dojo/Require's Module Cache?

I have a dojo-based module that automates loading a dojo/store/Memory for me, using a bang. It's called like so:
require( [ 'squad_builder/storeBroker!collectionStore' ],
function( collectionStore )
{
// use store...
} );
The first require() call loads the store and subsequent ones load the store from a cache.
This works well but I cannot figure out how to invalidate require's internal cache so I can make the next request load the store with fresh data.
Is there anything built into require() to do this or do I need to mess with some internal workings (and if so, where?)
Edit
In the docs it mentions:
Note: the dojo loader includes the nonstandard function require.undef,
which undefines a module value.
But that method is undefined when I call it. Looking at require() in Firebug with:
for( i in require )
{
console.log( 'require', i, require[ i ] );
}
require.module has a def() method but not an undef() one.
Edit 2
Require.cache only seems to contain dojo and dijit modules. Where are custom namespaced modules cached?
According to the dojo site, the function is not automatically included in "built" dojo files. If you look at an uncompressed dojo.js you will see it there.
From:http://dojotoolkit.org/reference-guide/1.9/loader/amd.html
The following table provides a list of options that are leveraged
within the loader. The first column is the Option/Feature as defined
within the loader, the second options is whether this is a detected
feature (via has.add()) or if it is just an option and its default
value. With “unbuilt” source, all the features and options are
available. If the loader has been built, then some of these features
may have been set as staticHasFeatures and not be configurable
anymore.
Also here it says that you might be able to turn the function back on by adding a line go djconfig
http://dojo-toolkit.33424.n3.nabble.com/require-undef-td3990559.html
dojoConfig = { has : {
"dojo-undef-api": true } }

Manually Trigger Upload within fineUploaderDnd

I have a problem. I have autoUpload set to false within $('element').fineUploaderDnd();
I can drag and drop files just fine. However, I can't seem to figure out how to manually trigger the upload. I have tried both of the following:
var uploader = $('#droppable').fineUploaderDnd(/*{ ... }*/);
uploader.fineUploaderDnd('uploadStoredFiles'); //Doesnt work
uploader.fineUploaderDnd('addFiles', handleUploads.fineUploaderFiles); //Also doesnt work
Note that handleUploads.fineUploaderFiles is an array of the 'File' objects the plugin returns to me .on('processingDroppedFilesComplete')
They both give me errors saying they don't support that. I've also tried various methods of using both the Dnd thing for drag/drop and the normal jquery fineUploader for 'addFiles' but that also doesn't seem to work.
What am I missing?
These lines aren't going to work:
uploader.fineUploaderDnd('uploadStoredFiles'); //Doesnt work
uploader.fineUploaderDnd('addFiles', handleUploads.fineUploaderFiles); //Also doesnt work
Because you can only call the uploadStoredFiles and addFiles methods on instances of FineUploader. It appears you are calling these methods on instances of the DnD module.
There are no such options in the standalone Fine Uploader DnD module. The standalone drag-and-drop module doesn't upload anything. It is meant to be used alongside FineUploaderBasic mode instance (note that you can use it outside of Fine Uploader entirely if you want to). This module is provided for FineUploaderBasic users who want to integrate drag & drop support easily into their app. If you are using FineUploader mode, drag & drop is already integrated for you, however.
To achieve this in basic mode
First, add an instance of FineUploader:
var uploader = $("#uploader").fineUploader({ uploaderType: 'basic' /*, ... */ })
Next, add an upload button:
var uploadButton = $("#upload-button").on('click', function () {
$("#uploader").fineUploader('uploadStoredFiles');
});
Then, instantiate your drag and drop module (note that this is separate from FineUploader's instance!):
var dnd = $('#droppable').fineUploaderDnd({
/* custom options */
}).on('processingDroppedFilesComplete', function (event, files) {
uploader('addFiles', files); //this submits the dropped files to Fine Uploader
});
For reference, please see the following:
Difference between FineUploaderBasic & FineUploader mode
Documentation on the standalone DnD module
API for FineUploaderBasic mode

Redefining a RequireJS module -- is it possible?

Basically, there is a page that I visit that uses RequireJS. I want to make adjustments to this page, so I went the route of a userscript. While looking at the client-side code I see that there is a module defined as so:
define("settings", [], function() {
return {
SETTINGA: "100",
SETTINGB: "200",
etc.
}
})
I want to add my own item to the settings array, as well as change some settings without having to redefine the module in my userscript (with the changes) and then removing/readding it. Is it possible to just make adjustments to this module?
P.S. I'm using the Script Injection technique to get my userscript to interact with other javascript in the original page.
Also, doing require("settings") in the Javascript console returns an object (not an array), so I can't do things like require("settings")[0] or require("settings").push(...), however I can access the settings by doing require("settings").SETTINGA. So, I'm not sure how to add/redefine settings to this since it is not an array?
Use this:
require('settings').new_property = 'new value';
The reason you can't retrieve or add settings to "the settings array" is that you aren't creating an array to begin with. {foo:bar} is an object literal, not an array literal ([foo,bar]).

Categories

Resources