1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | (function($) {
|
16 | var debug = false,
|
17 | animId;
|
18 | function showPlaceholderIfEmpty(input,options) {
|
19 | if( input.val() === '' ){
|
20 | input.data('placeholder').removeClass(options.hideClass);
|
21 | }else{
|
22 | input.data('placeholder').addClass(options.hideClass);
|
23 | }
|
24 | }
|
25 | function hidePlaceholder(input,options){
|
26 | input.data('placeholder').addClass(options.hideClass);
|
27 | }
|
28 | function positionPlaceholder(placeholder,input){
|
29 | var ta = input.is('textarea');
|
30 | var pt = parseFloat(input.css('padding-top'));
|
31 | var pl = parseFloat(input.css('padding-left'));
|
32 |
|
33 |
|
34 | var offset = input.offset();
|
35 | if (pt) {
|
36 | offset.top += pt;
|
37 | }
|
38 | if (pl) {
|
39 | offset.left += pl;
|
40 | }
|
41 |
|
42 | placeholder.css({
|
43 | width : input.innerWidth()-(ta ? 20 : 4),
|
44 | height : input.innerHeight()-6,
|
45 | lineHeight : input.css('line-height'),
|
46 | whiteSpace : ta ? 'normal' : 'nowrap',
|
47 | overflow : 'hidden'
|
48 | }).offset(offset);
|
49 | }
|
50 | function startFilledCheckChange(input,options){
|
51 | var val = input.val();
|
52 | (function checkloop(){
|
53 | animId = requestAnimationFrame(checkloop);
|
54 | if(input.val() !== val){
|
55 | hidePlaceholder(input,options);
|
56 | stopCheckChange();
|
57 | startEmptiedCheckChange(input,options);
|
58 | }
|
59 | }());
|
60 | }
|
61 | function startEmptiedCheckChange(input,options){
|
62 | (function checkloop(){
|
63 | animId = requestAnimationFrame(checkloop);
|
64 | showPlaceholderIfEmpty(input,options);
|
65 | }());
|
66 | }
|
67 | function stopCheckChange(){
|
68 | if (window.cancelAnimationFrame) {
|
69 | cancelAnimationFrame(animId);
|
70 | }
|
71 | }
|
72 | function log(msg){
|
73 | if(debug && window.console && window.console.log){
|
74 | window.console.log(msg);
|
75 | }
|
76 | }
|
77 |
|
78 | $.fn.placeHolder = function(config) {
|
79 | log('init placeHolder');
|
80 | var o = this;
|
81 | var l = $(this).length;
|
82 | this.options = $.extend({
|
83 | className: 'placeholder',
|
84 | visibleToScreenreaders : true,
|
85 | visibleToScreenreadersHideClass : 'placeholder-hide-except-screenreader',
|
86 | visibleToNoneHideClass : 'placeholder-hide',
|
87 | hideOnFocus : false,
|
88 | removeLabelClass : 'visuallyhidden',
|
89 | hiddenOverrideClass : 'visuallyhidden-with-placeholder',
|
90 | forceHiddenOverride : true,
|
91 | forceApply : false,
|
92 | autoInit : true
|
93 | }, config);
|
94 | this.options.hideClass = this.options.visibleToScreenreaders ? this.options.visibleToScreenreadersHideClass : this.options.visibleToNoneHideClass;
|
95 | return $(this).each(function(index) {
|
96 | var input = $(this),
|
97 | text = input.attr('placeholder'),
|
98 | id = input.attr('id'),
|
99 | label,placeholder,titleNeeded,polyfilled;
|
100 |
|
101 | function onFocusIn() {
|
102 | if(!o.options.hideOnFocus && window.requestAnimationFrame){
|
103 | startFilledCheckChange(input,o.options);
|
104 | }else{
|
105 | hidePlaceholder(input,o.options);
|
106 | }
|
107 | }
|
108 |
|
109 | if(text === "" || text === undefined) {
|
110 | text = input[0].attributes["placeholder"].value;
|
111 | }
|
112 | label = input.closest('label');
|
113 | input.removeAttr('placeholder');
|
114 | if(!label.length && !id){
|
115 | log('the input element with the placeholder needs an id!');
|
116 | return;
|
117 | }
|
118 | label = label.length ? label : $('label[for="'+id+'"]').first();
|
119 | if(!label.length){
|
120 | log('the input element with the placeholder needs a label!');
|
121 | return;
|
122 | }
|
123 | polyfilled = $(label).find('.placeholder');
|
124 | if(polyfilled.length) {
|
125 |
|
126 | positionPlaceholder(polyfilled,input);
|
127 | polyfilled.text(text);
|
128 | return input;
|
129 | }
|
130 | if(label.hasClass(o.options.removeLabelClass)){
|
131 | label.removeClass(o.options.removeLabelClass)
|
132 | .addClass(o.options.hiddenOverrideClass);
|
133 | }
|
134 |
|
135 | placeholder = $('<span>').addClass(o.options.className).text(text).appendTo(label);
|
136 |
|
137 | titleNeeded = (placeholder.width() > input.width());
|
138 | if(titleNeeded){
|
139 | placeholder.attr('title',text);
|
140 | }
|
141 | positionPlaceholder(placeholder,input);
|
142 | input.data('placeholder',placeholder);
|
143 | placeholder.data('input',input);
|
144 | placeholder.click(function(){
|
145 | $(this).data('input').focus();
|
146 | });
|
147 | input.focusin(onFocusIn);
|
148 | input.focusout(function(){
|
149 | showPlaceholderIfEmpty($(this),o.options);
|
150 | if(!o.options.hideOnFocus){
|
151 | stopCheckChange();
|
152 | }
|
153 | });
|
154 | showPlaceholderIfEmpty(input,o.options);
|
155 |
|
156 |
|
157 | $(document).bind("fontresize resize", function(){
|
158 | positionPlaceholder(placeholder,input);
|
159 | });
|
160 |
|
161 |
|
162 | if($.event.special.resize){
|
163 | $("textarea").bind("resize", function(event){
|
164 | if ($(this).is(":visible")) {
|
165 | positionPlaceholder(placeholder,input);
|
166 | }
|
167 | event.stopPropagation();
|
168 | event.preventDefault();
|
169 | });
|
170 | }else{
|
171 |
|
172 | $("textarea").css('resize','none');
|
173 | }
|
174 |
|
175 | if(index >= l-1 && typeof $.attrHooks !== 'undefined'){
|
176 | $.attrHooks.placeholder = {
|
177 | get: function(elem) {
|
178 | if (elem.nodeName.toLowerCase() === 'input' || elem.nodeName.toLowerCase() === 'textarea') {
|
179 | if( $(elem).data('placeholder') ){
|
180 |
|
181 | return $( $(elem).data('placeholder') ).text();
|
182 | }else{
|
183 |
|
184 | return $(elem)[0].placeholder;
|
185 | }
|
186 | }else{
|
187 | return undefined;
|
188 | }
|
189 | },
|
190 | set: function(elem, value){
|
191 | return $( $(elem).data('placeholder') ).text(value);
|
192 | }
|
193 | };
|
194 | }
|
195 |
|
196 | if (input.is(":focus")) {
|
197 | onFocusIn();
|
198 | }
|
199 | });
|
200 |
|
201 |
|
202 |
|
203 | };
|
204 | $(function(){
|
205 | var config = window.placeHolderConfig || {};
|
206 | if(config.autoInit === false){
|
207 | log('placeholder:abort because autoInit is off');
|
208 | return;
|
209 | }
|
210 | if(('placeholder' in $('<input>')[0] || 'placeHolder' in $('<input>')[0]) && !config.forceApply){
|
211 | log('placeholder:abort because browser has native support');
|
212 | return;
|
213 | }
|
214 | $('input[placeholder], textarea[placeholder]').placeHolder(config);
|
215 | });
|
216 | }(jQuery));
|