Is there anyway to transfer html elements from one client to another with keeping of every entered values like in textboxes? - javascript

Let's say I have a page with some html elements.
Those elements are textboxes ,checkboxes ,radiobuttons and other user responsive things.
I need a possibility to transfer whole page from client1 to client2, so client2 will see everything that client1 has set into html elements.
I use WebSocket technology for that, but I don't know how to transfer that elements. If I transfer document.body.innerHTML then client2 see blank elements, instead of filled ones.
On the page could be any amount of any html elements. Is it possible to do something like clonning elements but over websocket? Like I serialize whole document.body and transfer it to another client?
The page are simple html ones. No any server side script are used. I use self made http + websocket server that is working on same port.

I started something that could help you.
You make a loop to get element by Tag (to get all input)
You process them according to the type: text, checkbox, radio,... by saving the value in an attribute (in my exemple, I update the defaultvalue using the value)
then you send it the way you want to. In my example, i show the content using alert; but use your socket.
Maybe you need to add some processing on the the receiving page.
The Text input will show the default value, but you may have to set checkbox 'checked' from the 'value' attribute. I would use a document.onload, with a for each (get element by tag)
Here is the example:
Javascript get Body content into variable
<body>
<p class="first">Hello World Dude</p>
<label for="search_field">my text:</label>
<input type='text' id ='myinput' class='MyIntputField' />
<input type="checkbox" name="vehicle" value="Bike"> I have a bike<br>
<input type="checkbox" name="vehicle" value="Car" checked> I have a car<br>
</body>
<p id="demo" onclick='myFunction()'>Click me to send Data.</p>
<script>
function myFunction() {
inputs = document.getElementsByTagName('input');
for (index = 0; index < inputs.length; ++index) {
switch (inputs[index].type){
case "text":
inputs[index].defaultValue = inputs[index].value;
break;
case "checkbox":
inputs[index].value = inputs[index].checked;
break;
}
}
var $mybody = $("body").html();
}
</script>

You need to use outerHTML instead of innerHTML, however that wont set your input values so you have to do that manually.
// To send your html via websocket
//var ws = new WebSocket('ws://my.url.com:PORT');
//ws.onopen = function(event) { // Make sure it only runs after the web socket is open
document.querySelector('button').addEventListener("click", function() {
var inputs = document.querySelectorAll('input');
Array.prototype.forEach.call(inputs, function(el, i) {
el.setAttribute('value', el.value);
});
document.querySelector('button').setAttribute('data-button', true); // Attributes are rememebered
var HTML = document.querySelector('section').outerHTML;
document.querySelector('#result').innerHTML = HTML;
document.querySelector('#resulttext').textContent = HTML;
//ws.send(HTML);
});
//};
html,
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
div {
background: orange;
border: 3px solid black;
}
<section>
<div>
<input />
</div>
<div>
<input />
</div>
<div>
<input />
</div>
<div>
<input />
</div>
<div>
<input />
</div>
<div>
<button>Generate</button>
</div>
</section>
<p id="resulttext"></p>
<p id="result"></p>

Related

Remove option item from dataset

