Trying to create a dynamic list item. jQuery - javascript

I have a couple of list items, on the left side and aligned vertically. I'm trying to make so that the container on the right side, which is empty, will populate with information from the url for that list item's specific id. I was able to create a jQuery function using load() and it allowed me to click within the list item and data was populated in the right container, but it's only the data for the smallest id. If I click the other list items, the data in the right container doesn't change. Currently, I added this line of code,
var strReqUrl = $(this).attr('href');
alert(strReqUrl);
to see if an alert would display the link it's supposed to be using. When I click within the list item, the alert says "Undefined". :(
I tried adding a link within the list item, and it works. The correct data is shown, however, I leave my current page every time to see it and it doesn't populate in the container on the right at all, which is now on the previous page.
Is there anyway to get the proper id assigned to the proper list item?
Here is my HTML:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("li").click(function(){
var strReqUrl = $(this).attr('href');
alert(strReqUrl);
//$("#divId").load("pm_message.php?u=<?php echo $log_username; ?>&pmid=<?php echo $pmid; ?> #pm_post");
});
});
<body>
<div class="wrapper"> <!--Left and Right container wrapper-->
<div class="container">
<div class="left">
<!--left container-->
<div class="top">
<input type="text" />
</div>
<ul class="people">
<?php echo $people; ?> <!--generates list of people-->
</ul>
</div>
<div class="right" id="right">
<!--Right container-->
<div class="top"><span class="name"></span></div>
<div id="divId"></div>
</div>
</body>
</html>
And script:
//DB connection
//Collecting data from db
//Variable $people collects data for the people listed in the left container
$people = '
<li class="person">
<a id="a" href="pm_message.php?u='.$log_username.'&pmid='.$pmid.'"><span class="name">'.$sender.'</span></a>
<!--<span class="name">'.$sender.'</span>-->
<span class="time">'.$time.'</span>
<span class="preview">'.$message.'</span>
</li>';

When you assign event handlers, li is not already in the document. You need to use delegated handling. And the href attribute you are looking for is not there. Try this:
$('ul').on('click', 'li', function() {
var strReqUrl = $(this).find('a').attr('href');
alert(strReqUrl);
});
See more - http://api.jquery.com/on/

Related

Javascript modal that displays list that closes and returns to main html

