load HTML elements conditionally before DOM ready - javascript

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>

Related

How to use checked input values used for math as part of cloned div elements

I have written a script that clones a certain div as required by the user. Within the div there are three checkbox input options and each option as a numeric value. I want the script to allow the user to select a checkbox and then the value will be reflected in another input space and each value that are added will be separated by a comma.
The tricky part is that it should be done for each clone, and that each checkbox has the same class name to which the script should be written. I realize that using unique id's would be better, but I would like it that a for loop could do it for any number of checkboxes under the specific class.
Here is the html script:
<style>
.hidden {
display: none;
}
</style>
<body>
<h2>Test</h2>
<button id="add">Add</button>
<div class="test hidden">
<div class="user_input1">
<label>Input1</label>
<input class="input1" type="text" required>
<label>Input2</label>
<input type="text" name="value2" required>
<div class="user_input2">
<table>
<thead>
<tr>
<th>Pick Option</th>
</tr>
</thead>
<tbody>
<tr id="append">
<td><input class="test" type="checkbox" name="test" value="1">Test1</td>
<td><input class="test" type="checkbox" name="test" value="2">Test2</td>
<td><input class="test" type="checkbox" name="test" value="3">Test3</td>
</tr>
</tbody>
</table>
<input type="text" id="insert" name="check">
<button class="hidden" id="testbtn">Calc</button>
</div>
</div>
</div>
<form action="server/server.php" method="POST">
<div class="paste">
</div>
<button type="submit" name="insert_res">Submit</button>
</form>
</body>
And my attempt for the jQuery:
$(document).ready(function() {
var variable = 0
$("#add").click(function() {
var element = $(".test.hidden").clone(true);
element.removeClass("hidden").appendTo(".paste:last");
});
});
$(document).ready(function(event) {
$(".test").keyup(function(){
if ($(".test").is(":checked")) {
var test = $(".test").val();
};
$("#insert").val(test);
});
$("#testbtn").click(function() {
$(".test").keyup();
});
});
I think a for loop should be used for each checkbox element and this to specify each individual clone, but I have no idea where or how to do this. Please help!
I am assuming you already know how to get a reference to the dom element you need in order to append, as well as how to create elements and append them.
You are right in that you can loop over your dataset and produce dom elements with unique id's so you can later refer to them when transferring new values into your input.
...forEach((obj, index) => {
(produce tr dom element here)
(produce three inputs, give all unique-identifier)
oneOfThreeInputs.setAttribute('unique-identifier', index); // can set to whatever you want, really
(proceed to creating your inputs and appending them to the tr dom element)
targetInputDomElementChild.setAttribute('id', `unique-input-${index}`); // same here, doesn't have to be class
});
Observe that I am using template strings to concat the index number value to the rest of the strings. From then on, you can either reference the index to refer to the correct input or tr using jquery in your keyUp event handler:
function keyUpEventHandler($event) {
const index = $(this).attr('unique-identifier');
const targetInput = $(`#unique-input-${index}`)
// do stuff with targetInput
}
I have created a fiddle to show you the route you can take using the above information:
http://jsfiddle.net/zApv4/48/
Notice that when you click an checkbox, in the console you will see the variable number that designates that set of checkboxes. You can use that specific number to get the input you need to add to and concat the values.
Of course, you still need to validate whether it is being checked or unchecked to you can remove from the input.

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

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>

Javascript Dynamic Form Field

