How to change <input type="file"> design so it won't display the text-field? [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
input type=file show only button
The has this kind of design:
Can I modify it so it won't show the text field?

a very good guide is found in quirksmode - Styling an input type="file"
quote with some modifications to match question:
Take a normal <input type="file"> and put it in an element with position: relative. or absolute
To this same parent element, add an image or a button, which have the correct styles. Position this element absolutely, so
that they occupy the same place as the <input type="file">.
Set the z-index of the <input type="file"> to 2 so that it lies on top of the styled image or button.
Finally, set the opacity of the <input type="file"> to 0. The <input type="file"> now becomes effectively invisible, and the styled
image or button shines through, but you can still click on the "Browse"
button. (Note that you can't use visibility: hidden, because a truly
invisible element is unclickable, too, and we need the <input
type="file"> to remain clickable)

Suggestion: You can use the uploadify plugin.

Don't see a jQuery tag in your question but hey, it's helpful, and possibly quite easy to rewrite in vanilla JS. This is a little jQuery plugin I extracted from Ideal Forms, a plugin I maintain at github. It covers all the basics to do what you want, with fallback for IE and multiple for HTML5 browsers. Plus handling events and markup replacement. CSS is on your own, but nothing too complicated to style as you can see. You can hide the text field too if you want. The idea here is that this allows for ANY customization possible with CSS.
$.fn.toCustomFile = function () {
return this.each(function () {
var
$file = $(this), // The file input
// Necessary markup
$wrap = $('<div class="wrap">'),
$input = $('<input type="text" class="filename" />'),
$button = $('<button type="button" class="upload">Open</button>')
// Hide by shifting to the left, that way can
// still use events that are otherwise problematic
// if the field is hidden as in "display: none"
$file.css({
position: 'absolute',
left: '-9999px'
})
// Events
$button
.attr('tabIndex', -1) // disable focus on button for better usability
.click(function () {
$file.trigger('click') // Yes, `click`, not `change`. Crossbrowser compat.
})
$file
.attr('tabIndex', -1)
.on({
change: function () {
// Detect if browser supports HTML5 "file multiple"
var multipleSupport = typeof $('input')[0].multiple !== 'undefined',
files = [],
fileArr,
filename
if (multipleSupport) {
fileArr = $file[0].files
for (var i = 0, len = fileArr.length; i < len; i++)
files.push(fileArr[i].name)
filename = files.join(', ')
} else {
filename = $file.val().split('\\').pop() // Remove fakepath
}
$input.val(filename)
// Set filename as title tooltip on
// input field for better usability
$input.attr('title', filename)
},
focus: function () {
$input.trigger('focus')
}
})
$input
.on({
keyup: function () { $file.trigger('change') },
focus: function () { $file.trigger('change') },
blur: function () { $file.trigger('blur') },
// Open files when pressing [ENTER]
// on the input field
keydown: function (e) { if (e.which === 13) $file.trigger('click') }
})
// Append to DOM
$wrap.append($button, $input).insertAfter($file)
})
}
Here's a gist for ease of use: https://gist.github.com/3051209

Related

Use XPath or onClick or onblur to select an element and use jQuery to blur this element

