reccommended way to output HTML from JavaScript - javascript

I know this has probably been asked before, but here goes: I have a web application that needs to generate modal dialogs. alert, confirm, and prompt are too simple and ugly, and that modal window function...it's a long story. I can't use it. So, I'm going to create the modal box using DOM functions and CSS. However, I need to put quite a lot of content into the dialog, and I'm wondering what the best way to do this is. Putting the HTML into a string and using innerHTML is unwieldy. I could use the DOM, but that's annoying and takes too much time to code. I know I can use a script with a weird type tag (something like x-random/x-htmlstuff) and then copy it's content to the innerHTML, but is there a better, more "official" way to do this?

if the layout of the modals are static, just put them into the HTML of the page. Use CSS to set them to display: none when the page is displayed normally. When you want to display the model, use
document.getElementById('modal-id').style.display = 'block';

I've heard that some people use this solution:
<script type="text/html" id="popup_html">
html...
</script>
(of course, you should make it invisible)
But, most likely, if you're trying to write a lot of HTML from javascript, then you should retrace and think if there's a better way.
If you're using the same div multiple times, you should just create it in the HTML page, and display it when needed
if you're creating a new element - see if you can use the document.createElement and appendChild methods (assuming there aren't many nodes involved)
if neither apply - retrace. For large projects, maybe object-oriented javascript can help.

There's no magical way that I'm aware of. I usually just use innerHTML and write the HTML out in a well formatting from such as:
box.innerHTML = "<div id='boxChild'>\n" +
" <p>Put whatever content here</p>\n" +
"</div>";
The \n make it so if you view your code, it will be well formatted, and no one long string once the JS writes it.

A way to do this, is to generate the popups within the html and show or hide them when you need, like this:
<div class="myPopup">
<div class="pop-message msg-01">This a pre generated alert with the id: <span class="dynamic-field-01"></span></div>
<div class="pop-message msg-02">This another pre generated alert with the id: <span class="dynamic-field-02"></span></div>
<div class="pop-message msg-03">...</div>
</div>
.pop-message {
display: none;
}
Now while user navigates the page, you are going to hide and show the .pop-message's while replacing those .dynamic-field's if needed.

