From 79b8a27ba0511c5e1934621adbf8a146fff632ed Mon Sep 17 00:00:00 2001 From: raghu Date: Tue, 25 Sep 2012 16:39:32 +0530 Subject: [PATCH] A Polyfill for Placeholders added to the contacts_rework branch --- index.php | 1 + js/placeholder.polyfill.jquery.js | 212 ++++++++++++++++++++++++++++++ 2 files changed, 213 insertions(+) create mode 100644 js/placeholder.polyfill.jquery.js diff --git a/index.php b/index.php index 2a3be9da..490d6de9 100644 --- a/index.php +++ b/index.php @@ -51,6 +51,7 @@ OCP\Util::addscript('', 'jquery.multiselect'); OCP\Util::addscript('', 'oc-vcategories'); OCP\Util::addscript('contacts', 'app'); OCP\Util::addscript('contacts', 'modernizr'); +OCP\Util::addscript('contacts', 'placeholder.polyfill.jquery'); OCP\Util::addscript('contacts', 'expanding'); OCP\Util::addscript('contacts', 'jquery.combobox'); OCP\Util::addscript('files', 'jquery.fileupload'); diff --git a/js/placeholder.polyfill.jquery.js b/js/placeholder.polyfill.jquery.js new file mode 100644 index 00000000..16969eb8 --- /dev/null +++ b/js/placeholder.polyfill.jquery.js @@ -0,0 +1,212 @@ +/** +* HTML5 placeholder polyfill +* @requires jQuery - tested with 1.6.2 but might as well work with older versions +* +* code: https://github.com/ginader/HTML5-placeholder-polyfill +* please report issues at: https://github.com/ginader/HTML5-placeholder-polyfill/issues +* +* Copyright (c) 2012 Dirk Ginader (ginader.de) +* Dual licensed under the MIT and GPL licenses: +* http://www.opensource.org/licenses/mit-license.php +* http://www.gnu.org/licenses/gpl.html +* +* Version: 2.0.3 +* +* History: +* * 1.0 initial release +* * 1.1 added support for multiline placeholders in textareas +* * 1.2 Allow label to wrap the input element by noah https://github.com/ginader/HTML5-placeholder-polyfill/pull/1 +* * 1.3 New option to read placeholder to Screenreaders. Turned on by default +* * 1.4 made placeholder more rubust to allow labels being offscreen + added minified version of the 3rd party libs +* * 1.5 emptying the native placeholder to prevent double rendering in Browsers with partial support +* * 1.6 optional reformat when a textarea is being resized - requires http://benalman.com/projects/jquery-resize-plugin/ +* * 1.7 feature detection is now included in the polyfill so you can simply include it without the need for Modernizr +* * 1.8 replacing the HTML5 Boilerplate .visuallyhidden technique with one that still allows the placeholder to be rendered +* * 1.8.1 bugfix for implicit labels +* * 1.9 New option "hideOnFocus" which, if set to false will mimic the behavior of mobile safari and chrome (remove label when typed instead of onfocus) +* * 1.9.1 added reformat event on window resize +* * 1.9.2 more flexible way to "fix" labels that are hidden using clip() thanks to grahambates: https://github.com/ginader/HTML5-placeholder-polyfill/issues/12 +* * 2.0 new easier configuration technique and new options forceApply and AutoInit and support for setters and getters +* * 2.0.1 changed check for empty field so a space character is no longer ignored +* * 2.0.2 allow rerun of the placeholder() to cover generated elements - existing polyfilled placeholder will be repositioned. Fixing: https://github.com/ginader/HTML5-placeholder-polyfill/issues/15 +* * 2.0.3 turn debugging of for production. fix https://github.com/ginader/HTML5-placeholder-polyfill/issues/18 +*/ + +(function($) { + var debug = false, + animId; + function showPlaceholderIfEmpty(input,options) { + if( input.val() === '' ){ + input.data('placeholder').removeClass(options.hideClass); + }else{ + input.data('placeholder').addClass(options.hideClass); + } + } + function hidePlaceholder(input,options){ + input.data('placeholder').addClass(options.hideClass); + } + function positionPlaceholder(placeholder,input){ + var ta = input.is('textarea'); + placeholder.css({ + width : input.innerWidth()-(ta ? 20 : 4), + height : input.innerHeight()-6, + lineHeight : input.css('line-height'), + whiteSpace : ta ? 'normal' : 'nowrap', + overflow : 'hidden' + }).offset(input.offset()); + } + function startFilledCheckChange(input,options){ + var input = input, + val = input.val(); + (function checkloop(){ + animId = requestAnimationFrame(checkloop); + if(input.val() != val){ + hidePlaceholder(input,options); + stopCheckChange(); + startEmptiedCheckChange(input,options); + } + })(); + } + function startEmptiedCheckChange(input,options){ + var input = input, + val = input.val(); + (function checkloop(){ + animId = requestAnimationFrame(checkloop); + showPlaceholderIfEmpty(input,options); + })(); + } + function stopCheckChange(){ + cancelAnimationFrame(animId); + } + function log(msg){ + if(debug && window.console && window.console.log){ + window.console.log(msg); + } + } + + $.fn.placeHolder = function(config) { + log('init placeHolder'); + var o = this; + var l = $(this).length; + this.options = $.extend({ + className: 'placeholder', // css class that is used to style the placeholder + visibleToScreenreaders : true, // expose the placeholder text to screenreaders or not + visibleToScreenreadersHideClass : 'placeholder-hide-except-screenreader', // css class is used to visually hide the placeholder + visibleToNoneHideClass : 'placeholder-hide', // css class used to hide the placeholder for all + hideOnFocus : false, // either hide the placeholder on focus or on type + removeLabelClass : 'visuallyhidden', // remove this class from a label (to fix hidden labels) + hiddenOverrideClass : 'visuallyhidden-with-placeholder', // replace the label above with this class + forceHiddenOverride : true, // allow the replace of the removeLabelClass with hiddenOverrideClass or not + forceApply : false, // apply the polyfill even for browser with native support + autoInit : true // init automatically or not + }, config); + this.options.hideClass = this.options.visibleToScreenreaders ? this.options.visibleToScreenreadersHideClass : this.options.visibleToNoneHideClass; + return $(this).each(function(index) { + var input = $(this), + text = input.attr('placeholder'), + id = input.attr('id'), + label,placeholder,titleNeeded,polyfilled; + label = input.closest('label'); + input.removeAttr('placeholder'); + if(!label.length && !id){ + log('the input element with the placeholder needs an id!'); + return; + } + label = label.length ? label : $('label[for="'+id+'"]').first(); + if(!label.length){ + log('the input element with the placeholder needs a label!'); + return; + } + polyfilled = $(label).find('.placeholder'); + if(polyfilled.length) { + //log('the input element already has a polyfilled placeholder!'); + positionPlaceholder(polyfilled,input); + return input; + } + + if(label.hasClass(o.options.removeLabelClass)){ + label.removeClass(o.options.removeLabelClass) + .addClass(o.options.hiddenOverrideClass); + } + + placeholder = $(''+text+'').appendTo(label); + + titleNeeded = (placeholder.width() > input.width()); + if(titleNeeded){ + placeholder.attr('title',text); + } + positionPlaceholder(placeholder,input); + input.data('placeholder',placeholder); + placeholder.data('input',placeholder); + placeholder.click(function(){ + $(this).data('input').focus(); + }); + input.focusin(function() { + if(!o.options.hideOnFocus && window.requestAnimationFrame){ + startFilledCheckChange(input,o.options); + }else{ + hidePlaceholder(input,o.options); + } + }); + input.focusout(function(){ + showPlaceholderIfEmpty($(this),o.options); + if(!o.options.hideOnFocus && window.cancelAnimationFrame){ + stopCheckChange(); + } + }); + showPlaceholderIfEmpty(input,o.options); + + // reformat on window resize and optional reformat on font resize - requires: http://www.tomdeater.com/jquery/onfontresize/ + $(document).bind("fontresize resize", function(){ + positionPlaceholder(placeholder,input); + }); + + // optional reformat when a textarea is being resized - requires http://benalman.com/projects/jquery-resize-plugin/ + if($.event.special.resize){ + $("textarea").bind("resize", function(e){ + positionPlaceholder(placeholder,input); + }); + }else{ + // we simply disable the resizeablilty of textareas when we can't react on them resizing + $("textarea").css('resize','none'); + } + + if(index >= l-1){ + $.attrHooks.placeholder = { + get: function(elem) { + if (elem.nodeName.toLowerCase() == 'input' || elem.nodeName.toLowerCase() == 'textarea') { + if( $(elem).data('placeholder') ){ + // has been polyfilled + return $( $(elem).data('placeholder') ).text(); + }else{ + // native / not yet polyfilled + return $(elem)[0].placeholder; + } + + }else{ + return undefined; + } + }, + set: function(elem, value){ + return $( $(elem).data('placeholder') ).text(value); + } + }; + } + }); + + + + }; + $(function(){ + var config = window.placeHolderConfig || {}; + if(config.autoInit === false){ + log('placeholder:abort because autoInit is off'); + return + } + if('placeholder' in $('')[0] && !config.forceApply){ // don't run the polyfill when the browser has native support + log('placeholder:abort because browser has native support'); + return; + } + $('input[placeholder], textarea[placeholder]').placeHolder(config); + }); +})(jQuery); \ No newline at end of file