I've been reading with interest about the dialog element in HTML:
<dialog id="helpOnName">
<p>
The name is arbitrary. There is no validation, whatsoever.
</p>
</dialog>
So, that's well for this simple text. However, with growing complexity, I'd rather have something like
<dialog url="helpOnName.html"></dialog>
In other words: Rather than embedding the dialog contents into the opening page, I'd like it to be read from another file.
Is that possible? How? (Using JQuery would be fine.)
You may have different options to achieve the goal to have content loaded from an external resource.
Doing an ajax request that will return a response to embed
dynamically in the dialog
Embedding the content inside an <iframe> tag
Referencing the content with an <object> tag
This is the demo for the third and most original option of those.
The content for the <dialog> is specified by an <object> element fed by an url having its content. As a fallback, I added the option that will override its content with a default template defined in the page itself.
<object>: The External Object element
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object
:scope (worth of mention)
*for selecting only starting from the direct children
https://developer.mozilla.org/en-US/docs/Web/CSS/:scope
This is an answer better covering <iframe> <embed> <object>
Difference between iframe, embed and object elements
And I would add I forgot to mention <link>
document.addEventListener('DOMContentLoaded', ()=>{
const dialog = document.getElementById('primaryDialog');
fillDialogContent(dialog);
})
function fillDialogContent(dialog){
const template = dialog.querySelector(':scope > .fallback');
const content = template.content.cloneNode(true);
const objectEl = dialog.querySelector('object');
objectEl.append(content);
}
<dialog id="primaryDialog" open>
<object data="your-custom-dialog-content.html" type="text/html"></object>
<template class="fallback">
<div class="container">
<p>This is the default dialog content</p>
<p>An error occurred in the attempt to load the custom template</p>
</div>
</template>
</dialog>
Here is another way of doing it with fetch():
document.addEventListener('DOMContentLoaded', function(ev) {
document.querySelectorAll("[data-url]").forEach(el=>
fetch(el.dataset.url).then(r=>r.text()).then(html=>el.innerHTML=html)
)
});
<h3>First dialogue</h3>
<div data-url="https://baconipsum.com/api/?type=all-meat¶s=3&format=html">hello</div>
<h3>Second dialogue</h3>
<div data-url="https://baconipsum.com/api/?type=all-meat¶s=5&make-it-spicy=1&format=html">hello again</div>
Related
I'm pretty new to web design, and I'm trying to build a dashboard for a project. So far, I've got my UI looking like I want it to. It basically consists of a header bar, with a navigation bar on the left side with some options that the user can click on. I want a click on each item to change the content in the central area. The way I thought of was simply to use:
document.getElementById("central text element").innerHTML = "the HTML I want to change it to";
This approach, functionally, does everything I would like. The only problem is, the content I would like to insert is not short. For each of my options, I basically have to create individual HTML documents that I could edit the content in, then run it through a converter like this: https://tomeko.net/online_tools/cpp_text_escape.php?lang=en, then copy it in. As you can probably understand, this method is not very streamlined, as every time I want to make some changes to the code, I have to copy that chunk of code into this converter then paste it into the JavaScript function.
Is there a better way to achieve what I'm trying to do here?
There are several ways to do this:
The <template> element
If you want all the content to be loaded in the page, you can use <template>.
const content1 = document.getElementById("content1").content,
content2 = document.getElementById("content2").content,
div = document.getElementById("div");
function changeContent(content) {
const nodes = [...div.childNodes];
for (let node of nodes) {
node.remove();
}
div.appendChild(content.cloneNode(true));
}
document.getElementById("add-content1-btn").addEventListener("click", () => {
changeContent(content1);
});
document.getElementById("add-content2-btn").addEventListener("click", () => {
changeContent(content2);
});
#div {
border: 1px solid black
}
<template id="content1">
<p>
This is some HTML content. It won't be rendered unless you use JavaScript.
It supports <strong>markup</strong>, of course.
</p>
</template>
<template id="content2">
<p>
This is another HTML content.
</p>
<ul>
<li>Yes,</li>
<li>it</li>
<li>supports</li>
<li>lists.</li>
</ul>
</template>
<button id="add-content1-btn">Add content1 to div</button> <button id="add-content2-btn">Add content2 to div</button>
<div id="div"></div>
Loading pages with <iframe>
You can use <iframe> to load another page inside a page. This is a great approach if the content is really big, because the main page won't need to load that content unless requested. You can change the src attribute of the <iframe> dynamically to load different pages. Note that the page you load needs to be a full page, with its own CSS and all.
<iframe src="https://example.com/">
I've recently started using the <template> tag for HTML that I process afterwards using a template library, e.g.
<template id="tmpl">
<div class="something">
{{title}}
</div>
</template>
...
<script>
var output = Mustache.render($('#tmpl').html(), {
link: 'abc',
title: 'abc'
});
</script>
However, I've come to realise this means I have a broken link (example.com/pages/{{link}}) in my HTML. This is a concern, as various crawlers might consider it invalid (in fact, the Google Search Console reports my homepage as having a broken link).
Is it valid to use <template> this way?
Is it better to put it in something like <script type="text/template"> instead (as seen on the handlebars.js website)?
The output variable does contain the HTML we would expect, i.e., the rendered template; however, your code does not write the contents of the output variable anywhere.
Here is a working example:
<template id="tmpl">
<div class="something">
{{title}}
</div>
</template>
<span id="output"></span>
<script>
var output = Mustache.render($('#tmpl').html(), {
link: 'abc',
title: 'abc'
});
$('#output').html(output);
</script>
Google has not properly crawled the test site I setup for this. However, when I asked GoogleBot to render my version of your code it displayed the link inside the template element, i.e., *{{title}}* and the rendered template link, i.e., *abc*. Even though Google says you have a broken link in the template element, you really don't when a user views it.
One possible way to get Google to quit indicating that you have a broken link is to surround your template tags with <!--googleoff: anchor--> ...templates... <!--googleon: anchor-->. These tags stop googlebot from indexing anchor tags contained within.
Example:
<!--googleoff: anchor-->
<template id="tmpl">
<div class="something">
{{title}}
</div>
</template>
<!--googleon: anchor-->
How do i make a div that will not break even if the structure of the information inside it is improperly made.
ie:
<div id="bulletproof_div">
<div> </div>
<div> </div>
<div id="unclosed_div">
</div>
<div id="normally_this_one_would_break">
</div>
edit: the context is that it is a mailing system where i have no control over the information that is being sent to me, that is why i need to make it so that the website will not break.
i have tried successfully with iframe but i need to be able to modify the inner html of the div so iframe is not ideal.
Thank you for reading
Iframes are the only 100% bullet-proof containers to isolate contents from the surrounding page.
If you have access to the broken markup before it is appended to the 'bulletproof_div' you can use this function to 'fix' the markup before it is appended
function cleanMarkup(markupStr) {
// temp 'div' only used as a container, it is not returned with output
var temp = document.createElement("div");
temp.innerHTML = markupStr;
return temp.innerHTML;
}
Most browsers will attempt to fix broken markup, so when you retrieve the innerHTML property immediately after setting it, the value will be a 'fixed' markup string.
So given this input
cleanMarkup("<div></div> <div id='unclosed'>test!")
The function should return
<div></div> <div id="unclosed">test!</div>
I want to navigate from a link on a html site to another where a TabContainer with two different tabs is located.
I have one tab selected by default (which I want to keep) in the destination html file.
How do I have to put the link so that this is working? I found several documents on the net but nothing works. So probably someone needs to explain this to me the dumb way.
Here is the destination TabContainer:
<div dojoType="dijit.layout.TabContainer" region="center" tabStrip="true">
<div dojoType="dijit.layout.ContentPane" title="Contact" selected="true">
some text
</div>
<div dojoType="dijit.layout.ContentPane" title="Imprint" selected="true">
some text
</div>
I want to place a link to autmatically be navigated to the title "Imprint".
Can someone help?
Thanks a lot and all the best
TTP
You can either select it from javascript, or generate the markup for the tab from your server with the selected attribute to true (you'll need to set the other to false). This second alternative, depends on your server technology.
For the first option, add ids to the container and tabs and select the tab when the page finished loading. Something like:
<div id="tabContainer" dojoType="dijit.layout.TabContainer" region="center" tabStrip="true">
<div id="tab1" dojoType="dijit.layout.ContentPane" title="Contact" selected="true">
some text
</div>
<div id="tab2" dojoType="dijit.layout.ContentPane" title="Imprint" selected="false">
some text
</div>
</div>
<script>
dojo.ready(function() {
dijit.byId('tabContainer').selectChild(dijit.byId('tab2'));
});
</script>
If you want to dynamically select either tab, you'll need to pass some kind of parameter in the URL to your page. You can use a query parameter (variables after the ? symbol) or a hash fragment (anything after #). Query parameter you can read both from the server and from javascript. Hash fragments, only from javascript.
You can access those parameters by inspecting the location object. For example, using a hash fragment, you'd link to your page like http://host/page.html#imprint. Then in the <script> tag above:
<script>
dojo.ready(function() {
if (location.hash == '#imprint') {
dijit.byId('tabContainer').selectChild(dijit.byId('tab2'));
}
});
</script>
For query parameters, also see dojo.queryToObject().
I have a webapplication where (as in many other ones out there) you click on an image to do something, for instance, mark an entry, send a mail, flag something...
Short, clicking on the image is supposed to call an action (via javascript, but that's not the point).
I was wondering, what is the "right" way to do this?
<a>-tag? Hmm... actually it is not a link...
<button>? Because obviously a button is the semantic element for calling an action...
<div>?
Any hints?
Short Answer
Use an <img> - not a button or an anchor or an input - as the rest suggest that the element is interactive, even without JavaScript.
Long Answer
clicking on the image is supposed to call an action (via javascript, but that's not the point).
I disagree; that is the point :)
Because the clicking activates JS-only features, your image should only be available in a JS environment.
As such the proper way is to insert it with JavaScript; while an HTML document should be semantically correct, a DOM structure doesn't really need to be semantically correct, so which element you use becomes irrelevant.
The Wrong Way
<div>
Click on the image to do something:
</div>
<div>
Click on the image to do something: <input type="image" onclick="wtv()" src="..." />
</div>
<div>
Click on the image to do something: <img onclick="wtv()" src="..." />
</div>
<div>
Click on the image to do something: <button onclick="wtv()"><img onclick="wtv()" src="..." /></button>
</div>
These are all wrong because a user who doesn't have JavaScript sees these items and can't use them.
Of all of these, I'd say the <img> is the lesser evil, as it doesn't suggest an interactive element. The greatest evil is using the <a> as an anchor should be a hyperlink to another document, and you should never, ever use the javascript: protocol.
You'll still have the same problem when you add the JavaScript event handlers externally:
/* external .js file */
document.getElementById("myButton").onclick = wtv;
<!-- HTML document -->
<div id="myButtonParent">
Click on the image to do something: <a id="myButton" href="#" style="background-image:url(...)"> </a>
</div>
As, again, you still have the (non-functioning) hyperlink available to those users who don't have JavaScript.
Instead
Instead, insert the whole damn thing using DOM scripting! I'm going to use an <img> with an onclick event:
/* external .js file */
window.onload = function() {
var img = document.createElement("img");
img.src = "...";
img.onclick = wtv;
img.style.cursor = "pointer"; // so the mouse turns into a finger,
// like on a hyperlink
// Note: instead assign a class attribute and put this in an external CSS file...
document.getElementById("myButtonParent").appendChild(img);
}
You could add an onclick event for the image:
<img id='image1' onclick="javascript:DoSomething()"...
or add it via jquery:
$("#image1").click(
function() {
DoSomething();
});
I don't think you should use an anchor tag here. Anchoring is for navigating not doing things. Not to mention if you use the beforeunload events, they will get fired if you use an anchor.
While the div works it doesn't add anything semantically to the page. You are not defining a distinct chunk of the page you need to make an image clickable.
I don't use a button control enough to talk about that as an option.
Do not quite understand what you want to achieve. But have you tried image input?
<input type="image" src="image source">
It will do an operation similar to form submit.