*UPDATE:I am new to jQuery, as well as using XPath, and I am struggling with getting a proper working solution that will blur a dynamically created HTML element. I have an .onblur event hooked up (doesn't work as expected), and have tried using the $(document.activeElement), but my implementation might be incorrect. I would appreciate any help in creating a working solution, that will blur this element (jqInput) when a user clicks anywhere outside the active element. I have added the HTML and jQuery/JavaScript below.
Some ideas I have had:
(1) Use XPath to select a dynamic HTML element (jqInput), and then use jQuery's .onClick method to blur a this element, when a user clicks anywhere outside of the area of the XPath selected element.
(2) Use the $(document.activeElement) to determine where the .onblur should fire:
var thisTitle = input0;
var activeElement = $(document.activeElement);
if (thisTitle != activeElement) {
jqInput.hide();
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
}
I am open to all working solutions. And hopefully this will answer someone else's question in the future.
My challenge: Multiple elements are active, and the .onblur does not fire. See the image below:
NOTE: The <input /> field has focus, as well as the <div> to the left of the (the blue outline). If a user clicks anywhere outside that <input />, the blur must be applied to that element.
My Code: jQuery and JavaScript
This is a code snippet where the variable jqInput and input0 is created:
var jqInput = null;
if (jqHeaderText.next().hasClass("inline-editable"))
{
//Use existing input if it already exists
jqInput = jqHeaderText.next();
}
else
{
//Creaet a new editable header text input
jqInput = $("<input class=\"inline-editable\" type=\"text\"/>").insertAfter(jqHeaderText);
}
var input0 = jqInput.get(0);
//Assign key down event for the input when user preses enter to complete entering of the text
input0.onkeydown = function (e)
{
if (e.keyCode === 13)
{
jqInput.trigger("blur");
e.preventDefault();
e.stopPropagation();
}
};
This is my .onblur event, and my helper method to blur the element:
input0.onblur = function ()
{
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
};
inputOnBlurHandler: function (canvasObj, jqHeaderText, jqInput)
{
// Hide input textbox
jqInput.hide();
// Store the value in the canvas
canvasObj.headingText = jqInput.val();
_layout.updateCanvasControlProperty(canvasObj.instanceid, "Title", canvasObj.headingText, canvasObj.headingText);
// Show header element
jqHeaderText.show();
_layout.$propertiesContent.find(".propertyGridEditWrapper").filter(function ()
{
return $(this).data("propertyName") === "Title";
}).find("input[type=text]").val(canvasObj.headingText); // Update the property grid title input element
}
I have tried using the active element, but I don't think the implementation is correct:
var thisTitle = input0;
var activeElement = $(document.activeElement);
if (thisTitle != activeElement) {
jqInput.hide();
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
}
My HTML code:
<div class="panel-header-c">
<div class="panel-header-wrapper">
<div class="panel-header-text" style="display: none;">(Enter View Title)</div><input class="inline-editable" type="text" style="display: block;"><div class="panel-header-controls">
<span></span>
</div>
</div>
</div>
I thank you all in advance.

jQuery highlight plugin cancels text selection, making copy impossible while also rendering links unclickable

I'm using the jQuery Highlight plugin to select some text on a web page.
I've hooked up selecting and deselecting with mouse events:
document.addEventListener('mouseup', doSelect);
document.addEventListener('mousedown', doDeselect);
The functions are:
function doSelect() {
var selectionRange = window.getSelection();
var selection = selectionRange.toString();
if (selection.trim().length > 0) {
$('body').highlight(selection);
}
}
function doDeselect() {
$('body').unhighlight();
}
Short and easy. The library searches for the selected text and wraps each occurrence in a <span> and so the text stands out.
It's working great, but I have two issues with how it behaves.
The problem is that once the span elements are applied, I cannot click hyperlinks (the ones that were found/selected), they don't react to clicks (I have to deselect the text first).
Once the span elements are added, the original selection is somehow lost, i.e. I cannot copy what I selected with CTRL+C.
These issues can be seen in this jsfiddle.
Why is this happening?
The code
The working demo is available here: jsfiddle
JavaScript
var $body = $('body');
var $copyArea = $('#copyArea');
document.addEventListener('mouseup', doSelect);
document.addEventListener('mousedown', doDeselect);
document.addEventListener('keydown', keyPressHandler);
function keyPressHandler(e) {
if(e.ctrlKey && e.keyCode == 67) {
$copyArea.focus().select();
}
}
function doSelect() {
var selectionRange = window.getSelection();
var selection = selectionRange.toString();
if (selection.trim().length > 0) {
$copyArea.val(selection);
$body.highlight(selection);
}
}
function doDeselect(e) {
var elem = $(e.target).parents('a');
if(elem.length == 0) {
$copyArea.val('');
$body.unhighlight();
}
}
HTML
Sample text to select.
<br/>Sample text to select.
<br/>Sample text to select.
<br/>google.com
google.com
<a href="http://google.com" target="_blank">
<span>
<span>google.com</span>
</span>
</a>
<textarea id="copyArea"></textarea>
CSS
.highlight {
background-color: #FFFF88;
}
#copyArea {
position:fixed;
top:-999px;
height:0px;
}
Part 1 - Clicking through the selection
Presumably, the reason clicking on a highlighted link doesn't work is because the process that disables the highlighting kicks in first and cancels the click.
To bypass that, we implement a condition that checks if the target element of the mousedown event has an a element as ancestor. If that is true, we simply do not execute $body.unhighlight();, allowing the click to pass through and open the link.
function doDeselect(e) {
var elem = $(e.target).parents('a');
if(elem.length == 0) {
$copyArea.val('');
$body.unhighlight();
}
}
Part 2 - Copying the selection
Presumably, again, the reason the selection is lost is because the document is modified by the highlighting, which introduces elements into the DOM.
My first idea was to reapply the selection after the modification was done. This became annoying and I went in a different direction, which allowed me to stumble upon this:
The Definitive Guide to Copying and Pasting in JavaScript
This offered a simple and efficient idea: using an hidden element that could contain selectable text.
Therefore, to allow copying the selected text that we highlighted despite having lost the original selection:
We add a hidden textarea element to our document.
<textarea id="copyArea"></textarea>
We get a reference to that element.
var $copyArea = $('#copyArea');
We add an event handler for the keydown event.
document.addEventListener('keydown', keyPressHandler);
We add the event handler.
function keyPressHandler(e) {
if(e.ctrlKey && e.keyCode == 67) {
$copyArea.focus().select();
}
}
We modify doSelect() to add some logic that will set the selection as the value of the textarea element, in the form of $copyArea.val(selection);.
function doSelect() {
var selectionRange = window.getSelection();
var selection = selectionRange.toString();
if (selection.trim().length > 0) {
$copyArea.val(selection);
$body.highlight(selection);
}
}
What does the handler do ? it captures the combination CTRL+C and focuses on the text in the hidden textarea, which ends up being copied by the keyboard command we just issued.

