]> git.andy128k.dev Git - ipf.git/commitdiff
Tiny MCE images plugin
authoravl <alex.litovchenko@gmail.com>
Thu, 2 Oct 2008 20:51:13 +0000 (23:51 +0300)
committeravl <alex.litovchenko@gmail.com>
Thu, 2 Oct 2008 20:51:13 +0000 (23:51 +0300)
44 files changed:
ipf.php
ipf/admin/media/tiny_mce/plugins/images/css/default.css [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/desktop.ini [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/editor_plugin.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/editor_plugin_src.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/fancy.htm [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images.htm [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/arrow.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/back/back.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/back/browse.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/back/clean.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/back/del_file.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/back/files.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/back/larr.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/back/left.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/back/new_folder.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/back/ok.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/back/right.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/bar.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/failed.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/file.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/folder.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/icon.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/progress.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/success.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/upload_back.gif [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/images/uploading.png [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/js/FancyUpload2.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/js/Fx.ProgressBar.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/js/JsHttpRequest.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/js/Swiff.Uploader.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/js/Swiff.Uploader.swf [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/js/images.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/js/mootools.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/langs/en.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/langs/en_dlg.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/langs/ru.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/langs/ru_dlg.js [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/read_ru.txt [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/server_connector/JsHttpRequest.php [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/server_connector/ajax.php [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/server_connector/files_conn.php [new file with mode: 0755]
ipf/admin/media/tiny_mce/plugins/images/server_connector/tinyimages.php [new file with mode: 0755]
ipf/form/widget/htmlinput.php

diff --git a/ipf.php b/ipf.php
index 491a505b61a656ffb9888119e39359fea5685882..15a1692ab1b8856095d2d13b7368813a59a7a7fd 100644 (file)
--- a/ipf.php
+++ b/ipf.php
@@ -75,6 +75,10 @@ final class IPF{
             IPF::$settings['media_url'] = '/media/';
         }
 
+        if (!isset(IPF::$settings['tiny_mce_url'])){
+            IPF::$settings['tiny_mce_url'] = '/media/tiny_mce/';
+        }
+
         if (!isset(IPF::$settings['admin_media_url'])){
             IPF::$settings['admin_media_url'] = '/ipf/ipf/admin/media/';
         }
diff --git a/ipf/admin/media/tiny_mce/plugins/images/css/default.css b/ipf/admin/media/tiny_mce/plugins/images/css/default.css
new file mode 100755 (executable)
index 0000000..acac999
--- /dev/null
@@ -0,0 +1,216 @@
+.all {\r
+       width:100%;\r
+       height:100%;\r
+}\r
+html, body { height:99%; }\r
+html, body, td, th {\r
+       padding:0px;\r
+       margin:0px;\r
+       vertical-align:top;\r
+       font-family:Verdana,Arial,Helvetica,sans-serif;\r
+       font-size:10px;\r
+}\r
+img { border:none; }\r
+\r
+.header {\r
+       height:50px;\r
+}\r
+\r
+.header .path {\r
+       margin-bottom:3px;\r
+       padding:2px;\r
+       font-size:14px;\r
+       border-left: #888 solid 1px;\r
+       border-top: #888 solid 1px;\r
+       border-right: #ccc solid 1px;\r
+       border-bottom: #ccc solid 1px;\r
+}\r
+.header .path a {\r
+       background: transparent url(../images/arrow.gif) left center no-repeat;\r
+       padding: 2px 10px 3px 15px;\r
+       text-decoration:none;\r
+}\r
+.header .path a:hover { background-color:#cfe1fc; }\r
+\r
+.header img { vertical-align:middle; }\r
+.header .path .first { background:none; padding:0px 10px 0px 0px; }\r
+\r
+.panel { background:#468da0 url(../images/back/back.gif) top repeat-x; height:32px; }\r
+.p1 { background:transparent url(../images/back/left.gif) left no-repeat; height:32px; }\r
+.p2 { background:transparent url(../images/back/right.gif) right no-repeat; height:32px; }\r
+.panel .btns a {\r
+       color: white;\r
+       height:32px;\r
+       text-decoration:none;\r
+       margin:0 5px 0 10px;\r
+}\r
+.panel .btns img { vertical-align:middle; }\r
+\r
+.left {\r
+       border-right:1px solid #ddd;\r
+       width:150px;\r
+}\r
+\r
+.content {\r
+       \r
+}\r
+\r
+h1.blue_header {\r
+       font-size:16px;\r
+       font-weight:normal;\r
+       color:#6FA8DC;\r
+       margin-bottom:10px;\r
+}\r
+\r
+.folder {\r
+       background: transparent url(../images/folder.gif) left center no-repeat;\r
+       margin: 1px 10px 1px 5px;\r
+       padding:1px;\r
+       height:16px;\r
+       font-size:12px;\r
+}\r
+\r
+.folder a {\r
+       padding:0 0 0 20px;\r
+       text-decoration:none;\r
+       outline: none;\r
+}\r
+\r
+\r
+.item {\r
+       width:120px;\r
+       height:150px;\r
+       margin:5px 0 0 5px;\r
+       float:left;\r
+       overflow:hidden;\r
+}\r
+.item:hover { background-color:#deecff; }\r
+.item img { width:100px; height:100px; margin:10px; }\r
+.item .labels { color:#0a4d76; text-align:center; }\r
+.item_ {\r
+       background-color:#cfe1fc;\r
+}\r
+.item_:hover {\r
+       background-color:#bfd9ff;\r
+}\r
+\r
+.upload {\r
+       background:transparent url(../images/upload_back.gif) top repeat-x;\r
+       text-align: center;\r
+}\r
+.upload input {\r
+       font-size: 20px;\r
+       font-family: serif;\r
+       margin: 10px 0 10px 0;\r
+       width: 150px;\r
+}\r
+\r
+#mainfield {\r
+       width:530px;\r
+       height:475px;\r
+       overflow:scroll;\r
+}\r
+\r
+\r
+\r
+/* Fancy */\r
+#demo-status\r
+{\r
+    /*background-color:        #F9F7ED;*/\r
+    padding:                10px 15px;\r
+    width:                    420px;\r
+}\r
\r
+#demo-status fieldset\r
+{\r
+    padding:                0.5em 1em;\r
+    border:                    none;\r
+}\r
\r
+#demo-status legend\r
+{\r
+    display:                block;\r
+    font:                    1.2em bold Verdana, Geneva, Arial, Helvetica, sans-serif;\r
+}\r
\r
+#demo-status .progress\r
+{\r
+    background:                white url(../images/progress.gif) no-repeat;\r
+    background-position:    +50% 0;\r
+    margin-right:            0.5em;\r
+}\r
\r
+#demo-status .progress-text\r
+{\r
+    font-size:                0.9em;\r
+    font-weight:            bold;\r
+}\r
\r
+#demo-list\r
+{\r
+    list-style:                none;\r
+    width:                    450px;\r
+    /*overflow:                auto;*/\r
+    margin:                    0;\r
+}\r
\r
+#demo-list li.file\r
+{\r
+    border-bottom:            1px solid #eee;\r
+    /*overflow:                auto;*/\r
+    background:                url(../images/file.png) no-repeat 4px 4px;\r
+}\r
+#demo-list li.file.file-uploading\r
+{\r
+    background-image:        url(../images/uploading.png);\r
+    background-color:        #D9DDE9;\r
+}\r
+#demo-list li.file.file-success\r
+{\r
+    background-image:        url(../images/success.png);\r
+}\r
+#demo-list li.file.file-failed\r
+{\r
+    background-image:        url(../images/failed.png);\r
+}\r
\r
+#demo-list li.file .file-name\r
+{\r
+    font-size:                1.2em;\r
+    margin-left:            44px;\r
+    display:                block;\r
+    line-height:            40px;\r
+    height:                    40px;\r
+    font-weight:            bold;\r
+}\r
+#demo-list li.file .file-size\r
+{\r
+    line-height:            20px;\r
+    float:                    right;\r
+}\r
+#demo-list li.file .file-info\r
+{\r
+    display:                block;\r
+    margin-left:            44px;\r
+}\r
+#demo-list li.file .file-remove\r
+{\r
+    clear:                    right;\r
+    float:                    right;\r
+    line-height:            20px;\r
+}\r
+.overall-title {\r
+       font-size: 16px;\r
+       margin: 0 0 3px 5px;\r
+}\r
+.current-title {\r
+       font-size: 16px;\r
+       margin: 8px 0 3px 5px;\r
+}\r
+.current-text {\r
+       position: absolute;\r
+       right:10px;\r
+       top: 65px;\r
+       width:320px;\r
+       font-size: 15px;\r
+}
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/desktop.ini b/ipf/admin/media/tiny_mce/plugins/images/desktop.ini
new file mode 100755 (executable)
index 0000000..8a96fbb
--- /dev/null
@@ -0,0 +1,4 @@
+[ViewState]\r
+Mode=\r
+Vid=\r
+FolderType=NotSpecified\r
diff --git a/ipf/admin/media/tiny_mce/plugins/images/editor_plugin.js b/ipf/admin/media/tiny_mce/plugins/images/editor_plugin.js
new file mode 100755 (executable)
index 0000000..dd30479
--- /dev/null
@@ -0,0 +1 @@
+(function(){tinymce.create('tinymce.plugins.Images',{init:function(ed,url){ed.addCommand('mceImages',function(){ed.windowManager.open({file:url+'/images.htm',width:700,height:550,inline:1},{plugin_url:url})});ed.addButton('images',{title:'images.desc',cmd:'mceImages',image:url+'/images/icon.gif'});ed.onNodeChange.add(function(ed,cm,n){cm.setActive('images',n.nodeName=='IMG')})},getInfo:function(){return{longname:'Images',author:'Antonov Andrey',authorurl:'http://dustweb.ru/',infourl:'http://dustweb.ru/log/projects/tinymce_images/',version:"1.0"}}});tinymce.PluginManager.add('images',tinymce.plugins.Images)})();
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/editor_plugin_src.js b/ipf/admin/media/tiny_mce/plugins/images/editor_plugin_src.js
new file mode 100755 (executable)
index 0000000..16cb6f3
--- /dev/null
@@ -0,0 +1,38 @@
+(function() {\r
+       tinymce.create('tinymce.plugins.Images', {\r
+               init : function(ed, url) {\r
+                       ed.addCommand('mceImages', function() {\r
+                               ed.windowManager.open({\r
+                                       file : url + '/images.htm',\r
+                                       width : 700,\r
+                                       height : 550,\r
+                                       inline : 1\r
+                               }, {\r
+                                       plugin_url : url\r
+                               });\r
+                       });\r
+                       \r
+                       ed.addButton('images', {\r
+                               title : 'images.desc',\r
+                               cmd : 'mceImages',\r
+                               image : url + '/images/icon.gif'\r
+                       });\r
+                       \r
+                       ed.onNodeChange.add(function(ed, cm, n) {\r
+                               cm.setActive('images', n.nodeName == 'IMG');\r
+                       });\r
+               },\r
+               \r
+               getInfo : function() {\r
+                       return {\r
+                               longname : 'Images',\r
+                               author : 'Antonov Andrey',\r
+                               authorurl : 'http://dustweb.ru/',\r
+                               infourl : 'http://dustweb.ru/log/projects/tinymce_images/',\r
+                               version : "1.0"\r
+                       };\r
+               }\r
+       });\r
+       \r
+       tinymce.PluginManager.add('images', tinymce.plugins.Images);\r
+})();
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/fancy.htm b/ipf/admin/media/tiny_mce/plugins/images/fancy.htm
new file mode 100755 (executable)
index 0000000..779f2af
--- /dev/null
@@ -0,0 +1,110 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+       <title>{#images_dlg.fancy_title}</title>\r
+       <link href="css/default.css" rel="stylesheet" type="text/css"/>\r
+       \r
+       <script type="text/javascript" src="../../tiny_mce_popup.js"></script>\r
+       <script type="text/javascript" src="js/mootools.js"></script>\r
+       <script type="text/javascript" src="js/Swiff.Uploader.js"></script>\r
+       <script type="text/javascript" src="js/Fx.ProgressBar.js"></script>\r
+       <script type="text/javascript" src="js/FancyUpload2.js"></script>\r
+       <script type="text/javascript">\r
+\r
+function getURLParam(strParamName) {\r
+  var strReturn = "";\r
+  var strHref = window.location.href;\r
+  if ( strHref.indexOf("?") > -1 ){\r
+    var strQueryString = strHref.substr(strHref.indexOf("?")).toLowerCase();\r
+    var aQueryString = strQueryString.split("&");\r
+    for ( var iParam = 0; iParam < aQueryString.length; iParam++ ){\r
+      if (\r
+aQueryString[iParam].indexOf(strParamName.toLowerCase() + "=") > -1 ){\r
+        var aParam = aQueryString[iParam].split("=");\r
+        strReturn = aParam[1];\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  return unescape(strReturn);\r
+}\r
+\r
+\r
+var allcookies = document.cookie;\r
+var pos = allcookies.indexOf("PHPSESSID=");\r
+if(pos != -1) {\r
+       var start = pos + 10;\r
+       var end = allcookies.indexOf(";", start);\r
+       if(end == -1) end = allcookies.length;\r
+       var value = allcookies.substring(start, end);\r
+       value = unescape(value);\r
+}\r
+\r
+var urlregexp = /([\s\S]*)\/fancy\.htm\?/im;\r
+var urlmatch = urlregexp.exec(window.location.href);\r
+var urlpart = urlmatch[1];\r
+\r
+window.addEvent('load', function() {\r
+    var swiffy = new FancyUpload2($('demo-status'), $('demo-list'), {\r
+        'url': urlpart + '/server_connector/files_conn.php?uri=' + getURLParam('uri') + '&PHPSESSID=' + value + '&lng=' + tinyMCEPopup.editor.settings.language,\r
+        'fieldName': 'photoupload',\r
+        'path': 'js/Swiff.Uploader.swf'\r
+    });\r
+    /**\r
+     * Various interactions\r
+     */\r
+    $('link-2').addEvent('click', function() {\r
+        swiffy.browse({'Images (*.jpg, *.jpeg, *.gif, *.png)': '*.jpg; *.jpeg; *.gif; *.png'});\r
+        return false;\r
+    });\r
+    $('link-22').addEvent('click', function() {\r
+        swiffy.browse({'Images (*.jpg, *.jpeg, *.gif, *.png)': '*.jpg; *.jpeg; *.gif; *.png'});\r
+        return false;\r
+    });\r
+    $('link-3').addEvent('click', function() {\r
+        swiffy.removeFile();\r
+        return false;\r
+    });\r
+    $('link-4').addEvent('click', function() {\r
+        swiffy.upload();\r
+        return false;\r
+    });\r
+});\r
+</script>\r
+       <base target="_self"/>\r
+</head>\r
+<body> \r
+\r
+<div class="panel" style="margin:5px;">\r
+       <div class="p1">\r
+               <div class="p2">\r
+                       <div class="btns">\r
+                               <a href="#" onclick="document.location = 'images.htm?uri=' + getURLParam('uri'); return false;"><img src="images/back/larr.gif" width="16" height="32" alt="{#images_dlg.fancy_back_alt}" /> {#images_dlg.fancy_back}</a>\r
+                               <a href="#" id="link-2"><img src="images/back/browse.gif" width="16" height="32" alt="{#images_dlg.fancy_browse}" /> {#images_dlg.fancy_browse}</a>\r
+                               <a href="#" id="link-4"><img src="images/back/ok.gif" width="16" height="32" alt="{#images_dlg.fancy_begin_upload}"/> {#images_dlg.fancy_upload_files}</a>\r
+                               <a href="#" id="link-3"><img src="images/back/clean.gif" width="13" height="32" alt="{#images_dlg.fancy_clear}"/> {#images_dlg.fancy_clear}</a>\r
+                       </div>\r
+               </div>\r
+       </div>\r
+</div>\r
+\r
+<form action="/admin/files" method="post" enctype="multipart/form-data" id="form-demo">\r
+       <div id="demo-browse" style="display:block; padding:12px 0 0 22px; font-size:16px;"><a style="color:black; text-decoration: none;" href="#" id="link-22">{#images_dlg.fancy_begin_upload_files}</a></div>\r
+    <div id="demo-status" style="display:none;">\r
+        <div>\r
+            <div class="overall-title">{#images_dlg.fancy_general_status}</div>\r
+            <img src="images/bar.gif" class="progress overall-progress" />\r
+        </div>\r
+        <div>\r
+            <div class="current-title">{#images_dlg.fancy_file_status}</div>\r
+            <img src="images/bar.gif" class="progress current-progress" />\r
+        </div>\r
+        <div class="current-text"></div>\r
+    </div>\r
\r
+    <ul id="demo-list"></ul>\r
\r
+</form>\r
+\r
+</body>\r
+</html>\r
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images.htm b/ipf/admin/media/tiny_mce/plugins/images/images.htm
new file mode 100755 (executable)
index 0000000..0a98b80
--- /dev/null
@@ -0,0 +1,239 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+    <head>\r
+        <title>{#images_dlg.title}</title>\r
+        <link href="css/default.css" rel="stylesheet" type="text/css"/>\r
+        <script type="text/javascript" src="../../tiny_mce_popup.js"></script>\r
+        <script type="text/javascript" src="js/images.js"></script>\r
+        \r
+        <script type="text/javascript" src="js/mootools.js"></script>\r
+        \r
+        <base target="_self" />\r
+               <script src="js/JsHttpRequest.js" type="text/javascript"></script>\r
+    </head>\r
+    <body style="display:none;" onKeyDown="setCtrl(event)" onKeyUp="resetCtrl()">\r
+       \r
+       <div style="display: none;">\r
+        <div id="l1">{#images_dlg.del_sel_folder}</div>\r
+        <div id="l2">{#images_dlg.sel_files_for_del}</div>\r
+        <div id="l3">{#images_dlg.files_to_del}</div>\r
+        <div id="l4">{#images_dlg.delete_str}</div>\r
+       </div>\r
+       \r
+<script type="text/javascript">\r
+function getURLParam(strParamName) {\r
+  var strReturn = "";\r
+  var strHref = window.location.href;\r
+  if ( strHref.indexOf("?") > -1 ){\r
+    var strQueryString = strHref.substr(strHref.indexOf("?")).toLowerCase();\r
+    var aQueryString = strQueryString.split("&");\r
+    for ( var iParam = 0; iParam < aQueryString.length; iParam++ ){\r
+      if (\r
+aQueryString[iParam].indexOf(strParamName.toLowerCase() + "=") > -1 ){\r
+        var aParam = aQueryString[iParam].split("=");\r
+        strReturn = aParam[1];\r
+        break;\r
+      }\r
+    }\r
+  }\r
+  return unescape(strReturn);\r
+}\r
+\r
+\r
+var current = '';\r
+var current_file = new Array();\r
+var i=0;\r
+\r
+function activateItem(obj,src) {\r
+       \r
+       if(ctrlState==1) {\r
+               obj.className = 'item item_';\r
+               current = obj.childNodes[1].src;\r
+               \r
+               if(current_file.indexOf(src)==-1) current_file.push(src);\r
+               \r
+       } else {\r
+       \r
+               current_file = [src];\r
+               \r
+               var     list = obj.parentNode.childNodes;\r
+               for(var i=0; i<list.length; i++) {\r
+                       list[i].className = 'item';\r
+               }\r
+               \r
+               obj.className = 'item item_';\r
+               current = obj.childNodes[1].src;\r
+       }\r
+}\r
+\r
+var current_dir = '';\r
+function activateDir(obj, dir) {\r
+       var     list = obj.parentNode.parentNode.childNodes;\r
+       \r
+       for(var i=0; i<list.length; i++) {\r
+               list[i].style.backgroundColor = 'transparent';\r
+       }\r
+       \r
+       obj.parentNode.style.backgroundColor = '#BFD9FF';\r
+       current_dir = dir;\r
+}\r
+\r
+var themiraclevar = '';\r
+function changeFolder(uri) {\r
+       JsHttpRequest.query('server_connector/ajax.php', { 'm': 'tinyimages->ChangeDir', 'uri': uri, 'lng': tinyMCEPopup.editor.settings.language },\r
+               function(result, errors) {\r
+                       \r
+                       if (result) {\r
+                               document.getElementById('leftpanel').innerHTML = result['leftpanel']; \r
+                               document.getElementById('addressbar').innerHTML = result['addressbar'];\r
+                               document.getElementById('mainfield').innerHTML = result['mainfield'];\r
+                               themiraclevar = result['uri'];\r
+                               current_file = new Array();\r
+                               current_dir = '';\r
+                       }\r
+               },\r
+               true \r
+       );\r
+}\r
+\r
+var new_folder_state = false;\r
+function createFolder() {\r
+       if(new_folder_state == false) {\r
+               $('leftpanel').innerHTML = $('leftpanel').innerHTML + '<div class="folder"><form onsubmit="submitFolder(); return false;" style="margin-left:20px;"><input type="text" name="new_folder" onblur="submitFolder();" id="new_folder" /></form></div>';\r
+               new_folder_state = true;\r
+               $('new_folder').focus();\r
+       } else {\r
+               $('new_folder').focus();\r
+       }\r
+}\r
+\r
+function submitFolder() {\r
+       JsHttpRequest.query('server_connector/ajax.php', { 'm': 'tinyimages->MakeFolder', 'uri': themiraclevar, 'name': $('new_folder').value, 'lng': tinyMCEPopup.editor.settings.language },\r
+               function(result, errors) {\r
+                       \r
+                       if (result) {\r
+                               if(!result['error']) {\r
+                                       new_folder_state = false;\r
+                                       changeFolder(themiraclevar);\r
+                               } else {\r
+                                       alert(result['error']);\r
+                               }\r
+                       }\r
+               },\r
+               true \r
+       );\r
+}\r
+\r
+function deleteFile() {\r
+\r
+       if (current_file.length==0 && current_dir != '') {\r
+               if (!confirm(document.getElementById('l1').innerHTML)) return false;\r
+               \r
+               JsHttpRequest.query('server_connector/ajax.php', { 'm': 'tinyimages->DelDir', 'dir': current_dir, 'lng': tinyMCEPopup.editor.settings.language },\r
+                       function(result, errors) {\r
+                               if (result) {\r
+                                       if(!result['error']) {\r
+                                               changeFolder(themiraclevar);\r
+                                       } else {\r
+                                               alert(result['error']);\r
+                                       }\r
+                               }\r
+                       },\r
+                       true \r
+               );\r
+               \r
+               \r
+               return true;\r
+       }\r
+\r
+       \r
+       if(current_file.length == 0) { alert(document.getElementById('l2').innerHTML); return false; }\r
+\r
+       if (!confirm(document.getElementById('l3').innerHTML+': ' + current_file.length+ '. '+document.getElementById('l4').innerHTML+'?')) return false;\r
+\r
+       JsHttpRequest.query('server_connector/ajax.php', { 'm': 'tinyimages->DelFile', 'src': current_file, 'lng': tinyMCEPopup.editor.settings.language },\r
+               function(result, errors) {\r
+                       if (result) {\r
+                               if(!result['error']) {\r
+                                       changeFolder(themiraclevar);\r
+                               } else {\r
+                                       alert(result['error']);\r
+                               }\r
+                       }\r
+               },\r
+               true \r
+       );\r
+}\r
+\r
+function uploadImagesBtn() {\r
+       document.location = 'fancy.htm?uri='+ themiraclevar;\r
+}\r
+\r
+function addImage(obj,path,width) {\r
+       ImagesDialog.insert(path, obj.childNodes[0].alt, width);\r
+}\r
+\r
+\r
+ctrlState = 0;\r
+function setCtrl(tmp) {\r
+       var isIE = navigator.appName.indexOf("Microsoft") != -1;\r
+       if(isIE) {\r
+               if(!window.event) window.event=tmp;\r
+               tmp=window.event.keyCode;\r
+       } else {\r
+               event=tmp;\r
+               tmp=event.keyCode;\r
+       }\r
+       if(tmp==17) ctrlState = 1;\r
+}\r
+\r
+function resetCtrl() { ctrlState = 0; }\r
+\r
+\r
+\r
+if(window.opera) document.onkeydown=setCtrl;\r
+\r
+if(window.opera) document.onkeyup=resetCtrl;\r
+</script>\r
+        <table class="all" cellpadding="0" cellspacing="0">\r
+            <tr>\r
+                <td class="header">\r
+                    <div class="path" id="addressbar">\r
+                        <!-- Àäðåñíàÿ ñòðîêà -->\r
+                    </div>\r
+                    <div class="panel">\r
+                        <div class="p1">\r
+                            <div class="p2">\r
+                                <div class="btns">\r
+                                    <a href="#" onclick="createFolder(); return false;"><img src="images/back/new_folder.gif" width="16" height="32" alt="{#images_dlg.create_new_fld}"/> {#images_dlg.create_fld}</a><a href="#" onclick="uploadImagesBtn(); return false;"><img src="images/back/files.gif" width="19" height="32" alt="{#images_dlg.upload_files}" /> {#images_dlg.upload_files}</a><a href="#" onclick="deleteFile(); return false;"><img src="images/back/del_file.gif" width="16" height="32" alt="{#images_dlg.delete_file}"/> {#images_dlg.delete_file}</a>\r
+                                </div>\r
+                            </div>\r
+                        </div>\r
+                    </div>\r
+                </td>\r
+            </tr>\r
+            <tr>\r
+                <td valign="top">\r
+                    <table cellpadding="0" cellspacing="0">\r
+                        <tr>\r
+                            <td class="left" width="150" id="leftpanel" style="padding-top:15px;">\r
+                               <!-- Ñïèñîê ïàïîê â òåêóùåé äèðåêòîðèè -->\r
+                            </td>\r
+                            <td>\r
+                            <div id="mainfield">\r
+\r
+                            </div>\r
+                            </td>\r
+                        </tr>\r
+                    </table>\r
+                </td>\r
+            </tr>\r
+        </table>\r
+        \r
+        \r
+        <script type="text/javascript">\r
+         changeFolder(getURLParam('uri'));\r
+        </script>\r
+        \r
+    </body>\r
+</html>\r
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/arrow.gif b/ipf/admin/media/tiny_mce/plugins/images/images/arrow.gif
new file mode 100755 (executable)
index 0000000..5549ad4
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/arrow.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/back/back.gif b/ipf/admin/media/tiny_mce/plugins/images/images/back/back.gif
new file mode 100755 (executable)
index 0000000..36d8d53
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/back/back.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/back/browse.gif b/ipf/admin/media/tiny_mce/plugins/images/images/back/browse.gif
new file mode 100755 (executable)
index 0000000..ff7623e
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/back/browse.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/back/clean.gif b/ipf/admin/media/tiny_mce/plugins/images/images/back/clean.gif
new file mode 100755 (executable)
index 0000000..6abb6f2
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/back/clean.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/back/del_file.gif b/ipf/admin/media/tiny_mce/plugins/images/images/back/del_file.gif
new file mode 100755 (executable)
index 0000000..f094e14
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/back/del_file.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/back/files.gif b/ipf/admin/media/tiny_mce/plugins/images/images/back/files.gif
new file mode 100755 (executable)
index 0000000..9ef1185
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/back/files.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/back/larr.gif b/ipf/admin/media/tiny_mce/plugins/images/images/back/larr.gif
new file mode 100755 (executable)
index 0000000..2f6766f
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/back/larr.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/back/left.gif b/ipf/admin/media/tiny_mce/plugins/images/images/back/left.gif
new file mode 100755 (executable)
index 0000000..6d6d740
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/back/left.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/back/new_folder.gif b/ipf/admin/media/tiny_mce/plugins/images/images/back/new_folder.gif
new file mode 100755 (executable)
index 0000000..79392de
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/back/new_folder.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/back/ok.gif b/ipf/admin/media/tiny_mce/plugins/images/images/back/ok.gif
new file mode 100755 (executable)
index 0000000..a027504
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/back/ok.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/back/right.gif b/ipf/admin/media/tiny_mce/plugins/images/images/back/right.gif
new file mode 100755 (executable)
index 0000000..354e2dc
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/back/right.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/bar.gif b/ipf/admin/media/tiny_mce/plugins/images/images/bar.gif
new file mode 100755 (executable)
index 0000000..abc513f
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/bar.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/failed.png b/ipf/admin/media/tiny_mce/plugins/images/images/failed.png
new file mode 100755 (executable)
index 0000000..7233d45
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/failed.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/file.png b/ipf/admin/media/tiny_mce/plugins/images/images/file.png
new file mode 100755 (executable)
index 0000000..e6d64bb
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/file.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/folder.gif b/ipf/admin/media/tiny_mce/plugins/images/images/folder.gif
new file mode 100755 (executable)
index 0000000..9cf8707
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/folder.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/icon.gif b/ipf/admin/media/tiny_mce/plugins/images/images/icon.gif
new file mode 100755 (executable)
index 0000000..45fc766
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/icon.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/progress.gif b/ipf/admin/media/tiny_mce/plugins/images/images/progress.gif
new file mode 100755 (executable)
index 0000000..2988647
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/progress.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/success.png b/ipf/admin/media/tiny_mce/plugins/images/images/success.png
new file mode 100755 (executable)
index 0000000..5b7e649
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/success.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/upload_back.gif b/ipf/admin/media/tiny_mce/plugins/images/images/upload_back.gif
new file mode 100755 (executable)
index 0000000..8831dd6
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/upload_back.gif differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/images/uploading.png b/ipf/admin/media/tiny_mce/plugins/images/images/uploading.png
new file mode 100755 (executable)
index 0000000..9442085
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/images/uploading.png differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/js/FancyUpload2.js b/ipf/admin/media/tiny_mce/plugins/images/js/FancyUpload2.js
new file mode 100755 (executable)
index 0000000..6d3656d
--- /dev/null
@@ -0,0 +1,449 @@
+/**\r
+ * FancyUpload - Flash meets Ajax for simply working uploads\r
+ *\r
+ * @version            2.0 beta 2\r
+ *\r
+ * @license            MIT License\r
+ *\r
+ * @author             Harald Kirschner <mail [at] digitarald [dot] de>\r
+ * @copyright  Authors\r
+ */\r
+\r
+if(tinyMCEPopup.editor.settings.language != 'ru'){\r
+var FancyUpload2 = new Class({\r
+\r
+       Extends: Swiff.Uploader,\r
+\r
+       options: {\r
+               createElement: null,\r
+               updateElement: null,\r
+               removeElement: null\r
+       },\r
+\r
+       initialize: function(status, list, options) {\r
+               this.status = $(status);\r
+               this.list = $(list);\r
+\r
+               this.files = [];\r
+\r
+               this.overallTitle = this.status.getElement('.overall-title');\r
+               this.currentTitle = this.status.getElement('.current-title');\r
+               this.currentText = this.status.getElement('.current-text');\r
+\r
+               var progress = this.status.getElement('.overall-progress');\r
+               this.overallProgress = new Fx.ProgressBar(progress, {\r
+                       text: new Element('span', {'class': 'progress-text'}).inject(progress, 'after')\r
+               });\r
+               progress = this.status.getElement('.current-progress')\r
+               this.currentProgress = new Fx.ProgressBar(progress, {\r
+                       text: new Element('span', {'class': 'progress-text'}).inject(progress, 'after')\r
+               });\r
+\r
+               this.parent(options);\r
+       },\r
+\r
+       onLoad: function() {\r
+               this.log('Uploader ready!');\r
+       },\r
+\r
+       onBeforeOpen: function(file) {\r
+               this.log('Initialize upload for "{name}".', file);\r
+       },\r
+\r
+       onOpen: function(file, overall) {\r
+               this.log('Starting upload "{name}".', file);\r
+               file = this.getFile(file);\r
+               file.element.addClass('file-uploading');\r
+               this.currentProgress.cancel().set(0);\r
+               this.currentTitle.set('html', 'File Progress "{name}"'.substitute(file) );\r
+       },\r
+\r
+       onProgress: function(file, current, overall) {\r
+               this.overallProgress.start(overall.bytesLoaded, overall.bytesTotal);\r
+               var units = Date.parseIntervals(current.timeLeft || 0), timeLeft = [];\r
+               for (var unit in units) timeLeft.push(units[unit] + ' ' + unit);\r
+               this.currentText.set('html', 'Upload with {rate}/s. Est. time left: {timeLeft}'.substitute({\r
+                       rate: (current.rate) ? this.sizeToKB(current.rate) : '- B',\r
+                       timeLeft: timeLeft.join(', ')\r
+               }));\r
+               this.currentProgress.start(current.bytesLoaded, current.bytesTotal);\r
+       },\r
+\r
+       onSelect: function(file, index, length) {\r
+               this.log('Checked in file ' + index + '/' + length + ' "' + file.name + '" with ' + file.size + ' bytes.');\r
+       },\r
+\r
+       onAllSelect: function(files, current, overall) {\r
+               $('demo-status').style.display = 'block';\r
+               $('demo-browse').style.display = 'none';\r
+               this.log('Added ' + files.length + ' files, now we have (' + current.bytesTotal + ' bytes).', arguments);\r
+               this.overallTitle.set('html', 'Overall Progress ({size})'.substitute({size: this.sizeToKB(current.bytesTotal)}));\r
+               files.each(function(file) {\r
+                       this.createFileElement(file);\r
+                       this.files.push(file);\r
+               }, this);\r
+               this.status.removeClass('status-browsing');\r
+       },\r
+\r
+       onComplete: function(file, response) {\r
+               this.log('Completed upload "' + file.name + '".', arguments);\r
+               this.currentText.set('html', 'Upload complete!');\r
+               this.currentProgress.start(100);\r
+               file = this.getFile(file);\r
+               file.element.removeClass('file-uploading');\r
+               var json = $H(JSON.decode(response, true));\r
+               if (json.get('result') == 'success') {\r
+                       file.element.addClass('file-success');\r
+                       file.info.set('html', json.get('size'));\r
+               } else {\r
+                       file.element.addClass('file-failed');\r
+                       file.info.set('html', json.get('error') || response);\r
+               }\r
+       },\r
+\r
+       onError: function(file, error, info) {\r
+               this.log('Upload "' + file.name + '" failed. "{1}": "{2}".', arguments);\r
+               file = this.finishFile(file);\r
+               file.element.addClass('file-failed');\r
+               file.info.set('html', '<strong>' + error + '</strong><br />' + info);\r
+       },\r
+\r
+       onCancel: function() {\r
+               this.log('Filebrowser cancelled.', arguments);\r
+               this.status.removeClass('file-browsing');\r
+       },\r
+\r
+       onAllComplete: function(current) {\r
+               this.log('Completed all files, ' + current.bytesTotal + ' bytes.', arguments);\r
+               this.overallTitle.set('html', 'Overall Progress (' + this.sizeToKB(current.bytesTotal) + ')');\r
+               this.overallProgress.start(100);\r
+               this.status.removeClass('file-uploading');\r
+       },\r
+\r
+       browse: function(fileList) {\r
+               var ret = this.parent(fileList);\r
+               if (ret !== true){\r
+                       this.log('Browse in progress.');\r
+                       if (ret) alert(ret);\r
+               } else {\r
+                       this.log('Browse started.');\r
+                       this.status.addClass('file-browsing');\r
+               }\r
+       },\r
+\r
+       upload: function(options) {\r
+               var ret = this.parent(options);\r
+               if (ret !== true) {\r
+                       this.log('Upload in progress or nothing to upload.');\r
+                       if (ret) alert(ret);\r
+               } else {\r
+                       this.log('Upload started.');\r
+                       this.status.addClass('file-uploading');\r
+                       this.overallProgress.set(0);\r
+               }\r
+       },\r
+\r
+       removeFile: function(file) {\r
+               if (!file) {\r
+                       this.files.each(this.removeFileElement, this);\r
+                       this.files.empty();\r
+               } else {\r
+                       if (!file.element) file = this.getFile(file);\r
+                       this.files.erase(file);\r
+                       this.removeFileElement(file);\r
+               }\r
+               this.parent(file);\r
+       },\r
+\r
+       getFile: function(file) {\r
+               var ret = null;\r
+               this.files.some(function(value) {\r
+                       if ((value.name != file.name) || (value.size != file.size)) return false;\r
+                       ret = value;\r
+                       return true;\r
+               });\r
+               return ret;\r
+       },\r
+\r
+       removeFileElement: function(file) {\r
+               file.element.fade('out').retrieve('tween').chain(Element.destroy.bind(Element, file.element));\r
+       },\r
+\r
+       finishFile: function(file) {\r
+               file = this.getFile(file);\r
+               file.element.removeClass('file-uploading');\r
+               file.finished = true;\r
+               return file;\r
+       },\r
+\r
+       createFileElement: function(file) {\r
+               file.info = new Element('span', {'class': 'file-info'});\r
+               file.element = new Element('li', {'class': 'file'}).adopt(\r
+                       new Element('span', {'class': 'file-size', 'html': this.sizeToKB(file.size)}),\r
+                       new Element('a', {\r
+                               'class': 'file-remove',\r
+                               'href': '#',\r
+                               'html': 'Remove',\r
+                               'events': {\r
+                                       'click': function() {\r
+                                               this.removeFile(file);\r
+                                               return false;\r
+                                       }.bind(this)\r
+                               }\r
+                       }),\r
+                       new Element('span', {'class': 'file-name', 'html': file.name}),\r
+                       file.info\r
+               ).inject(this.list);\r
+       },\r
+\r
+       sizeToKB: function(size) {\r
+               var unit = 'B';\r
+               if ((size / 1048576) > 1) {\r
+                       unit = 'MB';\r
+                       size /= 1048576;\r
+               } else if ((size / 1024) > 1) {\r
+                       unit = 'kB';\r
+                       size /= 1024;\r
+               }\r
+               return size.round(1) + ' ' + unit;\r
+       },\r
+\r
+       log: function(text, args) {\r
+               if (window.console) console.log(text.substitute(args || {}));\r
+       }\r
+\r
+});\r
+\r
+Date.parseIntervals = function(sec, max) {\r
+       var units = {}, conv = Date.durations, count = 0;\r
+       for (var unit in conv) {\r
+               var value = Math.floor(sec / conv[unit]);\r
+               if (value) {\r
+                       units[unit] = value;\r
+                       if ((max && max <= ++count) || !(sec -= value * conv[unit])) break;\r
+               }\r
+       }\r
+       return units;\r
+};\r
+\r
+Date.intervals = {y: 31556926, mo: 2629743.83, d: 86400, h: 3600, mi: 60, s: 1, ms: 0.001};\r
+}\r
+else {\r
+var FancyUpload2 = new Class({\r
+\r
+       Extends: Swiff.Uploader,\r
+\r
+       options: {\r
+               createElement: null,\r
+               updateElement: null,\r
+               removeElement: null\r
+       },\r
+\r
+       initialize: function(status, list, options) {\r
+               this.status = $(status);\r
+               this.list = $(list);\r
+\r
+               this.files = [];\r
+\r
+               this.overallTitle = this.status.getElement('.overall-title');\r
+               this.currentTitle = this.status.getElement('.current-title');\r
+               this.currentText = this.status.getElement('.current-text');\r
+\r
+               var progress = this.status.getElement('.overall-progress');\r
+               this.overallProgress = new Fx.ProgressBar(progress, {\r
+                       text: new Element('span', {'class': 'progress-text'}).inject(progress, 'after')\r
+               });\r
+               progress = this.status.getElement('.current-progress')\r
+               this.currentProgress = new Fx.ProgressBar(progress, {\r
+                       text: new Element('span', {'class': 'progress-text'}).inject(progress, 'after')\r
+               });\r
+\r
+               this.parent(options);\r
+       },\r
+\r
+       onLoad: function() {\r
+               this.log('Uploader ready!');\r
+       },\r
+\r
+       onBeforeOpen: function(file) {\r
+               this.log('Initialize upload for "{name}".', file);\r
+       },\r
+\r
+       onOpen: function(file, overall) {\r
+               this.log('Starting upload "{name}".', file);\r
+               file = this.getFile(file);\r
+               file.element.addClass('file-uploading');\r
+               this.currentProgress.cancel().set(0);\r
+               this.currentTitle.set('html', 'Ñòàòóñ ôàéëà "{name}"'.substitute(file) );\r
+       },\r
+\r
+       onProgress: function(file, current, overall) {\r
+               this.overallProgress.start(overall.bytesLoaded, overall.bytesTotal);\r
+               var units = Date.parseIntervals(current.timeLeft || 0), timeLeft = [];\r
+               for (var unit in units) timeLeft.push(units[unit] + ' ' + unit);\r
+               this.currentText.set('html', 'Ñêîðîñòü çàãðóçêè {rate}/ñ. '.substitute({\r
+                       rate: (current.rate) ? this.sizeToKB(current.rate) : '- B',\r
+                       timeLeft: timeLeft.join(', ')\r
+               }));\r
+               this.currentProgress.start(current.bytesLoaded, current.bytesTotal);\r
+       },\r
+\r
+       onSelect: function(file, index, length) {\r
+               this.log('Checked in file ' + index + '/' + length + ' "' + file.name + '" with ' + file.size + ' bytes.');\r
+       },\r
+\r
+       onAllSelect: function(files, current, overall) {\r
+               $('demo-status').style.display = 'block';\r
+               $('demo-browse').style.display = 'none';\r
+               this.log('Added ' + files.length + ' files, now we have (' + current.bytesTotal + ' bytes).', arguments);\r
+               this.overallTitle.set('html', 'Îáùèé ñòàòóñ ({size})'.substitute({size: this.sizeToKB(current.bytesTotal)}));\r
+               files.each(function(file) {\r
+                       this.createFileElement(file);\r
+                       this.files.push(file);\r
+               }, this);\r
+               this.status.removeClass('status-browsing');\r
+       },\r
+\r
+       onComplete: function(file, response) {\r
+               this.log('Completed upload "' + file.name + '".', arguments);\r
+               this.currentText.set('html', 'Çàãðóçêà çàâåðøåíà!');\r
+               this.currentProgress.start(100);\r
+               file = this.getFile(file);\r
+               file.element.removeClass('file-uploading');\r
+               var json = $H(JSON.decode(response, true));\r
+               if (json.get('result') == 'success') {\r
+                       file.element.addClass('file-success');\r
+                       file.info.set('html', json.get('size'));\r
+               } else {\r
+                       file.element.addClass('file-failed');\r
+                       file.info.set('html', json.get('error') || response);\r
+               }\r
+       },\r
+\r
+       onError: function(file, error, info) {\r
+               this.log('Çàãðóçêà "' + file.name + '" íå óäàëàñü. "{1}": "{2}".', arguments);\r
+               file = this.finishFile(file);\r
+               file.element.addClass('file-failed');\r
+               file.info.set('html', '<strong>' + error + '</strong><br />' + info);\r
+       },\r
+\r
+       onCancel: function() {\r
+               this.log('Filebrowser cancelled.', arguments);\r
+               this.status.removeClass('file-browsing');\r
+       },\r
+\r
+       onAllComplete: function(current) {\r
+               this.log('Completed all files, ' + current.bytesTotal + ' bytes.', arguments);\r
+               this.overallTitle.set('html', 'Îáùèé ñòàòóñ (' + this.sizeToKB(current.bytesTotal) + ')');\r
+               this.overallProgress.start(100);\r
+               this.status.removeClass('file-uploading');\r
+       },\r
+\r
+       browse: function(fileList) {\r
+               var ret = this.parent(fileList);\r
+               if (ret !== true){\r
+                       this.log('Browse in progress.');\r
+                       if (ret) alert(ret);\r
+               } else {\r
+                       this.log('Browse started.');\r
+                       this.status.addClass('file-browsing');\r
+               }\r
+       },\r
+\r
+       upload: function(options) {\r
+               var ret = this.parent(options);\r
+               if (ret !== true) {\r
+                       this.log('Upload in progress or nothing to upload.');\r
+                       if (ret) alert(ret);\r
+               } else {\r
+                       this.log('Upload started.');\r
+                       this.status.addClass('file-uploading');\r
+                       this.overallProgress.set(0);\r
+               }\r
+       },\r
+\r
+       removeFile: function(file) {\r
+               if (!file) {\r
+                       this.files.each(this.removeFileElement, this);\r
+                       this.files.empty();\r
+               } else {\r
+                       if (!file.element) file = this.getFile(file);\r
+                       this.files.erase(file);\r
+                       this.removeFileElement(file);\r
+               }\r
+               this.parent(file);\r
+       },\r
+\r
+       getFile: function(file) {\r
+               var ret = null;\r
+               this.files.some(function(value) {\r
+                       if ((value.name != file.name) || (value.size != file.size)) return false;\r
+                       ret = value;\r
+                       return true;\r
+               });\r
+               return ret;\r
+       },\r
+\r
+       removeFileElement: function(file) {\r
+               file.element.fade('out').retrieve('tween').chain(Element.destroy.bind(Element, file.element));\r
+       },\r
+\r
+       finishFile: function(file) {\r
+               file = this.getFile(file);\r
+               file.element.removeClass('file-uploading');\r
+               file.finished = true;\r
+               return file;\r
+       },\r
+\r
+       createFileElement: function(file) {\r
+               file.info = new Element('span', {'class': 'file-info'});\r
+               file.element = new Element('li', {'class': 'file'}).adopt(\r
+                       new Element('span', {'class': 'file-size', 'html': this.sizeToKB(file.size)}),\r
+                       new Element('a', {\r
+                               'class': 'file-remove',\r
+                               'href': '#',\r
+                               'html': 'Óáðàòü',\r
+                               'events': {\r
+                                       'click': function() {\r
+                                               this.removeFile(file);\r
+                                               return false;\r
+                                       }.bind(this)\r
+                               }\r
+                       }),\r
+                       new Element('span', {'class': 'file-name', 'html': file.name}),\r
+                       file.info\r
+               ).inject(this.list);\r
+       },\r
+\r
+       sizeToKB: function(size) {\r
+               var unit = 'B';\r
+               if ((size / 1048576) > 1) {\r
+                       unit = 'MB';\r
+                       size /= 1048576;\r
+               } else if ((size / 1024) > 1) {\r
+                       unit = 'kB';\r
+                       size /= 1024;\r
+               }\r
+               return size.round(1) + ' ' + unit;\r
+       },\r
+\r
+       log: function(text, args) {\r
+               if (window.console) console.log(text.substitute(args || {}));\r
+       }\r
+\r
+});\r
+\r
+Date.parseIntervals = function(sec, max) {\r
+       var units = {}, conv = Date.durations, count = 0;\r
+       for (var unit in conv) {\r
+               var value = Math.floor(sec / conv[unit]);\r
+               if (value) {\r
+                       units[unit] = value;\r
+                       if ((max && max <= ++count) || !(sec -= value * conv[unit])) break;\r
+               }\r
+       }\r
+       return units;\r
+};\r
+\r
+Date.intervals = {y: 31556926, mo: 2629743.83, d: 86400, h: 3600, mi: 60, s: 1, ms: 0.001};\r
+}
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/js/Fx.ProgressBar.js b/ipf/admin/media/tiny_mce/plugins/images/js/Fx.ProgressBar.js
new file mode 100755 (executable)
index 0000000..1b55469
--- /dev/null
@@ -0,0 +1,40 @@
+/**\r
+ * FancyUpload - Flash meets Ajax for simply working uploads\r
+ *\r
+ * @version            1.0\r
+ *\r
+ * @license            MIT License\r
+ *\r
+ * @author             Harald Kirschner <mail [at] digitarald [dot] de>\r
+ * @copyright  Authors\r
+ */\r
+\r
+Fx.ProgressBar = new Class({\r
+\r
+       Extends: Fx,\r
+\r
+       options: {\r
+               text: null,\r
+               transition: Fx.Transitions.Circ.easeOut,\r
+               link: 'cancel'\r
+       },\r
+\r
+       initialize: function(element, options) {\r
+               this.element = $(element);\r
+               this.parent(options);\r
+               this.text = $(this.options.text);\r
+               this.set(0);\r
+       },\r
+\r
+       start: function(to, total) {\r
+               return this.parent(this.now, (arguments.length == 1) ? to.limit(0, 100) : to / total * 100);\r
+       },\r
+\r
+       set: function(to) {\r
+               this.now = to;\r
+               this.element.setStyle('backgroundPosition', (100 - to) + '% 0px');\r
+               if (this.text) this.text.set('text', Math.round(to) + '%');\r
+               return this;\r
+       }\r
+\r
+});
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/js/JsHttpRequest.js b/ipf/admin/media/tiny_mce/plugins/images/js/JsHttpRequest.js
new file mode 100755 (executable)
index 0000000..e0d9323
--- /dev/null
@@ -0,0 +1,576 @@
+/**\r
+ * JsHttpRequest: JavaScript "AJAX" data loader\r
+ * Minimized version: see debug directory for the complete one.\r
+ *\r
+ * @license LGPL\r
+ * @author Dmitry Koterov, http://en.dklab.ru/lib/JsHttpRequest/\r
+ * @version 5.x $Id$\r
+ */\r
+function JsHttpRequest(){\r
+var t=this;\r
+t.onreadystatechange=null;\r
+t.readyState=0;\r
+t.responseText=null;\r
+t.responseXML=null;\r
+t.status=200;\r
+t.statusText="OK";\r
+t.responseJS=null;\r
+t.caching=false;\r
+t.loader=null;\r
+t.session_name="PHPSESSID";\r
+t._ldObj=null;\r
+t._reqHeaders=[];\r
+t._openArgs=null;\r
+t._errors={inv_form_el:"Invalid FORM element detected: name=%, tag=%",must_be_single_el:"If used, <form> must be a single HTML element in the list.",js_invalid:"JavaScript code generated by backend is invalid!\n%",url_too_long:"Cannot use so long query with GET request (URL is larger than % bytes)",unk_loader:"Unknown loader: %",no_loaders:"No loaders registered at all, please check JsHttpRequest.LOADERS array",no_loader_matched:"Cannot find a loader which may process the request. Notices are:\n%"};\r
+t.abort=function(){\r
+with(this){\r
+if(_ldObj&&_ldObj.abort){\r
+_ldObj.abort();\r
+}\r
+_cleanup();\r
+if(readyState==0){\r
+return;\r
+}\r
+if(readyState==1&&!_ldObj){\r
+readyState=0;\r
+return;\r
+}\r
+_changeReadyState(4,true);\r
+}\r
+};\r
+t.open=function(_2,_3,_4,_5,_6){\r
+with(this){\r
+if(_3.match(/^((\w+)\.)?(GET|POST)\s+(.*)/i)){\r
+this.loader=RegExp.$2?RegExp.$2:null;\r
+_2=RegExp.$3;\r
+_3=RegExp.$4;\r
+}\r
+try{\r
+if(document.location.search.match(new RegExp("[&?]"+session_name+"=([^&?]*)"))||document.cookie.match(new RegExp("(?:;|^)\\s*"+session_name+"=([^;]*)"))){\r
+_3+=(_3.indexOf("?")>=0?"&":"?")+session_name+"="+this.escape(RegExp.$1);\r
+}\r
+}\r
+catch(e){\r
+}\r
+_openArgs={method:(_2||"").toUpperCase(),url:_3,asyncFlag:_4,username:_5!=null?_5:"",password:_6!=null?_6:""};\r
+_ldObj=null;\r
+_changeReadyState(1,true);\r
+return true;\r
+}\r
+};\r
+t.send=function(_7){\r
+if(!this.readyState){\r
+return;\r
+}\r
+this._changeReadyState(1,true);\r
+this._ldObj=null;\r
+var _8=[];\r
+var _9=[];\r
+if(!this._hash2query(_7,null,_8,_9)){\r
+return;\r
+}\r
+var _a=null;\r
+if(this.caching&&!_9.length){\r
+_a=this._openArgs.username+":"+this._openArgs.password+"@"+this._openArgs.url+"|"+_8+"#"+this._openArgs.method;\r
+var _b=JsHttpRequest.CACHE[_a];\r
+if(_b){\r
+this._dataReady(_b[0],_b[1]);\r
+return false;\r
+}\r
+}\r
+var _c=(this.loader||"").toLowerCase();\r
+if(_c&&!JsHttpRequest.LOADERS[_c]){\r
+return this._error("unk_loader",_c);\r
+}\r
+var _d=[];\r
+var _e=JsHttpRequest.LOADERS;\r
+for(var _f in _e){\r
+var ldr=_e[_f].loader;\r
+if(!ldr){\r
+continue;\r
+}\r
+if(_c&&_f!=_c){\r
+continue;\r
+}\r
+var _11=new ldr(this);\r
+JsHttpRequest.extend(_11,this._openArgs);\r
+JsHttpRequest.extend(_11,{queryText:_8.join("&"),queryElem:_9,id:(new Date().getTime())+""+JsHttpRequest.COUNT++,hash:_a,span:null});\r
+var _12=_11.load();\r
+if(!_12){\r
+this._ldObj=_11;\r
+JsHttpRequest.PENDING[_11.id]=this;\r
+return true;\r
+}\r
+if(!_c){\r
+_d[_d.length]="- "+_f.toUpperCase()+": "+this._l(_12);\r
+}else{\r
+return this._error(_12);\r
+}\r
+}\r
+return _f?this._error("no_loader_matched",_d.join("\n")):this._error("no_loaders");\r
+};\r
+t.getAllResponseHeaders=function(){\r
+with(this){\r
+return _ldObj&&_ldObj.getAllResponseHeaders?_ldObj.getAllResponseHeaders():[];\r
+}\r
+};\r
+t.getResponseHeader=function(_13){\r
+with(this){\r
+return _ldObj&&_ldObj.getResponseHeader?_ldObj.getResponseHeader(_13):null;\r
+}\r
+};\r
+t.setRequestHeader=function(_14,_15){\r
+with(this){\r
+_reqHeaders[_reqHeaders.length]=[_14,_15];\r
+}\r
+};\r
+t._dataReady=function(_16,js){\r
+with(this){\r
+if(caching&&_ldObj){\r
+JsHttpRequest.CACHE[_ldObj.hash]=[_16,js];\r
+}\r
+responseText=responseXML=_16;\r
+responseJS=js;\r
+if(js!==null){\r
+status=200;\r
+statusText="OK";\r
+}else{\r
+status=500;\r
+statusText="Internal Server Error";\r
+}\r
+_changeReadyState(2);\r
+_changeReadyState(3);\r
+_changeReadyState(4);\r
+_cleanup();\r
+}\r
+};\r
+t._l=function(_18){\r
+var i=0,p=0,msg=this._errors[_18[0]];\r
+while((p=msg.indexOf("%",p))>=0){\r
+var a=_18[++i]+"";\r
+msg=msg.substring(0,p)+a+msg.substring(p+1,msg.length);\r
+p+=1+a.length;\r
+}\r
+return msg;\r
+};\r
+t._error=function(msg){\r
+msg=this._l(typeof (msg)=="string"?arguments:msg);\r
+msg="JsHttpRequest: "+msg;\r
+if(!window.Error){\r
+throw msg;\r
+}else{\r
+if((new Error(1,"test")).description=="test"){\r
+throw new Error(1,msg);\r
+}else{\r
+throw new Error(msg);\r
+}\r
+}\r
+};\r
+t._hash2query=function(_1e,_1f,_20,_21){\r
+if(_1f==null){\r
+_1f="";\r
+}\r
+if((""+typeof (_1e)).toLowerCase()=="object"){\r
+var _22=false;\r
+if(_1e&&_1e.parentNode&&_1e.parentNode.appendChild&&_1e.tagName&&_1e.tagName.toUpperCase()=="FORM"){\r
+_1e={form:_1e};\r
+}\r
+for(var k in _1e){\r
+var v=_1e[k];\r
+if(v instanceof Function){\r
+continue;\r
+}\r
+var _25=_1f?_1f+"["+this.escape(k)+"]":this.escape(k);\r
+var _26=v&&v.parentNode&&v.parentNode.appendChild&&v.tagName;\r
+if(_26){\r
+var tn=v.tagName.toUpperCase();\r
+if(tn=="FORM"){\r
+_22=true;\r
+}else{\r
+if(tn=="INPUT"||tn=="TEXTAREA"||tn=="SELECT"){\r
+}else{\r
+return this._error("inv_form_el",(v.name||""),v.tagName);\r
+}\r
+}\r
+_21[_21.length]={name:_25,e:v};\r
+}else{\r
+if(v instanceof Object){\r
+this._hash2query(v,_25,_20,_21);\r
+}else{\r
+if(v===null){\r
+continue;\r
+}\r
+if(v===true){\r
+v=1;\r
+}\r
+if(v===false){\r
+v="";\r
+}\r
+_20[_20.length]=_25+"="+this.escape(""+v);\r
+}\r
+}\r
+if(_22&&_21.length>1){\r
+return this._error("must_be_single_el");\r
+}\r
+}\r
+}else{\r
+_20[_20.length]=_1e;\r
+}\r
+return true;\r
+};\r
+t._cleanup=function(){\r
+var _28=this._ldObj;\r
+if(!_28){\r
+return;\r
+}\r
+JsHttpRequest.PENDING[_28.id]=false;\r
+var _29=_28.span;\r
+if(!_29){\r
+return;\r
+}\r
+_28.span=null;\r
+var _2a=function(){\r
+_29.parentNode.removeChild(_29);\r
+};\r
+JsHttpRequest.setTimeout(_2a,50);\r
+};\r
+t._changeReadyState=function(s,_2c){\r
+with(this){\r
+if(_2c){\r
+status=statusText=responseJS=null;\r
+responseText="";\r
+}\r
+readyState=s;\r
+if(onreadystatechange){\r
+onreadystatechange();\r
+}\r
+}\r
+};\r
+t.escape=function(s){\r
+return escape(s).replace(new RegExp("\\+","g"),"%2B");\r
+};\r
+}\r
+JsHttpRequest.COUNT=0;\r
+JsHttpRequest.MAX_URL_LEN=2000;\r
+JsHttpRequest.CACHE={};\r
+JsHttpRequest.PENDING={};\r
+JsHttpRequest.LOADERS={};\r
+JsHttpRequest._dummy=function(){\r
+};\r
+JsHttpRequest.TIMEOUTS={s:window.setTimeout,c:window.clearTimeout};\r
+JsHttpRequest.setTimeout=function(_2e,dt){\r
+window.JsHttpRequest_tmp=JsHttpRequest.TIMEOUTS.s;\r
+if(typeof (_2e)=="string"){\r
+id=window.JsHttpRequest_tmp(_2e,dt);\r
+}else{\r
+var id=null;\r
+var _31=function(){\r
+_2e();\r
+delete JsHttpRequest.TIMEOUTS[id];\r
+};\r
+id=window.JsHttpRequest_tmp(_31,dt);\r
+JsHttpRequest.TIMEOUTS[id]=_31;\r
+}\r
+window.JsHttpRequest_tmp=null;\r
+return id;\r
+};\r
+JsHttpRequest.clearTimeout=function(id){\r
+window.JsHttpRequest_tmp=JsHttpRequest.TIMEOUTS.c;\r
+delete JsHttpRequest.TIMEOUTS[id];\r
+var r=window.JsHttpRequest_tmp(id);\r
+window.JsHttpRequest_tmp=null;\r
+return r;\r
+};\r
+JsHttpRequest.query=function(url,_35,_36,_37){\r
+var req=new this();\r
+req.caching=!_37;\r
+req.onreadystatechange=function(){\r
+if(req.readyState==4){\r
+_36(req.responseJS,req.responseText);\r
+}\r
+};\r
+req.open(null,url,true);\r
+req.send(_35);\r
+};\r
+JsHttpRequest.dataReady=function(d){\r
+var th=this.PENDING[d.id];\r
+delete this.PENDING[d.id];\r
+if(th){\r
+th._dataReady(d.text,d.js);\r
+}else{\r
+if(th!==false){\r
+throw "dataReady(): unknown pending id: "+d.id;\r
+}\r
+}\r
+};\r
+JsHttpRequest.extend=function(_3b,src){\r
+for(var k in src){\r
+_3b[k]=src[k];\r
+}\r
+};\r
+JsHttpRequest.LOADERS.xml={loader:function(req){\r
+JsHttpRequest.extend(req._errors,{xml_no:"Cannot use XMLHttpRequest or ActiveX loader: not supported",xml_no_diffdom:"Cannot use XMLHttpRequest to load data from different domain %",xml_no_headers:"Cannot use XMLHttpRequest loader or ActiveX loader, POST method: headers setting is not supported, needed to work with encodings correctly",xml_no_form_upl:"Cannot use XMLHttpRequest loader: direct form elements using and uploading are not implemented"});\r
+this.load=function(){\r
+if(this.queryElem.length){\r
+return ["xml_no_form_upl"];\r
+}\r
+if(this.url.match(new RegExp("^([a-z]+://[^\\/]+)(.*)","i"))){\r
+if(RegExp.$1.toLowerCase()!=document.location.protocol+"//"+document.location.hostname.toLowerCase()){\r
+return ["xml_no_diffdom",RegExp.$1];\r
+}\r
+}\r
+var xr=null;\r
+if(window.XMLHttpRequest){\r
+try{\r
+xr=new XMLHttpRequest();\r
+}\r
+catch(e){\r
+}\r
+}else{\r
+if(window.ActiveXObject){\r
+try{\r
+xr=new ActiveXObject("Microsoft.XMLHTTP");\r
+}\r
+catch(e){\r
+}\r
+if(!xr){\r
+try{\r
+xr=new ActiveXObject("Msxml2.XMLHTTP");\r
+}\r
+catch(e){\r
+}\r
+}\r
+}\r
+}\r
+if(!xr){\r
+return ["xml_no"];\r
+}\r
+var _40=window.ActiveXObject||xr.setRequestHeader;\r
+if(!this.method){\r
+this.method=_40&&this.queryText.length?"POST":"GET";\r
+}\r
+if(this.method=="GET"){\r
+if(this.queryText){\r
+this.url+=(this.url.indexOf("?")>=0?"&":"?")+this.queryText;\r
+}\r
+this.queryText="";\r
+if(this.url.length>JsHttpRequest.MAX_URL_LEN){\r
+return ["url_too_long",JsHttpRequest.MAX_URL_LEN];\r
+}\r
+}else{\r
+if(this.method=="POST"&&!_40){\r
+return ["xml_no_headers"];\r
+}\r
+}\r
+this.url+=(this.url.indexOf("?")>=0?"&":"?")+"JsHttpRequest="+(req.caching?"0":this.id)+"-xml";\r
+var id=this.id;\r
+xr.onreadystatechange=function(){\r
+if(xr.readyState!=4){\r
+return;\r
+}\r
+xr.onreadystatechange=JsHttpRequest._dummy;\r
+req.status=null;\r
+try{\r
+req.status=xr.status;\r
+req.responseText=xr.responseText;\r
+}\r
+catch(e){\r
+}\r
+if(!req.status){\r
+return;\r
+}\r
+try{\r
+eval("JsHttpRequest._tmp = function(id) { var d = "+req.responseText+"; d.id = id; JsHttpRequest.dataReady(d); }");\r
+}\r
+catch(e){\r
+return req._error("js_invalid",req.responseText);\r
+}\r
+JsHttpRequest._tmp(id);\r
+JsHttpRequest._tmp=null;\r
+};\r
+xr.open(this.method,this.url,true,this.username,this.password);\r
+if(_40){\r
+for(var i=0;i<req._reqHeaders.length;i++){\r
+xr.setRequestHeader(req._reqHeaders[i][0],req._reqHeaders[i][1]);\r
+}\r
+xr.setRequestHeader("Content-Type","application/octet-stream");\r
+}\r
+xr.send(this.queryText);\r
+this.span=null;\r
+this.xr=xr;\r
+return null;\r
+};\r
+this.getAllResponseHeaders=function(){\r
+return this.xr.getAllResponseHeaders();\r
+};\r
+this.getResponseHeader=function(_43){\r
+return this.xr.getResponseHeader(_43);\r
+};\r
+this.abort=function(){\r
+this.xr.abort();\r
+this.xr=null;\r
+};\r
+}};\r
+JsHttpRequest.LOADERS.script={loader:function(req){\r
+JsHttpRequest.extend(req._errors,{script_only_get:"Cannot use SCRIPT loader: it supports only GET method",script_no_form:"Cannot use SCRIPT loader: direct form elements using and uploading are not implemented"});\r
+this.load=function(){\r
+if(this.queryText){\r
+this.url+=(this.url.indexOf("?")>=0?"&":"?")+this.queryText;\r
+}\r
+this.url+=(this.url.indexOf("?")>=0?"&":"?")+"JsHttpRequest="+this.id+"-"+"script";\r
+this.queryText="";\r
+if(!this.method){\r
+this.method="GET";\r
+}\r
+if(this.method!=="GET"){\r
+return ["script_only_get"];\r
+}\r
+if(this.queryElem.length){\r
+return ["script_no_form"];\r
+}\r
+if(this.url.length>JsHttpRequest.MAX_URL_LEN){\r
+return ["url_too_long",JsHttpRequest.MAX_URL_LEN];\r
+}\r
+var th=this,d=document,s=null,b=d.body;\r
+if(!window.opera){\r
+this.span=s=d.createElement("SCRIPT");\r
+var _49=function(){\r
+s.language="JavaScript";\r
+if(s.setAttribute){\r
+s.setAttribute("src",th.url);\r
+}else{\r
+s.src=th.url;\r
+}\r
+b.insertBefore(s,b.lastChild);\r
+};\r
+}else{\r
+this.span=s=d.createElement("SPAN");\r
+s.style.display="none";\r
+b.insertBefore(s,b.lastChild);\r
+s.innerHTML="Workaround for IE.<s"+"cript></"+"script>";\r
+var _49=function(){\r
+s=s.getElementsByTagName("SCRIPT")[0];\r
+s.language="JavaScript";\r
+if(s.setAttribute){\r
+s.setAttribute("src",th.url);\r
+}else{\r
+s.src=th.url;\r
+}\r
+};\r
+}\r
+JsHttpRequest.setTimeout(_49,10);\r
+return null;\r
+};\r
+}};\r
+JsHttpRequest.LOADERS.form={loader:function(req){\r
+JsHttpRequest.extend(req._errors,{form_el_not_belong:"Element \"%\" does not belong to any form!",form_el_belong_diff:"Element \"%\" belongs to a different form. All elements must belong to the same form!",form_el_inv_enctype:"Attribute \"enctype\" of the form must be \"%\" (for IE), \"%\" given."});\r
+this.load=function(){\r
+var th=this;\r
+if(!th.method){\r
+th.method="POST";\r
+}\r
+th.url+=(th.url.indexOf("?")>=0?"&":"?")+"JsHttpRequest="+th.id+"-"+"form";\r
+if(th.method=="GET"){\r
+if(th.queryText){\r
+th.url+=(th.url.indexOf("?")>=0?"&":"?")+th.queryText;\r
+}\r
+if(th.url.length>JsHttpRequest.MAX_URL_LEN){\r
+return ["url_too_long",JsHttpRequest.MAX_URL_LEN];\r
+}\r
+var p=th.url.split("?",2);\r
+th.url=p[0];\r
+th.queryText=p[1]||"";\r
+}\r
+var _4d=null;\r
+var _4e=false;\r
+if(th.queryElem.length){\r
+if(th.queryElem[0].e.tagName.toUpperCase()=="FORM"){\r
+_4d=th.queryElem[0].e;\r
+_4e=true;\r
+th.queryElem=[];\r
+}else{\r
+_4d=th.queryElem[0].e.form;\r
+for(var i=0;i<th.queryElem.length;i++){\r
+var e=th.queryElem[i].e;\r
+if(!e.form){\r
+return ["form_el_not_belong",e.name];\r
+}\r
+if(e.form!=_4d){\r
+return ["form_el_belong_diff",e.name];\r
+}\r
+}\r
+}\r
+if(th.method=="POST"){\r
+var _51="multipart/form-data";\r
+var _52=(_4d.attributes.encType&&_4d.attributes.encType.nodeValue)||(_4d.attributes.enctype&&_4d.attributes.enctype.value)||_4d.enctype;\r
+if(_52!=_51){\r
+return ["form_el_inv_enctype",_51,_52];\r
+}\r
+}\r
+}\r
+var d=_4d&&(_4d.ownerDocument||_4d.document)||document;\r
+var _54="jshr_i_"+th.id;\r
+var s=th.span=d.createElement("DIV");\r
+s.style.position="absolute";\r
+s.style.display="none";\r
+s.style.visibility="hidden";\r
+s.innerHTML=(_4d?"":"<form"+(th.method=="POST"?" enctype=\"multipart/form-data\" method=\"post\"":"")+"></form>")+"<iframe name=\""+_54+"\" id=\""+_54+"\" style=\"width:0px; height:0px; overflow:hidden; border:none\"></iframe>";\r
+if(!_4d){\r
+_4d=th.span.firstChild;\r
+}\r
+d.body.insertBefore(s,d.body.lastChild);\r
+var _56=function(e,_58){\r
+var sv=[];\r
+var _5a=e;\r
+if(e.mergeAttributes){\r
+var _5a=d.createElement("form");\r
+_5a.mergeAttributes(e,false);\r
+}\r
+for(var i=0;i<_58.length;i++){\r
+var k=_58[i][0],v=_58[i][1];\r
+sv[sv.length]=[k,_5a.getAttribute(k)];\r
+_5a.setAttribute(k,v);\r
+}\r
+if(e.mergeAttributes){\r
+e.mergeAttributes(_5a,false);\r
+}\r
+return sv;\r
+};\r
+var _5e=function(){\r
+top.JsHttpRequestGlobal=JsHttpRequest;\r
+var _5f=[];\r
+if(!_4e){\r
+for(var i=0,n=_4d.elements.length;i<n;i++){\r
+_5f[i]=_4d.elements[i].name;\r
+_4d.elements[i].name="";\r
+}\r
+}\r
+var qt=th.queryText.split("&");\r
+for(var i=qt.length-1;i>=0;i--){\r
+var _63=qt[i].split("=",2);\r
+var e=d.createElement("INPUT");\r
+e.type="hidden";\r
+e.name=unescape(_63[0]);\r
+e.value=_63[1]!=null?unescape(_63[1]):"";\r
+_4d.appendChild(e);\r
+}\r
+for(var i=0;i<th.queryElem.length;i++){\r
+th.queryElem[i].e.name=th.queryElem[i].name;\r
+}\r
+var sv=_56(_4d,[["action",th.url],["method",th.method],["onsubmit",null],["target",_54]]);\r
+_4d.submit();\r
+_56(_4d,sv);\r
+for(var i=0;i<qt.length;i++){\r
+_4d.lastChild.parentNode.removeChild(_4d.lastChild);\r
+}\r
+if(!_4e){\r
+for(var i=0,n=_4d.elements.length;i<n;i++){\r
+_4d.elements[i].name=_5f[i];\r
+}\r
+}\r
+};\r
+JsHttpRequest.setTimeout(_5e,100);\r
+return null;\r
+};\r
+}};\r
+\r
diff --git a/ipf/admin/media/tiny_mce/plugins/images/js/Swiff.Uploader.js b/ipf/admin/media/tiny_mce/plugins/images/js/Swiff.Uploader.js
new file mode 100755 (executable)
index 0000000..069700e
--- /dev/null
@@ -0,0 +1,110 @@
+/**\r
+ * Swiff.Uploader - Flash FileReference Control\r
+ *\r
+ * @version            1.1\r
+ *\r
+ * @license            MIT License\r
+ *\r
+ * @author             Harald Kirschner <mail [at] digitarald [dot] de>\r
+ * @copyright  Authors\r
+ */\r
+\r
+Swiff.Uploader = new Class({\r
+\r
+       Extends: Swiff,\r
+\r
+       Implements: Events,\r
+\r
+       options: {\r
+               path: 'Swiff.Uploader.swf',\r
+               multiple: true,\r
+               queued: true,\r
+               typeFilter: null,\r
+               url: null,\r
+               method: 'post',\r
+               data: null,\r
+               fieldName: 'Filedata',\r
+               callBacks: null\r
+       },\r
+\r
+       initialize: function(options){\r
+               if (Browser.Plugins.Flash.version < 9) return false;\r
+               this.setOptions(options);\r
+\r
+               var callBacks = this.options.callBacks || this;\r
+               if (callBacks.onLoad) this.addEvent('onLoad', callBacks.onLoad);\r
+\r
+               var prepare = {}, self = this;\r
+               ['onSelect', 'onAllSelect', 'onCancel', 'onBeforeOpen', 'onOpen', 'onProgress', 'onComplete', 'onError', 'onAllComplete'].each(function(index) {\r
+                       var fn = (callBacks[index]) ? callBacks[index] : $empty;\r
+                       prepare[index] = function() {\r
+                               return fn.apply(self, arguments);\r
+                       };\r
+               }, this);\r
+\r
+               prepare.onLoad = this.load.create({delay: 10, bind: this});\r
+               this.options.callBacks = prepare;\r
+\r
+               var path = this.options.path;\r
+               if (!path.contains('?')) path += '?noCache=' + $time(); // quick fix\r
+\r
+               delete this.options.params.wMode;\r
+               this.parent(path);\r
+\r
+               if (!this.options.container) document.body.appendChild(this.object);\r
+               return this;\r
+       },\r
+\r
+       load: function(){\r
+               this.remote('register', this.instance, this.options.multiple, this.options.queued);\r
+               this.fireEvent('onLoad');\r
+       },\r
+\r
+       /*\r
+       Method: browse\r
+               Open the file browser.\r
+       */\r
+\r
+       browse: function(typeFilter){\r
+               return this.remote('browse', $pick(typeFilter, this.options.typeFilter));\r
+       },\r
+\r
+       /*\r
+       Method: upload\r
+               Starts the upload of all selected files.\r
+       */\r
+\r
+       upload: function(options){\r
+               var current = this.options;\r
+               options = $extend({data: current.data, url: current.url, method: current.method, fieldName: current.fieldName}, options);\r
+               if ($type(options.data) == 'element') options.data = $(options.data).toQueryString();\r
+               return this.remote('upload', options);\r
+       },\r
+\r
+       /*\r
+       Method: removeFile\r
+               For multiple uploads cancels and removes the given file from queue.\r
+\r
+       Arguments:\r
+               name - (string) Filename\r
+               name - (string) Filesize in byte\r
+       */\r
+\r
+       removeFile: function(file){\r
+               if (file) file = {name: file.name, size: file.size};\r
+               return this.remote('removeFile', file);\r
+       },\r
+\r
+       /*\r
+       Method: getFileList\r
+               Returns one Array with with arrays containing name and size of the file.\r
+\r
+       Returns:\r
+               (array) An array with files\r
+       */\r
+\r
+       getFileList: function(){\r
+               return this.remote('getFileList');\r
+       }\r
+\r
+});\r
diff --git a/ipf/admin/media/tiny_mce/plugins/images/js/Swiff.Uploader.swf b/ipf/admin/media/tiny_mce/plugins/images/js/Swiff.Uploader.swf
new file mode 100755 (executable)
index 0000000..a816031
Binary files /dev/null and b/ipf/admin/media/tiny_mce/plugins/images/js/Swiff.Uploader.swf differ
diff --git a/ipf/admin/media/tiny_mce/plugins/images/js/images.js b/ipf/admin/media/tiny_mce/plugins/images/js/images.js
new file mode 100755 (executable)
index 0000000..5a4f195
--- /dev/null
@@ -0,0 +1,24 @@
+tinyMCEPopup.requireLangPack();\r
+\r
+var ImagesDialog = {\r
+       init : function(ed) {\r
+               tinyMCEPopup.resizeToInnerSize();\r
+       },\r
+\r
+       insert : function(file, title, width) {\r
+               var ed = tinyMCEPopup.editor, dom = ed.dom;\r
+\r
+               tinyMCEPopup.execCommand('mceInsertContent', false, dom.createHTML('img', {\r
+                       src : file,\r
+                       alt : title,\r
+                       title : title,\r
+                       width : width,\r
+                       /*height : 0,*/\r
+                       border : 0\r
+               }));\r
+\r
+               tinyMCEPopup.close();\r
+       }\r
+};\r
+\r
+tinyMCEPopup.onInit.add(ImagesDialog.init, ImagesDialog);
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/js/mootools.js b/ipf/admin/media/tiny_mce/plugins/images/js/mootools.js
new file mode 100755 (executable)
index 0000000..1247f1c
--- /dev/null
@@ -0,0 +1,5209 @@
+/*\r
+Script: Core.js\r
+       MooTools - My Object Oriented JavaScript Tools.\r
+\r
+License:\r
+       MIT-style license.\r
+\r
+Copyright:\r
+       Copyright (c) 2006-2007 [Valerio Proietti](http://mad4milk.net/).\r
+\r
+Code & Documentation:\r
+       [The MooTools production team](http://mootools.net/developers/).\r
+\r
+Inspiration:\r
+       - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)\r
+       - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)\r
+*/\r
+\r
+var MooTools = {\r
+       'version': '1.2dev',\r
+       'build': '%build%'\r
+};\r
+      \r
+var Native = function(options){\r
+       options = options || {};\r
+\r
+       var afterImplement = options.afterImplement || function(){};\r
+       var generics = options.generics;\r
+       generics = (generics !== false);\r
+       var legacy = options.legacy;\r
+       var initialize = options.initialize;\r
+       var protect = options.protect;\r
+       var name = options.name;\r
+\r
+       var object = initialize || legacy;\r
+\r
+       object.constructor = Native;\r
+       object.$family = {name: 'native'};\r
+       if (legacy && initialize) object.prototype = legacy.prototype;\r
+       object.prototype.constructor = object;\r
+\r
+       if (name){\r
+               var family = name.toLowerCase();\r
+               object.prototype.$family = {name: family};\r
+               Native.typize(object, family);\r
+       }\r
+\r
+       var add = function(obj, name, method, force){\r
+               if (!protect || force || !obj.prototype[name]) obj.prototype[name] = method;\r
+               if (generics) Native.genericize(obj, name, protect);\r
+               afterImplement.call(obj, name, method);\r
+               return obj;\r
+       };\r
+       \r
+       object.implement = function(a1, a2, a3){\r
+               if (typeof a1 == 'string') return add(this, a1, a2, a3);\r
+               for (var p in a1) add(this, p, a1[p], a2);\r
+               return this;\r
+       };\r
+       \r
+       object.alias = function(a1, a2, a3){\r
+               if (typeof a1 == 'string'){\r
+                       a1 = this.prototype[a1];\r
+                       if (a1) add(this, a2, a1, a3);\r
+               } else {\r
+                       for (var a in a1) this.alias(a, a1[a], a2);\r
+               }\r
+               return this;\r
+       };\r
+\r
+       return object;\r
+};\r
+\r
+Native.implement = function(objects, properties){\r
+       for (var i = 0, l = objects.length; i < l; i++) objects[i].implement(properties);\r
+};\r
+\r
+Native.genericize = function(object, property, check){\r
+       if ((!check || !object[property]) && typeof object.prototype[property] == 'function') object[property] = function(){\r
+               var args = Array.prototype.slice.call(arguments);\r
+               return object.prototype[property].apply(args.shift(), args);\r
+       };\r
+};\r
+\r
+Native.typize = function(object, family){\r
+       if (!object.type) object.type = function(item){\r
+               return ($type(item) === family);\r
+       };\r
+};\r
+\r
+Native.alias = function(objects, a1, a2, a3){\r
+       for (var i = 0, j = objects.length; i < j; i++) objects[i].alias(a1, a2, a3);\r
+};\r
+\r
+(function(objects){\r
+       for (var name in objects) Native.typize(objects[name], name.toLowerCase());\r
+})({'Boolean': Boolean, 'Native': Native, 'Object': Object});\r
+\r
+(function(objects){\r
+       for (var name in objects) new Native({name: name, initialize: objects[name], protect: true});\r
+})({'String': String, 'Function': Function, 'Number': Number, 'Array': Array, 'RegExp': RegExp, 'Date': Date});\r
+\r
+(function(object, methods){\r
+       for (var i = 0, l = methods.length; i < l; i++) Native.genericize(object, methods[i], true);\r
+       return arguments.callee;\r
+})\r
+(Array, ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', 'toString', 'valueOf', 'indexOf', 'lastIndexOf'])\r
+(String, ['charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'replace', 'search', 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase', 'valueOf']);\r
+\r
+function $chk(obj){\r
+       return !!(obj || obj === 0);\r
+};\r
+\r
+function $clear(timer){\r
+       clearTimeout(timer);\r
+       clearInterval(timer);\r
+       return null;\r
+};\r
+\r
+function $defined(obj){\r
+       return (obj != undefined);\r
+};\r
+\r
+function $empty(){};\r
+\r
+function $arguments(i){\r
+       return function(){\r
+               return arguments[i];\r
+       };\r
+};\r
+\r
+function $lambda(value){\r
+       return (typeof value == 'function') ? value : function(){\r
+               return value;\r
+       };\r
+};\r
+\r
+function $extend(original, extended){\r
+       for (var key in (extended || {})) original[key] = extended[key];\r
+       return original;\r
+};\r
+\r
+function $unlink(object){\r
+       var unlinked = null;\r
+       \r
+       switch ($type(object)){\r
+               case 'object':\r
+                       unlinked = {};\r
+                       for (var p in object) unlinked[p] = $unlink(object[p]);\r
+               break;\r
+               case 'hash':\r
+                       unlinked = $unlink(object.getClean());\r
+               break;\r
+               case 'array':\r
+                       unlinked = [];\r
+                       for (var i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]);\r
+               break;\r
+               default: return object;\r
+       }\r
+       \r
+       return unlinked;\r
+};\r
+\r
+function $merge(){\r
+       var mix = {};\r
+       for (var i = 0, l = arguments.length; i < l; i++){\r
+               var object = arguments[i];\r
+               if ($type(object) != 'object') continue;\r
+               for (var key in object){\r
+                       var op = object[key], mp = mix[key];\r
+                       mix[key] = (mp && $type(op) == 'object' && $type(mp) == 'object') ? $merge(mp, op) : $unlink(op);\r
+               }\r
+       }\r
+       return mix;\r
+};\r
+\r
+function $pick(){\r
+       for (var i = 0, l = arguments.length; i < l; i++){\r
+               if (arguments[i] != undefined) return arguments[i];\r
+       }\r
+       return null;\r
+};\r
+\r
+function $random(min, max){\r
+       return Math.floor(Math.random() * (max - min + 1) + min);\r
+};\r
+\r
+function $splat(obj){\r
+       var type = $type(obj);\r
+       return (type) ? ((type != 'array' && type != 'arguments') ? [obj] : obj) : [];\r
+};\r
+\r
+var $time = Date.now || function(){\r
+       return new Date().getTime();\r
+};\r
+\r
+function $try(){\r
+       for (var i = 0, l = arguments.length; i < l; i++){\r
+               try {\r
+                       return arguments[i]();\r
+               } catch(e){}\r
+       }\r
+       return null;\r
+};\r
+\r
+function $type(obj){\r
+       if (obj == undefined) return false;\r
+       if (obj.$family) return (obj.$family.name == 'number' && !isFinite(obj)) ? false : obj.$family.name;\r
+       if (obj.nodeName){\r
+               switch (obj.nodeType){\r
+                       case 1: return 'element';\r
+                       case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';\r
+               }\r
+       } else if (typeof obj.length == 'number'){\r
+               if (obj.callee) return 'arguments';\r
+               else if (obj.item) return 'collection';\r
+       }\r
+       return typeof obj;\r
+};\r
+\r
+var Hash = new Native({\r
+\r
+       name: 'Hash',\r
+\r
+       initialize: function(object){\r
+               if ($type(object) == 'hash') object = $unlink(object.getClean());\r
+               for (var key in object) this[key] = object[key];\r
+               return this;\r
+       }\r
+\r
+});\r
+\r
+Hash.implement({\r
+       \r
+       getLength: function(){\r
+               var length = 0;\r
+               for (var key in this){\r
+                       if (this.hasOwnProperty(key)) length++;\r
+               }\r
+               return length;\r
+       },\r
+\r
+       forEach: function(fn, bind){\r
+               for (var key in this){\r
+                       if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this);\r
+               }\r
+       },\r
+       \r
+       getClean: function(){\r
+               var clean = {};\r
+               for (var key in this){\r
+                       if (this.hasOwnProperty(key)) clean[key] = this[key];\r
+               }\r
+               return clean;\r
+       }\r
+\r
+});\r
+\r
+Hash.alias('forEach', 'each');\r
+\r
+function $H(object){\r
+       return new Hash(object);\r
+};\r
+\r
+Array.implement({\r
+\r
+       forEach: function(fn, bind){\r
+               for (var i = 0, l = this.length; i < l; i++) fn.call(bind, this[i], i, this);\r
+       }\r
+\r
+});\r
+\r
+Array.alias('forEach', 'each');\r
+\r
+function $A(iterable){\r
+       if (iterable.item){\r
+               var array = [];\r
+               for (var i = 0, l = iterable.length; i < l; i++) array[i] = iterable[i];\r
+               return array;\r
+       }\r
+       return Array.prototype.slice.call(iterable);\r
+};\r
+\r
+function $each(iterable, fn, bind){\r
+       var type = $type(iterable);\r
+       ((type == 'arguments' || type == 'collection' || type == 'array') ? Array : Hash).each(iterable, fn, bind);\r
+};\r
+/*\r
+Script: Browser.js\r
+       The Browser Core. Contains Browser initialization, Window and Document, and the Browser Hash.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Browser = new Hash({\r
+       Engine: {name: 'unknown', version: ''},\r
+       Platform: {name: (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()},\r
+       Features: {xpath: !!(document.evaluate), air: !!(window.runtime)},\r
+       Plugins: {}\r
+});\r
+\r
+if (window.opera) Browser.Engine = {name: 'presto', version: (document.getElementsByClassName) ? 950 : 925};\r
+else if (window.ActiveXObject) Browser.Engine = {name: 'trident', version: (window.XMLHttpRequest) ? 5 : 4};\r
+else if (!navigator.taintEnabled) Browser.Engine = {name: 'webkit', version: (Browser.Features.xpath) ? 420 : 419};\r
+else if (document.getBoxObjectFor != null) Browser.Engine = {name: 'gecko', version: (document.getElementsByClassName) ? 19 : 18};\r
+Browser.Engine[Browser.Engine.name] = Browser.Engine[Browser.Engine.name + Browser.Engine.version] = true;\r
+\r
+if (window.orientation != undefined) Browser.Platform.name = 'ipod';\r
+\r
+Browser.Platform[Browser.Platform.name] = true;\r
+\r
+Browser.Request = function(){\r
+       return $try(function(){\r
+               return new XMLHttpRequest();\r
+       }, function(){\r
+               return new ActiveXObject('MSXML2.XMLHTTP');\r
+       });\r
+};\r
+\r
+Browser.Features.xhr = !!(Browser.Request());\r
+\r
+Browser.Plugins.Flash = (function(){\r
+       var version = ($try(function(){\r
+               return navigator.plugins['Shockwave Flash'].description;\r
+       }, function(){\r
+               return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');\r
+       }) || '0 r0').match(/\d+/g);\r
+       return {version: parseInt(version[0] || 0 + '.' + version[1] || 0), build: parseInt(version[2] || 0)};\r
+})();\r
+\r
+function $exec(text){\r
+       if (!text) return text;\r
+       if (window.execScript){\r
+               window.execScript(text);\r
+       } else {\r
+               var script = document.createElement('script');\r
+               script.setAttribute('type', 'text/javascript');\r
+               script.text = text;\r
+               document.head.appendChild(script);\r
+               document.head.removeChild(script);\r
+       }\r
+       return text;\r
+};\r
+\r
+Native.UID = 1;\r
+\r
+var $uid = (Browser.Engine.trident) ? function(item){\r
+       return (item.uid || (item.uid = [Native.UID++]))[0];\r
+} : function(item){\r
+       return item.uid || (item.uid = Native.UID++);\r
+};\r
+\r
+var Window = new Native({\r
+\r
+       name: 'Window',\r
+\r
+       legacy: (Browser.Engine.trident) ? null: window.Window,\r
+\r
+       initialize: function(win){\r
+               $uid(win);\r
+               if (!win.Element){\r
+                       win.Element = $empty;\r
+                       if (Browser.Engine.webkit) win.document.createElement("iframe"); //fixes safari 2\r
+                       win.Element.prototype = (Browser.Engine.webkit) ? window["[[DOMElement.prototype]]"] : {};\r
+               }\r
+               return $extend(win, Window.Prototype);\r
+       },\r
+\r
+       afterImplement: function(property, value){\r
+               window[property] = Window.Prototype[property] = value;\r
+       }\r
+\r
+});\r
+\r
+Window.Prototype = {$family: {name: 'window'}};\r
+\r
+new Window(window);\r
+\r
+var Document = new Native({\r
+\r
+       name: 'Document',\r
+\r
+       legacy: (Browser.Engine.trident) ? null: window.Document,\r
+\r
+       initialize: function(doc){\r
+               $uid(doc);\r
+               doc.head = doc.getElementsByTagName('head')[0];\r
+               doc.html = doc.getElementsByTagName('html')[0];\r
+               doc.window = doc.defaultView || doc.parentWindow;\r
+               if (Browser.Engine.trident4) $try(function(){\r
+                       doc.execCommand("BackgroundImageCache", false, true);\r
+               });\r
+               return $extend(doc, Document.Prototype);\r
+       },\r
+\r
+       afterImplement: function(property, value){\r
+               document[property] = Document.Prototype[property] = value;\r
+       }\r
+\r
+});\r
+\r
+Document.Prototype = {$family: {name: 'document'}};\r
+\r
+new Document(document);/*\r
+Script: Array.js\r
+       Contains Array Prototypes like copy, each, contains, and remove.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Array.implement({\r
+\r
+       every: function(fn, bind){\r
+               for (var i = 0, l = this.length; i < l; i++){\r
+                       if (!fn.call(bind, this[i], i, this)) return false;\r
+               }\r
+               return true;\r
+       },\r
+\r
+       filter: function(fn, bind){\r
+               var results = [];\r
+               for (var i = 0, l = this.length; i < l; i++){\r
+                       if (fn.call(bind, this[i], i, this)) results.push(this[i]);\r
+               }\r
+               return results;\r
+       },\r
+       \r
+       clean: function() {\r
+               return this.filter($defined);\r
+       },\r
+\r
+       indexOf: function(item, from){\r
+               var len = this.length;\r
+               for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){\r
+                       if (this[i] === item) return i;\r
+               }\r
+               return -1;\r
+       },\r
+\r
+       map: function(fn, bind){\r
+               var results = [];\r
+               for (var i = 0, l = this.length; i < l; i++) results[i] = fn.call(bind, this[i], i, this);\r
+               return results;\r
+       },\r
+\r
+       some: function(fn, bind){\r
+               for (var i = 0, l = this.length; i < l; i++){\r
+                       if (fn.call(bind, this[i], i, this)) return true;\r
+               }\r
+               return false;\r
+       },\r
+\r
+       associate: function(keys){\r
+               var obj = {}, length = Math.min(this.length, keys.length);\r
+               for (var i = 0; i < length; i++) obj[keys[i]] = this[i];\r
+               return obj;\r
+       },\r
+\r
+       link: function(object){\r
+               var result = {};\r
+               for (var i = 0, l = this.length; i < l; i++){\r
+                       for (var key in object){\r
+                               if (object[key](this[i])){\r
+                                       result[key] = this[i];\r
+                                       delete object[key];\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+               return result;\r
+       },\r
+\r
+       contains: function(item, from){\r
+               return this.indexOf(item, from) != -1;\r
+       },\r
+\r
+       extend: function(array){\r
+               for (var i = 0, j = array.length; i < j; i++) this.push(array[i]);\r
+               return this;\r
+       },\r
+\r
+       getLast: function(){\r
+               return (this.length) ? this[this.length - 1] : null;\r
+       },\r
+\r
+       getRandom: function(){\r
+               return (this.length) ? this[$random(0, this.length - 1)] : null;\r
+       },\r
+\r
+       include: function(item){\r
+               if (!this.contains(item)) this.push(item);\r
+               return this;\r
+       },\r
+\r
+       combine: function(array){\r
+               for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);\r
+               return this;\r
+       },\r
+\r
+       erase: function(item){\r
+               for (var i = this.length; i--; i){\r
+                       if (this[i] === item) this.splice(i, 1);\r
+               }\r
+               return this;\r
+       },\r
+\r
+       empty: function(){\r
+               this.length = 0;\r
+               return this;\r
+       },\r
+\r
+       flatten: function(){\r
+               var array = [];\r
+               for (var i = 0, l = this.length; i < l; i++){\r
+                       var type = $type(this[i]);\r
+                       if (!type) continue;\r
+                       array = array.concat((type == 'array' || type == 'collection' || type == 'arguments') ? Array.flatten(this[i]) : this[i]);\r
+               }\r
+               return array;\r
+       },\r
+\r
+       hexToRgb: function(array){\r
+               if (this.length != 3) return null;\r
+               var rgb = this.map(function(value){\r
+                       if (value.length == 1) value += value;\r
+                       return value.toInt(16);\r
+               });\r
+               return (array) ? rgb : 'rgb(' + rgb + ')';\r
+       },\r
+\r
+       rgbToHex: function(array){\r
+               if (this.length < 3) return null;\r
+               if (this.length == 4 && this[3] == 0 && !array) return 'transparent';\r
+               var hex = [];\r
+               for (var i = 0; i < 3; i++){\r
+                       var bit = (this[i] - 0).toString(16);\r
+                       hex.push((bit.length == 1) ? '0' + bit : bit);\r
+               }\r
+               return (array) ? hex : '#' + hex.join('');\r
+       }\r
+\r
+});/*\r
+Script: Function.js\r
+       Contains Function Prototypes like create, bind, pass, and delay.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Function.implement({\r
+\r
+       extend: function(properties){\r
+               for (var property in properties) this[property] = properties[property];\r
+               return this;\r
+       },\r
+\r
+       create: function(options){\r
+               var self = this;\r
+               options = options || {};\r
+               return function(event){\r
+                       var args = options.arguments;\r
+                       args = (args != undefined) ? $splat(args) : Array.slice(arguments, (options.event) ? 1 : 0);\r
+                       if (options.event) args = [event || window.event].extend(args);\r
+                       var returns = function(){\r
+                               return self.apply(options.bind || null, args);\r
+                       };\r
+                       if (options.delay) return setTimeout(returns, options.delay);\r
+                       if (options.periodical) return setInterval(returns, options.periodical);\r
+                       if (options.attempt) return $try(returns);\r
+                       return returns();\r
+               };\r
+       },\r
+\r
+       pass: function(args, bind){\r
+               return this.create({arguments: args, bind: bind});\r
+       },\r
+\r
+       attempt: function(args, bind){\r
+               return this.create({arguments: args, bind: bind, attempt: true})();\r
+       },\r
+\r
+       bind: function(bind, args){\r
+               return this.create({bind: bind, arguments: args});\r
+       },\r
+\r
+       bindWithEvent: function(bind, args){\r
+               return this.create({bind: bind, event: true, arguments: args});\r
+       },\r
+\r
+       delay: function(delay, bind, args){\r
+               return this.create({delay: delay, bind: bind, arguments: args})();\r
+       },\r
+\r
+       periodical: function(interval, bind, args){\r
+               return this.create({periodical: interval, bind: bind, arguments: args})();\r
+       },\r
+\r
+       run: function(args, bind){\r
+               return this.apply(bind, $splat(args));\r
+       }\r
+\r
+});/*\r
+Script: Number.js\r
+       Contains Number Prototypes like limit, round, times, and ceil.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Number.implement({\r
+\r
+       limit: function(min, max){\r
+               return Math.min(max, Math.max(min, this));\r
+       },\r
+\r
+       round: function(precision){\r
+               precision = Math.pow(10, precision || 0);\r
+               return Math.round(this * precision) / precision;\r
+       },\r
+\r
+       times: function(fn, bind){\r
+               for (var i = 0; i < this; i++) fn.call(bind, i, this);\r
+       },\r
+\r
+       toFloat: function(){\r
+               return parseFloat(this);\r
+       },\r
+\r
+       toInt: function(base){\r
+               return parseInt(this, base || 10);\r
+       }\r
+\r
+});\r
+\r
+Number.alias('times', 'each');\r
+\r
+(function(math){\r
+       var methods = {};\r
+       math.each(function(name){\r
+               if (!Number[name]) methods[name] = function(){\r
+                       return Math[name].apply(null, [this].concat($A(arguments)));\r
+               };\r
+       });\r
+       Number.implement(methods);\r
+})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);/*\r
+Script: String.js\r
+       Contains String Prototypes like camelCase, capitalize, test, and toInt.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+String.implement({\r
+\r
+       test: function(regex, params){\r
+               return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this);\r
+       },\r
+\r
+       contains: function(string, separator){\r
+               return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;\r
+       },\r
+\r
+       trim: function(){\r
+               return this.replace(/^\s+|\s+$/g, '');\r
+       },\r
+\r
+       clean: function(){\r
+               return this.replace(/\s+/g, ' ').trim();\r
+       },\r
+\r
+       camelCase: function(){\r
+               return this.replace(/-\D/g, function(match){\r
+                       return match.charAt(1).toUpperCase();\r
+               });\r
+       },\r
+\r
+       hyphenate: function(){\r
+               return this.replace(/[A-Z]/g, function(match){\r
+                       return ('-' + match.charAt(0).toLowerCase());\r
+               });\r
+       },\r
+\r
+       capitalize: function(){\r
+               return this.replace(/\b[a-z]/g, function(match){\r
+                       return match.toUpperCase();\r
+               });\r
+       },\r
+\r
+       escapeRegExp: function(){\r
+               return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');\r
+       },\r
+\r
+       toInt: function(base){\r
+               return parseInt(this, base || 10);\r
+       },\r
+\r
+       toFloat: function(){\r
+               return parseFloat(this);\r
+       },\r
+\r
+       hexToRgb: function(array){\r
+               var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);\r
+               return (hex) ? hex.slice(1).hexToRgb(array) : null;\r
+       },\r
+\r
+       rgbToHex: function(array){\r
+               var rgb = this.match(/\d{1,3}/g);\r
+               return (rgb) ? rgb.rgbToHex(array) : null;\r
+       },\r
+\r
+       stripScripts: function(option){\r
+               var scripts = '';\r
+               var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){\r
+                       scripts += arguments[1] + '\n';\r
+                       return '';\r
+               });\r
+               if (option === true) $exec(scripts);\r
+               else if ($type(option) == 'function') option(scripts, text);\r
+               return text;\r
+       },\r
+\r
+       substitute: function(object, regexp){\r
+               return this.replace(regexp || (/\\?\{([^}]+)\}/g), function(match, name){\r
+                       if (match.charAt(0) == '\\') return match.slice(1);\r
+                       return (object[name] != undefined) ? object[name] : '';\r
+               });\r
+       }\r
+\r
+});/*\r
+Script: Hash.js\r
+       Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Hash.implement({\r
+\r
+       has: Object.prototype.hasOwnProperty,\r
+\r
+       keyOf: function(value){\r
+               for (var key in this){\r
+                       if (this.hasOwnProperty(key) && this[key] === value) return key;\r
+               }\r
+               return null;\r
+       },\r
+\r
+       hasValue: function(value){\r
+               return (Hash.keyOf(this, value) !== null);\r
+       },\r
+\r
+       extend: function(properties){\r
+               Hash.each(properties, function(value, key){\r
+                       Hash.set(this, key, value);\r
+               }, this);\r
+               return this;\r
+       },\r
+\r
+       combine: function(properties){\r
+               Hash.each(properties, function(value, key){\r
+                       Hash.include(this, key, value);\r
+               }, this);\r
+               return this;\r
+       },\r
+\r
+       erase: function(key){\r
+               if (this.hasOwnProperty(key)) delete this[key];\r
+               return this;\r
+       },\r
+\r
+       get: function(key){\r
+               return (this.hasOwnProperty(key)) ? this[key] : null;\r
+       },\r
+\r
+       set: function(key, value){\r
+               if (!this[key] || this.hasOwnProperty(key)) this[key] = value;\r
+               return this;\r
+       },\r
+\r
+       empty: function(){\r
+               Hash.each(this, function(value, key){\r
+                       delete this[key];\r
+               }, this);\r
+               return this;\r
+       },\r
+\r
+       include: function(key, value){\r
+               var k = this[key];\r
+               if (k == undefined) this[key] = value;\r
+               return this;\r
+       },\r
+\r
+       map: function(fn, bind){\r
+               var results = new Hash;\r
+               Hash.each(this, function(value, key){\r
+                       results.set(key, fn.call(bind, value, key, this));\r
+               }, this);\r
+               return results;\r
+       },\r
+\r
+       filter: function(fn, bind){\r
+               var results = new Hash;\r
+               Hash.each(this, function(value, key){\r
+                       if (fn.call(bind, value, key, this)) results.set(key, value);\r
+               }, this);\r
+               return results;\r
+       },\r
+\r
+       every: function(fn, bind){\r
+               for (var key in this){\r
+                       if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false;\r
+               }\r
+               return true;\r
+       },\r
+\r
+       some: function(fn, bind){\r
+               for (var key in this){\r
+                       if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true;\r
+               }\r
+               return false;\r
+       },\r
+\r
+       getKeys: function(){\r
+               var keys = [];\r
+               Hash.each(this, function(value, key){\r
+                       keys.push(key);\r
+               });\r
+               return keys;\r
+       },\r
+\r
+       getValues: function(){\r
+               var values = [];\r
+               Hash.each(this, function(value){\r
+                       values.push(value);\r
+               });\r
+               return values;\r
+       },\r
+       \r
+       toQueryString: function(base){\r
+               var queryString = [];\r
+               Hash.each(this, function(value, key){\r
+                       if (base) key = base + '[' + key + ']';\r
+                       var result;\r
+                       switch ($type(value)){\r
+                               case 'object': result = Hash.toQueryString(value, key); break;\r
+                               case 'array':\r
+                                       var qs = {};\r
+                                       value.each(function(val, i){\r
+                                               qs[i] = val;\r
+                                       });\r
+                                       result = Hash.toQueryString(qs, key);\r
+                               break;\r
+                               default: result = key + '=' + encodeURIComponent(value);\r
+                       }\r
+                       if (value != undefined) queryString.push(result);\r
+               });\r
+               \r
+               return queryString.join('&');\r
+       }\r
+\r
+});\r
+\r
+Hash.alias({keyOf: 'indexOf', hasValue: 'contains'});/*\r
+Script: Event.js\r
+       Contains the Event Native, to make the event object completely crossbrowser.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Event = new Native({\r
+\r
+       name: 'Event',\r
+\r
+       initialize: function(event, win){\r
+               win = win || window;\r
+               var doc = win.document;\r
+               event = event || win.event;\r
+               if (event.$extended) return event;\r
+               this.$extended = true;\r
+               var type = event.type;\r
+               var target = event.target || event.srcElement;\r
+               while (target && target.nodeType == 3) target = target.parentNode;\r
+               \r
+               if (type.test(/key/)){\r
+                       var code = event.which || event.keyCode;\r
+                       var key = Event.Keys.keyOf(code);\r
+                       if (type == 'keydown'){\r
+                               var fKey = code - 111;\r
+                               if (fKey > 0 && fKey < 13) key = 'f' + fKey;\r
+                       }\r
+                       key = key || String.fromCharCode(code).toLowerCase();\r
+               } else if (type.match(/(click|mouse|menu)/i)){\r
+                       doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;\r
+                       var page = {\r
+                               x: event.pageX || event.clientX + doc.scrollLeft,\r
+                               y: event.pageY || event.clientY + doc.scrollTop\r
+                       };\r
+                       var client = {\r
+                               x: (event.pageX) ? event.pageX - win.pageXOffset : event.clientX,\r
+                               y: (event.pageY) ? event.pageY - win.pageYOffset : event.clientY\r
+                       };\r
+                       if (type.match(/DOMMouseScroll|mousewheel/)){\r
+                               var wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;\r
+                       }\r
+                       var rightClick = (event.which == 3) || (event.button == 2);\r
+                       var related = null;\r
+                       if (type.match(/over|out/)){\r
+                               switch (type){\r
+                                       case 'mouseover': related = event.relatedTarget || event.fromElement; break;\r
+                                       case 'mouseout': related = event.relatedTarget || event.toElement;\r
+                               }\r
+                               if (!(function(){\r
+                                       while (related && related.nodeType == 3) related = related.parentNode;\r
+                                       return true;\r
+                               }).create({attempt: Browser.Engine.gecko})()) related = false;\r
+                       }\r
+               }\r
+\r
+               return $extend(this, {\r
+                       event: event,\r
+                       type: type,\r
+                       \r
+                       page: page,\r
+                       client: client,\r
+                       rightClick: rightClick,\r
+                       \r
+                       wheel: wheel,\r
+                       \r
+                       relatedTarget: related,\r
+                       target: target,\r
+                       \r
+                       code: code,\r
+                       key: key,\r
+                       \r
+                       shift: event.shiftKey,\r
+                       control: event.ctrlKey,\r
+                       alt: event.altKey,\r
+                       meta: event.metaKey\r
+               });\r
+       }\r
+\r
+});\r
+\r
+Event.Keys = new Hash({\r
+       'enter': 13,\r
+       'up': 38,\r
+       'down': 40,\r
+       'left': 37,\r
+       'right': 39,\r
+       'esc': 27,\r
+       'space': 32,\r
+       'backspace': 8,\r
+       'tab': 9,\r
+       'delete': 46\r
+});\r
+\r
+Event.implement({\r
+\r
+       stop: function(){\r
+               return this.stopPropagation().preventDefault();\r
+       },\r
+\r
+       stopPropagation: function(){\r
+               if (this.event.stopPropagation) this.event.stopPropagation();\r
+               else this.event.cancelBubble = true;\r
+               return this;\r
+       },\r
+\r
+       preventDefault: function(){\r
+               if (this.event.preventDefault) this.event.preventDefault();\r
+               else this.event.returnValue = false;\r
+               return this;\r
+       }\r
+\r
+});/*\r
+Script: Class.js\r
+       Contains the Class Function for easily creating, extending, and implementing reusable Classes.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Class = new Native({\r
+\r
+       name: 'Class',\r
+\r
+       initialize: function(properties){\r
+\r
+               properties = properties || {};\r
+\r
+               var klass = function(empty){\r
+                                               \r
+                       for (var key in this) this[key] = $unlink(this[key]);\r
+\r
+                       for (var mutator in Class.Mutators){\r
+                               if (!this[mutator]) continue;\r
+                               Class.Mutators[mutator](this, this[mutator]);\r
+                               delete this[mutator];\r
+                       }\r
+\r
+                       this.constructor = klass;\r
+                       \r
+                       if (empty === $empty) return this;\r
+                       \r
+                       var self = (this.initialize) ? this.initialize.apply(this, arguments) : this;\r
+                       if (this.options && this.options.initialize) this.options.initialize.call(this);\r
+\r
+                       return self;\r
+               };\r
+\r
+               $extend(klass, this);\r
+               klass.constructor = Class;\r
+               klass.prototype = properties;\r
+               return klass;\r
+       }\r
+\r
+});\r
+\r
+Class.implement({\r
+\r
+       implement: function(){\r
+               Class.Mutators.Implements(this.prototype, Array.slice(arguments));\r
+               return this;\r
+       }\r
+\r
+});\r
+\r
+Class.Mutators = {};\r
+\r
+Class.Mutators.Implements = function(self, klasses){\r
+       $splat(klasses).each(function(klass){\r
+               $extend(self, ($type(klass) == 'class') ? new klass($empty) : klass);\r
+       });\r
+};\r
+\r
+Class.Mutators.Extends = function(self, klass){\r
+       \r
+       var instance = new klass($empty);\r
+       \r
+       delete instance.parent;\r
+       delete instance.parentOf;\r
+       \r
+       for (var key in instance){\r
+\r
+               var current = self[key], previous = instance[key];\r
+               \r
+               if (current == undefined){\r
+                       self[key] = previous;\r
+                       continue;\r
+               }\r
+\r
+               var ctype = $type(current), ptype = $type(previous);\r
+               \r
+               if (ctype != ptype) continue;\r
+               \r
+               switch (ctype){\r
+                       case 'function': \r
+                       \r
+                               // opera does not support function.caller, so we replace the function code with brute force. Not pretty, but its just for opera.\r
+                               // if future opera versions will support function.caller, this code wont be executed anymore.\r
+                               // this code will be only executed if the current browser does not support function.caller (only opera).\r
+                               // there is also a fix for an opera bug where in the function string, parentheses around numbers are ignored, and an error is thrown.\r
+                               \r
+                               if (!arguments.callee.caller) self[key] = eval('(' + String(current).replace(/\bthis\.parent\(\s*(\))?/g, function(full, close){\r
+                                       return 'arguments.callee._parent_.call(this' + (close || ', ');\r
+                               }).replace(/(\d+)\.([A-Za-z_])/g, '($1).$2') + ')');\r
+                               \r
+                               // end "opera" code\r
+                       \r
+                               self[key]._parent_ = previous;\r
+                       break;\r
+                       case 'object': self[key] = $merge(previous, current);\r
+               }\r
+               \r
+       }\r
+       \r
+       self.parent = function(){\r
+               return arguments.callee.caller._parent_.apply(this, arguments);\r
+       };\r
+       \r
+       self.parentOf = function(descendant){\r
+               return descendant._parent_.apply(this, Array.slice(arguments, 1));\r
+       };\r
+\r
+};/*\r
+Script: Class.Extras.js\r
+       Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Chain = new Class({\r
+\r
+       chain: function(){\r
+               this.$chain = (this.$chain || []).extend(arguments);\r
+               return this;\r
+       },\r
+\r
+       callChain: function(){\r
+               return (this.$chain && this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;\r
+       },\r
+\r
+       clearChain: function(){\r
+               if (this.$chain) this.$chain.empty();\r
+               return this;\r
+       }\r
+\r
+});\r
+\r
+var Events = new Class({\r
+\r
+       addEvent: function(type, fn, internal){\r
+               if (fn != $empty){\r
+                       this.$events = this.$events || {};\r
+                       this.$events[type] = this.$events[type] || [];\r
+                       this.$events[type].include(fn);\r
+                       if (internal) fn.internal = true;\r
+               }\r
+               return this;\r
+       },\r
+\r
+       addEvents: function(events){\r
+               for (var type in events) this.addEvent(type, events[type]);\r
+               return this;\r
+       },\r
+\r
+       fireEvent: function(type, args, delay){\r
+               if (!this.$events || !this.$events[type]) return this;\r
+               this.$events[type].each(function(fn){\r
+                       fn.create({'bind': this, 'delay': delay, 'arguments': args})();\r
+               }, this);\r
+               return this;\r
+       },\r
+\r
+       removeEvent: function(type, fn){\r
+               if (!this.$events || !this.$events[type]) return this;\r
+               if (!fn.internal) this.$events[type].erase(fn);\r
+               return this;\r
+       },\r
+\r
+       removeEvents: function(type){\r
+               for (var e in this.$events){\r
+                       if (type && type != e) continue;\r
+                       var fns = this.$events[e];\r
+                       for (var i = fns.length; i--; i) this.removeEvent(e, fns[i]);\r
+               }\r
+               return this;\r
+       }\r
+\r
+});\r
+\r
+var Options = new Class({\r
+\r
+       setOptions: function(){\r
+               this.options = $merge.run([this.options].extend(arguments));\r
+               if (!this.addEvent) return this;\r
+               for (var option in this.options){\r
+                       if ($type(this.options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;\r
+                       this.addEvent(option, this.options[option]);\r
+                       delete this.options[option];\r
+               }\r
+               return this;\r
+       }\r
+\r
+});/*\r
+Script: Element.js\r
+       One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser,\r
+       time-saver methods to let you easily work with HTML Elements.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Document.implement({\r
+\r
+       newElement: function(tag, props){\r
+               if (Browser.Engine.trident && props){\r
+                       ['name', 'type', 'checked'].each(function(attribute){\r
+                               if (!props[attribute]) return;\r
+                               tag += ' ' + attribute + '="' + props[attribute] + '"';\r
+                               if (attribute != 'checked') delete props[attribute];\r
+                       });\r
+                       tag = '<' + tag + '>';\r
+               }\r
+               return $.element(this.createElement(tag)).set(props);\r
+       },\r
+\r
+       newTextNode: function(text){\r
+               return this.createTextNode(text);\r
+       },\r
+\r
+       getDocument: function(){\r
+               return this;\r
+       },\r
+\r
+       getWindow: function(){\r
+               return this.defaultView || this.parentWindow;\r
+       },\r
+\r
+       purge: function(){\r
+               var elements = this.getElementsByTagName('*');\r
+               for (var i = 0, l = elements.length; i < l; i++) Browser.freeMem(elements[i]);\r
+       }\r
+\r
+});\r
+\r
+var Element = new Native({\r
+\r
+       name: 'Element',\r
+\r
+       legacy: window.Element,\r
+\r
+       initialize: function(tag, props){\r
+               var konstructor = Element.Constructors.get(tag);\r
+               if (konstructor) return konstructor(props);\r
+               if (typeof tag == 'string') return document.newElement(tag, props);\r
+               return $(tag).set(props);\r
+       },\r
+\r
+       afterImplement: function(key, value){\r
+               if (!Array[key]) Elements.implement(key, Elements.multi(key));\r
+               Element.Prototype[key] = value;\r
+       }\r
+\r
+});\r
+\r
+Element.Prototype = {$family: {name: 'element'}};\r
+\r
+Element.Constructors = new Hash;\r
+\r
+var IFrame = new Native({\r
+\r
+       name: 'IFrame',\r
+\r
+       generics: false,\r
+\r
+       initialize: function(){\r
+               var params = Array.link(arguments, {properties: Object.type, iframe: $defined});\r
+               var props = params.properties || {};\r
+               var iframe = $(params.iframe) || false;\r
+               var onload = props.onload || $empty;\r
+               delete props.onload;\r
+               props.id = props.name = $pick(props.id, props.name, iframe.id, iframe.name, 'IFrame_' + $time());\r
+               iframe = new Element(iframe || 'iframe', props);\r
+               var onFrameLoad = function(){\r
+                       var host = $try(function(){\r
+                               return iframe.contentWindow.location.host;\r
+                       });\r
+                       if (host && host == window.location.host){\r
+                               var win = new Window(iframe.contentWindow);\r
+                               var doc = new Document(iframe.contentWindow.document);\r
+                               $extend(win.Element.prototype, Element.Prototype);\r
+                       }\r
+                       onload.call(iframe.contentWindow, iframe.contentWindow.document);\r
+               };\r
+               (!window.frames[props.id]) ? iframe.addListener('load', onFrameLoad) : onFrameLoad();\r
+               return iframe;\r
+       }\r
+\r
+});\r
+\r
+var Elements = new Native({\r
+\r
+       initialize: function(elements, options){\r
+               options = $extend({ddup: true, cash: true}, options);\r
+               elements = elements || [];\r
+               if (options.ddup || options.cash){\r
+                       var uniques = {}, returned = [];\r
+                       for (var i = 0, l = elements.length; i < l; i++){\r
+                               var el = $.element(elements[i], !options.cash);\r
+                               if (options.ddup){\r
+                                       if (uniques[el.uid]) continue;\r
+                                       uniques[el.uid] = true;\r
+                               }\r
+                               returned.push(el);\r
+                       }\r
+                       elements = returned;\r
+               }\r
+               return (options.cash) ? $extend(elements, this) : elements;\r
+       }\r
+\r
+});\r
+\r
+Elements.implement({\r
+\r
+       filter: function(filter, bind){\r
+               if (!filter) return this;\r
+               return new Elements(Array.filter(this, (typeof filter == 'string') ? function(item){\r
+                       return item.match(filter);\r
+               } : filter, bind));\r
+       }\r
+\r
+});\r
+\r
+Elements.multi = function(property){\r
+       return function(){\r
+               var items = [];\r
+               var elements = true;\r
+               for (var i = 0, j = this.length; i < j; i++){\r
+                       var returns = this[i][property].apply(this[i], arguments);\r
+                       items.push(returns);\r
+                       if (elements) elements = ($type(returns) == 'element');\r
+               }\r
+               return (elements) ? new Elements(items) : items;\r
+       };\r
+};\r
+\r
+Window.implement({\r
+\r
+       $: function(el, nocash){\r
+               if (el && el.$family && el.uid) return el;\r
+               var type = $type(el);\r
+               return ($[type]) ? $[type](el, nocash, this.document) : null;\r
+       },\r
+\r
+       $$: function(selector){\r
+               if (arguments.length == 1 && typeof selector == 'string') return this.document.getElements(selector);\r
+               var elements = [];\r
+               var args = Array.flatten(arguments);\r
+               for (var i = 0, l = args.length; i < l; i++){\r
+                       var item = args[i];\r
+                       switch ($type(item)){\r
+                               case 'element': item = [item]; break;\r
+                               case 'string': item = this.document.getElements(item, true); break;\r
+                               default: item = false;\r
+                       }\r
+                       if (item) elements.extend(item);\r
+               }\r
+               return new Elements(elements);\r
+       },\r
+\r
+       getDocument: function(){\r
+               return this.document;\r
+       },\r
+\r
+       getWindow: function(){\r
+               return this;\r
+       }\r
+\r
+});\r
+\r
+$.string = function(id, nocash, doc){\r
+       id = doc.getElementById(id);\r
+       return (id) ? $.element(id, nocash) : null;\r
+};\r
+\r
+$.element = function(el, nocash){\r
+       $uid(el);\r
+       if (!nocash && !el.$family && !(/^object|embed$/i).test(el.tagName)){\r
+               var proto = Element.Prototype;\r
+               for (var p in proto) el[p] = proto[p];\r
+       };\r
+       return el;\r
+};\r
+\r
+$.object = function(obj, nocash, doc){\r
+       if (obj.toElement) return $.element(obj.toElement(doc), nocash);\r
+       return null;\r
+};\r
+\r
+$.textnode = $.whitespace = $.window = $.document = $arguments(0);\r
+\r
+Native.implement([Element, Document], {\r
+\r
+       getElement: function(selector, nocash){\r
+               return $(this.getElements(selector, true)[0] || null, nocash);\r
+       },\r
+\r
+       getElements: function(tags, nocash){\r
+               tags = tags.split(',');\r
+               var elements = [];\r
+               var ddup = (tags.length > 1);\r
+               tags.each(function(tag){\r
+                       var partial = this.getElementsByTagName(tag.trim());\r
+                       (ddup) ? elements.extend(partial) : elements = partial;\r
+               }, this);\r
+               return new Elements(elements, {ddup: ddup, cash: !nocash});\r
+       }\r
+\r
+});\r
+\r
+Element.Storage = {\r
+\r
+       get: function(uid){\r
+               return (this[uid] || (this[uid] = {}));\r
+       }\r
+\r
+};\r
+\r
+Element.Inserters = new Hash({\r
+\r
+       before: function(context, element){\r
+               if (element.parentNode) element.parentNode.insertBefore(context, element);\r
+       },\r
+\r
+       after: function(context, element){\r
+               if (!element.parentNode) return;\r
+               var next = element.nextSibling;\r
+               (next) ? element.parentNode.insertBefore(context, next) : element.parentNode.appendChild(context);\r
+       },\r
+\r
+       bottom: function(context, element){\r
+               element.appendChild(context);\r
+       },\r
+\r
+       top: function(context, element){\r
+               var first = element.firstChild;\r
+               (first) ? element.insertBefore(context, first) : element.appendChild(context);\r
+       }\r
+\r
+});\r
+\r
+Element.Inserters.inside = Element.Inserters.bottom;\r
+\r
+Element.Inserters.each(function(value, key){\r
+\r
+       var Key = key.capitalize();\r
+\r
+       Element.implement('inject' + Key, function(el){\r
+               value(this, $(el, true));\r
+               return this;\r
+       });\r
+\r
+       Element.implement('grab' + Key, function(el){\r
+               value($(el, true), this);\r
+               return this;\r
+       });\r
+\r
+});\r
+\r
+Element.implement({\r
+\r
+       getDocument: function(){\r
+               return this.ownerDocument;\r
+       },\r
+\r
+       getWindow: function(){\r
+               return this.ownerDocument.getWindow();\r
+       },\r
+\r
+       getElementById: function(id, nocash){\r
+               var el = this.ownerDocument.getElementById(id);\r
+               if (!el) return null;\r
+               for (var parent = el.parentNode; parent != this; parent = parent.parentNode){\r
+                       if (!parent) return null;\r
+               }\r
+               return $.element(el, nocash);\r
+       },\r
+\r
+       set: function(prop, value){\r
+               switch ($type(prop)){\r
+                       case 'object':\r
+                               for (var p in prop) this.set(p, prop[p]);\r
+                               break;\r
+                       case 'string':\r
+                               var property = Element.Properties.get(prop);\r
+                               (property && property.set) ? property.set.apply(this, Array.slice(arguments, 1)) : this.setProperty(prop, value);\r
+               }\r
+               return this;\r
+       },\r
+\r
+       get: function(prop){\r
+               var property = Element.Properties.get(prop);\r
+               return (property && property.get) ? property.get.apply(this, Array.slice(arguments, 1)) : this.getProperty(prop);\r
+       },\r
+\r
+       erase: function(prop){\r
+               var property = Element.Properties.get(prop);\r
+               (property && property.erase) ? property.erase.apply(this, Array.slice(arguments, 1)) : this.removeProperty(prop);\r
+               return this;\r
+       },\r
+\r
+       match: function(tag){\r
+               return (!tag || Element.get(this, 'tag') == tag);\r
+       },\r
+\r
+       inject: function(el, where){\r
+               Element.Inserters.get(where || 'bottom')(this, $(el, true));\r
+               return this;\r
+       },\r
+\r
+       wraps: function(el, where){\r
+               el = $(el, true);\r
+               return this.replaces(el).grab(el, where);\r
+       },\r
+\r
+       grab: function(el, where){\r
+               Element.Inserters.get(where || 'bottom')($(el, true), this);\r
+               return this;\r
+       },\r
+\r
+       appendText: function(text, where){\r
+               return this.grab(this.getDocument().newTextNode(text), where);\r
+       },\r
+\r
+       adopt: function(){\r
+               Array.flatten(arguments).each(function(element){\r
+                       element = $(element, true);\r
+                       if (element) this.appendChild(element);\r
+               }, this);\r
+               return this;\r
+       },\r
+\r
+       dispose: function(){\r
+               return (this.parentNode) ? this.parentNode.removeChild(this) : this;\r
+       },\r
+\r
+       clone: function(contents, keepid){\r
+               switch ($type(this)){\r
+                       case 'element':\r
+                               var attributes = {};\r
+                               for (var j = 0, l = this.attributes.length; j < l; j++){\r
+                                       var attribute = this.attributes[j], key = attribute.nodeName.toLowerCase();\r
+                                       var value = (key == 'style' && this.style) ? this.style.cssText : attribute.nodeValue;\r
+                                       if (!$chk(value) || key == 'uid' || (key == 'id' && !keepid)) continue;\r
+                                       if (value != 'inherit' && ['string', 'number'].contains($type(value))) attributes[key] = value;\r
+                               }\r
+                               var element = new Element(this.nodeName.toLowerCase(), attributes);\r
+                               if (contents !== false){\r
+                                       for (var i = 0, k = this.childNodes.length; i < k; i++){\r
+                                               var child = Element.clone(this.childNodes[i], true, keepid);\r
+                                               if (child) element.grab(child);\r
+                                       }\r
+                               }\r
+                               return element;\r
+                       case 'textnode': return document.newTextNode(this.nodeValue);\r
+               }\r
+               return null;\r
+       },\r
+\r
+       replaces: function(el){\r
+               el = $(el, true);\r
+               el.parentNode.replaceChild(this, el);\r
+               return this;\r
+       },\r
+\r
+       hasClass: function(className){\r
+               return this.className.contains(className, ' ');\r
+       },\r
+\r
+       addClass: function(className){\r
+               if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();\r
+               return this;\r
+       },\r
+\r
+       removeClass: function(className){\r
+               this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean();\r
+               return this;\r
+       },\r
+\r
+       toggleClass: function(className){\r
+               return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);\r
+       },\r
+\r
+       getComputedStyle: function(property){\r
+               if (this.currentStyle) return this.currentStyle[property.camelCase()];\r
+               var computed = this.getWindow().getComputedStyle(this, null);\r
+               return (computed) ? computed.getPropertyValue([property.hyphenate()]) : null;\r
+       },\r
+\r
+       empty: function(){\r
+               $A(this.childNodes).each(function(node){\r
+                       Browser.freeMem(node);\r
+                       Element.empty(node);\r
+                       Element.dispose(node);\r
+               }, this);\r
+               return this;\r
+       },\r
+\r
+       destroy: function(){\r
+               Browser.freeMem(this.empty().dispose());\r
+               return null;\r
+       },\r
+\r
+       getSelected: function(){\r
+               return new Elements($A(this.options).filter(function(option){\r
+                       return option.selected;\r
+               }));\r
+       },\r
+\r
+       toQueryString: function(){\r
+               var queryString = [];\r
+               this.getElements('input, select, textarea').each(function(el){\r
+                       if (!el.name || el.disabled) return;\r
+                       var value = (el.tagName.toLowerCase() == 'select') ? Element.getSelected(el).map(function(opt){\r
+                               return opt.value;\r
+                       }) : ((el.type == 'radio' || el.type == 'checkbox') && !el.checked) ? null : el.value;\r
+                       $splat(value).each(function(val){\r
+                               if (val) queryString.push(el.name + '=' + encodeURIComponent(val));\r
+                       });\r
+               });\r
+               return queryString.join('&');\r
+       },\r
+\r
+       getProperty: function(attribute){\r
+               var EA = Element.Attributes, key = EA.Props[attribute];\r
+               var value = (key) ? this[key] : this.getAttribute(attribute, 2);\r
+               return (EA.Bools[attribute]) ? !!value : (key) ? value : value || null;\r
+       },\r
+\r
+       getProperties: function(){\r
+               var args = $A(arguments);\r
+               return args.map(function(attr){\r
+                       return this.getProperty(attr);\r
+               }, this).associate(args);\r
+       },\r
+\r
+       setProperty: function(attribute, value){\r
+               var EA = Element.Attributes, key = EA.Props[attribute], hasValue = $defined(value);\r
+               if (key && EA.Bools[attribute]) value = (value || !hasValue) ? true : false;\r
+               else if (!hasValue) return this.removeProperty(attribute);\r
+               (key) ? this[key] = value : this.setAttribute(attribute, value);\r
+               return this;\r
+       },\r
+\r
+       setProperties: function(attributes){\r
+               for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);\r
+               return this;\r
+       },\r
+\r
+       removeProperty: function(attribute){\r
+               var EA = Element.Attributes, key = EA.Props[attribute], isBool = (key && EA.Bools[attribute]);\r
+               (key) ? this[key] = (isBool) ? false : '' : this.removeAttribute(attribute);\r
+               return this;\r
+       },\r
+\r
+       removeProperties: function(){\r
+               Array.each(arguments, this.removeProperty, this);\r
+               return this;\r
+       }\r
+\r
+});\r
+\r
+(function(){\r
+\r
+var walk = function(element, walk, start, match, all, nocash){\r
+       var el = element[start || walk];\r
+       var elements = [];\r
+       while (el){\r
+               if (el.nodeType == 1 && (!match || Element.match(el, match))){\r
+                       elements.push(el);\r
+                       if (!all) break;\r
+               }\r
+               el = el[walk];\r
+       }\r
+       return (all) ? new Elements(elements, {ddup: false, cash: !nocash}) : $(elements[0], nocash);\r
+};\r
+\r
+Element.implement({\r
+\r
+       getPrevious: function(match, nocash){\r
+               return walk(this, 'previousSibling', null, match, false, nocash);\r
+       },\r
+\r
+       getAllPrevious: function(match, nocash){\r
+               return walk(this, 'previousSibling', null, match, true, nocash);\r
+       },\r
+\r
+       getNext: function(match, nocash){\r
+               return walk(this, 'nextSibling', null, match, false, nocash);\r
+       },\r
+\r
+       getAllNext: function(match, nocash){\r
+               return walk(this, 'nextSibling', null, match, true, nocash);\r
+       },\r
+\r
+       getFirst: function(match, nocash){\r
+               return walk(this, 'nextSibling', 'firstChild', match, false, nocash);\r
+       },\r
+\r
+       getLast: function(match, nocash){\r
+               return walk(this, 'previousSibling', 'lastChild', match, false, nocash);\r
+       },\r
+\r
+       getParent: function(match, nocash){\r
+               return walk(this, 'parentNode', null, match, false, nocash);\r
+       },\r
+\r
+       getParents: function(match, nocash){\r
+               return walk(this, 'parentNode', null, match, true, nocash);\r
+       },\r
+\r
+       getChildren: function(match, nocash){\r
+               return walk(this, 'nextSibling', 'firstChild', match, true, nocash);\r
+       },\r
+\r
+       hasChild: function(el){\r
+               el = $(el, true);\r
+               return (!!el && $A(this.getElementsByTagName(el.tagName)).contains(el));\r
+       }\r
+\r
+});\r
+\r
+})();\r
+\r
+Element.Properties = new Hash;\r
+\r
+Element.Properties.style = {\r
+\r
+       set: function(style){\r
+               this.style.cssText = style;\r
+       },\r
+\r
+       get: function(){\r
+               return this.style.cssText;\r
+       },\r
+\r
+       erase: function(){\r
+               this.style.cssText = '';\r
+       }\r
+\r
+};\r
+\r
+Element.Properties.tag = {get: function(){\r
+       return this.tagName.toLowerCase();\r
+}};\r
+\r
+Element.Properties.href = {get: function(){\r
+       return (!this.href) ? null : this.href.replace(new RegExp('^' + document.location.protocol + '\/\/' + document.location.host), '');\r
+}};\r
+\r
+Element.Properties.html = {set: function(){\r
+       return this.innerHTML = Array.flatten(arguments).join('');\r
+}};\r
+\r
+Native.implement([Element, Window, Document], {\r
+\r
+       addListener: function(type, fn){\r
+               if (this.addEventListener) this.addEventListener(type, fn, false);\r
+               else this.attachEvent('on' + type, fn);\r
+               return this;\r
+       },\r
+\r
+       removeListener: function(type, fn){\r
+               if (this.removeEventListener) this.removeEventListener(type, fn, false);\r
+               else this.detachEvent('on' + type, fn);\r
+               return this;\r
+       },\r
+\r
+       retrieve: function(property, dflt){\r
+               var storage = Element.Storage.get(this.uid);\r
+               var prop = storage[property];\r
+               if ($defined(dflt) && !$defined(prop)) prop = storage[property] = dflt;\r
+               return $pick(prop);\r
+       },\r
+\r
+       store: function(property, value){\r
+               var storage = Element.Storage.get(this.uid);\r
+               storage[property] = value;\r
+               return this;\r
+       },\r
+\r
+       eliminate: function(property){\r
+               var storage = Element.Storage.get(this.uid);\r
+               delete storage[property];\r
+               return this;\r
+       }\r
+\r
+});\r
+\r
+Element.Attributes = new Hash({\r
+       Props: {'html': 'innerHTML', 'class': 'className', 'for': 'htmlFor', 'text': (Browser.Engine.trident) ? 'innerText' : 'textContent'},\r
+       Bools: ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readonly', 'multiple', 'selected', 'noresize', 'defer'],\r
+       Camels: ['value', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', 'rowSpan', 'tabIndex', 'useMap']\r
+});\r
+\r
+Browser.freeMem = function(item){\r
+       if (!item) return;\r
+       if (Browser.Engine.trident && (/object/i).test(item.tagName)){\r
+               for (var p in item){\r
+                       if (typeof item[p] == 'function') item[p] = $empty;\r
+               }\r
+               Element.dispose(item);\r
+       }\r
+       if (item.uid && item.removeEvents) item.removeEvents();\r
+};\r
+\r
+(function(EA){\r
+\r
+       var EAB = EA.Bools, EAC = EA.Camels;\r
+       EA.Bools = EAB = EAB.associate(EAB);\r
+       Hash.extend(Hash.combine(EA.Props, EAB), EAC.associate(EAC.map(function(v){\r
+               return v.toLowerCase();\r
+       })));\r
+       EA.erase('Camels');\r
+\r
+})(Element.Attributes);\r
+\r
+window.addListener('unload', function(){\r
+       window.removeListener('unload', arguments.callee);\r
+       document.purge();\r
+       if (Browser.Engine.trident) CollectGarbage();\r
+});/*\r
+Script: Element.Event.js\r
+       Contains Element methods for dealing with events, and custom Events.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Element.Properties.events = {set: function(events){\r
+       this.addEvents(events);\r
+}};\r
+\r
+Native.implement([Element, Window, Document], {\r
+\r
+       addEvent: function(type, fn){\r
+               var events = this.retrieve('events', {});\r
+               events[type] = events[type] || {'keys': [], 'values': []};\r
+               if (events[type].keys.contains(fn)) return this;\r
+               events[type].keys.push(fn);\r
+               var realType = type, custom = Element.Events.get(type), condition = fn, self = this;\r
+               if (custom){\r
+                       if (custom.onAdd) custom.onAdd.call(this, fn);\r
+                       if (custom.condition){\r
+                               condition = function(event){\r
+                                       if (custom.condition.call(this, event)) return fn.call(this, event);\r
+                                       return false;\r
+                               };\r
+                       }\r
+                       realType = custom.base || realType;\r
+               }\r
+               var defn = function(){\r
+                       return fn.call(self);\r
+               };\r
+               var nativeEvent = Element.NativeEvents[realType] || 0;\r
+               if (nativeEvent){\r
+                       if (nativeEvent == 2){\r
+                               defn = function(event){\r
+                                       event = new Event(event, self.getWindow());\r
+                                       if (condition.call(self, event) === false) event.stop();\r
+                               };\r
+                       }\r
+                       this.addListener(realType, defn);\r
+               }\r
+               events[type].values.push(defn);\r
+               return this;\r
+       },\r
+\r
+       removeEvent: function(type, fn){\r
+               var events = this.retrieve('events');\r
+               if (!events || !events[type]) return this;\r
+               var pos = events[type].keys.indexOf(fn);\r
+               if (pos == -1) return this;\r
+               var key = events[type].keys.splice(pos, 1)[0];\r
+               var value = events[type].values.splice(pos, 1)[0];\r
+               var custom = Element.Events.get(type);\r
+               if (custom){\r
+                       if (custom.onRemove) custom.onRemove.call(this, fn);\r
+                       type = custom.base || type;\r
+               }\r
+               return (Element.NativeEvents[type]) ? this.removeListener(type, value) : this;\r
+       },\r
+\r
+       addEvents: function(events){\r
+               for (var event in events) this.addEvent(event, events[event]);\r
+               return this;\r
+       },\r
+\r
+       removeEvents: function(type){\r
+               var events = this.retrieve('events');\r
+               if (!events) return this;\r
+               if (!type){\r
+                       for (var evType in events) this.removeEvents(evType);\r
+                       events = null;\r
+               } else if (events[type]){\r
+                       while (events[type].keys[0]) this.removeEvent(type, events[type].keys[0]);\r
+                       events[type] = null;\r
+               }\r
+               return this;\r
+       },\r
+\r
+       fireEvent: function(type, args, delay){\r
+               var events = this.retrieve('events');\r
+               if (!events || !events[type]) return this;\r
+               events[type].keys.each(function(fn){\r
+                       fn.create({'bind': this, 'delay': delay, 'arguments': args})();\r
+               }, this);\r
+               return this;\r
+       },\r
+\r
+       cloneEvents: function(from, type){\r
+               from = $(from);\r
+               var fevents = from.retrieve('events');\r
+               if (!fevents) return this;\r
+               if (!type){\r
+                       for (var evType in fevents) this.cloneEvents(from, evType);\r
+               } else if (fevents[type]){\r
+                       fevents[type].keys.each(function(fn){\r
+                               this.addEvent(type, fn);\r
+                       }, this);\r
+               }\r
+               return this;\r
+       }\r
+\r
+});\r
+\r
+Element.NativeEvents = {\r
+       click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons\r
+       mousewheel: 2, DOMMouseScroll: 2, //mouse wheel\r
+       mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement\r
+       keydown: 2, keypress: 2, keyup: 2, //keyboard\r
+       focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements\r
+       load: 1, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window\r
+       error: 1, abort: 1, scroll: 1 //misc\r
+};\r
+\r
+(function(){\r
+\r
+var $check = function(event){\r
+       var related = event.relatedTarget;\r
+       if (related == undefined) return true;\r
+       if (related === false) return false;\r
+       return ($type(this) != 'document' && related != this && related.prefix != 'xul' && !this.hasChild(related));\r
+};\r
+\r
+Element.Events = new Hash({\r
+\r
+       mouseenter: {\r
+               base: 'mouseover',\r
+               condition: $check\r
+       },\r
+\r
+       mouseleave: {\r
+               base: 'mouseout',\r
+               condition: $check\r
+       },\r
+\r
+       mousewheel: {\r
+               base: (Browser.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel'\r
+       }\r
+\r
+});\r
+\r
+})();/*\r
+Script: Element.Style.js\r
+       Contains methods for interacting with the styles of Elements in a fashionable way.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Element.Properties.styles = {set: function(styles){\r
+       this.setStyles(styles);\r
+}};\r
+\r
+Element.Properties.opacity = {\r
+\r
+       set: function(opacity, novisibility){\r
+               if (!novisibility){\r
+                       if (opacity == 0){\r
+                               if (this.style.visibility != 'hidden') this.style.visibility = 'hidden';\r
+                       } else {\r
+                               if (this.style.visibility != 'visible') this.style.visibility = 'visible';\r
+                       }\r
+               }\r
+               if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;\r
+               if (Browser.Engine.trident) this.style.filter = (opacity == 1) ? '' : 'alpha(opacity=' + opacity * 100 + ')';\r
+               this.style.opacity = opacity;\r
+               this.store('opacity', opacity);\r
+       },\r
+\r
+       get: function(){\r
+               return this.retrieve('opacity', 1);\r
+       }\r
+\r
+};\r
+\r
+Element.implement({\r
+       \r
+       setOpacity: function(value){\r
+               return this.set('opacity', value, true);\r
+       },\r
+       \r
+       getOpacity: function(){\r
+               return this.get('opacity');\r
+       },\r
+\r
+       setStyle: function(property, value){\r
+               switch (property){\r
+                       case 'opacity': return this.set('opacity', parseFloat(value));\r
+                       case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat';\r
+               }\r
+               property = property.camelCase();\r
+               if ($type(value) != 'string'){\r
+                       var map = (Element.Styles.get(property) || '@').split(' ');\r
+                       value = $splat(value).map(function(val, i){\r
+                               if (!map[i]) return '';\r
+                               return ($type(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;\r
+                       }).join(' ');\r
+               } else if (value == String(Number(value))){\r
+                       value = Math.round(value);\r
+               }\r
+               this.style[property] = value;\r
+               return this;\r
+       },\r
+\r
+       getStyle: function(property){\r
+               switch (property){\r
+                       case 'opacity': return this.get('opacity');\r
+                       case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat';\r
+               }\r
+               property = property.camelCase();\r
+               var result = this.style[property];\r
+               if (!$chk(result)){\r
+                       result = [];\r
+                       for (var style in Element.ShortStyles){\r
+                               if (property != style) continue;\r
+                               for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s));\r
+                               return result.join(' ');\r
+                       }\r
+                       result = this.getComputedStyle(property);\r
+               }\r
+               if (result){\r
+                       result = String(result);\r
+                       var color = result.match(/rgba?\([\d\s,]+\)/);\r
+                       if (color) result = result.replace(color[0], color[0].rgbToHex());\r
+               }\r
+               if (Browser.Engine.presto || (Browser.Engine.trident && !$chk(parseInt(result)))){\r
+                       if (property.test(/^(height|width)$/)){\r
+                               var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;\r
+                               values.each(function(value){\r
+                                       size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt();\r
+                               }, this);\r
+                               return this['offset' + property.capitalize()] - size + 'px';\r
+                       }\r
+                       if (Browser.Engine.presto && String(result).test('px')) return result;\r
+                       if (property.test(/(border(.+)Width|margin|padding)/)) return '0px';\r
+               }\r
+               return result;\r
+       },\r
+\r
+       setStyles: function(styles){\r
+               for (var style in styles) this.setStyle(style, styles[style]);\r
+               return this;\r
+       },\r
+\r
+       getStyles: function(){\r
+               var result = {};\r
+               Array.each(arguments, function(key){\r
+                       result[key] = this.getStyle(key);\r
+               }, this);\r
+               return result;\r
+       }\r
+\r
+});\r
+\r
+Element.Styles = new Hash({\r
+       left: '@px', top: '@px', bottom: '@px', right: '@px',\r
+       width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px',\r
+       backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)',\r
+       fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)',\r
+       margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',\r
+       borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',\r
+       zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@'\r
+});\r
+\r
+Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}};\r
+\r
+['Top', 'Right', 'Bottom', 'Left'].each(function(direction){\r
+       var Short = Element.ShortStyles;\r
+       var All = Element.Styles;\r
+       ['margin', 'padding'].each(function(style){\r
+               var sd = style + direction;\r
+               Short[style][sd] = All[sd] = '@px';\r
+       });\r
+       var bd = 'border' + direction;\r
+       Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';\r
+       var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';\r
+       Short[bd] = {};\r
+       Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';\r
+       Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';\r
+       Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)';\r
+});\r
+/*\r
+Script: Element.Dimensions.js\r
+       Contains methods to work with size, scroll, or positioning of Elements and the window object.\r
+\r
+License:\r
+       MIT-style license.\r
+\r
+Credits:\r
+       - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html).\r
+       - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html).\r
+*/\r
+\r
+(function(){\r
+\r
+Element.implement({\r
+\r
+       scrollTo: function(x, y){\r
+               if (isBody(this)){\r
+                       this.getWindow().scrollTo(x, y);\r
+               } else {\r
+                       this.scrollLeft = x;\r
+                       this.scrollTop = y;\r
+               }\r
+               return this;\r
+       },\r
+\r
+       getSize: function(){\r
+               if (isBody(this)) return this.getWindow().getSize();\r
+               return {x: this.offsetWidth, y: this.offsetHeight};\r
+       },\r
+\r
+       getScrollSize: function(){\r
+               if (isBody(this)) return this.getWindow().getScrollSize();\r
+               return {x: this.scrollWidth, y: this.scrollHeight};\r
+       },\r
+\r
+       getScroll: function(){\r
+               if (isBody(this)) return this.getWindow().getScroll();\r
+               return {x: this.scrollLeft, y: this.scrollTop};\r
+       },\r
+\r
+       getScrolls: function(){\r
+               var element = this, position = {x: 0, y: 0};\r
+               while (element && !isBody(element)){\r
+                       position.x += element.scrollLeft;\r
+                       position.y += element.scrollTop;\r
+                       element = element.parentNode;\r
+               }\r
+               return position;\r
+       },\r
+\r
+       getOffsets: function(){\r
+               var element = this, position = {x: 0, y: 0};\r
+               if (isBody(this)) return position;\r
+\r
+               while (element && !isBody(element)){\r
+                       position.x += element.offsetLeft;\r
+                       position.y += element.offsetTop;\r
+\r
+                       if (Browser.Engine.gecko){\r
+                               if (!borderBox(element)){\r
+                                       position.x += leftBorder(element);\r
+                                       position.y += topBorder(element);\r
+                               }\r
+                               var parent = element.parentNode;\r
+                               if (parent && styleString(parent, 'overflow') != 'visible'){\r
+                                       position.x += leftBorder(parent);\r
+                                       position.y += topBorder(parent);\r
+                               }\r
+                       } else if (element != this && (Browser.Engine.trident || Browser.Engine.webkit)){\r
+                               position.x += leftBorder(element);\r
+                               position.y += topBorder(element);\r
+                       }\r
+\r
+                       element = element.offsetParent;\r
+                       if (Browser.Engine.trident){\r
+                               while (element && !element.currentStyle.hasLayout) element = element.offsetParent;\r
+                       }\r
+               }\r
+               if (Browser.Engine.gecko && !borderBox(this)){\r
+                       position.x -= leftBorder(this);\r
+                       position.y -= topBorder(this);\r
+               }\r
+               return position;\r
+       },\r
+\r
+       getPosition: function(relative){\r
+               if (isBody(this)) return {x: 0, y: 0};\r
+               var offset = this.getOffsets(), scroll = this.getScrolls();\r
+               var position = {x: offset.x - scroll.x, y: offset.y - scroll.y};\r
+               var relativePosition = (relative && (relative = $(relative))) ? relative.getPosition() : {x: 0, y: 0};\r
+               return {x: position.x - relativePosition.x, y: position.y - relativePosition.y};\r
+       },\r
+\r
+       getCoordinates: function(element){\r
+               if (isBody(this)) return this.getWindow().getCoordinates();\r
+               var position = this.getPosition(element), size = this.getSize();\r
+               var obj = {left: position.x, top: position.y, width: size.x, height: size.y};\r
+               obj.right = obj.left + obj.width;\r
+               obj.bottom = obj.top + obj.height;\r
+               return obj;\r
+       },\r
+\r
+       computePosition: function(obj){\r
+               return {left: obj.x - styleNumber(this, 'margin-left'), top: obj.y - styleNumber(this, 'margin-top')};\r
+       },\r
+\r
+       position: function(obj){\r
+               return this.setStyles(this.computePosition(obj));\r
+       }\r
+\r
+});\r
+\r
+Native.implement([Document, Window], {\r
+\r
+       getSize: function(){\r
+               var win = this.getWindow();\r
+               if (Browser.Engine.presto || Browser.Engine.webkit) return {x: win.innerWidth, y: win.innerHeight};\r
+               var doc = getCompatElement(this);\r
+               return {x: doc.clientWidth, y: doc.clientHeight};\r
+       },\r
+\r
+       getScroll: function(){\r
+               var win = this.getWindow();\r
+               var doc = getCompatElement(this);\r
+               return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};\r
+       },\r
+\r
+       getScrollSize: function(){\r
+               var doc = getCompatElement(this);\r
+               var min = this.getSize();\r
+               return {x: Math.max(doc.scrollWidth, min.x), y: Math.max(doc.scrollHeight, min.y)};\r
+       },\r
+\r
+       getPosition: function(){\r
+               return {x: 0, y: 0};\r
+       },\r
+\r
+       getCoordinates: function(){\r
+               var size = this.getSize();\r
+               return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x};\r
+       }\r
+\r
+});\r
+\r
+// private methods\r
+\r
+var styleString = Element.getComputedStyle;\r
+\r
+function styleNumber(element, style){\r
+       return styleString(element, style).toInt() || 0;\r
+};\r
+\r
+function borderBox(element){\r
+       return styleString(element, '-moz-box-sizing') == 'border-box';\r
+};\r
+\r
+function topBorder(element){\r
+       return styleNumber(element, 'border-top-width');\r
+};\r
+\r
+function leftBorder(element){\r
+       return styleNumber(element, 'border-left-width');\r
+};\r
+\r
+function isBody(element){\r
+       return (/^(?:body|html)$/i).test(element.tagName);\r
+};\r
+\r
+function getCompatElement(element){\r
+       var doc = element.getDocument();\r
+       return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;\r
+};\r
+\r
+})();\r
+\r
+//aliases\r
+\r
+Native.implement([Window, Document, Element], {\r
+\r
+       getHeight: function(){\r
+               return this.getSize().y;\r
+       },\r
+\r
+       getWidth: function(){\r
+               return this.getSize().x;\r
+       },\r
+\r
+       getScrollTop: function(){\r
+               return this.getScroll().y;\r
+       },\r
+\r
+       getScrollLeft: function(){\r
+               return this.getScroll().x;\r
+       },\r
+\r
+       getScrollHeight: function(){\r
+               return this.getScrollSize().y;\r
+       },\r
+\r
+       getScrollWidth: function(){\r
+               return this.getScrollSize().x;\r
+       },\r
+\r
+       getTop: function(){\r
+               return this.getPosition().y;\r
+       },\r
+\r
+       getLeft: function(){\r
+               return this.getPosition().x;\r
+       }\r
+\r
+});/*\r
+Script: Selectors.js\r
+       Adds advanced CSS Querying capabilities for targeting elements. Also includes pseudoselectors support.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Native.implement([Document, Element], {\r
+       \r
+       getElements: function(expression, nocash){\r
+               expression = expression.split(',');\r
+               var items, local = {};\r
+               for (var i = 0, l = expression.length; i < l; i++){\r
+                       var selector = expression[i], elements = Selectors.Utils.search(this, selector, local);\r
+                       if (i != 0 && elements.item) elements = $A(elements);\r
+                       items = (i == 0) ? elements : (items.item) ? $A(items).concat(elements) : items.concat(elements);\r
+               }\r
+               return new Elements(items, {ddup: (expression.length > 1), cash: !nocash});\r
+       }\r
+       \r
+});\r
+\r
+Element.implement({\r
+       \r
+       match: function(selector){\r
+               if (!selector) return true;\r
+               var tagid = Selectors.Utils.parseTagAndID(selector);\r
+               var tag = tagid[0], id = tagid[1];\r
+               if (!Selectors.Filters.byID(this, id) || !Selectors.Filters.byTag(this, tag)) return false;\r
+               var parsed = Selectors.Utils.parseSelector(selector);\r
+               return (parsed) ? Selectors.Utils.filter(this, parsed, {}) : true;\r
+       }\r
+       \r
+});\r
+\r
+var Selectors = {Cache: {nth: {}, parsed: {}}};\r
+\r
+Selectors.RegExps = {\r
+       id: (/#([\w-]+)/),\r
+       tag: (/^(\w+|\*)/),\r
+       quick: (/^(\w+|\*)$/),\r
+       splitter: (/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g),\r
+       combined: (/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)["']?(.*?)["']?)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g)\r
+};\r
+\r
+Selectors.Utils = {\r
+       \r
+       chk: function(item, uniques){\r
+               if (!uniques) return true;\r
+               var uid = $uid(item);\r
+               if (!uniques[uid]) return uniques[uid] = true;\r
+               return false;\r
+       },\r
+       \r
+       parseNthArgument: function(argument){\r
+               if (Selectors.Cache.nth[argument]) return Selectors.Cache.nth[argument];\r
+               var parsed = argument.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/);\r
+               if (!parsed) return false;\r
+               var inta = parseInt(parsed[1]);\r
+               var a = (inta || inta === 0) ? inta : 1;\r
+               var special = parsed[2] || false;\r
+               var b = parseInt(parsed[3]) || 0;\r
+               if (a != 0){\r
+                       b--;\r
+                       while (b < 1) b += a;\r
+                       while (b >= a) b -= a;\r
+               } else {\r
+                       a = b;\r
+                       special = 'index';\r
+               }\r
+               switch (special){\r
+                       case 'n': parsed = {a: a, b: b, special: 'n'}; break;\r
+                       case 'odd': parsed = {a: 2, b: 0, special: 'n'}; break;\r
+                       case 'even': parsed =  {a: 2, b: 1, special: 'n'}; break;\r
+                       case 'first': parsed = {a: 0, special: 'index'}; break;\r
+                       case 'last': parsed = {special: 'last-child'}; break;\r
+                       case 'only': parsed = {special: 'only-child'}; break;\r
+                       default: parsed = {a: (a - 1), special: 'index'};\r
+               }\r
+               \r
+               return Selectors.Cache.nth[argument] = parsed;\r
+       },\r
+       \r
+       parseSelector: function(selector){\r
+               if (Selectors.Cache.parsed[selector]) return Selectors.Cache.parsed[selector];\r
+               var m, parsed = {classes: [], pseudos: [], attributes: []};\r
+               while ((m = Selectors.RegExps.combined.exec(selector))){\r
+                       var cn = m[1], an = m[2], ao = m[3], av = m[4], pn = m[5], pa = m[6];\r
+                       if (cn){\r
+                               parsed.classes.push(cn);\r
+                       } else if (pn){\r
+                               var parser = Selectors.Pseudo.get(pn);\r
+                               if (parser) parsed.pseudos.push({parser: parser, argument: pa});\r
+                               else parsed.attributes.push({name: pn, operator: '=', value: pa});\r
+                       } else if (an){\r
+                               parsed.attributes.push({name: an, operator: ao, value: av});\r
+                       }\r
+               }\r
+               if (!parsed.classes.length) delete parsed.classes;\r
+               if (!parsed.attributes.length) delete parsed.attributes;\r
+               if (!parsed.pseudos.length) delete parsed.pseudos;\r
+               if (!parsed.classes && !parsed.attributes && !parsed.pseudos) parsed = null;\r
+               return Selectors.Cache.parsed[selector] = parsed;\r
+       },\r
+       \r
+       parseTagAndID: function(selector){\r
+               var tag = selector.match(Selectors.RegExps.tag);\r
+               var id = selector.match(Selectors.RegExps.id);\r
+               return [(tag) ? tag[1] : '*', (id) ? id[1] : false];\r
+       },\r
+       \r
+       filter: function(item, parsed, local){\r
+               var i;\r
+               if (parsed.classes){\r
+                       for (i = parsed.classes.length; i--; i){\r
+                               var cn = parsed.classes[i];\r
+                               if (!Selectors.Filters.byClass(item, cn)) return false;\r
+                       }\r
+               }\r
+               if (parsed.attributes){\r
+                       for (i = parsed.attributes.length; i--; i){\r
+                               var att = parsed.attributes[i];\r
+                               if (!Selectors.Filters.byAttribute(item, att.name, att.operator, att.value)) return false;\r
+                       }\r
+               }\r
+               if (parsed.pseudos){\r
+                       for (i = parsed.pseudos.length; i--; i){\r
+                               var psd = parsed.pseudos[i];\r
+                               if (!Selectors.Filters.byPseudo(item, psd.parser, psd.argument, local)) return false;\r
+                       }\r
+               }\r
+               return true;\r
+       },\r
+       \r
+       getByTagAndID: function(ctx, tag, id){\r
+               if (id){\r
+                       var item = ctx.getElementById(id, true);\r
+                       return (item && Selectors.Filters.byTag(item, tag)) ? [item] : [];\r
+               } else {\r
+                       return ctx.getElementsByTagName(tag);\r
+               }\r
+       },\r
+       \r
+       search: function(self, expression, local){\r
+               var splitters = [];\r
+               \r
+               var selectors = expression.trim().replace(Selectors.RegExps.splitter, function(m0, m1, m2){\r
+                       splitters.push(m1);\r
+                       return ':)' + m2;\r
+               }).split(':)');\r
+               \r
+               var items, match, filtered, item;\r
+               \r
+               for (var i = 0, l = selectors.length; i < l; i++){\r
+                       \r
+                       var selector = selectors[i];\r
+                       \r
+                       if (i == 0 && Selectors.RegExps.quick.test(selector)){\r
+                               items = self.getElementsByTagName(selector);\r
+                               continue;\r
+                       }\r
+                       \r
+                       var splitter = splitters[i - 1];\r
+                       \r
+                       var tagid = Selectors.Utils.parseTagAndID(selector);\r
+                       var tag = tagid[0], id = tagid[1];\r
+\r
+                       if (i == 0){\r
+                               items = Selectors.Utils.getByTagAndID(self, tag, id);\r
+                       } else {\r
+                               var uniques = {}, found = [];\r
+                               for (var j = 0, k = items.length; j < k; j++) found = Selectors.Getters[splitter](found, items[j], tag, id, uniques);\r
+                               items = found;\r
+                       }\r
+                       \r
+                       var parsed = Selectors.Utils.parseSelector(selector);\r
+                       \r
+                       if (parsed){\r
+                               filtered = [];\r
+                               for (var m = 0, n = items.length; m < n; m++){\r
+                                       item = items[m];\r
+                                       if (Selectors.Utils.filter(item, parsed, local)) filtered.push(item);\r
+                               }\r
+                               items = filtered;\r
+                       }\r
+                       \r
+               }\r
+               \r
+               return items;\r
+               \r
+       }\r
+       \r
+};\r
+\r
+Selectors.Getters = {\r
+       \r
+       ' ': function(found, self, tag, id, uniques){\r
+               var items = Selectors.Utils.getByTagAndID(self, tag, id);\r
+               for (var i = 0, l = items.length; i < l; i++){\r
+                       var item = items[i];\r
+                       if (Selectors.Utils.chk(item, uniques)) found.push(item);\r
+               }\r
+               return found;\r
+       },\r
+       \r
+       '>': function(found, self, tag, id, uniques){\r
+               var children = Selectors.Utils.getByTagAndID(self, tag, id);\r
+               for (var i = 0, l = children.length; i < l; i++){\r
+                       var child = children[i];\r
+                       if (child.parentNode == self && Selectors.Utils.chk(child, uniques)) found.push(child);\r
+               }\r
+               return found;\r
+       },\r
+       \r
+       '+': function(found, self, tag, id, uniques){\r
+               while ((self = self.nextSibling)){\r
+                       if (self.nodeType == 1){\r
+                               if (Selectors.Utils.chk(self, uniques) && Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self);\r
+                               break;\r
+                       }\r
+               }\r
+               return found;\r
+       },\r
+       \r
+       '~': function(found, self, tag, id, uniques){\r
+               \r
+               while ((self = self.nextSibling)){\r
+                       if (self.nodeType == 1){\r
+                               if (!Selectors.Utils.chk(self, uniques)) break;\r
+                               if (Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self);\r
+                       } \r
+               }\r
+               return found;\r
+       }\r
+       \r
+};\r
+\r
+Selectors.Filters = {\r
+       \r
+       byTag: function(self, tag){\r
+               return (tag == '*' || (self.tagName && self.tagName.toLowerCase() == tag));\r
+       },\r
+       \r
+       byID: function(self, id){\r
+               return (!id || (self.id && self.id == id));\r
+       },\r
+       \r
+       byClass: function(self, klass){\r
+               return (self.className && self.className.contains(klass, ' '));\r
+       },\r
+       \r
+       byPseudo: function(self, parser, argument, local){\r
+               return parser.call(self, argument, local);\r
+       },\r
+       \r
+       byAttribute: function(self, name, operator, value){\r
+               var result = Element.prototype.getProperty.call(self, name);\r
+               if (!result) return false;\r
+               if (!operator || value == undefined) return true;\r
+               switch (operator){\r
+                       case '=': return (result == value);\r
+                       case '*=': return (result.contains(value));\r
+                       case '^=': return (result.substr(0, value.length) == value);\r
+                       case '$=': return (result.substr(result.length - value.length) == value);\r
+                       case '!=': return (result != value);\r
+                       case '~=': return result.contains(value, ' ');\r
+                       case '|=': return result.contains(value, '-');\r
+               }\r
+               return false;\r
+       }\r
+       \r
+};\r
+\r
+Selectors.Pseudo = new Hash({\r
+       \r
+       // w3c pseudo selectors\r
+       \r
+       empty: function(){\r
+               return !(this.innerText || this.textContent || '').length;\r
+       },\r
+       \r
+       not: function(selector){\r
+               return !Element.match(this, selector);\r
+       },\r
+       \r
+       contains: function(text){\r
+               return (this.innerText || this.textContent || '').contains(text);\r
+       },\r
+       \r
+       'first-child': function(){\r
+               return Selectors.Pseudo.index.call(this, 0);\r
+       },\r
+       \r
+       'last-child': function(){\r
+               var element = this;\r
+               while ((element = element.nextSibling)){\r
+                       if (element.nodeType == 1) return false;\r
+               }\r
+               return true;\r
+       },\r
+       \r
+       'only-child': function(){\r
+               var prev = this;\r
+               while ((prev = prev.previousSibling)){\r
+                       if (prev.nodeType == 1) return false;\r
+               }\r
+               var next = this;\r
+               while ((next = next.nextSibling)){\r
+                       if (next.nodeType == 1) return false;\r
+               }\r
+               return true;\r
+       },\r
+       \r
+       'nth-child': function(argument, local){\r
+               argument = (argument == undefined) ? 'n' : argument;\r
+               var parsed = Selectors.Utils.parseNthArgument(argument);\r
+               if (parsed.special != 'n') return Selectors.Pseudo[parsed.special].call(this, parsed.a, local);\r
+               var count = 0;\r
+               local.positions = local.positions || {};\r
+               var uid = $uid(this);\r
+               if (!local.positions[uid]){\r
+                       var self = this;\r
+                       while ((self = self.previousSibling)){\r
+                               if (self.nodeType != 1) continue;\r
+                               count ++;\r
+                               var position = local.positions[$uid(self)];\r
+                               if (position != undefined){\r
+                                       count = position + count;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       local.positions[uid] = count;\r
+               }\r
+               return (local.positions[uid] % parsed.a == parsed.b);\r
+       },\r
+       \r
+       // custom pseudo selectors\r
+       \r
+       index: function(index){\r
+               var element = this, count = 0;\r
+               while ((element = element.previousSibling)){\r
+                       if (element.nodeType == 1 && ++count > index) return false;\r
+               }\r
+               return (count == index);\r
+       },\r
+       \r
+       even: function(argument, local){\r
+               return Selectors.Pseudo['nth-child'].call(this, '2n+1', local);\r
+       },\r
+\r
+       odd: function(argument, local){\r
+               return Selectors.Pseudo['nth-child'].call(this, '2n', local);\r
+       }\r
+       \r
+});/*\r
+Script: Domready.js\r
+       Contains the domready custom event.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Element.Events.domready = {\r
+\r
+       onAdd: function(fn){\r
+               if (Browser.loaded) fn.call(this);\r
+       }\r
+\r
+};\r
+\r
+(function(){\r
+       \r
+       var domready = function(){\r
+               if (Browser.loaded) return;\r
+               Browser.loaded = true;\r
+               window.fireEvent('domready');\r
+               document.fireEvent('domready');\r
+       };\r
+       \r
+       switch (Browser.Engine.name){\r
+\r
+               case 'webkit': (function(){\r
+                       (['loaded', 'complete'].contains(document.readyState)) ? domready() : arguments.callee.delay(50);\r
+               })(); break;\r
+\r
+               case 'trident':\r
+                       var temp = document.createElement('div');\r
+                       (function(){\r
+                               ($try(function(){\r
+                                       temp.doScroll('left');\r
+                                       return $(temp).inject(document.body).set('html', 'temp').dispose();\r
+                               })) ? domready() : arguments.callee.delay(50);\r
+                       })();\r
+               break;\r
+               \r
+               default:\r
+                       window.addEvent('load', domready);\r
+                       document.addEvent('DOMContentLoaded', domready);\r
+\r
+       }\r
+       \r
+})();/*\r
+Script: JSON.js\r
+       JSON encoder and decoder.\r
+\r
+License:\r
+       MIT-style license.\r
+\r
+See Also:\r
+       <http://www.json.org/>\r
+*/\r
+\r
+var JSON = new Hash({\r
+\r
+       encode: function(obj){\r
+               switch ($type(obj)){\r
+                       case 'string':\r
+                               return '"' + obj.replace(/[\x00-\x1f\\"]/g, JSON.$replaceChars) + '"';\r
+                       case 'array':\r
+                               return '[' + String(obj.map(JSON.encode).filter($defined)) + ']';\r
+                       case 'object': case 'hash':\r
+                               var string = [];\r
+                               Hash.each(obj, function(value, key){\r
+                                       var json = JSON.encode(value);\r
+                                       if (json) string.push(JSON.encode(key) + ':' + json);\r
+                               });\r
+                               return '{' + string + '}';\r
+                       case 'number': case 'boolean': return String(obj);\r
+                       case false: return 'null';\r
+               }\r
+               return null;\r
+       },\r
+\r
+       $specialChars: {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'},\r
+\r
+       $replaceChars: function(chr){\r
+               return JSON.$specialChars[chr] || '\\u00' + Math.floor(chr.charCodeAt() / 16).toString(16) + (chr.charCodeAt() % 16).toString(16);\r
+       },\r
+\r
+       decode: function(string, secure){\r
+               if ($type(string) != 'string' || !string.length) return null;\r
+               if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null;\r
+               return eval('(' + string + ')');\r
+       }\r
+\r
+});\r
+\r
+Native.implement([Hash, Array, String, Number], {\r
+\r
+       toJSON: function(){\r
+               return JSON.encode(this);\r
+       }\r
+\r
+});\r
+/*\r
+Script: Cookie.js\r
+       Class for creating, loading, and saving browser Cookies.\r
+\r
+License:\r
+       MIT-style license.\r
+\r
+Credits:\r
+       Based on the functions by Peter-Paul Koch (http://quirksmode.org).\r
+*/\r
+\r
+var Cookie = new Class({\r
+\r
+       Implements: Options,\r
+\r
+       options: {\r
+               path: false,\r
+               domain: false,\r
+               duration: false,\r
+               secure: false,\r
+               document: document\r
+       },\r
+\r
+       initialize: function(key, options){\r
+               this.key = key;\r
+               this.setOptions(options);\r
+       },\r
+\r
+       write: function(value){\r
+               value = encodeURIComponent(value);\r
+               if (this.options.domain) value += '; domain=' + this.options.domain;\r
+               if (this.options.path) value += '; path=' + this.options.path;\r
+               if (this.options.duration){\r
+                       var date = new Date();\r
+                       date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);\r
+                       value += '; expires=' + date.toGMTString();\r
+               }\r
+               if (this.options.secure) value += '; secure';\r
+               this.options.document.cookie = this.key + '=' + value;\r
+               return this;\r
+       },\r
+\r
+       read: function(){\r
+               var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)');\r
+               return (value) ? decodeURIComponent(value[1]) : null;\r
+       },\r
+\r
+       dispose: function(){\r
+               new Cookie(this.key, $merge(this.options, {duration: -1})).write('');\r
+               return this;\r
+       }\r
+\r
+});\r
+\r
+Cookie.write = function(key, value, options){\r
+       return new Cookie(key, options).write(value);\r
+};\r
+\r
+Cookie.read = function(key){\r
+       return new Cookie(key).read();\r
+};\r
+\r
+Cookie.dispose = function(key, options){\r
+       return new Cookie(key, options).dispose();\r
+};/*\r
+Script: Swiff.js\r
+       Wrapper for embedding SWF movies. Supports (and fixes) External Interface Communication.\r
+\r
+License:\r
+       MIT-style license.\r
+\r
+Credits:\r
+       Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject.\r
+*/\r
+\r
+var Swiff = new Class({\r
+\r
+       Implements: [Options],\r
+\r
+       options: {\r
+               id: null,\r
+               height: 1,\r
+               width: 1,\r
+               container: null,\r
+               properties: {},\r
+               params: {\r
+                       quality: 'high',\r
+                       allowScriptAccess: 'always',\r
+                       wMode: 'transparent',\r
+                       swLiveConnect: true\r
+               },\r
+               callBacks: {},\r
+               vars: {}\r
+       },\r
+\r
+       toElement: function(){\r
+               return this.object;\r
+       },\r
+\r
+       initialize: function(path, options){\r
+               this.instance = 'Swiff_' + $time();\r
+\r
+               this.setOptions(options);\r
+               options = this.options;\r
+               var id = this.id = options.id || this.instance;\r
+               var container = $(options.container);\r
+\r
+               Swiff.CallBacks[this.instance] = {};\r
+\r
+               var params = options.params, vars = options.vars, callBacks = options.callBacks;\r
+               var properties = $extend({height: options.height, width: options.width}, options.properties);\r
+\r
+               var self = this;\r
+\r
+               for (var callBack in callBacks){\r
+                       Swiff.CallBacks[this.instance][callBack] = (function(option){\r
+                               return function(){\r
+                                       return option.apply(self.object, arguments);\r
+                               };\r
+                       })(callBacks[callBack]);\r
+                       vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack;\r
+               }\r
+\r
+               params.flashVars = Hash.toQueryString(vars);\r
+               if (Browser.Engine.trident){\r
+                       properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';\r
+                       params.movie = path;\r
+               } else {\r
+                       properties.type = 'application/x-shockwave-flash';\r
+                       properties.data = path;\r
+               }\r
+               var build = '<object id="' + id + '"';\r
+               for (var property in properties) build += ' ' + property + '="' + properties[property] + '"';\r
+               build += '>';\r
+               for (var param in params){\r
+                       if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />';\r
+               }\r
+               build += '</object>';\r
+               this.object =  ((container) ? container.empty() : new Element('div')).set('html', build).firstChild;\r
+       },\r
+\r
+       replaces: function(element){\r
+               element = $(element, true);\r
+               element.parentNode.replaceChild(this.toElement(), element);\r
+               return this;\r
+       },\r
+\r
+       inject: function(element){\r
+               $(element, true).appendChild(this.toElement());\r
+               return this;\r
+       },\r
+\r
+       remote: function(){\r
+               return Swiff.remote.apply(Swiff, [this.toElement()].extend(arguments));\r
+       }\r
+\r
+});\r
+\r
+Swiff.CallBacks = {};\r
+\r
+Swiff.remote = function(obj, fn){\r
+       var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');\r
+       return eval(rs);\r
+};/*\r
+Script: Fx.js\r
+       Contains the basic animation logic to be extended by all other Fx Classes.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Fx = new Class({\r
+\r
+       Implements: [Chain, Events, Options],\r
+\r
+       options: {\r
+               /*\r
+               onStart: $empty,\r
+               onCancel: $empty,\r
+               onComplete: $empty,\r
+               */\r
+               fps: 50,\r
+               unit: false,\r
+               duration: 500,\r
+               link: 'ignore',\r
+               transition: function(p){\r
+                       return -(Math.cos(Math.PI * p) - 1) / 2;\r
+               }\r
+       },\r
+\r
+       initialize: function(options){\r
+               this.subject = this.subject || this;\r
+               this.setOptions(options);\r
+               this.options.duration = Fx.Durations[this.options.duration] || this.options.duration.toInt();\r
+               var wait = this.options.wait;\r
+               if (wait === false) this.options.link = 'cancel';\r
+       },\r
+\r
+       step: function(){\r
+               var time = $time();\r
+               if (time < this.time + this.options.duration){\r
+                       var delta = this.options.transition((time - this.time) / this.options.duration);\r
+                       this.set(this.compute(this.from, this.to, delta));\r
+               } else {\r
+                       this.set(this.compute(this.from, this.to, 1));\r
+                       this.complete();\r
+               }\r
+       },\r
+\r
+       set: function(now){\r
+               return now;\r
+       },\r
+\r
+       compute: function(from, to, delta){\r
+               return Fx.compute(from, to, delta);\r
+       },\r
+\r
+       check: function(caller){\r
+               if (!this.timer) return true;\r
+               switch (this.options.link){\r
+                       case 'cancel': this.cancel(); return true;\r
+                       case 'chain': this.chain(caller.bind(this, Array.slice(arguments, 1))); return false;\r
+               }\r
+               return false;\r
+       },\r
+\r
+       start: function(from, to){\r
+               if (!this.check(arguments.callee, from, to)) return this;\r
+               this.from = from;\r
+               this.to = to;\r
+               this.time = 0;\r
+               this.startTimer();\r
+               this.onStart();\r
+               return this;\r
+       },\r
+\r
+       complete: function(){\r
+               if (this.stopTimer()) this.onComplete();\r
+               return this;\r
+       },\r
+\r
+       cancel: function(){\r
+               if (this.stopTimer()) this.onCancel();\r
+               return this;\r
+       },\r
+\r
+       onStart: function(){\r
+               this.fireEvent('onStart', this.subject);\r
+       },\r
+\r
+       onComplete: function(){\r
+               this.fireEvent('onComplete', this.subject);\r
+               if (!this.callChain()) this.fireEvent('onChainComplete', this.subject);\r
+       },\r
+\r
+       onCancel: function(){\r
+               this.fireEvent('onCancel', this.subject).clearChain();\r
+       },\r
+\r
+       pause: function(){\r
+               this.stopTimer();\r
+               return this;\r
+       },\r
+\r
+       resume: function(){\r
+               this.startTimer();\r
+               return this;\r
+       },\r
+\r
+       stopTimer: function(){\r
+               if (!this.timer) return false;\r
+               this.time = $time() - this.time;\r
+               this.timer = $clear(this.timer);\r
+               return true;\r
+       },\r
+\r
+       startTimer: function(){\r
+               if (this.timer) return false;\r
+               this.time = $time() - this.time;\r
+               this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this);\r
+               return true;\r
+       }\r
+\r
+});\r
+\r
+Fx.compute = function(from, to, delta){\r
+       return (to - from) * delta + from;\r
+};\r
+\r
+Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000};\r
+/*\r
+Script: Fx.CSS.js\r
+       Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Fx.CSS = new Class({\r
+\r
+       Extends: Fx,\r
+\r
+       //prepares the base from/to object\r
+\r
+       prepare: function(element, property, values){\r
+               values = $splat(values);\r
+               var values1 = values[1];\r
+               if (!$chk(values1)){\r
+                       values[1] = values[0];\r
+                       values[0] = element.getStyle(property);\r
+               }\r
+               var parsed = values.map(this.parse);\r
+               return {from: parsed[0], to: parsed[1]};\r
+       },\r
+\r
+       //parses a value into an array\r
+\r
+       parse: function(value){\r
+               value = $lambda(value)();\r
+               value = (typeof value == 'string') ? value.split(' ') : $splat(value);\r
+               return value.map(function(val){\r
+                       val = String(val);\r
+                       var found = false;\r
+                       Fx.CSS.Parsers.each(function(parser, key){\r
+                               if (found) return;\r
+                               var parsed = parser.parse(val);\r
+                               if ($chk(parsed)) found = {value: parsed, parser: parser};\r
+                       });\r
+                       found = found || {value: val, parser: Fx.CSS.Parsers.String};\r
+                       return found;\r
+               });\r
+       },\r
+\r
+       //computes by a from and to prepared objects, using their parsers.\r
+\r
+       compute: function(from, to, delta){\r
+               var computed = [];\r
+               (Math.min(from.length, to.length)).times(function(i){\r
+                       computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});\r
+               });\r
+               computed.$family = {name: 'fx:css:value'};\r
+               return computed;\r
+       },\r
+\r
+       //serves the value as settable\r
+\r
+       serve: function(value, unit){\r
+               if ($type(value) != 'fx:css:value') value = this.parse(value);\r
+               var returned = [];\r
+               value.each(function(bit){\r
+                       returned = returned.concat(bit.parser.serve(bit.value, unit));\r
+               });\r
+               return returned;\r
+       },\r
+\r
+       //renders the change to an element\r
+\r
+       render: function(element, property, value, unit){\r
+               element.setStyle(property, this.serve(value, unit));\r
+       },\r
+\r
+       //searches inside the page css to find the values for a selector\r
+\r
+       search: function(selector){\r
+               if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];\r
+               var to = {};\r
+               Array.each(document.styleSheets, function(sheet, j){\r
+                       var href = sheet.href;\r
+                       if (href && href.contains('://') && !href.contains(document.domain)) return;\r
+                       var rules = sheet.rules || sheet.cssRules;\r
+                       Array.each(rules, function(rule, i){\r
+                               if (!rule.style) return;\r
+                               var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){\r
+                                       return m.toLowerCase();\r
+                               }) : null;\r
+                               if (!selectorText || !selectorText.test('^' + selector + '$')) return;\r
+                               Element.Styles.each(function(value, style){\r
+                                       if (!rule.style[style] || Element.ShortStyles[style]) return;\r
+                                       value = String(rule.style[style]);\r
+                                       to[style] = (value.test(/^rgb/)) ? value.rgbToHex() : value;\r
+                               });\r
+                       });\r
+               });\r
+               return Fx.CSS.Cache[selector] = to;\r
+       }\r
+\r
+});\r
+\r
+Fx.CSS.Cache = {};\r
+\r
+Fx.CSS.Parsers = new Hash({\r
+\r
+       Color: {\r
+               parse: function(value){\r
+                       if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);\r
+                       return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false;\r
+               },\r
+               compute: function(from, to, delta){\r
+                       return from.map(function(value, i){\r
+                               return Math.round(Fx.compute(from[i], to[i], delta));\r
+                       });\r
+               },\r
+               serve: function(value){\r
+                       return value.map(Number);\r
+               }\r
+       },\r
+\r
+       Number: {\r
+               parse: parseFloat,\r
+               compute: Fx.compute,\r
+               serve: function(value, unit){\r
+                       return (unit) ? value + unit : value;\r
+               }\r
+       },\r
+\r
+       String: {\r
+               parse: $lambda(false),\r
+               compute: $arguments(1),\r
+               serve: $arguments(0)\r
+       }\r
+\r
+});\r
+/*\r
+Script: Fx.Tween.js\r
+       Formerly Fx.Style, effect to transition any CSS property for an element.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Fx.Tween = new Class({\r
+\r
+       Extends: Fx.CSS,\r
+\r
+       initialize: function(element, options){\r
+               this.element = this.subject = $(element);\r
+               this.parent(options);\r
+       },\r
+\r
+       set: function(property, now){\r
+               if (arguments.length == 1){\r
+                       now = property;\r
+                       property = this.property || this.options.property;\r
+               }\r
+               this.render(this.element, property, now, this.options.unit);\r
+               return this;\r
+       },\r
+\r
+       start: function(property, from, to){\r
+               if (!this.check(arguments.callee, property, from, to)) return this;\r
+               var args = Array.flatten(arguments);\r
+               this.property = this.options.property || args.shift();\r
+               var parsed = this.prepare(this.element, this.property, args);\r
+               return this.parent(parsed.from, parsed.to);\r
+       }\r
+\r
+});\r
+\r
+Element.Properties.tween = {\r
+\r
+       set: function(options){\r
+               var tween = this.retrieve('tween');\r
+               if (tween) tween.cancel();\r
+               return this.eliminate('tween').store('tween:options', $extend({link: 'cancel'}, options));\r
+       },\r
+\r
+       get: function(options){\r
+               if (options || !this.retrieve('tween')){\r
+                       if (options || !this.retrieve('tween:options')) this.set('tween', options);\r
+                       this.store('tween', new Fx.Tween(this, this.retrieve('tween:options')));\r
+               }\r
+               return this.retrieve('tween');\r
+       }\r
+\r
+};\r
+\r
+Element.implement({\r
+\r
+       tween: function(property, from, to){\r
+               this.get('tween').start(arguments);\r
+               return this;\r
+       },\r
+\r
+       fade: function(how){\r
+               var fade = this.get('tween'), o = 'opacity', toggle;\r
+               how = $pick(how, 'toggle');\r
+               switch (how){\r
+                       case 'in': fade.start(o, 1); break;\r
+                       case 'out': fade.start(o, 0); break;\r
+                       case 'show': fade.set(o, 1); break;\r
+                       case 'hide': fade.set(o, 0); break;\r
+                       case 'toggle':\r
+                               var flag = this.retrieve('fade:flag', this.get('opacity') == 1);\r
+                               fade.start(o, (flag) ? 0 : 1);\r
+                               this.store('fade:flag', !flag);\r
+                               toggle = true;\r
+                       break;\r
+                       default: fade.start(o, arguments);\r
+               }\r
+               if (!toggle) this.eliminate('fade:flag');\r
+               return this;\r
+       },\r
+\r
+       highlight: function(start, end){\r
+               if (!end){\r
+                       end = this.retrieve('highlight:original', this.getStyle('background-color'));\r
+                       end = (end == 'transparent') ? '#fff' : end;\r
+               }\r
+               var tween = this.get('tween');\r
+               tween.start('background-color', start || '#ffff88', end).chain(function(){\r
+                       this.setStyle('background-color', this.retrieve('highlight:original'));\r
+                       tween.callChain();\r
+               }.bind(this));\r
+               return this;\r
+       }\r
+\r
+});\r
+/*\r
+Script: Fx.Morph.js\r
+       Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Fx.Morph = new Class({\r
+\r
+       Extends: Fx.CSS,\r
+\r
+       initialize: function(element, options){\r
+               this.element = this.subject = $(element);\r
+               this.parent(options);\r
+       },\r
+\r
+       set: function(now){\r
+               if (typeof now == 'string') now = this.search(now);\r
+               for (var p in now) this.render(this.element, p, now[p], this.options.unit);\r
+               return this;\r
+       },\r
+\r
+       compute: function(from, to, delta){\r
+               var now = {};\r
+               for (var p in from) now[p] = this.parent(from[p], to[p], delta);\r
+               return now;\r
+       },\r
+\r
+       start: function(properties){\r
+               if (!this.check(arguments.callee, properties)) return this;\r
+               if (typeof properties == 'string') properties = this.search(properties);\r
+               var from = {}, to = {};\r
+               for (var p in properties){\r
+                       var parsed = this.prepare(this.element, p, properties[p]);\r
+                       from[p] = parsed.from;\r
+                       to[p] = parsed.to;\r
+               }\r
+               return this.parent(from, to);\r
+       }\r
+\r
+});\r
+\r
+Element.Properties.morph = {\r
+\r
+       set: function(options){\r
+               var morph = this.retrieve('morph');\r
+               if (morph) morph.cancel();\r
+               return this.eliminate('morph').store('morph:options', $extend({link: 'cancel'}, options));\r
+       },\r
+\r
+       get: function(options){\r
+               if (options || !this.retrieve('morph')){\r
+                       if (options || !this.retrieve('morph:options')) this.set('morph', options);\r
+                       this.store('morph', new Fx.Morph(this, this.retrieve('morph:options')));\r
+               }\r
+               return this.retrieve('morph');\r
+       }\r
+\r
+};\r
+\r
+Element.implement({\r
+\r
+       morph: function(props){\r
+               this.get('morph').start(props);\r
+               return this;\r
+       }\r
+\r
+});/*\r
+Script: Fx.Transitions.js\r
+       Contains a set of advanced transitions to be used with any of the Fx Classes.\r
+\r
+License:\r
+       MIT-style license.\r
+\r
+Credits:\r
+       Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools.\r
+*/\r
+\r
+(function(){\r
+\r
+       var old = Fx.prototype.initialize;\r
+\r
+       Fx.prototype.initialize = function(options){\r
+               old.call(this, options);\r
+               var trans = this.options.transition;\r
+               if (typeof trans == 'string' && (trans = trans.split(':'))){\r
+                       var base = Fx.Transitions;\r
+                       base = base[trans[0]] || base[trans[0].capitalize()];\r
+                       if (trans[1]) base = base['ease' + trans[1].capitalize() + (trans[2] ? trans[2].capitalize() : '')];\r
+                       this.options.transition = base;\r
+               }\r
+       };\r
+\r
+})();\r
+\r
+Fx.Transition = function(transition, params){\r
+       params = $splat(params);\r
+       return $extend(transition, {\r
+               easeIn: function(pos){\r
+                       return transition(pos, params);\r
+               },\r
+               easeOut: function(pos){\r
+                       return 1 - transition(1 - pos, params);\r
+               },\r
+               easeInOut: function(pos){\r
+                       return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2;\r
+               }\r
+       });\r
+};\r
+\r
+Fx.Transitions = new Hash({\r
+\r
+       linear: $arguments(0)\r
+\r
+});\r
+\r
+Fx.Transitions.extend = function(transitions){\r
+       for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);\r
+};\r
+\r
+Fx.Transitions.extend({\r
+\r
+       Pow: function(p, x){\r
+               return Math.pow(p, x[0] || 6);\r
+       },\r
+\r
+       Expo: function(p){\r
+               return Math.pow(2, 8 * (p - 1));\r
+       },\r
+\r
+       Circ: function(p){\r
+               return 1 - Math.sin(Math.acos(p));\r
+       },\r
+\r
+       Sine: function(p){\r
+               return 1 - Math.sin((1 - p) * Math.PI / 2);\r
+       },\r
+\r
+       Back: function(p, x){\r
+               x = x[0] || 1.618;\r
+               return Math.pow(p, 2) * ((x + 1) * p - x);\r
+       },\r
+\r
+       Bounce: function(p){\r
+               var value;\r
+               for (var a = 0, b = 1; 1; a += b, b /= 2){\r
+                       if (p >= (7 - 4 * a) / 11){\r
+                               value = - Math.pow((11 - 6 * a - 11 * p) / 4, 2) + b * b;\r
+                               break;\r
+                       }\r
+               }\r
+               return value;\r
+       },\r
+\r
+       Elastic: function(p, x){\r
+               return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3);\r
+       }\r
+\r
+});\r
+\r
+['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){\r
+       Fx.Transitions[transition] = new Fx.Transition(function(p){\r
+               return Math.pow(p, [i + 2]);\r
+       });\r
+});\r
+/*\r
+Script: Request.js\r
+       Powerful all purpose Request Class. Uses XMLHTTPRequest.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Request = new Class({\r
+\r
+       Implements: [Chain, Events, Options],\r
+\r
+       options: {\r
+               /*onRequest: $empty,\r
+               onSuccess: $empty,\r
+               onFailure: $empty,\r
+               onException: $empty,*/\r
+               url: '',\r
+               data: '',\r
+               headers: {\r
+                       'X-Requested-With': 'XMLHttpRequest',\r
+                       'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'\r
+               },\r
+               async: true,\r
+               method: 'post',\r
+               link: 'ignore',\r
+               isSuccess: null,\r
+               emulation: true,\r
+               urlEncoded: true,\r
+               encoding: 'utf-8',\r
+               evalScripts: false,\r
+               evalResponse: false\r
+       },\r
+\r
+       initialize: function(options){\r
+               this.xhr = new Browser.Request();\r
+               this.setOptions(options);\r
+               this.options.isSuccess = this.options.isSuccess || this.isSuccess;\r
+               this.headers = new Hash(this.options.headers);\r
+       },\r
+\r
+       onStateChange: function(){\r
+               if (this.xhr.readyState != 4 || !this.running) return;\r
+               this.running = false;\r
+               this.status = 0;\r
+               $try(function(){\r
+                       this.status = this.xhr.status;\r
+               }.bind(this));\r
+               if (this.options.isSuccess.call(this, this.status)){\r
+                       this.response = {text: this.xhr.responseText, xml: this.xhr.responseXML};\r
+                       this.success(this.response.text, this.response.xml);\r
+               } else {\r
+                       this.response = {text: null, xml: null};\r
+                       this.failure();\r
+               }\r
+               this.xhr.onreadystatechange = $empty;\r
+       },\r
+\r
+       isSuccess: function(){\r
+               return ((this.status >= 200) && (this.status < 300));\r
+       },\r
+\r
+       processScripts: function(text){\r
+               if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return $exec(text);\r
+               return text.stripScripts(this.options.evalScripts);\r
+       },\r
+\r
+       success: function(text, xml){\r
+               this.onSuccess(this.processScripts(text), xml);\r
+       },\r
+       \r
+       onSuccess: function(){\r
+               this.fireEvent('onComplete', arguments).fireEvent('onSuccess', arguments).callChain();\r
+       },\r
+       \r
+       failure: function(){\r
+               this.onFailure();\r
+       },\r
+\r
+       onFailure: function(){\r
+               this.fireEvent('onComplete').fireEvent('onFailure', this.xhr);\r
+       },\r
+\r
+       setHeader: function(name, value){\r
+               this.headers.set(name, value);\r
+               return this;\r
+       },\r
+\r
+       getHeader: function(name){\r
+               return $try(function(){\r
+                       return this.xhr.getResponseHeader(name);\r
+               }.bind(this));\r
+       },\r
+\r
+       check: function(caller){\r
+               if (!this.running) return true;\r
+               switch (this.options.link){\r
+                       case 'cancel': this.cancel(); return true;\r
+                       case 'chain': this.chain(caller.bind(this, Array.slice(arguments, 1))); return false;\r
+               }\r
+               return false;\r
+       },\r
+\r
+       send: function(options){\r
+               if (!this.check(arguments.callee, options)) return this;\r
+               this.running = true;\r
+\r
+               var type = $type(options);\r
+               if (type == 'string' || type == 'element') options = {data: options};\r
+\r
+               var old = this.options;\r
+               options = $extend({data: old.data, url: old.url, method: old.method}, options);\r
+               var data = options.data, url = options.url, method = options.method;\r
+\r
+               switch ($type(data)){\r
+                       case 'element': data = $(data).toQueryString(); break;\r
+                       case 'object': case 'hash': data = Hash.toQueryString(data);\r
+               }\r
+\r
+               if (this.options.emulation && ['put', 'delete'].contains(method)){\r
+                       var _method = '_method=' + method;\r
+                       data = (data) ? _method + '&' + data : _method;\r
+                       method = 'post';\r
+               }\r
+\r
+               if (this.options.urlEncoded && method == 'post'){\r
+                       var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';\r
+                       this.headers.set('Content-type', 'application/x-www-form-urlencoded' + encoding);\r
+               }\r
+\r
+               if (data && method == 'get'){\r
+                       url = url + (url.contains('?') ? '&' : '?') + data;\r
+                       data = null;\r
+               }\r
+\r
+               this.xhr.open(method.toUpperCase(), url, this.options.async);\r
+\r
+               this.xhr.onreadystatechange = this.onStateChange.bind(this);\r
+\r
+               this.headers.each(function(value, key){\r
+                       if (!$try(function(){\r
+                               this.xhr.setRequestHeader(key, value);\r
+                               return true;\r
+                       }.bind(this))) this.fireEvent('onException', [key, value]);\r
+               }, this);\r
+\r
+               this.fireEvent('onRequest');\r
+               this.xhr.send(data);\r
+               if (!this.options.async) this.onStateChange();\r
+               return this;\r
+       },\r
+\r
+       cancel: function(){\r
+               if (!this.running) return this;\r
+               this.running = false;\r
+               this.xhr.abort();\r
+               this.xhr.onreadystatechange = $empty;\r
+               this.xhr = new Browser.Request();\r
+               this.fireEvent('onCancel');\r
+               return this;\r
+       }\r
+\r
+});\r
+\r
+(function(){\r
+\r
+var methods = {};\r
+['get', 'post', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){\r
+       methods[method] = function(){\r
+               var params = Array.link(arguments, {url: String.type, data: $defined});\r
+               return this.send($extend(params, {method: method.toLowerCase()}));\r
+       };\r
+});\r
+\r
+Request.implement(methods);\r
+\r
+})();\r
+\r
+Element.Properties.send = {\r
+       \r
+       set: function(options){\r
+               var send = this.retrieve('send');\r
+               if (send) send.cancel();\r
+               return this.eliminate('send').store('send:options', $extend({\r
+                       data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action')\r
+               }, options));\r
+       },\r
+\r
+       get: function(options){\r
+               if (options || !this.retrieve('send')){\r
+                       if (options || !this.retrieve('send:options')) this.set('send', options);\r
+                       this.store('send', new Request(this.retrieve('send:options')));\r
+               }\r
+               return this.retrieve('send');\r
+       }\r
+\r
+};\r
+\r
+Element.implement({\r
+\r
+       send: function(url){\r
+               var sender = this.get('send');\r
+               sender.send({data: this, url: url || sender.options.url});\r
+               return this;\r
+       }\r
+\r
+});\r
+/*\r
+Script: Request.HTML.js\r
+       Extends the basic Request Class with additional methods for interacting with HTML responses.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Request.HTML = new Class({\r
+\r
+       Extends: Request,\r
+\r
+       options: {\r
+               update: false,\r
+               evalScripts: true,\r
+               filter: false\r
+       },\r
+\r
+       processHTML: function(text){\r
+               var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i);\r
+               text = (match) ? match[1] : text;\r
+               \r
+               var container = new Element('div');\r
+               \r
+               return $try(function(){\r
+                       var root = '<root>' + text + '</root>', doc;\r
+                       if (Browser.Engine.trident){\r
+                               doc = new ActiveXObject('Microsoft.XMLDOM');\r
+                               doc.async = false;\r
+                               doc.loadXML(root);\r
+                       } else {\r
+                               doc = new DOMParser().parseFromString(root, 'text/xml');\r
+                       }\r
+                       root = doc.getElementsByTagName('root')[0];\r
+                       for (var i = 0, k = root.childNodes.length; i < k; i++){\r
+                               var child = Element.clone(root.childNodes[i], true, true);\r
+                               if (child) container.grab(child);\r
+                       }\r
+                       return container;\r
+               }) || container.set('html', text);\r
+       },\r
+\r
+       success: function(text){\r
+               var options = this.options, response = this.response;\r
+               \r
+               response.html = text.stripScripts(function(script){\r
+                       response.javascript = script;\r
+               });\r
+               \r
+               var temp = this.processHTML(response.html);\r
+               \r
+               response.tree = temp.childNodes;\r
+               response.elements = temp.getElements('*');\r
+               \r
+               if (options.filter) response.tree = response.elements.filter(options.filter);\r
+               if (options.update) $(options.update).empty().adopt(response.tree);\r
+               if (options.evalScripts) $exec(response.javascript);\r
+               \r
+               this.onSuccess(response.tree, response.elements, response.html, response.javascript);\r
+       }\r
+\r
+});\r
+\r
+Element.Properties.load = {\r
+       \r
+       set: function(options){\r
+               var load = this.retrieve('load');\r
+               if (load) send.cancel();\r
+               return this.eliminate('load').store('load:options', $extend({data: this, link: 'cancel', update: this, method: 'get'}, options));\r
+       },\r
+\r
+       get: function(options){\r
+               if (options || ! this.retrieve('load')){\r
+                       if (options || !this.retrieve('load:options')) this.set('load', options);\r
+                       this.store('load', new Request.HTML(this.retrieve('load:options')));\r
+               }\r
+               return this.retrieve('load');\r
+       }\r
+\r
+};\r
+\r
+Element.implement({\r
+       \r
+       load: function(){\r
+               this.get('load').send(Array.link(arguments, {data: Object.type, url: String.type}));\r
+               return this;\r
+       }\r
+\r
+});\r
+/*\r
+Script: Request.JSON.js\r
+       Extends the basic Request Class with additional methods for sending and receiving JSON data.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Request.JSON = new Class({\r
+\r
+       Extends: Request,\r
+\r
+       options: {\r
+               secure: true\r
+       },\r
+\r
+       initialize: function(options){\r
+               this.parent(options);\r
+               this.headers.extend({'Accept': 'application/json', 'X-Request': 'JSON'});\r
+       },\r
+\r
+       success: function(text){\r
+               this.response.json = JSON.decode(text, this.options.secure);\r
+               this.onSuccess(this.response.json, text);\r
+       }\r
+\r
+});/*\r
+Script: Fx.Slide.js\r
+       Effect to slide an element in and out of view.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Fx.Slide = new Class({\r
+\r
+       Extends: Fx,\r
+\r
+       options: {\r
+               mode: 'vertical'\r
+       },\r
+\r
+       initialize: function(element, options){\r
+               this.addEvent('onComplete', function(){\r
+                       this.open = (this.wrapper['offset' + this.layout.capitalize()] != 0);\r
+                       if (this.open && Browser.Engine.webkit419) this.element.dispose().inject(this.wrapper);\r
+               }, true);\r
+               this.element = this.subject = $(element);\r
+               this.parent(options);\r
+               var wrapper = this.element.retrieve('wrapper');\r
+               this.wrapper = wrapper || new Element('div', {\r
+                       styles: $extend(this.element.getStyles('margin', 'position'), {'overflow': 'hidden'})\r
+               }).wraps(this.element);\r
+               this.element.store('wrapper', this.wrapper).setStyle('margin', 0);\r
+               this.now = [];\r
+               this.open = true;\r
+       },\r
+\r
+       vertical: function(){\r
+               this.margin = 'margin-top';\r
+               this.layout = 'height';\r
+               this.offset = this.element.offsetHeight;\r
+       },\r
+\r
+       horizontal: function(){\r
+               this.margin = 'margin-left';\r
+               this.layout = 'width';\r
+               this.offset = this.element.offsetWidth;\r
+       },\r
+\r
+       set: function(now){\r
+               this.element.setStyle(this.margin, now[0]);\r
+               this.wrapper.setStyle(this.layout, now[1]);\r
+               return this;\r
+       },\r
+\r
+       compute: function(from, to, delta){\r
+               var now = [];\r
+               (2).times(function(i){\r
+                       now[i] = Fx.compute(from[i], to[i], delta);\r
+               });\r
+               return now;\r
+       },\r
+\r
+       start: function(how, mode){\r
+               if (!this.check(arguments.callee, how, mode)) return this;\r
+               this[mode || this.options.mode]();\r
+               var margin = this.element.getStyle(this.margin).toInt();\r
+               var layout = this.wrapper.getStyle(this.layout).toInt();\r
+               var caseIn = [[margin, layout], [0, this.offset]];\r
+               var caseOut = [[margin, layout], [-this.offset, 0]];\r
+               var start;\r
+               switch (how){\r
+                       case 'in': start = caseIn; break;\r
+                       case 'out': start = caseOut; break;\r
+                       case 'toggle': start = (this.wrapper['offset' + this.layout.capitalize()] == 0) ? caseIn : caseOut;\r
+               }\r
+               return this.parent(start[0], start[1]);\r
+       },\r
+\r
+       slideIn: function(mode){\r
+               return this.start('in', mode);\r
+       },\r
+\r
+       slideOut: function(mode){\r
+               return this.start('out', mode);\r
+       },\r
+\r
+       hide: function(mode){\r
+               this[mode || this.options.mode]();\r
+               this.open = false;\r
+               return this.set([-this.offset, 0]);\r
+       },\r
+\r
+       show: function(mode){\r
+               this[mode || this.options.mode]();\r
+               this.open = true;\r
+               return this.set([0, this.offset]);\r
+       },\r
+\r
+       toggle: function(mode){\r
+               return this.start('toggle', mode);\r
+       }\r
+\r
+});\r
+\r
+Element.Properties.slide = {\r
+\r
+       set: function(options){\r
+               var slide = this.retrieve('slide');\r
+               if (slide) slide.cancel();\r
+               return this.eliminate('slide').store('slide:options', $extend({link: 'cancel'}, options));\r
+       },\r
+       \r
+       get: function(options){\r
+               if (options || !this.retrieve('slide')){\r
+                       if (options || !this.retrieve('slide:options')) this.set('slide', options);\r
+                       this.store('slide', new Fx.Slide(this, this.retrieve('slide:options')));\r
+               }\r
+               return this.retrieve('slide');\r
+       }\r
+\r
+};\r
+\r
+Element.implement({\r
+\r
+       slide: function(how, mode){\r
+               how = how || 'toggle';\r
+               var slide = this.get('slide'), toggle;\r
+               switch (how){\r
+                       case 'hide': slide.hide(mode); break;\r
+                       case 'show': slide.show(mode); break;\r
+                       case 'toggle':\r
+                               var flag = this.retrieve('slide:flag', slide.open);\r
+                               slide[(flag) ? 'slideOut' : 'slideIn'](mode);\r
+                               this.store('slide:flag', !flag);\r
+                               toggle = true;\r
+                       break;\r
+                       default: slide.start(how, mode);\r
+               }\r
+               if (!toggle) this.eliminate('slide:flag');\r
+               return this;\r
+       }\r
+\r
+});\r
+/*\r
+Script: Fx.Scroll.js\r
+       Effect to smoothly scroll any element, including the window.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Fx.Scroll = new Class({\r
+\r
+       Extends: Fx,\r
+\r
+       options: {\r
+               offset: {'x': 0, 'y': 0},\r
+               wheelStops: true\r
+       },\r
+\r
+       initialize: function(element, options){\r
+               this.element = this.subject = $(element);\r
+               this.parent(options);\r
+               var cancel = this.cancel.bind(this, false);\r
+\r
+               if ($type(this.element) != 'element') this.element = $(this.element.getDocument().body);\r
+\r
+               var stopper = this.element;\r
+\r
+               if (this.options.wheelStops){\r
+                       this.addEvent('onStart', function(){\r
+                               stopper.addEvent('mousewheel', cancel);\r
+                       }, true);\r
+                       this.addEvent('onComplete', function(){\r
+                               stopper.removeEvent('mousewheel', cancel);\r
+                       }, true);\r
+               }\r
+       },\r
+\r
+       set: function(){\r
+               var now = Array.flatten(arguments);\r
+               this.element.scrollTo(now[0], now[1]);\r
+       },\r
+\r
+       compute: function(from, to, delta){\r
+               var now = [];\r
+               (2).times(function(i){\r
+                       now.push(Fx.compute(from[i], to[i], delta));\r
+               });\r
+               return now;\r
+       },\r
+\r
+       start: function(x, y){\r
+               if (!this.check(arguments.callee, x, y)) return this;\r
+               var offsetSize = this.element.getSize(), scrollSize = this.element.getScrollSize();\r
+               var scroll = this.element.getScroll(), values = {x: x, y: y};\r
+               for (var z in values){\r
+                       var max = scrollSize[z] - offsetSize[z];\r
+                       if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? values[z].limit(0, max) : max;\r
+                       else values[z] = scroll[z];\r
+                       values[z] += this.options.offset[z];\r
+               }\r
+               return this.parent([scroll.x, scroll.y], [values.x, values.y]);\r
+       },\r
+\r
+       toTop: function(){\r
+               return this.start(false, 0);\r
+       },\r
+\r
+       toLeft: function(){\r
+               return this.start(0, false);\r
+       },\r
+\r
+       toRight: function(){\r
+               return this.start('right', false);\r
+       },\r
+\r
+       toBottom: function(){\r
+               return this.start(false, 'bottom');\r
+       },\r
+\r
+       toElement: function(el){\r
+               var position = $(el).getPosition(this.element);\r
+               return this.start(position.x, position.y);\r
+       }\r
+\r
+});\r
+/*\r
+Script: Fx.Elements.js\r
+       Effect to change any number of CSS properties of any number of Elements.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Fx.Elements = new Class({\r
+\r
+       Extends: Fx.CSS,\r
+\r
+       initialize: function(elements, options){\r
+               this.elements = this.subject = $$(elements);\r
+               this.parent(options);\r
+       },\r
+\r
+       compute: function(from, to, delta){\r
+               var now = {};\r
+               for (var i in from){\r
+                       var iFrom = from[i], iTo = to[i], iNow = now[i] = {};\r
+                       for (var p in iFrom) iNow[p] = this.parent(iFrom[p], iTo[p], delta);\r
+               }\r
+               return now;\r
+       },\r
+\r
+       set: function(now){\r
+               for (var i in now){\r
+                       var iNow = now[i];\r
+                       for (var p in iNow) this.render(this.elements[i], p, iNow[p], this.options.unit);\r
+               }\r
+               return this;\r
+       },\r
+\r
+       start: function(obj){\r
+               if (!this.check(arguments.callee, obj)) return this;\r
+               var from = {}, to = {};\r
+               for (var i in obj){\r
+                       var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {};\r
+                       for (var p in iProps){\r
+                               var parsed = this.prepare(this.elements[i], p, iProps[p]);\r
+                               iFrom[p] = parsed.from;\r
+                               iTo[p] = parsed.to;\r
+                       }\r
+               }\r
+               return this.parent(from, to);\r
+       }\r
+\r
+});/*\r
+Script: Drag.js\r
+       The base Drag Class. Can be used to drag and resize Elements using mouse events.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Drag = new Class({\r
+\r
+       Implements: [Events, Options],\r
+\r
+       options: {/*\r
+               onBeforeStart: $empty,\r
+               onStart: $empty,\r
+               onDrag: $empty,\r
+               onCancel: $empty,\r
+               onComplete: $empty,*/\r
+               snap: 6,\r
+               unit: 'px',\r
+               grid: false,\r
+               style: true,\r
+               limit: false,\r
+               handle: false,\r
+               invert: false,\r
+               preventDefault: false,\r
+               modifiers: {x: 'left', y: 'top'}\r
+       },\r
+\r
+       initialize: function(){\r
+               var params = Array.link(arguments, {'options': Object.type, 'element': $defined});\r
+               this.element = $(params.element);\r
+               this.document = this.element.getDocument();\r
+               this.setOptions(params.options || {});\r
+               var htype = $type(this.options.handle);\r
+               this.handles = (htype == 'array' || htype == 'collection') ? $$(this.options.handle) : $(this.options.handle) || this.element;\r
+               this.mouse = {'now': {}, 'pos': {}};\r
+               this.value = {'start': {}, 'now': {}};\r
+               \r
+               this.selection = (Browser.Engine.trident) ? 'selectstart' : 'mousedown';\r
+               \r
+               this.bound = {\r
+                       start: this.start.bind(this),\r
+                       check: this.check.bind(this),\r
+                       drag: this.drag.bind(this),\r
+                       stop: this.stop.bind(this),\r
+                       cancel: this.cancel.bind(this),\r
+                       eventStop: $lambda(false)\r
+               };\r
+               this.attach();\r
+       },\r
+\r
+       attach: function(){\r
+               this.handles.addEvent('mousedown', this.bound.start);\r
+               return this;\r
+       },\r
+\r
+       detach: function(){\r
+               this.handles.removeEvent('mousedown', this.bound.start);\r
+               return this;\r
+       },\r
+\r
+       start: function(event){\r
+               if (this.options.preventDefault) event.preventDefault();\r
+               this.fireEvent('onBeforeStart', this.element);\r
+               this.mouse.start = event.page;\r
+               var limit = this.options.limit;\r
+               this.limit = {'x': [], 'y': []};\r
+               for (var z in this.options.modifiers){\r
+                       if (!this.options.modifiers[z]) continue;\r
+                       if (this.options.style) this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt();\r
+                       else this.value.now[z] = this.element[this.options.modifiers[z]];\r
+                       if (this.options.invert) this.value.now[z] *= -1;\r
+                       this.mouse.pos[z] = event.page[z] - this.value.now[z];\r
+                       if (limit && limit[z]){\r
+                               for (var i = 2; i--; i){\r
+                                       if ($chk(limit[z][i])) this.limit[z][i] = $lambda(limit[z][i])();\r
+                               }\r
+                       }\r
+               }\r
+               if ($type(this.options.grid) == 'number') this.options.grid = {'x': this.options.grid, 'y': this.options.grid};\r
+               this.document.addEvents({mousemove: this.bound.check, mouseup: this.bound.cancel});\r
+               this.document.addEvent(this.selection, this.bound.eventStop);\r
+       },\r
+\r
+       check: function(event){\r
+               if (this.options.preventDefault) event.preventDefault();\r
+               var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));\r
+               if (distance > this.options.snap){\r
+                       this.cancel();\r
+                       this.document.addEvents({\r
+                               mousemove: this.bound.drag,\r
+                               mouseup: this.bound.stop\r
+                       });\r
+                       this.fireEvent('onStart', this.element).fireEvent('onSnap', this.element);\r
+               }\r
+       },\r
+\r
+       drag: function(event){\r
+               if (this.options.preventDefault) event.preventDefault();\r
+               this.mouse.now = event.page;\r
+               for (var z in this.options.modifiers){\r
+                       if (!this.options.modifiers[z]) continue;\r
+                       this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];\r
+                       if (this.options.invert) this.value.now[z] *= -1;\r
+                       if (this.options.limit && this.limit[z]){\r
+                               if ($chk(this.limit[z][1]) && (this.value.now[z] > this.limit[z][1])){\r
+                                       this.value.now[z] = this.limit[z][1];\r
+                               } else if ($chk(this.limit[z][0]) && (this.value.now[z] < this.limit[z][0])){\r
+                                       this.value.now[z] = this.limit[z][0];\r
+                               }\r
+                       }\r
+                       if (this.options.grid[z]) this.value.now[z] -= (this.value.now[z] % this.options.grid[z]);\r
+                       if (this.options.style) this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit);\r
+                       else this.element[this.options.modifiers[z]] = this.value.now[z];\r
+               }\r
+               this.fireEvent('onDrag', this.element);\r
+       },\r
+\r
+       cancel: function(event){\r
+               this.document.removeEvent('mousemove', this.bound.check);\r
+               this.document.removeEvent('mouseup', this.bound.cancel);\r
+               if (event){\r
+                       this.document.removeEvent(this.selection, this.bound.eventStop);\r
+                       this.fireEvent('onCancel', this.element);\r
+               }\r
+       },\r
+\r
+       stop: function(event){\r
+               this.document.removeEvent(this.selection, this.bound.eventStop);\r
+               this.document.removeEvent('mousemove', this.bound.drag);\r
+               this.document.removeEvent('mouseup', this.bound.stop);\r
+               if (event) this.fireEvent('onComplete', this.element);\r
+       }\r
+\r
+});\r
+\r
+Element.implement({\r
+       \r
+       makeResizable: function(options){\r
+               return new Drag(this, $merge({modifiers: {'x': 'width', 'y': 'height'}}, options));\r
+       }\r
+\r
+});/*\r
+Script: Drag.Move.js\r
+       A Drag extension that provides support for the constraining of draggables to containers and droppables.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Drag.Move = new Class({\r
+\r
+       Extends: Drag,\r
+\r
+       options: {\r
+               droppables: [],\r
+               container: false\r
+       },\r
+\r
+       initialize: function(element, options){\r
+               this.parent(element, options);\r
+               this.droppables = $$(this.options.droppables);\r
+               this.container = $(this.options.container);\r
+               if (this.container && $type(this.container) != 'element') this.container = $(this.container.getDocument().body);\r
+               element = this.element;\r
+               \r
+               var current = element.getStyle('position');\r
+               var position = (current != 'static') ? current : 'absolute';\r
+               if (element.getStyle('left') == 'auto' || element.getStyle('top') == 'auto') element.position(element.getPosition(element.offsetParent));\r
+               \r
+               element.setStyle('position', position);\r
+               \r
+               this.addEvent('onStart', function(){\r
+                       this.checkDroppables();\r
+               }, true);\r
+       },\r
+\r
+       start: function(event){\r
+               if (this.container){\r
+                       var el = this.element, cont = this.container, ccoo = cont.getCoordinates(el.offsetParent), cps = {}, ems = {};\r
+\r
+                       ['top', 'right', 'bottom', 'left'].each(function(pad){\r
+                               cps[pad] = cont.getStyle('padding-' + pad).toInt();\r
+                               ems[pad] = el.getStyle('margin-' + pad).toInt();\r
+                       }, this);\r
+\r
+                       var width = el.offsetWidth + ems.left + ems.right, height = el.offsetHeight + ems.top + ems.bottom;\r
+                       var x = [ccoo.left + cps.left, ccoo.right - cps.right - width];\r
+                       var y = [ccoo.top + cps.top, ccoo.bottom - cps.bottom - height];\r
+\r
+                       this.options.limit = {x: x, y: y};\r
+               }\r
+               this.parent(event);\r
+       },\r
+\r
+       checkAgainst: function(el){\r
+               el = el.getCoordinates();\r
+               var now = this.mouse.now;\r
+               return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);\r
+       },\r
+\r
+       checkDroppables: function(){\r
+               var overed = this.droppables.filter(this.checkAgainst, this).getLast();\r
+               if (this.overed != overed){\r
+                       if (this.overed) this.fireEvent('onLeave', [this.element, this.overed]);\r
+                       if (overed){\r
+                               this.overed = overed;\r
+                               this.fireEvent('onEnter', [this.element, overed]);\r
+                       } else {\r
+                               this.overed = null;\r
+                       }\r
+               }\r
+       },\r
+\r
+       drag: function(event){\r
+               this.parent(event);\r
+               if (this.droppables.length) this.checkDroppables();\r
+       },\r
+\r
+       stop: function(event){\r
+               this.checkDroppables();\r
+               this.fireEvent('onDrop', [this.element, this.overed]);\r
+               this.overed = null;\r
+               return this.parent(event);\r
+       }\r
+\r
+});\r
+\r
+Element.implement({\r
+\r
+       makeDraggable: function(options){\r
+               return new Drag.Move(this, options);\r
+       }\r
+\r
+});\r
+/*\r
+Script: Color.js\r
+       Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Color = new Native({\r
+  \r
+       initialize: function(color, type){\r
+               if (arguments.length >= 3){\r
+                       type = "rgb"; color = Array.slice(arguments, 0, 3);\r
+               } else if (typeof color == 'string'){\r
+                       if (color.match(/rgb/)) color = color.rgbToHex().hexToRgb(true);\r
+                       else if (color.match(/hsb/)) color = color.hsbToRgb();\r
+                       else color = color.hexToRgb(true);\r
+               }\r
+               type = type || 'rgb';\r
+               switch (type){\r
+                       case 'hsb':\r
+                               var old = color;\r
+                               color = color.hsbToRgb();\r
+                               color.hsb = old;\r
+                       break;\r
+                       case 'hex': color = color.hexToRgb(true); break;\r
+               }\r
+               color.rgb = color.slice(0, 3);\r
+               color.hsb = color.hsb || color.rgbToHsb();\r
+               color.hex = color.rgbToHex();\r
+               return $extend(color, this);\r
+       }\r
+\r
+});\r
+\r
+Color.implement({\r
+\r
+       mix: function(){\r
+               var colors = Array.slice(arguments);\r
+               var alpha = ($type(colors.getLast()) == 'number') ? colors.pop() : 50;\r
+               var rgb = this.slice();\r
+               colors.each(function(color){\r
+                       color = new Color(color);\r
+                       for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha));\r
+               });\r
+               return new Color(rgb, 'rgb');\r
+       },\r
+\r
+       invert: function(){\r
+               return new Color(this.map(function(value){\r
+                       return 255 - value;\r
+               }));\r
+       },\r
+\r
+       setHue: function(value){\r
+               return new Color([value, this.hsb[1], this.hsb[2]], 'hsb');\r
+       },\r
+\r
+       setSaturation: function(percent){\r
+               return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb');\r
+       },\r
+\r
+       setBrightness: function(percent){\r
+               return new Color([this.hsb[0], this.hsb[1], percent], 'hsb');\r
+       }\r
+\r
+});\r
+\r
+function $RGB(r, g, b){\r
+       return new Color([r, g, b], 'rgb');\r
+};\r
+\r
+function $HSB(h, s, b){\r
+       return new Color([h, s, b], 'hsb');\r
+};\r
+\r
+function $HEX(hex){\r
+       return new Color(hex, 'hex');\r
+};\r
+\r
+Array.implement({\r
+\r
+       rgbToHsb: function(){\r
+               var red = this[0], green = this[1], blue = this[2];\r
+               var hue, saturation, brightness;\r
+               var max = Math.max(red, green, blue), min = Math.min(red, green, blue);\r
+               var delta = max - min;\r
+               brightness = max / 255;\r
+               saturation = (max != 0) ? delta / max : 0;\r
+               if (saturation == 0){\r
+                       hue = 0;\r
+               } else {\r
+                       var rr = (max - red) / delta;\r
+                       var gr = (max - green) / delta;\r
+                       var br = (max - blue) / delta;\r
+                       if (red == max) hue = br - gr;\r
+                       else if (green == max) hue = 2 + rr - br;\r
+                       else hue = 4 + gr - rr;\r
+                       hue /= 6;\r
+                       if (hue < 0) hue++;\r
+               }\r
+               return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)];\r
+       },\r
+\r
+       hsbToRgb: function(){\r
+               var br = Math.round(this[2] / 100 * 255);\r
+               if (this[1] == 0){\r
+                       return [br, br, br];\r
+               } else {\r
+                       var hue = this[0] % 360;\r
+                       var f = hue % 60;\r
+                       var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255);\r
+                       var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255);\r
+                       var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255);\r
+                       switch (Math.floor(hue / 60)){\r
+                               case 0: return [br, t, p];\r
+                               case 1: return [q, br, p];\r
+                               case 2: return [p, br, t];\r
+                               case 3: return [p, q, br];\r
+                               case 4: return [t, p, br];\r
+                               case 5: return [br, p, q];\r
+                       }\r
+               }\r
+               return false;\r
+       }\r
+\r
+});\r
+\r
+String.implement({\r
+\r
+       rgbToHsb: function(){\r
+               var rgb = this.match(/\d{1,3}/g);\r
+               return (rgb) ? hsb.rgbToHsb() : null;\r
+       },\r
+       \r
+       hsbToRgb: function(){\r
+               var hsb = this.match(/\d{1,3}/g);\r
+               return (hsb) ? hsb.hsbToRgb() : null;\r
+       }\r
+\r
+});\r
+/*\r
+Script: Group.js\r
+       Class for monitoring collections of events\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Group = new Class({\r
+\r
+       initialize: function(){\r
+               this.instances = Array.flatten(arguments);\r
+               this.events = {};\r
+               this.checker = {};\r
+       },\r
+\r
+       addEvent: function(type, fn){\r
+               this.checker[type] = this.checker[type] || {};\r
+               this.events[type] = this.events[type] || [];\r
+               if (this.events[type].contains(fn)) return false;\r
+               else this.events[type].push(fn);\r
+               this.instances.each(function(instance, i){\r
+                       instance.addEvent(type, this.check.bind(this, [type, instance, i]));\r
+               }, this);\r
+               return this;\r
+       },\r
+\r
+       check: function(type, instance, i){\r
+               this.checker[type][i] = true;\r
+               var every = this.instances.every(function(current, j){\r
+                       return this.checker[type][j] || false;\r
+               }, this);\r
+               if (!every) return;\r
+               this.checker[type] = {};\r
+               this.events[type].each(function(event){\r
+                       event.call(this, this.instances, instance);\r
+               }, this);\r
+       }\r
+\r
+});\r
+/*\r
+Script: Hash.Cookie.js\r
+       Class for creating, reading, and deleting Cookies in JSON format.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+Hash.Cookie = new Class({\r
+\r
+       Extends: Cookie,\r
+\r
+       options: {\r
+               autoSave: true\r
+       },\r
+\r
+       initialize: function(name, options){\r
+               this.parent(name, options);\r
+               this.load();\r
+       },\r
+\r
+       save: function(){\r
+               var value = JSON.encode(this.hash);\r
+               if (!value || value.length > 4096) return false; //cookie would be truncated!\r
+               if (value == '{}') this.dispose();\r
+               else this.write(value);\r
+               return true;\r
+       },\r
+\r
+       load: function(){\r
+               this.hash = new Hash(JSON.decode(this.read(), true));\r
+               return this;\r
+       }\r
+\r
+});\r
+\r
+Hash.Cookie.implement((function(){\r
+       \r
+       var methods = {};\r
+       \r
+       Hash.each(Hash.prototype, function(method, name){\r
+               methods[name] = function(){\r
+                       var value = method.apply(this.hash, arguments);\r
+                       if (this.options.autoSave) this.save();\r
+                       return value;\r
+               };\r
+       });\r
+       \r
+       return methods;\r
+       \r
+})());/*\r
+Script: Sortables.js\r
+       Class for creating a drag and drop sorting interface for lists of items.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Sortables = new Class({\r
+\r
+       Implements: [Events, Options],\r
+\r
+       options: {/*\r
+               onSort: $empty,\r
+               onStart: $empty,\r
+               onComplete: $empty,*/\r
+               snap: 4,\r
+               opacity: 1,\r
+               clone: false,\r
+               revert: false,\r
+               handle: false,\r
+               constrain: false\r
+       },\r
+\r
+       initialize: function(lists, options){\r
+               this.setOptions(options);\r
+               this.elements = [];\r
+               this.lists = [];\r
+               this.idle = true;\r
+               \r
+               this.addLists($$($(lists) || lists));\r
+               if (!this.options.clone) this.options.revert = false;\r
+               if (this.options.revert) this.effect = new Fx.Morph(null, $merge({duration: 250, link: 'cancel'}, this.options.revert));\r
+       },\r
+\r
+       attach: function(){\r
+               this.addLists(this.lists);\r
+               return this;\r
+       },\r
+\r
+       detach: function(){\r
+               this.lists = this.removeLists(this.lists);\r
+               return this;\r
+       },\r
+\r
+       addItems: function(){\r
+               Array.flatten(arguments).each(function(element){\r
+                       this.elements.push(element);\r
+                       var start = element.retrieve('sortables:start', this.start.bindWithEvent(this, element));\r
+                       (this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent('mousedown', start);\r
+               }, this);\r
+               return this;\r
+       },\r
+\r
+       addLists: function(){\r
+               Array.flatten(arguments).each(function(list){\r
+                       this.lists.push(list);\r
+                       this.addItems(list.getChildren());\r
+               }, this);\r
+               return this;\r
+       },\r
+\r
+       removeItems: function(){\r
+               var elements = [];\r
+               Array.flatten(arguments).each(function(element){\r
+                       elements.push(element);\r
+                       this.elements.erase(element);\r
+                       var start = element.retrieve('sortables:start');\r
+                       (this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start);\r
+               }, this);\r
+               return $$(elements);\r
+       },\r
+\r
+       removeLists: function(){\r
+               var lists = [];\r
+               Array.flatten(arguments).each(function(list){\r
+                       lists.push(list);\r
+                       this.lists.erase(list);\r
+                       this.removeItems(list.getChildren());\r
+               }, this);\r
+               return $$(lists);\r
+       },\r
+\r
+       getClone: function(event, element){\r
+               if (!this.options.clone) return new Element('div').inject(document.body);\r
+               if ($type(this.options.clone) == 'function') return this.options.clone.call(this, event, element, this.list);\r
+               return element.clone(true).setStyles({\r
+                       'margin': '0px',\r
+                       'position': 'absolute',\r
+                       'visibility': 'hidden',\r
+                       'width': element.getStyle('width')\r
+               }).inject(this.list).position(element.getPosition(element.offsetParent));\r
+       },\r
+\r
+       getDroppables: function(){\r
+               var droppables = this.list.getChildren();\r
+               if (!this.options.constrain) droppables = this.lists.concat(droppables).erase(this.list);\r
+               return droppables.erase(this.clone).erase(this.element);\r
+       },\r
+\r
+       insert: function(dragging, element){\r
+               var where = 'inside';\r
+               if (this.lists.contains(element)){\r
+                       this.list = element;\r
+                       this.drag.droppables = this.getDroppables();\r
+               } else {\r
+                       where = this.element.getAllPrevious().contains(element) ? 'before' : 'after';\r
+               }\r
+               this.element.inject(element, where);\r
+               this.fireEvent('onSort', [this.element, this.clone]);\r
+       },\r
+\r
+       start: function(event, element){\r
+               if (!this.idle) return;\r
+               this.idle = false;\r
+               this.element = element;\r
+               this.opacity = element.get('opacity');\r
+               this.list = element.getParent();\r
+               this.clone = this.getClone(event, element);\r
+               \r
+               this.drag = new Drag.Move(this.clone, {\r
+                       snap: this.options.snap,\r
+                       container: this.options.constrain && this.element.getParent(),\r
+                       droppables: this.getDroppables(),\r
+                       onSnap: function(){\r
+                               event.stop();\r
+                               this.clone.setStyle('visibility', 'visible');\r
+                               this.element.set('opacity', this.options.opacity || 0);\r
+                               this.fireEvent('onStart', [this.element, this.clone]);\r
+                       }.bind(this),\r
+                       onEnter: this.insert.bind(this),\r
+                       onCancel: this.reset.bind(this),\r
+                       onComplete: this.end.bind(this)\r
+               });\r
+               \r
+               this.clone.inject(this.element, 'before');\r
+               this.drag.start(event);\r
+       },\r
+\r
+       end: function(){\r
+               this.drag.detach();\r
+               this.element.set('opacity', this.opacity);\r
+               if (this.effect){\r
+                       var dim = this.element.getStyles('width', 'height');\r
+                       var pos = this.clone.computePosition(this.element.getPosition(this.clone.offsetParent));\r
+                       this.effect.element = this.clone;\r
+                       this.effect.start({\r
+                               top: pos.top,\r
+                               left: pos.left,\r
+                               width: dim.width,\r
+                               height: dim.height,\r
+                               opacity: 0.25\r
+                       }).chain(this.reset.bind(this));\r
+               } else {\r
+                       this.reset();\r
+               }\r
+       },\r
+\r
+       reset: function(){\r
+               this.idle = true;\r
+               this.clone.destroy();\r
+               this.fireEvent('onComplete', this.element);\r
+       },\r
+\r
+       serialize: function(){\r
+               var params = Array.link(arguments, {modifier: Function.type, index: $defined});\r
+               var serial = this.lists.map(function(list){\r
+                       return list.getChildren().map(params.modifier || function(element){\r
+                               return element.get('id');\r
+                       }, this);\r
+               }, this);\r
+               \r
+               var index = params.index;\r
+               if (this.lists.length == 1) index = 0;\r
+               return $chk(index) && index >= 0 && index < this.lists.length ? serial[index] : serial;\r
+       }\r
+\r
+});/*\r
+Script: Tips.js\r
+       Class for creating nice tips that follow the mouse cursor when hovering an element.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Tips = new Class({\r
+\r
+       Implements: [Events, Options],\r
+\r
+       options: {\r
+               onShow: function(tip){\r
+                       tip.setStyle('visibility', 'visible');\r
+               },\r
+               onHide: function(tip){\r
+                       tip.setStyle('visibility', 'hidden');\r
+               },\r
+               showDelay: 100,\r
+               hideDelay: 100,\r
+               className: null,\r
+               offsets: {x: 16, y: 16},\r
+               fixed: false\r
+       },\r
+\r
+       initialize: function(){\r
+               var params = Array.link(arguments, {options: Object.type, elements: $defined});\r
+               this.setOptions(params.options || null);\r
+               \r
+               this.tip = new Element('div').inject(document.body);\r
+               \r
+               if (this.options.className) this.tip.addClass(this.options.className);\r
+               \r
+               var top = new Element('div', {'class': 'tip-top'}).inject(this.tip);\r
+               this.container = new Element('div', {'class': 'tip'}).inject(this.tip);\r
+               var bottom = new Element('div', {'class': 'tip-bottom'}).inject(this.tip);\r
+\r
+               this.tip.setStyles({position: 'absolute', top: 0, left: 0, visibility: 'hidden'});\r
+               \r
+               if (params.elements) this.attach(params.elements);\r
+       },\r
+       \r
+       attach: function(elements){\r
+               $$(elements).each(function(element){\r
+                       var title = element.retrieve('tip:title', element.get('title'));\r
+                       var text = element.retrieve('tip:text', element.get('rel') || element.get('href'));\r
+                       var enter = element.retrieve('tip:enter', this.elementEnter.bindWithEvent(this, element));\r
+                       var leave = element.retrieve('tip:leave', this.elementLeave.bindWithEvent(this, element));\r
+                       element.addEvents({mouseenter: enter, mouseleave: leave});\r
+                       if (!this.options.fixed){\r
+                               var move = element.retrieve('tip:move', this.elementMove.bindWithEvent(this, element));\r
+                               element.addEvent('mousemove', move);\r
+                       }\r
+                       element.store('tip:native', element.get('title'));\r
+                       element.erase('title');\r
+               }, this);\r
+               return this;\r
+       },\r
+       \r
+       detach: function(elements){\r
+               $$(elements).each(function(element){\r
+                       element.removeEvent('mouseenter', element.retrieve('tip:enter') || $empty);\r
+                       element.removeEvent('mouseleave', element.retrieve('tip:leave') || $empty);\r
+                       element.removeEvent('mousemove', element.retrieve('tip:move') || $empty);\r
+                       element.eliminate('tip:enter').eliminate('tip:leave').eliminate('tip:move');\r
+                       var original = element.retrieve('tip:native');\r
+                       if (original) element.set('title', original);\r
+               });\r
+               return this;\r
+       },\r
+       \r
+       elementEnter: function(event, element){\r
+               \r
+               $A(this.container.childNodes).each(Element.dispose);\r
+               \r
+               var title = element.retrieve('tip:title');\r
+               \r
+               if (title){\r
+                       this.titleElement = new Element('div', {'class': 'tip-title'}).inject(this.container);\r
+                       this.fill(this.titleElement, title);\r
+               }\r
+               \r
+               var text = element.retrieve('tip:text');\r
+               if (text){\r
+                       this.textElement = new Element('div', {'class': 'tip-text'}).inject(this.container);\r
+                       this.fill(this.textElement, text);\r
+               }\r
+               \r
+               this.timer = $clear(this.timer);\r
+               this.timer = this.show.delay(this.options.showDelay, this);\r
+\r
+               this.position((!this.options.fixed) ? event : {page: element.getPosition()});\r
+       },\r
+       \r
+       elementLeave: function(event){\r
+               $clear(this.timer);\r
+               this.timer = this.hide.delay(this.options.hideDelay, this);\r
+       },\r
+       \r
+       elementMove: function(event){\r
+               this.position(event);\r
+       },\r
+       \r
+       position: function(event){\r
+               var size = window.getSize(), scroll = window.getScroll();\r
+               var tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight};\r
+               var props = {x: 'left', y: 'top'};\r
+               for (var z in props){\r
+                       var pos = event.page[z] + this.options.offsets[z];\r
+                       if ((pos + tip[z] - scroll[z]) > size[z]) pos = event.page[z] - this.options.offsets[z] - tip[z];\r
+                       this.tip.setStyle(props[z], pos);\r
+               }\r
+       },\r
+       \r
+       fill: function(element, contents){\r
+               (typeof contents == 'string') ? element.set('html', contents) : element.adopt(contents);\r
+       },\r
+\r
+       show: function(){\r
+               this.fireEvent('onShow', this.tip);\r
+       },\r
+\r
+       hide: function(){\r
+               this.fireEvent('onHide', this.tip);\r
+       }\r
+\r
+});/*\r
+Script: SmoothScroll.js\r
+       Class for creating a smooth scrolling effect to all internal links on the page.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var SmoothScroll = new Class({\r
+\r
+       Extends: Fx.Scroll,\r
+\r
+       initialize: function(options, context){\r
+               context = context || document;\r
+               var doc = context.getDocument(), win = context.getWindow();\r
+               this.parent(doc, options);\r
+               this.links = (this.options.links) ? $$(this.options.links) : $$(doc.links);\r
+               var location = win.location.href.match(/^[^#]*/)[0] + '#';\r
+               this.links.each(function(link){\r
+                       if (link.href.indexOf(location) != 0) return;\r
+                       var anchor = link.href.substr(location.length);\r
+                       if (anchor && $(anchor)) this.useLink(link, anchor);\r
+               }, this);\r
+               if (!Browser.Engine.webkit419) this.addEvent('onComplete', function(){\r
+                       win.location.hash = this.anchor;\r
+               }, true);\r
+       },\r
+\r
+       useLink: function(link, anchor){\r
+               link.addEvent('click', function(event){\r
+                       this.anchor = anchor;\r
+                       this.toElement(anchor);\r
+                       event.stop();\r
+               }.bind(this));\r
+       }\r
+\r
+});/*\r
+Script: Slider.js\r
+       Class for creating horizontal and vertical slider controls.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Slider = new Class({\r
+\r
+       Implements: [Events, Options],\r
+\r
+       options: {/*\r
+               onChange: $empty,\r
+               onComplete: $empty,*/\r
+               onTick: function(position){\r
+                       if(this.options.snap) position = this.toPosition(this.step);\r
+                       this.knob.setStyle(this.property, position);\r
+               },\r
+               snap: false,\r
+               offset: 0,\r
+               range: false,\r
+               wheel: false,\r
+               steps: 100,\r
+               mode: 'horizontal'\r
+       },\r
+\r
+       initialize: function(element, knob, options){\r
+               this.setOptions(options);\r
+               this.element = $(element);\r
+               this.knob = $(knob);\r
+               this.previousChange = this.previousEnd = this.step = -1;\r
+               this.element.addEvent('mousedown', this.clickedElement.bind(this));\r
+               if (this.options.wheel) this.element.addEvent('mousewheel', this.scrolledElement.bindWithEvent(this));\r
+               var offset, limit = {}, modifiers = {'x': false, 'y': false};\r
+               switch (this.options.mode){\r
+                       case 'vertical':\r
+                               this.axis = 'y';\r
+                               this.property = 'top';\r
+                               offset = 'offsetHeight';\r
+                               break;\r
+                       case 'horizontal':\r
+                               this.axis = 'x';\r
+                               this.property = 'left';\r
+                               offset = 'offsetWidth';\r
+               }\r
+               this.half = this.knob[offset] / 2;\r
+               this.full = this.element[offset] - this.knob[offset] + (this.options.offset * 2);\r
+               this.min = $chk(this.options.range[0]) ? this.options.range[0] : 0;\r
+               this.max = $chk(this.options.range[1]) ? this.options.range[1] : this.options.steps;\r
+               this.range = this.max - this.min;\r
+               this.steps = this.options.steps || this.full;\r
+               this.stepSize = Math.abs(this.range) / this.steps;\r
+               this.stepWidth = this.stepSize * this.full / Math.abs(this.range) ;\r
+               \r
+               this.knob.setStyle('position', 'relative').setStyle(this.property, - this.options.offset);\r
+               modifiers[this.axis] = this.property;\r
+               limit[this.axis] = [- this.options.offset, this.full - this.options.offset];\r
+               this.drag = new Drag(this.knob, {\r
+                       snap: 0,\r
+                       limit: limit,\r
+                       modifiers: modifiers,\r
+                       onDrag: this.draggedKnob.bind(this),\r
+                       onStart: this.draggedKnob.bind(this),\r
+                       onComplete: function(){\r
+                               this.draggedKnob();\r
+                               this.end();\r
+                       }.bind(this)\r
+               });\r
+               if (this.options.snap) {\r
+                       this.drag.options.grid = Math.ceil(this.stepWidth);\r
+                       this.drag.options.limit[this.axis][1] = this.full;\r
+               }\r
+       },\r
+\r
+       set: function(step){\r
+               if (!((this.range > 0) ^ (step < this.min))) step = this.min;\r
+               if (!((this.range > 0) ^ (step > this.max))) step = this.max;\r
+               \r
+               this.step = Math.round(step);\r
+               this.checkStep();\r
+               this.end();\r
+               this.fireEvent('onTick', this.toPosition(this.step));\r
+               return this;\r
+       },\r
+\r
+       clickedElement: function(event){\r
+               var dir = this.range < 0 ? -1 : 1;\r
+               var position = event.page[this.axis] - this.element.getPosition()[this.axis] - this.half;\r
+               position = position.limit(-this.options.offset, this.full -this.options.offset);\r
+               \r
+               this.step = Math.round(this.min + dir * this.toStep(position));\r
+               this.checkStep();\r
+               this.end();\r
+               this.fireEvent('onTick', position);\r
+       },\r
+       \r
+       scrolledElement: function(event){\r
+               var mode = (this.options.mode == 'horizontal') ? (event.wheel < 0) : (event.wheel > 0);\r
+               this.set(mode ? this.step - this.stepSize : this.step + this.stepSize);\r
+               event.stop();\r
+       },\r
+\r
+       draggedKnob: function(){\r
+               var dir = this.range < 0 ? -1 : 1;\r
+               var position = this.drag.value.now[this.axis];\r
+               position = position.limit(-this.options.offset, this.full -this.options.offset);\r
+               this.step = Math.round(this.min + dir * this.toStep(position));\r
+               this.checkStep();\r
+       },\r
+\r
+       checkStep: function(){\r
+               if (this.previousChange != this.step){\r
+                       this.previousChange = this.step;\r
+                       this.fireEvent('onChange', this.step);\r
+               }\r
+       },\r
+\r
+       end: function(){\r
+               if (this.previousEnd !== this.step){\r
+                       this.previousEnd = this.step;\r
+                       this.fireEvent('onComplete', this.step + '');\r
+               }\r
+       },\r
+\r
+       toStep: function(position){\r
+               var step = (position + this.options.offset) * this.stepSize / this.full * this.steps;\r
+               return this.options.steps ? Math.round(step -= step % this.stepSize) : step;\r
+       },\r
+\r
+       toPosition: function(step){\r
+               return (this.full * Math.abs(this.min - step)) / (this.steps * this.stepSize) - this.options.offset;\r
+       }\r
+\r
+});/*\r
+Script: Scroller.js\r
+       Class which scrolls the contents of any Element (including the window) when the mouse reaches the Element's boundaries.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Scroller = new Class({\r
+\r
+       Implements: [Events, Options],\r
+\r
+       options: {\r
+               area: 20,\r
+               velocity: 1,\r
+               onChange: function(x, y){\r
+                       this.element.scrollTo(x, y);\r
+               }\r
+       },\r
+\r
+       initialize: function(element, options){\r
+               this.setOptions(options);\r
+               this.element = $(element);\r
+               this.listener = ($type(this.element) != 'element') ? $(this.element.getDocument().body) : this.element;\r
+               this.timer = null;\r
+       },\r
+\r
+       start: function(){\r
+               this.coord = this.getCoords.bind(this);\r
+               this.listener.addEvent('mousemove', this.coord);\r
+       },\r
+\r
+       stop: function(){\r
+               this.listener.removeEvent('mousemove', this.coord);\r
+               this.timer = $clear(this.timer);\r
+       },\r
+\r
+       getCoords: function(event){\r
+               this.page = (this.listener.get('tag') == 'body') ? event.client : event.page;\r
+               if (!this.timer) this.timer = this.scroll.periodical(50, this);\r
+       },\r
+\r
+       scroll: function(){\r
+               var size = this.element.getSize(), scroll = this.element.getScroll(), pos = this.element.getPosition(), change = {'x': 0, 'y': 0};\r
+               for (var z in this.page){\r
+                       if (this.page[z] < (this.options.area + pos[z]) && scroll[z] != 0)\r
+                               change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity;\r
+                       else if (this.page[z] + this.options.area > (size[z] + pos[z]) && size[z] + size[z] != scroll[z])\r
+                               change[z] = (this.page[z] - size[z] + this.options.area - pos[z]) * this.options.velocity;\r
+               }\r
+               if (change.y || change.x) this.fireEvent('onChange', [scroll.x + change.x, scroll.y + change.y]);\r
+       }\r
+\r
+});/*\r
+Script: Assets.js\r
+       Provides methods to dynamically load JavaScript, CSS, and Image files into the document.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Asset = new Hash({\r
+\r
+       javascript: function(source, properties){\r
+               properties = $extend({\r
+                       onload: $empty,\r
+                       document: document,\r
+                       check: $lambda(true)\r
+               }, properties);\r
+               \r
+               var script = new Element('script', {'src': source, 'type': 'text/javascript'});\r
+               \r
+               var load = properties.onload.bind(script), check = properties.check, doc = properties.document;\r
+               delete properties.onload; delete properties.check; delete properties.document;\r
+               \r
+               script.addEvents({\r
+                       load: load,\r
+                       readystatechange: function(){\r
+                               if (['loaded', 'complete'].contains(this.readyState)) load();\r
+                       }\r
+               }).setProperties(properties);\r
+               \r
+               \r
+               if (Browser.Engine.webkit419) var checker = (function(){\r
+                       if (!$try(check)) return;\r
+                       $clear(checker);\r
+                       load();\r
+               }).periodical(50);\r
+               \r
+               return script.inject(doc.head);\r
+       },\r
+\r
+       css: function(source, properties){\r
+               return new Element('link', $merge({\r
+                       'rel': 'stylesheet', 'media': 'screen', 'type': 'text/css', 'href': source\r
+               }, properties)).inject(document.head);\r
+       },\r
+\r
+       image: function(source, properties){\r
+               properties = $merge({\r
+                       'onload': $empty,\r
+                       'onabort': $empty,\r
+                       'onerror': $empty\r
+               }, properties);\r
+               var image = new Image();\r
+               var element = $(image) || new Element('img');\r
+               ['load', 'abort', 'error'].each(function(name){\r
+                       var type = 'on' + name;\r
+                       var event = properties[type];\r
+                       delete properties[type];\r
+                       image[type] = function(){\r
+                               if (!image) return;\r
+                               if (!element.parentNode){\r
+                                       element.width = image.width;\r
+                                       element.height = image.height;\r
+                               }\r
+                               image = image.onload = image.onabort = image.onerror = null;\r
+                               event.delay(1, element, element);\r
+                               element.fireEvent(name, element, 1);\r
+                       };\r
+               });\r
+               image.src = element.src = source;\r
+               if (image && image.complete) image.onload.delay(1);\r
+               return element.setProperties(properties);\r
+       },\r
+\r
+       images: function(sources, options){\r
+               options = $merge({\r
+                       onComplete: $empty,\r
+                       onProgress: $empty\r
+               }, options);\r
+               if (!sources.push) sources = [sources];\r
+               var images = [];\r
+               var counter = 0;\r
+               sources.each(function(source){\r
+                       var img = new Asset.image(source, {\r
+                               'onload': function(){\r
+                                       options.onProgress.call(this, counter, sources.indexOf(source));\r
+                                       counter++;\r
+                                       if (counter == sources.length) options.onComplete();\r
+                               }\r
+                       });\r
+                       images.push(img);\r
+               });\r
+               return new Elements(images);\r
+       }\r
+\r
+});/*\r
+Script: Accordion.js\r
+       An Fx.Elements extension which allows you to easily create accordion type controls.\r
+\r
+License:\r
+       MIT-style license.\r
+*/\r
+\r
+var Accordion = new Class({\r
+\r
+       Extends: Fx.Elements,\r
+\r
+       options: {/*\r
+               onActive: $empty,\r
+               onBackground: $empty,*/\r
+               display: 0,\r
+               show: false,\r
+               height: true,\r
+               width: false,\r
+               opacity: true,\r
+               fixedHeight: false,\r
+               fixedWidth: false,\r
+               wait: false,\r
+               alwaysHide: false\r
+       },\r
+\r
+       initialize: function(){\r
+               var params = Array.link(arguments, {'container': Element.type, 'options': Object.type, 'togglers': $defined, 'elements': $defined});\r
+               this.parent(params.elements, params.options);\r
+               this.togglers = $$(params.togglers);\r
+               this.container = $(params.container);\r
+               this.previous = -1;\r
+               if (this.options.alwaysHide) this.options.wait = true;\r
+               if ($chk(this.options.show)){\r
+                       this.options.display = false;\r
+                       this.previous = this.options.show;\r
+               }\r
+               if (this.options.start){\r
+                       this.options.display = false;\r
+                       this.options.show = false;\r
+               }\r
+               this.effects = {};\r
+               if (this.options.opacity) this.effects.opacity = 'fullOpacity';\r
+               if (this.options.width) this.effects.width = this.options.fixedWidth ? 'fullWidth' : 'offsetWidth';\r
+               if (this.options.height) this.effects.height = this.options.fixedHeight ? 'fullHeight' : 'scrollHeight';\r
+               for (var i = 0, l = this.togglers.length; i < l; i++) this.addSection(this.togglers[i], this.elements[i]);\r
+               this.elements.each(function(el, i){\r
+                       if (this.options.show === i){\r
+                               this.fireEvent('onActive', [this.togglers[i], el]);\r
+                       } else {\r
+                               for (var fx in this.effects) el.setStyle(fx, 0);\r
+                       }\r
+               }, this);\r
+               if ($chk(this.options.display)) this.display(this.options.display);\r
+       },\r
+\r
+       addSection: function(toggler, element, pos){\r
+               toggler = $(toggler);\r
+               element = $(element);\r
+               var test = this.togglers.contains(toggler);\r
+               var len = this.togglers.length;\r
+               this.togglers.include(toggler);\r
+               this.elements.include(element);\r
+               if (len && (!test || pos)){\r
+                       pos = $pick(pos, len - 1);\r
+                       toggler.inject(this.togglers[pos], 'before');\r
+                       element.inject(toggler, 'after');\r
+               } else if (this.container && !test){\r
+                       toggler.inject(this.container);\r
+                       element.inject(this.container);\r
+               }\r
+               var idx = this.togglers.indexOf(toggler);\r
+               toggler.addEvent('click', this.display.bind(this, idx));\r
+               if (this.options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'});\r
+               if (this.options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'});\r
+               element.fullOpacity = 1;\r
+               if (this.options.fixedWidth) element.fullWidth = this.options.fixedWidth;\r
+               if (this.options.fixedHeight) element.fullHeight = this.options.fixedHeight;\r
+               element.setStyle('overflow', 'hidden');\r
+               if (!test){\r
+                       for (var fx in this.effects) element.setStyle(fx, 0);\r
+               }\r
+               return this;\r
+       },\r
+\r
+       display: function(index){\r
+               index = ($type(index) == 'element') ? this.elements.indexOf(index) : index;\r
+               if ((this.timer && this.options.wait) || (index === this.previous && !this.options.alwaysHide)) return this;\r
+               this.previous = index;\r
+               var obj = {};\r
+               this.elements.each(function(el, i){\r
+                       obj[i] = {};\r
+                       var hide = (i != index) || (this.options.alwaysHide && (el.offsetHeight > 0));\r
+                       this.fireEvent(hide ? 'onBackground' : 'onActive', [this.togglers[i], el]);\r
+                       for (var fx in this.effects) obj[i][fx] = hide ? 0 : el[this.effects[fx]];\r
+               }, this);\r
+               return this.start(obj);\r
+       }\r
+\r
+});
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/langs/en.js b/ipf/admin/media/tiny_mce/plugins/images/langs/en.js
new file mode 100755 (executable)
index 0000000..573158a
--- /dev/null
@@ -0,0 +1,3 @@
+tinyMCE.addI18n('en.images',{\r
+       desc : 'Upload and insert picture'\r
+});
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/langs/en_dlg.js b/ipf/admin/media/tiny_mce/plugins/images/langs/en_dlg.js
new file mode 100755 (executable)
index 0000000..e4ea417
--- /dev/null
@@ -0,0 +1,22 @@
+tinyMCE.addI18n('en.images_dlg',{\r
+title:"Pictures",\r
+del_sel_folder:"Remove selected folder?",\r
+sel_files_for_del:"Select files for removal.\n\nYou can remove several files simultaneously by selecting it with Ctrl.",\r
+files_to_del:"Files for removal",\r
+delete_str:"Remove",\r
+create_new_fld:"Create new folder",\r
+create_fld:"Create folder",\r
+upload_files:"Upload files",\r
+delete_file:"Delete file",\r
+\r
+fancy_title:"Image uploading",\r
+fancy_back_alt:"Back to files list",\r
+fancy_back:"Back to files",\r
+fancy_browse:"Browse",\r
+fancy_begin_upload:"Start upload",\r
+fancy_upload_files:"Upload files",\r
+fancy_clear:"Clear list",\r
+fancy_begin_upload_files:"Start files upload",\r
+fancy_general_status:"General status",\r
+fancy_file_status:"File status"\r
+});
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/langs/ru.js b/ipf/admin/media/tiny_mce/plugins/images/langs/ru.js
new file mode 100755 (executable)
index 0000000..2ed3767
--- /dev/null
@@ -0,0 +1,3 @@
+tinyMCE.addI18n('ru.images',{\r
+       desc : '\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430\u0020\u0438\u0020\u0432\u0441\u0442\u0430\u0432\u043A\u0430\u0020\u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0439'\r
+});
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/langs/ru_dlg.js b/ipf/admin/media/tiny_mce/plugins/images/langs/ru_dlg.js
new file mode 100755 (executable)
index 0000000..f964e1e
--- /dev/null
@@ -0,0 +1,22 @@
+tinyMCE.addI18n('ru.images_dlg',{\r
+title:"\u041A\u0430\u0440\u0442\u0438\u043D\u043A\u0438",\r
+del_sel_folder:"\u0423\u0434\u0430\u043B\u0438\u0442\u044C\u0020\u0432\u044B\u0431\u0440\u0430\u043D\u043D\u0443\u044E\u0020\u043F\u0430\u043F\u043A\u0443?",\r
+sel_files_for_del:"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435\u0020\u0444\u0430\u0439\u043B\u044B\u0020\u0434\u043B\u044F\u0020\u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F\u002E\u005C\u006E\u005C\u006E\u0414\u043B\u044F\u0020\u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F\u0020\u043D\u0435\u0441\u043A\u043E\u043B\u044C\u043A\u0438\u0445\u0020\u0444\u0430\u0439\u043B\u043E\u0432\u0020\u0432\u044B\u0434\u0435\u043B\u0438\u0442\u0435\u0020\u0438\u0445\u0020\u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044F\u0020\u0043\u0074\u0072\u006C\u002E",\r
+files_to_del:"\u0424\u0430\u0439\u043B\u043E\u0432\u0020\u043A\u0020\u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044E",\r
+delete_str:"\u0423\u0434\u0430\u043B\u0438\u0442\u044C",\r
+create_new_fld:"\u0421\u043E\u0437\u0434\u0430\u0442\u044C\u0020\u043D\u043E\u0432\u0443\u044E\u0020\u043F\u0430\u043F\u043A\u0443",\r
+create_fld:"\u0421\u043E\u0437\u0434\u0430\u0442\u044C\u0020\u043F\u0430\u043F\u043A\u0443",\r
+upload_files:"\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C\u0020\u0444\u0430\u0439\u043B\u044B",\r
+delete_file:"\u0423\u0434\u0430\u043B\u0438\u0442\u044C\u0020\u0444\u0430\u0439\u043B",\r
+\r
+fancy_title:"\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430\u0020\u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0439",\r
+fancy_back_alt:"\u0412\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F\u0020\u043A\u0020\u0441\u043F\u0438\u0441\u043A\u0443\u0020\u0444\u0430\u0439\u043B\u043E\u0432",\r
+fancy_back:"\u0412\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F\u0020\u043A\u0020\u0444\u0430\u0439\u043B\u0430\u043C",\r
+fancy_browse:"\u041E\u0431\u0437\u043E\u0440",\r
+fancy_begin_upload:"\u041D\u0430\u0447\u0430\u0442\u044C\u0020\u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0443",\r
+fancy_upload_files:"\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C\u0020\u0444\u0430\u0439\u043B\u044B",\r
+fancy_clear:"\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u044C\u0020\u0441\u043F\u0438\u0441\u043E\u043A",\r
+fancy_begin_upload_files:"\u041D\u0430\u0447\u0430\u0442\u044C\u0020\u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0443\u0020\u0444\u0430\u0439\u043B\u043E\u0432",\r
+fancy_general_status:"\u041E\u0431\u0449\u0438\u0439\u0020\u0441\u0442\u0430\u0442\u0443\u0441",\r
+fancy_file_status:"\u0421\u0442\u0430\u0442\u0443\u0441\u0020\u0444\u0430\u0439\u043B\u0430"\r
+});
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/read_ru.txt b/ipf/admin/media/tiny_mce/plugins/images/read_ru.txt
new file mode 100755 (executable)
index 0000000..a62fc1b
--- /dev/null
@@ -0,0 +1,3 @@
+TinyMCE Images Plugin\r
+\r
+Ñàéò àâòîðà: http://dustweb.ru/log/projects/tinymce_images/
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/server_connector/JsHttpRequest.php b/ipf/admin/media/tiny_mce/plugins/images/server_connector/JsHttpRequest.php
new file mode 100755 (executable)
index 0000000..9348199
--- /dev/null
@@ -0,0 +1,521 @@
+<?php\r
+/**\r
+ * JsHttpRequest: PHP backend for JavaScript DHTML loader.\r
+ * (C) Dmitry Koterov, http://en.dklab.ru\r
+ *\r
+ * This library is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU Lesser General Public\r
+ * License as published by the Free Software Foundation; either\r
+ * version 2.1 of the License, or (at your option) any later version.\r
+ * See http://www.gnu.org/copyleft/lesser.html\r
+ *\r
+ * Do not remove this comment if you want to use the script!\r
+ * Íå óäàëÿéòå äàííûé êîììåíòàðèé, åñëè âû õîòèòå èñïîëüçîâàòü ñêðèïò!\r
+ *\r
+ * This backend library also supports POST requests additionally to GET.\r
+ *\r
+ * @author Dmitry Koterov \r
+ * @version 5.x $Id$\r
+ */\r
+\r
+class JsHttpRequest\r
+{\r
+    var $SCRIPT_ENCODING = "windows-1251";\r
+    var $SCRIPT_DECODE_MODE = '';\r
+    var $LOADER = null;\r
+    var $ID = null;    \r
+    var $RESULT = null;\r
+    \r
+    // Internal; uniq value.\r
+    var $_uniqHash;\r
+    // Magic number for display_error checking.\r
+    var $_magic = 14623;\r
+    // Previous display_errors value.\r
+    var $_prevDisplayErrors = null;    \r
+    // Internal: response content-type depending on loader type.\r
+    var $_contentTypes = array(\r
+        "script" => "text/javascript",\r
+        "xml"    => "text/plain", // In XMLHttpRequest mode we must return text/plain - stupid Opera 8.0. :(\r
+        "form"   => "text/html",\r
+        ""       => "text/plain", // for unknown loader\r
+    );\r
+    // Internal: conversion to UTF-8 JSON cancelled because of non-ascii key.\r
+    var $_toUtfFailed = false;\r
+    // Internal: list of characters 128...255 (for strpbrk() ASCII check).\r
+    var $_nonAsciiChars = '';\r
+    // Which Unicode conversion function is available?\r
+    var $_unicodeConvMethod = null;\r
+    // Emergency memory buffer to be freed on memory_limit error.\r
+    var $_emergBuffer = null;\r
+\r
+    \r
+    /**\r
+     * Constructor.\r
+     * \r
+     * Create new JsHttpRequest backend object and attach it\r
+     * to script output buffer. As a result - script will always return\r
+     * correct JavaScript code, even in case of fatal errors.\r
+     *\r
+     * QUERY_STRING is in form of: PHPSESSID=<sid>&a=aaa&b=bbb&JsHttpRequest=<id>-<loader>\r
+     * where <id> is a request ID, <loader> is a loader name, <sid> - a session ID (if present), \r
+     * PHPSESSID - session parameter name (by default = "PHPSESSID").\r
+     * \r
+     * If an object is created WITHOUT an active AJAX query, it is simply marked as\r
+     * non-active. Use statuc method isActive() to check.\r
+     */\r
+    function JsHttpRequest($enc)\r
+    {\r
+        global $JsHttpRequest_Active;\r
+        \r
+        // To be on a safe side - do not allow to drop reference counter on ob processing.\r
+        $GLOBALS['_RESULT'] =& $this->RESULT; \r
+        \r
+        // Parse QUERY_STRING.\r
+        if (preg_match('/^(.*)(?:&|^)JsHttpRequest=(?:(\d+)-)?([^&]+)((?:&|$).*)$/s', @$_SERVER['QUERY_STRING'], $m)) {\r
+            $this->ID = $m[2];\r
+            $this->LOADER = strtolower($m[3]);\r
+            $_SERVER['QUERY_STRING'] = preg_replace('/^&+|&+$/s', '', preg_replace('/(^|&)'.session_name().'=[^&]*&?/s', '&', $m[1] . $m[4]));\r
+            unset(\r
+                $_GET['JsHttpRequest'],\r
+                $_REQUEST['JsHttpRequest'],\r
+                $_GET[session_name()],\r
+                $_POST[session_name()],\r
+                $_REQUEST[session_name()]\r
+            );\r
+            // Detect Unicode conversion method.\r
+            $this->_unicodeConvMethod = function_exists('mb_convert_encoding')? 'mb' : (function_exists('iconv')? 'iconv' : null);\r
+    \r
+            // Fill an emergency buffer. We erase it at the first line of OB processor\r
+            // to free some memory. This memory may be used on memory_limit error.\r
+            $this->_emergBuffer = str_repeat('a', 1024 * 200);\r
+\r
+            // Intercept fatal errors via display_errors (seems it is the only way).     \r
+            $this->_uniqHash = md5('JsHttpRequest' . microtime() . getmypid());\r
+            $this->_prevDisplayErrors = ini_get('display_errors');\r
+            ini_set('display_errors', $this->_magic); //\r
+            ini_set('error_prepend_string', $this->_uniqHash . ini_get('error_prepend_string'));\r
+            ini_set('error_append_string',  ini_get('error_append_string') . $this->_uniqHash);\r
+\r
+            // Start OB handling early.\r
+            ob_start(array(&$this, "_obHandler"));\r
+            $JsHttpRequest_Active = true;\r
+    \r
+            // Set up the encoding.\r
+            $this->setEncoding($enc);\r
+    \r
+            // Check if headers are already sent (see Content-Type library usage).\r
+            // If true - generate a debug message and exit.\r
+            $file = $line = null;\r
+            $headersSent = version_compare(PHP_VERSION, "4.3.0") < 0? headers_sent() : headers_sent($file, $line);\r
+            if ($headersSent) {\r
+                trigger_error(\r
+                    "HTTP headers are already sent" . ($line !== null? " in $file on line $line" : " somewhere in the script") . ". "\r
+                    . "Possibly you have an extra space (or a newline) before the first line of the script or any library. "\r
+                    . "Please note that JsHttpRequest uses its own Content-Type header and fails if "\r
+                    . "this header cannot be set. See header() function documentation for more details",\r
+                    E_USER_ERROR\r
+                );\r
+                exit();\r
+            }\r
+        } else {\r
+            $this->ID = 0;\r
+            $this->LOADER = 'unknown';\r
+            $JsHttpRequest_Active = false;\r
+        }\r
+    }\r
+    \r
+\r
+    /**\r
+     * Static function.\r
+     * Returns true if JsHttpRequest output processor is currently active.\r
+     * \r
+     * @return boolean    True if the library is active, false otherwise.\r
+     */\r
+    function isActive()\r
+    {\r
+        return !empty($GLOBALS['JsHttpRequest_Active']);\r
+    }\r
+    \r
+\r
+    /**\r
+     * string getJsCode()\r
+     * \r
+     * Return JavaScript part of the library.\r
+     */\r
+    function getJsCode()\r
+    {\r
+        return file_get_contents(dirname(__FILE__) . '/JsHttpRequest.js');\r
+    }\r
+\r
+\r
+    /**\r
+     * void setEncoding(string $encoding)\r
+     * \r
+     * Set an active script encoding & correct QUERY_STRING according to it.\r
+     * Examples:\r
+     *   "windows-1251"          - set plain encoding (non-windows characters, \r
+     *                             e.g. hieroglyphs, are totally ignored)\r
+     *   "windows-1251 entities" - set windows encoding, BUT additionally replace:\r
+     *                             "&"         ->  "&amp;" \r
+     *                             hieroglyph  ->  &#XXXX; entity\r
+     */\r
+    function setEncoding($enc)\r
+    {\r
+        // Parse an encoding.\r
+        preg_match('/^(\S*)(?:\s+(\S*))$/', $enc, $p);\r
+        $this->SCRIPT_ENCODING    = strtolower(!empty($p[1])? $p[1] : $enc);\r
+        $this->SCRIPT_DECODE_MODE = !empty($p[2])? $p[2] : '';\r
+        // Manually parse QUERY_STRING because of damned Unicode's %uXXXX.\r
+        $this->_correctSuperglobals();\r
+    }\r
+\r
+    \r
+    /**\r
+     * string quoteInput(string $input)\r
+     * \r
+     * Quote a string according to the input decoding mode.\r
+     * If entities are used (see setEncoding()), no '&' character is quoted,\r
+     * only '"', '>' and '<' (we presume that '&' is already quoted by\r
+     * an input reader function).\r
+     *\r
+     * Use this function INSTEAD of htmlspecialchars() for $_GET data \r
+     * in your scripts.\r
+     */\r
+    function quoteInput($s)\r
+    {\r
+        if ($this->SCRIPT_DECODE_MODE == 'entities')\r
+            return str_replace(array('"', '<', '>'), array('&quot;', '&lt;', '&gt;'), $s);\r
+        else\r
+            return htmlspecialchars($s);\r
+    }\r
+    \r
+\r
+    /**\r
+     * Convert a PHP scalar, array or hash to JS scalar/array/hash. This function is \r
+     * an analog of json_encode(), but it can work with a non-UTF8 input and does not \r
+     * analyze the passed data. Output format must be fully JSON compatible.\r
+     * \r
+     * @param mixed $a   Any structure to convert to JS.\r
+     * @return string    JavaScript equivalent structure.\r
+     */\r
+    function php2js($a=false)\r
+    {\r
+        if (is_null($a)) return 'null';\r
+        if ($a === false) return 'false';\r
+        if ($a === true) return 'true';\r
+        if (is_scalar($a)) {\r
+            if (is_float($a)) {\r
+                // Always use "." for floats.\r
+                $a = str_replace(",", ".", strval($a));\r
+            }\r
+            // All scalars are converted to strings to avoid indeterminism.\r
+            // PHP's "1" and 1 are equal for all PHP operators, but \r
+            // JS's "1" and 1 are not. So if we pass "1" or 1 from the PHP backend,\r
+            // we should get the same result in the JS frontend (string).\r
+            // Character replacements for JSON.\r
+            static $jsonReplaces = array(\r
+                array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"'),\r
+                array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"')\r
+            );\r
+            return '"' . str_replace($jsonReplaces[0], $jsonReplaces[1], $a) . '"';\r
+        }\r
+        $isList = true;\r
+        for ($i = 0, reset($a); $i < count($a); $i++, next($a)) {\r
+            if (key($a) !== $i) { \r
+                $isList = false; \r
+                break; \r
+            }\r
+        }\r
+        $result = array();\r
+        if ($isList) {\r
+            foreach ($a as $v) {\r
+                $result[] = JsHttpRequest::php2js($v);\r
+            }\r
+            return '[ ' . join(', ', $result) . ' ]';\r
+        } else {\r
+            foreach ($a as $k => $v) {\r
+                $result[] = JsHttpRequest::php2js($k) . ': ' . JsHttpRequest::php2js($v);\r
+            }\r
+            return '{ ' . join(', ', $result) . ' }';\r
+        }\r
+    }\r
+    \r
+        \r
+    /**\r
+     * Internal methods.\r
+     */\r
+\r
+    /**\r
+     * Parse & decode QUERY_STRING.\r
+     */\r
+    function _correctSuperglobals()\r
+    {\r
+        // In case of FORM loader we may go to nirvana, everything is already parsed by PHP.\r
+        if ($this->LOADER == 'form') return;\r
+        \r
+        // ATTENTION!!!\r
+        // HTTP_RAW_POST_DATA is only accessible when Content-Type of POST request\r
+        // is NOT default "application/x-www-form-urlencoded"!!!\r
+        // Library frontend sets "application/octet-stream" for that purpose,\r
+        // see JavaScript code. In PHP 5.2.2.HTTP_RAW_POST_DATA is not set sometimes; \r
+        // in such cases - read the POST data manually from the STDIN stream.\r
+        $rawPost = strcasecmp($_SERVER['REQUEST_METHOD'], 'POST') == 0? (isset($GLOBALS['HTTP_RAW_POST_DATA'])? $GLOBALS['HTTP_RAW_POST_DATA'] : @file_get_contents("php://input")) : null;\r
+        $source = array(\r
+            '_GET' => !empty($_SERVER['QUERY_STRING'])? $_SERVER['QUERY_STRING'] : null, \r
+            '_POST'=> $rawPost,\r
+        );\r
+        foreach ($source as $dst=>$src) {\r
+            // First correct all 2-byte entities.\r
+            $s = preg_replace('/%(?!5B)(?!5D)([0-9a-f]{2})/si', '%u00\\1', $src);\r
+            // Now we can use standard parse_str() with no worry!\r
+            $data = null;\r
+            parse_str($s, $data);\r
+            $GLOBALS[$dst] = $this->_ucs2EntitiesDecode($data);\r
+        }\r
+        $GLOBALS['HTTP_GET_VARS'] = $_GET; // deprecated vars\r
+        $GLOBALS['HTTP_POST_VARS'] = $_POST;\r
+        $_REQUEST = \r
+            (isset($_COOKIE)? $_COOKIE : array()) + \r
+            (isset($_POST)? $_POST : array()) + \r
+            (isset($_GET)? $_GET : array());\r
+        if (ini_get('register_globals')) {\r
+            // TODO?\r
+        }\r
+    }\r
+\r
+\r
+    /**\r
+     * Called in case of error too!\r
+     */\r
+    function _obHandler($text)\r
+    {\r
+        unset($this->_emergBuffer); // free a piece of memory for memory_limit error\r
+        unset($GLOBALS['JsHttpRequest_Active']);\r
+        \r
+        // Check for error & fetch a resulting data.\r
+        if (preg_match("/{$this->_uniqHash}(.*?){$this->_uniqHash}/sx", $text, $m)) {\r
+            if (!ini_get('display_errors') || (!$this->_prevDisplayErrors && ini_get('display_errors') == $this->_magic)) {\r
+                // Display_errors:\r
+                // 1. disabled manually after the library initialization, or\r
+                // 2. was initially disabled and is not changed\r
+                $text = str_replace($m[0], '', $text); // strip whole error message\r
+            } else {\r
+                $text = str_replace($this->_uniqHash, '', $text);\r
+            }\r
+        }\r
+        if ($m && preg_match('/\bFatal error(<.*?>)?:/i', $m[1])) {\r
+            // On fatal errors - force null result (generate 500 error).\r
+            $this->RESULT = null;\r
+        } else {\r
+            // Make a resulting hash.\r
+            if (!isset($this->RESULT)) {\r
+                global $_RESULT;\r
+                $this->RESULT = $_RESULT;\r
+            }\r
+        }\r
+        \r
+        $result = array(\r
+            'id'   => $this->ID,\r
+            'js'   => $this->RESULT,\r
+            'text' => $text,\r
+        );\r
+        $text = null;\r
+        $encoding = $this->SCRIPT_ENCODING;\r
+        $status = $this->RESULT !== null? 200 : 500;\r
+\r
+        // Try to use very fast json_encode: 3-4 times faster than a manual encoding.\r
+        if (function_exists('array_walk_recursive') && function_exists('json_encode') && $this->_unicodeConvMethod) {\r
+            $this->_nonAsciiChars = join("", array_map('chr', range(128, 255)));\r
+            $this->_toUtfFailed = false;\r
+            $resultUtf8 = $result;\r
+            array_walk_recursive($resultUtf8, array(&$this, '_toUtf8_callback'), $this->SCRIPT_ENCODING);\r
+            if (!$this->_toUtfFailed) {\r
+                // If some key contains non-ASCII character, convert everything manually.\r
+                $text = json_encode($resultUtf8);\r
+                $encoding = "UTF-8";\r
+            }\r
+        }\r
+        \r
+        // On failure, use manual encoding.\r
+        if ($text === null) {\r
+            $text = $this->php2js($result);\r
+        }\r
+\r
+        if ($this->LOADER != "xml") {\r
+            // In non-XML mode we cannot use plain JSON. So - wrap with JS function call.\r
+            // If top.JsHttpRequestGlobal is not defined, loading is aborted and \r
+            // iframe is removed, so - do not call dataReady().\r
+            $text = "" \r
+                . ($this->LOADER == "form"? 'top && top.JsHttpRequestGlobal && top.JsHttpRequestGlobal' : 'JsHttpRequest') \r
+                . ".dataReady(" . $text . ")\n"\r
+                . "";\r
+            if ($this->LOADER == "form") {\r
+                $text = '<script type="text/javascript" language="JavaScript"><!--' . "\n$text" . '//--></script>';\r
+            }\r
+            \r
+            // Always return 200 code in non-XML mode (else SCRIPT does not work in FF).\r
+            // For XML mode, 500 code is okay.\r
+            $status = 200;\r
+        }\r
+\r
+        // Status header. To be safe, display it only in error mode. In case of success \r
+        // termination, do not modify the status (""HTTP/1.1 ..." header seems to be not\r
+        // too cross-platform).\r
+        if ($this->RESULT === null) {\r
+            if (php_sapi_name() == "cgi") {\r
+                header("Status: $status");\r
+            } else {\r
+                header("HTTP/1.1 $status");\r
+            }\r
+        }\r
+\r
+        // In XMLHttpRequest mode we must return text/plain - damned stupid Opera 8.0. :(\r
+        $ctype = !empty($this->_contentTypes[$this->LOADER])? $this->_contentTypes[$this->LOADER] : $this->_contentTypes[''];\r
+        header("Content-type: $ctype; charset=$encoding");\r
+\r
+        return $text;\r
+    }\r
+\r
+\r
+    /**\r
+     * Internal function, used in array_walk_recursive() before json_encode() call.\r
+     * If a key contains non-ASCII characters, this function sets $this->_toUtfFailed = true,\r
+     * becaues array_walk_recursive() cannot modify array keys.\r
+     */\r
+    function _toUtf8_callback(&$v, $k, $fromEnc)\r
+    {\r
+        if ($v === null || is_bool($v)) return;\r
+        if ($this->_toUtfFailed || !is_scalar($v) || strpbrk($k, $this->_nonAsciiChars) !== false) {\r
+            $this->_toUtfFailed = true;\r
+        } else {\r
+            $v = $this->_unicodeConv($fromEnc, 'UTF-8', $v);\r
+        }\r
+    }\r
+    \r
+\r
+    /**\r
+     * Decode all %uXXXX entities in string or array (recurrent).\r
+     * String must not contain %XX entities - they are ignored!\r
+     */\r
+    function _ucs2EntitiesDecode($data)\r
+    {\r
+        if (is_array($data)) {\r
+            $d = array();\r
+            foreach ($data as $k=>$v) {\r
+                $d[$this->_ucs2EntitiesDecode($k)] = $this->_ucs2EntitiesDecode($v);\r
+            }\r
+            return $d;\r
+        } else {\r
+            if (strpos($data, '%u') !== false) { // improve speed\r
+                $data = preg_replace_callback('/%u([0-9A-F]{1,4})/si', array(&$this, '_ucs2EntitiesDecodeCallback'), $data);\r
+            }\r
+            return $data;\r
+        }\r
+    }\r
+\r
+\r
+    /**\r
+     * Decode one %uXXXX entity (RE callback).\r
+     */\r
+    function _ucs2EntitiesDecodeCallback($p)\r
+    {\r
+        $hex = $p[1];\r
+        $dec = hexdec($hex);\r
+        if ($dec === "38" && $this->SCRIPT_DECODE_MODE == 'entities') {\r
+            // Process "&" separately in "entities" decode mode.\r
+            $c = "&amp;";\r
+        } else {\r
+            if ($this->_unicodeConvMethod) {\r
+                $c = @$this->_unicodeConv('UCS-2BE', $this->SCRIPT_ENCODING, pack('n', $dec));\r
+            } else {\r
+                $c = $this->_decUcs2Decode($dec, $this->SCRIPT_ENCODING);\r
+            }\r
+            if (!strlen($c)) {\r
+                if ($this->SCRIPT_DECODE_MODE == 'entities') {\r
+                    $c = '&#' . $dec . ';';\r
+                } else {\r
+                    $c = '?';\r
+                }\r
+            }\r
+        }\r
+        return $c;\r
+    }\r
+\r
+\r
+    /**\r
+     * Wrapper for iconv() or mb_convert_encoding() functions.\r
+     * This function will generate fatal error if none of these functons available!\r
+     * \r
+     * @see iconv()\r
+     */\r
+    function _unicodeConv($fromEnc, $toEnc, $v)\r
+    {\r
+        if ($this->_unicodeConvMethod == 'iconv') {\r
+            return iconv($fromEnc, $toEnc, $v);\r
+        } \r
+        return mb_convert_encoding($v, $toEnc, $fromEnc);\r
+    }\r
+\r
+\r
+    /**\r
+     * If there is no ICONV, try to decode 1-byte characters manually\r
+     * (for most popular charsets only).\r
+     */\r
+     \r
+    /**\r
+     * Convert from UCS-2BE decimal to $toEnc.\r
+     */\r
+    function _decUcs2Decode($code, $toEnc)\r
+    {\r
+        if ($code < 128) return chr($code);\r
+        if (isset($this->_encTables[$toEnc])) {\r
+            // TODO: possible speedup by using array_flip($this->_encTables) and later hash access in the constructor.\r
+            $p = array_search($code, $this->_encTables[$toEnc]);\r
+            if ($p !== false) return chr(128 + $p);\r
+        }\r
+        return "";\r
+    }\r
+    \r
+\r
+    /**\r
+     * UCS-2BE -> 1-byte encodings (from #128).\r
+     */\r
+    var $_encTables = array(\r
+        'windows-1251' => array(\r
+            0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,\r
+            0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,\r
+            0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,\r
+            0x0098, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,\r
+            0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,\r
+            0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,\r
+            0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,\r
+            0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,\r
+            0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,\r
+            0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,\r
+            0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,\r
+            0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,\r
+            0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,\r
+            0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,\r
+            0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,\r
+            0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,\r
+        ),\r
+        'koi8-r' => array(\r
+            0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,\r
+            0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,\r
+            0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219, 0x221A, 0x2248,\r
+            0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,\r
+            0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556,\r
+            0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255d, 0x255E,\r
+            0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565,\r
+            0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9,\r
+            0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,\r
+            0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043d, 0x043E,\r
+            0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,\r
+            0x044C, 0x044B, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044A,\r
+            0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,\r
+            0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041d, 0x041E,\r
+            0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,\r
+            0x042C, 0x042B, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042A      \r
+        ),\r
+    );\r
+}\r
diff --git a/ipf/admin/media/tiny_mce/plugins/images/server_connector/ajax.php b/ipf/admin/media/tiny_mce/plugins/images/server_connector/ajax.php
new file mode 100755 (executable)
index 0000000..f022184
--- /dev/null
@@ -0,0 +1,20 @@
+<?php\r
+require_once 'JsHttpRequest.php';\r
+require_once 'tinyimages.php';\r
+\r
+$JsHttpRequest =& new JsHttpRequest('windows-1251');\r
+\r
+if(!isset($_REQUEST['m'])) {\r
+       $GLOBALS['_RESULT'] = array( 'error' => 'Íå çàäàí ìåòîä');\r
+       exit();\r
+}\r
+list($module, $method) = explode('->',$_REQUEST['m']);\r
+if(empty($method)) {\r
+       list($module, $method) = explode('-%3E',$_REQUEST['m']);\r
+}\r
+$method = 'ajax'.$method;\r
+\r
+$timgs = new tinyimages();\r
+\r
+$GLOBALS['_RESULT'] = $timgs->$method($_REQUEST);\r
+exit();
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/server_connector/files_conn.php b/ipf/admin/media/tiny_mce/plugins/images/server_connector/files_conn.php
new file mode 100755 (executable)
index 0000000..189681d
--- /dev/null
@@ -0,0 +1,8 @@
+<?php\r
+//session_start();\r
+\r
+include 'tinyimages.php';\r
+\r
+$images = new tinyimages();\r
+$images->UploadFiles();\r
+?>
\ No newline at end of file
diff --git a/ipf/admin/media/tiny_mce/plugins/images/server_connector/tinyimages.php b/ipf/admin/media/tiny_mce/plugins/images/server_connector/tinyimages.php
new file mode 100755 (executable)
index 0000000..040c885
--- /dev/null
@@ -0,0 +1,490 @@
+<?php\r
+class tinyimages {\r
+       \r
+       var $folder = '/media/upload/editor';\r
+       \r
+       function __construct() {\r
+               define(DIR, $_SERVER['DOCUMENT_ROOT'].'/');\r
+               \r
+               // ATTENTION!\r
+               // You need to check the session here, because methods of this class can be danger to security!\r
+               //if(!isset($_SESSION['user']['type'])) return false;\r
+               \r
+               $this->folder = $this->folder;\r
+               $this->restrict = $this->folder;\r
+       }\r
+       \r
+       private function leftPanel() {\r
+               $ret = array();\r
+               if ($handle = opendir ( DIR.$this->folder )) {\r
+                       while (false !== ($file = readdir ( $handle ))) {\r
+                               if (is_dir(DIR.$this->folder.'/'.$file) && $file != '.') {\r
+                                       $ret[] = array(\r
+                                               'path' => $file,\r
+                                               'name'  => $file\r
+                                       );\r
+                               }\r
+                       }\r
+                       closedir ($handle);\r
+               }\r
+               \r
+               if(count($ret) > 0) {\r
+                       $return = '';\r
+                       foreach ($ret as $val) {\r
+                               if($val['path'] == '.thumbs') continue;\r
+                               if($val['path'] == '..') {\r
+                                       $act = '';\r
+                                       if($this->folder == $this->restrict) continue;\r
+                                       $path = substr($this->folder,0,strrpos($this->folder,'/'));\r
+                                       if($path == '') continue;\r
+                               }\r
+                               else { $path = $this->folder.'/'.$val['path']; $act = 'onclick="activateDir(this, \''.$path.'\'); return false;"'; }\r
+                               $return .= '<div class="folder"><a href="#" '.$act.' ondblclick="changeFolder(\''.$path.'\'); return false;">'.$val['name'].'</a></div>';\r
+                       }\r
+                       \r
+                       $name = '';\r
+                       \r
+                       return $return;\r
+               }\r
+       }\r
+       \r
+       private function addressBar() {\r
+               $way = explode('/',str_replace($this->restrict, '', $this->folder));\r
+               $way = array_filter($way);\r
+               $ret = $link = '';\r
+               foreach ($way as $val) {\r
+                       $link = $link.'/'.$val;\r
+                       $ret .= '<a href="#" onclick="changeFolder(\''.$this->restrict.$link.'\'); return false;">'.$val.'</a>';\r
+               }\r
+               return '<a href="#" onclick="changeFolder(\''.$this->restrict.'\'); return false;" class="first"><img src="images/folder.gif" width="16" height="16" /></a>'.$ret;\r
+       }\r
+       \r
+       private function mainField() {\r
+               $ret = array();\r
+               if ($handle = opendir ( DIR.$this->folder )) {\r
+                       while (false !== ($file = readdir ( $handle ))) {\r
+                               if (is_file(DIR.$this->folder.'/'.$file)) {\r
+                                       \r
+                                       list($width, $height, $type, $attr) = getimagesize(DIR.$this->folder.'/'.$file);\r
+                                       \r
+                                       $size = number_format((filesize(DIR.$this->folder.'/'.$file)/1024),2,',',' ').' KB';\r
+                                       \r
+                                       $ret[] = array(\r
+                                               'src'   => $this->folder.'/.thumbs/100x100_'.$file,\r
+                                               'attr'  => $attr,\r
+                                               'path'  => $this->folder.'/'.$file,\r
+                                               'name'  => $file,\r
+                                               'width' => $width,\r
+                                               'height'=> $height,\r
+                                               'size'  => $size\r
+                                       );\r
+                               }\r
+                       }\r
+                       closedir ($handle);\r
+               }\r
+               \r
+               \r
+               if(count($ret) > 0) {\r
+                       $return = '';\r
+                       foreach ($ret as $val) {\r
+                               $width_for_insert = $val['width']>500?500:$val['width'];\r
+                               $return .= '<div class="item" ondblclick="addImage(this,\''.$val['path'].'\','.$width_for_insert.');" onclick="activateItem(this,\''.$val['path'].'\');"><img src="'.$val['src'].'" width="100" height="100" alt=" " /><div class="labels">'.$val['width'].'x'.$val['height'].'</div><div class="labels">'.$val['size'].'</div></div>';\r
+                       }\r
+                       \r
+                       $name = '';\r
+                       \r
+                       return $return.'<div style="clear:both;"></div>';\r
+               }\r
+       }\r
+       \r
+       function ajaxChangeDir($input) {\r
+               \r
+               $our_folder = $this->folder;\r
+               \r
+               if($input['uri'] != '') {\r
+                       $this->folder = $input['uri'];\r
+                       \r
+                       $realpath1 = realpath(DIR.$our_folder);\r
+                       $realpath2 = realpath(DIR.$input['uri']);\r
+                       \r
+                       $strlen1 = strlen($realpath1);\r
+                       $strlen2 = strlen($realpath2);\r
+                       if($strlen1 > $strlen2) { page404(); exit(); }\r
+                       for($i=0;$i<$strlen1;$i++) {\r
+                               if($realpath1[$i] != $realpath2[$i]) { page404(); exit(); }\r
+                       }\r
+               }elseif(isset($_SESSION['tiny_folder'])) {\r
+                       if($_SESSION['tiny_folder'] != '') {\r
+                               $this->folder = $_SESSION['tiny_folder'];\r
+                       }\r
+               }\r
+               \r
+               \r
+               $_SESSION['tiny_folder'] = $this->folder;\r
+               return array(\r
+                       'leftpanel'             => $this->leftPanel(),\r
+                       'addressbar'    => $this->addressBar(),\r
+                       'mainfield'             => $this->mainField(),\r
+                       'uri'                   => $this->folder\r
+               );\r
+       }\r
+       \r
+       \r
+       \r
+       function ajaxDelDir($input) {\r
+               $our_folder = $this->folder;\r
+               \r
+               if($input['dir'] != '') {\r
+                       $this->folder = $input['dir'];\r
+                       \r
+                       $realpath1 = realpath(DIR.$our_folder);\r
+                       $realpath2 = realpath(DIR.$input['dir']);\r
+                       \r
+                       $strlen1 = strlen($realpath1);\r
+                       $strlen2 = strlen($realpath2);\r
+                       if($strlen1 > $strlen2) { page404(); exit(); }\r
+                       for($i=0;$i<$strlen1;$i++) {\r
+                               if($realpath1[$i] != $realpath2[$i]) { page404(); exit(); }\r
+                       }\r
+               } else { page404(); exit(); }\r
+               \r
+               if ($handle = opendir ( DIR.$input['dir'] )) {\r
+                       while (false !== ($file = readdir ( $handle ))) {\r
+                               if (is_file(DIR.$input['dir'].'/'.$file)) {\r
+                                       \r
+                                       $thumb_info = pathinfo(DIR.$input['dir'].'/'.$file);\r
+                                       $thumb = $thumb_info['dirname'].'/.thumbs/100x100_'.$thumb_info['basename'];\r
+                                       unlink($thumb);\r
+                                       unlink(DIR.$input['dir'].'/'.$file);\r
+                               }\r
+                       }\r
+                       closedir ($handle);\r
+               }\r
+               \r
+               if ($handle = opendir ( DIR.$input['dir'].'/.thumbs' )) {\r
+                       while (false !== ($file = readdir ( $handle ))) {\r
+                               if (is_file(DIR.$input['dir'].'/.thumbs'.'/'.$file)) {\r
+                                       \r
+                                       $thumb_info = pathinfo(DIR.$input['dir'].'/.thumbs'.'/'.$file);\r
+                                       $thumb = $thumb_info['dirname'].'/.thumbs/100x100_'.$thumb_info['basename'];\r
+                                       unlink($thumb);\r
+                                       unlink(DIR.$input['dir'].'/.thumbs'.'/'.$file);\r
+                               }\r
+                       }\r
+                       closedir ($handle);\r
+               }\r
+               rmdir(DIR.$input['dir'].'/.thumbs');\r
+               \r
+               if(!rmdir(DIR.$input['dir'])) {\r
+                       if($input['lng']=='ru') {\r
+                               return array('error'=>'Îøèáêà óäàëåíèÿ ïàïêè, âîçìîæíî îíà ñîäåðæèò íå óäàëåííûå êàòàëîãè!');\r
+                       } else {\r
+                               return array('error'=>'Error delete a folder, perhaps it has not deleted directories!');\r
+                       }\r
+               } else return array();\r
+               \r
+       }\r
+       \r
+       \r
+       function ajaxDelFile($input) {\r
+               \r
+               $error = array();\r
+               \r
+               $input['src'] = array_filter($input['src']);\r
+               \r
+               $input['src'] = array_unique($input['src']);\r
+               \r
+               foreach ($input['src'] as $key=>$val) {\r
+                       if(!is_numeric($key)) continue;\r
+                       $our_folder = $this->folder;\r
+                       $pi = pathinfo($val);\r
+                       $input['uri'] = $pi['dirname'];\r
+                       \r
+                       if($input['uri'] != '') {\r
+                               $this->folder = $input['uri'];\r
+                               \r
+                               $realpath1 = realpath(DIR.$our_folder);\r
+                               $realpath2 = realpath(DIR.$input['uri']);\r
+                               \r
+                               $strlen1 = strlen($realpath1);\r
+                               $strlen2 = strlen($realpath2);\r
+                               if($strlen1 > $strlen2) { page404(); exit(); }\r
+                               for($i=0;$i<$strlen1;$i++) {\r
+                                       if($realpath1[$i] != $realpath2[$i]) { page404(); exit(); }\r
+                               }\r
+                       } else { page404(); exit(); }\r
+                       \r
+                       if(is_file(DIR.$input['src'][$key])) {\r
+                               $thumb_info = pathinfo(DIR.$input['src'][$key]);\r
+                               $thumb = $thumb_info['dirname'].'/.thumbs/100x100_'.$thumb_info['basename'];\r
+                               unlink($thumb);\r
+                               unlink(DIR.$input['src'][$key]);\r
+                       } else {\r
+                               if($input['lng']=='ru') { \r
+                                       $error[] = 'Ôàéë '.$val.' íå íàéäåí!';\r
+                               } else {\r
+                                       $error[] = 'File '.$val.' not found!';\r
+                               }\r
+                       }\r
+               \r
+               }\r
+               \r
+               if(count($error) > 0) return array('error'=>implode(', ',$error));\r
+               else return array();\r
+       }\r
+       \r
+       \r
+       function UploadFiles() {\r
+               $our_folder = $this->folder;\r
+               \r
+               if($_GET['uri'] != '') {\r
+                       $this->folder = $_GET['uri'];\r
+                       \r
+                       $realpath1 = realpath(DIR.$our_folder);\r
+                       $realpath2 = realpath(DIR.$_GET['uri']);\r
+                       \r
+                       $strlen1 = strlen($realpath1);\r
+                       $strlen2 = strlen($realpath2);\r
+                       \r
+                       if($strlen1 > $strlen2) { page404(); exit(); }\r
+                       for($i=0;$i<$strlen1;$i++) {\r
+                               if($realpath1[$i] != $realpath2[$i]) { page404(); exit(); }\r
+                       }\r
+               }\r
+               \r
+               $result = array();\r
+\r
+               if (isset($_FILES['photoupload'])) {\r
+                       $file = $_FILES['photoupload']['tmp_name'];\r
+                       $error = false;\r
+                       $size = false;\r
+\r
+                       if (!is_uploaded_file($file) || ($_FILES['photoupload']['size'] > 2 * 1024 * 1024) ) {\r
+                               if($_GET['lng']=='ru') {\r
+                                       $error = 'Ïîæàëóéñòà, çàãðóæàéòå ôàéëû íå áîëåå 2Ìá!';\r
+                               } else {\r
+                                       $error = 'Please do not upload files over 2Mb!';\r
+                               }\r
+                       } else\r
+                       if (!$error && !($size = @getimagesize($file) ) ) {\r
+                               if($_GET['lng']=='ru') {\r
+                                       $error = 'Îøèáêà, íå âåðíûé òèï ôàéëà';\r
+                               } else {\r
+                                       $error = 'Error, unsupported type of file';\r
+                               }\r
+                       } else\r
+                       if (!$error && !in_array($size[2], array(1, 2, 3, 7, 8) ) ) {\r
+                               if($_GET['lng']=='ru') {\r
+                                       $error = 'Îøèáêà òèïà ôàéëà, ðåêîìåíäóåòñÿ çàãðóæàòü ôàéëû JPEG';\r
+                               } else {\r
+                                       $error = 'Error type of file, recommend upload JPEG files';\r
+                               }\r
+                       } else\r
+                       if (!$error && ($size[0] < 5) || ($size[1] < 5)) {\r
+                               if($_GET['lng']=='ru') {\r
+                                       $error = 'Ïîæàëóéñòà, çàãðóæàéòå êàðòèíêè ðàçìåðîì áîëåå 5px.';\r
+                               } else {\r
+                                       $error = 'Please upload pictures larger than 5px.';\r
+                               }\r
+                       }\r
+                       if ($error) {\r
+                               $result['result'] = 'failed';\r
+                               $result['error'] = $error;\r
+                       }\r
+                       else {\r
+                               $ext = substr($_FILES['photoupload']['name'],strrpos($_FILES['photoupload']['name'],'.')+1);\r
+                               $name = md5_file($_FILES['photoupload']['tmp_name']);\r
+                               $source = DIR.$this->folder.'/'.$name.'.'.$ext;\r
+                               \r
+                               if(!copy($_FILES['photoupload']['tmp_name'], $source)) {\r
+                                       $result['result'] = 'error';\r
+                                       if($_GET['lng']=='ru') {\r
+                                               $result['error'] = 'Îøèáêà ïðè êîïèðîâàíèè ôàéëà!';\r
+                                       } else {\r
+                                               $result['error'] = 'Failed to copy a file!';\r
+                                       }\r
+                               } else {\r
+                                       \r
+                                       if(!file_exists(DIR.$this->folder.'/.thumbs')) mkdir(DIR.$this->folder.'/.thumbs');\r
+                                       $thumb = DIR.$this->folder.'/.thumbs/100x100_'.$name.'.'.$ext;\r
+                                       \r
+                                       //$image = new files('tinyimages');\r
+                                       $this->Resize($source,$thumb,100,100,'back-ffffff');\r
+                                       \r
+                                       $result['result'] = 'success';\r
+                                       if($_GET['lng']=='ru') {\r
+                                               $result['size'] = "Çàãðóæåíî èçîáðàæåíèå ({$size['mime']}) ðàçìåðîì {$size[0]}px/{$size[1]}px.";\r
+                                       } else {\r
+                                               $result['size'] = "Uploaded image ({$size['mime']}) size {$size[0]}px/{$size[1]}px.";\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               else {\r
+                       $result['result'] = 'error';\r
+                       if($_GET['lng']=='ru') {\r
+                               $result['error'] = 'Íåò ôàéëà èëè âíóòðåííÿÿ îøèáêà!';\r
+                       } else {\r
+                               $result['error'] = 'No file or an internal error!';\r
+                       }\r
+               }\r
+               if (!headers_sent() ) {\r
+                       header('Content-type: application/json');\r
+               }\r
+               \r
+               foreach ($result as $key=>$val) {
+                       $return[$key] = iconv("windows-1251", "utf-8", $val);
+               }
+               \r
+               \r
+               header("Content-Type: text/plain; charset=UTF-8");\r
+               echo json_encode($return);\r
+               exit();\r
+       }\r
+       \r
+       function ajaxMakeFolder($input) {\r
+               \r
+               if($input['lng']=='ru') {\r
+                       if(trim($input['name']) == '') return array('error' => 'Íå çàäàíî èìÿ');\r
+               } else {\r
+                       if(trim($input['name']) == '') return array('error' => 'Not a name');\r
+               }\r
+               \r
+               if($input['uri'] != '') {\r
+                       $this->folder = $input['uri'];\r
+                       \r
+                       $realpath1 = realpath(DIR.$our_folder);\r
+                       $realpath2 = realpath(DIR.$input['uri']);\r
+                       \r
+                       $strlen1 = strlen($realpath1);\r
+                       $strlen2 = strlen($realpath2);\r
+                       \r
+                       if($strlen1 > $strlen2) { page404(); exit(); }\r
+                       for($i=0;$i<$strlen1;$i++) {\r
+                               if($realpath1[$i] != $realpath2[$i]) { page404(); exit(); }\r
+                       }\r
+               }\r
+               \r
+               if(mkdir(DIR.$this->folder.'/'.$input['name'])) { return array(); }\r
+               else {\r
+                       if($input['lng']=='ru') {\r
+                               array('error' => 'Íå óäàëîñü ñîçäàòü ïàïêó');\r
+                       } else {\r
+                               array('error' => 'Unable to create a folder');\r
+                       }\r
+               }\r
+       }\r
+       \r
+       \r
+       function Resize($filename, $dest, $width, $height, $pictype = "") {\r
+               $format = strtolower(substr(strrchr($filename,"."),1));\r
+               switch($format)\r
+               {\r
+                       case 'gif' :\r
+                               $type ="gif";\r
+                               $img = ImageCreateFromGif($filename);\r
+                               break;\r
+                       case 'png' :\r
+                               $type ="png";\r
+                               $img = ImageCreateFromPng($filename);\r
+                               break;\r
+                       case 'jpg' :\r
+                               $type ="jpg";\r
+                               $img = ImageCreateFromJpeg($filename);\r
+                               break;\r
+                       case 'jpeg' :\r
+                               $type ="jpg";\r
+                               $img = ImageCreateFromJpeg($filename);\r
+                               break;\r
+                       default :\r
+                               return false;\r
+                               break;\r
+               }\r
+\r
+               list($org_width, $org_height) = getimagesize($filename);\r
+               $xoffset = 0;\r
+               $yoffset = 0;\r
+               if ($pictype == "thumb") // To minimize destortion\r
+               {\r
+                       if ($org_width / $width > $org_height/ $height)\r
+                       {\r
+                               $xtmp = $org_width;\r
+                               $xratio = 1-((($org_width/$org_height)-($width/$height))/2);\r
+                               $org_width = $org_width * $xratio;\r
+                               $xoffset = ($xtmp - $org_width)/2;\r
+                       }\r
+                       elseif ($org_height/ $height > $org_width / $width)\r
+                       {\r
+                               $ytmp = $org_height;\r
+                               $yratio = 1-((($width/$height)-($org_width/$org_height))/2);\r
+                               $org_height = $org_height * $yratio;\r
+                               $yoffset = ($ytmp - $org_height)/2;\r
+                       }\r
+                       //Added this else part -------------\r
+               } elseif(substr($pictype,0,4) == "back") {\r
+                       $xtmp = $org_width/$width;\r
+                       $new_width = $width;\r
+                       $new_height = $org_height/$xtmp;\r
+                       if ($new_height > $org_height && $new_width > $org_width) {\r
+                               $new_height = $org_height;\r
+                               $new_width = $org_width;\r
+                       } elseif ($new_height > $height){\r
+                               $ytmp = $org_height/$height;\r
+                               $new_height = $height;\r
+                               $new_width = $org_width/$ytmp;\r
+                       }\r
+                       $width_d = round($new_width)<$width?$width:round($new_width);\r
+                       $height_d = round($new_height)<$height?$height:round($new_height);\r
+                       \r
+                       $width = round($new_width);\r
+                       $height = round($new_height);\r
+                       \r
+                       $width_diff = $width_d - $width;\r
+                       $height_diff = $height_d - $height;\r
+               } else {\r
+                       $xtmp = $org_width/$width;\r
+                       $new_width = $width;\r
+                       $new_height = $org_height/$xtmp;\r
+                       if ($new_height > $height){\r
+                               $ytmp = $org_height/$height;\r
+                               $new_height = $height;\r
+                               $new_width = $org_width/$ytmp;\r
+                       }\r
+                       $width = round($new_width);\r
+                       $height = round($new_height);\r
+               }\r
+\r
+               if(substr($pictype,0,4) == "back") {\r
+                       $img_n=imagecreatetruecolor ($width+$width_diff, $height+$height_diff);\r
+                       $r = hexdec(substr($pictype,5,2));\r
+                       $g = hexdec(substr($pictype,7,2));\r
+                       $b = hexdec(substr($pictype,9,2));\r
+                       $back = imagecolorallocate($img_n, $r, $g, $b);\r
+                       imagefill($img_n, 0, 0, $back);\r
+                       imagecopyresampled($img_n, $img, round($width_diff/2), round($height_diff/2), $xoffset, $yoffset, $width, $height, $org_width, $org_height);\r
+               } else {\r
+                       $img_n=imagecreatetruecolor ($width, $height);\r
+                       imagecopyresampled($img_n, $img, 0, 0, $xoffset, $yoffset, $width, $height, $org_width, $org_height);\r
+               }\r
+\r
+               if($type=="gif")\r
+               {\r
+                       imagegif($img_n, $dest);\r
+               }\r
+               elseif($type=="jpg")\r
+               {\r
+                       imagejpeg($img_n, $dest, 100);\r
+               }\r
+               elseif($type=="png")\r
+               {\r
+                       imagepng($img_n, $dest);\r
+               }\r
+               elseif($type=="bmp")\r
+               {\r
+                       imagewbmp($img_n, $dest);\r
+               }\r
+               return true;\r
+       }\r
+}\r
+\r
+?>
\ No newline at end of file
index 10958c1da2e8d823ca7e98ce3bc2442750ba98a8..99d7f2b0d6de6443bd4f816a07f829ce813ec2d7 100644 (file)
@@ -45,44 +45,36 @@ class IPF_Form_Widget_HTMLInput extends IPF_Form_Widget
                 $extra_config = ",\n".implode(",\n", $_st);
             }
         }
-        $final_attrs = $this->buildAttrs(array('name' => $name),
-                                         $extra_attrs);
-        // The special include for tinyMCE
-        
+        $final_attrs = $this->buildAttrs(array('name' => $name), $extra_attrs);
         $out = '';
-        
         if (!IPF_Form_Widget_HTMLInput::$js_include){
             IPF_Form_Widget_HTMLInput::$js_include = true;
-                    $out .= '<script language="javascript" type="text/javascript" src="'.IPF::get('admin_media_url').'tiny_mce/tiny_mce.js"></script>'."\n";
+                    $out .= '<script language="javascript" type="text/javascript" src="'.IPF::get('tiny_mce_url').'tiny_mce.js"></script>'."\n";
                     $out .='<script language="javascript" type="text/javascript">
                tinyMCE.init({
+                    theme_advanced_buttons1 : "bold, italic, separator, undo, redo, separator, bullist, numlist, outdent, indent, separator, justifyleft, justifycenter, justifyright, separator, link, unlink, forecolor, backcolor, sub, sup",
+                    theme_advanced_buttons2 : "code, images, fullscreen, charmap, separator, separator, pastetext, pasteword, selectall, removeformat, separator, formatselect, preview", 
+                    theme_advanced_buttons3 : "",
+                    theme_advanced_toolbar_location : "top",
+                    theme_advanced_toolbar_align: "left",
                     mode : "specific_textareas",
                     editor_selector : "htmlEditor",
                        theme : "advanced",
-                   theme_advanced_toolbar_location : "top",
-                       theme_advanced_toolbar_align: "left",
-                    theme_advanced_buttons1 : "bold, italic, separator, undo, redo, separator, bullist, numlist, outdent, indent, separator, justifyleft, justifycenter, justifyright, separator, link, unlink, separator, selectall, removeformat, separator,sub,sup,separator, forecolor, backcolor",
-                    theme_advanced_buttons2 : "", 
-                    theme_advanced_buttons3 : "",
                        convert_urls:"false",
-                    plugins : "paste, table",
+                       plugins : "inlinepopups, images, charmap, paste, table, fullscreen, preview, print",
                     button_tile_map : true,
                     fix_list_elements : true,
                     gecko_spellcheck : true,
                     verify_html : true,
                     dialog_type : "modal",
                     height : "800",
-                    height : "300"
+                    height : "300",
+                    relative_urls : false,
+                    remove_script_host : true,
+                    content_css : "/media/tiny_mce/themes/advanced/skins/default/content.css"
                });
             </script>';
-
-
         }
-        
-
-// buttons: code, separator pastetext, pasteword, 
-//plugins : "inlinepopups, paste, table, fullscreen, preview, print, charmap, separator, ",
-
         return new IPF_Template_SafeString(
                        $out.sprintf('<textarea%s class="htmlEditor">%s</textarea>',
                                IPF_Form_Widget_Attrs($final_attrs),