LiveCSSDocument manages a single CSS source document
Editing the document will cause the style sheet to be reloaded in the browser, which immediately updates the appearance of the rendered document.
DOM nodes corresponding to the rule at the current cursor position are highlighted.
LiveCSSDocument dispatches these events: deleted - When the file for the underlying Document has been deleted. The 2nd argument to the listener will be this LiveCSSDocument.
var LiveCSSDocument = function LiveCSSDocument(protocol, urlResolver, doc, editor, roots) {
LiveDocument.apply(this, arguments);
// Add a ref to the doc since we're listening for change events
this.doc.addRef();
this.onChange = this.onChange.bind(this);
this.onDeleted = this.onDeleted.bind(this);
this.doc.on("change.LiveCSSDocument", this.onChange);
this.doc.on("deleted.LiveCSSDocument", this.onDeleted);
if (editor) {
this._attachToEditor(editor);
}
};
LiveCSSDocument.prototype = Object.create(LiveDocument.prototype);
LiveCSSDocument.prototype.constructor = LiveCSSDocument;
LiveCSSDocument.prototype.parentClass = LiveDocument.prototype;
EventDispatcher.makeEventDispatcher(LiveCSSDocument.prototype);
When the user edits the file, update the stylesheet in the browser and redraw highlights.
LiveCSSDocument.prototype._updateBrowser = function () {
var i,
docUrl = this.doc.url;
// Determines whether an url() line contains a relative or absolute URL, and makes
// the URL absolute to the CSS file if it is relative
function makeUrlsRelativeToCss(match, quotationMark, url) {
if (PathUtils.isRelativeUrl(url)) {
var absUrl = PathUtils.makeUrlAbsolute(url, docUrl);
return "url(" + quotationMark + absUrl + quotationMark + ")";
}
return match;
}
for (i = 0; i < this.roots.length; i++) {
if (docUrl !== this.roots[i].toString()) {
// if it's not directly included through <link>,
// reload the original doc
this.trigger("updateDoc", this.roots[i]);
} else {
var docText = this.doc.getText();
// Replace all occurrences of url() where the URL is relative to the CSS file with
// an absolute URL so it is relative to the CSS file, not the HTML file (see #11936)
docText = docText.replace(/\burl\(\s*(["']?)([^)\n]+)\1\s*\)/ig, makeUrlsRelativeToCss);
this.protocol.setStylesheetText(docUrl, docText);
}
}
this.redrawHighlights();
};
LiveCSSDocument.prototype.close = function () {
this.doc.off(".LiveCSSDocument");
this.doc.releaseRef();
this.parentClass.close.call(this);
};
LiveCSSDocument.prototype.isLiveEditingEnabled = function () {
return true;
};
LiveCSSDocument.prototype.onChange = function (event, editor, change) {
this._updateBrowser();
};
LiveCSSDocument.prototype.onDeleted = function (event) {
// TODO Need to add protocol API to remove the stylesheet from the document.
//CSSAgent.clearCSSForDocument(this.doc);
// shut down, since our Document is now dead
this.close();
this.trigger("deleted", [this]);
};
// Only used for unit testing.
LiveCSSDocument.prototype.getSourceFromBrowser = function () {
var deferred = new $.Deferred();
this.protocol.getStylesheetText(this.doc.url)
.then(function (res) {
deferred.resolve(res.text);
}, deferred.reject);
return deferred.promise();
};
// Export the class
module.exports = LiveCSSDocument;
});
LiveCSSDocument.prototype.updateHighlight = function () {
if (this.isHighlightEnabled() && this.editor) {
var editor = this.editor,
selectors = [];
_.each(this.editor.getSelections(), function (sel) {
var selector = CSSUtils.findSelectorAtDocumentPos(editor, (sel.reversed ? sel.end : sel.start));
if (selector) {
selectors.push(selector);
}
});
if (selectors.length) {
this.highlightRule(selectors.join(","));
} else {
this.hideHighlight();
}
}
};