Am trying to achieve the following:
The user can select a resource name from a datalist.
The selected resource name will be created in another div.
At the same time, the resource name should be removed from the original datalist. Just to prevent from having the user selecting the same resource name again.
I used the following HTML Code:
<div class="container-client">
<form action="#">
<div class="user-details">
<div class="input-box">
<span class="details">Collaborateurs<small>*</small></span>
<input type="text" placeholder="Selectionner un collaborateur" list="resource-list" required autocomplete="off" id="candidate">
<datalist id="customer-list">
<option value="Alex">Menuisier</option>
<option value="Peter">Charpentier</option>
<option value="Alain">Ingénieur béton</option>
<option value="Adam">Placo</option>
</datalist>
</div>
<div class="button-plus">
<input type="button" value="+" onClick="addResource();">
</div>
</div>
</form>
<hr>
<form action="index.html">
<div class="user-details">
<div class="input-box">
<span class="details">Mon équipe:</span>
</div>
<div class="new-box" id="dynamic-list">
</div>
<div class="new-box">
<div class="button">
<input type="submit" value="✔">
</div>
</div>
</div>
</form>
</div>
Here below the JS code I tried to use; adding the resource name to the div works completely fine, however the removal of the resource name doesn't work.
function addResource()
{
var new_team_member = document.getElementById ('dynamic-list');
var generic_list = document.getElementById ('resource-list');
var candidate = document.getElementById("candidate");
if (candidate.value =='')
{
alert('No data selected');
}
else
{
var div = document.createElement("div");
div.setAttribute('class','input-box');
var input = document.createElement("input");
input.setAttribute('type','text');
input.setAttribute('placeholder',candidate.value);
input.setAttribute('disabled','disabled');
div.appendChild(input);
new_team_member.appendChild(div);
generic_list.removeChild(candidate);
document.getElementById('candidate').value = '';
}
}
The error message I got is about "add-resources.js:20 Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node." indicating thatt the following JS line is causing the problem: generic_list.removeChild(candidate);
Can you please help recommending a solution. Thanks in advance.
First of all, in the code, you provided the resource-list and customer-list look like they should be the same thing. In the input tag, the customer-list is used, and in the datalist, the resource-list is used. I've guessed that both of these should be resource-list, to link them correctly.
It looks like you are trying to get the datalist item that you clicked. In the code, as it is right now, you are removing the <input> tag as your candidate variable. If you would remove this, the whole input field would be gone, and the error is caused by this input field not being a child of the generic_list variable.
Now to solve this issue, you can use the document.querySelector() function to get the datalist item that was selected. The following change to your code would have the desired effect:
function addResource()
{
var new_team_member = document.getElementById ('dynamic-list');
var generic_list = document.getElementById ('resource-list');
var candidate = document.getElementById("candidate");
if (candidate.value =='')
{
alert('No data selected');
}
else
{
var div = document.createElement("div");
div.setAttribute('class','input-box');
var input = document.createElement("input");
input.setAttribute('type','text');
input.setAttribute('placeholder',candidate.value);
input.setAttribute('disabled','disabled');
div.appendChild(input);
new_team_member.appendChild(div);
// Get datalist item with selected candidate
datalist_item = document.querySelector('#resource-list option[value="'+CSS.escape(candidate.value)+'"]');
// Remove item from list
generic_list.removeChild(datalist_item);
document.getElementById('candidate').value = '';
}
}
This query selector allow you to use CSS like syntax to select elements. In the string '#resource-list option[value="'+CSS.escape(candidate.value)+'"]' it first finds the resource list, and then takes the option tag that has the candidate name as its value.
For security, I also use the CSS.escape() function that makes sure any name with special characters gets correctly escaped in this string.

List item can't be added using javascript

