How would you go about dynamically loading a web component - in response to a url route change for example?
I won't know the requested component ahead of time, so could you simply use JavaScript to write the HTML import and then add the code to the page, or are there implications with this? Perhaps Google Polymer helps?
Considering just Custom Elements, you can call document.registerElement whenever you want. So from that standpoint, you can dynamically load script using any well known method and have dynamic custom elements.
Now, with respect to HTML Imports:
could you simply use JavaScript to write the HTML import and then add
the code to the page
Yes, that's the basic idea.
Recent versions of the HTML Imports polyfill support dynamic link tags. IOW, you can do
var link = document.createElement('link');
link.setAttribute('rel', 'import');
link.setAttribute('href', some_href);
link.onload = function() {
// do stuff with import content
};
document.body.appendChild(link);
Also, Polymer has enhanced support for this feature, namely an imperative api like this:
Polymer.import([some_href], function() {
// called back when some_href is completely loaded, including
// external CSS from templates
});
The first argument is an array, so you can ask for multiple hrefs.
Hi I asked this question over at the polymer google groups.
https://groups.google.com/forum/#!topic/polymer-dev/uarVrxBK7XU
and was directed to this article
http://www.html5rocks.com/en/tutorials/webcomponents/customelements/#instantiating
This makes it clear you can instantiate an element on the fly by either adding the element to the dom or programatically. However this appears to imply that you've loaded the html imports at runtime. What I think we both want to achieve is loading the html imports (with additional css and js includes) using ajax and then add our element. I'm going to link back to the polymer support forum to see if I can get an answer over here.
Related
I have been trying to dynamically change the content of my HTML page by importing external HTML-files. I found a way to do this using HTML imports but if I have understood it correctly this feature is going to become obsolete in because of the ES6 update. From what I've manage to found online there could maybe be an alternative way to do this using javascript modules but I can't find anything concrete.
I want to be to change a big part of the page (a window containing a form becoming a window showcasing user statistics) so it doesn't seem smart to use .innerHTML in javascript. Does anyone have any good ideas on how to import html files or dynamically change the content of the page ? (using javascript, node, etc)
Any help much appreciated :)
I'm a bit late and the answer has already been linked to in the comments of this question, but here i go anyways.
You should be able to use Ajax to get the html file contents. (As a string)
With the content of the html file you should be able to parse it to a htmlDoc in JS (like the global document from document.getElement etc) using the DOMParser class.
https://developer.mozilla.org/en-US/docs/Web/API/DOMParser
https://codepen.io/Deefoozy/pen/PeYWge
After parsing the html into a htmlDocument you should be able to get the body through the result using .getElement or .body.children. The result of this should be a simple domNode which you can append to another domNode.
For single page applications I was wondering if it's possible to remove a custom gtm html tag from the DOM after it has been fired.
The idea behind this is to avoid an uncontrollable growing of the DOM through custom scripts.
I've encountered the same problem in a recent project I've been working on. However, I haven't found any 'native' solution for it, mainly because every Tag that can be injected with GTM can inject code in a totally different way.
What I have ended doing for this project is implement a rather simple solution (even if not perfect), which consists in:
Include a unique ID for every "Custom Tag" in GTM, with a common prefix that can be stored inside a variable (SCRIPT_ID). A CSS class would be better, but GTM seems to ignore them at all.
<script id="{{SCRIPT_ID}}__PIXEL_ID">
... custom code ...
</script>
Create a function that searches and removes any script inside the <body> tag (where GTM injects the Tags) with an ID that starts with the previous prefix.
function flushScripts() {
const pixels = document.body.querySelectorAll(':scope > script[id^="SCRIPT_ID"]');
for (const p of pixels) { document.body.removeChild(p); }
}
Execute that function every time the route changes or every time you see fit.
I'm taking a looking at bootstrap tags found here: http://bootstrap-tagsinput.github.io/bootstrap-tagsinput/examples/
I'd like to be able to hook into the HTML that's being rendered to add additional anchors/links to the tags being generated. There is an event named: beforeItemAdd() that allows you to see the item before it's added, but you can't necessarily interact with it other than prevent it from being rendered.
Is there a way to customize the HTML output here so I can add additional links besides the 'x' to my tag? Just applying a CSS class won't work, I need to be able to modify the actual markup being rendered so I can add content to the tags.
Alternatively, I'm open to a solution with tagging that allows for the customizing of tag HTML rendering.
Without digging really deep into the plugin source ( I've never used this plugin), or figuring out what data is stored, one way would be to use this in the event callback to traverse to the main container the plugin wraps everything in and then find the tag elements.
Add a class each time and then you know what you have already modified and the one without that class would be your new one
$('input').on('itemAdded', function(event) {
var $cont = $(this).siblings('.bootstrap-tagsinput'),
$tag = $cont.find('.tag').not('.modified').addClass('modified');
$tag.doSomeStuff();
});
Generally, there are 3 ways (that I am aware of) to execute javascript from an <a/> tag:
1) Use onclick():
hello
2) Directly link:
hello
3) Or attach externally:
// In an onload event or similar
document.getElementById('hello').onclick = window.alert('Hello');
return false;
<a id="hello" href="#">hello</a>
I am actually loading the link via AJAX, so #3 is basically out. So, is it better to do #1 or #2 or something completely different? Also, why? What are the pitfalls that I should be aware of?
Also of note, the anchor really doesn't link anywhere, hence the href="#", I am using a so the styles conform as this is still an object to be clicked and a button is inappropriate in the context.
Thanks
If you are loading the content via ajax and need to hook up event handlers, then you have these choices:
Put a javascript handler in your HTML with your option 1) or 2). In my mind option 1) is a cleaner way of specifying it, but I don't think there's a mountain of difference between 1) or 2) - they both do essentially the same thing. I'm not a fan of this option in general because I think there's value in keeping the markup and the code separate.
After loading the content with ajax, call some local code that will find and hook up all the links. This would be the same kind of code you would have in your page and execute on DOMReady if the HTML had been static HTML in your page. I would use addEventListener (falling back to attachEvent) to hook up this way as it more cleanly allows multiple listeners for a single object.
Call some code after you load the content with ajax that finds all the links and hooks up the clicks to some generic click handler that can then examine meta data in the link and figure out what should be done on that click based on the meta data. For example, this meta data could be attributes on the clicked link.
When you load the content, also load code that can find each link individually and hook up an appropriate event handler for each link much the way one would do it if the content was just being loaded in a regular page. This would meet the desire of separating HTML from JS as the JS would find each appropriate link and hook up an event handler for it with addEventListener or attachEvent.
Much like jQuery .live() works, hook up a generic event handler for unhandled clicks on links at the document level and dispatch each click based on some meta data in the link.
Run some code that uses an actual framework like jQuery's .live() capability rather than building your own capability.
Which I would use would depend a little on the circumstances.
First of all, of your three options for attaching an event handler, I'd use a new option #4. I'd use addEventListener (falling back to attachEvent for old versions of IE) rather than assigning to onclick because this more cleanly allows for multiple listeners on an item. If it were me, I'd be using a framework (jQuery or YUI) that makes the cross browser compatibility invisible. This allows complete separation of HTML and JS (no JS inline with the HTML) which I think is desirable in any project involving more than one person and just seems cleaner to me..
Then, it's just a question for me for which of the options above I'd use to run the code that hooks up these event listeners.
If there were a lot of different snippets of HTML that I was dynamically loading and it would be cleaner if they were all "standalone" and separately maintainable, then I would want to load both HTML and relevant code at the same time so have the newly loaded code handle hooking up to it's appropriate links.
If a generic standalone system wasn't really required because there were only a few snippets to be loaded and the code to handle them could be pre-included in the page, then I'd probably just make a function call after the HTML snippet was loaded via ajax to have the javascript hook up to the links in the snippet that had just been loaded. This would maintain the complete separation between HTML and JS, but be pretty easy to implement. You could put some sort of key object in each snippet that would identify which piece of JS to call or could be used as a parameter to pass to the JS or the JS could just examine the snippet to see which objects were available and hook up to whichever ones were present.
Number 3 is not "out" if you want to load via AJAX.
var link = document.createElement("a");
//Add attributes (href, text, etc...)
link.onclick = function () { //This has to be a function, not a string
//Handle the click
return false; //to prevent following the link
};
parent.appendChild(link); //Add it to the DOM
Modern browsers support a Content Security Policy or CSP. This is the highest level of web security and strongly recommended if you can apply it because it completely blocks all XSS attacks.
The way that CSP does this is disabling all the vectors where a user could inject Javascript into a page - in your question that is both options 1 and 2 (especially 1).
For this reason best practice is always option 3, as any other option will break if CSP is enabled.
I'm a firm believer of separating javascript from markup. There should be a distinct difference, IMHO, between what is for display purposes and what is for execution purposes. With that said, avoid using onclick attribute and embedding javascript:* in a href attribute.
Alternatives?
You can include javascript library files using AJAX.
You can setup javascript to look for changes in the DOM (i.e. if it's a "standard task", make the anchor use a CSS class name that can be used to bind a specific mechanism when it's later added dynamically. (jQuery does a great job at this with .delegate()))
Run your scripts POST-AJAX call. (Bring in the new content, then use javascript to [re]bind the functionality) e.g.:
function ajaxCallback(content){
// add content to dom
// search within newly added content for elements that need binding
}
Is there a way in JavaScript to get the contents of a linked file without making a second GET request? That is, if I have
<link rel="foo" href="bar.txt">
the browser should automatically download bar.txt. Is there any way to read its contents without getting it again (i.e. via jQuery's $.get or similar)?
Edit
I could use a second GET request and as mentioned in the comments there likely wouldn't be a performance hit, but this question is mainly a thought experiment: it seems like it'd be pretty standard functionality, but more and more things point to this not being possible. Is there a reason why?
If the tag has absolutly no other purpose than being a placeholder for the source, then the objective is to prevent the first get rather then the second ;) By using another attribute you avoid the default behaviour.
<link data-src='file.txt' />
'data-...' is a valid HTML5 attribute you can use right now, though the html will not be valid if an older doctype is declared but will still work.
Next when using jQuery:
$('link[data-src]').each(function(){
var self = $(this)
, src = self.attr('data-src');
$.get(src, function(fileContent){
// do stuff with fileContent
})
});
Obviously any element will do rather then the link element when using 'data-...', I use this technique myself to add data in a component based architecture, lazily binding resources and meta information to components without it affecting default behaviours/renditions.