I am having difficulty with a javascript that I need some help with. I have a form which sends to a php the exact amount of inputs to be filled, now I want to create a preview using jQuery/javascript but how can I catch all the fields dynamically.
Here is a portion of my form for reference:
<td>
<div class="input-group">
<span class="input-group-addon">
<i class="fa fa-pencil"></i></span>
<input class="form-control" id="task" type="text" name="task" placeholder="Task Title">
</div>
</td>
<td>
<div class="input-group">
<span class="input-group-addon">
<i class="fa fa-pencil"></i>
</span>
<input class="form-control" id="description" type="text" name="description" placeholder="Task Description">
</div>
</td>
So, I added in PHP the name field + the number, this way I can get different names ie: task1, task2,...etc.
Now what I need to do is get the values using jQuery/javascript.
My thoughts so far is to declare the var (variable) inside a for() (loop)
var task = $('input[name=task]').val();
How can I get all values task1, task2. No one knows how many task fields the user will submit so I need to get the number of fields
Any help direction so I can figure this out
First of all, you don't need to give your input fields names like task1, task2, etc to distinguish among them on the server-side i.e on the PHP. You just need to give all of them a name attribute value like tasks[] And notice the brackets [] so you may have something like the following:
<input class="form-control" id="tasks[]" type="text" name="tasks[]" placeholder="Task Title">
...
<input class="form-control" id="tasks[]" type="text" name="tasks[]" placeholder="Task Title">
Like that automatically values in those fields will be posted as an array to the PHP and it is going to be received like the following in PHP script:
$tasks = $_POST['tasks'];
foreach ($tasks as $task){
echo $task;
}
Second By this way you will easily able to collect your inputs data using Javascript inorder to generate the preview by using getElementsByName method as follows:
function preview(){
output = "";
tasks = document.getElementsByName('tasks[]');
for (i=0; i < tasks.length; i++){
output += "<b>Title</b>: "+tasks[i].value+"<hr />";
}
panel = document.getElementById('panel');
panel.innerHTML = output;
}
Of course you can expand this solution to any number of fields in your form such as descriptions[].
A javascript DEMO: http://jsbin.com/kiyisi/1/
Using the Attribute Starts With Selector [name^="value"] and jQuery.each()
var tasks = $('input[name^=task]').val();
$.each(tasks,function(index, value){
//do something with the value
alert($(this).val());
});
edit
var tasks = $('input[name^=task]');
$.each(tasks,function(index, value){
//do something with the value
$('#Preview').append($(this).val());
});
Q: now I want to create a preview using jquery/javascript but how can I catch all the fields dinamically:
If you give them a class, you can get all fields with each:
$(".className").each(function() {
do something
Next, "catch" all fields... I'm assuming you may want the values of these fields too? Check this example for details, here is a snippet which loads the key:value pairs (form field name : value of field) into a map:
var map = {};
$(".activeInput").each(function() {
map[$(this).attr("name")] = $(this).val();
});
Print all values inside div (Here, I'm assuming you're talking about children values of div):
<div>
<span>Hi</span>
<span>Hello</span>
<span>Hi again</span>
</div>
$("div").children().each(function () {
console.log($(this).text());
});
OR
$("div span").each(function () {
console.log($(this).text());
});

jQuery autocomplete for innerHTML generated textbox

I realize similar questions have been asked thousands times and yet it doesn't seem to work for me. I have a textbox called "movieTitle", it is generated via Javascript by clicking a button. And I'm calling jQueryUI autocomplete on that textbox just like in the official example http://jqueryui.com/autocomplete/#remote.
It works well if I hardcode "movieTitle" in the original page; however it just fails when I create "movieTitle" by changing the innerHTML of the div "formsArea". searchMovies.php is the same with search.php from the example. I had tried many answers from internet and from here. I learned that I would have to use .on() to bind the dynamic element "movieTitle". Still it doesn't seem to work. Even the alert("hahaha") works. Thanks for your time. :) Here's my script:
$(function()
{
$(document).on('focus', '#movieTitle', function(){
//alert("hahaha");
$("#movieTitle").autocomplete({
source: "../searchMovies.php",
minLength: 2
});
}
);
window.onload = main;
function main()
{
document.getElementById("movieQuery").onclick = function(){showForms(this.value);};
document.getElementById("oscarQuery").onclick = function(){showForms(this.value);};
// displays query forms based on user choice of radio buttons
function showForms(str)
{
var heredoc = "";
if (str === "movie")
{
heredoc = '\
<h1>Movie Query</h1>\
<form action="processQuery.php" method="get">\
<div class="ui-widget">\
<label for="movieTitle"><strong>Name: </strong></label>\
<input type="text" id="movieTitle" name="movieTitle" />\
<input type="submit" name="submitMovie" value="Submit" />\
</div>\
</form>';
//document.getElementById("formsArea").innerHTML = heredoc;
//$("#formsArea").append(heredoc);
$("#formsArea").html(heredoc);
}
else if (str === "oscar")
{
heredoc = '\
<h1>Oscar Query</h1>\
<form action="processQuery.php" method="get">\
<strong>Name: </strong>\
<input type="text" name="oscarTitle" />\
<input type="submit" name="submitOscar" value="Submit"/>\
</form>';
document.getElementById("formsArea").innerHTML = heredoc;
}
}
}
});
The HTML is:
<form action=$scriptName method="get">
<label for="movieQuery"><input type="radio" name="query" id="movieQuery" value="movie" />Movie Query</label>
<label for="oscarQuery"><input type="radio" name="query" id="oscarQuery" value="oscar" />Oscar Query</label>
</form>
<div id="formsArea">
<b>Please choose a query.</b>
</div>
You should check for the URL you're sending an AJAX request to. The paths in script files are relative to the page they're being displayed in. So albeit your script is in /web/scripts/javascripts/js.js, when this file is included in /web/scripts/page.php, the path to /web/scripts/searchMovies.php should be searchMovies.php instead of ../searchMovies.php because your script is being used in /web/scripts/.
Good ways to avoid such confusion is to
a. use absolute URL
b. the URL that're relative to root of your domain (that start with a /),
c. or define your domain's path in a variable, var domain_path = 'http://www.mysite.com/' and use it in your scripts.
I hope it clarifies things :)
Relative Paths in Javascript in an external file

Creating and Removing Information with jQuery

I'm working on a tagging system and I want users to be able to add and remove tags on the page. for each one thats added I am displaying a small div with the tag and an x to remove the tag. I have the adding functionality working, but I'm not sure how to go about making it so I can remove them. I also have a hidden input which should hold all the values so that when the information is submitted I can use it.
Heres my attempt that doesn't work:
function tagsremove(tag) {
$('#hiddentags').val().replace('/'+tag+'\,\s/', '');
$("#tagdiv-"+tag.replace(" ","_")).fadeOut('normal', function(){
$(this).remove();
});
}
$(document).ready(function(){
$('#tagbutton').click(function(){
var tags = $('#tagsbox').val().split(", ");
for (var i in tags) {
$('#hiddentags').val($('#hiddentags').val() + tags[i] +", ");
$('#curtags').append("<div class='tag'>" + tags[i] + " <a href='#' id='#tagdiv-"+tags[i].replace(" ", "_")+"' onclick='tagsremove(\""+tags[i]+"\");' >x</a></div>");
}
$('#tagsbox').val('');
});
});
heres the html to go with it:
<div class='statbox'>
<form method='post' action='post.php' id='writeform'>
<p class='subtitle'>Title</p>
<input type='text' name='title' id='titlebox' /><br />
<p class='subtitle'>Body</p>
<textarea id='postbox' name='body' rows='10'></textarea><br />
<p class='subtitle'>Tags</p>
<input type='text' id='tagsbox' /><input type='button' id='tagbutton' value='Add' />
<p class='subsubtitle'>Seperate by commas (eg. "programming, work, job")</p>
<div class='subsubtitle' id='curtags'>Current Tags:</div>
<input type='hidden' value='' name='tags' id='hiddentags' />
</form>
</div>
Make each of your tag divs have a relevant ID. For, say, the "play pen balls" tag, your ID could be "tagdiv-play_pen_balls". Now you can just do
function removeTag(tag) {
$("#tagdiv-"+tag.replace(" ","_")).remove();
}
to remove the visible div.
(I'm not sure if that's what you were asking for, though...)
Instead of using .val('') you should be using .html('');
http://docs.jquery.com/Manipulation

Categories