I checked all the code and there is nothing wrong with it. When I check the "vegetables" radio button, write something in the text field and hit add, it doesn't add the element.
function add() {
var item;
item = document.getElementById("item").value;
if (document.getElementById("1").checked) {
var li = document.createElement(li);
text = document.createTextNode(item);
li.appendChild(text);
document.getElementById("1v").appendChild(li);
}
}
<section>
<h1>Welcome to your shopping List!</h1>
<h2>Type in the item, choose its type, and hit add !!</h2>
<div id="blue">
<form action="">
<label for="task">I need :</label><br>
<input type="text" placeholder="Example : Apples" id="item" name="item"><br>
<br>
<label for="type">which is :</label><br>
<div class="">
<input type="radio" id="1" name="type" value="Vegetables">
<label for="">Vegetables</label><br>
</div>
<br>
<button id="add" onclick="add()">Add !</button>
</section>
</form>
</div>
<br>
<footer id="white">
<div>
<table border="bold">
<th>Vegetables</th>
<tbody>
<tr>
<td>
<ol id="1v"></ol>
</td>
</tr>
</tbody>
</table>
</div>
</footer>
You have several problems:
You are using a form, so when you click the button, the form
submits and you leave the page. In your case, you aren't really going to submit data anywhere, so you really don't even need the form element or to specify name attributes for your fields.
You don't have li in quotes, so you aren't actually creating an
<li> element. Without quotes, the system thinks li is a variable, but since you don't have a variable called that, a new Global variable is created with a value of undefined, so your code executes as: document.createElement("undefined"), which does actually create: <undefined></undefined>, but since that isn't an actual HTML element, nothing is rendered for it, except the text you placed inside it (but no numbering):
var li;
let el = document.createElement(li);
console.log(el);
You are using label incorrectly. A <label> element correlates to a form-field element (i.e. input, select, textarea) as a way to have a "caption" for that element. To use it, you should set its for attribute to the id of the form-field its associated with or you can not use for and just nest the form-field its associated with inside of the label. label is not just for text you want to display.
Your HTML is not nested properly and you are missing elements.
Tables should really not be used for anything but displaying tabular
data. They should not be used for layout. Since you are creating new
ordered list items for each item added, you should not use a table.
But, even when you do, you can't just have th. th must be inside
of tr, which would then be inside of thead.
A footer element is meant to provide "the fine print" content at the end of a section. Producing your list isn't that kind of content and shouldn't be in a footer.
Here's all of that put toghether:
// Get your DOM references just once
const item = document.getElementById("item");
const list = document.getElementById("1v");
const veg = document.getElementById("type");
// Don't use inline HTML event attributes to set up events.
// Do your event binding in JavaScript, not HTML.
document.getElementById("add").addEventListener("click", add);
function add() {
if (veg.checked) {
var li = document.createElement("li"); // <-- Need quotes around the element name
li.textContent = item.value;
list.appendChild(li);
}
}
table,th,td { border:1px solid black; }
<section>
<h1>Welcome to your shopping List!</h1>
<h2>Type in the item, choose its type, and hit add !!</h2>
<div id="blue">
I need : <input type="text" placeholder="Example : Apples" id="item"><br>
<br>
which is : <input type="checkbox" id="type" value="Vegetables"> Vegetables
<div><button id="add">Add !</button></div>
</div>
</section>
<br>
<footer id="white">
<div>
Vegetables
<ol id="1v"></ol>
</div>
</footer>
2 quick fixes to your code (personally, I would rewrite the whole thing):
add type="button" to the button. It will prevent the button from defaulting to a submit.
Syntax error in var li = document.createElement(li);. the li should be in quotes:
var li = document.createElement('li');

load HTML elements conditionally before DOM ready

