Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Commit

Permalink
Merge pull request #8144 from MarcelGerber/live-css-iframe
Browse files Browse the repository at this point in the history
Fix Live CSS with an iframe element
  • Loading branch information
redmunds committed Aug 6, 2014
2 parents 45bbc38 + 1893696 commit e5e1f46
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 65 deletions.
96 changes: 55 additions & 41 deletions src/LiveDevelopment/Agents/CSSAgent.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,15 @@ define(function CSSAgent(require, exports, module) {

require("thirdparty/path-utils/path-utils.min");

var _ = require("thirdparty/lodash");

var Inspector = require("LiveDevelopment/Inspector/Inspector");

/**
* Stylesheet urls
* Stylesheet details
* @type {Object.<string, CSS.CSSStyleSheetHeader>}
*/
var _urlToStyle = {};

/**
* Map of stylesheet ids to urls
* @type {Object.<string, string>}
*/
var _styleSheetIdToUrl;
var _styleSheetDetails = {};

/**
* Is getAllStyleSheets() API defined? - This is undefined until we test for API
Expand All @@ -73,18 +69,26 @@ define(function CSSAgent(require, exports, module) {
* @param {frame: Frame} res
*/
function _onFrameNavigated(event, res) {
// Clear maps when navigating to a new page
_urlToStyle = {};
_styleSheetIdToUrl = {};
// Clear maps when navigating to a new page, but not if an iframe was loaded
if (!res.frame.parentId) {
_styleSheetDetails = {};
}
}

/**
* Get a style sheet for a url
* Get the style sheets for a url
* @param {string} url
* @return {CSS.CSSStyleSheetHeader}
* @return {Object.<string, CSSStyleSheetHeader>}
*/
function styleForURL(url) {
return _urlToStyle[_canonicalize(url)];
var styleSheetId, styles = {};
url = _canonicalize(url);
for (styleSheetId in _styleSheetDetails) {
if (_styleSheetDetails[styleSheetId].canonicalizedURL === url) {
styles[styleSheetId] = _styleSheetDetails[styleSheetId];
}
}
return styles;
}

/**
Expand All @@ -93,24 +97,36 @@ define(function CSSAgent(require, exports, module) {
* @deprecated
*/
function getStylesheetURLs() {
var urls = [], url;
for (url in _urlToStyle) {
if (_urlToStyle.hasOwnProperty(url)) {
urls.push(url);
}
var styleSheetId, urls = [];
for (styleSheetId in _styleSheetDetails) {
urls[_styleSheetDetails[styleSheetId].canonicalizedURL] = true;
}
return urls;
return _.keys(urls);
}

/**
* Reload a CSS style sheet from a document
* @param {Document} document
* @param {string=} newContent new content of every stylesheet. Defaults to doc.getText() if omitted
* @return {jQuery.Promise}
*/
function reloadCSSForDocument(doc) {
var style = styleForURL(doc.url);
console.assert(style, "Style Sheet for document not loaded: " + doc.url);
return Inspector.CSS.setStyleSheetText(style.styleSheetId, doc.getText());
function reloadCSSForDocument(doc, newContent) {
var styles = styleForURL(doc.url),
styleSheetId,
deferreds = [];

if (newContent === undefined) {
newContent = doc.getText();
}
for (styleSheetId in styles) {
deferreds.push(Inspector.CSS.setStyleSheetText(styles[styleSheetId].styleSheetId, newContent));
}
if (!deferreds.length) {
console.error("Style Sheet for document not loaded: " + doc.url);
return new $.Deferred().reject().promise();
}
// return master deferred
return $.when.apply($, deferreds);
}

/**
Expand All @@ -119,9 +135,7 @@ define(function CSSAgent(require, exports, module) {
* @return {jQuery.Promise}
*/
function clearCSSForDocument(doc) {
var style = styleForURL(doc.url);
console.assert(style, "Style Sheet for document not loaded: " + doc.url);
return Inspector.CSS.setStyleSheetText(style.styleSheetId, "");
return reloadCSSForDocument(doc, "");
}

/**
Expand All @@ -130,16 +144,21 @@ define(function CSSAgent(require, exports, module) {
* @param {header: CSSStyleSheetHeader}
*/
function _styleSheetAdded(event, res) {
var url = _canonicalize(res.header.sourceURL),
existing = _urlToStyle[url];
var url = _canonicalize(res.header.sourceURL),
existing = styleForURL(res.header.sourceURL),
styleSheetId = res.header.styleSheetId,
duplicate;

// detect duplicates
if (existing && existing.styleSheetId === res.header.styleSheetId) {
duplicate = _.some(existing, function (styleSheet) {
return styleSheet && styleSheet.styleSheetId === styleSheetId;
});
if (duplicate) {
return;
}

_urlToStyle[url] = res.header;
_styleSheetIdToUrl[res.header.styleSheetId] = url;
_styleSheetDetails[styleSheetId] = res.header;
_styleSheetDetails[styleSheetId].canonicalizedURL = url; // canonicalized URL

$(exports).triggerHandler("styleSheetAdded", [url, res.header]);
}
Expand All @@ -150,16 +169,11 @@ define(function CSSAgent(require, exports, module) {
* @param {styleSheetId: StyleSheetId}
*/
function _styleSheetRemoved(event, res) {
var url = _styleSheetIdToUrl[res.styleSheetId],
header = url && _urlToStyle[url];

if (url) {
delete _urlToStyle[url];
}
var header = _styleSheetDetails[res.styleSheetId];

delete _styleSheetIdToUrl[res.styleSheetId];
delete _styleSheetDetails[res.styleSheetId];

$(exports).triggerHandler("styleSheetRemoved", [url, header]);
$(exports).triggerHandler("styleSheetRemoved", [header.canonicalizedURL, header]);
}

/**
Expand Down Expand Up @@ -233,4 +247,4 @@ define(function CSSAgent(require, exports, module) {
exports.clearCSSForDocument = clearCSSForDocument;
exports.load = load;
exports.unload = unload;
});
});
7 changes: 5 additions & 2 deletions src/LiveDevelopment/Agents/NetworkAgent.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ define(function NetworkAgent(require, exports, module) {
// WebInspector Event: Page.frameNavigated
function _onFrameNavigated(event, res) {
// res = {frame}
_reset();
// Clear log when navigating to a new page, but not if an iframe was loaded
if (!res.frame.parentId) {
_reset();
}
_logURL(res.frame.url);
}

Expand Down Expand Up @@ -101,4 +104,4 @@ define(function NetworkAgent(require, exports, module) {
exports.enable = enable;
exports.load = load;
exports.unload = unload;
});
});
7 changes: 6 additions & 1 deletion src/LiveDevelopment/Agents/RemoteAgent.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,12 @@ define(function RemoteAgent(require, exports, module) {

// WebInspector Event: Page.frameNavigated
function _onFrameNavigated(event, res) {
// res = {timestamp}
// res = {frame}
// Re-inject RemoteFunctions when navigating to a new page, but not if an iframe was loaded
if (res.frame.parentId) {
return;
}

_stopKeepAliveInterval();

// inject RemoteFunctions
Expand Down
8 changes: 5 additions & 3 deletions src/LiveDevelopment/Agents/ScriptAgent.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,10 @@ define(function ScriptAgent(require, exports, module) {
* @param {frame: Frame} res
*/
function _onFrameNavigated(event, res) {
// Clear maps when navigating to a new page
_reset();
// Clear maps when navigating to a new page, but not if an iframe was loaded
if (!res.frame.parentId) {
_reset();
}
}

/** Initialize the agent */
Expand Down Expand Up @@ -171,4 +173,4 @@ define(function ScriptAgent(require, exports, module) {
exports.scriptForURL = scriptForURL;
exports.load = load;
exports.unload = unload;
});
});
30 changes: 22 additions & 8 deletions src/LiveDevelopment/Documents/CSSDocument.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,27 @@ define(function CSSDocumentModule(require, exports, module) {
* @return {jQuery.promise} Promise resolved with the text content of this CSS document
*/
CSSDocument.prototype.getSourceFromBrowser = function getSourceFromBrowser() {
function getOnlyValue(obj) {
var key;
for (key in obj) {
if (_.has(obj, key)) {
return obj[key];
}
}
return null;
}

var deferred = new $.Deferred(),
styleSheetId = this._getStyleSheetHeader().styleSheetId,
inspectorPromise = Inspector.CSS.getStyleSheetText(styleSheetId);
styleSheetHeader = this._getStyleSheetHeader(),
styleSheet = getOnlyValue(styleSheetHeader);

inspectorPromise.then(function (res) {
deferred.resolve(res.text);
}, deferred.reject);
if (styleSheet) {
Inspector.CSS.getStyleSheetText(styleSheet.styleSheetId).then(function (res) {
deferred.resolve(res.text);
}, deferred.reject);
} else {
deferred.reject();
}

return deferred.promise();
};
Expand Down Expand Up @@ -252,12 +266,12 @@ define(function CSSDocumentModule(require, exports, module) {
Inspector.CSS.getMatchedStylesForNode(node.nodeId, function onGetMatchesStyles(res) {
// res = {matchedCSSRules, pseudoElements, inherited}
var codeMirror = this.editor._codeMirror,
styleSheetId = this._getStyleSheetHeader().styleSheetId;
styleSheetIds = this._getStyleSheetHeader();

var i, rule, from, to;
for (i in res.matchedCSSRules) {
rule = res.matchedCSSRules[i];
if (rule.ruleId && rule.ruleId.styleSheetId === styleSheetId) {
if (rule.ruleId && styleSheetIds[rule.ruleId.styleSheetId]) {
from = codeMirror.posFromIndex(rule.selectorRange.start);
to = codeMirror.posFromIndex(rule.style.range.end);
this._highlight.push(codeMirror.markText(from, to, { className: "highlight" }));
Expand All @@ -268,4 +282,4 @@ define(function CSSDocumentModule(require, exports, module) {

// Export the class
module.exports = CSSDocument;
});
});
9 changes: 9 additions & 0 deletions test/spec/LiveDevelopment-test-files/iframe.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#testId {
font-size: 20px;
}

.testClass {
background-color:rgba(102,102,204,.5);
color:rgba(255,255,255,1);
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8">
<title>Simple Test</title>
<link rel="stylesheet" href="simpleShared.css">
<link rel="stylesheet" href="simple2.css">
<link rel="stylesheet" href="iframe.css">
</head>

<body>
Expand Down
14 changes: 14 additions & 0 deletions test/spec/LiveDevelopment-test-files/simple1iframe.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Simple Test</title>
<link rel="stylesheet" href="simpleShared.css">
<link rel="stylesheet" href="simple1.css">
</head>

<body>
<p id="testId" class="testClass">iframes are cool.</p>
<iframe src="iframe.html"></iframe>
</body>
</html>
8 changes: 0 additions & 8 deletions test/spec/LiveDevelopment-test-files/simple2.css

This file was deleted.

10 changes: 9 additions & 1 deletion test/spec/LiveDevelopment-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ define(function (require, exports, module) {
HighlightAgentModule.load();

// module spies
spyOn(CSSAgentModule, "styleForURL").andReturn("");
spyOn(CSSAgentModule, "styleForURL").andReturn([]);
spyOn(CSSAgentModule, "reloadCSSForDocument").andCallFake(function () { return new $.Deferred().resolve(); });
spyOn(HighlightAgentModule, "redraw").andCallFake(function () {});
spyOn(HighlightAgentModule, "rule").andCallFake(function () {});
Expand Down Expand Up @@ -642,6 +642,10 @@ define(function (require, exports, module) {
doOneTest("simple1Query.html", "simple1.css");
});

it("should push changes after loading an iframe", function () {
doOneTest("simple1iframe.html", "simple1.css");
});

it("should push in memory css changes made before the session starts", function () {
var localText,
browserText;
Expand Down Expand Up @@ -767,6 +771,10 @@ define(function (require, exports, module) {
expect(updatedNode.value).toBe("Live Preview in Brackets is awesome!");
});
});

it("should push changes to the iframes' css file", function () {
doOneTest("simple1iframe.html", "iframe.css");
});
});

describe("HTML Editing", function () {
Expand Down

0 comments on commit e5e1f46

Please sign in to comment.