I'm trying to make a page that has some editabable fields, but I only want them to display as input boxes once the user clicks on them (the rest of the time showing as plain text). Is there a simple way to do this in Javascript?
To populate a text field, deploy the Run JavaScript function on web page action and populate the following code in the JavaScript function field. After pasting the code, replace the CSS-selector and value-to-populate placeholders with the previously copied selector and the value to populate, respectively.
To change the type of input it is (button to text, for example), use: myButton. type = "text"; //changes the input type from 'button' to 'text'. Another way to change or create an attribute is to use a method like element.
To select all text inside an element such as DIV, we can simply use JavaScript document. createRange() method to create a range, and than using range. selectNodeContents() we can set node range (start and end), after which use selection.
Fairly simple, yes. I can think of two basic approaches:
contenteditable
attributeinput
you add on-the-flyHandy references for both of the below:
contenteditable
attributeThe contentEditable
attribute (W3C, MDC, MSDN) can be "true" indicating that the element can be edited directly. This has the advantage of not requiring any JavaScript at all (live example):
<p id="container">The <span contenteditable="true">colored items</span> in this paragraph
are <span contenteditable="true">editable</span>.</p>
Lest you think this is some l33t new thing, IE has supported it since IE 5.5 and other major browsers for very nearly that long. (In fact, this was one of many Microsoft innovations from the IE5.5 / IE6 timeframe; they also gave us innerHTML
and Ajax.)
If you want to grab the (edited) content, you just grab innerHTML
from the elements you've made editable. Here's an example of some JavaScript that will flag up when contenteditable
spans blur
(live copy):
var spans = document.getElementsByTagName("span"),
index,
span;
for (index = 0; index < spans.length; ++index) {
span = spans[index];
if (span.contentEditable) {
span.onblur = function() {
var text = this.innerHTML;
text = text.replace(/&/g, "&").replace(/</g, "<");
console.log("Content committed, span " +
(this.id || "anonymous") +
": '" +
text + "'");
};
}
}
#container span {
background-color: #ff6;
}
<p id="container">The <span id="span1" contenteditable="true">colored items</span> in this paragraph
are <span contenteditable="true">editable</span>.</p>
input
you add on-the-flyYou need to get a reference to the element that you're using for display (a span
, perhaps) and then hook its click
event (or hook the click
event on a parent of the desired element(s)). In the click
event, hide the span
and insert a input[type=text]
alongside it.
Here's a very simple example of using an input
:
window.onload = function() {
document.getElementById('container').onclick = function(event) {
var span, input, text;
// Get the event (handle MS difference)
event = event || window.event;
// Get the root element of the event (handle MS difference)
span = event.target || event.srcElement;
// If it's a span...
if (span && span.tagName.toUpperCase() === "SPAN") {
// Hide it
span.style.display = "none";
// Get its text
text = span.innerHTML;
// Create an input
input = document.createElement("input");
input.type = "text";
input.value = text;
input.size = Math.max(text.length / 4 * 3, 4);
span.parentNode.insertBefore(input, span);
// Focus it, hook blur to undo
input.focus();
input.onblur = function() {
// Remove the input
span.parentNode.removeChild(input);
// Update the span
span.innerHTML = input.value == "" ? " " : input.value;
// Show the span again
span.style.display = "";
};
}
};
};
#container span {
background-color: #ff6;
}
<p id="container">The <span>colored items</span> in this paragraph
are <span>editable</span>.</p>
There I'm hooking the click
on the parent p
element, not the individual spans, because I wanted to have more than one and it's easier to do that. (It's called "event delegation.") You can find the various functions used above in the references I gave at the beginning of the answer.
In this case I used blur
to take the edit down again, but you may wish to have an OK button and/or other triggers (like the Enter key).
Off-topic: You may have noticed in the JavaScript code above that I had to handle a couple of "MS differences" (e.g., things that IE does differently from other browsers), and I've used the old "DOM0" style of event handler where you just assign a function to a property, which isn't ideal, but it avoids my having to handle yet another difference where some versions of IE don't have the DOM2 addEventListener
and so you have to fall back to attachEvent
.
My point here is: You can smooth over browser differences and get a lot of utility functions as well by using a decent JavaScript library like jQuery, Prototype, YUI, Closure, or any of several others. You didn't say you were using any libraries, so I didn't in the above, but there are compelling reasons to use them so you don't have to worry about all the little browser niggles and can just get on with addressing your actual business need.
A trivial example using plain JavaScript would be along the lines of: http://jsfiddle.net/vzxW4/.
document.getElementById('test').onclick = function() {
document.body.removeChild(this);
var input = document.createElement('input');
input.id = 'test';
input.value = this.innerHTML;
document.body.appendChild(input);
input.select();
}
Using a library would save you time and headaches, though. For example, using jQuery: http://jsfiddle.net/vzxW4/1/.
$("#test").click(function() {
var input = $("<input>", { val: $(this).text(),
type: "text" });
$(this).replaceWith(input);
input.select();
});
Can we do it simple guys?
Just keep textbox with readonly property true and some CSS which makes text box looks like span with border.
Then as soon as user clicks on text box remove readonly attribute.
On blur restore the CSS and readonly attributes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With