Replacing normal file upload input with an image - javascript

Bit of a newbie question here.
I have a form and one of it's fields is for a file upload. Instead of having the boring old usual text input box with a 'choose file' button beside it, I'd like to have an image which when you click opens the dialog box to browse for the photo.
The way I was hoping to be able to do this was with two forms. IE when the user clicks the image a modal box appears with form upload input in it. User chooses file and clicks submit the user is returned to the form.
That doesn't seem to work because having a form inside a form must be bad practice i suppose :) Is there a way to do it like this?
The alternative is that I can somehow replace the usual text input box with the 'choose file' button with my own graphic but despite google I ain't found out how to do that.
Any ideas

Very simple solution - simply put a label tag for your input
<label for="uploadFile">
<div id="image"></div>
</label>
<input type="file" id="uploadFile" style="display:none" />
And the just add a background-image property to the #image div :)

Because of the heap of security issues around how file inputs work, they're pretty hard to fix. What does work, however, is a scheme like this:
Design your own look for a file input that's fairly close to the default one in size and shape
Position your file input and a real file input at the same place in your form, with the real one on top of yours
Make the real input be transparent (that is, set the opacity to zero)
Now clicks on your elements styled the way you want them to look will actually be interpreted by the browser as clicks on the file input. You have to tweak things somewhat for IE, because IE7 allows the user to type directly into the input while other browsers all immediately launch the file chooser when the element is clicked anywhere.
edit — here is a jsfiddle that works in Chrome at least. The HTML:
<div class='fancy-file'>
<div class='fancy-file-name'> </div>
<button class='fancy-file-button'>Browse...</button>
<div class='input-container'>
<input type='file'>
</div>
</div>
That wraps the "fake" file input that I'll style with my own CSS, as well as the real <input> element. Here's the CSS:
div.fancy-file {
position: relative;
overflow: hidden;
cursor: pointer;
}
div.fancy-file-name {
float: left;
border-radius: 3px;
background-color: #aaa;
box-shadow:
inset 1px 1px 3px #eee,
inset -1px -1px 3px #888,
1px 1px 3px #222;
font-weight: bold;
font-family: Courier New, fixed;
width: 155px;
font-size: 12px;
padding: 1px 4px;
}
button.fancy-file-button {
float: left;
border-radius: 3px;
border: 1px solid red;
background-color: #F5BD07;
font-weight: bold;
vertical-align: top;
margin: 0 0 0 3px;
}
div.input-container {
position: absolute;
top: 0; left: 0;
}
div.input-container input {
opacity: 0;
}
The outer container is made "position: relative" to make it easy to position the real <input> over the fake stuff. The fake stuff has my made-up fancy styles, and it's sized so that it's just about the same as the overall size of a real file input. The real one is absolutely positioned and transparent.
Here's some jQuery to drive it:
$('div.fancy-file input:file').bind('change blur', function() {
var $inp = $(this), fn;
fn = $inp.val();
if (/fakepath/.test(fn))
fn = fn.replace(/^.*\\/, '');
$inp.closest('.fancy-file').find('.fancy-file-name').text(fn);
});
Browsers won't give you the complete pathname, but they'll give you a part of it. Some browsers (Chrome and IE) give you an obviously-fake path prefix, so the code strips that out (because it's useless).

File upload fields are quite limited. See: http://www.quirksmode.org/dom/inputfile.html

Related

Strange behavior with absolute positioning, style.top, style.left and "a" tag

I was trying to complete a simple task on Javascript.info and I'm getting my ass beaten by an "a" tag. The task is to simply place (and remove) a tooltip above the element on hover and I have no problem with the roof or the house, but when I try to place the box above the link, it breaks and I can't solve it for my life.
I'm asking for help here because the solution on the site uses position:fixed while I'm trying to use position:absolute and simply mimicking the solution won't help me learning anything. The problem is all on line 77 and 78, when I try to assign tooltip.style.left and tooltip.style.top.
If I try to assign it usign a literal (for example, "-58px"), it works. Otherwise, it just defaults to whatever value the tooltip on "house" would have. I tried to see what is going on with some tactical alerts and it drove me insane. It shows me that if I use a computed value, it defaults and if I use a literal, it will work normally.
I'd like someone to explain what is going on and possibly some insight (pointing out if I got wrong how position:absolute works, how element size properties works or something on this nature)
The code (I only made the part that is inside of the script tag on line 64, the rest is from the authors of the task):
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<style>
body {
height: 2000px;
/* the tooltip should work after page scroll too */
}
.tooltip {
position: fixed;
z-index: 100;
padding: 10px 20px;
border: 1px solid #b3c9ce;
border-radius: 4px;
text-align: center;
font: italic 14px/1.3 sans-serif;
color: #333;
background: #fff;
box-shadow: 3px 3px 3px rgba(0, 0, 0, .3);
}
#house {
margin-top: 50px;
width: 400px;
border: 1px solid brown;
}
#roof {
width: 0;
height: 0;
border-left: 200px solid transparent;
border-right: 200px solid transparent;
border-bottom: 20px solid brown;
margin-top: -20px;
}
p {
text-align: justify;
margin: 10px 3px;
}
</style>
</head>
<body>
<div data-tooltip="Here is the house interior" id="house">
<div data-tooltip="Here is the roof" id="roof"></div>
<p>Once upon a time there was a mother pig who had three little pigs.</p>
<p>The three little pigs grew so big that their mother said to them, "You are too big to live here any longer. You must go and build houses for yourselves. But take care that the wolf does not catch you."</p>
<p>The three little pigs set off. "We will take care that the wolf does not catch us," they said.</p>
<p>Soon they met a man. Hover over me</p>
</div>
<script>
house.onmouseover= function(event){
let target= event.target.closest('[data-tooltip]');
let tooltip= document.createElement('div');
tooltip.textContent= target.dataset.tooltip;
tooltip.classList.add("tooltip");
target.append(tooltip);
if(!tooltip.parentElement.style.position){
tooltip.parentElement.style.position= 'relative';
}
tooltip.style.position= 'absolute';
tooltip.style.top= "-"+(tooltip.offsetHeight+5)+"px";
tooltip.style.left= -target.clientLeft+(target.offsetWidth-tooltip.offsetWidth)/2+"px";
//alert("-"+(tooltip.offsetHeight+5)+"px");
//alert(tooltip.style.top);
}
house.onmouseout= function(event){
let target= event.target.closest('[data-tooltip]');
tooltips= target.querySelectorAll('.tooltip');
for(tooltip of tooltips){
tooltip.remove();
}
}
</script>
</body>
</html>
Thanks already :)
when I try to place the box above the link, it breaks
This is because the tooltip box is positioned to appear under the mouse. Hovering over the link generates a regenerative feedback loop of
Create and append the tooltip element to the <a> element
The mouse is over the tooltip element
Fire mouseout on the a element in preparation of firing mouseover on the tooltip.
mouseout handling removes the tooltip element
The mouse is now over the a element,
Fire mouseover on the a element and repeat from step 1.
The roof and interior mouseover events don't trigger the loop because the tooltip box is outside the target element with the data-tooltip attribute.
You could try
Moving the tooltip box so it cannot appear under the mouse, or
Think of creative ways of using mousenter and mouseleave events on the anchor element that don't fire when hovering over the tooltip because it is a child of the anchor element, or
Turn off pointer events from tooltip elements:
.tooltip {
pointer-events: none;
}
Additional listeners used to verify the problem:
house.addEventListener("mouseover", e=>console.log("over"));
house.addEventListener("mouseout", e=>console.log("out"));
The additional delay caused by console.log did result in the tooltip box being rendered and becoming visible in Firefox, but the log output definitely confirms the feed back loop in action.

