Get element content without displaying on page in Polymer - javascript

I am building a custom element with Polymer 1.0 and need to get the content inside the tag using javascipt without it being displayed on the page. I tried using the <content> tag and fetching it inside the javascript with a query selector. This works except it displays on the page even if I use a style="display: none;" attribute. How can I get the content inside the tag without it displaying on the page?

Not sure what exactly your use-case is, but how about simply wrapping your <content> tag with a hidden <div>?
<dom-module id="x-test">
<template>
<div hidden>
<content id="content"></content>
</div>
</template>
<script>
Polymer({
is: "x-test",
attached: function () {
// access distributed content like this
var myContent = Polymer.dom(this.$.content).getDistributedNodes();
}
});
<script>
</dom-module>

Related

document.getElementById not behaving as expected

I'm trying to get the contents of a div with a specific Id. However, if the div is nested inside a tag such as <template> it can't be found. I don't have control over the html output of the page, so I need to find a way to find this element no matter where its nested. It's my understanding that document.getElementById is supposed to be able to find an element with the given Id no matter where it is located. The javascript code is always located in script tags at the end of the body.
Below it is working as expected, nested within a div.
const str = document.getElementById("somethingsomething").innerText;
console.log(str);
<html>
<body>
<div>
<div hidden="" id="somethingsomething">
<b>dark side</b>
</div>
</div>
</body>
</html>
Here is the example that I would expect to work in the same manner but doesn't.
const str = document.getElementById("somethingsomething").innerText;
console.log(str);
<html>
<body>
<template>
<div hidden="" id="somethingsomething">
<b>dark side</b>
</div>
</template>
</body>
</html>
A <template>'s children don't get rendered - they aren't really on the page. As MDN says:
Think of a template as a content fragment that is being stored for subsequent use in the document. While the parser does process the contents of the <template> element while loading the page, it does so only to ensure that those contents are valid; the element's contents are not rendered, however.
It doesn't have children in the DOM.
console.log(document.querySelector('template').children.length);
<template>
<p>foo</p>
</template>
So, any descendant of a template won't be found with document.querySelector or any of the other methods to find elements that start with the document as the root.
I think you'll need to do two things here:
First check if the element exists on the page
If it doesn't, it may be in a template; iterate over the templates and their .content to see if what you're looking for is inside there
const getText = doc => doc.getElementById("somethingsomething")?.textContent;
const getStr = () => {
const textOnPage = getText(document);
if (textOnPage !== undefined) return textOnPage;
for (const template of document.querySelectorAll('template')) {
const textInTemplate = getText(template.content);
if (textInTemplate !== undefined) return textInTemplate;
}
};
const str = getStr();
console.log(str);
<html>
<body>
<template>
<div hidden="" id="somethingsomething">
<b>dark side</b>
</div>
</template>
</body>
</html>
A <template> element contains markup, but the contents are not part of the DOM. The content can be added to the DOM, one or more times, by JavaScript after the page has loaded.
The <template> tag keeps all content within it hidden from being rendered until it is actually needed. So you need to activate the template to get any elements defined within it otherwise they will return null.
You can do that by using document.importNode(externalNode, deep). Where externalNode references the template element itself and deep indicates if you want the entire subtree of the template being imported.
Once you've imported node then you need to append it to the document body for it to be rendered onto the page so getElementById can see it.
You can find more in depth examples in the following links:
document.getElementById doesn't work with <template> custom tag
https://www.html5rocks.com/en/tutorials/webcomponents/template/#toc-using
https://developer.mozilla.org/en-US/docs/Web/API/Document/importNode

vue.js - escape html inside slot

