Cleanest way to add reply forms to nested comments - html

I am adding nested (reddit-like) comments to my app; so far I'm just using comment divs, where in my CSS I do this:
.comment {
margin-left: 40px;
}
This works fine for displaying comments. My question is what is the cleanest way to now add reply forms to each comment (and only show it when the user clicks a reply button of some sort)?
Is this usually done by adding all the input boxes for the comments right away, hiding them at first, and then only showing them if the user clicks on a reply button? Or perhaps should I only append the relevant <form> HTML code to a given div once the user clicks reply for that comment?
What is the cleanest way to do this?

You can do that by having one form field hidden somewhere in the html and when ever user clicks on the commect clone the form element and append it to the comment div
checkout this jsFiddle example below is the code snippet
<div class="comment">
comment1
</div>
<div class="comment">
comment2
</div>
<div style="display:none">
<form id="commentForm">
<textarea name="comment"></textarea>
</form>
</div>
var Comment = {
init: function() {
$(".comment").bind('click', $.proxy(this.handleClick, this));
},
handleClick: function(evt) {
var form = $('#commentForm').clone();
var target = $(evt.target);
var isFormAvailable = $("#commentForm", target).length > 0;
if(!isFormAvailable) {
$(evt.target).append(form);
}
}
};
$(function() {
Comment.init();
});

Keep a template of the form somewhere in your document and keep it hidden. On click of reply next to any comment, do following.
Clone the template (you can jquery clone function)
Set a hidden field in the template to the id of the comment for which reply is been clicked
append it next to comment that need to be replied
I'll go with this.
Keep the input boxes with each comment right away doesn't make sense. It's unnecessarily increasing the size of the page.

Related

HTML fieldset: form attribute not working

I am trying to create an HTML form is separate parts for layout reasons. As far as I understand, you can use a fieldset with a form attribute to associate the fieldset with the form, even if it’s not inside the form (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset).
However, if I have a separate fieldset with a submit button or another input in it, it doesn’t seem to work.
<form id="test">
<input name="inside-stuff" value="Inside">
<button type="submit">Doit Inside</button>
</form>
<fieldset form="test">
<input name="outside-stuff" value="Outside">
<button type="submit">Doit Outside</button>
</fieldset>
In the above snippet I have two submit buttons and two inputs. The one in the actual form works, while the one in the attached fieldset doesn’t. When I use the inside submit button, it only submits what’s in side the main form, not what is in the associated fieldset.
This may not be obvious when running the snippet, but is certainly the case when tried in real life.
What is missing to make this work?
Update 1
The problem appears to be more generic than that. I find that input elements inside an associated fieldset don’t get submitted either.
Update 2
This is not a duplicate of Submit form using a button outside the <form> tag. This question specifically refers to a fieldset element. The other doesn’t even mention it.
I wrote the following javascript
function control() {
function view(i) {
var frm = items[i].getAttribute("form");
var fBase = document.querySelector("form[id=" + frm + "]");
fBase.addEventListener("submit", function(){
var fld = document.querySelector("fieldset[form='" + this.id + "']");
var cln = fld.cloneNode(true);
cln.style.display = "none";
document.getElementById(frm).appendChild(cln);
},true);
}
var items = document.querySelectorAll("FIELDSET[form]");
var getter = function () {
return this.getAttribute("form");
};
for(var i = 0; i < items.length; i++) {
view(i);
Object.defineProperty(items[i], 'form', {
get: getter
});
}
}
window.addEventListener("load",control,true);
It's happening because the Form you have placed inside the fieldset is wrong. The form should be the parent of the fieldset in order to get it to work!
The form tag should always be the parent of the fieldset.
If you place <form> and <fieldset> then it will work. The code below should do.
<form id="test">
<input name="stuff">
<button type="submit">Doit</button>
</form>
<form>
<fieldset>
<input type="text" name="stuff2">
<button type="submit">Doit</button>
</fieldset>
</form>
I hope this will help!

show/hide on multiple div without defining div element id

