diff --git a/README.md b/README.md index 4ac15cc2..a61fd7a2 100644 --- a/README.md +++ b/README.md @@ -67,12 +67,29 @@ this. Learn more about [events][evt]. +## Manage loading everywhere + +Usually, it's easiest to include a copy of webfontloader in every window where +fonts are needed, so that each window manages its own fonts. However, if you +need to have a single window manage fonts for multiple same-origin child windows +or iframes that are built up using JavaScript, webfontloader supports that as +well. Just use the optional `context` configuration option and give it a +reference to the target window for loading: + + ## A common ground WebFont Loader aims to provide a common interface for font loading. Today it -works with Google, Typekit, Fonts.com Web fonts and your own CSS. Learn more in -[transitions][trn]. +works with Google, Typekit, Ascender, Fontdeck, Fonts.com Web fonts and your own +CSS. Learn more in [transitions][trn]. ## More to see @@ -125,11 +142,11 @@ Then, run the tests. * That's it! - ## Authors * Ryan Carver / ryan@typekit.com * Jeremie Lenfant-engelmann / jeremiele@google.com +* Sean McBride / sean@typekit.com ## License diff --git a/lib/webfontloader/demo/public/ascender-iframe.html b/lib/webfontloader/demo/public/ascender-iframe.html new file mode 100644 index 00000000..3146ee1c --- /dev/null +++ b/lib/webfontloader/demo/public/ascender-iframe.html @@ -0,0 +1,46 @@ + + + + Ascender Module Demo + + + + + + + + + +
+ +

+ Hide Page | + Reload Cached +

+

+ Note: use "localhost" when testing web fonts. +

+

+ The goal of this page is to show how fonts load from Ascender in a child + iframe. +

+ + + diff --git a/lib/webfontloader/demo/public/blank.html b/lib/webfontloader/demo/public/blank.html new file mode 100644 index 00000000..0923a947 --- /dev/null +++ b/lib/webfontloader/demo/public/blank.html @@ -0,0 +1,9 @@ + + + + + Blank page + + + + diff --git a/lib/webfontloader/demo/public/custom-iframe.html b/lib/webfontloader/demo/public/custom-iframe.html new file mode 100644 index 00000000..f5795e19 --- /dev/null +++ b/lib/webfontloader/demo/public/custom-iframe.html @@ -0,0 +1,41 @@ + + + + Custom Module + + + + + + + + +
+

+ Hide Page | + Reload Cached +

+

+ The goal of this page is to show how fonts load from a custom module in a + child iframe. +

+ + + diff --git a/lib/webfontloader/demo/public/custom.html b/lib/webfontloader/demo/public/custom.html index 5e21ff79..1cd28139 100644 --- a/lib/webfontloader/demo/public/custom.html +++ b/lib/webfontloader/demo/public/custom.html @@ -6,7 +6,7 @@ + + + + + + +
+

+ Hide Page | + Reload Cached +

+

+ The goal of this page is demonstrate fonts loading from Google via + Javascript into a child iframe. +

+ + diff --git a/lib/webfontloader/demo/public/index.html b/lib/webfontloader/demo/public/index.html index ed469a3a..39fa71c7 100644 --- a/lib/webfontloader/demo/public/index.html +++ b/lib/webfontloader/demo/public/index.html @@ -16,7 +16,7 @@

WebFont Loader Demos

Modules

- WebFont Loader provides modules to load fonts from many places. + WebFont Loader provides modules to load fonts from many places.

  1. Google / CSS Link: Load fonts from Google with a link tag. Consider this a base case for font loading.
  2. @@ -25,7 +25,20 @@

    Modules

  3. Custom / WebFont Loader: Load fonts from your own CSS with WebFont Loader.
  4. Ascender / WebFont Loader: Load fonts from Ascender with WebFont Loader.
  5. Fontdeck / WebFont Loader: Load fonts from Fontdeck with WebFont Loader.
  6. -
  7. monotype / WebFont Loader: Load fonts from webfonts.fonts.com with WebFont Loader.
  8. +
  9. Monotype / WebFont Loader: Load fonts from webfonts.fonts.com with WebFont Loader.
  10. +
+ +

Modules in Iframes

+

+ WebFont Loader provides the ability to load fonts in child iframes using modules, instead of the main window. +

+
    +
  1. Google / WebFont Loader: Load fonts from Google in a child iframe with WebFont Loader.
  2. +
  3. Typekit / WebFont Loader: Load fonts from Typekit in a child iframe with WebFont Loader.
  4. +
  5. Custom / WebFont Loader: Load fonts from your own CSS in a child iframe with WebFont Loader.
  6. +
  7. Ascender / WebFont Loader: Load fonts from Ascender in a child iframe with WebFont Loader.
  8. +
  9. Fontdeck / WebFont Loader: Their demo fonts seem to be broken at the moment, so we don't have an iframe demo of this module.
  10. +
  11. Monotype / WebFont Loader: Load fonts from webfonts.fonts.com in a child iframe with WebFont Loader.

Events

diff --git a/lib/webfontloader/demo/public/monotype-iframe.html b/lib/webfontloader/demo/public/monotype-iframe.html new file mode 100644 index 00000000..cbc9dfd9 --- /dev/null +++ b/lib/webfontloader/demo/public/monotype-iframe.html @@ -0,0 +1,46 @@ + + + + + + + + + + + + +
+ +