How to set input:focus style programatically using JavaScript

I'm building a UI library in JS that can, without relying on any CSS stylesheets, create UI components, stylised from code. So far, it's been quite easy, with exception of styling different control states (such as input:focus one).
Code that I use to create input field:
function newInput()
{
var ctr = docmuent.createElement("input");
ctr.setAttribute("type","text");
ctr.setAttribute("value", some-default-value);
ctr.style.fontFamily = "sans-serif,helvetica,verdana";
/* some font setup here, like color, bold etc... */
ctr.style.width = "256px";
ctr.style.height = "32px";
return ctr;
}
Styling it for default state is easy. However I am unsure how to set style for states such as focused, disabled or not-editable.
If I'd be having CSS stylesheets included in the project that would be easily sorted out. However I can't have any CSS files included, it must be pure JS.
Does anyone know how to set style for an input field state (eg. input:focus) straight from JS code?
No JQuery please :-) Just straight-up JS.
Thanks in advance!
You would need to add an event listener to the element in order to change the style of it. Here is a very basic example.
var input = document.getElementById("something");
input.addEventListener("focus", function () {
this.style.backgroundColor = "red";
});
<input type="text" id="something" />
Other alternative would be to build a stylesheet for the page.
Something like this:
var styles='input:focus {background-color:red}';
var styleTag=document.createElement('style');
if (styleTag.styleSheet)
styleTag.styleSheet.cssText=styles;
else
styleTag.appendChild(document.createTextNode(styles));
document.getElementsByTagName('head')[0].appendChild(styleTag);
This way you will have clean separation of css styles from the scripts and so the better maintenance.
Use CSS Variables if possible
It's 2022 and there are more simple solutions to this problem than adding event listeners all over the place that may never get cleaned up.
Instead if you have control over the CSS simply do this in your CSS:
.my-class {
--focusHeight: 32px;
--focusWidth: 256px;
}
.my-class:focus {
height: var(--focusHeight);
width: var(--focusWidth);
}
Then in your JavaScript it's as simple as using setProperty to update the variables:
const el = document.getElementById('elementId');
el.style.setProperty('--focusHeight', newFocusHeight);
el.style.setProperty('--focusWidth', newFocusWidth);
At first, create your input:
<input type="text" id="myElementID" />
Then add the javascript the following javascript:
const element = document.getElementById("myElementID");
// Add a box shadow on focus
element.addEventListener("focus", (e) => {
e.target.style.boxShadow = "0 0 0 3px #006bff40";
});
// Remove the box shadow when the user doesn't focus anymore
element.addEventListener("blur", (e) => {
e.target.style.boxShadow = "";
});
A quick oneliner, which dynamically appends a style tag to the
body.
document.body.innerHTML += '<style>#foo:focus {background-color:gold}</style>'
<input id="foo"/>
let input = document.querySelector(".input-text");
let label = document.querySelector('.fields-label');
input.addEventListener('focus', function(e){
label.classList.add('is-active');
})
input.addEventListener('blur', function(e){
if(input.value === "") {
label.classList.remove('is-active');
}
})
label.is-active{
color:red;
}
<div class="input-fields">
<label class="fields-label">Last Name</label>
<input type="text" class="input-text">
</div>

Javascript plugin to manage placeholder

