Cleaner way to add large block of HTML in javascript in rails - javascript

I have a rails app along with angular, and I need to populate a large block of HTML so that it can fill in default text for textarea tag. Currently what I did was add the text like this
"<div class='navbar navbar-default letter-header hidden-sm hidden-xs'>\n" +
" <div class='container'>\n" +
" <div class='letter-navbar-header navbar-header'>\n" +
" <a href='/'><img src='/assets/logo.png' class='letters-logo navbar-brand'></a>\n" +
" </div>\n" +
" <div class='navbar-header header-text'>\n" +
" <div class='navbar-text'>\n" +
" "text" + "\n" +
" </div>\n" +
" </div>\n" +
" <div class='letter-navbar-header navbar-header'>\n" +
" <a href='/'>\n" +
" <img src='' class='second-logo'>\n" +
" </a>\n" +
" </div>\n" +
" <div class='navbar-header navbar-right'>\n" +
" {{ user_login }}" + "\n" +
" </div>\n" +
" </div>\n" +
"</div>\n"
I would like to know if there is a cleaner way to do it. I have tried using js.erb file with the render function like this
<%= j render('navbar') %>
but placed it in the asset folder so the render function is not working https://stackoverflow.com/a/8370847/1087841. I would like to know if there is a better way to do it.
[EDIT]
The js.erb file is actually an angular factory which has default HTML for the navbar, which then can be used by the angular controller to render default data. The factory file is then also gets added to application.js as a require.
this is the textarea that needs default html
<textarea name="t[navigation]" id="input-navigation-bar" ng-model="t.navigation_bar" class="form-control" rows="10"></textarea>
I could have placed the value tag with the default html but it has ng-model so nothing gets displayed. So I created a factory for the default data. Now the factory lives in /assets and has a //= require 'default_html_factory' in application.js.

I finally found a way to do it. In the erb page I added
<script>
<%= render 'style_factory.js.erb' %>
</script>
and in the factory I added this
this.ngapp.factory('TenantStyle', function() {
return {
header: "<%= j render 'navbar' %>"
}
});
and in the _navbar.html.erb file I added this
<div class="navbar navbar-default letter-header hidden-sm hidden-xs">
<div class="container">
<div class="letter-navbar-header navbar-header">
</div>
<div class="navbar-header header-text">
<div class="navbar-text">
</div>
</div>
<div class='letter-navbar-header navbar-header'>
<a href='/'>
<img src='' class='second-logo'>
</a>
</div>
<div class="navbar-header navbar-right">
</div>
</div>
</div>
and now I can call the factory in angular and get the header value.

Related

HTML DOM have data I didn't add through Javascript

I have generated my Header from JavaScript Data.
To generate I'm iterating through an Object.
Generating the HTML looks like:
for (const topic in templateTopic) {
if (Object.prototype.hasOwnProperty.call(templateTopic, topic)) {
const element = templateTopic[topic]
// console.log(element);
template += '<div class="col col-topic-element" id="' + element + '" onClick="filterTopic(' + element + ')">'
template += '<p>' + element + '</p>'
template += '</div>'
}
}
parent.innerHTML = '';
parent.insertAdjacentHTML('afterbegin', template);
When I inspect the Element it contain following strange data (Chrome Inspector Output):
<div id="topics" class="row">
<div class="col col-topic-element" id="film" onclick="filterTopic(film)">
<p>film</p>
</div>
<div class="col col-topic-element" id="photography" onclick="filterTopic(photography)">
<p>photography</p>
</div>
<div class="col col-topic-element" id="visual design" onclick="filterTopic(visual design)" data-kwdiaostructure=""0":"input","1":"submit#visual design##col col-topic-element####KwDiaoTagDIV","2":"visual design""
data-kwdiaohashid="input#submit#visual design##col col-topic-element####KwDiaoTagDIV#visual design">
<p>visual design</p>
</div>
</div>
How can I get rid of the data, because when I click on the last Element ("visual design"), the console throws an error and I can't add further code.
Console output after clicking the 3 generated Items:
I integrated Bootstrap 4 CDN and fontawesome.

How to take a script from an HTML file and move it to it's own .JS file?

