Load dynamic content to a bootstrap modal - javascript

I receive some data after an AJAX call and I populate a list.
But when an item is clicked from that list, I want to show a modal with information about that item (like a picture, how popular it is - how many times it was clicked -, author etc). I can do this in an ugly way:
$('#target').append(
$('<div class = "col-md-4" data-toggle = "modal" data-target = "#myModal" onClick = someFunction(' + someArgument + ')>' + someText + '</div>' +
'<div class = "modal fade" id = "myModal" role = "dialog">' + '<div class = "modal-dialog modal-lg">' +
'<div class = "modal-content"> <div class = "modal-header"> <h4 class = "modal-title">' + someTitle + '</h4></div>' +
'<div class = "modal-body">Description: ' + description + ' Author: ' + author + '<br</br>' +
'<img src = "' + imgSource + '" class = "modal-dialog modal-lg" style = "max-width: 25%;">' +
'<button type = "button" class = "close" data-dismiss = "modal" id = "myModal">×</button>' +
'<div class = "modal-footer"></div></div></div></div></div>'));
This is ugly, error prone, hard to maintain, hard to read. Can it be done in a more elegant manner?

Firstly, your code should be written inside show.bs.modal function.
$('#target').on('show.bs.modal', function (e) {
// do something...
})
See this: http://getbootstrap.com/javascript/#modals-events
Second, I prefer to use jQuery to create DOM elements, like this
$("<div>").addClass("col-md-4").attr("data-target","#myModal").append(
$("<div>").addClass("modal fade")//add more here
);

Related

javascript: insert html tag with innerHTML

I have to integrate several html type tags (ex: <div id = "mysection"> <div class = "mycontainer"> <h1> mytitle </h1> </div> </div>) to format data (here "mytitle") output in javascript
So, I have in my HTML <span id="datahere"></span>
and the js i need to edit is :
function Bigdata(title, subtitle, type) {
const mydata = document.getElementById('datahere');
mydata.innerHTML += title + subtitle + (type ? ' <strong>(type is ' + type + ')</strong>' : '') +'<br/>';
}
// element in which the data is initialized, visible in another <span>
const sprit = document.getElementById('sprit');
// when a given message is received
sprit.addEventListener(SpritEvents.MessageSprit, ({ data }) => {
Bigdata('Sprit', data.text, data.type);
// if there are actions, we offer links
if (data.actions) {
var links = '';
for (var i = 0; i < data.actions.length; i++) {
if (i > 0) {
links += ', ';
}
let act = data.actions[i];
links += '<a data-val="' + act.value + '">' + act.title + '</a>';
}
Bigdata('Sprit', links);
}
});
I cannot integrate the tags which must "contain" data (title, subtitle, type) WHITH links if there are actions ...
if I add my tags like this: mydata.innerHTML += '<div id = "mysection"> <div class = "mycontainer"><h1>' + title + '</h1>' + subtitle + (type ? ' <strong>(type =' + type + ')</strong>' : '') +'<br/></div></div>';
that does not surround the whole, the div and the h1 are duplicated (surrounds on one side title, subtitle, type and on the other links).
I'm not used to using pure javascript ... I hope you can help me
I recommend rewriting it using Template literals:
mydata.innerHTML += `<h1>${title}</h1>`;
More on this topic:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
This makes things look much lighter.
Also, it looks like you are not closing the html tags. For example: <div>, needs to be closed with </div>

How to concatenate and pass parameters values in html using jQuery