+ + Hide Page | + + Reload Cached + +

+ +

+ The goal of this page is to show how monotype fonts load in a child iframe. +

+ +

+ You must use "localhost" when testing monotype fonts. +

+ + diff --git a/lib/webfontloader/demo/public/typekit-iframe.html b/lib/webfontloader/demo/public/typekit-iframe.html new file mode 100644 index 00000000..26c942d9 --- /dev/null +++ b/lib/webfontloader/demo/public/typekit-iframe.html @@ -0,0 +1,41 @@ + + + + + + + + + + + + +
+

+ Hide Page | + Reload Cached +

+

+ The goal of this page is to show how Typekit fonts load into an iframe. +

+

+ You must load the fonts on "localhost" for this demo to work. +

+ + diff --git a/lib/webfontloader/demo/public/typekit.html b/lib/webfontloader/demo/public/typekit.html index be80d037..153a9418 100644 --- a/lib/webfontloader/demo/public/typekit.html +++ b/lib/webfontloader/demo/public/typekit.html @@ -6,8 +6,7 @@ @@ -16,15 +15,14 @@ h1 { visibility: hidden; } - .wf-arialblack-n4-active h1 { - font-family: 'Arial Black'; + .wf-futurapt-n7-active h1 { visibility: visible; }

- Hello World. I am Arial Black. + Hello World. I am Futura PT.


@@ -32,10 +30,10 @@

Reload Cached

- The goal of this page is to show how Typekit fonts load. Note that it uses - a minimal Typekit script in order to reduce dependencies. This script - simply provides the system font 'Arial Black' instead of loading a web - font. + The goal of this page is to show how Typekit fonts load. +

+

+ You must load this page on "localhost" in order for the fonts to load.

diff --git a/src-test/ascender/ascender_script_test.js b/src-test/ascender/ascender_script_test.js index b2974135..71f860f0 100644 --- a/src-test/ascender/ascender_script_test.js +++ b/src-test/ascender/ascender_script_test.js @@ -14,6 +14,9 @@ AscenderScriptTest.prototype.testLoadAndFamilyVariations = function(){ createCssLink: function(cssLink) { css = cssLink; return ''; + }, + getProtocol: function() { + return 'http:'; } }; diff --git a/src-test/core/domhelpertest.js b/src-test/core/domhelpertest.js index 34d5095b..356b86b2 100644 --- a/src-test/core/domhelpertest.js +++ b/src-test/core/domhelpertest.js @@ -1,7 +1,7 @@ var DomHelperTest = TestCase('DomHelperTest'); DomHelperTest.prototype.setUp = function() { - this.domHelper_ = new webfont.DomHelper(document); + this.domHelper_ = new webfont.DomHelper(window); }; DomHelperTest.prototype.testCreateElementNoAttr = function() { @@ -106,3 +106,46 @@ DomHelperTest.prototype.testHasSupportForStyle = function() { this.domHelper_.supportForStyle_ = true; assertTrue(this.domHelper_.hasSupportForStyle_()); }; + +DomHelperTest.prototype.testGetWindows = function() { + var fakeMainWindow = 'main window'; + var fakeLoadWindow = 'load window'; + var domHelper = new webfont.DomHelper(fakeMainWindow, fakeLoadWindow); + assertEquals('main window', domHelper.getMainWindow()); + assertEquals('load window', domHelper.getLoadWindow()); +}; + +DomHelperTest.prototype.testGetProtocol = function() { + var fakeWindow = { + location: { + protocol: 'https:' + } + }; + var domHelper = new webfont.DomHelper(fakeWindow); + assertEquals('https:', domHelper.getProtocol()); +}; + +DomHelperTest.prototype.testGetProtocolHttpDefault = function() { + var fakeWindow = { + location: { + protocol: 'file:' + } + }; + var domHelper = new webfont.DomHelper(fakeWindow); + assertEquals('http:', domHelper.getProtocol()); +}; + +DomHelperTest.prototype.testGetProtocolIframeFallback = function() { + var fakeMainWindow = { + location: { + protocol: 'https:' + } + }; + var fakeLoadWindow = { + location: { + protocol: 'about:' + } + }; + var domHelper = new webfont.DomHelper(fakeMainWindow, fakeLoadWindow); + assertEquals('https:', domHelper.getProtocol()); +}; diff --git a/src-test/core/eventdispatchertest.js b/src-test/core/eventdispatchertest.js index cdd3e6c7..096d83fd 100644 --- a/src-test/core/eventdispatchertest.js +++ b/src-test/core/eventdispatchertest.js @@ -15,7 +15,7 @@ EventDispatcherTest.prototype.setUp = function() { var self = this; this.eventDispatcher_ = new webfont.EventDispatcher(new webfont.DomHelper( - document), this.fakeHtmlElement_, { + window), this.fakeHtmlElement_, { loading: function() { self.loadingEventCalled_ = true; }, diff --git a/src-test/core/fonttest.js b/src-test/core/fonttest.js index bf6a5712..d304660c 100644 --- a/src-test/core/fonttest.js +++ b/src-test/core/fonttest.js @@ -1,49 +1,38 @@ var FontTest = TestCase('FontTest'); FontTest.prototype.setUp = function() { - this.fakeHtmlElement_ = { className: '' }; - this.fakeDomHelper_ = { - appendClassName: function() {}, - removeClassName: function() {}, - hasClassName: function() {}, - createElement: function(name) { - return document.createElement(name); - }, - insertInto: function() {}, - removeElement: function() {} - }; this.fontModuleLoader_ = new webfont.FontModuleLoader(); }; FontTest.prototype.testFontLoad = function() { var userAgent = new webfont.UserAgent('Firefox', '3.6', 'Gecko', '1.9.2', 'Macintosh', '10.6', undefined, true); - var font = new webfont.WebFont(this.fakeDomHelper_, this.fontModuleLoader_, - this.fakeHtmlElement_, function(func, timeout) { func(); }, userAgent); - var self = this; + var font = new webfont.WebFont(window, this.fontModuleLoader_, + function(func, timeout) { func(); }, userAgent); var testModule = null; - font.addModule('test', function(conf) { + font.addModule('test', function(conf, domHelper) { testModule = new function() { this.conf = conf; + this.domHelper = domHelper; this.loadCalled = false; this.supportUserAgentCalled = false; - }; - testModule.load = function(onReady) { - this.loadCalled = true; - onReady([]); }; - testModule.supportUserAgent = function(ua, support) { - this.supportUserAgentCalled = true; - support(true); - }; - return testModule; + testModule.load = function(onReady) { + this.loadCalled = true; + onReady([]); + }; + testModule.supportUserAgent = function(ua, support) { + this.supportUserAgentCalled = true; + support(true); + }; + return testModule; }); - var loadingEventCalled = false; assertEquals(0, font.moduleFailedLoading_); assertEquals(0, font.moduleLoading_); + var loadingEventCalled = false; font.load({ test: { somedata: 'in french a cow says meuh' @@ -58,17 +47,53 @@ FontTest.prototype.testFontLoad = function() { assertNotNull(testModule); assertNotUndefined(testModule.conf); assertNotNull(testModule.conf); + assertNotUndefined(testModule.domHelper); + assertNotNull(testModule.domHelper); + assertSame(window, testModule.domHelper.getMainWindow()); + assertSame(window, testModule.domHelper.getLoadWindow()); assertEquals('in french a cow says meuh', testModule.conf.somedata); assertTrue(testModule.loadCalled); assertTrue(testModule.supportUserAgentCalled); assertTrue(loadingEventCalled); }; +FontTest.prototype.testFontLoadWithContext = function() { + var fakeMainWindow = {}; + + var userAgent = new webfont.UserAgent('Firefox', '3.6', 'Gecko', '1.9.2', + 'Macintosh', '10.6', undefined, true); + var font = new webfont.WebFont(fakeMainWindow, this.fontModuleLoader_, + function(func, timeout) { func(); }, userAgent); + var testModule = null; + + font.addModule('test', function(conf, domHelper) { + testModule = new function() { + this.domHelper = domHelper; + }; + testModule.load = function() {}; + testModule.supportUserAgent = function(ua, support) { + support(true); + }; + return testModule; + }); + + font.load({ + test: { + somedata: 'in french a cow says meuh' + }, + context: window + }); + + assertNotUndefined(testModule.domHelper); + assertNotNull(testModule.domHelper); + assertSame(fakeMainWindow, testModule.domHelper.getMainWindow()); + assertSame(window, testModule.domHelper.getLoadWindow()); +}; + FontTest.prototype.testFontInactive = function() { var userAgent = new webfont.UserAgent('Firefox', '3.0', false); - var font = new webfont.WebFont(this.fakeDomHelper_, this.fontModuleLoader_, - this.fakeHtmlElement_, function(func, timeout) { func(); }, userAgent); - var self = this; + var font = new webfont.WebFont(window, this.fontModuleLoader_, + function(func, timeout) { func(); }, userAgent); var testModule; font.addModule('test', function(conf) { diff --git a/src-test/fontdeck/fontdeck_script_test.js b/src-test/fontdeck/fontdeck_script_test.js index 841da7a4..a631084e 100644 --- a/src-test/fontdeck/fontdeck_script_test.js +++ b/src-test/fontdeck/fontdeck_script_test.js @@ -41,6 +41,10 @@ FontdeckScriptTest.prototype.testSupportAndLoadLifecycle = function() { ] }; var insert = ''; + var global = { + // No hostname to verify fallback behavior for empty iframe + location: {} + }; var src = ''; var fakeDomHelper = { insertInto: function(tag, e) { @@ -48,19 +52,22 @@ FontdeckScriptTest.prototype.testSupportAndLoadLifecycle = function() { }, createScriptSrc: function(srcLink) { src = srcLink; - } - }; - var global = { - location: { - protocol: 'https:' }, - document: { - location: { - hostname: 'test-host-name' - } + getLoadWindow: function() { + return global; + }, + getMainWindow: function() { + return { + location: { + hostname: 'test-host-name' + } + }; + }, + getProtocol: function() { + return 'https:'; } }; - var fontdeck = new webfont.FontdeckScript(global, fakeDomHelper, configuration); + var fontdeck = new webfont.FontdeckScript(fakeDomHelper, configuration); // supportUserAgent var userAgent = 'user agent'; @@ -80,7 +87,7 @@ FontdeckScriptTest.prototype.testSupportAndLoadLifecycle = function() { assertEquals(fontdeck.fontFamilies_, [apiResponse.fonts[0].name, apiResponse.fonts[1].name]); assertEquals(fontdeck.fontVariations_[apiResponse.fonts[0].name], ['n4']); assertEquals(fontdeck.fontVariations_[apiResponse.fonts[1].name], ['i7']); - + assertEquals(true, isSupport); }; @@ -90,17 +97,20 @@ FontdeckScriptTest.prototype.testNoProjectId = function() { }; var insert = ''; var src = ''; - var fakeDomHelper = {}; - var global = {}; - var fontdeck = new webfont.FontdeckScript(global, fakeDomHelper, configuration); + var fakeDomHelper = { + getLoadWindow: function() { + return {}; + } + }; + var fontdeck = new webfont.FontdeckScript(fakeDomHelper, configuration); // supportUserAgent var userAgent = 'user agent'; var isSupport = null; fontdeck.supportUserAgent(userAgent, function(support) { isSupport = support; }); - + assertEquals(fontdeck.fontFamilies_, []); assertEquals(fontdeck.fontVariations_, []); assertEquals(true, isSupport); -} \ No newline at end of file +} diff --git a/src-test/google/fontapiurlbuildertest.js b/src-test/google/fontapiurlbuildertest.js index f117c819..2282b406 100644 --- a/src-test/google/fontapiurlbuildertest.js +++ b/src-test/google/fontapiurlbuildertest.js @@ -2,7 +2,7 @@ var FontApiUrlBuilderTest = TestCase('FontApiUrlBuilderTest'); FontApiUrlBuilderTest.prototype.testThrowsExceptionIfNoFontFamilies = function() { - var fontApiUrlBuilder = new webfont.FontApiUrlBuilder("http://moo"); + var fontApiUrlBuilder = new webfont.FontApiUrlBuilder("http://moo", "http:"); try { fontApiUrlBuilder.build(); @@ -13,14 +13,14 @@ FontApiUrlBuilderTest.prototype.testThrowsExceptionIfNoFontFamilies = }; FontApiUrlBuilderTest.prototype.testBuildProperUrl = function() { - var fontApiUrlBuilder = new webfont.FontApiUrlBuilder("http://moo"); + var fontApiUrlBuilder = new webfont.FontApiUrlBuilder("http://moo", "http:"); fontApiUrlBuilder.setFontFamilies([ 'Font1', 'Font2' ]); assertEquals('http://moo?family=Font1%7CFont2', fontApiUrlBuilder.build()); }; FontApiUrlBuilderTest.prototype.testBuildProperDefaultUrl = function() { - var fontApiUrlBuilder = new webfont.FontApiUrlBuilder(); + var fontApiUrlBuilder = new webfont.FontApiUrlBuilder(undefined, "http:"); fontApiUrlBuilder.setFontFamilies([ 'Font1', 'Font2' ]); assertEquals("http:" + webfont.FontApiUrlBuilder.DEFAULT_API_URL + @@ -29,7 +29,7 @@ FontApiUrlBuilderTest.prototype.testBuildProperDefaultUrl = function() { FontApiUrlBuilderTest.prototype.testBuildProperUrlWithSubsets = function() { - var fontApiUrlBuilder = new webfont.FontApiUrlBuilder(); + var fontApiUrlBuilder = new webfont.FontApiUrlBuilder(undefined, "http:"); fontApiUrlBuilder.setFontFamilies([ 'Font1:bold:greek,cyrillic', 'Font2:italic', 'Font3' ]); @@ -40,7 +40,7 @@ FontApiUrlBuilderTest.prototype.testBuildProperUrlWithSubsets = function() { FontApiUrlBuilderTest.prototype.testBuildProperUrlWithSubsetsNoVariations = function() { - var fontApiUrlBuilder = new webfont.FontApiUrlBuilder(); + var fontApiUrlBuilder = new webfont.FontApiUrlBuilder(undefined, "http:"); fontApiUrlBuilder.setFontFamilies([ 'Font1:bold,italic:greek,cyrillic', 'Font2:italic', 'Font3::latin' ]); diff --git a/src-test/google/googlefontapitest.js b/src-test/google/googlefontapitest.js index 1bf52e2e..0e5d8644 100644 --- a/src-test/google/googlefontapitest.js +++ b/src-test/google/googlefontapitest.js @@ -9,6 +9,9 @@ GoogleFontApiTest.prototype.testCallOnReadyWithFontFamilyLoading = function() { }, createCssLink: function(csslink) { link = csslink; + }, + getProtocol: function() { + return 'http:'; } }; var userAgent = new webfont.UserAgent("Test", "1.0", true); @@ -53,6 +56,9 @@ GoogleFontApiTest.prototype.testCallOnReadyWithFontFamilyLoadingApiUrlChanged = }, createCssLink: function(csslink) { link = csslink; + }, + getProtocol: function() { + return 'http:'; } }; var userAgent = new webfont.UserAgent("Test", "1.0", true); @@ -95,6 +101,9 @@ GoogleFontApiTest.prototype.testSpacesReplacedByPlus = function() { }, createCssLink: function(csslink) { link = csslink; + }, + getProtocol: function() { + return 'http:'; } }; var userAgent = new webfont.UserAgent("Test", "1.0", true); @@ -137,6 +146,9 @@ GoogleFontApiTest.prototype.testLoadWithVariations = function() { }, createCssLink: function(csslink) { link = csslink; + }, + getProtocol: function() { + return 'http:'; } }; var userAgent = new webfont.UserAgent("Test", "1.0", true); diff --git a/src-test/monotype/monotype_script_test.js b/src-test/monotype/monotype_script_test.js index 145be14e..c0ae8ea3 100644 --- a/src-test/monotype/monotype_script_test.js +++ b/src-test/monotype/monotype_script_test.js @@ -1,46 +1,7 @@ var MonotypeScriptTest = TestCase('MonotypeScriptTest'); -MonotypeScriptTest.prototype.testIfProtocolMethodIsReturningProperly = function () { - var fakeDocument = { - location: { protocol: "https:" } - }; - var global = {}; // should be window in actual situation. - var script = null; - var userAgent = new webfont.UserAgent("Test", "1.0", true); - var config = { projectId: '01e2ff27-25bf-4801-a23e-73d328e6c7cc' }; - var fakedom = []; - var fakeDomHelper = { - createScriptSrc: function (s) { - script = { src: s }; - return script; - }, - insertInto: function (tag, elem) { - fakedom[tag].push(elem); - global[webfont.MonotypeScript.HOOK + config.projectId] = function () { - return ["aachen bold", "kid print regualr"]; - }; - if (script.onload) { - script.onload(); - } - } - }; - - var monotypeScript = new webfont.MonotypeScript(global, userAgent, fakeDomHelper, fakeDocument, config); - assertEquals("https:", monotypeScript.protocol()); - - fakeDocument = { - location: { protocol: "http:" } - }; - - monotypeScript = new webfont.MonotypeScript(global, userAgent, fakeDomHelper, fakeDocument, config); - assertEquals("http:", monotypeScript.protocol()); -}; - MonotypeScriptTest.prototype.testIfScriptTagIsAdded = function () { var fakedom = { 'head': [], 'body': [] }; - var fakeDocument = { - location: { protocol: "http:" } - }; var script = null; var global = {}; // should be window in actual situation. var families = null; @@ -59,6 +20,12 @@ MonotypeScriptTest.prototype.testIfScriptTagIsAdded = function () { if (script.onload) { script.onload(); } + }, + getLoadWindow: function () { + return global; + }, + getProtocol: function () { + return "http:"; } }; @@ -77,7 +44,7 @@ MonotypeScriptTest.prototype.testIfScriptTagIsAdded = function () { } var isSupport = null; var userAgent = new webfont.UserAgent("Test", "1.0", true); - var monotypeScript = new webfont.MonotypeScript(global, userAgent, fakeDomHelper, fakeDocument, config); + var monotypeScript = new webfont.MonotypeScript(userAgent, fakeDomHelper, config); monotypeScript.supportUserAgent(userAgent, function (support) { isSupport = support; }); monotypeScript.load(function (fontFamilies) { families = fontFamilies; @@ -93,12 +60,7 @@ MonotypeScriptTest.prototype.testIfScriptTagIsAdded = function () { //If current page is browsed using https protocol, the added script should be requested with SSL. MonotypeScriptTest.prototype.testIfScriptTagHasCorrectSSL = function () { var fakedom = { 'head': [], 'body': [] }; - var fakeDocument1 = { - location: { protocol: "https:" } - }; - var fakeDocument2 = { - location: { protocol: "http:" } - }; + var fakeProtocol = "https:"; var script = null; var global = {}; // should be window in actual situation. var families = null; @@ -117,6 +79,12 @@ MonotypeScriptTest.prototype.testIfScriptTagHasCorrectSSL = function () { if (script.onload) { script.onload(); } + }, + getLoadWindow: function () { + return global; + }, + getProtocol: function () { + return fakeProtocol; } }; @@ -136,7 +104,7 @@ MonotypeScriptTest.prototype.testIfScriptTagHasCorrectSSL = function () { } var isSupport = null; var userAgent = new webfont.UserAgent("Test", "1.0", true); - var monotypeScript = new webfont.MonotypeScript(global, userAgent, fakeDomHelper, fakeDocument1, config); + var monotypeScript = new webfont.MonotypeScript(userAgent, fakeDomHelper, config); monotypeScript.supportUserAgent(userAgent, function (support) { isSupport = support; }); monotypeScript.load(function (fontFamilies) { families = fontFamilies; @@ -150,7 +118,8 @@ MonotypeScriptTest.prototype.testIfScriptTagHasCorrectSSL = function () { //one page can have multiple projects, but not 2 projects with same projectId. config = { projectId: '01e2ff27-25bf-4801-a23e-73d328e6c7c1', api: "http://fast.fonts.com/jsapidev" }; - var monotypeScript2 = new webfont.MonotypeScript(global, userAgent, fakeDomHelper, fakeDocument2, config); + fakeProtocol = "http:"; + var monotypeScript2 = new webfont.MonotypeScript(userAgent, fakeDomHelper, config); monotypeScript2.supportUserAgent(userAgent, function (support) { isSupport = support; }); monotypeScript2.load(function (fontFamilies) { families = fontFamilies; @@ -182,11 +151,11 @@ MonotypeScriptTest.prototype.testIfScriptTagIsAddedWithoutApiurl = function () { if (script.onload) { script.onload(); } - } - }; - - var fakeDocHelper = { - protocol: function () { + }, + getLoadWindow: function () { + return global; + }, + getProtocol: function () { return "http:"; } }; @@ -207,7 +176,7 @@ MonotypeScriptTest.prototype.testIfScriptTagIsAddedWithoutApiurl = function () { var isSupport = null; var userAgent = new webfont.UserAgent("Test", "1.0", true); - var monotypeScript = new webfont.MonotypeScript(global, userAgent, fakeDomHelper, fakeDocHelper, config); + var monotypeScript = new webfont.MonotypeScript(userAgent, fakeDomHelper, config); monotypeScript.supportUserAgent(userAgent, function (support) { isSupport = support; }); monotypeScript.load(function (fontFamilies) { @@ -224,7 +193,6 @@ MonotypeScriptTest.prototype.testIfScriptTagIsAddedWithoutApiurl = function () { //If current page is browsed using https protocol, the added script should be requested with SSL. MonotypeScriptTest.prototype.testIfScriptTagIsAddedWithoutApiurlAndTheScriptUrlHasCorrectSSL = function () { var fakedom = { 'head': [], 'body': [] }; - var fakeDocument = { location: { protocol: "https:"} }; var global = {}; // should be window in actual situation. var script = null; var families = null; @@ -243,6 +211,12 @@ MonotypeScriptTest.prototype.testIfScriptTagIsAddedWithoutApiurlAndTheScriptUrlH if (script.onload) { script.onload(); } + }, + getLoadWindow: function () { + return global; + }, + getProtocol: function () { + return "https:"; } }; @@ -262,7 +236,7 @@ MonotypeScriptTest.prototype.testIfScriptTagIsAddedWithoutApiurlAndTheScriptUrlH var isSupport = null; var userAgent = new webfont.UserAgent("Test", "1.0", true); - var monotypeScript = new webfont.MonotypeScript(global, userAgent, fakeDomHelper, fakeDocument, config); + var monotypeScript = new webfont.MonotypeScript(userAgent, fakeDomHelper, config); monotypeScript.supportUserAgent(userAgent, function (support) { isSupport = support; }); monotypeScript.load(function (fontFamilies) { @@ -297,18 +271,18 @@ MonotypeScriptTest.prototype.testWithoutProjectId = function () { if (script.onload) { script.onload(); } - } - }; - - var fakeDocHelper = { - protocol: function () { + }, + getLoadWindow: function () { + return global; + }, + getProtocol: function () { return "http:"; } }; var isSupport = null; var userAgent = new webfont.UserAgent("Test", "1.0", true); - var monotypeScript = new webfont.MonotypeScript(global, userAgent, fakeDomHelper, fakeDocHelper, config); + var monotypeScript = new webfont.MonotypeScript(userAgent, fakeDomHelper, config); monotypeScript.supportUserAgent(userAgent, function (support) { isSupport = support; }); monotypeScript.load(function (fontFamilies) { diff --git a/src-test/typekit/typekit_script_test.js b/src-test/typekit/typekit_script_test.js index 58305aa7..b4fd21cd 100644 --- a/src-test/typekit/typekit_script_test.js +++ b/src-test/typekit/typekit_script_test.js @@ -6,16 +6,22 @@ TypekitScriptTest.prototype.testSupportAndLoadLifecycle = function() { }; var insert = ''; var src = ''; + var global = {}; var fakeDomHelper = { insertInto: function(tag, e) { insert = tag; }, createScriptSrc: function(srcLink) { src = srcLink; + }, + getLoadWindow: function() { + return global; + }, + getProtocol: function() { + return 'http:'; } }; - var global = {}; - var typeKit = new webfont.TypekitScript(global, fakeDomHelper, configuration); + var typeKit = new webfont.TypekitScript(fakeDomHelper, configuration); // supportUserAgent var userAgent = 'user agent'; @@ -65,16 +71,22 @@ TypekitScriptTest.prototype.testLoadWithVariations = function() { }; var insert = ''; var src = ''; + var global = {}; var fakeDomHelper = { insertInto: function(tag, e) { insert = tag; }, createScriptSrc: function(srcLink) { src = srcLink; + }, + getLoadWindow: function() { + return global; + }, + getProtocol: function() { + return 'http:'; } }; - var global = {}; - var typeKit = new webfont.TypekitScript(global, fakeDomHelper, configuration); + var typeKit = new webfont.TypekitScript(fakeDomHelper, configuration); // supportUserAgent var userAgent = 'user agent'; @@ -129,9 +141,15 @@ TypekitScriptTest.prototype.testAlternateApi = function() { }, createScriptSrc: function(srcLink) { src = srcLink; + }, + getLoadWindow: function() { + return {}; + }, + getProtocol: function() { + return 'http:'; } }; - var typeKit = new webfont.TypekitScript({}, fakeDomHelper, configuration); + var typeKit = new webfont.TypekitScript(fakeDomHelper, configuration); var userAgent = 'user agent'; var isSupport = null; @@ -152,9 +170,15 @@ TypekitScriptTest.prototype.testNoKitId = function() { }, createScriptSrc: function(srcLink) { src = srcLink; + }, + getLoadWindow: function() { + return {}; + }, + getProtocol: function() { + return 'http:'; } }; - var typeKit = new webfont.TypekitScript({}, fakeDomHelper, configuration); + var typeKit = new webfont.TypekitScript(fakeDomHelper, configuration); var userAgent = 'user agent'; var isSupport = null; diff --git a/src/ascender/ascender_script.js b/src/ascender/ascender_script.js index dad558ec..121214e6 100644 --- a/src/ascender/ascender_script.js +++ b/src/ascender/ascender_script.js @@ -33,7 +33,7 @@ webfont.AscenderScript.prototype.supportUserAgent = function(userAgent, support) webfont.AscenderScript.prototype.load = function(onReady) { var key = this.configuration_['key']; - var protocol = (('https:' == document.location.protocol) ? 'https:' : 'http:'); + var protocol = this.domHelper_.getProtocol(); var url = protocol + '//webfonts.fontslive.com/css/' + key + '.css'; this.domHelper_.insertInto('head', this.domHelper_.createCssLink(url)); var fv = this.parseFamiliesAndVariations(this.configuration_['families']); @@ -78,7 +78,6 @@ webfont.AscenderScript.prototype.parseVariations = function(source){ return variations; }; -globalNamespaceObject.addModule(webfont.AscenderScript.NAME, function(configuration) { - var domHelper = new webfont.DomHelper(document); +globalNamespaceObject.addModule(webfont.AscenderScript.NAME, function(configuration, domHelper) { return new webfont.AscenderScript(domHelper, configuration); }); diff --git a/src/core/domhelper.js b/src/core/domhelper.js index e98877f8..da0eaec0 100644 --- a/src/core/domhelper.js +++ b/src/core/domhelper.js @@ -1,11 +1,17 @@ /** * Handles common DOM manipulation tasks. The aim of this library is to cover * the needs of typical font loading. Not more, not less. - * @param {HTMLDocument} doc The HTML document we'll manipulate. + * @param {Window} mainWindow The main window webfontloader.js is loaded in. + * @param {Window=} opt_loadWindow The window we'll load the font into. By + * default, the main window is used. * @constructor */ -webfont.DomHelper = function(doc) { - this.document_ = doc; +webfont.DomHelper = function(mainWindow, opt_loadWindow) { + this.mainWindow_ = mainWindow; + this.loadWindow_ = opt_loadWindow || mainWindow; + + /** @type {Document} */ + this.document_ = this.loadWindow_.document; /** @type {boolean|undefined} */ this.supportForStyle_ = undefined; @@ -28,7 +34,7 @@ webfont.DomHelper.prototype.createElement = function(elem, opt_attr, if (opt_attr.hasOwnProperty(attr)) { if (attr == "style") { this.setStyle(domElement, opt_attr[attr]); - } else { + } else { domElement.setAttribute(attr, opt_attr[attr]); } } @@ -194,3 +200,29 @@ webfont.DomHelper.prototype.hasSupportForStyle_ = function() { } return this.supportForStyle_ }; + +/** + * @return {Window} The main window webfontloader.js is loaded in (for config). + */ +webfont.DomHelper.prototype.getMainWindow = function() { + return this.mainWindow_; +}; + +/** + * @return {Window} The window that we're loading the font(s) into. + */ +webfont.DomHelper.prototype.getLoadWindow = function() { + return this.loadWindow_; +}; + +/** + * @return {string} The protocol (http: or https:) to request resources in. + */ +webfont.DomHelper.prototype.getProtocol = function() { + var protocol = this.loadWindow_.location.protocol; + // For empty iframes, fallback to main window's protocol. + if (protocol == 'about:') { + protocol = this.mainWindow_.location.protocol; + } + return protocol == 'https:' ? 'https:' : 'http:'; +}; diff --git a/src/core/font.js b/src/core/font.js index fc01c6ee..526a7a52 100644 --- a/src/core/font.js +++ b/src/core/font.js @@ -1,11 +1,14 @@ /** + * @param {Window} mainWindow The main application window containing + * webfontloader.js. + * @param {webfont.FontModuleLoader} fontModuleLoader A loader instance to use. + * @param {function(function(), number=)} asyncCall An async function to use. + * @param {webfont.UserAgent} userAgent The detected user agent to load for. * @constructor */ -webfont.WebFont = function(domHelper, fontModuleLoader, htmlElement, asyncCall, - userAgent) { - this.domHelper_ = domHelper; +webfont.WebFont = function(mainWindow, fontModuleLoader, asyncCall, userAgent) { + this.mainWindow_ = mainWindow; this.fontModuleLoader_ = fontModuleLoader; - this.htmlElement_ = htmlElement; this.asyncCall_ = asyncCall; this.userAgent_ = userAgent; this.moduleLoading_ = 0; @@ -17,8 +20,11 @@ webfont.WebFont.prototype.addModule = function(name, factory) { }; webfont.WebFont.prototype.load = function(configuration) { + var context = configuration['context'] || this.mainWindow_; + this.domHelper_ = new webfont.DomHelper(this.mainWindow_, context); + var eventDispatcher = new webfont.EventDispatcher( - this.domHelper_, this.htmlElement_, configuration); + this.domHelper_, context.document.documentElement, configuration); if (this.userAgent_.isSupportingWebFont()) { this.load_(eventDispatcher, configuration); @@ -66,7 +72,7 @@ webfont.WebFont.prototype.onModuleReady_ = function(eventDispatcher, fontWatcher }; webfont.WebFont.prototype.load_ = function(eventDispatcher, configuration) { - var modules = this.fontModuleLoader_.getModules(configuration), + var modules = this.fontModuleLoader_.getModules(configuration, this.domHelper_), self = this; this.moduleFailedLoading_ = this.moduleLoading_ = modules.length; diff --git a/src/core/fontmoduleloader.js b/src/core/fontmoduleloader.js index 292327d2..ac25b5a1 100644 --- a/src/core/fontmoduleloader.js +++ b/src/core/fontmoduleloader.js @@ -9,7 +9,7 @@ webfont.FontModuleLoader.prototype.addModuleFactory = function(name, factory) { this.modules_[name] = factory; }; -webfont.FontModuleLoader.prototype.getModules = function(configuration) { +webfont.FontModuleLoader.prototype.getModules = function(configuration, domHelper) { var modules = []; for (var key in configuration) { @@ -17,7 +17,7 @@ webfont.FontModuleLoader.prototype.getModules = function(configuration) { var moduleFactory = this.modules_[key]; if (moduleFactory) { - modules.push(moduleFactory(configuration[key])); + modules.push(moduleFactory(configuration[key], domHelper)); } } } diff --git a/src/core/initialize.js b/src/core/initialize.js index af007c9c..b362cfee 100644 --- a/src/core/initialize.js +++ b/src/core/initialize.js @@ -5,11 +5,10 @@ var globalName = 'WebFont'; var globalNamespaceObject = window[globalName] = (function() { var userAgentParser = new webfont.UserAgentParser(navigator.userAgent, document); var userAgent = userAgentParser.parse(); - var domHelper = new webfont.DomHelper(document); + var fontModuleLoader = new webfont.FontModuleLoader(); var asyncCall = function(func, timeout) { setTimeout(func, timeout); }; - return new webfont.WebFont(domHelper, new webfont.FontModuleLoader(), - document.documentElement, asyncCall, userAgent); + return new webfont.WebFont(window, fontModuleLoader, asyncCall, userAgent); })(); // Export the public API. diff --git a/src/custom/customcss.js b/src/custom/customcss.js index 9db15ab2..0b9b1d63 100644 --- a/src/custom/customcss.js +++ b/src/custom/customcss.js @@ -31,7 +31,6 @@ webfont.CustomCss.prototype.supportUserAgent = function(userAgent, support) { return support(userAgent.isSupportingWebFont()); }; -globalNamespaceObject.addModule(webfont.CustomCss.NAME, function(configuration) { - var domHelper = new webfont.DomHelper(document); +globalNamespaceObject.addModule(webfont.CustomCss.NAME, function(configuration, domHelper) { return new webfont.CustomCss(domHelper, configuration); }); diff --git a/src/fontdeck/fontdeck_script.js b/src/fontdeck/fontdeck_script.js index 29728ac4..222be6b8 100644 --- a/src/fontdeck/fontdeck_script.js +++ b/src/fontdeck/fontdeck_script.js @@ -1,8 +1,7 @@ /** * @constructor */ -webfont.FontdeckScript = function(global, domHelper, configuration) { - this.global_ = global; +webfont.FontdeckScript = function(domHelper, configuration) { this.domHelper_ = domHelper; this.configuration_ = configuration; this.fontFamilies_ = []; @@ -15,24 +14,28 @@ webfont.FontdeckScript.HOOK = '__webfontfontdeckmodule__'; webfont.FontdeckScript.API = '//f.fontdeck.com/s/css/js/'; webfont.FontdeckScript.prototype.getScriptSrc = function(projectId) { - var protocol = 'https:' == this.global_.location.protocol ? 'https:' : 'http:'; + var protocol = this.domHelper_.getProtocol(); + // For empty iframes, fall back to main window's hostname. + var hostname = this.domHelper_.getLoadWindow().location.hostname || + this.domHelper_.getMainWindow().location.hostname; var api = this.configuration_['api'] || webfont.FontdeckScript.API; - return protocol + api + this.global_.document.location.hostname + '/' + projectId + '.js'; + return protocol + api + hostname + '/' + projectId + '.js'; }; webfont.FontdeckScript.prototype.supportUserAgent = function(userAgent, support) { var projectId = this.configuration_['id']; + var loadWindow = this.domHelper_.getLoadWindow(); var self = this; if (projectId) { // Provide data to Fontdeck for processing. - if (!this.global_[webfont.FontdeckScript.HOOK]) { - this.global_[webfont.FontdeckScript.HOOK] = {}; + if (!loadWindow[webfont.FontdeckScript.HOOK]) { + loadWindow[webfont.FontdeckScript.HOOK] = {}; } // Fontdeck will call this function to indicate support status // and what fonts are provided. - this.global_[webfont.FontdeckScript.HOOK][projectId] = function(fontdeckSupports, data) { + loadWindow[webfont.FontdeckScript.HOOK][projectId] = function(fontdeckSupports, data) { for (var i = 0, j = data['fonts'].length; i