I am trying to simplify my HTML file, and I have very long scripts that consist of just HTML (templates) that I'd like to move to their own external files. This is easy for me to do when the <script> tags involve functions, but in my case it's just straight HTML. In the new external file, how do I properly type up those HTML tags? See below.
<script type="text/template7" id="myStuffTemplate">
{{#each results}}
<div class="list-block media-list">
<ul>
<li>
<a href="#" class="item-link item-content">
<div class="item-media"><img src={{this.pictures['1']}} width="80" height="80px"></div>
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">{{this.name}}</div>
</div>
<div class="item-text">{{this.description}}</div>
</div>
</a>
</li>
</ul>
</div>
{{else}}
<div style="text-align:center">
<h1>Nothing yet!</h1>
<h2>Upload things you're willing to trade so you can start trading!</h2>
</div>
{{/each}}
</script>
That's the script within the HTML File. I'd like that moved into its own external file. How can one go about doing this? And do I reference it just like every other file when I link it? eg.:
<script type="text/template7" src="js/views/mystuff.js" id="myStuffTemplate"></script>
Thanks in advance.
This is not a script, it's a template made with either handlebars or moustache templates.
You can't "source" them with <script src="..."> like you can with Javascript, but they can be stored externally, then loaded and processed at runtime. This needs to be done asynchronously through an AJAX call. For example, assuming you were using jQuery, you could achieve it with the following:
// request the template
$.get('templates/products.hbs', function(rawTemplate) {
// once received, convert the raw template to a handlebars template
var template = Handlebars.compile(rawTemplate);
// compile the template with your context 'data' and set it on an element with an id
$('#someTargetId').html(template(data));
}, 'html'); // <-- tell jquery to load the file as html
Just be warned, even small templates will take some time to load, so there will be a delay between your page loading and the template loading then being displayed.
First of all, consider using a framework like Angular.js or React.js however this should work for you:
Let's suppose that you want to put that inside a div with id=items:
<div id="items"> Your code... </div>
In the html file add this, just before the <body> closing tag:
<script type="text/javascript" src="code.js"></script>
to include your code and this
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
to include jQuery.
Create a code.js file and put the following code inside:
$(document).ready( function() {
var myCode = "{{#each results}}" +
"<div class="list-block media-list">" +
"<ul>" +
"<li>" +
"<a href="#" class="item-link item-content">" +
"<div class="item-media"><img src={{this.pictures['1']}} width="80" height="80px"></div>" +
"<div class="item-inner">" +
"<div class="item-title-row">" +
"<div class="item-title">{{this.name}}</div>" +
"</div>" +
"<div class="item-text">{{this.description}}</div>" +
"</div>" +
"</a>" +
"</li>" +
"</ul>" +
"</div>" +
"{{else}} " +
"<div style="text-align:center">" +
"<h1>Nothing yet!</h1>" +
"<h2>Upload things you're willing to trade so you can start trading!</h2>" +
"</div>" +
"{{/each}}";
$( "#items" ).html( myCode );
} );

Jquery Tabs created dynamically with dynamic naming assignments

I am using the jquery ui tabs to create dynamic tabs on the fly which will start off without any content. From what I can tell my code is building everything and putting it in the proper places, but jquery is not recognizing them as tabs. How would I get it to recognize the new tabs that were created after page load?
The html code:
<div class="main">
<div>
<button id="new">button</button>
</div>
<div id="tabs">
<ul>
<li>View1</li>
<li>View2</li>
<li id="createView">Create New</li>
</ul>
<div id="tabs-1">
<p>something on this page</p>
</div>
<div id="tabs-2">
<div>
<p>something else on this page</p>
</div>
</div>
</div>
</div>​​​​​​​​
the Javascript:
//Tabs functionality
$('#tabs').tabs();
//Create new view
var tabNum = 3;
$('#new').click(function() {
$('#tabs ul').append('<li>' + '' + 'newitem' + '' + '</li>');
$('#tabs').append('<div id="' + 'tabs-' + tabNum + '">' + '<div>new</div>' + '</div>');
var NewViewNum = 'tabs-' + tabNum;
$(NewViewNum).focus();
tabNum++;
});​
The jQuery UI Tabs have a refresh method you can use per the documentation.
Try calling:
$("#tabs").tabs("refresh");

Templating Bootstrap Carousel with underscore.js and Backbone.marionette

I am the last step of a multi-level, nested sturcture of views - a collection of composite views.
However, based on array of image information, I am trying to render the bootstrap carousel, where the image with the highest priority_order is given the default "item active" class.
<%=_.each(images, function(x){
if (x.priority_order = 1)
{return
"<div class='item active'>
<img class='responsive-image' src=" + x.image + " alt=''>
<div class='container'>
<div class='carousel-caption'>
<h1>" + x.title + "</h1>
</div>
</div>
</div>"
}
else
{return
"<div class='item'>
<img class='responsive-image' src" + x.image + " alt=''>
<div class='container'>
<div class='carousel-caption'>
<h1>" + x.title + "</h1>
</div>
</div>
</div>"}
})%>
NOTE: The Above is simply manually pretty-printed for this post. In the real code, the line breaks are removed, otherwise you'll get:
Uncaught SyntaxError: Unexpected token ILLEGAL
When all is said and done, this still doesn't render properly. Am I missing something, or can underscore perform do this?
The way you've got it written there is syntax-error bait. (Plus, using a string literal largely defeats the purpose of using a template, no?)
I'd use code blocks <% %> for the logic parts, <%= %> for the rendering parts, and have the HTML as markup, not as a string literal:
<% _.each(images, function(x){ %>
<% if (x.priority_order == 1){ %>
<div class='item active'>
<img class='responsive-image' src=" + x.image + " alt=''>
<div class='container'>
<div class='carousel-caption'>
<h1> <%= x.title %></h1>
</div>
</div>
</div>
<% } %>
<%  } %>
Also, this is a typo -- if (x.priority_order = 1) -- should be the equality operator ==.
JSFiddle
Just as a note -- if you absolutely have to putt the markup in a string literal for some reason, then you can't have new lines within the string. It has to be either inline like this:
print "<div class='item active'><img class='responsive-image' src='" + x.image + "' alt=''><div class='container'><div class='carousel-caption'><h1>" + x.title + "</h1></div></div></div>";
Or appending the strings with the + like:
print "<div class='item active'>" +
"<img class='responsive-image' src='" + x.image + "' alt=''>" +
"<div class='container'>" +
"<div class='carousel-caption'>" +
"<h1>" + x.title + "</h1></div></div></div>";

Why won't mailto include link parameters?

When this code runs the alert box comes up with the link that includes &list=groceries and &email=tim#sitebuilt.net. When the mailto: fires and brings up the email window those parameters are missing and I can't figure out why. the length of the string doesn't seem to matter.
This code has all it needs to run. You can run it here: http://jsfiddle.net/mckennatim/rRerR/
<div data-role="header">
<h1>My Title</h1>
</div><!-- /header -->
<div data-role="content">
<h3>Add List</h3>
<form>
<div data-role="controlgroup" id="addwhat">
<input type="email" id="shemail" name="inp0" class="inp" />
</div>
<div data-role="controlgroup" data-type="horizontal" class="aisubmit">
<input type="submit" data-theme="b" id="mailit" value="mail it"/>
</div>
</form>
</div><!-- /content -->
</div><!-- /page -->
<script>
$('body').on('click', "#mailit", function (e) {
e.stopImmediatePropagation();
e.preventDefault();
repo = "Sebaza";
list = "groceries";
semail = $("#shemail").val();
//(semail);
urri ='mailto:'+ semail + '?subject=share this list with me' + '&cc=' + semail + '&body=Hi, I think it would be cool if we shared this ' + list +' list on our phones. That way when either of us modified it we would see the update. http://10.0.1.18/webeshoppin/stuff2get/www/food2buy.html?repo=' + repo + '&list=' + list + '&email=' + semail ;
window.location = urri;
alert('clicked ashare ' +urri);
});
</script>
</body>
</html>
The '?' and '&' characters are being stripped out by the parser of the mailto link.
Those characters need to be encoded. Try replacing with:
? = %3F
& = %26
so, that JS line would look like:
urri ='mailto:'+ semail + '?subject=share this list with me' + '&cc=' + semail + '&body=Hi, I think it would be cool if we shared this ' + list +' list on our phones. That way when either of us modified it we would see the update. http://10.0.1.18/webeshoppin/stuff2get/www/food2buy.html%3Frepo=' + repo + '%26list=' + list + '%26email=' + semail;

Categories