Why is Modernizr loading Google fonts? - ssl

I am building a web app and just installed ssl.
Everything seems to be fine except for these two errors I'm getting about fonts being loaded over an insecure connection. The console suggests it's something that Modernizr is doing, but I can't figure out where and how to fix it.
Here's the console output:
The page at 'https://myawesomewebsite.com/' was loaded over HTTPS, but ran insecure content from 'http://themes.googleusercontent.com/static/fonts/rosarivo/v1/OGdIq-p0tOtBN2VMVvO9W_esZW2xOQ-xsNqO47m55DA.woff': this content should also be loaded over HTTPS.
modernizr-2.8.0.min.js:4
The page at 'https://myawesomewebsite.com/' was loaded over HTTPS, but ran insecure content from 'http://themes.googleusercontent.com/static/fonts/inconsolata/v5/BjAYBlHtW3CJxDcjzrnZCIbN6UDyHWBl620a-IRfuBk.woff': this content should also be loaded over HTTPS.
modernizr-2.8.0.min.js:4
I am actually using TypeKit for my fonts, so I have no idea what these Google Fonts are doing on the page and why Modernizr would be loading them.

There is a test for #font-face for CCS3 support in the full build of modernizr. I believe this test code loads some font just to see if that is working.
If you don't need that, use the build configurator on the modernizr page to exclude that from your custom built library.
By the way, it seems that the newer version of modernizr loads the fonts over SSL.
Test Code in modernizr 2.8.3
/*>>fontface*/
// #font-face detection routine by Diego Perini
// javascript.nwbox.com/CSSSupport/
// false positives:
// WebOS github.com/Modernizr/Modernizr/issues/342
// WP7 github.com/Modernizr/Modernizr/issues/538
tests['fontface'] = function() {
var bool;
injectElementWithStyles('#font-face {font-family:"font";src:url("https://")}', function( node, rule ) {
var style = document.getElementById('smodernizr'),
sheet = style.sheet || style.styleSheet,
cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : '';
bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0;
});
return bool;
};
/*>>fontface*/
// CSS generated content detection
tests['generatedcontent'] = function() {
var bool;
injectElementWithStyles(['#',mod,'{font:0/0 a}#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) {
bool = node.offsetHeight >= 3;
});
return bool;
};

Related

<video> tag. DOMException: The element has no supported sources, when not utilizing require()

I am trying to play a video when developing locally with VueJS 2.
My code is the following :
<video class="back_video" :src="`../videos/Space${videoIndex}.mp4`" id="background-video"></video>
...
data :
function() {
return {
videoIndex:1
}
}
...
const vid = document.getElementById("background-video");
vid.crossOrigin = 'anonymous';
let playPromise = vid.play();
if (playPromise !== undefined) {
playPromise.then(function() {
console.log("video playing");
}).catch(function(error) {
console.error(error);
});
}
This code is causing the exception given in title. Tried in several browsers, always the same.
If I change the src by :
:src="require(`../videos/Space${videoIndex}.mp4`)"
it works.
But in that case building time is very long as I have many different videos in my videos directory, because adding require() will force to copy all videos in the running directory at build phase (vue-cli serve), and this is really annoying. In other words I want to refer videos that are outside the build directory to avoid this (but also to avoid having videos in my git).
It is interesting to note that when I deploy server side, it works perfectly with my original code
:src="`../videos/Space${videoIndex}.mp4`"
Note also that if i replace my code with simply
src="../videos/Space1.mp4"
it works too. So the video itself, or its location, are not the source of the problem.
Any clue ?
You can host your videos on a CDN to have something faster and easier to debug/work with.
Otherwise, it will need to bundle it locally and may take some time.

Cypress - run test in iframe