Showing a document to write text on with javascript

I am attempting to design a very basic word processor. I want to have a "page" shown in the background (like you might see on Google Docs, or MS Word) that your text is written on.
How do I draw this page? Should it be an SVG? A stylized DIV? A big canvas? I am very new to designing using the DOM, so any help is appreciated.
Take a look at the contenteditable property here. This actually allows some elements content to be edited by the end user. For example, if I have
<div contenteditable="true">Hello!</div>
I can actually edit the text and change it as it fits my needs, right from the browser. This will come in handy when you try to implement features like bold or italic text, and a div element is also much easier to generally style than a huge textarea or input field.
As a notice, also don't forget about XSS.
You may be interested in the getting the page-like appearance at Google Docs. If so, then check out this really nice tutorial on building a collaborative text editor with Javascript. It's well written and introduces concepts gradually and even has a GitHub repo.
I streamlined the example into a single file HTML file that you can play with. This example also uses the contenteditable property mentioned in Armen's answer. By the way, the page-like effect is achieved via CSS which I've included within the HTML file using the <style> tag.
<html><head><style>
body { font-size: 14px; line-height: 20px; background: #e8e8e8; }
.ribbon { height: 200px; background: #3F51B5; }
.editor { width: 60%; padding: 40px 28px; min-height: 300px;
background: #fff; margin: 0 auto; position: relative;
top: -150px; font-size: 24px; }
</style>
<body>
<div class="ribbon"></div>
<div id="doc" class="editor" contenteditable="true"></div>
<script>document.getElementById('doc').focus();</script>
</head></body></html>
You can use a textarea element and set a specific height and width.
const bold = document.getElementById('bold');
const text = document.getElementById('text');
bold.addEventListener('click', () => {
if (text.style.fontWeight != 'bolder') {
text.style.fontWeight = 'bolder';
}
else {
text.style.fontWeight = 'normal';
}
});
textarea {
height: 500px;
width: 300px;
}
<button id="bold">bold</button>
<br>
<textarea id="text" placeholder="write text here!"></textarea>

Is it possible/feasible to replace certain characters with <span>[character]</span> as they are typed?

I'd like to have it so that whenever a user types a '#' into the search form, the '#' is styled a specific color.
I assume that the only way to do this would be to replace every instance of that character with a <span class="colorHash"></span> and to then apply the color to the class with css.
Is this possible? Can anyone point me in the right direction?
One solution would be to have an element that mimics a text input by looking as much like one as possible be placed over the actual input. This mimic would be updated every time the input changes, and include the color-changed hashes. It would have no pointer events, so clicking on it would allow the user to interact with the underlying real input.
Here is a reference implementation. It is by no means perfect, and I do not recommend copying code from it.
Good things:
Input data is stored unchanged in an <input> element, so works fine with forms.
Bad things:
What is shown is not an actual <input> element, but a mimic. This causes there to be no cursor (bad), and may cause other issues. It means all styling on input[type=text] should be on the mimic, too.
Slight input lag.
A slightly different way of doing this would be to have the mimic be invisible, except for the red hashes.
Here is a reference implementation. It is by no means perfect, and I do not recommend copying code from it.
Good things:
Removes lag on input
Cursor is visible
User sees the real input element (good in my book)
Bad things:
Red color lags (mostly visible when using the jQuery version of the code)
Likely much harder to maintain. The mimic must be positioned to pixel-perfection on top of the real input.
Since this seems to be closer to what you're looking for, I'll include the code for this version here...
This code is by no means perfect, and I do not recommend copying code from it.
<div id="wrapper">
<input type="text" id="data-input">
<pre class="text-input-mimic" id="shown-data"></pre>
</div>
#wrapper { position: relative; }
#shown-data {
/* Stacked in top-left corner */
position: absolute;
top: 0;
left: 0;
/* Clicking and typing goes through to real input */
pointer-events: none;
}
.text-input-mimic, input[type=text] {
border: 1px solid grey;
width: 250px;
height: 20px;
padding: 5px;
display: inline-block;
margin: 0;
font-family: Calibri !important;
font-size: 16px !important;
}
.text-input-mimic {
/* Make invisible except for hashes */
background: none !important;
border: none !important;
color: rgba(0, 0, 0, 0);
/* Pixel-perfect adjustments */
padding-top: 7px;
padding-left: 6px;
}
.colored { color: red !important; }
JS (jQ):
$('#data-input').on("change keyup paste", function() {
let inp = $('#data-input').val();
let modified = inp.replace(/#/g, '<span class="colored">#</span>');
$('#shown-data').html(modified);
});
Alternatively, JS (plain):
real = document.getElementById('data-input');
mimic = document.getElementById('shown-data');
real.addEventListener('input', function() {
let inputVal = real.value;
let modified = inputVal.replace(/#/g, '<span class="colored">#</span>');
mimic.innerHTML = modified;
});

Dynamically changing the height of a div based on content

So I am trying to make a website and have a popup window/box DIV that appears after clicking something. This popup DIV contains text/content, let's name it "Locations," as per my website's design. This Locations Popup DIV has a fixed height and width, and consequently, there is a vertical scroll bar I've created to scroll down and read the text. I would like to add more content to this popup but unfortunately, the text is being cutoff, and the scroll does not continue scrolling down. I have set a pretty large value for the margin/padding in the DIV to make this work for a very long page length, but it is very inefficient and poor programming.
How can I set the style of a div to the height of the total HTML document (which is the dyanamic, changing factor here) using JavaScript or CSS so I can do this intelligently and properly? I don't want to have to manually do this, as the longer the HTML Document becomes if I choose, I will always have to go back and either change the margin/padding value in CSS or do something to the JavaScript.
Below is the CSS for it:
/* Pop Up */
#popupAbout, #popupLocations, #popupContact, #popupBlog {
height: 600px;
width: 900px;
overflow: scroll;
background-color: rgba(0, 0, 0, 0.75);
border: 2px solid #cecece;
z-index: 15;
padding: 20px;
color: #FFF;
-webkit-box-shadow: 0px 0px 4px #000 inset;
-moz-box-shadow: 0px 0px 4px #000 inset;
box-shadow: 0px 0px 4px #000 inset;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-o-border-radius: 10px;
-ms-border-radius: 10px;
-khtml-border-radius: 10px;
border-radius: 10px;
margin-top: -50px;
visibility: hidden;
}
#popupAbout p, #popupLocations p, #popupContact p, #popupBlog p {
padding-left: 10px;
font-size: 18px;
line-height: 20px;
}
#popupAbout h1, #popupLocations h1, #popupContact h1, #popupBlog h1 {
text-align: left;
font-size: 30px;
letter-spacing: 1px;
border-bottom: 1px dotted #D3D3D3;
padding-bottom: 2px;
margin-bottom: 20px;
}
#popupAboutClose, #popupLocationsClose, #popupContactClose, #popupBlogClose {
right: 6px;
top: 6px;
position: absolute;
display: block;
}
And the appropriate JavaScript:
//Locations Page Pop Up
var popupLocationsStatus = 0;
function loadPopupLocations(){
if(popupLocationsStatus==0){
$("#popupLocations").fadeIn("slow");
popupLocationsStatus = 1;
}
}
function disablePopupLocations(){
if(popupLocationsStatus==1){
$("#popupLocations").fadeOut("slow");
popupLocationsStatus = 0;
}
}
function centerPopupLocations(){
var windowWidth = document.documentElement.clientWidth;
var windowHeight = document.documentElement.clientHeight;
var popupLocationsHeight = $("#popupLocations").height();
var popupLocationsWidth = $("#popupLocations").width();
$("#popupLocations").css({
"position": "absolute",
"top": windowHeight/2-popupLocationsHeight/2,
"left": windowWidth/2-popupLocationsWidth/2
});
}
$(document).ready(function(){
$("#popupLocations").fadeOut();
popupLocationsStatus = 0;
$("#Locations").click(function(){
$("#popupLocations").css({
"visibility": "visible" });
disablePopupAbout();
disablePopupContact();
centerPopupLocations();
loadPopupLocations();
});
$("#popupLocationsClose").click(function(){
disablePopupLocations();
});
});
$(function()
{
$('#popupLocations').jScrollPane();
$('.popupLocations').jScrollPane(
{
showArrows: true,
horizontalGutter: 10
}
);
});
Here is the screenshot I've saved to give a better look at what I am talking about exactly (looking at the bottom of the popup window where the text is being cutoff):
My Website Screenshot
Everyone may view my work so far at: www.zaheeruddinsyed.com, to see exactly what I am talking about.
I believe you're looking for overflow: auto property. Take a look at this fiddle.
If you want to achieve the scrollbar like on sample image, you'll have to play around with css, here is tutorial on how to apply custom style to scrollbar.
Btw, if you want to make popup window, you might want to look at Fancybox, which, in my opinion, looks really good and most of work is already done! The only downside might be that you have to use it with jQuery, but it's already used on most of the webpages today.
Edit
When I've looked at page source, I found the problem in less than a minute. The content of your popup div isn't scrolling to the bottom, it stops for some reason.
This question is similar: Bottom content cutoff using overflow: auto; and jscrollpane
Try and put this code in JavaScript console (Ctrl + Shift + (J in Chrome, K in Firefox):
$("#popupLocations .jspPane").css("top","-800px")
It scrolls down to the bottom where it should. I know that this doesn't solve your problem just yet, but I think I've found a solution (I'm not sure because I can't test it myself). But if you look at that other question, the solution is using autoReinitialise:true. You can try it right away by running this in JavaScript console:
$('.popupLocations').jScrollPane({
showArrows: true,
horizontalGutter: 10,
autoReinitialise:true
}
);
Of course you'll have to put it in your file where you're initializing jScrollPane if you want it to work correctly every time you refresh the page.
And why do you have 2 $(document).ready(function()...) and 2 $(function()... (which is the same) definitions in your file? You should put all the code in one function, which will be called when the DOM is loaded. And for the sake of your users UX, try to reduce the images and files, also try to avoid using millions of different js plugins. It took me almost 11s (according to network profiler) to load for the first time and I have 100Mb/s uplink, I can't imagine someone with mobile internet. The webpage makes over 100 requests, a lot of them are 1x1px pngs. If all that is really necessary, you might want to look into compressing and bundling. It depends on what back-end framework you'll be using. I can say that ASP.NET MVC 4 provides very simple bundle manager but I'm sure that PHP or rails provide something similar.

Controls are not positioning correctly when displaying validation summary on top of web page

I am getting weird problem in using custom validator function in asp.net page and showing validation summary on the top of web page using CSS Styles.....
and this is the screen shot before clicking the button submit changes
after submitting the page the validation summary is displayed on top but controls positon is changing like this
and this is my code for
<div id="validationSummaryHolder" class="validationSummaryHolder">
<asp:ValidationSummary runat="server" ID="valsErrors" ValidationGroup="TestValidation" DisplayMode="BulletList"
CssClass="validationsummary" HeaderText="<div class='validationheader'>Please correct the following:</div>" />
</div>
and this is my css styles for validation summary
Css Styles for validation summary
.validationheader
{
background-color: white;
color:green;
height: 14px;
font-weight: bold;
border-bottom: 1px solid #b08b34;
padding-top: 3px;
}
.validationsummary
{
border: 1px solid #b08b34;
padding: 0px 0px 0px 0px;
margin:5px 0 20px 0px;
font-size:12px;
width:99%;
}
.validationsummary ul
{
padding-top: 1px;
font-size: 12px;
color:#982b12;
}
.validationsummary ul li
{
padding: 1px 0px 0px 1px;
}
I have placed all controls in individual divs and mentioned type of positon for all controls is Relative ..
I don't know why I am getting this weird thing,
Do i need to set fixed height and width for total page ?
would any one pls help on this
Many thanks In advance....
Check the width of
<div id="validationSummaryHolder" class="validationSummaryHolder">
It is not likely the the validation summary's insides are causing anything of their own accord since they are contained in that div, but maybe the containing div is stretching or shrinking the page. Also some html in the question would help. If you can't paraphrase the html here, another option would be to show the wire frame of the page with and without the validation summary and the answer should be clear at that point what is happening.

Categories