diff --git a/packages/blaze/attrs.js b/packages/blaze/attrs.js index d3c5e0f657..58c4ff5512 100644 --- a/packages/blaze/attrs.js +++ b/packages/blaze/attrs.js @@ -1,3 +1,10 @@ +var jsUrlsAllowed = false; +Blaze._allowJavascriptUrls = function () { + jsUrlsAllowed = true; +}; +Blaze._javascriptUrlsAllowed = function () { + return jsUrlsAllowed; +}; // An AttributeHandler object is responsible for updating a particular attribute // of a particular element. AttributeHandler subclasses implement @@ -244,7 +251,7 @@ var getUrlProtocol = function (url) { // UrlHandler is an attribute handler for all HTML attributes that take // URL values. It disallows javascript: URLs, unless -// UI._allowJavascriptUrls() has been called. To detect javascript: +// Blaze._allowJavascriptUrls() has been called. To detect javascript: // urls, we set the attribute on a dummy anchor element and then read // out the 'protocol' property of the attribute. var origUpdate = AttributeHandler.prototype.update; @@ -253,14 +260,16 @@ var UrlHandler = AttributeHandler.extend({ var self = this; var args = arguments; - if (UI._javascriptUrlsAllowed()) { + if (Blaze._javascriptUrlsAllowed()) { origUpdate.apply(self, args); } else { var isJavascriptProtocol = (getUrlProtocol(value) === "javascript:"); if (isJavascriptProtocol) { + var blazeSymbol = ((typeof UI !== 'undefined') && UI === Blaze) ? + 'UI' : 'Blaze'; Meteor._debug("URLs that use the 'javascript:' protocol are not " + "allowed in URL attribute values. " + - "Call UI._allowJavascriptUrls() " + + "Call " + blazeSymbol + "._allowJavascriptUrls() " + "to enable them."); origUpdate.apply(self, [element, oldValue, null]); } else { diff --git a/packages/blaze/domrange.js b/packages/blaze/domrange.js index ad67a7f024..96ae8bf49d 100644 --- a/packages/blaze/domrange.js +++ b/packages/blaze/domrange.js @@ -304,12 +304,12 @@ DOMRange.prototype._memberIn = function (m) { DOMRange._destroy = function (m, _skipNodes) { if (m instanceof DOMRange) { if (m.view) - Blaze.destroyView(m.view, _skipNodes); + Blaze._destroyView(m.view, _skipNodes); m.parentRange = null; } else if ((! _skipNodes) && m.nodeType === 1) { // DOM Element if (m.$blaze_range) { - Blaze.destroyNode(m); + Blaze._destroyNode(m); m.$blaze_range = null; } } diff --git a/packages/blaze/lookup.js b/packages/blaze/lookup.js index 8b9c678f14..b70c11d9e6 100644 --- a/packages/blaze/lookup.js +++ b/packages/blaze/lookup.js @@ -1,3 +1,10 @@ +Blaze._globalHelpers = {}; + +Blaze.registerHelper = function (name, func) { + Blaze._globalHelpers[name] = func; +}; + + var bindIfIsFunction = function (x, target) { if (typeof x !== 'function') return x; @@ -24,17 +31,19 @@ var wrapHelper = function (f) { return Blaze._wrapCatchingExceptions(f, 'template helper'); }; -// !!! FIX THIS COMMENT !!! +// Looks up a name, like "foo" or "..", as a helper of the +// current template; a global helper; the name of a template; +// or a property of the data context. Called on the View of +// a template (i.e. a View with a `.template` property, +// where the helpers are). Used for the first name in a +// "path" in a template tag, like "foo" in `{{foo.bar}}` or +// ".." in `{{frobulate ../blah}}`. // -// Implements {{foo}} where `name` is "foo" -// and `component` is the component the tag is found in -// (the lexical "self," on which to look for methods). -// If a function is found, it is bound to the object it -// was found on. Returns a function, -// non-function value, or null. +// Returns a function, a non-function value, or null. If +// a function is found, it is bound appropriately. // // NOTE: This function must not establish any reactive -// dependencies. If there is any reactivity in the +// dependencies itself. If there is any reactivity in the // value, lookup should return a function. Blaze.View.prototype.lookup = function (name, _options) { var template = this.template; diff --git a/packages/blaze/preamble.js b/packages/blaze/preamble.js index 1ecdd57808..c1ade3cfc8 100644 --- a/packages/blaze/preamble.js +++ b/packages/blaze/preamble.js @@ -1 +1,20 @@ Blaze = {}; + +// Utility to HTML-escape a string. Included for legacy reasons. +Blaze._escape = (function() { + var escape_map = { + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`", /* IE allows backtick-delimited attributes?? */ + "&": "&" + }; + var escape_one = function(c) { + return escape_map[c]; + }; + + return function (x) { + return x.replace(/[&<>"'`]/g, escape_one); + }; +})(); diff --git a/packages/blaze/template.js b/packages/blaze/template.js index cb42f9153a..bb6af83011 100644 --- a/packages/blaze/template.js +++ b/packages/blaze/template.js @@ -143,3 +143,11 @@ Template.prototype.events = function (eventMap) { template.__eventMaps.push(eventMap2); }; + +Blaze._templateInstance = function () { + var templateView = Blaze.getCurrentTemplateView(); + if (! templateView) + throw new Error("No current template"); + + return Template.updateTemplateInstance(templateView); +}; diff --git a/packages/blaze/view.js b/packages/blaze/view.js index 0bd0b4c994..9a247ddf23 100644 --- a/packages/blaze/view.js +++ b/packages/blaze/view.js @@ -233,7 +233,7 @@ Blaze._materializeView = function (view, parentView) { domrange.onAttached(function attached(range, element) { teardownHook = Blaze._DOMBackend.Teardown.onElementTeardown( element, function teardown() { - Blaze.destroyView(view, true /* _skipNodes */); + Blaze._destroyView(view, true /* _skipNodes */); }); scheduleRenderedCallback(); @@ -271,10 +271,10 @@ Blaze._expandView = function (view, parentView) { if (Deps.active) { Deps.onInvalidate(function () { - Blaze.destroyView(view); + Blaze._destroyView(view); }); } else { - Blaze.destroyView(view); + Blaze._destroyView(view); } return result; @@ -330,7 +330,7 @@ Blaze._expandAttributes = function (attrs, parentView) { {parentView: parentView})).visitAttributes(attrs); }; -Blaze.destroyView = function (view, _skipNodes) { +Blaze._destroyView = function (view, _skipNodes) { if (view.isDestroyed) return; view.isDestroyed = true; @@ -345,11 +345,21 @@ Blaze.destroyView = function (view, _skipNodes) { view.domrange.destroyMembers(); }; -Blaze.destroyNode = function (node) { +Blaze._destroyNode = function (node) { if (node.nodeType === 1) Blaze._DOMBackend.Teardown.tearDownElement(node); }; +Blaze.destroy = function (nodeOrView) { + if (nodeOrView instanceof Blaze.View) { + Blaze._destroyView(nodeOrView); + } else if (typeof nodeOrView.nodeType === 'number') { + Blaze._destroyNode(nodeOrView); + } else { + throw new Error("Expected View or DOM node"); + } +}; + // Are the HTMLjs entities `a` and `b` the same? We could be // more elaborate here but the point is to catch the most basic // cases. @@ -457,6 +467,34 @@ Blaze.renderWithData = function (content, data, parentView) { return view; }; +// The publicly documented API for inserting a View returned from +// `UI.render` or `UI.renderWithData` into the DOM. If you then remove +// `parentElement` using jQuery, all reactive updates on the rendered +// template will stop. +Blaze.insert = function (view, parentElement, nextNode) { + // parentElement must be a DOM node. in particular, can't be the + // result of a call to `$`. Can't check if `parentElement instanceof + // Node` since 'Node' is undefined in IE8. + if (! parentElement || typeof parentElement.nodeType !== 'number') + throw new Error("'parentElement' must be a DOM node"); + if (nextNode && typeof nextNode.nodeType !== 'number') // 'nextNode' is optional + throw new Error("'nextNode' must be a DOM node"); + if (! (view && (view.domrange instanceof Blaze._DOMRange))) + throw new Error("Expected template rendered with UI.render"); + + view.domrange.attach(parentElement, nextNode); +}; + +Blaze.remove = function (view) { + if (! (view && (view.domrange instanceof Blaze._DOMRange))) + throw new Error("Expected template rendered with UI.render"); + + var range = view.domrange; + if (range.attached) + range.detach(); + range.destroy(); +}; + Blaze.toHTML = function (content, parentView) { parentView = parentView || currentViewIfRendering(); diff --git a/packages/templating/templating.js b/packages/templating/templating.js index 2bc1a28878..554abf1adf 100644 --- a/packages/templating/templating.js +++ b/packages/templating/templating.js @@ -15,14 +15,6 @@ Template.__assign = function (name, template) { Template[name] = template; }; -UI._templateInstance = function () { - var templateView = Blaze.getCurrentTemplateView(); - if (! templateView) - throw new Error("No current template"); - - return Template.updateTemplateInstance(templateView); -}; - // Define a template `Template._body_` that renders its // `contentViews`. `` tags (of which there may be // multiple) will have their contents added to it. @@ -54,40 +46,4 @@ Template._body_.renderToDocument = function () { UI.insert(view, document.body); }; -UI.render = Blaze.render; -UI.renderWithData = Blaze.renderWithData; -UI.toHTML = Blaze.toHTML; -UI.toHTMLWithData = Blaze.toHTMLWithData; - -// The publicly documented API for inserting a View returned from -// `UI.render` or `UI.renderWithData` into the DOM. If you then remove -// `parentElement` using jQuery, all reactive updates on the rendered -// template will stop. -UI.insert = function (view, parentElement, nextNode) { - // parentElement must be a DOM node. in particular, can't be the - // result of a call to `$`. Can't check if `parentElement instanceof - // Node` since 'Node' is undefined in IE8. - if (! parentElement || typeof parentElement.nodeType !== 'number') - throw new Error("'parentElement' must be a DOM node"); - if (nextNode && typeof nextNode.nodeType !== 'number') // 'nextNode' is optional - throw new Error("'nextNode' must be a DOM node"); - if (! (view && (view.domrange instanceof Blaze._DOMRange))) - throw new Error("Expected template rendered with UI.render"); - - view.domrange.attach(parentElement, nextNode); -}; - -// XXX test and document -UI.remove = function (view) { - if (! (view && (view.domrange instanceof Blaze._DOMRange))) - throw new Error("Expected template rendered with UI.render"); - - var range = view.domrange; - if (range.attached) - range.detach(); - range.destroy(); -}; - UI.body = Template._body_; - -UI.With = Blaze.With; diff --git a/packages/ui/ui.js b/packages/ui/ui.js index 6bdc4a3d6b..00525475f4 100644 --- a/packages/ui/ui.js +++ b/packages/ui/ui.js @@ -1,40 +1 @@ -UI = {}; - -UI._globalHelpers = {}; - -UI.registerHelper = function (name, func) { - UI._globalHelpers[name] = func; -}; - -// Utility to HTML-escape a string. -UI._escape = (function() { - var escape_map = { - "<": "<", - ">": ">", - '"': """, - "'": "'", - "`": "`", /* IE allows backtick-delimited attributes?? */ - "&": "&" - }; - var escape_one = function(c) { - return escape_map[c]; - }; - - return function (x) { - return x.replace(/[&<>"'`]/g, escape_one); - }; -})(); - -var jsUrlsAllowed = false; -UI._allowJavascriptUrls = function () { - jsUrlsAllowed = true; -}; -UI._javascriptUrlsAllowed = function () { - return jsUrlsAllowed; -}; - -UI._parentData = Blaze._parentData; - -UI.getElementData = Blaze.getElementData; - -UI.isTemplate = Blaze.isTemplate; +UI = Blaze;