first am sorry for bad English / grammar
am creating something where you show and hide.
but my problem is that when I click show/hide it only brings input box 1 on both buttons. and I want it to show/hide each box.
my problem is that. I don't want to use the id to define show/hide Element
because if I have more than 10 div with input boxes I have to define them all by getElementById I don't want that.
I want when I click on the show/hide it brings input box without getElementById
so that even if I have more then 10 input box to show I only click and show/hide without defining its id
function myFunction(event) {
var x = document.getElementById("mydv");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
x.parentNode.insertBefore(x, event.target.nextSibling);
}
document.addEventListener('click', function(event){
if(event.target.className.includes("dv1")){
myFunction(event);
}
});
<!DOCTYPE html>
<html>
<head>
<title> SHOW / Hide </title>
</head>
<body>
<ul>
<li>
<div id="mydv" style="display:none;">
<p>input box 1
<input type="text" name="textfield">
</p>
</div>
<button class="dv1">SHOW/HIDE</button>
</li>
<li><div id="mydv" style="display:none;">
<p>input box 2
<input type="text" name="textfield">
</p>
</div>
<button class="dv1">SHOW/HIDE</button></li>
</ul>
</body>
</html>
If you want to specify an element on a page, that can be similar in every way to other elements except perhaps text content or something else, realistically you need an id, as this is how JavaScript defines a unique element.
But what you can do, is change your HTML button, to contain a rel, which is an attribute, and then get that attribute and use that to specify which element id you're looking for.
You can then call a function and simply pass "this" as an argument.
HTML :
<button onclick="hideShow(this)" rel="mydv">Show/Hide</button>
JavaScript :
<script>
function hideShow(elem){
var ele = document.getElementById(elem.getAttribute("rel"));
if(ele.style.display == "none"){
ele.style.display = "block";
}
else{
ele.style.display = "none";
}
}
</script>
If you are absolutely abhorrent to using ID's, you can use child nodes and specify which child by number, but this means if ever you change anything, you will break your code, which is foolish. I recommend using unique ID's and simply changing your code in the above ways.
Short and lazy answer to your problems - if you are going to keep your current hierarchy, you can simply find DIV tag inside your LI parentNode (since its the only DIV tag).
Basically it goes like this - button press -> change focus from button to parentNode LI -> finds DIV.
in short - in function myFunction(event) change
var x = document.getElementById("mydv");
to
var x = event.target.parentNode.getElementsByTagName("DIV")[0];
Working example:
https://jsfiddle.net/w2a9zg46/1/
The problem is that getElementById refers to the first element with that id. It simply ignores everything else. Using the same id for more than one element is a bad practice. An id should be a unique reference to that element, use class instead.

AngularJs - how to support a textbox with hyperlinks

I'm new to Angular but I'm trying to implement a textbox that allows users to enter in links. I only want to support links, and otherwise I want to block all html from being presented as such. I could theoretically use something other than a textarea, but my requirements are that it must be bound to a variable in my scope (right now with ng-model) and I cannot accept html tags other than '< a >'
Here is my example plnkr
In the example, I would like the second seeded item to display as a link, blue and underlined. However, the third item should display as it is currently shown (without interpreting it as html).
HTML:
<textarea maxlength="160" ng-model="val.text"></textarea>
<div class="btn" ng-click="submit()">Submit</div>
<br><br>
<div ng-repeat="item in items">
{{display(item)}}
</div>
JS:
$scope.submit = function() {
if (!$scope.val.text) return
$scope.items.push($scope.val.text);
}
$scope.display = function(txt) {
return txt;
// something here? if txt contains <a> and </a> indicate
// that we should display as html
}

*Multiple* Print Specific Div

I'll try to explain:
I have numerous div classes, but for the sake of simplicity, let's say I only have 3.
Someone is viewing DIV 1, and I want to give them the option of only printing DIV 1, omitting 2 and 3.
However, on the same page, I would like to give them the option to ONLY PRINT DIV 2. Or only print DIV 3.
I think I get how you can omit certain things from getting printed. But how can you select a section here or there on the same page to be printed with a print link.
Thanks,
Tracy
You can use jQuery to show/hide divs. Read the jQuery tutorial:
http://docs.jquery.com/Tutorials
The code will look this way:
<script>
function showDiv(n) {
$('.divs').hide();
$('#div_'+n).show();
}
$(document).ready(function() { showDiv(1); });
</script>
<a href='javascript:showDiv(n)'>show div n</a>
<div class='divs' id='div_n'>I'm div n</div>
There are many related posts on printing div content, this particular question was still open though it was asked in '10.. Following JavaScript function can be used for printing content of a selected Div tag. Hope this helps. Declaimer: I used some of the existing answers, fixed/enhanced code/error(s) to work with (and tested on) IE-8.
function printDiv(divName) {
var divToPrint = document.getElementById(divName);
var newWin = window.open('', 'PrintWindow', 'width=400, height=400, top=100, left=100', '');
newWin.document.open();
newWin.document.write('<html><body onload="window.print()">' + divToPrint.innerHTML + '</body></html>');
newWin.document.close();
setTimeout(function () { newWin.close(); }, 10);
}
Call printDiv from anywhere in page or from within selected Div. Here is test link:
Print Customer Data
Print Order Data
Assign respective IDs to Div that is to be printed:
<div id="divCustomerData">Div Contents goes here... </div>
The only catch right now is it loses css styles. I'll update response when i get a chance to fix it. Thanks.
https://github.com/jasonday/jquery.printThis
I would give each div an id, and then using the above plugin (i wrote) specify according to div id.