I'm trying to find elements in iframe but it doesn't work.
Is there anyone who have some system to run tests with Cypress in iframe? Some way to get in iframe and work in there.
It's a known issue mentioned here. You can create your own custom cypress command which mocks the iframe feature. Add following function to your cypress/support/commands.js
Cypress.Commands.add('iframe', { prevSubject: 'element' }, ($iframe, selector) => {
Cypress.log({
name: 'iframe',
consoleProps() {
return {
iframe: $iframe,
};
},
});
return new Cypress.Promise(resolve => {
resolve($iframe.contents().find(selector));
});
});
Then you can use it like this:
cy.get('#iframe-id')
.iframe('body #elementToFind')
.should('exist')
Also, because of CORS/same-origin policy reasons, you might have to set chromeWebSecurity to false in cypress.json (Setting chromeWebSecurity to false allows you to access cross-origin iframes that are embedded in your application and also navigate to any superdomain without cross-origin errors).
This is a workaround though, it worked for me locally but not during CI runs.
This works for me locally and via CI. Credit: Gleb Bahmutov iframes blog post
export const getIframeBody = (locator) => {
// get the iframe > document > body
// and retry until the body element is not empty
return cy
.get(locator)
.its('0.contentDocument.body').should('not.be.empty')
// wraps "body" DOM element to allow
// chaining more Cypress commands, like ".find(...)"
// https://on.cypress.io/wrap
.then(cy.wrap)
}
spec file:
let iframeStripe = 'iframe[name="stripe_checkout_app"]'
getIframeBody(iframeStripe).find('button[type="submit"] .Button-content > span').should('have.text', `Buy me`)
that is correct. Cypress doesn't support Iframes. It is simple not possible at the moment. You can follow (and upvote) this ticket: https://github.com/cypress-io/cypress/issues/136

ArcGIS Api (Esri) triggering multipleDefine error

I have this weird issue while using ArcGIS API for JavaScript v4.4 in my code. I am trying to build an Excel Web Add-in in which I would like to load an ArcGIS map but when I load ArcGIS I get a multipleDefine error.
ArcGIS is getting bundled with Dojo which is used as the loader for all the ArcGIS/esri packages. I have no other choices to load my own custom JS bundles with Dojo because of the way ArcGIS has built their API. So I can't decide to not use Dojo and thus not getting the multipleDefine error.
I load my own JS files like this:
<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js" type="text/javascript"></script>
<script>
var dojoConfig = {
parseOnLoad: false,
async: false,
// we make aliases for our js file
aliases:  [
['index',  './Bundles/index.js'],
],
};
</script>
<script src="https://js.arcgis.com/4.4/init.js"></script>
<script>
require(['index'], function (index) {
//...do something
});
</script>
When I restart the page I get a multipleDefine error once in every two/three trials. After a lot of investigation I understood that the error lies with the Office.js API but I had a hard time to find a good solution.
After a while I found the cause of the problem; we cannot start office-js and Dojo together because they both want to add scripts in the head tag of our page and somehow they end up in conflict with one another, thus we get the dreaded multipleDefined Dojo error and some of our files do not get loaded.
Once this cause was identified I decided to solve it by making sure Dojo, Argis and my custom js files got loaded once Office and dependencies were fully loaded.
I implemented it like this in my js code:
// This Dojo config variable has to be defined before Dojo is loaded in our scripts
var dojoConfig = {
// we make aliases for our custom js file
aliases: [
['index', './Bundles/index.js'],
],
// We require our dependencies (our own code bundles) with Dojo.
// Notice that it is mandatory to bundle our js files
// as AMD Modules for Dojo to be able to load them as dependencies.
deps: ['index'],
};
// Once office has fully initialized we can add our arcgis file and let
// him load our own required javascript files.
// We cannot start Office-js and Dojo/Arcgis together because they both
// want to add scripts in the head tag of the HTML page and
// somehow they end up in conflict, thus we get the dreaded
// multipleDefined Dojo error and some of our files
// do not get loaded.
Office.initialize = function (reason) {
// we manually add the Arcgis script to the header of our page
// once we are sure Office and dependencies has fully loaded.
var tag = document.createElement('script');
tag.src = 'https://js.arcgis.com/4.4/init.js';
document.getElementsByTagName('head')[0].appendChild(tag);
};
Once this was added the code started working like a charm.

Arcgis conflict in Liferay 7.0

