{"id":170,"date":"2009-01-02T01:08:40","date_gmt":"2009-01-02T07:08:40","guid":{"rendered":"http:\/\/bililite.nfshost.com\/blog\/?p=170"},"modified":"2015-03-25T10:56:45","modified_gmt":"2015-03-25T16:56:45","slug":"new-ui-widgets-textpopup-and-hebrewkeyboard","status":"publish","type":"post","link":"https:\/\/bililite.com\/blog\/2009\/01\/02\/new-ui-widgets-textpopup-and-hebrewkeyboard\/","title":{"rendered":"New UI widgets: <code>textpopup<\/code> and <code>hebrewKeyboard<\/code>"},"content":{"rendered":"<p>Last modified 2011-10-28; added <code>box<\/code> option<p>\r\n<script src=\"\/inc\/bililiteRange.js\" type=\"text\/javascript\"><\/script>\r\n<script src=\"\/inc\/jquery.sendkeys.js\" type=\"text\/javascript\"><\/script>\r\n<script src=\"\/inc\/jquery.ui.subclass.js\" type=\"text\/javascript\"><\/script>\r\n<script src=\"\/inc\/jquery.textpopup.js\" type=\"text\/javascript\"><\/script>\r\n<p>The Hebrew pop-up keyboard on the <a href=\"http:\/\/youngisrael-stl.org#q\">YI site search box<\/a> was always hard-coded and kind of obtrusive, so I wanted to make a jQuery plugin to add a keyboard to any <code>input type=\"text\"<\/code> or <code>textarea<\/code>. To make it more flexible, I factored it into a general-purpose popup widget and the keyboard itself.<\/p>\r\n\r\n<p><a href=\"\/inc\/jquery.textpopup.js\">Download the code<\/a>.<\/p>\r\n<!--more-->\r\n<h4><code>$.ui.textpopup<\/code><\/h4>\r\n<p>The <code>$.ui.textpopup<\/code> widget is meant to be a <a href=\"\/blog\/extending-jquery-ui-widgets\/\">base class<\/a> for real popup widgets. It requires <a href=\"http:\/\/ui.jquery.com\">jQuery UI 1.7<\/a> and <a href=\"\/inc\/jquery.ui.subclass.js\">my subclassing code<\/a>. The subclass needs to override the <code>_fill<\/code> method to fill the box with the desired controls. For example:<\/p>\r\n<pre><code class=\"language-html demo\">\r\n&lt;div id=\"example1\"&gt;\r\n\tExample 1: &lt;input&gt;\r\n&lt;\/div&gt;\r\n<\/code><\/pre>\r\n<pre><code class=\"language-javascript demo\">\r\n$.widget(\"ui.helloWorld\", $.bililite.textpopup, {\r\n\t_fill: function(box){\r\n\t\tvar self = this;\r\n\t\t$('&lt;input type=\"button\" value=\"Hello, World\" \/&gt;').appendTo(box).click(function() {\r\n\t\t\tself.element.val('Hello, World')\r\n\t\t});\r\n\t}\r\n});\r\n\r\n$('#example1 input').helloWorld();\r\n<\/code><\/pre>\r\n<p><code>textpopup<\/code> has the following options:<\/p>\r\n<pre><code><dl>\r\n<dt>show {Function}<\/dt>\r\n<dd>Called to show the popup; <em>this<\/em> is set to the popup div and \r\nthe <a href=\"#speed\">speed<\/a> is the argument(s) (this is meant to be a function called like <em>$.fn.show<\/em>). <\/dd>\r\n<dt>hide {Function}<\/dt>\r\n<dd>Called to show the popup; <em>this<\/em> is set to the popup div and\r\nthe <a href=\"#speed\">speed<\/a> is the argument(s) (this is meant to be a function called like <em>$.fn.hide<\/em>)<\/dd>\r\n<dt>box {jQuery object|undefined}<\/dt>\r\n<dd>Element to contain the popup box. If undefined, a new, absolutely-positioned &lt;div&gt; is created. Set this to create an \"inline\" popup.<\/dd>\r\n<dt>shown {Function}<\/dt>\r\n<dd>Callback (<em>this<\/em> is set to the input element) called when <em>show<\/em> is completed\r\nAlso available as the custom event <em>textpopupshown<\/em><\/dd>\r\n<dt>hidden {Function}<\/dt>\r\n<dd>Callback (<em>this<\/em> is set to the input element) called when <em>hide<\/em> is completed\r\nAlso available as the custom event <em>textpopuphidden<\/em><\/dd>\r\n<dt>created {Function}<\/dt>\r\n<dd>Callback (<em>this<\/em> is set to the input element) called when the popup is created. Signature is\r\nFunction(<a href=\"http:\/\/docs.jquery.com\/Events\/jQuery.Event\">Event<\/a>, box {jQuery object})\r\nAlso available as the custom event <em>textpopupcreated<\/em><\/dd>\r\n<dt id=\"speed\">speed {String|Number|Array}<\/dt>\r\n<dd>Parameter to pass to show\/hide above. If it is an array, it is passed with <a href=\"https:\/\/developer.mozilla.org\/en\/JavaScript\/Reference\/Global_Objects\/function\/apply\">apply<\/a>\r\nso you can pass multiple arguments.\r\n For instance, to use <a href=\"http:\/\/docs.jquery.com\/UI\/Effects\">jQuery UI effects<\/a>, use <code class=\"language-javascript\">speed: ['slide', {direction: 'right'}, 'slow']<\/code><\/dd>\r\n<dt>hideOnOutsideClick {Boolean}<\/dt>\r\n<dd>true to hide the popup if the mouse is clicked outside the popup or the target element<\/dd>\r\n<dt>position {'tl'|'lt|'bl'|'lb'|'tr'|'rt'|'br'|'rb'|Object}<\/dt>\r\n<dd>String that indicates where to position the popup\r\n  relative to the textbox. 'tl' means on top of the input box, aligned to the left edge;\r\n  'lt' means on the left of the input box aligned to the top edge; similarly 'b' for bottom\r\n and 'r' for right. If an object is passed, it will be passed unchanged to <a href=\"http:\/\/docs.jquery.com\/UI\/Position#options\"><code>position<\/code><\/a>, except that if the <code>of<\/code> option\r\n is not specified, it will be set to <code class=\"language-javascript\">this.element<\/code><\/dd>\r\n<dt>trigger {'self'|null|String|jQuery|DOM element}<\/dt>\r\n<dd>Element(s) to use as the trigger to show the\r\n  popup. uses the code \r\n    if (trigger == 'self') trigger = self.element; if (trigger) $(trigger).click(function(){self.show()})<\/dd>\r\n<dt>class {String}<\/dt>\r\n<dd>class to be added to the popup box<\/dd>\r\n<\/dl><\/code><\/pre>\r\n<pre><code class=\"language-javascript\">\r\n\/\/ Default values\r\n$.ui.textpopup.prototype.options = {\r\n\tshow: $.fn.show,\r\n\thide: $.fn.hide,\r\n\tspeed: 'slow',\r\n\thideOnOutsideClick: true,\r\n\tposition: 'tl',\r\n\ttrigger: 'self',\r\n\t'class': 'ui-textpopup-box'\r\n};\r\n<\/code><\/pre>\r\n<p>Note that the event names prepend the actual name of the widget, so if you subclass <code>textpopup<\/code>, use the new name. Thus <code class=\"language-javascript\">$.ui.textpopup.subclass('foo'); $(selector).foo().bind('fooshown', function(){});<\/code>.<\/p>\r\n\r\n<p>Examples of position:<\/p>\r\n<pre><code class=\"language-html demo\">\r\n&lt;div id=\"example2\"&gt;\r\n&lt;div&gt;&lt;strong&gt;tl&lt;\/strong&gt;&lt;input\/&gt;&lt;\/div&gt;\r\n&lt;div&gt;&lt;strong&gt;lt&lt;\/strong&gt;&lt;input\/&gt;&lt;\/div&gt;\r\n&lt;div&gt;&lt;strong&gt;br&lt;\/strong&gt;&lt;input\/&gt;&lt;\/div&gt;\r\n&lt;div&gt;&lt;strong&gt;rb&lt;\/strong&gt;&lt;input\/&gt;&lt;\/div&gt;\r\n&lt;div&gt;&lt;strong&gt;lb&lt;\/strong&gt;&lt;input\/&gt;&lt;\/div&gt;\r\n&lt;\/div&gt;\r\n<\/code><\/pre>\r\n<pre><code class=\"language-javascript demo\">\r\n$('#example2 input').each(function(){\r\n  $(this).css({height: '50px'}).helloWorld({position: $(this).prev().text()});\r\n});\r\n\r\n$('#example2 div, #example2 span').css({margin:'2px'});\r\n<\/code><\/pre>\r\n<pre><code class=\"language-html demo\">\r\n&lt;div id=\"example3\"&gt;\r\n&lt;div&gt;&lt;strong&gt;Slide Right&lt;\/strong&gt;&lt;input\/&gt;&lt;\/div&gt;\r\n&lt;\/div&gt;\r\n<\/code><\/pre>\r\n<pre><code class=\"language-javascript demo\">\r\n$('#example3 input').each(function(){\r\n  $(this).css({height: '50px'}).helloWorld({\r\n    speed: ['slide', {direction: 'right'}, 'slow'],\r\n    position: {my: 'bottom', at: 'top'}\r\n  });\r\n});\r\n\r\n$('#example3 div, #example3 span').css({margin:'2px'});\r\n<\/code><\/pre>\r\n<p>Callable functions include (obviously, use the name of the subclass you created):<\/p>\r\n<pre><code><dl>\r\n<dt>$(...).textpopup('show') and $(...).helloWorld('hide')<\/dt>\r\n<dd>show and hide the popup. These return the jQuery object.<\/dd>\r\n<dt>$(...).textpopup('box')<\/dt>\r\n<dd>returns the popup div as a single-element jQuery object<\/dd>\r\n<dt>$(...).textpopup('position')<\/dt>\r\n<dd>repositions the popup. Use this if the size of the popup changes. Returns the jQuery object.<\/dd>\r\n<\/dl><\/code><\/pre>\r\n<p>Example of using callable functions and the trigger option:<\/p>\r\n<pre><code class=\"language-html demo\">\r\n&lt;div id=\"example4\"&gt;\r\n\t&lt;label&gt;Example 4 hidden:&lt;\/label&gt;&lt;br\/&gt;&lt;input id=\"input4\"&gt;\r\n&lt;\/div&gt;\r\n<\/code><\/pre>\r\n<pre><code class=\"language-javascript demo\">\r\n$('&lt;span&gt; Hide &lt;\/span&gt;').css({outline: 'black dotted thin'}).insertAfter('#input4').click (function(){\r\n  $('#input4').helloWorld('hide');\r\n});\r\nvar triggerElement = $('&lt;span&gt; Show &lt;\/span&gt;').css({outline: 'black dotted thin'}).insertAfter('#input4');\r\n$('#input4').helloWorld({\r\n  hideOnOutsideClick: false,\r\n  position: {my: 'right', at: 'left'},\r\n  speed: ['fold', {}, 1000],\r\n  trigger: triggerElement,\r\n  shown: function() {$('#example4 label').text('Example 4 visible:')},\r\n  hidden: function() {$('#example4 label').text('Example 4 hidden:')}\r\n});\r\n$('#input4').helloWorld('box').css('border', '2px outset #eee');\r\n<\/code><\/pre>\r\n\r\n<h4 id=\"hebrewkeyboard\"><code>$.ui.hebrewKeyboard<\/code><\/h4>\r\n<p>The <code>$.bililite.hebrewKeyboard<\/code> is just a subclass of <code>$.bililite.textpopup<\/code> that uses AJAX to load a Hebrew keyboard into the popup div and <a href=\"\/blog\/2008\/08\/20\/the-fnsendkeys-plugin\/\"><code>$.fn.sendkeys<\/code><\/a> to insert the Hebrew characters.<\/p>\r\n<p>Inspired by Ilya Lebedev's <a href=\"\/blog\/2011\/01\/03\/new-hebrew-keyboard\/\">VirtualKeyboard<\/a>, the plugin also catches keystrokes to allow typing directly in Hebrew, using the CapsLock key as a toggle between English and Hebrew keyboards.<\/p>\r\n<pre><code class=\"language-html demo\">\r\n&lt;div id=\"example5\"&gt;\r\n\tExample 5 (Hebrew): &lt;input id=\"input5\"&gt;\r\n&lt;\/div&gt;\r\n<\/code><\/pre>\r\n<pre><code class=\"language-javascript demo\">\r\n$('#input5').hebrewKeyboard();\r\n<\/code><\/pre>\r\n<p>It works with <code>contenteditable=\"true\"<\/code> elements as well:<\/p>\r\n<pre><code class=\"language-html demo\">\r\n&lt;div id=\"example6\" contenteditable=\"true\" &gt;\r\n\tExample 6 (Hebrew): Edit me!\r\n&lt;\/div&gt;\r\n<\/code><\/pre>\r\n<pre><code class=\"language-javascript demo\">\r\n$('#example6').hebrewKeyboard();\r\n<\/code><\/pre>\r\n\r\n\r\n<p>Download the <a href=\"http:\/\/github.bililite.com\/flexcal\/keyboard.html\">html<\/a> for the keyboard.<\/p>\r\n<p>The keyboard uses <a href=\"http:\/\/www.alistapart.com\/articles\/sprites\/\">CSS sprites<\/a> and a single image:<\/p>\r\n<div><img decoding=\"async\" src=\"http:\/\/github.bililite.com\/flexcal\/kb.gif\" alt=\"hebrew keyboard\"\/><\/div>\r\n<p>to simulate the keypresses. IE (of course) can't handle a:hover styling unless there's a real link,\r\nso each key has a pretend <code>href=\"javascript:insertLetter\"<\/code>, but really uses <code class=\"language-javascript\">$('a').click(function(){sendkeys...return false;})<\/code><\/p>","protected":false},"excerpt":{"rendered":"Last modified 2011-10-28; added box option The Hebrew pop-up keyboard on the YI site search box was always hard-coded and kind of obtrusive, so I wanted to make a jQuery plugin to add a keyboard to any input type=\"text\" or textarea. To make it more flexible, I factored it into a general-purpose popup widget and [&hellip;]","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,19],"tags":[],"_links":{"self":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/170"}],"collection":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/comments?post=170"}],"version-history":[{"count":89,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/170\/revisions"}],"predecessor-version":[{"id":3533,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/170\/revisions\/3533"}],"wp:attachment":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/media?parent=170"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/categories?post=170"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/tags?post=170"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}