I would suggest having the HTML for your modal content in separate files, and then loading it asynchronously when you need it to popup the modal.
partials/modal.html
<div class="content">My modal content</div>
main.js
var modalContent = null;
function _fillModal() {
modal.innerHTML = modalContent; // something like this
}
function openModal() {
if (!modalContent) {
// XMLHttpRequest, which populates the modalContent variable
// and in the callback, calls _fillModal()
}
// If already filled, just call
_fillModal()
}
If you want the content to be dynamic, make modal.html a template, and use a JS template library (for example http://underscorejs.org/#template), or write a simple RegExp replace yourself.

I'd suggest loading it with innerHTML or using jQuery to simplify things, but if you need
a modal window, could you use the jQuery UI modal dialog, shown here?
If you have the content loaded in divs in your HTML, and have them have css display:none;, and then show them with
document.getElementById("unshown-div").style.display="block";
If you can use jQuery, a modal box could be done with
<div id="modal" style="display:hidden">
Here is a modal dialog bbox
</div>
and your script:
$("#dialog").dialog();
Whatever you do, just don't use document.write()

Related

Is there a way to not load html until JavaScript loads?

I want to make sure that all JavaScript happens before the page is loaded. I am changing some innerhtml, but don't want the original innerhtml to show.
Currently, when my page loads "Books" is displayed for a brief moment, then finally when the script is read, it gets replaced. How do I prevent it from displaying the initial text?
FYI the script exists inside a php file.
<?php
?>
<script>
function changeme(){
var myvar = "test-string-is-long-to-notice-the-changed-text";
var spans = document.getElementsByTagName("span");
for(var i=0;i<spans.length; i++) {
if(spans[i].textContent.trim().toLowerCase()==="books") { //is this the "Welcome" span?
spans[i].innerHTML = myvar; //change to new value
break; //hop out of the loop, we're done
}
}
}
window.onload = function() {
changeme();
};
</script>
It is not a good idea to load JS before HTML, because you can not change the HTML elements before loading it using js.
Solution 1: Initially, keep the html tags empty that you do not want to show, because you want to show new data from JS.
Solution 2: Initially, keep the styles for those elements "display: none" and when you add the data using Js in element. Update the style to display: 'block' or any other you want, eg spans[i].style.display = 'block';.
You cant apply JS to a html document that doesnt yet exist. Your html is always loaded first, then your JS is applied. What you could be seeing here is the html is loaded and the JS is taking like what--a second to load and make the change? I recommend figuring out a more efficient way to implement the JS you need. You could just be seeing JS latency. You could use a more efficient implementation plus some CSS to fix it. I could be wrong here but it just doesn't make sense to apply JS to html went the html isnt even there yet.
How would I apply any JS to that if I'm trying to do it before the browser has even parsed and rendered my html?
Also remember that PHP is always "loaded" first, then html, then JS

How to capture clicked element using $(this) inside of a vue(js) instance

I am reworking an old app of mine and I am having issues with dom manipulation and basic selections within a vue instance.
Essentially I have information in a database that I load in via ajax.
Each record in the db has 2 sections. The header tab(title, time, date etc) and the body of the record(notes, ideas, etc)
When loaded, the header shows normally to the user but if they want to see what that note contains, they have to click on the header for the bottom to appear.
consider the following html:
<vuejs for loop>
<div v-bind:id='item._id' class="tabW" v-on:click="blueTabClick" >
<div class="blueTabMainColor">
<!-- header stuff here -->
</div>
<div class="notesOpenedW">
<!-- interior informaton here, HIDDEN BY CSS -->
</div>
</div>
<vuejs for loop ender>
This HTML is essentially inside a Vue for/loop directive, and generates however many "tabs(tabW)" as needed based on how much info I have in the DB
All I want the user to do is to be able to click whichever tab(tabW) they want information on, and for the notes show underneath(notesOpenedW).
I stripped my entire app and js and tried to keep it as simple a test as possible and even with the below, I still can't get anything.
here is my JS(JQ):
$(document).ready(function(evt){
$(".blueTabMainColor").click(function(){
$(this).next(".notesOpenedW").fadeToggle();
});
});
With this basic code, when I put it inside a Vue instance, via:
methods: {
blueTabClick: function (evt) {
evt.preventDefault();
$(".blueTabMainColor").click(function(){
//alert("you clicked me");
$(this).next(".notesOpenedW").fadeToggle();
});
}
}
It doesn't work, but if I take it out of the Vue instance, it works just fine.
how can I get this to work? or am I going about it the wrong way?
Vue will not cohabit happily with JQuery. You're $(this) will not work because you're not even in the document at that point, you're in pure js, virtual DOM, another universe. Then, if it did, the event listener you call may not exist. You will need to fundamentally transition this code to Vue if you want it to work, I fear.
You can achieve this by setting a ref on "notesOpenedW".
https://v2.vuejs.org/v2/api/#ref
I would strongly recommend to wrap this behaviour in a dedicated component
That would have the following content :
<div class="tabW" v-on:click="blueTabClick" >
<div class="blueTabMainColor">
<!-- header stuff here -->
</div>
<div class="notesOpenedW" ref="notesToggleDiv">
<!-- interior informaton here, HIDDEN BY CSS -->
</div>
</div>
And the method :
methods: {
blueTabClick: function () {
$(this.$refs.notesToggleDiv).fadeToggle();
}
}
Be aware that when using Vue, manipulating directly the dom is usually a bad idea.
As i showed you, it is possible to use jQuery with Vue if you absolutely need it (or cannot afford to rework more deeply your application).
Edit : Just found this article that i think would help you a lot :
https://www.smashingmagazine.com/2018/02/jquery-vue-javascript/?utm_campaign=Revue%20newsletter&utm_medium=Newsletter&utm_source=Vue.js%20Developers

setting content between div tags using javascript

I'm trying to set some content in between some div tags on a JSP page using javascript.
currently the div tag on the JSP page looks like this:
<div id="successAndErrorMessages"></div>
I want to fill the content in those div tags using some javascript method so that it will look like so:
<div id="successAndErrorMessages"><div class="portlet-msg-error">This is an error message</div></div>
I know you can go like this:
document.getElementById("successAndErrorMessages").value="someContent";
But that just changes the value of the 'value' attribute. It doesn't fill in content between those div tags. Anyone out there that can point me in the right direction?
Try the following:
document.getElementById("successAndErrorMessages").innerHTML="someContent";
msdn link for detail : innerHTML Property
See Creating and modifying HTML at what used to be called the Web Standards Curriculum.
Use the createElement, createTextNode and appendChild methods.
If the number of your messages is limited then the following may help. I used jQuery for the following example, but it works with plain js too.
The innerHtml property did not work for me. So I experimented with ...
<div id=successAndErrorMessages-1>100% OK</div>
<div id=successAndErrorMessages-2>This is an error mssg!</div>
and toggled one of the two on/off ...
$("#successAndErrorMessages-1").css('display', 'none')
$("#successAndErrorMessages-2").css('display', '')
For some reason I had to fiddle around with the ordering before it worked in all types of browsers.

Applying layer of JS before the HTML loads

I have a .html loaded to clients. On it, jQuery does some modifications.
The problem is that the page loads in two steps: first the original .html, then, a fraction of a second later, the modified .html.
This approach causes jerkyness. Is there a way to show the .html only once JavaScript has acted upon it?
If you MUST do this, then something like this:
Javascript:
$(document).ready(function(){
myfunction();
$("#wrapper").show();
}
CSS:
div#wrapper{ display: none; }
HTML:
<div id="wrapper">
<!-- my page stuff that i dont want to be jerky -->
</div>
However, I would raelly advise that you find a way to apply the styles/data to the page before you generate it (e.g. with PHP, ASP etc.),
You can use CSS to set default properties of the parts you are changing, if these are stylistic changes and not HTML changes.
You can also use jQuery's .load() to reload page fragments instead of the whole page.
Or, use css to set body { display: none; } and using (document).ready() to $('body').show().

Create new (not change) stylesheets using jQuery

We've got a little tool that I built where you can edit a jQuery template in one field and JSON data in another and then hit a button to see the results immediately within the browser.
I really need to expand this though so the designer can edit a full CSS stylesheet within another field and when we render the template, it will have the CSS applied to it. The idea being that once we've got good results we can take the contents of these three fields, put them in files and use them in our project.
I found the jQuery.cssRule plugin but it looks like it's basically abandoned (all the links go nowhere and there's been no development in three years). Is there something better or is it the only game in town?
Note: We're looking for something where someone types traditional CSS stylesheet data in here and that is used immediately for rendering within the page and that can be edited and changed at will with the old rules going away and new ones used in their stead. I'm not looking for something where the designer has to learn jQuery syntax and enter in individual .css("attribute", "value") type calls to jQuery.
Sure, just append a style tag to the head:
$("head").append("<style>p { color: blue; }</style>");
See it in action here.
You can replace the text in a dynamically added style tag using something like this:
$("head").append("<style id='dynamicStylesheet'></style>");
$("#dynamicStylesheet").text(newStyleTextGoesHere);
See this in action here.
The cleanest way to achieve this is by sandboxing your user-generated content into an <iframe>. This way, changes to the CSS won't affect the editor. (For example, input { display:none; } can't break your page.)
Just render out your HTML (including the CSS in the document's <head>, and write it into the <iframe>.
Example:
<iframe id="preview" src="about:blank">
var i = $('#preview')[0];
var doc = i.contentWindow || i.contentDocument;
if (doc.document) doc = doc.document;
doc.open('text/html',true);
doc.write('<!DOCTYPE html><html>...</html>');
doc.close();
If the user should be able to edit a whole stylesheet, not only single style attributes, then you can store the entered stylesheet in a temporary file and load it into your html document using
$('head').append('<link rel="stylesheet" href="temp.css" type="text/css" />');
sounds like you want to write an interpreter for the css? if it is entered by hand in text, then using it later would be as simple as copy and pasting it into a css file.
so if you have a textarea on your page to type in css and want to apply those rules when you press the button, you could use something like this (only pseudocode, needs work):
//for each css id in the text area
$.each($('textarea[name=cssTextArea]').html().split('#'), function({
//now get each property
$.each($(this).split(';'), function(){
$(elem).css({property:value});
});
});
then you could write something to go through each element that your designer typed in, and get the current css rules for it (including those that you applied using some code like the snippet above) and create a css string from that which could then be output or saved in a db. It's a pain and much faffing around with substrings but unfortunately I don't know of a faster or more efficient way.
Hope this atleast gives you some ideas

Categories