I try to use Arcgis javascript API in Liferay 7.0 but it's fail. I think because Liferay 7.0 using requireJS for using javascript which conflict with dojo of Arcgis javascript API. I am using this code for implement Arcgis API:
<script type="text/javascript" src="<%=request.getContextPath() %>/js/arcgis_js_api/library/3.14/3.14/init.js"></script>
<script>
require([
"esri/map", "dojo/dom"
], function(Map, dom) {
var map = new esri.Map("map", {
basemap: "topo", //For full list of pre-defined basemaps, navigate to http://arcg.is/1JVo6Wd
center: [-122.45, 37.75], // longitude, latitude
zoom: 13
});
});
This is console log:
java.lang.IllegalArgumentException: Path esri/map.js does not start with a "/" character
java.lang.IllegalArgumentException: Path dojo.js does not start with a "/" character
This is javascript error:
Error: defineAlreadyDefined
Anyone has solution help me please. Thanks!
As you mention Liferay7 and your script tag makes use of <%=request.getContextPath()%>, you most likely have a mismatch between your portlet and the servlet API: request is not aware of any portlet context (but is still there, because JSPs have been designed for servlets and it's a mandatory object that's around, irritating a lot of people)
The URLs for your own Javascript files are just not relative to the context root, but Liferay makes them available on a different path. The easiest way, without messing around with this location, is to just mention the file you'd like to include in your portlet's configuration. In Liferay 7 OSGi portlet modules, it works like this (pseudocode, simplified)
#Component(
immediate = true,
property = {
"com.liferay.portlet.footer-portlet-javascript=/js/main.js",
"javax.portlet.display-name=My Portlet",
},
service = Portlet.class
)
In JSR-286 portlets packaged in WARs, you'd use the footer-portlet-javascript value in WEB-INF/liferay-portlet.xml.
Alternatively, use the header-* variant.
I personally prefer this way over memorizing how the path of resources is being constructed.
I use this code before implement arcgis (javascript):
if(typeof define !== "undefined" && typeof require !== "undefined"){
window.__define = window.define;
window.__require = window.require;
window.define = undefined;
window.require = undefined;}
It will be resolved.

Ensure phonegap and plugins load before Sencha loader

