Jade / Pug: Hide div unless variable has data - javascript

I want to hide a div unless the div has received data to the local variable. I have this at the moment:
div#cost
p You earn #{cost} a day!
But it displays on the page. How do I hide it until it receives the data? Im confused about Jade's if/else syntax

-if (cost)
div#cost
p You earn #{cost} a day!
First of all, the - means that it is unbuffered Javascript code. Meaning this will not get rendered in the final version of the template. If you would want that, you should use a script tag like so: script..
Second, the if-statement will check if cost is not equal to null or undefined. When it doesn't exists, the code inside the if-statement will be skipped.
The above code will result in the following HTML if cost is not equal to null or undefined:
<div id="cost">
<p>You earn ... cost a day!</p>
</div>

What you are trying to achieve is not possible.
jade/pug is a template engine, you can give placeholder variable, perform loops, conditions etc but your browser does not understand jade/pug it understands only HTML, which means your template will be converted to a static HTML content before being displayed.
The if/else block decide what is going to be part of the generated HTML file, once the file is generated jade/pug does not have any control over it.
If you want to dynamically control your DOM you can use a web framework such as Angular, Vue, React or you can do DOM manipulation using jQuery or by hand with regular Javascript.

Related

how to use variable key in thymeleaf expression in js side

since few days, i tried to avoid to put an harcoded list in my JS to display a list of header labels.
I have tested many stuff but do not manage to find the way to do it.
In Html, if a put a list inside the model, the value is well interpreted by the tag th:text
<td th:each="header:${headerMemberLiaisonList}" th:text="#{'planner.table.header.'+ ${header}}">???planner.table.header</td>
The issue is that my list is not computed at this moment because it depends on the actions of the user in this view. So I try to move it in JS part.
But the same peace of code in js which should be [[#{'planner.table.header.'+headers[i]}]], is not interpreted because the value between brackets is read as string.
any idea?

Are there javascript template engines that support something like recursion?

The most obvious example I can think of is for outputting nested comments. Let's say you have a tree of comments and you want to output it as nested html (let's say lists inside lists or divs inside divs) using your template.
The "comment" block/function/tag/helper/whatever would have to be able to call itself somehow for the comment's children.
Are there template engines that would support that sort of thing inside one template file?
I am aware that you can just pre-compute the "indent" or "depth-level" of each comment and send them to the template as one flat list in the correct order, but let's just say I don't want that. And let's say I don't want to stitch snippets together in code / outside the template - I want the whole page self contained in one template or theme file.
Update: I want to generate nested html. I want the comments to be nested, not appear nested. I know how to indent things with CSS. :) Whether it is done in the browser or on the server is irrelevant because the point is I want the template to be self-contained in one file.
As in:
var html = render(template, {comments: aTreeOfNestedComments});
(see? that could be node.js, a brower plugin, some "jQuery" as some people like to call javascript these days...) It looks like jade can do this using mixins. Any tag-based templating engines that can do something similar?
Template engines can solve generic, run-off-the-mill problems. While nesting templates seems like a common use case, I haven't encountered many template engines who can do that.
Since the market didn't offer a good solution, I'm building my applications from JavaScript objects that know how to render themselves. I never use templates; every block gets a reference to the DOM (like the parent element to which is should attach itself) or the renderers return the child container and the parent element can add that in a suitable place.
This allows me to use the full power of JS without the limitations of template engines.
[EDIT] Here is a workaround: If you need a recursive element, add a span (if the recursive element should be inline) or div (if it's a block element). Give it the class recursiveTemplate and a data attribute data-template-name="..."
Run the template with your standard template engine. Afterwards, use jQuery or the like to find all elements with the class recursiveTemplate and replace them yourself.
Distal templates has an example here of a nested tree:
http://code.google.com/p/distal/wiki/UseCaseExamples#Building_a_nested_tree
as #TJHeuvel said, you can use the server side script to produce the desired otput, this would be the best way to do what you require. However if you must use JavaScript, I would advise jQuery this will also allow you to product the desired result.
for example:
$("ul li").css("margin-left", "10px");

HTML Template (Custom) Tag

I understand that using custom html tags is improper for a variety of reasons, but I wanted to run a specific situation by you that might warrant a custom html tag and hopefully get told otherwise or possibly a better way of achieving my goal.
Throughout my code I have what I term as templates that are made up of a div tag with a template and a hidden class attached to it. This is not visible on the screen, but basically these "template" tags contains html that I use in Javascript to create a variety of different items. I do this so that I can style my templates in html rather than have to worry about mixing CSS in with my Javascript.
<!-- TEMPLATE -->
<div class="template hidden">
<span>Random Container</span>
Random Button
</div>
In javascript I would do something like
var template = document.getElementById("template");
var clone = template.cloneNode(true);
clone.removeClass("template hidden");
I would rather be able to do something like this
<template class="hidden">
<span>Random Container</span>
Random Button
</template>
So that if I have multiple templates in a single div I can grab them all rather than having to give them unique class names. Of course my reasoning for needing an implementation goes a lot deeper than this, but its not necessary to waste your time with the details. Let's just say that it will help clean up my Javascript ALOT.
Because the custom template tag is hidden and really is nothing more than a container that is convenient to call within javascript with document.getElementsByTagName("template"); Is this ok to do? I would probably prefix the tag with a custom name in case template ever gets implemented into html.
Modern browsers generally “support” custom tags in the sense of parsing them and constructing DOM nodes, so that the elements can be styled and processed in scripting.
The main problem is IE prior to IE 9, but it can be handled using document.createElement('...') once for each custom tag name.
Another problem is that validators will report the tags as errors, and if there are loads of such errors, you might not notice some real errors in markup. In principle you can create your own DTD to deal with this (I have an HTML DTD generator under construction, but it is trickier than I expected...).
With these reservations, use custom tags if they essentially simplify your job as compared with using classes.
Why not use one of HTML5's data attributes? They are for storing private data or custom info.
For your case, you could add data-type="template" or data-name="template" and then search and remove based on that. One simple function just like you would write to remove your <template> tag, but without breaking rules.
So, using your example, <div data-type="template" class="hidden"></div>

Is it possible to insert rendered ASP.NET controls with JavaScript?

I'm not very familiar with ASP.NET, so forgive me if I word this question poorly. We build lots of .aspx pages that include dynamic "labels" that render as plain text when viewed in the browser. For example, if the source of my .aspx contains this code:
<p>Thanks for trying <em>{ProductName}</em>!</p>
The page when viewed in the browser will read:
Thanks for trying My Company's Product!
Now, I want to able to insert that text on the page dynamically via JavaScript. The problem is that if I have a script write that same bit of code to the page, I get this:
Thanks for trying {ProductName}!
I assume this is because the page has already finished rendering before the script runs, so the dynamic label gets treated as plain text instead of rendering on the server side first.
Is there any way at all that I can do this?
The .aspx scripts are server side rendered, so they are rendered at your web server and then downloaded by the user, so the user already gets a page with that values.
On the other side, javascript is rendered at the client machine, so he downloads the script, and the browser renders the page, thats why you dont get that value show.
There are some workarounds to do that.
First, and the better one is to try ajax. That means that the javascript will do another server request to get that value and show it to the user, and that value will come from server.
Second, you can try to put these server variables on script variables or hidden html elements. That way, when you want to use that values, you can get it from the local script(javascript). It would be something like writting the value on a hidden or hidden input " >, and recover it like
document.getElementById("value_id").innerHTML or even set the javascript variables at your page, doing something like
var val = "<%=ProductName%>";
I'm not familiar with that syntax. I would expect something like <%= ProductName %> instead. What flavor of ASP.Net are you using? WebForms? MVC? Spark?
Since curly braces are integral to the JavaScript language, it is likely that JavaScript tags are not parsed for string replacement. It would take a pretty robust parsing engine to know when the curly braces indicate a string replacement and when they are part of the JavaScript code. If you can switch to the <%= ProductName %> syntax for your JavaScript, that may be the easiest. If that's not an option or doesn't work for your situation, try putting the strings in the html, and extracting them from JavaScript. A hidden input seems ideal:
<input type="hidden" id="ProductName" value="{ProductName}" />
You may find it doesn't work in attributes. Fine, just use a hidden span:
<span class="hidden" id="ProductName">{ProductName}</span>
(don't forget to define a "hidden" css class to do the actual hiding: .hidden { display: none; })
Get at your strings with JavaScript:
var productName = document.getElementById("ProductName").value; // hidden input
var productName = document.getElementById("ProductName").innerHTML; // hidden span

How to let JavaScript know where I am on the site?

I have a single template file which renders pages that look very similar, but behave a bit different. I have a header and a few text boxes, which are filled by the template language, and there is a canvas, whose content actually differentiates the pages. It basically comes down to calling a different JavaScript function based on the page I am on, and I can't really think of an elegant (!) way to do that.
I have a single JavaScript file that uses jQuery's document ready callback to add interactivity to the site, and also to do the drawing in the canvas. For that, I have to call a specific drawing function based on which page I am on, but I don't know it at that point.
This is certainly not impossible, I can in fact think of several different solutions, but don't really like any of these. The script file is not run through a template engine, so I can't employ any server-side logic there. I could parse the URL in the script, but this sounds like a hack to me. I could also set a variable in a script block within the template file, set a hidden field's value or something like that, but I don't think this logic belongs into the template either.
So how is this usually done?
You can give the <body> tag a "class" value, and your JavaScript code can use that (and other similar cues) to know what sorts of behaviors to add.
For example, your code could do something like:
if ($('body').hasClass('image-gallery')) {
// ... initialize image gallery code ...
}
if ($('body').hasClass('shopping-cart-summary')) {
// ... whatever ...
}
Of course it doesn't have to be just the <body> tag. Your <canvas> could also get a "class" value (and/or "data-foo" attributes) to convey information to your code.
You can embed any JavaScript you want on to a web page, built with the same server-side logic you would build the page with. So you can set global variables or (preferably) invoke functions from your .js files with parameters that contain page-specific logic. Just supply the scripts between <script> tags.
It is not clear if you want to find the page you are on, or the location in the DOM of a given page. For the former, use location.href, or location.pathname to avoid the parsing.

Categories

Resources