I am currently working on a component that looks like this:
<pre v-highlightjs>
<code>
<slot></slot>
</code>
</pre>
So the problem I have is that when I am writing html inside the slot, this html is rendered and not shown as a string or code-sample in my case. I have tested it with escaped < and > and it works. How can I access the html inside the slot and escape it automatically?
Thank you
EDIT:
I use highlight.js for that component to highlight the code inside my component. highlight.js can highlight html aswell. When I put e.g.
<html><head></head><body></body></html>
inside my slot, the box is shown, but the input is rendered as html. So I want to escape the html-Tags (and other code-snippets) so that it is shown and ofc highlighted. Hope that specifies my problem a bit more.
An important limitation to be aware of is that your HTML is not HTML, it is input to Vue's templating engine, so what a component sees in the slot may not be exactly what is in the HTML file.
Writing a directive to take HTML content and replace it with a text version of that content is pretty straightforward. Putting that in a component is also pretty straightforward. You can see these together in the snippet below.
What you will also see is that the Vue templating engine strips out tags that shouldn't be inside the body: the html, head, and body tags don't make it to the component. Their contents, if any, remain.
If it is important to be able to use those tags (or, for that matter, possibly invalid HTML), you will not be able to do it in a slot. You will need to have the HTML as a data string, which you can easily interpolate using the normal curlies.
new Vue({
el: '#app',
data: {
headContent: 'Something in the head'
},
components: {
htmlEscaper: {
template: '#html-escaper',
directives: {
escapeContent: {
bind(el) {
const html = el.innerHTML;
el.textContent = html;
}
}
}
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
<html-escaper>
<html>
<head>
{{ headContent }}
</head>
<some-junk>
Custom tags are ok
</some-junk>
<body>
<div>This part is legit</div>
</body>
</html>
</html-escaper>
</div>
<template id="html-escaper">
<code v-escape-content>
<slot>
</slot>
</code>
</template>

load react script inside text/template script

I'm trying to contribute to a project that uses <script type="text/template"></script> for rendering the elements of a page.
My contribution is to change the elements of the page into react components. However when I order the react to render in a specific div with ReactDOM.render() I get an error saying
Uncaught Error: _registerComponent(...): Target container is not a DOM element.
I know that means that react doesn't find the div where to render so propably I will need to load the react script after the div, I've tried that but the error is there again.
I've tried loading the react script otherwise like this
<script type="text/template">
<ul class="new-component-template" id="xblocklist" >
</ul>
<script type="text/babel" src="path to react file"/>
</script>
but when I load the page the error is gone an the script is not loaded at all.
What I need is to load the script when the outer script is called, I.E can I write a function inside <script type="text/template"></script> that actually loads the react script inside.
UPDATE
var ListXblocks = React.createClass({
componentWillMount: function(){
this.setState({Problemstyle: this.props.Problemstyle})
fetch('http://192.168.33.10:8002/XBlocks/')
.then(result=>result.json())
.then(result=> {
this.setState({items:result})
})
},
render:function(){
return(
<div>
{
this.state.items.map((item)=>{return(
<li className="editor-manual" key={item.title}>
<button type="button" className="button-component" data-category="problem" data-boilerplate="">
<span className="name">{item.description}</span>
</button>
</li>)})
}
</div>
);
}
});
ReactDOM.render(<ListXblocks/>, document.getElementById('xblocklist'));
Script tag with type="text/template" doesn't do anything particularly and it just let browser to ignore what inside it. This approach usually uses by templating systems like handlebarjs and React doesn't support it. You can read more about this here. So if you put your React scripts also inside that, the browser is just going to ignore that as well.
Beacuse your ul tag is not a html element, document.getElementById('xblocklist') is going to return null. That's why you get "Target container is not a DOM element." error. So you have to get the html out of the script tag either manually or using JavaScript.

fetch data using class inside iframe and div using html, java script asp

I have an iframe and inside this there is a class called service-row and inside this div there is another class named service-cell
I want to get the data from that class how to do that. And there are 40 items with same name class how to get that data.
example
HTML page
<iframe id="iframe1">
<div class="servicesTab">
<div class="service-row">
<div class="service-cell">
Obstetrics(this data)
</div>
</div>
</div>
</iframe>
If you need data of specific cell then you can use the following code:
$("#iframe1 .service-cell:eq(0)").text()
else you can access all the cells using below code and then, iterate using for loop :
$("#iframe1 .service-cell")

Mustache JS Templating - How do I embed a variable in a script tag string?

I just started using Mustache and I like it so far, but this has me perplexed.
I am using the GitHub gist API to pull down my gists, and part of what I want to do is include the embedding functionality into my page. The problem is Mustache seems to not want to have anything to do with my dynamic script tag.
For example, this works fine:
<div class="gist-detail">
{{id}} <!-- This produces a valid Gist ID -->
</div>
Additionally, this works perfect:
<div class="gist-detail">
<script src='http://gist.github.com/1.js'></script> <!-- Produces the correct embed markup with Gist ID #1 -->
</div>
If I try to pull these together, something goes terribly wrong:
<div class="gist-detail">
<script src='http://gist.github.com/{{id}}.js'></script> <!-- Blows up! -->
</div>
Chrome Inspector shows this:
GET https://gist.github.com/%7B%7Bid%7D%7D.js 404 (Not Found)
... which looks like to me something is weird with escapes or whatnot, so I switch over to the raw syntax:
<div class="gist-detail">
<script src='http://gist.github.com/{{{id}}}.js'></script> <!-- Blows again! -->
</div>
And I get the same result in Inspector:
GET https://gist.github.com/%7B%7B%7Bid%7D%7D%7D.js 404 (Not Found)
How do I get the correct values to embed in the script tag?
EDIT
I am injecting the template as follows (in document.ready:
function LoadGists() {
var gistApi = "https://api.github.com/users/<myuser>/gists";
$.getJSON(gistApi, function (data) {
var html, template;
template = $('#mustache_gist').html();
html = Mustache.to_html(template, {gists: data}).replace(/^\s*/mg, '');
$('.gist').html(html);
});
}
The actually template is inside of a ruby partial, but it is wrapped in a div (not a script tag, is that a problem?) (that's hidden):
<div id="mustache_gist" style="display: none;">
{{#gists}}
<!-- see above -->
{{/gists}}
</div>
I assume a div is ok rather than a script because in either case, I'm pulling the .html(). Is this a bad assumption?
To avoid automatic escaping in Mustache use {{{token}}} instead of {{token}}.
It seems like your template is in HTML and trying to retrieve the template using html() results in a pre-URL-escaped template to be returned. Try placing your template inside a <script type="text/html"> tag instead.
When you embed your template inside an HTML element that excepts more HTML elements as children, it may get processed by the browser as HTML. Escaping may occur. By using a <script> tag with a non-script content type, you're basically telling the browser not to touch your template.
It looks like your script is getting requested before Mustache has a chance to update the src property. What you want to do is define the template in a way that it's not parsed as part of the DOM. A common approach is to define your template inside of a <textarea> tag. This will preserve formatting and prevent character escaping.
<textarea id="gist-detail-template" style="display:none">
<script src='http://gist.github.com/{{id}}.js'></script>
</textarea>
Now, to instantiate the template:
var template = $('#gist-detail-template').val();
var html = Mustache.to_html(template, yourTemplateData);
Here's an official example: http://mustache.github.com/#demo

Categories