I have a form with an upload field that allows users to select multiple files. However, I need to be able to allow the user to select file 1 from folder 1, then go and select file 2 from folder 2, and so on.
Currently, when the user selects file 1 from folder 1 then hits "Open", the selection window closes (leaving the user on my form). Then if the user goes and select file 2 from folder 2 and hits the "Open" button, file 1 is removed, leaving only file 2.
Basically, the user is unable to select multiple files unless they're all in the same location. Is there a way to make file 1 stay selected after file 2 is chosen?
How about this?
The solution uses HTML, jQuery/Javascript, and PHP (for server-side handling of this data). The idea is: 1.) HTML Form: Includes one "browse" button that allows the user to select multiple files (within one directory). 2.) jQuery: The option to create a new button in the form that allows users to select multiple files (within a different directory -- or even the same one actually!), with the ability to create new buttons "infinitely". 3.) PHP: As a bonus, I put some thought into packaging the data nicely for server-side handling.
Here is what the HTML form could look like (I used a found-icon for the clickable object, but you can easily replace it with a graphic of your choosing).
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>" enctype='multipart/form-data'>
Select files: <br/>
<input type='file' name='files0[]' id="files0" multiple><br/><br/><br/>
<span style="font-size: 10pt;">Click "+" for more files
<i id="more_files" class="general foundicon-plus" style="color: blue;cursor: pointer;"></i></span>
<br/><br/><br/>
<input type="submit" name="submit" value="Submit">
</form>
Here is the jQuery/Javascript to create a new "browse" button once the event is triggered (this even places it after the LAST "browse" button!):
<script type="text/javascript">
//jQuery
$(document).ready(function() {
$(document).on('click','#more_files', function() {
var numOfInputs = 1;
while($('#files'+numOfInputs).length) { numOfInputs++; }//once this loop breaks, numOfInputs is greater than the # of browse buttons
$("<input type='file' multiple/>")
.attr("id", "files"+numOfInputs)
.attr("name", "files"+numOfInputs+"[]")
.insertAfter("#files"+(numOfInputs-1));
$("<br/>").insertBefore("#files"+numOfInputs);
});
});
</script>
<script>
//vanilla javascript version
var location = document.getElementById("fileBrowsers");
var br = document.createElement("BR");
location.appendChild(br);
var input = document.createElement("input");
input.type = "file";
input.name = "files"+numOfInputs+"[]";
input.id = "files"+numOfInputs;
input.multiple = true;
location.appendChild(input);
</script>
Finally, and possibly most important, how to wrap up the data on the server in a familiar format:
<?php
if(isset($_POST['submit']) && !empty($_FILES)) {
$files = array();
$files = $_FILES['files0'];
//var_dump($files);//this array will match the structure of $_FILES['browser']
//Iterate through each browser button
$browserIterator = 1;
while(isset($_FILES['files'.$browserIterator])) {
//Files have same attribute structure, so grab each attribute and append data for each attribute from each file
foreach($_FILES['files'.$browserIterator] as $attr => $values) {//get each attribute
foreach($_FILES['files'.$browserIterator][$attr] as $fileValue) {//get each value from attribute
$files[$attr][] = $fileValue;//append value
}
}
$browserIterator++;
}
//Use $files like you would use $_FILES['browser'] -- It is as though all files came from one browser button!
$fileIterator = 0;
while($fileIterator < count($files['name'])) {
echo $files['name'][$fileIterator]."<br/>";
$fileIterator++;
}
}
?>
Update Note: jQuery script and vanilla Javascript accomplish the same goal. I ran into an issue that required the vanilla version. You only need one of them.
No, you can't. This is a behaviour defined by the operating systems and may vary between them. You can't control these things precisly and you will always fear what happen.
If the amount of folders people have to choose is quite small you could offer multiple upload fields.
Another solution is using old school (non-multiple) file inputs. In this case you cannot select multiple files to upload, but you can remove any file and add another. Initially there is only one file input on page, but when you select a file, it hiding and replacing by filename with delete button, and new file input appears.
var fileInput = document.getElementById('fileInput_0');
var filesList = document.getElementById('fileList');
var idBase = "fileInput_";
var idCount = 0;
var inputFileOnChange = function() {
var existingLabel = this.parentNode.getElementsByTagName("LABEL")[0];
var isLastInput = existingLabel.childNodes.length<=1;
if(!this.files[0]) {
if(!isLastInput) {
this.parentNode.parentNode.removeChild(this.parentNode);
}
return;
}
var filename = this.files[0].name;
var deleteButton = document.createElement('span');
deleteButton.innerHTML = '×';
deleteButton.onclick = function(e) {
this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);
}
var filenameCont = document.createElement('span');
filenameCont.innerHTML = filename;
existingLabel.innerHTML = "";
existingLabel.appendChild(filenameCont);
existingLabel.appendChild(deleteButton);
if(isLastInput) {
var newFileInput=document.createElement('input');
newFileInput.type="file";
newFileInput.name="file[]";
newFileInput.id=idBase + (++idCount);
newFileInput.onchange=inputFileOnChange;
var newLabel=document.createElement('label');
newLabel.htmlFor = newFileInput.id;
newLabel.innerHTML = '+';
var newDiv=document.createElement('div');
newDiv.appendChild(newFileInput);
newDiv.appendChild(newLabel);
filesList.appendChild(newDiv);
}
}
fileInput.onchange=inputFileOnChange;
#fileList > div > label > span:last-child {
color: red;
display: inline-block;
margin-left: 7px;
cursor: pointer;
}
#fileList input[type=file] {
display: none;
}
#fileList > div:last-child > label {
display: inline-block;
width: 23px;
height: 23px;
font: 16px/22px Tahoma;
color: orange;
text-align: center;
border: 2px solid orange;
border-radius: 50%;
}
<form enctype="multipart/form-data" method="post">
<div id="fileList">
<div>
<input id="fileInput_0" type="file" name="file[]" />
<label for="fileInput_0">+</label>
</div>
</div>
</form>
document.querySelector("input").addEventListener("change", list_files);
function list_files() {
var files = this.files;
for (var i = 0; i < files.length; i++) {
console.log(files[i].name);
}
}
<input type="file" multiple>
Related
I would like to have two buttons which are basically categories. Let's name them category A and category B. The are displayed left and right. Below i would like to display some text which is dependent of the chosen category (i.e the clicked button) so that category A shows text A and category B shows text B.
This if for html. I'm working on a wordpress homepage.
I was able to install one button which toggles text (basically button 1 = Category A). But i couldn't manage to insert a second button (basically button 2 = Category B). Any ideas? Highly appreciated!
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>Click the button to swap the text of the DIV element:</p>
<p><button onclick="myFunction()">Click Me</button></p>
<div id="myDIV">Hello</div>
<script>
function myFunction() {
var x = document.getElementById("myDIV");
if (x.innerHTML === "Hello") {
x.innerHTML = "Swapped text!";
} else {
x.innerHTML = "Hello";
}
}
</script>
</body>
</html>
I expect to have 2 buttons which display 2 categories, the text should toggle according to which button has been clicked.
Could put the description in an attribute, then get the attributes value on click and change the html of the description. Here is a jsFiddle
<div>
<button class="js-button default-button" data-description="Category A's Description" onclick="myFunction(this)">
Category A
</button>
<button class="js-button default-button" data-description="Category B's Description" onclick="myFunction(this)">
Category B
</button>
</div>
<div id="js-description" class="description">
</div>
<script>
function myFunction(elem) {
var x = document.getElementById("js-description");
var description = elem.getAttribute('data-description');
x.innerHTML = description;
var button = document.getElementsByClassName('js-button');
for (var i = 0; i < button.length; i++) {
button[i].classList.remove('active-button');
}
elem.classList.add('active-button');
}
</script>
<style>
.default-button{
font-size:16px;
border-radius: 4px;
padding:7px 12px;
}
.active-button{
background:blue;
color:#fff;
}
.description{
margin-top:20px;
}
</style>
I don't really like all these solutions because everything is written from JS but contents probably come from database. So here is my solution :
// Native JS version
// Working Fiddle : https://jsfiddle.net/d34cbtw7/
var togglers = document.querySelectorAll('[data-toggle="tab"]');
for (var i = 0; i < togglers.length; i++) {
togglers[i].addEventListener('click', function() {
var tabs = document.querySelectorAll('.tab');
for(var j = 0; j < tabs.length; j++) {
tabs[j].classList.remove('active');
}
var $target = document.querySelector(this.getAttribute('data-target'));
$target.classList.add('active');
});
}
// jQuery version
$('body').on('click', '[data-toggle="tab"]', function(e) {
e.preventDefault();
// Select our target
var $target = $($(this).data('target'));
// Hide all tabs
$('.tab-contents .tab').removeClass('active');
// Show only $target tab
$target.addClass('active');
});
.tab-contents .tab {
display: none;
}
.tab-contents .tab.active {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button data-toggle="tab" data-target="#cat-A-content">
Cat A
</button>
<button data-toggle="tab" data-target="#cat-B-content">
Cat B
</button>
<div class="tab-contents">
<div class="tab active" id="cat-A-content">
My category A contents
</div>
<div class="tab" id="cat-B-content">
My category B contents
</div>
</div>
I also don't really like "onclick" attribute in HTML...
I've made a quick codepen as example.
You can achieve this by passing a parameter to the onClick function. In this example I keep track of the last button clicked, and the text it should render. If the last button clicked was the same button, the switched back to default. I hope this helps.
https://codepen.io/maffekill/pen/rbpjzw
HTML
<p>Click the button to swap the text of the DIV element:</p>
<p><button onclick="myFunction(1, 'TEXT A')">TEXT A</button></p>
<p><button onclick="myFunction(2, 'TEXT B')">TEXT B</button></p>
<div id="myDIV">Default Text</div>
JS
// Keep track of the button currently clicked
var activeBtn = null;
function myFunction(btnId, text) {
var x = document.getElementById("myDIV");
// If the last button is the same as the new one, show default text
if (activeBtn === btnId) {
x.innerHTML = "Default Text";
activeBtn = null
} else {
// Else show the text given to the text param
x.innerHTML = text;
activeBtn = btnId;
}
}
There are multiple ways to achieve this, but the easiest way I could come up with to explain this to you would be as following:
function myFunction(myEle) {
var x = document.getElementById("myDIV");
x.innerHTML = "This is category " + myEle.value;
}
<p>Click the button to swap the text of the DIV element:</p>
<p>
<button onclick="myFunction(this)" value="a">
Category A
</button>
<button onclick="myFunction(this)" value="b">
Category B
</button>
</p>
<div id="myDIV">Hello</div>
JSFiddle
No need to overcomplicate things.
Firstly you would like to send the clicked element from the caller (which in this case would be the clicked element as well, the <button> element). You could use JavaScript's thisfor this purpose.
Within your function you can name a parameter between parenthesis, so in my example above: function myFunction() contains a parameter called myEle so it will look like: function myFunction(myEle). Once the function will be triggered, the parameter called myEle will be set to the clicked element (or
JavaScript's this). You can simply access any of its attributes like value by using a dot: myEle.value.
Knowing the above, you could apply it to whatever you require your function to do (refer to my example code above).
I have the following list of divs
<div id="multi-picker">
<div id="opt1">
<input type="checkbox"> Option 1
</div>
<div id="opt2">
<input type="checkbox"> Option 2
</div>
etc...
</div>
All working, but I'm not happy with the keyboard navigation. To navigate from opt1 to opt2 I need to press the tab key. Ideally I want to treat the options as a select and navigate with up/down arrow. Can this be done?
Alternatively...
Is there any way to have a multi-select with the options styled with checkboxes to reflect the selection state of each option?
I think you'll need javascript and using a plugin is an easier way to accomplish the task and maintain cross-browser functionality. However, here is a fiddle that, I think, kind of does what you want using just javascript. It defines additional attributes on your select elements and uses an onkeydown function to handle the navigation between the elements.
function keyPressed(e) {
var srcElement = e.target; // get the element that fired the onkeydown function
var dataset = false;
var selectList = false;
var next = "";
var prev = "";
if (srcElement.dataset) { // can we use HTML5 dataset?
dataset = true; // remember for later
// is this an element for which we care
if (srcElement.dataset.selectlist == 'true') {
selectList = true;
}
} else { // can't use HTML5 dataset, use getAttribute
if (srcElement.getAttribute('data-selectlist') == 'true') {
selectList = true;
}
}
// is it a select element and the user pressed either up arrow or down arrow
if (selectList && (e.keyCode == '38' || e.keyCode == '40')) {
// get the next and prev navigation options for this element
if (dataset) {
next = srcElement.dataset.next;
prev = srcElement.dataset.prev;
} else {
next = srcElement.getAttribute('data-next');
prev = srcElement.getAttribute('data-prev');
}
// up arrow was pressed and a prev element is defined
if (e.keyCode == '38' && prev != '') {
document.getElementById(prev).focus();
}
// down arrow was pressed and a next element is defined
if (e.keyCode == '40' && next != '') {
document.getElementById(next).focus();
}
// don't do native processing of the up or down arrow (page scrolling)
e.preventDefault;
}
}
document.onkeydown = keyPressed;
Here is the new html that contains the additional elements:
<div id="multi-picker">
<div id="opt1">
<input id="select1" type="checkbox" data-selectlist="true" data-prev="" data-next="select2"> Option 1
</div>
<div id="opt2">
<input id="select2" type="checkbox" data-selectlist="true" data-prev="select1" data-next=""> Option 2
</div>
</div>
This code is very specific to the problem presented and, though it may solve the problem, it would probably be better to use a general purpose plugin that would allow for more general application across your environment. You may also run into problems related to what your user expects the down and up arrow keys to do versus what you are doing by intercepting them.
In my experience I've run into problems where different browsers and even different end-user platforms present different behavior to the application making implementation consistency spotty. Many of the plugins are designed to eliminate that inconsistency and provide a cleaner, more intuitive interface.
Alternatively... Is there any way to have a multi-select with the options styled with checkboxes to reflect the selection state of each option?
That has multi-browser support? Not really. However, if you're a "It works in Chrome, it ships!" type dev, then you could totally fake a multi select to appear to have checkboxes that reflect the selection state of each option with good ol' CSS.
First our HTML:
<select multiple="multiple">
<option>Hello</option>
<option>World</option>
<option>Hello</option>
<option>World</option>
</select>
Next, dat CSS:
select {
border: none;
}
select:focus {
outline: none;
}
select option:before {
display: inline-block;
content: '';
width: 13px;
height: 13px;
position: relative;
margin-right: 3px;
background-image: url('http://i.imgur.com/5xszy3H.png');
background-position: -40px 0px;
top: 2px;
}
Using generated content, we've now applied our pseudo checkboxes. Let's add that last bit of CSS to give us a proper selected state!
select option:checked:before {
background-position: -40px -40px;
}
Woop.
Here's a fiddle to play around with: http://jsfiddle.net/9tLz6ugz/
In (limited) testing, this seemed to only work in Chrome and FireFox (both latest on OSX). Safari, IE, and Opera ignored the generated content all together. So, while not practical (at least not today), it's somewhat doable!
(Here's another fiddle without the background-image - requires a bit more work to get the look/feel consistent across browsers: http://jsfiddle.net/wpch98tg/ But does demonstrate use of unicode to fake a "checkbox" in a multi-select...)
I don't believe you'll find a way with plain HTML & CSS - this gets too far into customizing the core functionality so a bit of JavaScript should do the trick (I'm also using jQuery to make it slightly easier).
For my test, I used <label> instead of <div> to wrap the checkboxes, but this same idea holds true for divs. I just prefer labels so if JavaScript doesn't load, the checkboxes are still clickable.
<div class="fake-select">
<label for="fs1"><input type="checkbox" id="fs1" name="fs1" />Fake 1</label>
<label for="fs2"><input type="checkbox" id="fs2" name="fs2" />Fake 2</label>
[ ... ]
</div>
Basically, you need to track the user's keypresses and an "active" input. Look for up/down arrow key presses and change the active input based on that (scroll to it, add a class name for styling). I have it also allowing the space bar to check/uncheck the currently active box.
var fs = $(".fake-select"),
items = fs.find('input'),
divs = fs.find('label'),
active = 0;
// Hook keypresses
fs.keydown( function(e){
reCalculate(e);
rePosition();
return false;
});
// Click event for manual changes
items.unbind('click').click(function(e){
var thisInput = $(this),
thisLabel = $(this).parent();
window.active = thisLabel.index();
thisLabel.removeClass("checked");
if (thisInput.is(":checked"))
thisLabel.addClass("checked");
rePosition();
});
// Set new active element based on keypress
// Trigger click event if user hits space bar
function reCalculate(e){
var max = items.length -1,
cur = window.active,
charCode = (typeof e.which == "number" && e.which) ? e.which : e.keyCode;
if (charCode == 38) { // move up
cur--;
cur = (cur <= 0) ? 0 : cur;
}
if (charCode == 40) { // move down
cur++;
cur = (cur >= max) ? max : cur;
}
if (charCode == 32) { // space bar
items.eq(cur).focus().trigger('click');
}
window.active = cur;
}
// Add active class, call scroll function
function rePosition(){
divs.removeClass('active').eq(window.active).addClass('active');
scrollInView();
}
// Scroll the list so the active element is in view
function scrollInView(){
var target = divs.eq(window.active);
if (target.length) {
var top = fs.scrollTop() + target.position().top - fs.height()/2 + target.height()/2
fs.stop().animate({scrollTop: top}, 400);
}
return false;
}
jsFiddle example: http://jsfiddle.net/daCrosby/kqecngv0/13/
Can you use jQuery? This will activate the focus functionality via up/down arrow
function focusOnCheckboxes(locator){
var checkboxes = jQuery(locator).find(':checkbox');
var index = 0;
jQuery(locator).on('keydown', function(e){
if( e.keyCode == 38 ){
if(index > 0){
index = index - 1;
}
checkboxes[index].focus();
}
else if(e.keyCode == 40){
if(index < checkboxes.length - 1){
index = index + 1;
}
else{
index = checkboxes.length - 1;
}
checkboxes[index].focus();
}
else{
//console.log(e.keyCode);
}
});
}
// set the locator
focusOnCheckboxes('body');
I have tried following code for make the required field to notify the required field but its not working in safari browser.
Code:
<form action="" method="POST">
<input required />Your name:
<br />
<input type="submit" />
</form>
Above the code work in firefox. http://jsfiddle.net/X8UXQ/179/
Can you let me know the javascript code or any workarround? am new in javascript
Thanks
Safari, up to version 10.1 from Mar 26, 2017, doesn't support this attribute, you need to use JavaScript.
This page contains a hacky solution, that should add the desired functionality: http://www.html5rocks.com/en/tutorials/forms/constraintvalidation/#toc-safari
HTML:
<form action="" method="post" id="formID">
<label>Your name: <input required></label><br>
<label>Your age: <input required></label><br>
<input type="submit">
</form>
JavaScript:
var form = document.getElementById('formID'); // form has to have ID: <form id="formID">
form.noValidate = true;
form.addEventListener('submit', function(event) { // listen for form submitting
if (!event.target.checkValidity()) {
event.preventDefault(); // dismiss the default functionality
alert('Please, fill the form'); // error message
}
}, false);
You can replace the alert with some kind of less ugly warning, like show a DIV with error message:
document.getElementById('errorMessageDiv').classList.remove("hidden");
and in CSS:
.hidden {
display: none;
}
and in HTML:
<div id="errorMessageDiv" class="hidden">Please, fill the form.</div>
The only drawback to this approach is it doesn't handle the exact input that needs to be filled. It would require a loop accross all inputs in the form and checking the value (and better, check for "required" attribute presence).
The loop may look like this:
var elems = form.querySelectorAll("input,textarea,select");
for (var i = 0; i < elems.length; i++) {
if (elems[i].required && elems[i].value.length === 0) {
alert('Please, fill the form'); // error message
break; // show error message only once
}
}
If you go with jQuery then below code is much better. Just put this code bottom of the jquery.min.js file and it works for each and every form.
Just put this code on your common .js file and embed after this file jquery.js or jquery.min.js
$("form").submit(function(e) {
var ref = $(this).find("[required]");
$(ref).each(function(){
if ( $(this).val() == '' )
{
alert("Required field should not be blank.");
$(this).focus();
e.preventDefault();
return false;
}
}); return true;
});
This code work with those browser which does not support required (html5) attribute
Have a nice coding day friends.
I had the same problem with Safari and I can only beg you all to take a look at Webshim!
I found the solutions for this question and for this one very very useful, but if you want to "simulate" the native HTML5 input validation for Safari, Webshim saves you a lot of time.
Webshim delivers some "upgrades" for Safari and helps it to handle things like the HMTL5 datepicker or the form validation. It's not just easy to implement but also looks good enough to just use it right away.
Also useful answer on SO for initial set up for webshim here! Copy of the linked post:
At this time, Safari doesn't support the "required" input attribute. http://caniuse.com/#search=required
To use the 'required' attribute on Safari, You can use 'webshim'
1 - Download webshim
2 - Put this code :
<head>
<script src="js/jquery.js"></script>
<script src="js-webshim/minified/polyfiller.js"></script>
<script>
webshim.activeLang('en');
webshims.polyfill('forms');
webshims.cfg.no$Switch = true;
</script>
</head>
I have built a solution on top of #Roni 's one.
It seems Webshim is deprecating as it won't be compatible with jquery 3.0.
It is important to understand that Safari does validate the required attribute. The difference is what it does with it. Instead of blocking the submission and show up an error message tooltip next to the input, it simply let the form flow continues.
That being said, the checkValidity() is implemented in Safari and does returns us false if a required filed is not fulfilled.
So, in order to "fix it" and also show an error message with minimal intervention (no extra Div's for holding error messages) and no extra library (except jQuery, but I am sure it can be done in plain javascript)., I got this little hack using the placeholder to show standard error messages.
$("form").submit(function(e) {
if (!e.target.checkValidity()) {
console.log("I am Safari"); // Safari continues with form regardless of checkValidity being false
e.preventDefault(); // dismiss the default functionality
$('#yourFormId :input:visible[required="required"]').each(function () {
if (!this.validity.valid) {
$(this).focus();
$(this).attr("placeholder", this.validationMessage).addClass('placeholderError');
$(this).val(''); // clear value so it shows error message on Placeholder.
return false;
}
});
return; // its invalid, don't continue with submission
}
e.preventDefault(); // have to add it again as Chrome, Firefox will never see above
}
I found a great blog entry with a solution to this problem. It solves it in a way that I am more comfortable with and gives a better user experience than the other suggestions here. It will change the background color of the fields to denote if the input is valid or not.
CSS:
/* .invalid class prevents CSS from automatically applying */
.invalid input:required:invalid {
background: #BE4C54;
}
.invalid textarea:required:invalid {
background: #BE4C54;
}
.invalid select:required:invalid {
background: #BE4C54;
}
/* Mark valid inputs during .invalid state */
.invalid input:required:valid {
background: #17D654 ;
}
.invalid textarea:required:valid {
background: #17D654 ;
}
.invalid select:required:valid {
background: #17D654 ;
}
JS:
$(function () {
if (hasHtml5Validation()) {
$('.validate-form').submit(function (e) {
if (!this.checkValidity()) {
// Prevent default stops form from firing
e.preventDefault();
$(this).addClass('invalid');
$('#status').html('invalid');
}
else {
$(this).removeClass('invalid');
$('#status').html('submitted');
}
});
}
});
function hasHtml5Validation () {
return typeof document.createElement('input').checkValidity === 'function';
}
Credit: http://blueashes.com/2013/web-development/html5-form-validation-fallback/
(Note: I did extend the CSS from the post to cover textarea and select fields)
I use this solution and works fine
$('#idForm').click(function(e) {
e.preventDefault();
var sendModalForm = true;
$('[required]').each(function() {
if ($(this).val() == '') {
sendModalForm = false;
alert("Required field should not be blank."); // or $('.error-message').show();
}
});
if (sendModalForm) {
$('#idForm').submit();
}
});
The new Safari 10.1 released Mar 26, 2017, now supports the "required" attribute.
http://caniuse.com/#search=required
You can add this event handler to your form:
// Chrome and Firefox will not submit invalid forms
// so this code is for other browsers only (e.g. Safari).
form.addEventListener('submit', function(event) {
if (!event.target.checkValidity()) {
event.preventDefault();
var inputFields = form.querySelectorAll('input');
for (i=0; i < inputFields.length; i++) {
if (!inputFields[i].validity.valid) {
inputFields[i].focus(); // set cursor to first invalid input field
return false;
}
}
}
}, false);
Within each() function I found all DOM element of text input in the old version of PC Safari, I think this code useful for newer versions on MAC using inputobj['prpertyname'] object to get all properties and values:
$('form').find("[required]").each(function(index, inputobj) {
if (inputobj['required'] == true) { // check all required fields within the form
currentValue = $(this).val();
if (currentValue.length == 0) {
// $.each((inputobj), function(input, obj) { alert(input + ' - ' + obj); }); // uncomment this row to alert names and values of DOM object
var currentName = inputobj['placeholder']; // use for alerts
return false // here is an empty input
}
}
});
function customValidate(){
var flag=true;
var fields = $('#frm-add').find('[required]'); //get required field by form_ID
for (var i=0; i< fields.length;i++){
debugger
if ($(fields[i]).val()==''){
flag = false;
$(fields[i]).focus();
}
}
return flag;
}
if (customValidate()){
// do yor work
}
I'm creating a nice-ish HTML form on my website for a school project (though this question is not homework)
The form takes product specifications from input and lists them for sale or looks if they are available. The action the website takes depends on whether the user is a buyer or seller.
At the top of the form there are two nice buttons - "Buyer" and "Seller". The user selects one and proceeds with his details. However, when the form is processed, I can't think of a simple way to check which button was selected. With radio buttons it was easy, but I want to use full buttons like these because they will look much nicer on the site.
I've made a sample on JSFiddle- http://jsfiddle.net/6u6jN/1/
For a user who clicks "Buyer" and types the name "Sarah", the result I want is "You are a Buyer named Sarah".
Essentially, my question can be summed up as: How do you use ordinary buttons as though they were radio buttons?
Code from JSFiddle, as required by StackOverflow:
HTML:
<form>
<button type="button" class="mybutton" id="buyer">Buyer</button>
<button type="button" class="mybutton" id="seller">Seller</button>
<input type="text" id="inputBox" name="name" />
</br>
<button type="button" id="submit" onClick="inputProcess(this.form)">Enter</button>
</form>
<div id="results"></div>
CSS:
.mybutton {
padding: 20px;
font-family: inherit;
font: inherit;
color: inherit;
text-shadow: inherit;
text-align: center;
border-radius: 6px;
position: relative;
background: #0ff551;
border: 2px solid #c2e1f5;
display: inline-block;
}
#inputBox {
height: 40px;
width: 200px;
font-size: 30pt;
}
JavaScript:
function inputProcess(form){
var name = form.name.value;
var resultsDisplay = document.getElementById("results");
resultsDisplay.innerHTML = "<p> You are a ????? whose name is " + name + "</p>";
}
You need to add event listeners on the buttons, and then when the button is clicked you save the result in a variable, something like this:
var result;
document.getElementById('seller').addEventListener('click', function() {
result = this.textContent;
}, false);
document.getElementById('buyer').addEventListener('click', function() {
result = this.textContent;
}, false);
document.getElementById('submit').addEventListener('click', function() {
var name = document.getElementById('inputBox').value;
var resultsDisplay = document.getElementById("results");
resultsDisplay.innerHTML = "<p> You are a " + result + " whose name is " + name + " </p>";
}, false);
Also I would avoid attaching event directly to HTML like <button onclick="?"></button>, it's much cleaner to just attach the listener onload with document.addEventListener
JSFiddle
I have no idea what this is even called so not sure where to start, hoping you all are able to point me in the right direction. I am trying to create something like this:
The idea being that when a user types something in and then separates with a comma, their input into this form field will turn into a little tag-like box that they can then delete with the x.
Any ideas on where to start?
Thanks!
Here is simple example: http://jsfiddle.net/9tzb4/
HTML:
<form>
Tags:
<div class="tag_field">
<input type="text">
<input type="hidden" name="tags">
</div>
<br>
<input type="submit" value="Submit">
</form>
CSS:
.tag_buttons {
position: absolute;
}
.tag_buttons div {
display:inline-block;
margin: 2px;
border: 1px solid #666;
padding: 1px;
}
.tag_field input[type=text] {
padding: 5px;
width: 300px;
border: 1px solid #666;
}
JavaScript:
$(".tag_field").each(function() {
var buttons = $("<div/>");
var input = $(this).find("input[type=text]");
var output = $(this).find("input[type=hidden]");
var update_padding = function() {
input.css("padding-left", buttons.width() + 2);
};
setInterval(update_padding, 300);
$(this).prepend(buttons);
buttons.addClass("tag_buttons");
buttons.css({ left: input.offset().left + 1,
top: input.offset().top + 2 });
input.bind("keyup change paste", function() {
var i = input.val().indexOf(",");
if (i >= 0) {
var new_tag = input.val().substr(0, i);
input.val(input.val().substr(i+1));
buttons.append("<div id='button'><span class='value'>"+new_tag+"</span> <span class='close'>(x)</span></div>");
}
});
var form = $(this).closest("form");
if (form.length > 0) {
form.submit(function() {
var v = [];
form.find(".tag_buttons div").each(function() {
v.push($(this).find(".value").html());
});
output.val(v.join(","));
return false;
});
}
});
$(document).on("click", ".tag_buttons span.close", {}, function(e) {
$(e.target).closest("div").detach();
});
Check this out. http://davidwalsh.name/dw-content/jquery-chosen.php This is the things I guess will perfectly suite your application.
Check out the amazing jQuery chosen, which - among other things - does exactly what you're looking for.
select2 is a similar plugin, and it also allows you to add your own tags (as well as use an AJAX source).
Update from the select2 docs:
Note that when tagging is enabled the user can select from pre-existing tags or create a new tag by picking the first choice which is what the user has typed into the search box so far.
You may find the jQuery Tags Input Library helpful. It gives you something like this