I have written an application in Sencha Touch 2.1, of which I embed a package build into Cordova/PhoneGap 2.5.0 and compile in xCode to run on iOS Simulator / iOS. I have added the PGSQLite plugin to PhoneGap, and built my own PhoneGap/SQLite Proxy for Sencha, which I used on a few of my Stores.*
Problem: When I embed a package build into PhoneGap and run in iOS Simulator, I see that Cordova does not load before Sencha initializes. I see this because my calls in my Sencha app to Cordova.exec that I make in my Proxy initialization result in an error telling me that the Cordova object cannot be found.
I do successfully use Cordova.exec later in my application to run things like the Childbrowser plugin for PhoneGap, and it works. But using Cordova.exec at an early stage in the app's execution, i.e., initialization, is too soon to guarantee that the Cordova object will have been instantiated.
Already tried: I already tried the following approaches:
I tried simply embedding the developer build of my Sencha app into PhoneGap. Although this worked, I don't want to deploy my development build as my released app because it is inefficient and takes up a lot of space. I have learned from this experiment, however, that the way the Sencha Touch microloader works on package and production builds loads PhoneGap after Sencha. This can be clearly seen when inspecting the DOM after Sencha loads in a package build.
I have already configured my app.json file to include PhoneGap and
my plugins before app.js and the Sencha Touch framework. Playing
with the order of my JS file references in my app.json did not
seem to affect the load order.
I also tried creating a script loader, as described here
(StackOverflow). I then ran the script loader for Cordova, and in
the callback for that, ran the script loader for my plugin, and
then, finally, in the callback for that, ran the Sencha Touch
microloader. This resulted in an error. Additionally, I had to
manually set that up in my index.html file after Sencha built my
package. This seems unacceptable.
What I am looking for: I am looking for answers to the following:
Is there a way to configure Sencha's microloader or my Sencha app in general so that Cordova is ensured to have loaded before Sencha's microloader runs?
Is there a way to set this up so that using Sencha Cmd still works, and I don't have to hack around in my index.html file after I build the app?
Note:
*Please don't suggest I use the existing, so-called, SQLite Proxy for Sencha. I specifically chose my approach because, though I appreciated the existing work on a SQLite proxy for Sencha Touch 2 (namely, this), it is actually a WebSQL proxy that does not store natively in SQLite on iOS. My proxy uses the PGSQLite plugin for PhoneGap to natively store data in SQLite on iOS. I plan to open-source it when I have an opportunity to clean it up and untangle it from my code.
I ended up solving this myself by building a custom loader. I am not sure if there is a more Sencha-ish way to do it, but here are the details of what I did, which does work, in case anyone else wants to ensure that PhoneGap is completely loaded in package and production builds before running anything in Sencha. (That would probably be the case in all scenarios in which PhoneGap is packaging a Sencha app).
My index.html file:
<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
<!-- Load Cordova first. Replace with whatever version you are using -->
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8">
function onBodyLoad() {
// Check for whatever mobile you will run your PhoneGap app
// on. Below is a list of iOS devices. If you have a ton of
// devices, you can probably do this more elegantly.
// The goal here is to only listen to the onDeviceReady event
// to continue the load process on devices. Otherwise you will
// be waiting forever (literally) on Desktops.
if ((navigator.platform == 'iPad') ||
(navigator.platform == 'iPhone') ||
(navigator.platform == 'iPod') ||
(navigator.platform == 'iPhone Simulator') ||
(navigator.platform == 'iPadSimulator')
) {
// Listening for this event to continue the load process ensures
// that Cordova is loaded.
document.addEventListener("deviceready", onDeviceReady, false);
} else {
// If we're on Desktops, just proceed with loading Sencha.
loadScript('loader.js', function() {
console.log('Finished loading scripts.');
});
}
};
// This function is a modified version of the one found on
// StackOverflow, here: http://stackoverflow.com/questions/756382/bookmarklet-wait-until-javascript-is-loaded#answer-756526
// Using this allows you to wait to load another script by
// putting the call to load it in a callback, which is
// executed only when the script that loadScript is loading has
// been loaded.
function loadScript(url, callback)
{
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.src = url;
// Attach handlers for all browsers
var done = false;
script.onload = script.onreadystatechange = function()
{
if( !done && ( !this.readyState
|| this.readyState == "loaded"
|| this.readyState == "complete") )
{
done = true;
// Continue your code
callback();
}
};
head.appendChild(script);
}
function onDeviceReady() {
console.log("[PhoneGap] Device initialized.");
console.log("[PhoneGap] Loading plugins.");
// You can load whatever PhoneGap plugins you want by daisy-chaining
// callbacks together like I did with pgsqlite and Sencha.
loadScript('pgsqlite_plugin.js', function() {
console.log("[Sencha] Adding loader.");
// The last one to load is the custom Sencha loader.
loadScript('loader.js', function() {
console.log('Finished loading scripts.');
});
});
};
</script>
<meta charset="UTF-8">
<title>Sencha App</title>
</head>
<!-- Don't forget to call onBodyLoad() in onLoad -->
<body onLoad="onBodyLoad();">
</body>
</html>
Next, create a custom loader in loader.js in your document root, alongside your index.html. This one is heavily based on the development microloader that comes with Sencha. Much props to them:
console.log("Loader included.");
(function() {
function write(content) {
document.write(content);
}
function meta(name, content) {
write('<meta name="' + name + '" content="' + content + '">');
}
var global = this;
if (typeof Ext === 'undefined') {
var Ext = global.Ext = {};
}
var head = document.getElementsByTagName("head")[0];
var xhr = new XMLHttpRequest();
xhr.open('GET', 'app.json', false);
xhr.send(null);
var options = eval("(" + xhr.responseText + ")"),
scripts = options.js || [],
styleSheets = options.css || [],
i, ln, path;
meta('viewport', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no');
meta('apple-mobile-web-app-capable', 'yes');
meta('apple-touch-fullscreen', 'yes');
console.log("Loading stylesheets");
for (i = 0,ln = styleSheets.length; i < ln; i++) {
path = styleSheets[i];
if (typeof path != 'string') {
path = path.path;
}
var stylesheet = document.createElement("link");
stylesheet.rel = "stylesheet";
stylesheet.href = path;
head.appendChild(stylesheet);
}
for (i = 0,ln = scripts.length; i < ln; i++) {
path = scripts[i];
if (typeof path != 'string') {
path = path.path;
}
var script = document.createElement("script");
script.src = path;
head.appendChild(script);
}
})();
Notice that your index.html file does not contain a #microloader script element. That's because you should take it out and use your custom loader.
With all that in place, you will be able to sail smoothly, knowing that the whole PhoneGap environment is in place before your Sencha javascript starts doing things.