Ideas for multicolored textbox?

In my site, I would like to implement a textbox where people can input a set of strings separated by a separator character.
For example the tags textbox at the bottom of this page: tags(strings) delimited by space(separator).
To make it more clear to the user, it would make a lot of sence to give each string a different background color or other visual hint.
I don't think this is possible with a regular input[text] control.
Do you deem it possible to create something like that with javascript? Has somebody done this before me already? Do you have any other suggestions?
Basic Steps
Put a textbox in a div and style it too hide it.
Make the div look like a text box.
In the onClick handler of the div, set the input focus to the hidden text box.
Handle the onKeyUp event of the hidden text box to capture text, format as necessary and alter the innerHtml of the div.
Tis quite straightforward. I'll leave you to write your formatter but basically you'd just splitString on separator as per the Semi-Working-Example.
Simple Outline
<html>
<head>
<script language="javascript" type="text/javascript">
function focusHiddenInput()
{
var txt = document.getElementById("txtHidden");
txt.focus();
}
function formatInputAndDumpToDiv()
{
alert('Up to you how to format');
}
</script>
</head>
<body>
<div onclick="focusHiddenInput();">
Some label here followed by a divved textbox:
<input id="txtHidden" style="width:0px;" onKeyPress="formatInputAndDumpToDiv()" type="text">
</div>
</body>
</html>
Semi-Working Example
You still need to extend the click handlers to account for tag deletion/editing/backspacing/etc via keyboard.... or you could just use a click event to pop up another context menu div. But with tags and spacer ids identified in the code below that should be pretty easy:
<html>
<head>
<script language="javascript" type="text/javascript">
var myTags=null;
function init()
{
document.getElementById("txtHidden").onkeyup= runFormatter;
}
function focusHiddenInput()
{
document.getElementById("txtHidden").focus();
}
function runFormatter()
{
var txt = document.getElementById("txtHidden");
var txtdiv = document.getElementById("txtBoxDiv");
txtdiv.innerHTML = "";
formatText(txt.value, txtdiv);
}
function formatText(tagText, divTextBox)
{
var tagString="";
var newTag;
var newSpace;
myTags = tagText.split(' ');
for(i=0;i<myTags.length;i++) {
newTag = document.createElement("span");
newTag.setAttribute("id", "tagId_" + i);
newTag.setAttribute("title", myTags[i]);
newTag.setAttribute("innerText", myTags[i]);
if ((i % 2)==0) {
newTag.style.backgroundColor='#eee999';
}
else
{
newTag.style.backgroundColor='#ccceee';
}
divTextBox.appendChild(newTag);
newTag.onclick = function(){tagClickedHandler(this);}
newSpace = document.createElement("span");
newSpace.setAttribute("id", "spId_" + i);
newSpace.setAttribute("innerText", " ");
divTextBox.appendChild(newSpace);
newSpace.onclick = function(){spaceClickedHandler(this);}
}
}
function tagClickedHandler(tag)
{
alert('You clicked a tag:' + tag.title);
}
function spaceClickedHandler(spacer)
{
alert('You clicked a spacer');
}
window.onload=init;
</script>
</head>
<body>
<div id="txtBoxDivContainer">
Enter tags below (Click and Type):<div id="txtBoxDiv" style="border: solid 1px #cccccc; height:20px;width:400px;" onclick="focusHiddenInput();"></div>
<input id="txtHidden" style="width:0px;" type="text">
</div>
</body>
</html>
Cursor
You could CSS the cursor using blink (check support) or otherwise just advance and hide as necessary an animated gif.
This is quite interesting. The short answer to your question is no. Not with the basic input element.
The real answer is: Maybe with some trickery with javascript.
Apparently Facebook does something close to this. When you write a new message to multiple persons in Facebook, you can type their names this sort of way. Each recognized new name is added a bit like an tag here and has an small cross next to it for removing it.
What they seem to do, is fake the input area size by drawing an input-looking box and removing all styling from the actual input with css. Then they have plenty of logic done with javascript so that if you have added an friend as a tag and start backspacing, it will remove the whole friends name at once. etc.
So, yes, it's doable, but takes plenty of effort and adds accessibility problems.
You can look how they do that at scripts like TinyMCE, which add such features to textareas. In textareas you can use HTML to colorize text.
You can use multiple textboxes
textbox1 <space> textbox2 <space> textbox3 ....
and so on... You can then apply the background-color style to each textbox.