I want to apply Access Control on web application. I have an array AllowedElementsArray which contains names of elements. I want to add only allowed elements into DOM before DOM ready.
//my array
var AllowedElementsArray = ['textbox','button','radioButton'];
// HTML elements
<body>
Name: <input type='text' class='textbox'/>
Task: <input type='text' />
Hola: <input type='checkbox' class='checkbox'/>
Hello: <input type='radio'/>
Foo: <input type='radio' class='radioButton'/>
Bar: <input type='button' class='button'/>
</body>
// after DOM is ready only these elements should be shown
Name: <input type='text' class='textbox'/>
Foo: <input type='radio' class='radioButton'/>
Bar: <input type='button' class='button'/>
or is there any other efficient way, because my HTML is dense, have too many elements.
If you are very particular about having access control then I would suggest you to generate the HTML from server side, Else if you want to do on client side then the client can manipulate no matter what.
Jquery Approach
Anyways doing this on client side can be done as suggested below.
Also here is a Working Sample
change your HTML to so its easy to remove the unwanted elements when its wrapped around a span
<div id="elements">
<span>Name:<input type='text' class='textbox' /></span>
<span>Task:<input type='text' /></span>
<span>Hola:<input type='checkbox' class='checkbox' /></span>
<span>Hello:<input type='radio' /></span>
<span>Foo:<input type='radio' class='radioButton' /></span>
<span>Bar:<input type='button' class='button' /></span>
</div>
And the below script, I have used $.inArray() to check if the elements class exists in the array.
var AllowedElementsArray = ['textbox', 'button', 'radioButton'];
$(function() {
$.each($('#elements input'), function() {
var $input = $(this);
var shouldBeRetained = $.inArray($input.attr('class'), AllowedElementsArray);
if (shouldBeRetained == -1) { // -1 is given when the class is not found in the array
$input.parent().remove();
}
});
$('body').show();
});
Also have this styles, So the idea is to initially hide the body untill we have removed the unwanted elements. One our scripts are done executing we can show the body
body{
display:none;
}
MVC Approach
Edit: Since you said you are using MVC, You can do this without Jquery, All you have to do is add if checks on all your input controls. One thing to be clear is what ever c# code you write in the .cshtml file is server side, That is the MVC framework executes all the code in the .cshtml file and the final result will be plain HTML,Javascript(if any), Css (if any) which is returned as a response to the browser. You will not see razor or a c# syntax in your view page in the browser. So as all the information out there in the internet mentions data is sent from controller to view, its not totally right.. Data is passed from controller to a method named View() which will fetch the respective .cshtml file and processes it and the end result is passed to the Browser (which is pure HTML and not .cshtml). So once you are clear with this your problem can be solves as below.
in your controller add the array of visible type into a Viewbag;
ViewBag.AllowedElements = ["textbox", "button", "radioButton"];
Now in your view at the top add this code block and assign the ViewBag data into a variable.
#{
var allowedElements = ViewBag.AllowedElements;
}
Now add a if check to all your input elements.
<div id="elements">
#if(allowedElements.Contains("textbox")){
<span>Name:<input type='text' class='textbox' /></span>
}
#if(allowedElements.Contains("text")){
<span>Task:<input type='text' /></span>
}
#if(allowedElements.Contains("checkbox")){
<span>Hola:<input type='checkbox' class='checkbox' /></span>
}
#if(allowedElements.Contains("text")){
<span>Hello:<input type='radio' /></span>
}
#if(allowedElements.Contains("radioButton")){
<span>Foo:<input type='radio' class='radioButton' /></span>
}
#if(allowedElements.Contains("button")){
<span>Bar:<input type='button' class='button' /></span>
}
</div>
This way only the elements that satisfies the if check is sent to the browser and is cleaner way than doing it in Jquery.
Hope this helps...
This should get you started.
But if you can do this server side though, it would be better. No point in sending HTML down to the client if it's not needed..
$(function () {
var cls = AllowedElementsArray.map(
function (r) { return '.' + r }).join(',');
$(cls).removeClass('hidden');
});
.hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>var AllowedElementsArray = ['textbox','button','radioButton'];</script>
<body>
<div class="hidden textbox">Name: <input type='text'/></div>
<div class="hidden">Task: <input type='text'/></div>
<div class="checkbox hidden">Hola: <input type='checkbox' class='checkbox hidden'/></div>
<div class="hidden radio">Hello: <input type='radio hidden'/></div>
<div class="hidden radioButton">Foo: <input type='radio'/></div>
<div class="hidden button">Bar: <input type='button'/></div>
</body>
We can just loop your array and check for elements that match the class. Then show/hide as appropriate. I have wrapped each element and its label in div elements so that the text and the element can be hidden or shown as a single unit. No JQuery necessary.
var AllowedElementsArray = ['textbox','button','radioButton'];
// Get node-list of all the input elements in the page:
var inputs = document.getElementsByTagName("input");
// Loop through the elements
for(var i = 0; i < inputs.length; ++i){
// Check to see if the input has a class matching the AllowedElementsArray
// If so, show it. Otherwise, hide it.
if(AllowedElementsArray.indexOf(inputs[i].getAttribute("class")) > -1){
inputs[i].parentElement.style.display = "block";
} else {
inputs[i].parentElement.style.display = "none";
}
};
<div>Name: <input type='text' class='textbox'/></div>
<div>Task: <input type='text' /></div>
<div>Hola: <input type='checkbox' class='checkbox'/></div>
<div>Hello: <input type='radio'/></div>
<div>Foo: <input type='radio' class='radioButton'/></div>
<div>Bar: <input type='button' class='button'/></div>

Clear a single form field in HTML

