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 ;)
Related
I have a modal, which I feed its content information through variables.
<div id="myModal">
<div id="outer">
<div id="inner">
<div id="top">Headline</div>
<span><img class="btnClose bCancel" src="#"></span>
<div class="modalCnt"></div>
<div class="btn">
<span class="btnText">OK</span>
</div>
</div> <!-- Inner -->
</div> <!-- Outer -->
</div> <!-- Close myModal -->
My problem is that I use the same modal for all different messages that needs to popup. And at page load I have to messages that needs to popup, but only one shows up, which is the last modal that is called. Is there a way to que up the calls so that first modal is shown and then the second one?
$( document ).ready(function() {
modalHead.html("<h3>Headline 1</h3>");
modalContent.html("<p>Content 1</p>");
modal.show();
modalHead.html("<h3>Headline 2</h3>");
modalContent.html("<p>Content 2</p>");
modal.show();
});
Please revisit the following official documentation:
https://v4-alpha.getbootstrap.com/components/modal/#varying-modal-content
It is quite clear and elegant solution.
<script>
$('#myModal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget)
var header = button.data('header')
var content = button.data('content')
var modal = $(this)
modal.find('.modal-title').text(header)
modal.find('.modal-modalCnt').val(content)
})
</script>
And pass data-header="your_header" data-content="your_content" when you trigger the modal.
Plus add a class tittle to your header. Hope I was clear.
Try:
function new_modal(head, content){
var random = Math.floor(1000 + Math.random() * 9000);
var modal_html = '<div id="myModal_'+ random +'">' +
'<div id="outer">' +
'<div id="inner">' +
'<div id="top">'+head+'</div>' +
'<span><img class="btnClose bCancel" src="#"></span>' +
'<div class="modalCnt">'+content+'</div>' +
'<div class="btn">' +
'<span class="btnText">OK</span>' +
'</div>' +
'</div> <!-- Inner -->' +
'</div> <!-- Outer -->' +
'</div>';
$('body').append(modal_html);
return 'myModal_' + random;
}
$( document ).ready(function() {
modal1 = new_modal("<h3>Headline 1</h3>", "<p>Content 1</p>");
$('#' + modal1).show();
modal2 = new_modal("<h3>Headline 2</h3>", "<p>Content 2</p>");
$('#' + modal2).show();
});
Hope it Helps
what you are doing is calling the same function with 2 diffrent modal data at once . So if we go by the flow of function , it will finish the execution at the last line. So thats why its showing last modal, So what you can do is use if - else condition,
if modal1 {
modalHead.html("<h3>Headline 1</h3>");
modalContent.html("<p>Content 1</p>");
modal.show();
}
else if modal 2 {
modalHead.html("<h3>Headline 2</h3>");
modalContent.html("<p>Content 2</p>");
modal.show();
}
else {
//default part
}
I'm working at a twitch.tv online stream , and i'm tryin' :
To prepend an html code from javascript in HTML
To put the content called from javascript , in a div with id="followerInfo" , and change the content every time when i press the buttons (depends on type of data called by that buttons)
. When I press the button all , it must show me all the tv streams , same for online - online streams and also with offline btn
. and the most important , to understand what am I doing here, not only to copy paste a code...
I'm stuck here .. I'm a self-taught (tryin' to be programmer) and implicitly a newbie in this field, but I want to learn that's why I'm asking you for a little help , if you can also explain me a little bit how to do it.
<div class="row second text-center">
<div class="col-md-4 btn btn-info" id="all">
All
</div> <!-- Online -->
<div class="col-md-4 btn btn-success" id="online">
Online
</div> <!-- Online -->
<div class="col-md-4 btn btn-danger" id="offline">
Offline
</div> <!-- Offline -->
</div>
<div id="followerInfo" style="margin-top:50px;">
</div>
for button All
$("#followerInfo").prepend("<div class='row'>" + "<div class='col-md-4'>" + "<a href='" + ur_l + "' target='_blank'><img src='" + logo + "'></a>" + "</div>" + "<div class='col-md-4'>" + name + "</div>" + "<div class='col-md-4'>" + status + "</div></div>");
for button offline
$("#followerInfo").prepend("<div class='row'>" + "<div class='col-md-4'>" + "<a href='" + ur_l + "' target='_blank'><img src='" + logo + "'></a>" + "</div>" + "<div class='col-md-4'>" + name + "</div>" + "<div class='col-md-4'>" + status + "</div></div>");
for button online
$("#followerInfo").prepend("<div class='row'>" +
"<div class='col-md-4'>" + "<a href='" + ur_l +
"' target='_blank'><img src='" + logo + "'></a>" +
"</div>" +
"<div class='col-md-4'>" + name + "</div>" +
"<div class='col-md-4'>" + status + "</div></div>");
If it will help you to understand better my code , here is the codepen link
http://codepen.io/queky18/pen/BzbpwV
$('.second div').on('click', function(e) {
e.preventDefault();
var status = $(this).attr('id'), // get the id of the status button clicked on.
followerRow = $('#followerInfo .row'),
statusColumn = $('#followerInfo .col-md-4:last-child');
statusColumn.each(function(){// check the text in the last column of each row
if (status == "all") { // for the show all button.
followerRow.show();
} else {
if ($(this).text().toLowerCase() != status) { // convert text to lowercase and compare with status
$(this).parent().hide(); // gets the parent div of the last column, which would be the row and hide it.
} else {
$(this).parent().show(); // otherwise we show the row.
}
}
});
});
This should work with your current code, but as mentioned, it's probably worth the time to go through and re-factor your code if you start to see duplication.
See an updated version here - http://codepen.io/anon/pen/PzLALa
The first item in my list group has it's '< /a>' removed upon insertion into the page and my question is why and how do I fix this? If I console the html generated before and after the insertion the missing tag is there.
Here is the generator code:
function ObjMatched(item1, item2) {
this.item1 = item1;
this.item2 = item2;
}
var obj_list = '<div class="list-group>';
for (var i = 0; i < Obj.length;i++) {
if (Obj[i].item1 == selection) {
ObjMatched.item1 = Obj[i].item1;
ObjMatched.item2 = Obj[i].item2;
obj_list += '<a href="#" class="list-group-item" data-item1="' + ObjMatched.item1 + '" data-item2="' + ObjMatched.item2 + '" >' + ObjMatched.item1 + ', ' + ObjMatched.item2 + '</a>';
}
}
obj_list += '</div>';
$("#obj_block").append(obj_list);
Here is the HTML output:
<div id="obj_block">
<div class="list_group">
<a href="#" class="list-group-item" data-item1="mary" data-item2="smith">mary, smith
tom, jones
dirty, harry
</div>
</div>
As a consequence the first item does not appear as part of the list within the web browser and is not clickable. I have tried replacing append() with html() to no avail.
I have tested this in Chrome, Safari and Firefox all with the same result.
What am I doing wrong?
You're not closing the quotes on your first div:
var obj_list = '<div class="list-group>';
Change it to:
var obj_list = '<div class="list-group">';
And it will work. It's happening because the first apostrophe is closing this div and making the anchor tag invalid.
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
);
I'm using the following function to display the image on which the user clicks on in an above div.
In the event the user clicks again on the populated image (in the div), I would like to remove the image in the div and have the original image visible again.
<img id="<?php echo $id; ?>" src="img/.." url=".." name="..." onClick="changeImage(this)"/>
function changeImage(item) {
var url_img = $(item).attr('url');
var name_item = $(item).attr('name');
var item_id = $(item).attr('id');
document.getElementById('test').innerHTML += '<div style=\'display:inline-block\'><img src=' + url_img + ' url = ' + url_img + ' onClick=document.getElementById(' + item_id + ').classname=\'\'; /> ' + name_item + '</div>';
$(item).toggleClass('hideitem');
}
.hideitem is a class with display:none;
The onClick event in the function does not work (I was trying to remove the classname) and I'm not able to remove the div image when it is clicked with the onClick event.
Would anyone have an idea to fix this?
Thanks
There were some missing quotes and stuff in your code.
For this HTML:
<img id="myImgID" src="http://placehold.it/350x150" url="http://placehold.it/150x150" name="Example Dot Com" onClick="javascript:changeImage(this)" />
<div id="test">
<p>this is only a test</p>
</div>
This JS:
changeImage = function (item) {
var $item = $(item),
$test = $('#test'),
url_img = $item.attr('url'),
name_item = $item.attr('name'),
newDiv = $('<div/>').css('display', 'inline-block').text(name_item),
newImg = $('<img/>').attr({'src':url_img, 'url':url_img})
.click(function(e){$item.removeClass('hideitem')}).prependTo(newDiv);
$test.append(newDiv)
$item.toggleClass('hideitem');
}
See it in action here