Rather new to javascript, jquery and bootstrap, etc., so bear with me. I have a situation where I want to present a list of errors in a model dialog after the user hits a "validate" button. Got all the working - I am generating a list of objects that indicate to the user they need more work to the exact spot that needs additional data entry. I have the the DIV "id" that represents the field that needs more data (and each item will jump someplace different).I do not want a drop down list since there are be lots and lots of these items.
A few questions:
How do I go about jumping from the modal to the main html. I believe I have seen scrollIntoView mentioned in a few other posts as I was looking but will that hop to the DIV and also close the modal?
What construct should I use for the list? A list of scrolling button? The size of this can be quite large (hundreds) so it will need a scroll capability.
Finally, the app is "paged" with a next and prev buttons. I assume that will not be a problem from the aspect of jumping to a page not already displayed?
Here is the current modal code:
<script id="template-validation-error" type="text/x-handlebars-template">
<div id="validationErrorModal" class="modal">
<div class="message-container">
<div class="header">
Validation Errors
</div>
<div class="message">
The following fields are required:
</div>
<div class="center">
<input type="button" class="btn btn-solid-green btn-sm" onclick="fffdevice.validationErrorOk();" value="Done" />
</div>
</div>
</div>
</script>
and
showValidationError: function (fieldlist) {
settings.focusedField = $(':focus');
$("#validationErrorModal").detach();
$(".device-container").append(templates.validationerror({ fieldlist }));
$(".message-container input").focus();
},
validationErrorOk: function () {
$("#validationErrorModal").detach();
if (settings.focusedField) {
settings.focusedField.focus();
}
},
The field list is a list of objects that contain the id (field.id) of the DIV and also a description (field.fieldName) that I want to display.
Here is something I mocked up in paint...I am not sold on it but it show in a general sense what I am looking for:
I don't need a full solution rather, just want mechanisms I can use.
UPDATE
Just to help out anyone else in the future, using the info provided in the correct answer below I have a new code as follows:
<script id="template-validation-error" type="text/x-handlebars-template">
<div id="validationErrorModal" class="modal">
<div class="validation-container">
<div class="header" align="center">
Validation Errors
</div>
<div class="message">
<div class="scrolling-container" style="background-color: rgb(238, 238, 238); height:660px">
<div class="grid grid-pad">
{{#each fieldlist}}
<div class="row click-row" onclick="fffdevice.validationErrorFix('{{id}}');">
<div class="col-7-8 field-name">{{fieldName}}</div>
<div class="col-1-8">
<img class="pull-right" src="/mysite/Content/device/images/fix.png" style="width: 40px; position:relative; top: -5px;">
</div>
</div>
{{/each}}
</div>
</div>
</div>
<div><br/></div>
<div class="center">
<input type="button" class="btn btn-solid-green btn-sm" onclick="fffdevice.validationErrorOk();" value="Done" />
</div>
</div>
</div>
Then the Javascript for the onClick is:
validationErrorFix: function (id) {
$("#validationErrorModal").detach();
var x = document.getElementById(id);
x.scrollIntoView({
behavior: "smooth", // or "auto" or "instant"
block: "start" // or "end"
});
},
Which closes the dialog and jumps to the field. It looks like (I know this is ugly and I will clean it up later):
Bind the modal event to the validation code and show the modal if error(s) are found.
Display the modal with the list of errors using an html unordered list, inside the li element an anchor tag where the href attribute will have a value with the id that corresponds to the input field, all this done dynamically from your validation code.
Once an error in the list is clicked hide the modal using bootstrap $('#your-error-modal').modal('hide'); so the code would be something like this:
$('#your-error-modal').on('click', 'a.error-item', function(){
$('#your-error-modal').modal('hide');
});
I haven't tested this code, but if you're having issues with scrolling to the section of the input and closing the modal you can probably do something like this too:
$('#your-error-modal').on('click', 'a.error-item', function(e){ // use this method of onclick because your list will be created dynamically
e.preventDefault(); // prevent the default anchor tag action
var href = $(this).attr('href'); // grab the href value
$('#your-error-modal').modal('hide'); // close the modal first
scrollToDiv(href); // then take the user to the div with error with a nice smooth scroll animation
});
function scrollToDiv(location) {
$('html, body').animate({
scrollTop: $(location).offset().top
}, 2000);
}
Again this is untested code, but the idea is there.
For UX reasons you might also want to create a floating div or something where users can click on it and go back to the modal to continue reading your list of errors.

Struggling to expand div based on dynamic data from database (comments feature)

I have been struggling with this common social networking feature for quite some time. What I am trying to do is to expand the div to display comments, I'm sure you know what I am talking about.
Each post a user sends is automatically echo'd with an anchor link Comments. As mentioned, when this link is clicked, it will simply expand the div displaying all comments assigned to that thought_id.
Even if there are no comments assigned to the post, I still want the div to expand to display a text field so any user can post a comment, preferably echo this:
<?php
<form action='' method='post' enctype='multipart/form-data'>
<table style='width:850px;'>
<tr>
<td><textarea name='msg' rows='2' maxlength='255' cols='80' placeholder=' add your comment...'></textarea></td>
<td><input type='submit' name='send' value='Share'/> </td>
</tr>
</table>
</form>
?>
Here is what I have so far:
<script language="javascript">
var id = <?php echo $thought_id; ?>;
function toggle(id) {
var ele = document.getElementById("toggleComment" + id);
if (ele.style.display == "block") {
ele.style.display = "none";
} else {
ele.style.display = "block";
}
}
</script>
And here is where the comments anchor link is found. Since it is quite lengthy, I have reduced the echo's content to only the relevant code:
echo "<div class='message_wrapper'>
<div class='where_msg_displayed'>
<div class='more_options' style='float: right;'>
// Options, and display picture of the user who posted the
// thought can be found here.
</div>
</div>
<div class='where_details_displayed'>
<div class='mini_nav' style='float: right;'>
// Below is the comments anchor link.
<a onclick='return toggle($thought_id);' style='padding-left: 5px;'> Comments ($num_of_comments) </a>
</div>
// I expect the following piece below to every comment assigned to the thought_id in the database.
<div id='toggleComment$thought_id' class='new_comment' style='display:none;'>
<br/> $comment_posted_by said: $comment_body
</div>
</div>
</div>";
Other Infomation:
$thought_id is the id of the though the user posts. (table user_thoughts, column id).
I have another table called user_comments, which stores all comments and links it to the thought it is assigned to by post_id.
At the moment, nothing happens when I click comments.
First, here is a working example of what you want to achieve based on your code.
I had to strip the php part off because jsfiddle doesn't interpret it, so next is your code including the PHP bit.
I assumed that you have jQuery loaded as you added the jquery tag to the question.
It's complicated to know why what you tried doesn't work because we're missing important bit such as: how do you load your content into the DOM? dynamically or not (ajax?)
HTML/PHP
<div class='message_wrapper'>
<div class='where_msg_displayed'>
<div class='more_options' style='float: right;'>
</div>
</div>
<div class='where_details_displayed'>
<div class='mini_nav' style='float: right;'>
<a href="#" class="toggle-comment" data-id="<?=$thought_id?>" style='padding-left: 5px;'> Comments (<?=$num_of_comments?>) </a>
</div>
<div id='toggleComment<?=$thought_id?>' class='new_comment' style='display:none;'>
<br/> <?=$comment_posted_by?> said: <?=$comment_body?>
</div>
</div>
</div>
Your link was missing an href attribute, which is mandatory for it to be displayed properly. So we set it to the commonly used "#" which means blank anchor. We will then need to catch the click event on this link and prevent its default action so we don't see that ugly # in our url
You should avoid storing big chunks of html in a php var and then echo it but use html templates instead.
You should avoid mixing PHP and javascript like this line in your code that assign a php var into a js one var id = <?php echo $thought_id; ?>;
Instead, You can store your thought_ids as a data attribute of your links and easily fetch them using jQuery's data() later.
Javascript
$(function() {
$("a.toggle-comment").on("click", function(event) {
// prevents browser to go to href's #
event.preventDefault();
// uses Jquery's data() function to get comment id from link's data-id attribute
var id = $(this).data('id');
// get element by id and toggle display
var ele = document.getElementById("toggleComment" + id);
$(ele).toggle();
});
});
Here I got rid of your toggle() function and replaced it with a handler function using jQuery's on() that get called each time we click on a link that has the toggle-comment CSS class. It has the advantage of working on dynamically added content after the page is loaded. jQuery's on() documentation page does a great job explaining this (and the deprecated live() page too)
Notice that you will need to add this toggle-comment class to every of your Comments (X) links
If you are new to jQuery, you should consider reading this page to understand what the first line does and why you need it. (referring to enclosing your code into $(function() {...});)
event.preventDefault(); tells the browser to not perform its default behaviour when clicking on the link (which is go to that link and would append # to the address bar)
$(this).data('id'); reads put the clicked link (this) into a jQuery object and use data() to get the value of its data-id attribute, which is set to $thought_id
CSS issue update
See my updated fiddle for your CSS issue, I removed the float inline styles and positioned div.mini_nav using absolute positioning relative to message_wrapper.
I think that this issue is not related to the original question and should be asked in another one.
PHP Code as per OP's
<?php
$thought_id = 1;
$num_of_comments = 10;
$comment_posted_by = "Me";
$comment_body = "test comment body";
//hard coded above vars to achieve assumptions
echo "<div class='message_wrapper'>
<div class='where_msg_displayed'>
<div class='more_options' style='float: right;'>
// Options, and display picture of the user who posted the
// thought can be found here.
</div>
</div>
<div class='where_details_displayed'>
<div class='mini_nav' style='float: right;'>
// Below is the comments anchor link.
<a href='' onclick='return toggle($thought_id);' style='padding-left: 5px;'> Comments ($num_of_comments) </a>
</div>
// I expect the following piece below to every comment assigned to the thought_id in the database.
<div id='toggleComment$thought_id' class='new_comment' style='display:none;'>
<br/> $comment_posted_by said: $comment_body
</div>
</div>
</div>";
?>
JavaScript
<script language="javascript">
var id = <?php echo $thought_id; ?>;
function toggle(id) {
var ele = document.getElementById("toggleComment" + id);
if (ele.style.display == "block") {
ele.style.display = "none";
} else {
ele.style.display = "block";
}
return false;
}
</script>
The above code worked for me, as per single record.
Now as you have tagged your question under jQuery
you could simply use
$(".message_wrapper .mini_nav a[href!='']").click(function() {
$(this).parent().next().toggle();
});
You could simply use the <details> HTML tag which acts as a disclosure triangle.
<details>
<summary>View comments</summary>
<ul>
<li>You comments</li>
<li>You comments</li>
<li>You comments</li>
</ul>
</details>
https://developer.mozilla.org/en/docs/Web/HTML/Element/details
The only issue is that it is not supported by the lovely IE browsers.
If I understand your question correctly , this is what you are looking for
https://jsfiddle.net/vrqsz3ev/7/
<div class='message_wrapper'>
<div class="main-msg-container">
<div class='where_msg_displayed'>
<input type="hidden" id="msg-id" value="1">
<div class='more_options'>
MESSAGE1
</div>
<div class='mini_nav'>
<button class="open-comment">comments</button>
</div>
</div>
<div class="hide-mess-details">
<div class='where_details_displayed'>
<div id='toggleComment1'class='new_comment msg-id-1'>
sachin said: Hii guysss (cmt of msg 1)
</div>
<form action='' class="comment-form"method='post' enctype='multipart/form-data'>
<textarea name='msg' placeholder=' add your comment...'></textarea>
<input type='submit' name='send' value='Share'/>
</form>
</div>
</div>
</div>
I made it using jQuery
Some of the things to note while looking into the code is
Uses the concept of flexbox in css3 to style it.
if you click on the share button only the comment of the respective message gets updated . For checking I added a message id along with the form when comment button is clicked .for checking purpose I added an alert (message id of the respective messages) if you click the share button
Now you can add your messages under .where_msg_displayed using php
display all the comments under .where_details_displayed (if you want to , you can add details under there respective messages -little edit is needed)
If you are continuing with this code , with little edits you can achieve the above requirements .

Dynamically create page in jquery mobile, only to include specific data from websql database

I have an application that has a page where all id's are selected from the table and specific bits of information are shown in html.
What i would like to do next is to make each of these elements as a whole a link to essentially, a 2nd level down.
This level down page will reveal all information bound to that row's id, is it possible to build this in a way that is dynamic?
I am using jQuery mobile to build pages, and i'd like to use 1 template and append the relevant html elements into it, and populate each with the id bound information.
I hope this makes some sense, and any guidance or suggestions would be greatly appreciated.
The above mockups represent what i would like to achieve, the left image displays a list of all rows in the table, upon clicking one of them, you are taken to another page, with only information for that particular id.
Can i achieve this for each item within the list?
It's a good navigation example and it's not difficult to implement.
Since the information is coherent (every DB row has the same columns), create just one empty template (edit: it's now based on your PasteBin):
<div data-role="page" id="route_details">
<div data-role="header">
<a data-rel="back"><i class="fa fa-arrow-left"></i></a>
<h1 id="walkTitle"></h1>
</div>
<div data-role="main" class="ui-content">
<div class="finishedRouteInfo">
<div class="mapDetails" style="width: 100%; height: 150px;"></div>
<div class="ui-grid-a">
<div class="ui-block-a home_btns no_border">
<div class="ui-block-a finishedDistance"><i class="fa fa-map-marker"></i></div>
<div class="ui-block-b"><p>Distance <br/><span id="finalDistance" class="value"></span></p></div>
</div>
<div class="ui-block-b home_btns">
<div class="ui-block-a finishedDistance"><i class="fa fa-clock-o"></i></div>
<div class="ui-block-b finishedDuration"><p>Duration <br/><span class="value" id="finalDuration"></span></p></div>
</div>
<span class="horizontalSplitter"></span>
<div class="walkDescription"></div>
</div>
</div>
</div>
The code in your PasteBin cannot work because you are creating multiple pages with elements having the same IDs (i.e.: finalDistance, finalDuration). Also, you are creating many pages which probably the user will never see.
So, simplify your loading function:
var last_results = [];
$(document).on("pageinit", "#my-routes", function() {
db.transaction(function(t){
t.executeSql('SELECT * FROM WALKS', [], querySuccess, errorCB);
});
function querySuccess(t, results, Element) {
last_results = results;
}
});
and delay the content/map creation just before showing the page with route details:
$("#route_details").on("pagecontainerbeforeshow", function()
{
// use your DB data
var data = last_results.rows.item(clicked_route);
$("#walkTitle).html(data.WalkTitle);
$(".walkDescription").html(data.WalkDescription);
// ...create the map and fill the rest...
});
You just have to link each route to this page, setting clicked_route when the link is clicked using something like this:
<a class="walkPage" href="#route_details" data-route="0">Route 0</a>
<a class="walkPage" href="#route_details" data-route="1">Route 1</a>
<a class="walkPage" href="#route_details" data-route="2">Route 2</a>
JavaScript:
$(document).on("click", ".walkPage") {
clicked_route = parseInt($(this).attr("data-route"));
});
...Since you have to show the route map in two different pages, refactor your code so that you can easily create a map and add it to any page.
Hope it's sufficiently clear to fully implement it.

Temporarily store text from a dynamic location in the DOM in a javascript variable

I'm building a website for a school assignment, so it's kind of simple. Please excuse or correct any incorrect terminology.
I have multiple identical div's , all sharing the same class, each of these has two paragraph elements in them with some some text in each.
Triggered by a click, I want the specific div I clicked on to be assigned an id for reference in a variable, which should store some text from a child paragraph. I am trying to make a div appear, and the text to be pulled in from the variable.
This is the Javascript I have written:
$(document).ready(function(){
//Hide the overlay.
$('#overlay_align').hide()
//Fade in the overlay and change the title.
$('.object').click(function(){
//Sets the clicked item to have an id "active", for use in the variable "title".
$(this).attr("id", "active")
//Gets the text from this item's title section.
var title = $('#active:nth-child(2)').text()
//Sets the title printed in the overlay to whatever the title of the clicked item was.
$('#overlay_title').html(title)
console.log( title )
$('#overlay_align').fadeIn("fast");
})
//Fade out the overlay.
$('#close').click(function(){
$('#overlay_align').fadeOut("fast")
//remove the id for reuse when another item is clicked.
$('#active').removeAttr("id");
});
});
And the relevant part of the HTML document:
<head>
<link rel="stylesheet" type="text/css" href="Stylesheet.css"/>
<!--jQuery 1.4.2-->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<!--Overlay on click-->
<script type="text/javascript" src="../Overlay.js"></script>
</head>
<body>
<div id="overlay_align">
<div id="overlay">
<div id="overlay_left">
<img id="overlay_img" src=""/>
<img id="loading" src="../Loading.gif" width="50" height="50" style="margin-top:50%"/>
</div>
<div id="overlay_right">
<p id="overlay_title"></p>
<img id="close" src="../Close%20Button.png" width="20" height="20"/>
<p id="overlay_description"></p>
</div>
<div id="overlay_footer">
</div>
</div>
</div>
<div class="object">
<div class="display"></div>
<p class="title">Ttile</p>
<p class="category">Category</p>
</div>
<div class="object">
<div class="display"></div>
<p class="title">Ttile</p>
<p class="category">Category</p>
</div>
<div class="object">
<div class="display"></div>
<p class="title">Ttile</p>
<p class="category">Category</p>
</div>
The issue I have is that currently, the variable stores the content of both the paragraphs instead of just the second one, (so it appears as "Title Category", and even that only works with the first div. I'm not fixed on this way of doing it, so I'm open to any other ways of doing this too.
Reputation is preventing me from posting individual links, so heres an imgur album showing the different states it's appearing in: https://imgur.com/a/bB7XQ
PS: Is there any way to not have to manually indent every line with four spaces?
You are looking at the wrong element. The selector #active:nth-child(2) isn't looking for the second child in the element with id="active", it looks for an element with that id that is the second child. You would use #active p:nth-child(2) to look for the paragraph inside the element.
However, you will run into a problem as you are adding an id to the element. The second time that you click something you will have that id on two elements, so you will get the text from that element and the text from the previous element. Also, as an id should be unique in the page, you may even get some unexpected behaviour in some browsers.
You don't need to set the id on the element to find it, you already have a reference to it in this that you can use. Specify this as context, and use the selector p:nth-child(2):
$('.object').click(function(){
//Gets the text from this item's title section.
var title = $('p:nth-child(2)', this).text()
//Sets the title printed in the overlay to whatever the title of the clicked item was.
$('#overlay_title').html(title)
console.log( title )
$('#overlay_align').fadeIn("fast");
})
Demo: http://jsfiddle.net/6D9JD/
I am not sure if I am answering the question correctly. As per my understanding the problem you are facing is
var title = $('#active:nth-child(2)').text()
Instead of looking for the second last child you can find the class title in the corresponding div.
var title = $('#active').find('.title'); //Assuming that you have only one title in a single div
you need to use
$('#active:nth-child(2)').children().last().text()
instead of
$('#active:nth-child(2)').text()

iframe breaking jquery.contents?

So I am trying to do some inner HTML pop up window work, by using Jquery.contents() on a hidden div to place the content in the pop window on click.
For some reason, if any of the divs have an iframe in them, all the divs after them in the html will not be able to be appended. Is this some sort of bug? Here is an example:
<div class="hide">
<div id="apps">
<iframe src="http://ryansaxe.info/javascriptpaint" />
</div>
<div id="contact">
<ol>
<li>Phone: (111)-111-111</li>
<li>Email: email#gmail.com</li>
</ol>
</div>
<div id="resume">
<p>resume</p>
</div>
</div>
In the case above, only the #apps content reads, because it has an iframe, and all contents after that then don't read. If the div with the #apps id was last, every single one would have readable contents through Jquery.contents()
Jsfiddle
note:
Here is my jquery
$('.open').click(function(){
var name = $(this).attr("name");
var selector = $(name);
var cont = selector.contents();
$('#pop').append(cont.clone());
});
$('.close').click(function(){
$('#pop').empty();
});
Like scripts, you cannot use the /> syntax with iframes. Explicitly write out the </iframe>:
<iframe src="http://ryansaxe.info/javascriptpaint"></iframe>

Categories

Resources