I am creating a simple HTML login page, but if I enter data into the fields it stays there when I refresh the page. I have tried
function pageInit(ID) {
this.browserbot.getCurrentWindow().document.getElementById(ID).value = '';
}
but this doesn't do anything (I placed it into onLoad on the inputs of the login.)
HTML:
`
<title>Login</title>
</head>
<body>
<form>
<fieldset>
<legend><h3>Please Login:</h3></legend>
<input type="text" placeholder="Username" name="userId" id="userId" onLoad="pageInit('userId');"><br>
<input type="password" placeholder="Password" name="passwd" id="passwd" onLoad="pageInit('passwd');"><br>
</fieldset>
</form>
</body>
CSS:
<style>
html {
font-family: sans-serif;
text-align: center;
}
a {
font-weight: normal;
}
a:hover {
font-weight: bold;
}
#userId, #passwd {
width: 30%;
height: 40px;
text-align: center;
}
</style>
JS:
<script>
function pageInit(ID) {
this.browserbot.getCurrentWindow().document.getElementById(ID).value = '';
}
</script>
As far as I can tell, the previous answers to not cover the full extent of the question. The original question requests a function to be called to clear the field. However, I'm going to address this in several different ways.
This can be achieved with no JavaScript at all, but simply setting the value attribute as below:
<input type="text" placeholder="Username" name="userId" id="userId" value="" />
<input type="password" placeholder="Password" name="passwd" id="passwd" value="" />
The above will ensure that the fields are clear when the page is loaded, but using only HTML. To do this via JavaScript, multiple things have to be taken into consideration. First, a function should be defined, which needs to be called when the page is loaded.
function clearValue(id) {
document.getElementById(id).value = "";
}
This will simply set the value to blank. However, this gets us back to the original issue. Setting onload for each element does not work, instead we must use window.onload.
window.onload = function() {
clearValue("userID");
clearValue("passwd");
}
This will clear each value one-by-one. However, there is an even better way to do this. JavaScript has built-in functions that make it easy to clear the entire form, or access the elements of the form by their name, even if they are the child of another element within the form. However, keep in mind that only valid input (includes textarea, etc...) fields can be accessed in this way.
So, assuming that the form's ID is myform, this would clear the entire form, no matter how many fields:
document.getElementById("myform").reset();
It's that simple. Using the form element, you can also access the fields by name, as mentioned above.
var f = document.getElementById("myform").elements;
f["userId"].value = "";
f["passwd"].value = "";
Using the above code makes it much quicker, especially if you have more fields.
Putting the JS together, it might look like this:
window.onload = function() {
// using function
clearValue("userID");
clearValue("passwd");
// or, reset entire form
document.getElementById("myform").reset();
// or, clear each field one-by-one
var f = document.getElementById("myform").elements;
f["userId"].value = "";
f["passwd"].value = "";
}
May be it will help you.
<input type="text" value="initial" id="field">
<button id="reset">reset</button>
<script type="text/javascript">
document.getElementById('reset').onclick= function() {
var field= document.getElementById('field');
field.value= field.defaultValue;
};
</script>
Set the input value to " " - in other words, nothing.
This way, the value will be cleared when the page loads.
Implment this like so:
<input value="">
If you'd rather use JS, add this to your onload event:
window.onload = myOnloadFunc;
function myOnloadFunc() {
document.getElementById('userId').value = ''
}

Get the text within children nodes using jquery

I have the following html page structure:
<div class="result-row clearfix">
<span>Name1</span>
<span>city1</span>
<span>phone1</span>
<span>details1</span>
</div>
<div class="result-row clearfix">
<span>Name2</span>
<span>city2</span>
<span>phone2</span>
<span>details2</span>
</div>
...
... many such similar divs
And I got simple input field from the user
<label for="name">Name</label> <br />
<input type="text" name="name" autocomplete="off" /> <br />
<label for="city">City</label> <br />
<input type="text" name="city" autocomplete="off" /> <br />
On it's blur event, I would like to make invisible all such div's that does not have the text to be searched and just show the div's that has matched (i.e. the div that has the text within the span tag).
I am not able to retrieve and match this using jquery. I have tried the following:
var nodes = $(".result-row");
console.log("Nodes length: "+nodes.length); // Displays the correct number of child nodes
for(var i=0;i < nodes.length; i++) {
var cur = nodes[i];
console.log(cur); // Displays '#text' in browser js console log.
console.log(cur.childNodes[0]); // Gives undefined. Expecting to get the 1st span tag here.
}
EDIT
I need to display the rows that has the span with matching text. Have updated the html little bit, Please refer to the updated question.
I am able to get the complete data as text of all the span's combined. Is there any way to get the array of spans inside the particular div?
You can use :contains selector:
var $row = $('.result-row');
$('input[type=text]').blur(function() {
var val = this.value;
$row.hide();
$row.has('span:contains("'+val+'")').show()
})
http://jsfiddle.net/x3VtX/
nodes[i] is a jquery object, which doesn't have childNodes property i guess.. so you should be using nodes[i].get(0).childNodes instead...

Categories