add a context menu package
authorMarcin Koziej <marcin.koziej@nowoczesnapolska.org.pl>
Wed, 9 May 2012 09:13:16 +0000 (11:13 +0200)
committerMarcin Koziej <marcin.koziej@nowoczesnapolska.org.pl>
Wed, 9 May 2012 09:13:16 +0000 (11:13 +0200)
redakcja/static/contextmenu/images/cut.png [new file with mode: 0755]
redakcja/static/contextmenu/images/door.png [new file with mode: 0755]
redakcja/static/contextmenu/images/page_white_copy.png [new file with mode: 0755]
redakcja/static/contextmenu/images/page_white_delete.png [new file with mode: 0755]
redakcja/static/contextmenu/images/page_white_edit.png [new file with mode: 0755]
redakcja/static/contextmenu/images/page_white_paste.png [new file with mode: 0755]
redakcja/static/contextmenu/index.html [new file with mode: 0644]
redakcja/static/contextmenu/jquery.contextMenu.css [new file with mode: 0755]
redakcja/static/contextmenu/jquery.contextMenu.js [new file with mode: 0755]
redakcja/static/contextmenu/jquery.ui.position.js [new file with mode: 0755]

diff --git a/redakcja/static/contextmenu/images/cut.png b/redakcja/static/contextmenu/images/cut.png
new file mode 100755 (executable)
index 0000000..f215d6f
Binary files /dev/null and b/redakcja/static/contextmenu/images/cut.png differ
diff --git a/redakcja/static/contextmenu/images/door.png b/redakcja/static/contextmenu/images/door.png
new file mode 100755 (executable)
index 0000000..369fc46
Binary files /dev/null and b/redakcja/static/contextmenu/images/door.png differ
diff --git a/redakcja/static/contextmenu/images/page_white_copy.png b/redakcja/static/contextmenu/images/page_white_copy.png
new file mode 100755 (executable)
index 0000000..a9f31a2
Binary files /dev/null and b/redakcja/static/contextmenu/images/page_white_copy.png differ
diff --git a/redakcja/static/contextmenu/images/page_white_delete.png b/redakcja/static/contextmenu/images/page_white_delete.png
new file mode 100755 (executable)
index 0000000..af1ecaf
Binary files /dev/null and b/redakcja/static/contextmenu/images/page_white_delete.png differ
diff --git a/redakcja/static/contextmenu/images/page_white_edit.png b/redakcja/static/contextmenu/images/page_white_edit.png
new file mode 100755 (executable)
index 0000000..b93e776
Binary files /dev/null and b/redakcja/static/contextmenu/images/page_white_edit.png differ
diff --git a/redakcja/static/contextmenu/images/page_white_paste.png b/redakcja/static/contextmenu/images/page_white_paste.png
new file mode 100755 (executable)
index 0000000..5b2cbb3
Binary files /dev/null and b/redakcja/static/contextmenu/images/page_white_paste.png differ
diff --git a/redakcja/static/contextmenu/index.html b/redakcja/static/contextmenu/index.html
new file mode 100644 (file)
index 0000000..f099c95
--- /dev/null
@@ -0,0 +1,200 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+\r
+       <head>\r
+               <title>jQuery Context Menu Plugin Demo</title>\r
+               <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />\r
+               \r
+               <style type="text/css">\r
+                       BODY,\r
+                       HTML {\r
+                               padding: 0px;\r
+                               margin: 0px;\r
+                       }\r
+                       BODY {\r
+                               font-family: Verdana, Arial, Helvetica, sans-serif;\r
+                               font-size: 11px;\r
+                               background: #FFF;\r
+                               padding: 15px;\r
+                       }\r
+                       \r
+                       H1 {\r
+                               font-family: Georgia, serif;\r
+                               font-size: 20px;\r
+                               font-weight: normal;\r
+                       }\r
+                       \r
+                       H2 {\r
+                               font-family: Georgia, serif;\r
+                               font-size: 16px;\r
+                               font-weight: normal;\r
+                               margin: 0px 0px 10px 0px;\r
+                       }\r
+                       \r
+                       #myDiv {\r
+                               width: 150px;\r
+                               border: solid 1px #2AA7DE;\r
+                               background: #6CC8EF;\r
+                               text-align: center;\r
+                               padding: 4em .5em;\r
+                               margin: 1em;\r
+                               float: left;\r
+                       }\r
+                       \r
+                       #myList {\r
+                               margin: 1em;\r
+                               float: left;\r
+                       }\r
+                       \r
+                       #myList UL {\r
+                               padding: 0px;\r
+                               margin: 0em 1em;\r
+                       }\r
+                       \r
+                       #myList LI {\r
+                               width: 100px;\r
+                               border: solid 1px #2AA7DE;\r
+                               background: #6CC8EF;\r
+                               padding: 5px 5px;\r
+                               margin: 2px 0px;\r
+                               list-style: none;\r
+                       }\r
+                       \r
+                       #options {\r
+                               clear: left;\r
+                       }\r
+                       \r
+                       #options INPUT {\r
+                               font-family: Verdana, Arial, Helvetica, sans-serif;\r
+                               font-size: 11px;\r
+                               width: 150px;\r
+                       }\r
+                       \r
+               </style>                \r
+               \r
+               <script src="../js/lib/jquery-1.7.2.min.js" type="text/javascript"></script>\r
+               <script src="jquery.contextMenu.js" type="text/javascript"></script>\r
+               <link href="jquery.contextMenu.css" rel="stylesheet" type="text/css" />\r
+               \r
+               <script type="text/javascript">\r
+                       \r
+                       $(document).ready( function() {\r
+                               \r
+                               // Show menu when #myDiv is clicked\r
+                               $("#myDiv").contextMenu({\r
+                                       menu: 'myMenu'\r
+                               },\r
+                                       function(action, el, pos) {\r
+                                       alert(\r
+                                               'Action: ' + action + '\n\n' +\r
+                                               'Element ID: ' + $(el).attr('id') + '\n\n' + \r
+                                               'X: ' + pos.x + '  Y: ' + pos.y + ' (relative to element)\n\n' + \r
+                                               'X: ' + pos.docX + '  Y: ' + pos.docY+ ' (relative to document)'\r
+                                               );\r
+                               });\r
+                               \r
+                               // Show menu when a list item is clicked\r
+                               $("#myList UL LI").contextMenu({\r
+                                       menu: 'myMenu'\r
+                               }, function(action, el, pos) {\r
+                                       alert(\r
+                                               'Action: ' + action + '\n\n' +\r
+                                               'Element text: ' + $(el).text() + '\n\n' + \r
+                                               'X: ' + pos.x + '  Y: ' + pos.y + ' (relative to element)\n\n' + \r
+                                               'X: ' + pos.docX + '  Y: ' + pos.docY+ ' (relative to document)'\r
+                                               );\r
+                               });\r
+                               \r
+                               // Disable menus\r
+                               $("#disableMenus").click( function() {\r
+                                       $('#myDiv, #myList UL LI').disableContextMenu();\r
+                                       $(this).attr('disabled', true);\r
+                                       $("#enableMenus").attr('disabled', false);\r
+                               });\r
+                               \r
+                               // Enable menus\r
+                               $("#enableMenus").click( function() {\r
+                                       $('#myDiv, #myList UL LI').enableContextMenu();\r
+                                       $(this).attr('disabled', true);\r
+                                       $("#disableMenus").attr('disabled', false);\r
+                               });\r
+                               \r
+                               // Disable cut/copy\r
+                               $("#disableItems").click( function() {\r
+                                       $('#myMenu').disableContextMenuItems('#cut,#copy');\r
+                                       $(this).attr('disabled', true);\r
+                                       $("#enableItems").attr('disabled', false);\r
+                               });\r
+                               \r
+                               // Enable cut/copy\r
+                               $("#enableItems").click( function() {\r
+                                       $('#myMenu').enableContextMenuItems('#cut,#copy');\r
+                                       $(this).attr('disabled', true);\r
+                                       $("#disableItems").attr('disabled', false);\r
+                               });                             \r
+                               \r
+                       });\r
+                       \r
+               </script>\r
+       </head>\r
+       \r
+       <body>\r
+               \r
+               <h1>jQuery Context Menu Plugin Demo</h1>\r
+               <p>\r
+                       This plugin lets you add context menu functionality to your web applications.\r
+               </p>\r
+               \r
+               <p>\r
+                       <strong>Tip:</strong> Try using your keyboard to make a selection.\r
+               </p>\r
+               \r
+               <p>\r
+                       <a href="http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/">Back to the project page</a>\r
+               </p>\r
+               \r
+               <h2>Demo</h2>\r
+               \r
+               <div id="myDiv">\r
+                       Right click to view the context menu\r
+               </div>\r
+               \r
+               <div id="myList">\r
+                       <ul>\r
+                               <li>Item 1</li>\r
+                               <li>Item 2</li>\r
+                               <li>Item 3</li>\r
+                               <li>Item 4</li>\r
+                               <li>Item 5</li>\r
+                               <li>Item 6</li>\r
+                       </ul>\r
+               </div>\r
+               \r
+               <div id="options">\r
+                       <p>\r
+                               <input type="button" id="disableItems" value="Disable Cut/Copy" />\r
+                               <input type="button" id="enableItems" value="Enable Cut/Copy" disabled="disabled" />\r
+                       </p>\r
+                       \r
+                       <p>\r
+                               <input type="button" id="disableMenus" value="Disable Context Menus" />\r
+                               <input type="button" id="enableMenus" value="Enable Context Menus" disabled="disabled" />\r
+                       </p>\r
+               </div>\r
+               \r
+               <ul id="myMenu" class="contextMenu">\r
+                       <li class="edit"><a href="#edit">Edit</a></li>\r
+                       <li class="cut separator"><a href="#cut">Cut</a>\r
+                         <ul>\r
+                           <li class="pe"><a href="#pe">Pe</a></li>\r
+                         </ul>\r
+                       </li>\r
+                       <li class="copy"><a href="#copy">Copy</a></li>\r
+                       <li class="paste"><a href="#paste">Paste</a></li>\r
+                       <li class="delete"><a href="#delete">Delete</a></li>\r
+                       <li class="quit separator"><a href="#quit">Quit</a></li>\r
+               </ul>\r
+               \r
+       </body>\r
+</html>\r
diff --git a/redakcja/static/contextmenu/jquery.contextMenu.css b/redakcja/static/contextmenu/jquery.contextMenu.css
new file mode 100755 (executable)
index 0000000..46af248
--- /dev/null
@@ -0,0 +1,134 @@
+/*!\r
+ * jQuery contextMenu - Plugin for simple contextMenu handling\r
+ *\r
+ * Version: 1.5.13\r
+ *\r
+ * Authors: Rodney Rehm, Addy Osmani (patches for FF)\r
+ * Web: http://medialize.github.com/jQuery-contextMenu/\r
+ *\r
+ * Licensed under\r
+ *   MIT License http://www.opensource.org/licenses/mit-license\r
+ *   GPL v3 http://opensource.org/licenses/GPL-3.0\r
+ *\r
+ */\r
+\r
+.context-menu-list {\r
+    margin:0; \r
+    padding:0;\r
+    \r
+    min-width: 120px;\r
+    max-width: 250px;\r
+    display: inline-block;\r
+    position: absolute;\r
+    list-style-type: none;\r
+    \r
+    border: 1px solid #DDD;\r
+    background: #EEE;\r
+    \r
+    -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);\r
+       -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);\r
+        -ms-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);\r
+         -o-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);\r
+            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);\r
+    \r
+    font-family: Verdana, Arial, Helvetica, sans-serif;\r
+    font-size: 11px;\r
+}\r
+\r
+.context-menu-item {\r
+    padding: 2px 2px 2px 24px;\r
+    background-color: #EEE;\r
+    position: relative;\r
+    -moz-user-select: -moz-none;\r
+}\r
+\r
+.context-menu-separator {\r
+    padding-bottom:0;\r
+    border-bottom: 1px solid #DDD;\r
+}\r
+\r
+.context-menu-item > label {\r
+    -moz-user-select: text;\r
+}\r
+\r
+.context-menu-item.hover {\r
+    cursor: pointer;\r
+    background-color: #39F;\r
+}\r
+\r
+.context-menu-item.disabled {\r
+    color: #666;\r
+}\r
+\r
+.context-menu-input.hover,\r
+.context-menu-item.disabled.hover {\r
+    cursor: default;\r
+    background-color: #EEE;\r
+}\r
+\r
+.context-menu-submenu:after {\r
+    content: ">";\r
+    color: #666;\r
+    position: absolute;\r
+    top: 0;\r
+    right: 3px;\r
+    z-index: 1;\r
+}\r
+\r
+/* icons\r
+    #protip:\r
+    In case you want to use sprites for icons (which I would suggest you do) have a look at\r
+    http://css-tricks.com/13224-pseudo-spriting/ to get an idea of how to implement \r
+    .context-menu-item.icon:before {}\r
+ */\r
+.context-menu-item.icon { min-height: 18px; background-repeat: no-repeat; background-position: 4px 2px; }\r
+.context-menu-item.icon-edit { background-image: url(images/page_white_edit.png); }\r
+.context-menu-item.icon-cut { background-image: url(images/cut.png); }\r
+.context-menu-item.icon-copy { background-image: url(images/page_white_copy.png); }\r
+.context-menu-item.icon-paste { background-image: url(images/page_white_paste.png); }\r
+.context-menu-item.icon-delete { background-image: url(images/page_white_delete.png); }\r
+.context-menu-item.icon-quit { background-image: url(images/door.png); }\r
+\r
+/* vertically align inside labels */\r
+.context-menu-input > label > * { vertical-align: top; }\r
+\r
+/* position checkboxes and radios as icons */\r
+.context-menu-input > label > input[type="checkbox"],\r
+.context-menu-input > label > input[type="radio"] {\r
+    margin-left: -17px;\r
+}\r
+.context-menu-input > label > span {\r
+    margin-left: 5px;\r
+}\r
+\r
+.context-menu-input > label,\r
+.context-menu-input > label > input[type="text"],\r
+.context-menu-input > label > textarea,\r
+.context-menu-input > label > select {\r
+    display: block;\r
+    width: 100%;\r
+    \r
+    -webkit-box-sizing: border-box;\r
+       -moz-box-sizing: border-box;\r
+        -ms-box-sizing: border-box;\r
+         -o-box-sizing: border-box;\r
+            box-sizing: border-box;\r
+}\r
+\r
+.context-menu-input > label > textarea {\r
+    height: 100px;\r
+}\r
+.context-menu-item > .context-menu-list {\r
+    display: none;\r
+    /* re-positioned by js */\r
+    right: -5px;\r
+    top: 5px;\r
+}\r
+\r
+.context-menu-item.hover > .context-menu-list {\r
+    display: block;\r
+}\r
+\r
+.context-menu-accesskey {\r
+    text-decoration: underline;\r
+}\r
diff --git a/redakcja/static/contextmenu/jquery.contextMenu.js b/redakcja/static/contextmenu/jquery.contextMenu.js
new file mode 100755 (executable)
index 0000000..53c3fe9
--- /dev/null
@@ -0,0 +1,1485 @@
+/*!\r
+ * jQuery contextMenu - Plugin for simple contextMenu handling\r
+ *\r
+ * Version: 1.5.13\r
+ *\r
+ * Authors: Rodney Rehm, Addy Osmani (patches for FF)\r
+ * Web: http://medialize.github.com/jQuery-contextMenu/\r
+ *\r
+ * Licensed under\r
+ *   MIT License http://www.opensource.org/licenses/mit-license\r
+ *   GPL v3 http://opensource.org/licenses/GPL-3.0\r
+ *\r
+ */\r
+\r
+(function($, undefined){\r
+    \r
+    // TODO: -\r
+        // ARIA stuff: menuitem, menuitemcheckbox und menuitemradio\r
+        // create <menu> structure if $.support[htmlCommand || htmlMenuitem] and !opt.disableNative\r
+\r
+// determine html5 compatibility\r
+$.support.htmlMenuitem = ('HTMLMenuItemElement' in window);\r
+$.support.htmlCommand = ('HTMLCommandElement' in window);\r
+\r
+var // currently active contextMenu trigger\r
+    $currentTrigger = null,\r
+    // is contextMenu initialized with at least one menu?\r
+    initialized = false,\r
+    // window handle\r
+    $win = $(window),\r
+    // number of registered menus\r
+    counter = 0,\r
+    // mapping selector to namespace\r
+    namespaces = {},\r
+    // mapping namespace to options\r
+    menus = {},\r
+    // custom command type handlers\r
+    types = {},\r
+    // default values\r
+    defaults = {\r
+        // selector of contextMenu trigger\r
+        selector: null,\r
+        // where to append the menu to\r
+        appendTo: null,\r
+        // method to trigger context menu ["right", "left", "hover"]\r
+        trigger: "right",\r
+        // hide menu when mouse leaves trigger / menu elements\r
+        autoHide: false,\r
+        // ms to wait before showing a hover-triggered context menu\r
+        delay: 200,\r
+        // determine position to show menu at\r
+        determinePosition: function($menu) {\r
+            // position to the lower middle of the trigger element\r
+            if ($.ui && $.ui.position) {\r
+                // .position() is provided as a jQuery UI utility\r
+                // (...and it won't work on hidden elements)\r
+                $menu.css('display', 'block').position({\r
+                    my: "center top",\r
+                    at: "center bottom",\r
+                    of: this,\r
+                    offset: "0 5",\r
+                    collision: "fit"\r
+                }).css('display', 'none');\r
+            } else {\r
+                // determine contextMenu position\r
+                var offset = this.offset();\r
+                offset.top += this.outerHeight();\r
+                offset.left += this.outerWidth() / 2 - $menu.outerWidth() / 2;\r
+                $menu.css(offset);\r
+            }\r
+        },\r
+        // position menu\r
+        position: function(opt, x, y) {\r
+            var $this = this,\r
+                offset;\r
+            // determine contextMenu position\r
+            if (!x && !y) {\r
+                opt.determinePosition.call(this, opt.$menu);\r
+                return;\r
+            } else if (x === "maintain" && y === "maintain") {\r
+                // x and y must not be changed (after re-show on command click)\r
+                offset = opt.$menu.position();\r
+            } else {\r
+                // x and y are given (by mouse event)\r
+                var triggerIsFixed = opt.$trigger.parents().andSelf()\r
+                    .filter(function() {\r
+                        return $(this).css('position') == "fixed";\r
+                    }).length;\r
+\r
+                if (triggerIsFixed) {\r
+                    y -= $win.scrollTop();\r
+                    x -= $win.scrollLeft();\r
+                }\r
+                offset = {top: y, left: x};\r
+            }\r
+            \r
+            // correct offset if viewport demands it\r
+            var bottom = $win.scrollTop() + $win.height(),\r
+                right = $win.scrollLeft() + $win.width(),\r
+                height = opt.$menu.height(),\r
+                width = opt.$menu.width();\r
+            \r
+            if (offset.top + height > bottom) {\r
+                offset.top -= height;\r
+            }\r
+            \r
+            if (offset.left + width > right) {\r
+                offset.left -= width;\r
+            }\r
+            \r
+            opt.$menu.css(offset);\r
+        },\r
+        // position the sub-menu\r
+        positionSubmenu: function($menu) {\r
+            if ($.ui && $.ui.position) {\r
+                // .position() is provided as a jQuery UI utility\r
+                // (...and it won't work on hidden elements)\r
+                $menu.css('display', 'block').position({\r
+                    my: "left top",\r
+                    at: "right top",\r
+                    of: this,\r
+                    collision: "fit"\r
+                }).css('display', '');\r
+            } else {\r
+                // determine contextMenu position\r
+                var offset = this.offset();\r
+                offset.top += 0;\r
+                offset.left += this.outerWidth();\r
+                $menu.css(offset);\r
+            }\r
+        },\r
+        // offset to add to zIndex\r
+        zIndex: 1,\r
+        // show hide animation settings\r
+        animation: {\r
+            duration: 50,\r
+            show: 'slideDown',\r
+            hide: 'slideUp'\r
+        },\r
+        // events\r
+        events: {\r
+            show: $.noop,\r
+            hide: $.noop\r
+        },\r
+        // default callback\r
+        callback: null,\r
+        // list of contextMenu items\r
+        items: {}\r
+    },\r
+    // mouse position for hover activation\r
+    hoveract = {\r
+        timer: null,\r
+        pageX: null,\r
+        pageY: null\r
+    },\r
+    // determine zIndex\r
+    zindex = function($t) {\r
+        var zin = 0,\r
+            $tt = $t;\r
+\r
+        while (true) {\r
+            zin = Math.max(zin, parseInt($tt.css('z-index'), 10) || 0);\r
+            $tt = $tt.parent();\r
+            if (!$tt || !$tt.length || $tt.prop('nodeName').toLowerCase() == 'body') {\r
+                break;\r
+            }\r
+        }\r
+        \r
+        return zin;\r
+    },\r
+    // event handlers\r
+    handle = {\r
+        // abort anything\r
+        abortevent: function(e){\r
+            e.preventDefault();\r
+            e.stopImmediatePropagation();\r
+        },\r
+        \r
+        // contextmenu show dispatcher\r
+        contextmenu: function(e) {\r
+            var $this = $(this);\r
+            \r
+            // disable actual context-menu\r
+            e.preventDefault();\r
+            e.stopImmediatePropagation();\r
+            \r
+            // abort native-triggered events unless we're triggering on right click\r
+            if (e.data.trigger != 'right' && e.originalEvent) {\r
+                return;\r
+            }\r
+            \r
+            if (!$this.hasClass('context-menu-disabled')) {\r
+                // theoretically need to fire a show event at <menu>\r
+                // http://www.whatwg.org/specs/web-apps/current-work/multipage/interactive-elements.html#context-menus\r
+                // var evt = jQuery.Event("show", { data: data, pageX: e.pageX, pageY: e.pageY, relatedTarget: this });\r
+                // e.data.$menu.trigger(evt);\r
+                \r
+                $currentTrigger = $this;\r
+                if (e.data.build) {\r
+                    var built = e.data.build($currentTrigger, e);\r
+                    // abort if build() returned false\r
+                    if (built === false) {\r
+                        return;\r
+                    }\r
+                    \r
+                    // dynamically build menu on invocation\r
+                    e.data = $.extend(true, defaults, e.data, built || {});\r
+\r
+                    // abort if there are no items to display\r
+                    if (!e.data.items || $.isEmptyObject(e.data.items)) {\r
+                        // Note: jQuery captures and ignores errors from event handlers\r
+                        if (window.console) {\r
+                            (console.error || console.log)("No items specified to show in contextMenu");\r
+                        }\r
+                        \r
+                        throw new Error('No Items sepcified');\r
+                    }\r
+                    \r
+                    // backreference for custom command type creation\r
+                    e.data.$trigger = $currentTrigger;\r
+                    \r
+                    op.create(e.data);\r
+                }\r
+                // show menu\r
+                op.show.call($this, e.data, e.pageX, e.pageY);\r
+            }\r
+        },\r
+        // contextMenu left-click trigger\r
+        click: function(e) {\r
+            e.preventDefault();\r
+            e.stopImmediatePropagation();\r
+            $(this).trigger(jQuery.Event("contextmenu", { data: e.data, pageX: e.pageX, pageY: e.pageY }));\r
+        },\r
+        // contextMenu right-click trigger\r
+        mousedown: function(e) {\r
+            // register mouse down\r
+            var $this = $(this);\r
+            \r
+            // hide any previous menus\r
+            if ($currentTrigger && $currentTrigger.length && !$currentTrigger.is($this)) {\r
+                $currentTrigger.data('contextMenu').$menu.trigger('contextmenu:hide');\r
+            }\r
+            \r
+            // activate on right click\r
+            if (e.button == 2) {\r
+                $currentTrigger = $this.data('contextMenuActive', true);\r
+            }\r
+        },\r
+        // contextMenu right-click trigger\r
+        mouseup: function(e) {\r
+            // show menu\r
+            var $this = $(this);\r
+            if ($this.data('contextMenuActive') && $currentTrigger && $currentTrigger.length && $currentTrigger.is($this) && !$this.hasClass('context-menu-disabled')) {\r
+                e.preventDefault();\r
+                e.stopImmediatePropagation();\r
+                $currentTrigger = $this;\r
+                $this.trigger(jQuery.Event("contextmenu", { data: e.data, pageX: e.pageX, pageY: e.pageY }));\r
+            }\r
+            \r
+            $this.removeData('contextMenuActive');\r
+        },\r
+        // contextMenu hover trigger\r
+        mouseenter: function(e) {\r
+            var $this = $(this),\r
+                $related = $(e.relatedTarget),\r
+                $document = $(document);\r
+            \r
+            // abort if we're coming from a menu\r
+            if ($related.is('.context-menu-list') || $related.closest('.context-menu-list').length) {\r
+                return;\r
+            }\r
+            \r
+            // abort if a menu is shown\r
+            if ($currentTrigger && $currentTrigger.length) {\r
+                return;\r
+            }\r
+            \r
+            hoveract.pageX = e.pageX;\r
+            hoveract.pageY = e.pageY;\r
+            hoveract.data = e.data;\r
+            $document.on('mousemove.contextMenuShow', handle.mousemove);\r
+            hoveract.timer = setTimeout(function() {\r
+                hoveract.timer = null;\r
+                $document.off('mousemove.contextMenuShow');\r
+                $currentTrigger = $this;\r
+                $this.trigger(jQuery.Event("contextmenu", { data: hoveract.data, pageX: hoveract.pageX, pageY: hoveract.pageY }));\r
+            }, e.data.delay );\r
+        },\r
+        // contextMenu hover trigger\r
+        mousemove: function(e) {\r
+            hoveract.pageX = e.pageX;\r
+            hoveract.pageY = e.pageY;\r
+        },\r
+        // contextMenu hover trigger\r
+        mouseleave: function(e) {\r
+            // abort if we're leaving for a menu\r
+            var $related = $(e.relatedTarget);\r
+            if ($related.is('.context-menu-list') || $related.closest('.context-menu-list').length) {\r
+                return;\r
+            }\r
+            \r
+            try {\r
+                clearTimeout(hoveract.timer);\r
+            } catch(e) {}\r
+            \r
+            hoveract.timer = null;\r
+        },\r
+        \r
+        // click on layer to hide contextMenu\r
+        layerClick: function(e) {\r
+            var $this = $(this),\r
+                root = $this.data('contextMenuRoot');\r
+                \r
+            e.preventDefault();\r
+            e.stopImmediatePropagation();\r
+            \r
+            if ((root.trigger == 'left' && e.button == 0) || (root.trigger == 'right' && e.button == 2)) {\r
+                var offset = root.$trigger.offset();\r
+                \r
+                // while this looks kinda awful, it's the best way to avoid\r
+                // unnecessarily calculating any positions\r
+                offset.top += $(window).scrollTop();\r
+                if (offset.top <= e.pageY) {\r
+                    offset.left += $(window).scrollLeft();\r
+                    if (offset.left <= e.pageX) {\r
+                        offset.bottom = offset.top + root.$trigger.outerHeight();\r
+                        if (offset.bottom >= e.pageY) {\r
+                            offset.right = offset.left + root.$trigger.outerWidth();\r
+                            if (offset.right >= e.pageX) {\r
+                                // reposition\r
+                                root.position.call(root.$trigger, root, e.pageX, e.pageY);\r
+                                return;\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            } \r
+            \r
+            // remove only after mouseup has completed\r
+            $this.on('mouseup', function(e) {\r
+                e.preventDefault();\r
+                e.stopImmediatePropagation();\r
+                root.$menu.trigger('contextmenu:hide');\r
+            });\r
+        },\r
+        // key handled :hover\r
+        keyStop: function(e, opt) {\r
+            if (!opt.isInput) {\r
+                e.preventDefault();\r
+            }\r
+            \r
+            e.stopPropagation();\r
+        },\r
+        key: function(e) {\r
+            var opt = $currentTrigger.data('contextMenu') || {},\r
+                $children = opt.$menu.children(),\r
+                $round;\r
+\r
+            switch (e.keyCode) {\r
+                case 9:\r
+                case 38: // up\r
+                    handle.keyStop(e, opt);\r
+                    // if keyCode is [38 (up)] or [9 (tab) with shift]\r
+                    if (opt.isInput) {\r
+                        if (e.keyCode == 9 && e.shiftKey) {\r
+                            e.preventDefault();\r
+                            opt.$selected && opt.$selected.find('input, textarea, select').blur();\r
+                            opt.$menu.trigger('prevcommand');\r
+                            return;\r
+                        } else if (e.keyCode == 38 && opt.$selected.find('input, textarea, select').prop('type') == 'checkbox') {\r
+                            // checkboxes don't capture this key\r
+                            e.preventDefault();\r
+                            return;\r
+                        }\r
+                    } else if (e.keyCode != 9 || e.shiftKey) {\r
+                        opt.$menu.trigger('prevcommand');\r
+                        return;\r
+                    }\r
+                    \r
+                case 9: // tab\r
+                case 40: // down\r
+                    handle.keyStop(e, opt);\r
+                    if (opt.isInput) {\r
+                        if (e.keyCode == 9) {\r
+                            e.preventDefault();\r
+                            opt.$selected && opt.$selected.find('input, textarea, select').blur();\r
+                            opt.$menu.trigger('nextcommand');\r
+                            return;\r
+                        } else if (e.keyCode == 40 && opt.$selected.find('input, textarea, select').prop('type') == 'checkbox') {\r
+                            // checkboxes don't capture this key\r
+                            e.preventDefault();\r
+                            return;\r
+                        }\r
+                    } else {\r
+                        opt.$menu.trigger('nextcommand');\r
+                        return;\r
+                    }\r
+                    break;\r
+                \r
+                case 37: // left\r
+                    handle.keyStop(e, opt);\r
+                    if (opt.isInput || !opt.$selected || !opt.$selected.length) {\r
+                        break;\r
+                    }\r
+                \r
+                    if (!opt.$selected.parent().hasClass('context-menu-root')) {\r
+                        var $parent = opt.$selected.parent().parent();\r
+                        opt.$selected.trigger('contextmenu:blur');\r
+                        opt.$selected = $parent;\r
+                        return;\r
+                    }\r
+                    break;\r
+                    \r
+                case 39: // right\r
+                    handle.keyStop(e, opt);\r
+                    if (opt.isInput || !opt.$selected || !opt.$selected.length) {\r
+                        break;\r
+                    }\r
+                    \r
+                    var itemdata = opt.$selected.data('contextMenu') || {};\r
+                    if (itemdata.$menu && opt.$selected.hasClass('context-menu-submenu')) {\r
+                        opt.$selected = null;\r
+                        itemdata.$selected = null;\r
+                        itemdata.$menu.trigger('nextcommand');\r
+                        return;\r
+                    }\r
+                    break;\r
+                \r
+                case 35: // end\r
+                case 36: // home\r
+                    if (opt.$selected && opt.$selected.find('input, textarea, select').length) {\r
+                        return;\r
+                    } else {\r
+                        (opt.$selected && opt.$selected.parent() || opt.$menu)\r
+                            .children(':not(.disabled, .not-selectable)')[e.keyCode == 36 ? 'first' : 'last']()\r
+                            .trigger('contextmenu:focus');\r
+                        e.preventDefault();\r
+                        return;\r
+                    }\r
+                    break;\r
+                    \r
+                case 13: // enter\r
+                    handle.keyStop(e, opt);\r
+                    if (opt.isInput) {\r
+                        if (opt.$selected && !opt.$selected.is('textarea, select')) {\r
+                            e.preventDefault();\r
+                            return;\r
+                        }\r
+                        break;\r
+                    }\r
+                    opt.$selected && opt.$selected.trigger('mouseup');\r
+                    return;\r
+                    \r
+                case 32: // space\r
+                case 33: // page up\r
+                case 34: // page down\r
+                    // prevent browser from scrolling down while menu is visible\r
+                    handle.keyStop(e, opt);\r
+                    return;\r
+                    \r
+                case 27: // esc\r
+                    handle.keyStop(e, opt);\r
+                    opt.$menu.trigger('contextmenu:hide');\r
+                    return;\r
+                    \r
+                default: // 0-9, a-z\r
+                    var k = (String.fromCharCode(e.keyCode)).toUpperCase();\r
+                    if (opt.accesskeys[k]) {\r
+                        // according to the specs accesskeys must be invoked immediately\r
+                        opt.accesskeys[k].$node.trigger(opt.accesskeys[k].$menu\r
+                            ? 'contextmenu:focus'\r
+                            : 'mouseup'\r
+                        );\r
+                        return;\r
+                    }\r
+                    break;\r
+            }\r
+            // pass event to selected item, \r
+            // stop propagation to avoid endless recursion\r
+            e.stopPropagation();\r
+            opt.$selected && opt.$selected.trigger(e);\r
+        },\r
+\r
+        // select previous possible command in menu\r
+        prevItem: function(e) {\r
+            e.stopPropagation();\r
+            var opt = $(this).data('contextMenu') || {};\r
+\r
+            // obtain currently selected menu\r
+            if (opt.$selected) {\r
+                var $s = opt.$selected;\r
+                opt = opt.$selected.parent().data('contextMenu') || {};\r
+                opt.$selected = $s;\r
+            }\r
+            \r
+            var $children = opt.$menu.children(),\r
+                $prev = !opt.$selected || !opt.$selected.prev().length ? $children.last() : opt.$selected.prev(),\r
+                $round = $prev;\r
+            \r
+            // skip disabled\r
+            while ($prev.hasClass('disabled') || $prev.hasClass('not-selectable')) {\r
+                if ($prev.prev().length) {\r
+                    $prev = $prev.prev();\r
+                } else {\r
+                    $prev = $children.last();\r
+                }\r
+                if ($prev.is($round)) {\r
+                    // break endless loop\r
+                    return;\r
+                }\r
+            }\r
+            \r
+            // leave current\r
+            if (opt.$selected) {\r
+                handle.itemMouseleave.call(opt.$selected.get(0), e);\r
+            }\r
+            \r
+            // activate next\r
+            handle.itemMouseenter.call($prev.get(0), e);\r
+            \r
+            // focus input\r
+            var $input = $prev.find('input, textarea, select');\r
+            if ($input.length) {\r
+                $input.focus();\r
+            }\r
+        },\r
+        // select next possible command in menu\r
+        nextItem: function(e) {\r
+            e.stopPropagation();\r
+            var opt = $(this).data('contextMenu') || {};\r
+\r
+            // obtain currently selected menu\r
+            if (opt.$selected) {\r
+                var $s = opt.$selected;\r
+                opt = opt.$selected.parent().data('contextMenu') || {};\r
+                opt.$selected = $s;\r
+            }\r
+\r
+            var $children = opt.$menu.children(),\r
+                $next = !opt.$selected || !opt.$selected.next().length ? $children.first() : opt.$selected.next(),\r
+                $round = $next;\r
+\r
+            // skip disabled\r
+            while ($next.hasClass('disabled') || $next.hasClass('not-selectable')) {\r
+                if ($next.next().length) {\r
+                    $next = $next.next();\r
+                } else {\r
+                    $next = $children.first();\r
+                }\r
+                if ($next.is($round)) {\r
+                    // break endless loop\r
+                    return;\r
+                }\r
+            }\r
+            \r
+            // leave current\r
+            if (opt.$selected) {\r
+                handle.itemMouseleave.call(opt.$selected.get(0), e);\r
+            }\r
+            \r
+            // activate next\r
+            handle.itemMouseenter.call($next.get(0), e);\r
+            \r
+            // focus input\r
+            var $input = $next.find('input, textarea, select');\r
+            if ($input.length) {\r
+                $input.focus();\r
+            }\r
+        },\r
+        \r
+        // flag that we're inside an input so the key handler can act accordingly\r
+        focusInput: function(e) {\r
+            var $this = $(this).closest('.context-menu-item'),\r
+                data = $this.data(),\r
+                opt = data.contextMenu,\r
+                root = data.contextMenuRoot;\r
+\r
+            root.$selected = opt.$selected = $this;\r
+            root.isInput = opt.isInput = true;\r
+        },\r
+        // flag that we're inside an input so the key handler can act accordingly\r
+        blurInput: function(e) {\r
+            var $this = $(this).closest('.context-menu-item'),\r
+                data = $this.data(),\r
+                opt = data.contextMenu,\r
+                root = data.contextMenuRoot;\r
+\r
+            root.isInput = opt.isInput = false;\r
+        },\r
+        \r
+        // :hover on menu\r
+        menuMouseenter: function(e) {\r
+            var root = $(this).data().contextMenuRoot;\r
+            root.hovering = true;\r
+        },\r
+        // :hover on menu\r
+        menuMouseleave: function(e) {\r
+            var root = $(this).data().contextMenuRoot;\r
+            if (root.$layer && root.$layer.is(e.relatedTarget)) {\r
+                root.hovering = false;\r
+            }\r
+        },\r
+        \r
+        // :hover done manually so key handling is possible\r
+        itemMouseenter: function(e) {\r
+            var $this = $(this),\r
+                data = $this.data(),\r
+                opt = data.contextMenu,\r
+                root = data.contextMenuRoot;\r
+            \r
+            root.hovering = true;\r
+\r
+            // abort if we're re-entering\r
+            if (e && root.$layer && root.$layer.is(e.relatedTarget)) {\r
+                e.preventDefault();\r
+                e.stopImmediatePropagation();\r
+            }\r
+\r
+            // make sure only one item is selected\r
+            (opt.$menu ? opt : root).$menu\r
+                .children('.hover').trigger('contextmenu:blur');\r
+\r
+            if ($this.hasClass('disabled') || $this.hasClass('not-selectable')) {\r
+                opt.$selected = null;\r
+                return;\r
+            }\r
+            \r
+            $this.trigger('contextmenu:focus');\r
+        },\r
+        // :hover done manually so key handling is possible\r
+        itemMouseleave: function(e) {\r
+            var $this = $(this),\r
+                data = $this.data(),\r
+                opt = data.contextMenu,\r
+                root = data.contextMenuRoot;\r
+\r
+            if (root !== opt && root.$layer && root.$layer.is(e.relatedTarget)) {\r
+                root.$selected && root.$selected.trigger('contextmenu:blur');\r
+                e.preventDefault();\r
+                e.stopImmediatePropagation();\r
+                root.$selected = opt.$selected = opt.$node;\r
+                return;\r
+            }\r
+            \r
+            $this.trigger('contextmenu:blur');\r
+        },\r
+        // contextMenu item click\r
+        itemClick: function(e) {\r
+            var $this = $(this),\r
+                data = $this.data(),\r
+                opt = data.contextMenu,\r
+                root = data.contextMenuRoot,\r
+                key = data.contextMenuKey,\r
+                callback;\r
+\r
+            // abort if the key is unknown or disabled or is a menu\r
+            if (!opt.items[key] || $this.hasClass('disabled') || $this.hasClass('context-menu-submenu')) {\r
+                return;\r
+            }\r
+\r
+            e.preventDefault();\r
+            e.stopImmediatePropagation();\r
+\r
+            if ($.isFunction(root.callbacks[key])) {\r
+                // item-specific callback\r
+                callback = root.callbacks[key];\r
+            } else if ($.isFunction(root.callback)) {\r
+                // default callback\r
+                callback = root.callback;                \r
+            } else {\r
+                // no callback, no action\r
+                return;\r
+            }\r
+\r
+            // hide menu if callback doesn't stop that\r
+            if (callback.call(root.$trigger, key, root) !== false) {\r
+                root.$menu.trigger('contextmenu:hide');\r
+            } else {\r
+                op.update.call(root.$trigger, root);\r
+            }\r
+        },\r
+        // ignore click events on input elements\r
+        inputClick: function(e) {\r
+            e.stopImmediatePropagation();\r
+        },\r
+        \r
+        // hide <menu>\r
+        hideMenu: function(e) {\r
+            var root = $(this).data('contextMenuRoot');\r
+            op.hide.call(root.$trigger, root);\r
+        },\r
+        // focus <command>\r
+        focusItem: function(e) {\r
+            e.stopPropagation();\r
+            var $this = $(this),\r
+                data = $this.data(),\r
+                opt = data.contextMenu,\r
+                root = data.contextMenuRoot;\r
+\r
+            $this.addClass('hover')\r
+                .siblings('.hover').trigger('contextmenu:blur');\r
+            \r
+            // remember selected\r
+            opt.$selected = root.$selected = $this;\r
+            \r
+            // position sub-menu - do after show so dumb $.ui.position can keep up\r
+            if (opt.$node) {\r
+                root.positionSubmenu.call(opt.$node, opt.$menu);\r
+            }\r
+        },\r
+        // blur <command>\r
+        blurItem: function(e) {\r
+            e.stopPropagation();\r
+            var $this = $(this),\r
+                data = $this.data(),\r
+                opt = data.contextMenu,\r
+                root = data.contextMenuRoot;\r
+            \r
+            $this.removeClass('hover');\r
+            opt.$selected = null;\r
+        }\r
+    },\r
+    // operations\r
+    op = {\r
+        show: function(opt, x, y) {\r
+            var $this = $(this),\r
+                offset,\r
+                css = {};\r
+\r
+            // hide any open menus\r
+            $('#context-menu-layer').trigger('mousedown');\r
+\r
+            // backreference for callbacks\r
+            opt.$trigger = $this;\r
+\r
+            // show event\r
+            if (opt.events.show.call($this, opt) === false) {\r
+                $currentTrigger = null;\r
+                return;\r
+            }\r
+            \r
+            // create or update context menu\r
+            op.update.call($this, opt);\r
+            \r
+            // position menu\r
+            opt.position.call($this, opt, x, y);\r
+\r
+            // make sure we're in front\r
+            if (opt.zIndex) {\r
+                css.zIndex = zindex($this) + opt.zIndex;\r
+            }\r
+            \r
+            // add layer\r
+            op.layer.call(opt.$menu, opt, css.zIndex);\r
+            \r
+            // adjust sub-menu zIndexes\r
+            opt.$menu.find('ul').css('zIndex', css.zIndex + 1);\r
+            \r
+            // position and show context menu\r
+            opt.$menu.css( css )[opt.animation.show](opt.animation.duration);\r
+            // make options available\r
+            $this.data('contextMenu', opt);\r
+            // register key handler\r
+            $(document).off('keydown.contextMenu').on('keydown.contextMenu', handle.key);\r
+            // register autoHide handler\r
+            if (opt.autoHide) {\r
+                // trigger element coordinates\r
+                var pos = $this.position();\r
+                pos.right = pos.left + $this.outerWidth();\r
+                pos.bottom = pos.top + this.outerHeight();\r
+                // mouse position handler\r
+                $(document).on('mousemove.contextMenuAutoHide', function(e) {\r
+                    if (opt.$layer && !opt.hovering && (!(e.pageX >= pos.left && e.pageX <= pos.right) || !(e.pageY >= pos.top && e.pageY <= pos.bottom))) {\r
+                        // if mouse in menu...\r
+                        opt.$layer.trigger('mousedown');\r
+                    }\r
+                });\r
+            }\r
+        },\r
+        hide: function(opt) {\r
+            var $this = $(this);\r
+            if (!opt) {\r
+                opt = $this.data('contextMenu') || {};\r
+            }\r
+            \r
+            // hide event\r
+            if (opt.events && opt.events.hide.call($this, opt) === false) {\r
+                return;\r
+            }\r
+            \r
+            if (opt.$layer) {\r
+                // keep layer for a bit so the contextmenu event can be aborted properly by opera\r
+                setTimeout((function($layer){ return function(){\r
+                        $layer.remove();\r
+                    };\r
+                })(opt.$layer), 10);\r
+                \r
+                try {\r
+                    delete opt.$layer;\r
+                } catch(e) {\r
+                    opt.$layer = null;\r
+                }\r
+            }\r
+            \r
+            // remove handle\r
+            $currentTrigger = null;\r
+            // remove selected\r
+            opt.$menu.find('.hover').trigger('contextmenu:blur');\r
+            opt.$selected = null;\r
+            // unregister key and mouse handlers\r
+            //$(document).off('.contextMenuAutoHide keydown.contextMenu'); // http://bugs.jquery.com/ticket/10705\r
+            $(document).off('.contextMenuAutoHide').off('keydown.contextMenu');\r
+            // hide menu\r
+            opt.$menu && opt.$menu[opt.animation.hide](opt.animation.duration);\r
+            \r
+            // tear down dynamically built menu\r
+            if (opt.build) {\r
+                opt.$menu.remove();\r
+                $.each(opt, function(key, value) {\r
+                    switch (key) {\r
+                        case 'ns':\r
+                        case 'selector':\r
+                        case 'build':\r
+                        case 'trigger':\r
+                            return true;\r
+\r
+                        default:\r
+                            opt[key] = undefined;\r
+                            try {\r
+                                delete opt[key];\r
+                            } catch (e) {}\r
+                            return true;\r
+                   }\r
+                });\r
+            }\r
+        },\r
+        create: function(opt, root) {\r
+            if (root === undefined) {\r
+                root = opt;\r
+            }\r
+            // create contextMenu\r
+            opt.$menu = $('<ul class="context-menu-list ' + (opt.className || "") + '"></ul>').data({\r
+                'contextMenu': opt,\r
+                'contextMenuRoot': root\r
+            });\r
+            \r
+            $.each(['callbacks', 'commands', 'inputs'], function(i,k){\r
+                opt[k] = {};\r
+                if (!root[k]) {\r
+                    root[k] = {};\r
+                }\r
+            });\r
+            \r
+            root.accesskeys || (root.accesskeys = {});\r
+            \r
+            // create contextMenu items\r
+            $.each(opt.items, function(key, item){\r
+                var $t = $('<li class="context-menu-item ' + (item.className || "") +'"></li>'),\r
+                    $label = null,\r
+                    $input = null;\r
+                \r
+                item.$node = $t.data({\r
+                    'contextMenu': opt,\r
+                    'contextMenuRoot': root,\r
+                    'contextMenuKey': key\r
+                });\r
+                \r
+                // register accesskey\r
+                // NOTE: the accesskey attribute should be applicable to any element, but Safari5 and Chrome13 still can't do that\r
+                if (item.accesskey) {\r
+                    var aks = splitAccesskey(item.accesskey);\r
+                    for (var i=0, ak; ak = aks[i]; i++) {\r
+                        if (!root.accesskeys[ak]) {\r
+                            root.accesskeys[ak] = item;\r
+                            item._name = item.name.replace(new RegExp('(' + ak + ')', 'i'), '<span class="context-menu-accesskey">$1</span>');\r
+                            break;\r
+                        }\r
+                    }\r
+                }\r
+                \r
+                if (typeof item == "string") {\r
+                    $t.addClass('context-menu-separator not-selectable');\r
+                } else if (item.type && types[item.type]) {\r
+                    // run custom type handler\r
+                    types[item.type].call($t, item, opt, root);\r
+                    // register commands\r
+                    $.each([opt, root], function(i,k){\r
+                        k.commands[key] = item;\r
+                        if ($.isFunction(item.callback)) {\r
+                            k.callbacks[key] = item.callback;\r
+                        }\r
+                    });\r
+                } else {\r
+                    // add label for input\r
+                    if (item.type == 'html') {\r
+                        $t.addClass('context-menu-html not-selectable');\r
+                    } else if (item.type) {\r
+                        $label = $('<label></label>').appendTo($t);\r
+                        $('<span></span>').html(item._name || item.name).appendTo($label);\r
+                        $t.addClass('context-menu-input');\r
+                        opt.hasTypes = true;\r
+                        $.each([opt, root], function(i,k){\r
+                            k.commands[key] = item;\r
+                            k.inputs[key] = item;\r
+                        });\r
+                    } else if (item.items) {\r
+                        item.type = 'sub';\r
+                    }\r
+                \r
+                    switch (item.type) {\r
+                        case 'text':\r
+                            $input = $('<input type="text" value="1" name="context-menu-input-'+ key +'" value="">')\r
+                                .val(item.value || "").appendTo($label);\r
+                            break;\r
+                    \r
+                        case 'textarea':\r
+                            $input = $('<textarea name="context-menu-input-'+ key +'"></textarea>')\r
+                                .val(item.value || "").appendTo($label);\r
+\r
+                            if (item.height) {\r
+                                $input.height(item.height);\r
+                            }\r
+                            break;\r
+\r
+                        case 'checkbox':\r
+                            $input = $('<input type="checkbox" value="1" name="context-menu-input-'+ key +'" value="">')\r
+                                .val(item.value || "").prop("checked", !!item.selected).prependTo($label);\r
+                            break;\r
+\r
+                        case 'radio':\r
+                            $input = $('<input type="radio" value="1" name="context-menu-input-'+ item.radio +'" value="">')\r
+                                .val(item.value || "").prop("checked", !!item.selected).prependTo($label);\r
+                            break;\r
+                    \r
+                        case 'select':\r
+                            $input = $('<select name="context-menu-input-'+ key +'">').appendTo($label);\r
+                            if (item.options) {\r
+                                $.each(item.options, function(value, text) {\r
+                                    $('<option></option>').val(value).text(text).appendTo($input);\r
+                                });\r
+                                $input.val(item.selected);\r
+                            }\r
+                            break;\r
+                        \r
+                        case 'sub':\r
+                            $('<span></span>').html(item._name || item.name).appendTo($t);\r
+                            item.appendTo = item.$node;\r
+                            op.create(item, root);\r
+                            $t.data('contextMenu', item).addClass('context-menu-submenu');\r
+                            item.callback = null;\r
+                            break;\r
+                        \r
+                        case 'html':\r
+                            $(item.html).appendTo($t);\r
+                            break;\r
+                        \r
+                        default:\r
+                            $.each([opt, root], function(i,k){\r
+                                k.commands[key] = item;\r
+                                if ($.isFunction(item.callback)) {\r
+                                    k.callbacks[key] = item.callback;\r
+                                }\r
+                            });\r
+                            \r
+                            $('<span></span>').html(item._name || item.name || "").appendTo($t);\r
+                            break;\r
+                    }\r
+                    \r
+                    // disable key listener in <input>\r
+                    if (item.type && item.type != 'sub' && item.type != 'html') {\r
+                        $input\r
+                            .on('focus', handle.focusInput)\r
+                            .on('blur', handle.blurInput);\r
+                        \r
+                        if (item.events) {\r
+                            $input.on(item.events);\r
+                        }\r
+                    }\r
+                \r
+                    // add icons\r
+                    if (item.icon) {\r
+                        $t.addClass("icon icon-" + item.icon);\r
+                    }\r
+                }\r
+                \r
+                // cache contained elements\r
+                item.$input = $input;\r
+                item.$label = $label;\r
+\r
+                // attach item to menu\r
+                $t.appendTo(opt.$menu);\r
+                \r
+                // Disable text selection\r
+                if (!opt.hasTypes) {\r
+                    if($.browser.msie) {\r
+                        $t.on('selectstart.disableTextSelect', handle.abortevent);\r
+                    } else if(!$.browser.mozilla) {\r
+                        $t.on('mousedown.disableTextSelect', handle.abortevent);\r
+                    }\r
+                }\r
+            });\r
+            // attach contextMenu to <body> (to bypass any possible overflow:hidden issues on parents of the trigger element)\r
+            if (!opt.$node) {\r
+                opt.$menu.css('display', 'none').addClass('context-menu-root');\r
+            }\r
+            opt.$menu.appendTo(opt.appendTo || document.body);\r
+        },\r
+        update: function(opt, root) {\r
+            var $this = this;\r
+            if (root === undefined) {\r
+                root = opt;\r
+                // determine widths of submenus, as CSS won't grow them automatically\r
+                // position:absolute > position:absolute; min-width:100; max-width:200; results in width: 100;\r
+                // kinda sucks hard...\r
+                opt.$menu.find('ul').andSelf().css({position: 'static', display: 'block'}).each(function(){\r
+                    var $this = $(this);\r
+                    $this.width($this.css('position', 'absolute').width())\r
+                        .css('position', 'static');\r
+                }).css({position: '', display: ''});\r
+            }\r
+            // re-check disabled for each item\r
+            opt.$menu.children().each(function(){\r
+                var $item = $(this),\r
+                    key = $item.data('contextMenuKey'),\r
+                    item = opt.items[key],\r
+                    disabled = ($.isFunction(item.disabled) && item.disabled.call($this, key, root)) || item.disabled === true;\r
+\r
+                // dis- / enable item\r
+                $item[disabled ? 'addClass' : 'removeClass']('disabled');\r
+                \r
+                if (item.type) {\r
+                    // dis- / enable input elements\r
+                    $item.find('input, select, textarea').prop('disabled', disabled);\r
+                    \r
+                    // update input states\r
+                    switch (item.type) {\r
+                        case 'text':\r
+                        case 'textarea':\r
+                            item.$input.val(item.value || "");\r
+                            break;\r
+                            \r
+                        case 'checkbox':\r
+                        case 'radio':\r
+                            item.$input.val(item.value || "").prop('checked', !!item.selected);\r
+                            break;\r
+                            \r
+                        case 'select':\r
+                            item.$input.val(item.selected || "");\r
+                            break;\r
+                    }\r
+                }\r
+                \r
+                if (item.$menu) {\r
+                    // update sub-menu\r
+                    op.update.call($this, item, root);\r
+                }\r
+            });\r
+        },\r
+        layer: function(opt, zIndex) {\r
+            // add transparent layer for click area\r
+            // filter and background for Internet Explorer, Issue #23\r
+            return opt.$layer = $('<div id="context-menu-layer" style="position:fixed; z-index:' + zIndex + '; top:0; left:0; opacity: 0; filter: alpha(opacity=0); background-color: #000;"></div>')\r
+                .css({height: $win.height(), width: $win.width(), display: 'block'})\r
+                .data('contextMenuRoot', opt)\r
+                .insertBefore(this)\r
+                .on('contextmenu', handle.abortevent)\r
+                .on('mousedown', handle.layerClick);\r
+        }\r
+    };\r
+\r
+// split accesskey according to http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#assigned-access-key\r
+function splitAccesskey(val) {\r
+    var t = val.split(/\s+/),\r
+        keys = [];\r
+        \r
+    for (var i=0, k; k = t[i]; i++) {\r
+        k = k[0].toUpperCase(); // first character only\r
+        // theoretically non-accessible characters should be ignored, but different systems, different keyboard layouts, ... screw it.\r
+        // a map to look up already used access keys would be nice\r
+        keys.push(k);\r
+    }\r
+    \r
+    return keys;\r
+}\r
+\r
+// handle contextMenu triggers\r
+$.fn.contextMenu = function(operation) {\r
+    if (operation === undefined) {\r
+        this.first().trigger('contextmenu');\r
+    } else if (operation.x && operation.y) {\r
+        this.first().trigger(jQuery.Event("contextmenu", {pageX: operation.x, pageY: operation.y}));\r
+    } else if (operation === "hide") {\r
+        var $menu = this.data('contextMenu').$menu;\r
+        $menu && $menu.trigger('contextmenu:hide');\r
+    } else if (operation) {\r
+        this.removeClass('context-menu-disabled');\r
+    } else if (!operation) {\r
+        this.addClass('context-menu-disabled');\r
+    }\r
+    \r
+    return this;\r
+};\r
+\r
+// manage contextMenu instances\r
+$.contextMenu = function(operation, options) {\r
+    if (typeof operation != 'string') {\r
+        options = operation;\r
+        operation = 'create';\r
+    }\r
+    \r
+    if (typeof options == 'string') {\r
+        options = {selector: options};\r
+    } else if (options === undefined) {\r
+        options = {};\r
+    }\r
+    \r
+    // merge with default options\r
+    var o = $.extend(true, {}, defaults, options || {}),\r
+        $body = $body = $(document);\r
+    \r
+    switch (operation) {\r
+        case 'create':\r
+            // no selector no joy\r
+            if (!o.selector) {\r
+                throw new Error('No selector specified');\r
+            }\r
+            // make sure internal classes are not bound to\r
+            if (o.selector.match(/.context-menu-(list|item|input)($|\s)/)) {\r
+                throw new Error('Cannot bind to selector "' + o.selector + '" as it contains a reserved className');\r
+            }\r
+            if (!o.build && (!o.items || $.isEmptyObject(o.items))) {\r
+                throw new Error('No Items sepcified');\r
+            }\r
+            counter ++;\r
+            o.ns = '.contextMenu' + counter;\r
+            namespaces[o.selector] = o.ns;\r
+            menus[o.ns] = o;\r
+            \r
+            if (!initialized) {\r
+                // make sure item click is registered first\r
+                $body\r
+                    .on({\r
+                        'contextmenu:hide.contextMenu': handle.hideMenu,\r
+                        'prevcommand.contextMenu': handle.prevItem,\r
+                        'nextcommand.contextMenu': handle.nextItem,\r
+                        'contextmenu.contextMenu': handle.abortevent,\r
+                        'mouseenter.contextMenu': handle.menuMouseenter,\r
+                        'mouseleave.contextMenu': handle.menuMouseleave\r
+                    }, '.context-menu-list')\r
+                    .on('mouseup.contextMenu', '.context-menu-input', handle.inputClick)\r
+                    .on({\r
+                        'mouseup.contextMenu': handle.itemClick,\r
+                        'contextmenu:focus.contextMenu': handle.focusItem,\r
+                        'contextmenu:blur.contextMenu': handle.blurItem,\r
+                        'contextmenu.contextMenu': handle.abortevent,\r
+                        'mouseenter.contextMenu': handle.itemMouseenter,\r
+                        'mouseleave.contextMenu': handle.itemMouseleave\r
+                    }, '.context-menu-item');\r
+\r
+                initialized = true;\r
+            }\r
+            \r
+            // engage native contextmenu event\r
+            $body\r
+                .on('contextmenu' + o.ns, o.selector, o, handle.contextmenu);\r
+            \r
+            switch (o.trigger) {\r
+                case 'hover':\r
+                        $body\r
+                            .on('mouseenter' + o.ns, o.selector, o, handle.mouseenter)\r
+                            .on('mouseleave' + o.ns, o.selector, o, handle.mouseleave);                    \r
+                    break;\r
+                    \r
+                case 'left':\r
+                        $body.on('click' + o.ns, o.selector, o, handle.click);\r
+                    break;\r
+                /*\r
+                default:\r
+                    // http://www.quirksmode.org/dom/events/contextmenu.html\r
+                    $body\r
+                        .on('mousedown' + o.ns, o.selector, o, handle.mousedown)\r
+                        .on('mouseup' + o.ns, o.selector, o, handle.mouseup);\r
+                    break;\r
+                */\r
+            }\r
+            \r
+            // create menu\r
+            if (!o.build) {\r
+                op.create(o);\r
+            }\r
+            break;\r
+        \r
+        case 'destroy':\r
+            if (!o.selector) {\r
+                $body.off('.contextMenu .contextMenuAutoHide');\r
+                $.each(namespaces, function(key, value) {\r
+                    $body.off(value);\r
+                });\r
+                \r
+                namespaces = {};\r
+                menus = {};\r
+                counter = 0;\r
+                initialized = false;\r
+                \r
+                $('.context-menu-list').remove();\r
+            } else if (namespaces[o.selector]) {\r
+                try {\r
+                    if (menus[namespaces[o.selector]].$menu) {\r
+                        menus[namespaces[o.selector]].$menu.remove();\r
+                    }\r
+                    \r
+                    delete menus[namespaces[o.selector]];\r
+                } catch(e) {\r
+                    menus[namespaces[o.selector]] = null;\r
+                }\r
+                \r
+                $body.off(namespaces[o.selector]);\r
+            }\r
+            break;\r
+        \r
+        case 'html5':\r
+            // if <command> or <menuitem> are not handled by the browser,\r
+            // or options was a bool true,\r
+            // initialize $.contextMenu for them\r
+            if ((!$.support.htmlCommand && !$.support.htmlMenuitem) || (typeof options == "boolean" && options)) {\r
+                $('menu[type="context"]').each(function() {\r
+                    if (this.id) {\r
+                        $.contextMenu({\r
+                            selector: '[contextmenu=' + this.id +']',\r
+                            items: $.contextMenu.fromMenu(this)\r
+                        });\r
+                    }\r
+                }).css('display', 'none');\r
+            }\r
+            break;\r
+        \r
+        default:\r
+            throw new Error('Unknown operation "' + operation + '"');\r
+    }\r
+    \r
+    return this;\r
+};\r
+\r
+// import values into <input> commands\r
+$.contextMenu.setInputValues = function(opt, data) {\r
+    if (data === undefined) {\r
+        data = {};\r
+    }\r
+    \r
+    $.each(opt.inputs, function(key, item) {\r
+        switch (item.type) {\r
+            case 'text':\r
+            case 'textarea':\r
+                item.value = data[key] || "";\r
+                break;\r
+\r
+            case 'checkbox':\r
+                item.selected = data[key] ? true : false;\r
+                break;\r
+                \r
+            case 'radio':\r
+                item.selected = (data[item.radio] || "") == item.value ? true : false;\r
+                break;\r
+            \r
+            case 'select':\r
+                item.selected = data[key] || "";\r
+                break;\r
+        }\r
+    });\r
+};\r
+\r
+// export values from <input> commands\r
+$.contextMenu.getInputValues = function(opt, data) {\r
+    if (data === undefined) {\r
+        data = {};\r
+    }\r
+    \r
+    $.each(opt.inputs, function(key, item) {\r
+        switch (item.type) {\r
+            case 'text':\r
+            case 'textarea':\r
+            case 'select':\r
+                data[key] = item.$input.val();\r
+                break;\r
+\r
+            case 'checkbox':\r
+                data[key] = item.$input.prop('checked');\r
+                break;\r
+                \r
+            case 'radio':\r
+                if (item.$input.prop('checked')) {\r
+                    data[item.radio] = item.value;\r
+                }\r
+                break;\r
+        }\r
+    });\r
+    \r
+    return data;\r
+};\r
+\r
+// find <label for="xyz">\r
+function inputLabel(node) {\r
+    return (node.id && $('label[for="'+ node.id +'"]').val()) || node.name;\r
+}\r
+\r
+// convert <menu> to items object\r
+function menuChildren(items, $children, counter) {\r
+    if (!counter) {\r
+        counter = 0;\r
+    }\r
+    \r
+    $children.each(function() {\r
+        var $node = $(this),\r
+            node = this,\r
+            nodeName = this.nodeName.toLowerCase(),\r
+            label,\r
+            item;\r
+        \r
+        // extract <label><input>\r
+        if (nodeName == 'label' && $node.find('input, textarea, select').length) {\r
+            label = $node.text();\r
+            $node = $node.children().first();\r
+            node = $node.get(0);\r
+            nodeName = node.nodeName.toLowerCase();\r
+        }\r
+        \r
+        /*\r
+         * <menu> accepts flow-content as children. that means <embed>, <canvas> and such are valid menu items.\r
+         * Not being the sadistic kind, $.contextMenu only accepts:\r
+         * <command>, <menuitem>, <hr>, <span>, <p> <input [text, radio, checkbox]>, <textarea>, <select> and of course <menu>.\r
+         * Everything else will be imported as an html node, which is not interfaced with contextMenu.\r
+         */\r
+        \r
+        // http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#concept-command\r
+        switch (nodeName) {\r
+            // http://www.whatwg.org/specs/web-apps/current-work/multipage/interactive-elements.html#the-menu-element\r
+            case 'menu':\r
+                item = {name: $node.attr('label'), items: {}};\r
+                menuChildren(item.items, $node.children(), counter);\r
+                break;\r
+            \r
+            // http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#using-the-a-element-to-define-a-command\r
+            case 'a':\r
+            // http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#using-the-button-element-to-define-a-command\r
+            case 'button':\r
+                item = {\r
+                    name: $node.text(),\r
+                    disabled: !!$node.attr('disabled'),\r
+                    callback: (function(){ return function(){ $node.click(); }; })()\r
+                };\r
+                break;\r
+            \r
+            // http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#using-the-command-element-to-define-a-command\r
+\r
+            case 'menuitem':\r
+            case 'command':\r
+                switch ($node.attr('type')) {\r
+                    case undefined:\r
+                    case 'command':\r
+                    case 'menuitem':\r
+                        item = {\r
+                            name: $node.attr('label'),\r
+                            disabled: !!$node.attr('disabled'),\r
+                            callback: (function(){ return function(){ $node.click(); }; })()\r
+                        };\r
+                        break;\r
+                        \r
+                    case 'checkbox':\r
+                        item = {\r
+                            type: 'checkbox',\r
+                            disabled: !!$node.attr('disabled'),\r
+                            name: $node.attr('label'),\r
+                            selected: !!$node.attr('checked')\r
+                        };\r
+                        break;\r
+                        \r
+                    case 'radio':\r
+                        item = {\r
+                            type: 'radio',\r
+                            disabled: !!$node.attr('disabled'),\r
+                            name: $node.attr('label'),\r
+                            radio: $node.attr('radiogroup'),\r
+                            value: $node.attr('id'),\r
+                            selected: !!$node.attr('checked')\r
+                        };\r
+                        break;\r
+                        \r
+                    default:\r
+                        item = undefined;\r
+                }\r
+                break;\r
\r
+            case 'hr':\r
+                item = '-------';\r
+                break;\r
+                \r
+            case 'input':\r
+                switch ($node.attr('type')) {\r
+                    case 'text':\r
+                        item = {\r
+                            type: 'text',\r
+                            name: label || inputLabel(node),\r
+                            disabled: !!$node.attr('disabled'),\r
+                            value: $node.val()\r
+                        };\r
+                        break;\r
+                        \r
+                    case 'checkbox':\r
+                        item = {\r
+                            type: 'checkbox',\r
+                            name: label || inputLabel(node),\r
+                            disabled: !!$node.attr('disabled'),\r
+                            selected: !!$node.attr('checked')\r
+                        };\r
+                        break;\r
+                        \r
+                    case 'radio':\r
+                        item = {\r
+                            type: 'radio',\r
+                            name: label || inputLabel(node),\r
+                            disabled: !!$node.attr('disabled'),\r
+                            radio: !!$node.attr('name'),\r
+                            value: $node.val(),\r
+                            selected: !!$node.attr('checked')\r
+                        };\r
+                        break;\r
+                    \r
+                    default:\r
+                        item = undefined;\r
+                        break;\r
+                }\r
+                break;\r
+                \r
+            case 'select':\r
+                item = {\r
+                    type: 'select',\r
+                    name: label || inputLabel(node),\r
+                    disabled: !!$node.attr('disabled'),\r
+                    selected: $node.val(),\r
+                    options: {}\r
+                };\r
+                $node.children().each(function(){\r
+                    item.options[this.value] = $(this).text();\r
+                });\r
+                break;\r
+                \r
+            case 'textarea':\r
+                item = {\r
+                    type: 'textarea',\r
+                    name: label || inputLabel(node),\r
+                    disabled: !!$node.attr('disabled'),\r
+                    value: $node.val()\r
+                };\r
+                break;\r
+            \r
+            case 'label':\r
+                break;\r
+            \r
+            default:\r
+                item = {type: 'html', html: $node.clone(true)};\r
+                break;\r
+        }\r
+        \r
+        if (item) {\r
+            counter++;\r
+            items['key' + counter] = item;\r
+        }\r
+    });\r
+}\r
+\r
+// convert html5 menu\r
+$.contextMenu.fromMenu = function(element) {\r
+    var $this = $(element),\r
+        items = {};\r
+        \r
+    menuChildren(items, $this.children());\r
+    \r
+    return items;\r
+};\r
+\r
+// make defaults accessible\r
+$.contextMenu.defaults = defaults;\r
+$.contextMenu.types = types;\r
+\r
+})(jQuery);\r
diff --git a/redakcja/static/contextmenu/jquery.ui.position.js b/redakcja/static/contextmenu/jquery.ui.position.js
new file mode 100755 (executable)
index 0000000..cafdf02
--- /dev/null
@@ -0,0 +1,252 @@
+/*!
+ * jQuery UI Position 1.8.13
+ *
+ * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Position
+ */
+(function( $, undefined ) {
+
+$.ui = $.ui || {};
+
+var horizontalPositions = /left|center|right/,
+       verticalPositions = /top|center|bottom/,
+       center = "center",
+       _position = $.fn.position,
+       _offset = $.fn.offset;
+
+$.fn.position = function( options ) {
+       if ( !options || !options.of ) {
+               return _position.apply( this, arguments );
+       }
+
+       // make a copy, we don't want to modify arguments
+       options = $.extend( {}, options );
+
+       var target = $( options.of ),
+               targetElem = target[0],
+               collision = ( options.collision || "flip" ).split( " " ),
+               offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
+               targetWidth,
+               targetHeight,
+               basePosition;
+
+       if ( targetElem.nodeType === 9 ) {
+               targetWidth = target.width();
+               targetHeight = target.height();
+               basePosition = { top: 0, left: 0 };
+       // TODO: use $.isWindow() in 1.9
+       } else if ( targetElem.setTimeout ) {
+               targetWidth = target.width();
+               targetHeight = target.height();
+               basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
+       } else if ( targetElem.preventDefault ) {
+               // force left top to allow flipping
+               options.at = "left top";
+               targetWidth = targetHeight = 0;
+               basePosition = { top: options.of.pageY, left: options.of.pageX };
+       } else {
+               targetWidth = target.outerWidth();
+               targetHeight = target.outerHeight();
+               basePosition = target.offset();
+       }
+
+       // force my and at to have valid horizontal and veritcal positions
+       // if a value is missing or invalid, it will be converted to center 
+       $.each( [ "my", "at" ], function() {
+               var pos = ( options[this] || "" ).split( " " );
+               if ( pos.length === 1) {
+                       pos = horizontalPositions.test( pos[0] ) ?
+                               pos.concat( [center] ) :
+                               verticalPositions.test( pos[0] ) ?
+                                       [ center ].concat( pos ) :
+                                       [ center, center ];
+               }
+               pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
+               pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
+               options[ this ] = pos;
+       });
+
+       // normalize collision option
+       if ( collision.length === 1 ) {
+               collision[ 1 ] = collision[ 0 ];
+       }
+
+       // normalize offset option
+       offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
+       if ( offset.length === 1 ) {
+               offset[ 1 ] = offset[ 0 ];
+       }
+       offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
+
+       if ( options.at[0] === "right" ) {
+               basePosition.left += targetWidth;
+       } else if ( options.at[0] === center ) {
+               basePosition.left += targetWidth / 2;
+       }
+
+       if ( options.at[1] === "bottom" ) {
+               basePosition.top += targetHeight;
+       } else if ( options.at[1] === center ) {
+               basePosition.top += targetHeight / 2;
+       }
+
+       basePosition.left += offset[ 0 ];
+       basePosition.top += offset[ 1 ];
+
+       return this.each(function() {
+               var elem = $( this ),
+                       elemWidth = elem.outerWidth(),
+                       elemHeight = elem.outerHeight(),
+                       marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
+                       marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
+                       collisionWidth = elemWidth + marginLeft +
+                               ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
+                       collisionHeight = elemHeight + marginTop +
+                               ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
+                       position = $.extend( {}, basePosition ),
+                       collisionPosition;
+
+               if ( options.my[0] === "right" ) {
+                       position.left -= elemWidth;
+               } else if ( options.my[0] === center ) {
+                       position.left -= elemWidth / 2;
+               }
+
+               if ( options.my[1] === "bottom" ) {
+                       position.top -= elemHeight;
+               } else if ( options.my[1] === center ) {
+                       position.top -= elemHeight / 2;
+               }
+
+               // prevent fractions (see #5280)
+               position.left = Math.round( position.left );
+               position.top = Math.round( position.top );
+
+               collisionPosition = {
+                       left: position.left - marginLeft,
+                       top: position.top - marginTop
+               };
+
+               $.each( [ "left", "top" ], function( i, dir ) {
+                       if ( $.ui.position[ collision[i] ] ) {
+                               $.ui.position[ collision[i] ][ dir ]( position, {
+                                       targetWidth: targetWidth,
+                                       targetHeight: targetHeight,
+                                       elemWidth: elemWidth,
+                                       elemHeight: elemHeight,
+                                       collisionPosition: collisionPosition,
+                                       collisionWidth: collisionWidth,
+                                       collisionHeight: collisionHeight,
+                                       offset: offset,
+                                       my: options.my,
+                                       at: options.at
+                               });
+                       }
+               });
+
+               if ( $.fn.bgiframe ) {
+                       elem.bgiframe();
+               }
+               elem.offset( $.extend( position, { using: options.using } ) );
+       });
+};
+
+$.ui.position = {
+       fit: {
+               left: function( position, data ) {
+                       var win = $( window ),
+                               over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
+                       position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
+               },
+               top: function( position, data ) {
+                       var win = $( window ),
+                               over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
+                       position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
+               }
+       },
+
+       flip: {
+               left: function( position, data ) {
+                       if ( data.at[0] === center ) {
+                               return;
+                       }
+                       var win = $( window ),
+                               over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
+                               myOffset = data.my[ 0 ] === "left" ?
+                                       -data.elemWidth :
+                                       data.my[ 0 ] === "right" ?
+                                               data.elemWidth :
+                                               0,
+                               atOffset = data.at[ 0 ] === "left" ?
+                                       data.targetWidth :
+                                       -data.targetWidth,
+                               offset = -2 * data.offset[ 0 ];
+                       position.left += data.collisionPosition.left < 0 ?
+                               myOffset + atOffset + offset :
+                               over > 0 ?
+                                       myOffset + atOffset + offset :
+                                       0;
+               },
+               top: function( position, data ) {
+                       if ( data.at[1] === center ) {
+                               return;
+                       }
+                       var win = $( window ),
+                               over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
+                               myOffset = data.my[ 1 ] === "top" ?
+                                       -data.elemHeight :
+                                       data.my[ 1 ] === "bottom" ?
+                                               data.elemHeight :
+                                               0,
+                               atOffset = data.at[ 1 ] === "top" ?
+                                       data.targetHeight :
+                                       -data.targetHeight,
+                               offset = -2 * data.offset[ 1 ];
+                       position.top += data.collisionPosition.top < 0 ?
+                               myOffset + atOffset + offset :
+                               over > 0 ?
+                                       myOffset + atOffset + offset :
+                                       0;
+               }
+       }
+};
+
+// offset setter from jQuery 1.4
+if ( !$.offset.setOffset ) {
+       $.offset.setOffset = function( elem, options ) {
+               // set position first, in-case top/left are set even on static elem
+               if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
+                       elem.style.position = "relative";
+               }
+               var curElem   = $( elem ),
+                       curOffset = curElem.offset(),
+                       curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
+                       curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
+                       props     = {
+                               top:  (options.top  - curOffset.top)  + curTop,
+                               left: (options.left - curOffset.left) + curLeft
+                       };
+               
+               if ( 'using' in options ) {
+                       options.using.call( elem, props );
+               } else {
+                       curElem.css( props );
+               }
+       };
+
+       $.fn.offset = function( options ) {
+               var elem = this[ 0 ];
+               if ( !elem || !elem.ownerDocument ) { return null; }
+               if ( options ) { 
+                       return this.each(function() {
+                               $.offset.setOffset( this, options );
+                       });
+               }
+               return _offset.call( this );
+       };
+}
+
+}( jQuery ));