I'm using jquery.watermark for adding watermarks for html form inputs. I love it, really easy to use as a developer and makes the site easier to use for visitors. Problem is, for some browsers, people are submitting forms with fields that are supposed to be left empty... but they get submitted with the watermark text! That is an absolute dealbreaker problem and I'm going to have to stop using this watermark unfortunately because of it.
Are there any other mechanisms which do not exhibit this behavior, at least not in any modern browser (including IE6+)? I prefer jQuery, but any mechanism will do. I assume javascript is necessary..
UPDATE: I think I'm going to go with jq-watermark, unless there are better mechanisms someone knows about or there's something wrong with this? It looks great:
supports individualized css
supports html5's placeholder attribute as a fallback mechanism, which I was unaware of
uses a mechanism which doesn't allow for submitting watermarks to the server
has an elegant feel which fades the watermark with focus and only removes when entering text
UPDATE 2: Unfortunately, looks like the jq-watermark plugin doesn't actually work well at all... at least not for me and I have a pretty standard setup. Maybe there's a conflict with other javascript, but I doubt it. I really like their feature set, particularly the html5 fallback. In fact, I like the html5 fallback so much that I'm tempted to just forget about a javascript mechanism for this and only have this for html5 browsers. But not even firefox has this html5 feature yet, only safari and chrome as far as I can see :(. That's only 10% or so of my visitors...
UPDATE 3: I've finally been able to get jq-watermark to work well. I've had to add some CSS rules to its classes and adopt some html conventions (like using a div container instead of setting the width on an input element). The reason the html5 fallback mechanism wasn't working and I was experiencing weird behavior was that you can't rely on the automatic application of jq-watermark to all elements with the class jq_watermark, in fact it's harmful to have any elements with that class if you want to use the placeholder attribute. Instead you have to call $(selectors).watermark('placeholder text', {fallback:true});. Kind of sucks because you have to duplicate the placeholder text in that call and on the placeholder attribute. But, of course, you can use jQuery's .each() to read that attribute. Also, on firefox, the fading upon focus looks somewhat bad... but Firefox 4 will have placeholder html5 support, so I'm not too worried. The font changes a little as well frequently when focusing on an input element.
A bit disappointing having wasted a good few hours testing all the solutions out there and having a pretty poor choice for such a simple mechanism. jq-watermark, after tweaking it and your html, is probably the best solution there is.
I built a really simple jQuery plugin for this sort thing, it isn't that difficult. This uses the title attribute for the placeholder text but that is pretty easy to change.
(function($) {
$.fn.egText = function(options) {
options = $.extend({ }, $.fn.egText.defaults, options || { });
var $all = this;
$all.focus(function() {
var $this = $(this);
if(!$this.data(options.dataKey))
$this.data(options.dataKey, 'yes').removeClass(options.egClass).val('');
})
.blur(function() {
var $this = $(this);
if($this.val() == '')
$this.addClass(options.egClass).removeData(options.dataKey).val($this.attr('title'));
else
$this.data(options.dataKey, 'yes');
})
.blur();
$.unique($all.closest('form')).submit(function() {
$all.each(function() {
var $this = $(this);
if(!$this.data(options.dataKey))
$this.val('');
});
return true;
});
};
$.fn.egText.defaults = {
dataKey: 'egText', // The key we use for storing our state with .data(), just in case there are conflicts...
egClass: 'lolite' // The CSS class to add to the <input> when we're displaying the example text.
};
})(jQuery);
You're welcome to use this if it does what you need. I don't know if it works in IE6 but it does work in the latest Firefox, Safari, Opera, Chrome, IE7, and IE8.
This jQuery Watermark plugin does not alter the value of the input fields. So you should be safe using it.
Related
I tried to find a related question but could not find anything that sounded alike.
Im building a small javascript Slider plugin for multiple projects at our company.
Therefore i need to do basic style manipulation on some Elements in the DOM.
I tested this on current Chrome +ChromeOnAndroid, Safari +SafariIOS, Opera +OperaMobile.
When i try to do this on Firefox it seems like the Style attributes dont get touched at all:
Heres the code ( or the fiddle) :
// the html
<div id="testwrapper">
</div>
// the javascript
(function(){
var extend = function(source, additions) {
for (var addition in additions) {
source[addition] = additions[addition];
}
};
var testEl = document.getElementById('testwrapper');
var testStyles = {
width: '150px',
height: '150px',
padding: '5px',
margin: '5px'
};
window.setTimeout(function(){
extend(testEl.style, testStyles);
}, 15000)
}());
It's pretty obvious what im trying to accomplish.
Im taking the style attributes the element has and try to extend them by the ones i give in testStyles.
This seemed very straight forward to me and much easier then writing down all attributes i want to change this way :
testEl.style.width = 'Xpx';
testEl.style.height = 'Ypx';
// and so on
This way it would work in ff but..
that would blow up my code because i will have different conditions were some attributes may change and some may not.
So here comes the Question:
Is there a way to get the same result as in Chrome etc. in Firefox or am I doing something wrong.
Is this way of manipulating the style attribute supported in FF at all?
Thanks for your help.
PS: I dont need anyone telling me to use jQuery instead. Keep that in mind please.
Because objects are passed around by reference, you don't need return source; and you don't need testEl.style = either. Try removing these two things and see if that fixes the problem in Firefox - it probably doesn't like you doing a complete re-assign of the style object ;)
Please check my fiddle at http://jsfiddle.net/7995m/ . In the fiddle, the default text disappears as soon as the text box is clicked. I want the default text to not change till text is written. The following is my code:-
$(".defaultText").focus(function(srcc)
{
if ($(this).val() == $(this)[0].title)
{
$(this).removeClass("defaultTextActive");
$(this).val("");
}
});
$(".defaultText").blur(function()
{
if ($(this).val() == "")
{
$(this).addClass("defaultTextActive");
$(this).val($(this)[0].title);
}
});
$(".defaultText").blur();
This will get you started with using the HTML5 placeholder attribute http://davidwalsh.name/html5-placeholder
It is commonly used in web applications.
If the browser you're targeting doesn't support placeholders, you can create a polyfill using modernizr to support the html5 attribute. Here is a polyfill using jquery https://github.com/mathiasbynens/jquery-placeholder
You can find additional polyfills for placeholders or other html5 attributes here:
https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills
Here is a link to modernizr http://modernizr.com/
After creating the polyfill, the modernizr will detect if the browser rendering the page supports the placeholder attribute and if it doesn't, the polyfill will emulate the behavior. This way, the HTML code isn't polluted with a custom solution and future browsers will be unaffected if they support placeholders.
This is really the best way to go. Creating a custom solution is great in the short-term, but using a polyfill like this helps to avoid potential problems in the long term, such as new browsers not being compatible with the custom solution a year down the road. Using a polyfill to fill in the functionality for the HTML5 attribute will ensure your application won't break in the future while allowing for the same functionality in older browsers. It also aids in the readability of your html code.
Reduce your no.of lines of code,By using placeholder attribute.
Ex
<input type="text" name="first_name" placeholder="Your first name...">
Demo Fiddle
working fiddle
just replace your focus by keydown.Placeholder is a good solution,but IE7,8,9 does not support it.So instead of using some js(there are som polyfills available),I would suggest you to continue with this code itself.
$(".defaultText").keydown(function(srcc)
{
if ($(this).val() == $(this)[0].title)
{
$(this).removeClass("defaultTextActive");
$(this).val("");
}
});
$(".defaultText").blur(function()
{
if ($(this).val() == "")
{
$(this).addClass("defaultTextActive");
$(this).val($(this)[0].title);
}
});
$(".defaultText").blur();
You could use placeholder attribute.
if you really want to achieve this, although it is not quite the standard behaviour use this instead your focus event:
$(".defaultText").keydown(function(srcc)
{
$(this).removeClass("defaultTextActive");
$(this).val("");
});
but definitely use the placeholder tag, which is the right way to go
I've implemented this effect myself several times in raw jquery code, but I want to have it as a plugin. Problem is I don't know what it's called to search for the plugin. Basically, the input field has its label in pale gray inside the field itself. When the user clicks, the gray label disappears. If the user exited the field without typing anything, the gray label returns. Otherwise, whatever the user types stays there. It's really simple, does it have a name, and is there a plugin for it so I could something like
$('#blabla').effectname('Label');
Sorry if this is a stupid question but I'm really blanking out on this one.
It sounds like you're describing a 'placeholder'. This is actually built into HTML 5, and is supported in (as of this writing) WebKit (Chrome + Safari), FireFox 3.7 and above, and IE 9 beta (I think).
Just doing a bit of searching around I found this jQuery plugin - jQuery Placeholder.
Here is one I wrote a long time ago, I am sure it will help.
The function:
function textReplacement(input) {
var originalvalue = input.val();
input.focus(function() {
if ($.trim(input.val()) == originalvalue) {
input.val('').css("color", "#000");
}
});
input.blur(function() {
if ($.trim(input.val()) == '') {
input.val(originalvalue).css("color", "#999");
}
});
}
The usage:
textReplacement($('input#thisID').css("color", "#999"));
Enjoy!
It's called a watermark or placeholder. There is a suitable jQuery plugin I've used with no complaints here. It has all sorts of good stuff (like drag-and-drop support!).
I'm sure you can find many others as well. http://www.google.com/search?q=jQuery+watermark
I know innerHTML is supposedly evil, but I think it's the simplest way to change link text. For example:
<a id="mylink" href="">click me</a>
In JS you can change the text with:
document.getElementById("mylink").innerHTML = new_text;
And in Prototype/jQuery:
$("mylink").innerHTML = new_text;
works fine. Otherwise you have to replace all of the child nodes first and then add a text node. Why bother?
How about
document.getElementById('mylink').firstChild.nodeValue = new_text;
This won't suffer from the problems described by PEZ.
Regarding Triptych's comment and bobince's reply, here's another solution:
var oldLink = document.getElementById('mylink'),
newLink = oldLink.cloneNode(false);
newLink.appendChild(document.createTextNode(new_text));
oldLink.parentNode.replaceChild(newLink, oldLink);
innerHTML is not evil at all. There's nothing wrong with using it, as long as you're aware of the consequences.
For browsers supporting DOM3 you can use textContent:
document.getElementById("mylink").textContent = new_text;
This works in FF(tested in 3), Opera (tested in 9.6) and Chrome (tested in 1) but not in MSIE7 (haven't tested in MSIE8)
Added example
It's not pretty but should work cross browser (tested in win in FF3, Opera9.6, Crome1 and MSIE7)
function replaceTextContent(element,text) {
if (typeof element ==="string") element = document.getElementById(element);
if (!element||element.nodeType!==1) return;
if ("textContent" in element) {
element.textContent = text; //Standard, DOM3
} else if ("innerText" in element) {
element.innerText = text; //Proprietary, Micosoft
} else {
//Older standard, even supported by Microsoft
while (element.childNodes.length) element.removeChild(element.lastChild);
element.appendChild(document.createTextNode(text));
}
}
(updated: added support for Microsofts proprietary innerText)
innerHTML has side effects (like disconnecting existing DOM nodes and rerendering that might be heavy). One needs to be aware of these effects. And anyone maintaining the code will need to be alert to that innerHTML is used or they might run into strange bugs.
Up until a year ago, innerHTML was just a lot faster than manipulating events via the DOM. I haven't checked the latest versions of all major browsers for this myself.
Firefox for example doesn't handle this well. It sometimes only updates the screen to reflect the change. If you query the DOM after the change, it still has the old values.
Example: try to change the value of a textarea via innerHTML, and then post the form. It'll silently post the value that the textarea had before. Think of the catastrophic results that something like that could have.
Maybe it's just some standard addicts who reject the idea of innerHTML.
innerHTML is the practical standard because all browsers implement it though it's not a W3C standard.
Just use it. It works like a charm.
Another option is to have two divs and use .hide() & .show().
Since Flash 10 was introduced, many of the popular 'copy to clipboard' scripts out there have stopped working due to new security restrictions. There is a Flash-only solution here:
http://cfruss.blogspot.com/2009/01/copy-to-clipboard-swf-button-cross.html
...though I'm looking for the ability to trigger the copy function via JS, rather than relying on the user to click on a Flash object to trigger.
For an example of what we currently employ, see:
http://snipt.net/public
Any of the 'copy' links use jQuery's copy plugin here:
http://plugins.jquery.com/project/copy
UPDATE: OK, so I tried ZeroClipboard. At first glance, it looked great. However, the amount of redundant code needed to enable multiple clipboard bindings is unacceptable. In some cases, there will be 40+ instances of text that each have their own 'copy' link. Still looking for a better solution...
That's terrible news, I hadn't even noticed. I use the Flash trick extensively too. As far as I know that was the only way to get copy to work without having to install some other plugin (besides the ubiquitous Flash) due to browser security concerns.
Update: After much panic, and a few google searches, I stumbled on http://code.google.com/p/zeroclipboard/ which provides a Flash 10 compatible trick to get the copy to work once again. Now to go around updating websites...
This solution only works for keystrokes that would invoke the desired operation. It works by moving the user's cursor into a textarea element before the user finishes the relevant keystroke. It only works for text input. I've got this working in firefox and chrome. IE can use the clipboardData object (which is preferable to this hack).
In your html somewhere you should create a textarea element with arbitrarily large rows and cols attributes. The 'clipboard-textarea' element will be the holding area for the pasted and copied data. I hide the element using some style attributes.
The script:
var desiredClipboardContents = 'It works';
function onCopyKeyPressed() {
// The trick here is to populate the textarea with
// the text you want copied before the user releases
// the copy keystroke.
var textarea = document.getElementById('clipboard-textarea');
textarea.value = desiredClipboardContents;
textarea.focus();
textarea.select();
}
function onPasteKeyPressed() {
var textarea = document.getElementById('clipboard-textarea');
textarea.value = '';
textarea.focus();
// The trick here is to delay slurping the content
// that arrives in the textarea element until after
// the paste keystroke is completed. The 750 ms timeout
// provides the necessary delay.
setTimeout("finishedPasting", 750);
}
function finishedPasting() {
var textarea = document.getElementById('clipboard-textarea');
alert("Received from clipboard-paste: " + textarea.value);
}