Look at the Twitter sign up page at https://twitter.com/signup
Even when you click on first input field "Full name" placeholder stays there until I start typing something. That is awesome.
Does anyone know of a good jQuery plugin that comes close to that?
There's a lot of plugins out there for this. This is my homegrown solution I use:
/**
* Yet another textbox hint plugin...
* Usage: $('.selector').hint();
* The title attribute of the input will be used as the watermark value.
*/
(function($) {
$.fn.hint = function() {
var hintedClass = 'hinted';
return this.each(function() {
var $field = $(this),
title = $field.attr('title'),
$form = $(this.form);
// bail out if there isn't a title attribute
if (!title) { return; }
// add/remove hint behavior
var addHint = function() {
$field.val() || $field.addClass(hintedClass).val(title);
},
removeHint = function() {
if ($field.hasClass(hintedClass) && $field.val() === title) {
$field.val('').removeClass(hintedClass);
}
};
// set our focus/blur handlers
$field.focus(removeHint).blur(addHint);
// if the field isn't already focused, add the hint now
$field.is(':focus') || addHint();
// form submission handling
$form.submit(removeHint);
});
};
})(jQuery);
Zero JavaScript needed in browsers that support the HTML5 placeholder attribute
<label>Description: <input type="text" name="desc" placeholder="My Email Account"></label>
I wrote this example that functions just like the twitter one, but you might want to grab some additional CSS from the twitter bootstrap CSS if you want the exact styling.
I talk more about the method in this similar stackoverflow question.

Default text on input

How to set blank default text on input field and clear it when element is active.
In modern browsers, you may set the placeholder attribute on a field to set its default text.
<input type="text" placeholder="Type some text" id="myField" />
However, in older browsers, you may use JavaScript to capture the focus and blur events:
var addEvent = function(elem, type, fn) { // Simple utility for cross-browser event handling
if (elem.addEventListener) elem.addEventListener(type, fn, false);
else if (elem.attachEvent) elem.attachEvent('on' + type, fn);
},
textField = document.getElementById('myField'),
placeholder = 'Type some text'; // The placeholder text
addEvent(textField, 'focus', function() {
if (this.value === placeholder) this.value = '';
});
addEvent(textField, 'blur', function() {
if (this.value === '') this.value = placeholder;
});
Demo: http://jsbin.com/utecu
Using the onFocus and onBlur events allows you to achieve this, I.e.:
onfocus="if(this.value=='EGTEXT')this.value=''"
and
onblur="if(this.value=='')this.value='EGTEXT'"
The full example is as follows:
<input name="example" type="text" id="example" size="50" value="EGTEXT" onfocus="if(this.value=='EGTEXT')this.value=''" onblur="if(this.value=='')this.value='EGTEXT'" />
Or simply
<input name="example" type="text" id="example" value="Something" onfocus="value=''" />
This will not post back the default text once the box is cleared but also will allow the user to clear the box and see all results in the case of an autocomplete script.
Declare styles for inactive and active states:
.active {
color: black;
}
.inactive {
color: #909090;
}
Add the Javascript to handle the changing of state:
function toggleText(el)
{
var v = el.value;
//Remove text to allow editing
if(v=="Default text") {
el.value = "";
el.className = "active";
}
else {
//Remove whitespace
if(v.indexOf(" ")!=-1) {
split = v.split(" ").join("");
v = split;
}
//Change to inactive state
if(v=="") {
el.value = "Default text";
el.className = "inactive";
}
}
}
Add your input box, with the default value set, the inactive class set and Javascript handlers pointing to the toggleText() function (you could use event listeners to do this if you wish)
<input type="text" value="Default text" class="inactive" onFocus="toggleText(this);" onBlur="toggleText(this);">
From a usability point of view the text in the input component should be preserved only for user's input purposes. The possible default value in the input should be valid if left untouched by the user.
If the placeholder text is meant to be a hint for how to fill the input, it is better to be blaced near the input where it can be seen also when the input has been filled. Moreover, using a placeholder text inside text components can cause troubles e.g. with braille devices.
If a placeholder text is used, regardless of usability guidelines, one should make sure that it is done in an unobtrusive way so that it works with user agents without javascript or when js is turned off.
I have found jQuery plugin (http://www.jason-palmer.com/2008/08/jquery-plugin-form-field-default-value/) and use it :)
What I did is put a placeholder attribute for modern browsers:
<input id='search' placeholder='Search' />
Then, I made a fallback for older browsers using JQuery:
var placeholder = $('search').attr('placeholder');
//Set the value
$('search').val(placeholder);
//On focus (when user clicks into the input)
$('search').focus(function() {
if ($(this).val() == placeholder)
$(this).val('');
});
//If they focus out of the box (tab or click out)
$('search').blur(function() {
if ($(this).val() == '')
$(this).val(placeholder);
});
This works for me.
You can use this plugin (I'm an co-author)
https://github.com/tanin47/jquery.default_text
It clones an input field and put it there.
It works on IE, Firefox, Chrome and even iPhone Safari, which has the famous focus problem.
This way you do not have to be worried about clearing input field before submitting.
OR
If you want to HTML5 only, you can just use attribute "placeholder" on input field
You can use placeholder attribute.
np. <input type="text" name="fname" placeholder="First name">
check http://www.w3schools.com/tags/att_input_placeholder.asp

Categories

Resources