I'm using jQuery to get values from ajax rest call, I'm trying to concatenate these values into an 'a' tag in order to create a pagination section for my results (picture attached).
I'm sending the HTML (divHTMLPages) but the result is not well-formed and not working, I've tried with double quotes and single but still not well-formed. So, I wonder if this is a good approach to accomplish what I need to create the pagination. The 'a' tag is going to trigger the onclick event with four parameters (query for rest call, department, row limit and the start row for display)
if (_startRow == 0) {
console.log("First page");
var currentPage = 1;
// Set Next Page
var nextPage = 2;
var startRowNextPage = _startRow + _rowLimit + 1;
var query = $('#queryU').val();
// page Link
divHTMLPages = "<strong>1</strong> ";
divHTMLPages += "<a href='#' onclick='getRESTResults(" + query + "', '" + _reg + "', " + _rowLimit + ", " + _startRow + ")>" + nextPage + "</a> ";
console.log("Next page: " + nextPage);
}
Thanks in advance for any help on this.
Pagination
Rather than trying to type out how the function should be called in an HTML string, it would be much more elegant to attach an event listener to the element in question. For example, assuming the parent element you're inserting elements into is called parent, you could do something like this:
const a = document.createElement('a');
a.href = '#';
a.textContent = nextPage;
a.onclick = () => getRESTResults(query, _reg, _rowLimit, _startRow);
parent.appendChild(a);
Once an event listener is attached, like with the onclick above, make sure not to change the innerHTML of the container (like with innerHTML += <something>), because that will corrupt any existing listeners inside the container - instead, append elements explicitly with methods like createElement and appendChild, as shown above, or use insertAdjacentHTML (which does not re-parse the whole container's contents).
$(function()
{
var query=10;
var _reg="12";
var _rowLimit="test";
var _startRow="aa";
var nextPage="testhref";
//before divHTMLPages+=,must be define divHTMLPages value
var divHTMLPages = "<a href='#' onclick=getRESTResults('"+query + "','" + _reg + "','" + _rowLimit + "','" + _startRow + "')>" + nextPage + "</a>";
///or use es6 `` Template literals
var divHTMLPages1 = `` + nextPage + ``;
$("#test").append("<div>"+divHTMLPages+"</div>");
$("#test").append("<div>"+divHTMLPages1+"</div>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test"></div>

Dynamic HTML Tag generated from JavaScript, two-word class not working

I am trying to create dynamic html from an api response. Whenever I get a two-word class name, I cannot get it to save both words as the string is ending when it see's the space. See below:
for(var i = 0; i<articles.posts.length; i++){
var cls = 'fa '+articles.posts[i].category;
var el = "<article><i class="+cls+"></i><h2> From the Archive </h2><h1> " + articles.posts[i].title + "</h1><h3> " + articles.posts[i].date + " </h3><p> " + articles.posts[i].blurb + "</p></article>"
$("#article-list").last().append(el);
}
For Instance if 'cls' is fa fa-space-shuttle, the class gets set as 'fa' not both 'fa fa-space-shuttle'. Any idea how to get around this using javascript?
Whenever I get a two-word class name
There are no two-word class names. What you have there is two classes.
var el = "<article><i class="+cls+"></i><h2> From the Archive </h2><h1> " + articles.posts[i].title + "</h1><h3> " + articles.posts[i].date + " </h3><p> " + articles.posts[i].blurb + "</p></article>"
Look closely at the quotes in that line of code. There aren't any around the class attribute. So, according to the HTML specification, the value ends at the first space. Add quotes around it:
var el = "<article><i class='"+cls+"'></i><h2> From the Archive </h2><h1> " + articles.posts[i].title + "</h1><h3> " + articles.posts[i].date + " </h3><p> " + articles.posts[i].blurb + "</p></article>"
// -------------------------^-------^
Example:
var cls = "fa fa-link";
var el = "<article><i class='"+cls+"'></i><h2> From the Archive </h2></article>"
document.body.insertAdjacentHTML("beforeend", el);
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet"/>

Javascript (JQuery) and Bootstrap modals

I am currently working on a project that displays some information about movies(pulled from omdbapi.com) in a modal depending on the link that is clicked. Previously this was all done using PHP in the back end and was working without any issues, but as a page can have anywhere from 5-100 movie links on it, creating all of the modals was causing the page to take a while to load.
Now I want to move the modal creation/popup to the front with JS so that it is only created when and if that particular movie link is clicked. Moving it to use Javascript I have encountered two issues I am not able to solve.
The movie title link must be clicked twice in order for the modal to appear and I am not sure what is causing this. Looking at the dev tools I can see that on the first click a modal is created, but for some reason not displayed. On the second click another is created and displayed.
Once a modal is displayed I am unable to get my "X" button to close it. The code I was using in PHP"<button type=\"button\" class=\"close exit-button\" data-dismiss=\"modal\">×</button>"
no longer works. Bootstrap does have the ability to show/hide a modal with $("#movieInfo").modal("hide"), but if I create a function to run this when the button is clicked it still does not hide.
Here is the JS code that I am using:
window.addEventListener("load", function() {
var movielink = document.getElementById("movie");
movielink.addEventListener("click", function(){generateModal(this.innerHTML);}, false);
}, false);
function generateModal(movieT) {
var movieTitle = encodeURIComponent(movieT).replace(/%20/g, '+');
var url = "https://www.omdbapi.com/?t="+movieTitle+"&y=&plot=short";
$.getJSON(url, function(json) {
$('#modalContainer').html("<div id = \"movieInfo\" class = \"modal fade\" role = \"dialog\">"
+ "<div class \"modal-dialog modal-sm\">"
+ "<div class = \"modal-content\">"
+ "<div class = \"modal-body\">"
+ "<div class = \"poster\">"
+ "<img src = "+json.Poster+" width = 200 height = 300>"
+ "</div>"
+ "<div class = \"movie-specs\">"
+ "<button id = \"closebtn\" type=\"button\" class=\"close exit-button\"s onclick = \"closeModal()\">×</button>"
+ "<h3 class = \"movie-title\">"+json.Title+" ("+json.Year+")</h3>"
+ "<p class = \"topmargin-gone\">"+json.Rated+" | "+json.Runtime+" | "+json.Genre+"</p>"
+ "<p class = \"topmargin-gone\">"+json.Released+"</p><hr>"
+ "<div class = \"ratingInfo\">"
+ "<h4 class = \"topmargin-gone\"><strong>Ratings</strong></h4><p class = \"topmargin-gone\">Rated: "+json.imdbRating+"/10 "
+ "from "+json.imdbVotes+" users | Metascore: "+json.Metascore+"</p>"
+ "</div><hr>"
+ "<div class = \"plot-actors\">"
+ "<p>"+json.Plot+"</p><p><strong>Director: </strong>"+json.Director+"</p>"
+ "<p><strong>Writers: </strong>"+json.Writer+"</p>"
+ "<p><strong>Actors: </strong>"+json.Actors+"</p>"
+ "</div>"
+ "</div>"
+ "</div>"
+ "</div>"
+ "</div>"
+ "</div>");
});
$("#movieInfo").modal("show");
}
This is how the the links are created inside a loop in PHP:
$allDisplay .= "<li><em><a id ='movie' href = '#'>"
. "$title[$z]</a></em> - $nominees[$z]</li>";
And finally this is how the HTML looks where the links and modal reside:
<html>
<head>
<meta charset = "utf-8">
<title>Award Search</title>
<!-- jQuery Library -->
<script src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!--Bootstrap CSS -->
<link rel = "stylesheet" href = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<!-- Styles CSS sheet -->
<link rel = "stylesheet" href = "/src/styles/styles_awardQuery.css">
<!--Bootstrap JavaScript -->
<script src = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src = "/src/php/modalCreation.js"></script>
</head>
<body>
<div class = "site-wrapper">
<div class = "site-wrapper-inner">
<div class = "cover-container">
<div class = "masthead clearfix">
<div class = "inner">
<h3 class = "masthead-brand">Award Search</h3>
<ul class = "nav masthead-nav">
<li>Home</li>
<li>About</li>
<li>Logout</li>
</ul>
</div>
</div>
<div class = "inner cover">
<h1 class = "cover-heading">Academy Award Show Number <?php echo $academyNumber; ?>
<?php echo "($year[1])<br><span class = \"small\">Hosted by $acHost</span>"; ?></h1>
<?php echo $allDisplay; ?>
<div id ="modalContainer"></div>
</div>
</div>
</div>
</div>
</body>
</html>
I realize this looks messy, but just want to get it functioning right now. If anyone has any insight into either of the issues it would be much appreciated.
Thanks.
The $("#movieInfo").modal("show"); is triggered before the bloc was actually append to your web page. This is due to the network latency and the Async behaviour of AJAX call that allow your script to continue without waiting to get an answer.
To avoid this, you should put this line at the end of the network callback :
function generateModal(movieT) {
var movieTitle = encodeURIComponent(movieT).replace(/%20/g, '+');
var url = "https://www.omdbapi.com/?t="+movieTitle+"&y=&plot=short";
$.getJSON(url, function(json) {
$('#modalContainer').html('<div id="movieInfo" class="modal fade" role="dialog">'
+ '<div class "modal-dialog modal-sm">'
+ '<div class="modal-content">'
+ '<div class="modal-body">'
+ '<div class="poster">'+'<img src='+json.Poster+' width=200 height=300>'+'</div>'
+ '<div class="movie-specs">'
+ '<button id="closebtn" type="button" class="close exit-button"s onclick="closeModal()">×</button>'
+ '<h3 class="movie-title">'+json.Title+' ('+json.Year+')</h3>'
+ '<p class="topmargin-gone">'+json.Rated+' | '+json.Runtime+' | '+json.Genre+'</p>'
+ '<p class="topmargin-gone">'+json.Released+'</p><hr>'
+ '<div class="ratingInfo">'
+ '<h4 class="topmargin-gone"><strong>Ratings</strong></h4><p class="topmargin-gone">Rated: '+json.imdbRating+'/10 '
+ 'from '+json.imdbVotes+' users | Metascore: '+json.Metascore+'</p>'
+ '</div><hr>'
+ '<div class="plot-actors">'
+ '<p>'+json.Plot+'</p><p><strong>Director: </strong>'+json.Director+'</p>'
+ '<p><strong>Writers: </strong>'+json.Writer+'</p>'
+ '<p><strong>Actors: </strong>'+json.Actors+'</p>'
+ '</div>'+'</div>'+'</div>'+'</div>'+'</div>'+'</div>');
// after we have made the modal, we show it
$("#movieInfo").modal("show");
});
// code here will be fired before the end of the AJAX call
}
For your other bug, I think the double modal may explain the behaviour, so patch this first, and told us if you still can't close your modal ;)

javascript (jquery) added text comments dont linebreak/ ignore their div container

Im working on a JavaScript based comment system:
This is the Javascript that generates the comment html:
$.each(comments.user,function(key,value)
{
comment_string += '<div class = "r_comment_header">';
comment_string+= '<a class = "r_comment_user" href = "profile.php?id=' + comments.user_id[key] + '" title = "Profile of ' + value + '">' + value + ' </a>';
if(comments.pm_button[key])
comment_string+= '<input type = "button" class = "comment_send_pm" value = "Message" name = "' + comments.user_id[key] + '" title = "Send this user a private message"/>';
comment_string+= '<span class = "r_comment_time">' + comments.time[key] + '</span>';
comment_string+= '</div>';
comment_string+= comments.content[key];
comment_string+= '<div class = "comment_abuse_wrapper">';
comment_string+= '<input type = "button" class = "comment_report_abuse" name = "' + comments.id[key] + '" value = "Report abuse" title = "Report this comment as inappropriate content"/>';
comment_string+= '</div>';
});
$('#request_comments').html(comment_string);
Now what happens when I add a new comment via a text input field is that the content of the comment ignores the div containers boundaries and does not linebreak:
http://i.imgur.com/V85Vc.png
This is the div containers css:
#request_comments
{
width:658px;
padding: 10px;
margin: 10px 0 0 10px;
}
any suggestions?
This is the normal HTML behaviour. It happens if you have an unwrappable string (i.e. no symboly/whitespace) and is completely unrelated to JavaScript or jQuery.
The easiest solution is using the overflow: hidden CSS option.
PS: You should consider using templates instead of just creating your markup through strings. There are some nice template engines for JavaScript nowadays. Have a look at http://api.jquery.com/jquery.tmpl/ for example.

Categories